updated on Thu Jan 26 00:18:00 UTC 2012
[aur-mirror.git] / xulrunner-beta-kde-opensuse / mozilla-kde.patch
blobaf559afdf92c1f6f4e86b2d0c72397104e7c982c
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 @@ -55,16 +55,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 @@ -772,30 +773,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 @@ -890,24 +909,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/src/Makefile.in b/toolkit/components/downloads/src/Makefile.in
130 --- a/toolkit/components/downloads/src/Makefile.in
131 +++ b/toolkit/components/downloads/src/Makefile.in
132 @@ -71,8 +71,9 @@ EXTRA_COMPONENTS = \
133 nsDownloadManagerUI.manifest \
134 $(NULL)
135 endif
137 include $(topsrcdir)/config/rules.mk
139 EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
141 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
142 diff --git a/toolkit/components/downloads/src/nsDownloadManager.cpp b/toolkit/components/downloads/src/nsDownloadManager.cpp
143 --- a/toolkit/components/downloads/src/nsDownloadManager.cpp
144 +++ b/toolkit/components/downloads/src/nsDownloadManager.cpp
145 @@ -71,16 +71,20 @@
147 #if defined(XP_WIN) && !defined(WINCE)
148 #include <shlobj.h>
149 #ifdef DOWNLOAD_SCANNER
150 #include "nsDownloadScanner.h"
151 #endif
152 #endif
154 +#if defined(XP_UNIX) && !defined(XP_MACOSX)
155 +#include "nsKDEUtils.h"
156 +#endif
158 #ifdef XP_MACOSX
159 #include <CoreFoundation/CoreFoundation.h>
160 #endif
162 #define DOWNLOAD_MANAGER_BUNDLE "chrome://mozapps/locale/downloads/downloads.properties"
163 #define DOWNLOAD_MANAGER_ALERT_ICON "chrome://mozapps/skin/downloads/downloadIcon.png"
164 #define PREF_BDM_SHOWALERTONCOMPLETE "browser.download.manager.showAlertOnComplete"
165 #define PREF_BDM_SHOWALERTINTERVAL "browser.download.manager.showAlertInterval"
166 @@ -2199,16 +2203,25 @@ nsDownload::SetState(DownloadState aStat
167 nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID));
169 // Master pref to control this function.
170 PRBool showTaskbarAlert = PR_TRUE;
171 if (pref)
172 pref->GetBoolPref(PREF_BDM_SHOWALERTONCOMPLETE, &showTaskbarAlert);
174 if (showTaskbarAlert) {
175 + if( nsKDEUtils::kdeSupport()) {
176 + nsCStringArray command;
177 + command.AppendCString( NS_LITERAL_CSTRING( "DOWNLOADFINISHED" ));
178 + nsAutoString displayName;
179 + GetDisplayName( displayName );
180 + command.AppendCString( nsCAutoString( ToNewUTF8String( displayName )));
181 + nsKDEUtils::command( command );
182 + } else {
183 + // begin non-KDE block
184 PRInt32 alertInterval = 2000;
185 if (pref)
186 pref->GetIntPref(PREF_BDM_SHOWALERTINTERVAL, &alertInterval);
188 PRInt64 alertIntervalUSec = alertInterval * PR_USEC_PER_MSEC;
189 PRInt64 goat = PR_Now() - mStartTime;
190 showTaskbarAlert = goat > alertIntervalUSec;
192 @@ -2234,16 +2247,17 @@ nsDownload::SetState(DownloadState aStat
193 // because if it is, they'll click open the download manager and
194 // the items they downloaded will have been removed.
195 alerts->ShowAlertNotification(
196 NS_LITERAL_STRING(DOWNLOAD_MANAGER_ALERT_ICON), title,
197 message, !removeWhenDone, EmptyString(), mDownloadManager,
198 EmptyString());
201 + } // end non-KDE block
204 #if (defined(XP_WIN) && !defined(WINCE)) || defined(XP_MACOSX)
205 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mTarget);
206 nsCOMPtr<nsIFile> file;
207 nsAutoString path;
209 if (fileURL &&
210 diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn
211 --- a/toolkit/content/jar.mn
212 +++ b/toolkit/content/jar.mn
213 @@ -40,29 +40,33 @@ toolkit.jar:
214 *+ content/global/viewZoomOverlay.js (viewZoomOverlay.js)
215 *+ content/global/bindings/autocomplete.xml (widgets/autocomplete.xml)
216 *+ content/global/bindings/browser.xml (widgets/browser.xml)
217 *+ content/global/bindings/button.xml (widgets/button.xml)
218 *+ content/global/bindings/checkbox.xml (widgets/checkbox.xml)
219 *+ content/global/bindings/colorpicker.xml (widgets/colorpicker.xml)
220 *+ content/global/bindings/datetimepicker.xml (widgets/datetimepicker.xml)
221 *+ content/global/bindings/dialog.xml (widgets/dialog.xml)
222 +*+ content/global/bindings/dialog-kde.xml (widgets/dialog-kde.xml)
223 +% override chrome://global/content/bindings/dialog.xml chrome://global/content/bindings/dialog-kde.xml desktop=kde
224 *+ content/global/bindings/editor.xml (widgets/editor.xml)
225 * content/global/bindings/expander.xml (widgets/expander.xml)
226 * content/global/bindings/filefield.xml (widgets/filefield.xml)
227 *+ content/global/bindings/findbar.xml (widgets/findbar.xml)
228 *+ content/global/bindings/general.xml (widgets/general.xml)
229 *+ content/global/bindings/groupbox.xml (widgets/groupbox.xml)
230 *+ content/global/bindings/listbox.xml (widgets/listbox.xml)
231 *+ content/global/bindings/menu.xml (widgets/menu.xml)
232 *+ content/global/bindings/menulist.xml (widgets/menulist.xml)
233 *+ content/global/bindings/notification.xml (widgets/notification.xml)
234 *+ content/global/bindings/numberbox.xml (widgets/numberbox.xml)
235 *+ content/global/bindings/popup.xml (widgets/popup.xml)
236 *+ content/global/bindings/preferences.xml (widgets/preferences.xml)
237 +*+ content/global/bindings/preferences-kde.xml (widgets/preferences-kde.xml)
238 +% override chrome://global/content/bindings/preferences.xml chrome://global/content/bindings/preferences-kde.xml desktop=kde
239 *+ content/global/bindings/progressmeter.xml (widgets/progressmeter.xml)
240 *+ content/global/bindings/radio.xml (widgets/radio.xml)
241 *+ content/global/bindings/resizer.xml (widgets/resizer.xml)
242 *+ content/global/bindings/richlistbox.xml (widgets/richlistbox.xml)
243 *+ content/global/bindings/scale.xml (widgets/scale.xml)
244 *+ content/global/bindings/scrollbar.xml (widgets/scrollbar.xml)
245 *+ content/global/bindings/scrollbox.xml (widgets/scrollbox.xml)
246 *+ content/global/bindings/splitter.xml (widgets/splitter.xml)
247 diff --git a/toolkit/content/widgets/dialog-kde.xml b/toolkit/content/widgets/dialog-kde.xml
248 new file mode 100644
249 --- /dev/null
250 +++ b/toolkit/content/widgets/dialog-kde.xml
251 @@ -0,0 +1,447 @@
252 +<?xml version="1.0"?>
254 +<bindings id="dialogBindings"
255 + xmlns="http://www.mozilla.org/xbl"
256 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
257 + xmlns:xbl="http://www.mozilla.org/xbl">
259 + <binding id="dialog" extends="chrome://global/content/bindings/general.xml#root-element">
260 + <resources>
261 + <stylesheet src="chrome://global/skin/dialog.css"/>
262 + </resources>
263 + <content>
264 + <xul:vbox class="box-inherit dialog-content-box" flex="1">
265 + <children/>
266 + </xul:vbox>
268 + <xul:hbox class="dialog-button-box" anonid="buttons"
269 + xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient"
270 +#ifdef XP_UNIX_GNOME
272 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
273 + <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
274 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
275 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
276 + <xul:spacer anonid="spacer" flex="1"/>
277 + <xul:button dlgtype="cancel" class="dialog-button"/>
278 + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
279 +#elif XP_UNIX
280 + pack="end">
281 + <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
282 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
283 + <xul:spacer anonid="spacer" flex="1" hidden="true"/>
284 + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
285 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
286 + <xul:button dlgtype="cancel" class="dialog-button"/>
287 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
288 +#else
289 + pack="end">
290 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
291 + <xul:spacer anonid="spacer" flex="1" hidden="true"/>
292 + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
293 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
294 + <xul:button dlgtype="cancel" class="dialog-button"/>
295 + <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
296 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
297 +#endif
298 + </xul:hbox>
299 + </content>
301 + <implementation>
302 + <field name="_mStrBundle">null</field>
303 + <field name="_closeHandler">(function(event) {
304 + if (!document.documentElement.cancelDialog())
305 + event.preventDefault();
306 + })</field>
308 + <property name="buttons"
309 + onget="return this.getAttribute('buttons');"
310 + onset="this._configureButtons(val); return val;"/>
312 + <property name="defaultButton">
313 + <getter>
314 + <![CDATA[
315 + if (this.hasAttribute("defaultButton"))
316 + return this.getAttribute("defaultButton");
317 + else // default to the accept button
318 + return "accept";
319 + ]]>
320 + </getter>
321 + <setter>
322 + <![CDATA[
323 + this._setDefaultButton(val);
324 + return val;
325 + ]]>
326 + </setter>
327 + </property>
329 + <method name="acceptDialog">
330 + <body>
331 + <![CDATA[
332 + return this._doButtonCommand("accept");
333 + ]]>
334 + </body>
335 + </method>
337 + <method name="cancelDialog">
338 + <body>
339 + <![CDATA[
340 + return this._doButtonCommand("cancel");
341 + ]]>
342 + </body>
343 + </method>
345 + <method name="getButton">
346 + <parameter name="aDlgType"/>
347 + <body>
348 + <![CDATA[
349 + return this._buttons[aDlgType];
350 + ]]>
351 + </body>
352 + </method>
354 + <method name="moveToAlertPosition">
355 + <body>
356 + <![CDATA[
357 + // hack. we need this so the window has something like its final size
358 + if (window.outerWidth == 1) {
359 + dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n");
360 + sizeToContent();
363 + var xOffset = (opener.outerWidth - window.outerWidth) / 2;
364 + var yOffset = opener.outerHeight / 5;
366 + var newX = opener.screenX + xOffset;
367 + var newY = opener.screenY + yOffset;
369 + // ensure the window is fully onscreen (if smaller than the screen)
370 + if (newX < screen.availLeft)
371 + newX = screen.availLeft + 20;
372 + if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth))
373 + newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20;
375 + if (newY < screen.availTop)
376 + newY = screen.availTop + 20;
377 + if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight))
378 + newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60;
380 + window.moveTo( newX, newY );
381 + ]]>
382 + </body>
383 + </method>
385 + <method name="centerWindowOnScreen">
386 + <body>
387 + <![CDATA[
388 + var xOffset = screen.availWidth/2 - window.outerWidth/2;
389 + var yOffset = screen.availHeight/2 - window.outerHeight/2; //(opener.outerHeight *2)/10;
391 + xOffset = xOffset > 0 ? xOffset : 0;
392 + yOffset = yOffset > 0 ? yOffset : 0;
393 + window.moveTo(xOffset, yOffset);
394 + ]]>
395 + </body>
396 + </method>
398 + <constructor>
399 + <![CDATA[
400 + this._configureButtons(this.buttons);
402 + // listen for when window is closed via native close buttons
403 + window.addEventListener("close", this._closeHandler, false);
405 + // for things that we need to initialize after onload fires
406 + window.addEventListener("load", this.postLoadInit, false);
408 + window.moveToAlertPosition = this.moveToAlertPosition;
409 + window.centerWindowOnScreen = this.centerWindowOnScreen;
410 + ]]>
411 + </constructor>
413 + <method name="postLoadInit">
414 + <parameter name="aEvent"/>
415 + <body>
416 + <![CDATA[
417 + function focusInit() {
418 + const dialog = document.documentElement;
419 + const defaultButton = dialog.getButton(dialog.defaultButton);
420 + // give focus to the first focusable element in the dialog
421 + if (!document.commandDispatcher.focusedElement) {
422 + document.commandDispatcher.advanceFocusIntoSubtree(dialog);
424 + var focusedElt = document.commandDispatcher.focusedElement;
425 + if (focusedElt) {
426 + var initialFocusedElt = focusedElt;
427 + while (focusedElt.localName == "tab" ||
428 + focusedElt.getAttribute("noinitialfocus") == "true") {
429 + document.commandDispatcher.advanceFocusIntoSubtree(focusedElt);
430 + focusedElt = document.commandDispatcher.focusedElement;
431 + if (focusedElt == initialFocusedElt)
432 + break;
435 + if (initialFocusedElt.localName == "tab") {
436 + if (focusedElt.hasAttribute("dlgtype")) {
437 + // We don't want to focus on anonymous OK, Cancel, etc. buttons,
438 + // so return focus to the tab itself
439 + initialFocusedElt.focus();
442 +#ifndef XP_MACOSX
443 + else if (focusedElt.hasAttribute("dlgtype") && focusedElt != defaultButton) {
444 + defaultButton.focus();
446 +#endif
450 + try {
451 + if (defaultButton)
452 + window.notifyDefaultButtonLoaded(defaultButton);
453 + } catch (e) { }
456 + // Give focus after onload completes, see bug 103197.
457 + setTimeout(focusInit, 0);
458 + ]]>
459 + </body>
460 + </method>
462 + <property name="mStrBundle">
463 + <getter>
464 + <![CDATA[
465 + if (!this._mStrBundle) {
466 + // need to create string bundle manually instead of using <xul:stringbundle/>
467 + // see bug 63370 for details
468 + this._mStrBundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
469 + .getService(Components.interfaces.nsIStringBundleService)
470 + .createBundle("chrome://global/locale/dialog.properties");
472 + return this._mStrBundle;
473 + ]]></getter>
474 + </property>
476 + <method name="_configureButtons">
477 + <parameter name="aButtons"/>
478 + <body>
479 + <![CDATA[
480 + // by default, get all the anonymous button elements
481 + var buttons = {};
482 + this._buttons = buttons;
483 + buttons.accept = document.getAnonymousElementByAttribute(this, "dlgtype", "accept");
484 + buttons.cancel = document.getAnonymousElementByAttribute(this, "dlgtype", "cancel");
485 + buttons.extra1 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra1");
486 + buttons.extra2 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra2");
487 + buttons.help = document.getAnonymousElementByAttribute(this, "dlgtype", "help");
488 + buttons.disclosure = document.getAnonymousElementByAttribute(this, "dlgtype", "disclosure");
490 + // look for any overriding explicit button elements
491 + var exBtns = this.getElementsByAttribute("dlgtype", "*");
492 + var dlgtype;
493 + var i;
494 + for (i = 0; i < exBtns.length; ++i) {
495 + dlgtype = exBtns[i].getAttribute("dlgtype");
496 + buttons[dlgtype].hidden = true; // hide the anonymous button
497 + buttons[dlgtype] = exBtns[i];
500 + // add the label and oncommand handler to each button
501 + for (dlgtype in buttons) {
502 + var button = buttons[dlgtype];
503 + button.addEventListener("command", this._handleButtonCommand, true);
505 + // don't override custom labels with pre-defined labels on explicit buttons
506 + if (!button.hasAttribute("label")) {
507 + // dialog attributes override the default labels in dialog.properties
508 + if (this.hasAttribute("buttonlabel"+dlgtype)) {
509 + button.setAttribute("label", this.getAttribute("buttonlabel"+dlgtype));
510 + if (this.hasAttribute("buttonaccesskey"+dlgtype))
511 + button.setAttribute("accesskey", this.getAttribute("buttonaccesskey"+dlgtype));
512 + } else if (dlgtype != "extra1" && dlgtype != "extra2") {
513 + button.setAttribute("label", this.mStrBundle.GetStringFromName("button-"+dlgtype));
514 + var accessKey = this.mStrBundle.GetStringFromName("accesskey-"+dlgtype);
515 + if (accessKey)
516 + button.setAttribute("accesskey", accessKey);
519 + // allow specifying alternate icons in the dialog header
520 + if (!button.hasAttribute("icon")) {
521 + // if there's an icon specified, use that
522 + if (this.hasAttribute("buttonicon"+dlgtype))
523 + button.setAttribute("icon", this.getAttribute("buttonicon"+dlgtype));
524 + // otherwise set defaults
525 + else
526 + switch (dlgtype) {
527 + case "accept":
528 + button.setAttribute("icon","accept");
529 + break;
530 + case "cancel":
531 + button.setAttribute("icon","cancel");
532 + break;
533 + case "disclosure":
534 + button.setAttribute("icon","properties");
535 + break;
536 + case "help":
537 + button.setAttribute("icon","help");
538 + break;
539 + default:
540 + break;
545 + // ensure that hitting enter triggers the default button command
546 + this.defaultButton = this.defaultButton;
548 + // if there is a special button configuration, use it
549 + if (aButtons) {
550 + // expect a comma delimited list of dlgtype values
551 + var list = aButtons.split(",");
553 + // mark shown dlgtypes as true
554 + var shown = { accept: false, cancel: false, help: false,
555 + disclosure: false, extra1: false, extra2: false };
556 + for (i = 0; i < list.length; ++i)
557 + shown[list[i].replace(/ /g, "")] = true;
559 + // hide/show the buttons we want
560 + for (dlgtype in buttons)
561 + buttons[dlgtype].hidden = !shown[dlgtype];
563 +#ifdef XP_WIN
564 +# show the spacer on Windows only when the extra2 button is present
565 + var spacer = document.getAnonymousElementByAttribute(this, "anonid", "spacer");
566 + spacer.removeAttribute("hidden");
567 + spacer.setAttribute("flex", shown["extra2"]?"1":"0");
568 +#endif
571 + ]]>
572 + </body>
573 + </method>
575 + <method name="_setDefaultButton">
576 + <parameter name="aNewDefault"/>
577 + <body>
578 + <![CDATA[
579 + // remove the default attribute from the previous default button, if any
580 + var oldDefaultButton = this.getButton(this.defaultButton);
581 + if (oldDefaultButton)
582 + oldDefaultButton.removeAttribute("default");
584 + var newDefaultButton = this.getButton(aNewDefault);
585 + if (newDefaultButton) {
586 + this.setAttribute("defaultButton", aNewDefault);
587 + newDefaultButton.setAttribute("default", "true");
589 + else {
590 + this.setAttribute("defaultButton", "none");
591 + if (aNewDefault != "none")
592 + dump("invalid new default button: " + aNewDefault + ", assuming: none\n");
594 + ]]>
595 + </body>
596 + </method>
598 + <method name="_handleButtonCommand">
599 + <parameter name="aEvent"/>
600 + <body>
601 + <![CDATA[
602 + return document.documentElement._doButtonCommand(
603 + aEvent.target.getAttribute("dlgtype"));
604 + ]]>
605 + </body>
606 + </method>
608 + <method name="_doButtonCommand">
609 + <parameter name="aDlgType"/>
610 + <body>
611 + <![CDATA[
612 + var button = this.getButton(aDlgType);
613 + if (!button.disabled) {
614 + var noCancel = this._fireButtonEvent(aDlgType);
615 + if (noCancel) {
616 + if (aDlgType == "accept" || aDlgType == "cancel")
617 + window.close();
619 + return noCancel;
621 + return true;
622 + ]]>
623 + </body>
624 + </method>
626 + <method name="_fireButtonEvent">
627 + <parameter name="aDlgType"/>
628 + <body>
629 + <![CDATA[
630 + var event = document.createEvent("Events");
631 + event.initEvent("dialog"+aDlgType, true, true);
633 + // handle dom event handlers
634 + var noCancel = this.dispatchEvent(event);
636 + // handle any xml attribute event handlers
637 + var handler = this.getAttribute("ondialog"+aDlgType);
638 + if (handler != "") {
639 + var fn = new Function("event", handler);
640 + var returned = fn(event);
641 + if (returned == false)
642 + noCancel = false;
645 + return noCancel;
646 + ]]>
647 + </body>
648 + </method>
650 + <method name="_hitEnter">
651 + <parameter name="evt"/>
652 + <body>
653 + <![CDATA[
654 + if (evt.getPreventDefault())
655 + return;
657 + var btn = this.getButton(this.defaultButton);
658 + if (btn)
659 + this._doButtonCommand(this.defaultButton);
660 + ]]>
661 + </body>
662 + </method>
664 + </implementation>
666 + <handlers>
667 + <handler event="keypress" keycode="VK_ENTER"
668 + group="system" action="this._hitEnter(event);"/>
669 + <handler event="keypress" keycode="VK_RETURN"
670 + group="system" action="this._hitEnter(event);"/>
671 + <handler event="keypress" keycode="VK_ESCAPE" group="system">
672 + if (!event.getPreventDefault())
673 + this.cancelDialog();
674 + </handler>
675 +#ifdef XP_MACOSX
676 + <handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/>
677 +#else
678 + <handler event="focus" phase="capturing">
679 + var btn = this.getButton(this.defaultButton);
680 + if (btn)
681 + btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Components.interfaces.nsIDOMXULButtonElement));
682 + </handler>
683 +#endif
684 + </handlers>
686 + </binding>
688 + <binding id="dialogheader">
689 + <resources>
690 + <stylesheet src="chrome://global/skin/dialog.css"/>
691 + </resources>
692 + <content>
693 + <xul:label class="dialogheader-title" xbl:inherits="value=title,crop" crop="right" flex="1"/>
694 + <xul:label class="dialogheader-description" xbl:inherits="value=description"/>
695 + </content>
696 + </binding>
698 +</bindings>
699 diff --git a/toolkit/content/widgets/preferences-kde.xml b/toolkit/content/widgets/preferences-kde.xml
700 new file mode 100644
701 --- /dev/null
702 +++ b/toolkit/content/widgets/preferences-kde.xml
703 @@ -0,0 +1,1371 @@
704 +<?xml version="1.0"?>
706 +<!DOCTYPE bindings [
707 + <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
708 + %preferencesDTD;
709 + <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
710 + %globalKeysDTD;
713 +<bindings id="preferencesBindings"
714 + xmlns="http://www.mozilla.org/xbl"
715 + xmlns:xbl="http://www.mozilla.org/xbl"
716 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
719 +# = Preferences Window Framework
721 +# The syntax for use looks something like:
723 +# <prefwindow>
724 +# <prefpane id="prefPaneA">
725 +# <preferences>
726 +# <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/>
727 +# <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/>
728 +# </preferences>
729 +# <checkbox label="Preference" preference="preference1"/>
730 +# </prefpane>
731 +# </prefwindow>
734 + <binding id="preferences">
735 + <implementation implements="nsIObserver">
736 + <method name="observe">
737 + <parameter name="aSubject"/>
738 + <parameter name="aTopic"/>
739 + <parameter name="aData"/>
740 + <body>
741 + <![CDATA[
742 + for (var i = 0; i < this.childNodes.length; ++i) {
743 + var preference = this.childNodes[i];
744 + if (preference.name == aData) {
745 + preference.value = preference.valueFromPreferences;
748 + ]]>
749 + </body>
750 + </method>
752 + <method name="fireChangedEvent">
753 + <parameter name="aPreference"/>
754 + <body>
755 + <![CDATA[
756 + // Value changed, synthesize an event
757 + try {
758 + var event = document.createEvent("Events");
759 + event.initEvent("change", true, true);
760 + aPreference.dispatchEvent(event);
762 + catch (e) {
763 + Components.utils.reportError(e);
765 + ]]>
766 + </body>
767 + </method>
769 + <field name="service">
770 + Components.classes["@mozilla.org/preferences-service;1"]
771 + .getService(Components.interfaces.nsIPrefService);
772 + </field>
773 + <field name="rootBranch">
774 + Components.classes["@mozilla.org/preferences-service;1"]
775 + .getService(Components.interfaces.nsIPrefBranch);
776 + </field>
777 + <field name="defaultBranch">
778 + this.service.getDefaultBranch("");
779 + </field>
780 + <field name="rootBranchInternal">
781 + Components.classes["@mozilla.org/preferences-service;1"]
782 + .getService(Components.interfaces.nsIPrefBranchInternal);
783 + </field>
784 + <property name="type" readonly="true">
785 + <getter>
786 + <![CDATA[
787 + return document.documentElement.type || "";
788 + ]]>
789 + </getter>
790 + </property>
791 + <property name="instantApply" readonly="true">
792 + <getter>
793 + <![CDATA[
794 + var doc = document.documentElement;
795 + return this.type == "child" ? doc.instantApply
796 + : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply");
797 + ]]>
798 + </getter>
799 + </property>
800 + </implementation>
801 + </binding>
803 + <binding id="preference">
804 + <implementation>
805 + <constructor>
806 + <![CDATA[
807 + // if the element has been inserted without the name attribute set,
808 + // we have nothing to do here
809 + if (!this.name)
810 + return;
812 + this.preferences.rootBranchInternal
813 + .addObserver(this.name, this.preferences, false);
814 + // In non-instant apply mode, we must try and use the last saved state
815 + // from any previous opens of a child dialog instead of the value from
816 + // preferences, to pick up any edits a user may have made.
817 + if (this.preferences.type == "child" &&
818 + !this.instantApply && window.opener) {
819 + var pdoc = window.opener.document;
821 + // Try to find a preference element for the same preference.
822 + var preference = null;
823 + var parentPreferences = pdoc.getElementsByTagName("preferences");
824 + for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
825 + var parentPrefs = parentPreferences[k]
826 + .getElementsByAttribute("name", this.name);
827 + for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
828 + if (parentPrefs[l].localName == "preference")
829 + preference = parentPrefs[l];
832 + this._setValue(preference ? preference.value
833 + : this.valueFromPreferences, false);
835 + else
836 + this._setValue(this.valueFromPreferences, false);
837 + ]]>
838 + </constructor>
839 + <destructor>
840 + this.preferences.rootBranchInternal
841 + .removeObserver(this.name, this.preferences);
842 + </destructor>
844 + <property name="instantApply">
845 + <getter>
846 + return this.getAttribute("instantApply") == "true" || this.preferences.instantApply;
847 + </getter>
848 + </property>
850 + <property name="preferences" onget="return this.parentNode"/>
851 + <property name="name" onget="return this.getAttribute('name');">
852 + <setter>
853 + if (val == this.name)
854 + return val;
856 + this.preferences.rootBranchInternal
857 + .removeObserver(this.name, this.preferences);
858 + this.setAttribute('name', val);
859 + this.preferences.rootBranchInternal
860 + .addObserver(val, this.preferences, false);
862 + return val;
863 + </setter>
864 + </property>
865 + <property name="type" onget="return this.getAttribute('type');"
866 + onset="this.setAttribute('type', val); return val;"/>
867 + <property name="inverted" onget="return this.getAttribute('inverted') == 'true';"
868 + onset="this.setAttribute('inverted', val); return val;"/>
869 + <property name="readonly" onget="return this.getAttribute('readonly') == 'true';"
870 + onset="this.setAttribute('readonly', val); return val;"/>
872 + <field name="_value">null</field>
873 + <method name="_setValue">
874 + <parameter name="aValue"/>
875 + <parameter name="aUpdate"/>
876 + <body>
877 + <![CDATA[
878 + if (aUpdate && this.value !== aValue) {
879 + this._value = aValue;
880 + if (this.instantApply)
881 + this.valueFromPreferences = aValue;
882 + this.preferences.fireChangedEvent(this);
884 + else if (!aUpdate) {
885 + this._value = aValue;
886 + this.updateElements();
888 + return aValue;
889 + ]]>
890 + </body>
891 + </method>
892 + <property name="value" onget="return this._value" onset="return this._setValue(val, true);"/>
894 + <property name="locked">
895 + <getter>
896 + return this.preferences.rootBranch.prefIsLocked(this.name);
897 + </getter>
898 + </property>
900 + <property name="disabled">
901 + <getter>
902 + return this.getAttribute("disabled") == "true";
903 + </getter>
904 + <setter>
905 + <![CDATA[
906 + if (val)
907 + this.setAttribute("disabled", "true");
908 + else
909 + this.removeAttribute("disabled");
911 + if (!this.id)
912 + return val;
914 + var elements = document.getElementsByAttribute("preference", this.id);
915 + for (var i = 0; i < elements.length; ++i) {
916 + elements[i].disabled = val;
918 + var labels = document.getElementsByAttribute("control", elements[i].id);
919 + for (var j = 0; j < labels.length; ++j)
920 + labels[j].disabled = val;
923 + return val;
924 + ]]>
925 + </setter>
926 + </property>
928 + <property name="tabIndex">
929 + <getter>
930 + return parseInt(this.getAttribute("tabindex"));
931 + </getter>
932 + <setter>
933 + <![CDATA[
934 + if (val)
935 + this.setAttribute("tabindex", val);
936 + else
937 + this.removeAttribute("tabindex");
939 + if (!this.id)
940 + return val;
942 + var elements = document.getElementsByAttribute("preference", this.id);
943 + for (var i = 0; i < elements.length; ++i) {
944 + elements[i].tabIndex = val;
946 + var labels = document.getElementsByAttribute("control", elements[i].id);
947 + for (var j = 0; j < labels.length; ++j)
948 + labels[j].tabIndex = val;
951 + return val;
952 + ]]>
953 + </setter>
954 + </property>
956 + <property name="hasUserValue">
957 + <getter>
958 + <![CDATA[
959 + return this.preferences.rootBranch.prefHasUserValue(this.name) &&
960 + this.value !== undefined;
961 + ]]>
962 + </getter>
963 + </property>
965 + <method name="reset">
966 + <body>
967 + // defer reset until preference update
968 + this.value = undefined;
969 + </body>
970 + </method>
972 + <field name="_useDefault">false</field>
973 + <property name="defaultValue">
974 + <getter>
975 + <![CDATA[
976 + this._useDefault = true;
977 + var val = this.valueFromPreferences;
978 + this._useDefault = false;
979 + return val;
980 + ]]>
981 + </getter>
982 + </property>
984 + <property name="_branch">
985 + <getter>
986 + return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch;
987 + </getter>
988 + </property>
990 + <field name="batching">false</field>
992 + <method name="_reportUnknownType">
993 + <body>
994 + <![CDATA[
995 + var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
996 + .getService(Components.interfaces.nsIConsoleService);
997 + var msg = "<preference> with id='" + this.id + "' and name='" +
998 + this.name + "' has unknown type '" + this.type + "'.";
999 + consoleService.logStringMessage(msg);
1000 + ]]>
1001 + </body>
1002 + </method>
1004 + <property name="valueFromPreferences">
1005 + <getter>
1006 + <![CDATA[
1007 + try {
1008 + // Force a resync of value with preferences.
1009 + switch (this.type) {
1010 + case "int":
1011 + return this._branch.getIntPref(this.name);
1012 + case "bool":
1013 + var val = this._branch.getBoolPref(this.name);
1014 + return this.inverted ? !val : val;
1015 + case "wstring":
1016 + return this._branch
1017 + .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString)
1018 + .data;
1019 + case "string":
1020 + case "unichar":
1021 + return this._branch
1022 + .getComplexValue(this.name, Components.interfaces.nsISupportsString)
1023 + .data;
1024 + case "fontname":
1025 + var family = this._branch
1026 + .getComplexValue(this.name, Components.interfaces.nsISupportsString)
1027 + .data;
1028 + var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
1029 + .createInstance(Components.interfaces.nsIFontEnumerator);
1030 + return fontEnumerator.getStandardFamilyName(family);
1031 + case "file":
1032 + var f = this._branch
1033 + .getComplexValue(this.name, Components.interfaces.nsILocalFile);
1034 + return f;
1035 + default:
1036 + this._reportUnknownType();
1039 + catch (e) { }
1040 + return null;
1041 + ]]>
1042 + </getter>
1043 + <setter>
1044 + <![CDATA[
1045 + // Exit early if nothing to do.
1046 + if (this.readonly || this.valueFromPreferences == val)
1047 + return val;
1049 + // The special value undefined means 'reset preference to default'.
1050 + if (val === undefined) {
1051 + this.preferences.rootBranch.clearUserPref(this.name);
1052 + return val;
1055 + // Force a resync of preferences with value.
1056 + switch (this.type) {
1057 + case "int":
1058 + this.preferences.rootBranch.setIntPref(this.name, val);
1059 + break;
1060 + case "bool":
1061 + this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val);
1062 + break;
1063 + case "wstring":
1064 + var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
1065 + .createInstance(Components.interfaces.nsIPrefLocalizedString);
1066 + pls.data = val;
1067 + this.preferences.rootBranch
1068 + .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls);
1069 + break;
1070 + case "string":
1071 + case "unichar":
1072 + case "fontname":
1073 + var iss = Components.classes["@mozilla.org/supports-string;1"]
1074 + .createInstance(Components.interfaces.nsISupportsString);
1075 + iss.data = val;
1076 + this.preferences.rootBranch
1077 + .setComplexValue(this.name, Components.interfaces.nsISupportsString, iss);
1078 + break;
1079 + case "file":
1080 + var lf;
1081 + if (typeof(val) == "string") {
1082 + lf = Components.classes["@mozilla.org/file/local;1"]
1083 + .createInstance(Components.interfaces.nsILocalFile);
1084 + lf.persistentDescriptor = val;
1085 + if (!lf.exists())
1086 + lf.initWithPath(val);
1088 + else
1089 + lf = val.QueryInterface(Components.interfaces.nsILocalFile);
1090 + this.preferences.rootBranch
1091 + .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf);
1092 + break;
1093 + default:
1094 + this._reportUnknownType();
1096 + if (!this.batching)
1097 + this.preferences.service.savePrefFile(null);
1098 + return val;
1099 + ]]>
1100 + </setter>
1101 + </property>
1103 + <method name="setElementValue">
1104 + <parameter name="aElement"/>
1105 + <body>
1106 + <![CDATA[
1107 + if (this.locked)
1108 + aElement.disabled = true;
1110 + if (!this.isElementEditable(aElement))
1111 + return;
1113 + var rv = undefined;
1114 + if (aElement.hasAttribute("onsyncfrompreference")) {
1115 + // Value changed, synthesize an event
1116 + try {
1117 + var event = document.createEvent("Events");
1118 + event.initEvent("syncfrompreference", true, true);
1119 + var f = new Function ("event",
1120 + aElement.getAttribute("onsyncfrompreference"));
1121 + rv = f.call(aElement, event);
1123 + catch (e) {
1124 + Components.utils.reportError(e);
1127 + var val = rv !== undefined ? rv : (this.instantApply ? this.valueFromPreferences : this.value);
1128 + // if the preference is marked for reset, show default value in UI
1129 + if (val === undefined)
1130 + val = this.defaultValue;
1132 + /**
1133 + * Initialize a UI element property with a value. Handles the case
1134 + * where an element has not yet had a XBL binding attached for it and
1135 + * the property setter does not yet exist by setting the same attribute
1136 + * on the XUL element using DOM apis and assuming the element's
1137 + * constructor or property getters appropriately handle this state.
1138 + */
1139 + function setValue(element, attribute, value) {
1140 + if (attribute in element)
1141 + element[attribute] = value;
1142 + else
1143 + element.setAttribute(attribute, value);
1145 + if (aElement.localName == "checkbox" ||
1146 + aElement.localName == "listitem")
1147 + setValue(aElement, "checked", val);
1148 + else if (aElement.localName == "colorpicker")
1149 + setValue(aElement, "color", val);
1150 + else if (aElement.localName == "textbox") {
1151 + // XXXmano Bug 303998: Avoid a caret placement issue if either the
1152 + // preference observer or its setter calls updateElements as a result
1153 + // of the input event handler.
1154 + if (aElement.value !== val)
1155 + setValue(aElement, "value", val);
1157 + else
1158 + setValue(aElement, "value", val);
1159 + ]]>
1160 + </body>
1161 + </method>
1163 + <method name="getElementValue">
1164 + <parameter name="aElement"/>
1165 + <body>
1166 + <![CDATA[
1167 + if (aElement.hasAttribute("onsynctopreference")) {
1168 + // Value changed, synthesize an event
1169 + try {
1170 + var event = document.createEvent("Events");
1171 + event.initEvent("synctopreference", true, true);
1172 + var f = new Function ("event",
1173 + aElement.getAttribute("onsynctopreference"));
1174 + var rv = f.call(aElement, event);
1175 + if (rv !== undefined)
1176 + return rv;
1178 + catch (e) {
1179 + Components.utils.reportError(e);
1183 + /**
1184 + * Read the value of an attribute from an element, assuming the
1185 + * attribute is a property on the element's node API. If the property
1186 + * is not present in the API, then assume its value is contained in
1187 + * an attribute, as is the case before a binding has been attached.
1188 + */
1189 + function getValue(element, attribute) {
1190 + if (attribute in element)
1191 + return element[attribute];
1192 + return element.getAttribute(attribute);
1194 + if (aElement.localName == "checkbox" ||
1195 + aElement.localName == "listitem")
1196 + var value = getValue(aElement, "checked");
1197 + else if (aElement.localName == "colorpicker")
1198 + value = getValue(aElement, "color");
1199 + else
1200 + value = getValue(aElement, "value");
1202 + switch (this.type) {
1203 + case "int":
1204 + return parseInt(value, 10) || 0;
1205 + case "bool":
1206 + return typeof(value) == "boolean" ? value : value == "true";
1208 + return value;
1209 + ]]>
1210 + </body>
1211 + </method>
1213 + <method name="isElementEditable">
1214 + <parameter name="aElement"/>
1215 + <body>
1216 + <![CDATA[
1217 + switch (aElement.localName) {
1218 + case "checkbox":
1219 + case "colorpicker":
1220 + case "radiogroup":
1221 + case "textbox":
1222 + case "listitem":
1223 + case "listbox":
1224 + case "menulist":
1225 + return true;
1227 + return aElement.getAttribute("preference-editable") == "true";
1228 + ]]>
1229 + </body>
1230 + </method>
1232 + <method name="updateElements">
1233 + <body>
1234 + <![CDATA[
1235 + if (!this.id)
1236 + return;
1238 + // This "change" event handler tracks changes made to preferences by
1239 + // sources other than the user in this window.
1240 + var elements = document.getElementsByAttribute("preference", this.id);
1241 + for (var i = 0; i < elements.length; ++i)
1242 + this.setElementValue(elements[i]);
1243 + ]]>
1244 + </body>
1245 + </method>
1246 + </implementation>
1248 + <handlers>
1249 + <handler event="change">
1250 + this.updateElements();
1251 + </handler>
1252 + </handlers>
1253 + </binding>
1255 + <binding id="prefwindow"
1256 + extends="chrome://global/content/bindings/dialog.xml#dialog">
1257 + <resources>
1258 + <stylesheet src="chrome://global/skin/preferences.css"/>
1259 + </resources>
1260 + <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY"
1261 + closebuttonlabel="&preferencesCloseButton.label;"
1262 + closebuttonaccesskey="&preferencesCloseButton.accesskey;"
1263 + role="dialog"
1264 +#ifdef XP_WIN
1265 + title="&preferencesDefaultTitleWin.title;">
1266 +#else
1267 + title="&preferencesDefaultTitleMac.title;">
1268 +#endif
1269 + <xul:windowdragbox orient="vertical">
1270 + <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
1271 + role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
1272 + </xul:windowdragbox>
1273 + <xul:hbox flex="1" class="paneDeckContainer">
1274 + <xul:deck anonid="paneDeck" flex="1">
1275 + <children includes="prefpane"/>
1276 + </xul:deck>
1277 + </xul:hbox>
1278 + <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons"
1279 +#ifdef XP_UNIX_GNOME
1281 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
1282 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
1283 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
1284 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
1285 + <xul:spacer anonid="spacer" flex="1"/>
1286 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
1287 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
1288 +#elif XP_UNIX
1289 + pack="end">
1290 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
1291 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
1292 + <xul:spacer anonid="spacer" flex="1"/>
1293 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
1294 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
1295 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
1296 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
1297 +#else
1298 + pack="end">
1299 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
1300 + <xul:spacer anonid="spacer" flex="1"/>
1301 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
1302 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
1303 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
1304 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
1305 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
1306 +#endif
1307 + </xul:hbox>
1308 + <xul:hbox>
1309 + <children/>
1310 + </xul:hbox>
1311 + </content>
1312 + <implementation implements="nsITimerCallback">
1313 + <constructor>
1314 + <![CDATA[
1315 + if (this.type != "child") {
1316 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1317 + .getService(Components.interfaces.nsIPrefBranch);
1318 + this.instantApply = psvc.getBoolPref("browser.preferences.instantApply");
1319 + if (this.instantApply) {
1320 + var docElt = document.documentElement;
1321 + var acceptButton = docElt.getButton("accept");
1322 + acceptButton.hidden = true;
1323 + var cancelButton = docElt.getButton("cancel");
1324 +#ifdef XP_MACOSX
1325 + // no buttons on Mac except Help
1326 + cancelButton.hidden = true;
1327 + // Also, don't fire onDialogAccept on enter
1328 + acceptButton.disabled = true;
1329 +#else
1330 + // morph the Cancel button into the Close button
1331 + cancelButton.setAttribute ("icon", "close");
1332 + cancelButton.label = docElt.getAttribute("closebuttonlabel");
1333 + cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey");
1334 +#endif
1337 + this.setAttribute("animated", this._shouldAnimate ? "true" : "false");
1338 + var panes = this.preferencePanes;
1340 + var lastPane = null;
1341 + if (this.lastSelected) {
1342 + lastPane = document.getElementById(this.lastSelected);
1343 + if (!lastPane) {
1344 + this.lastSelected = null;
1348 + var paneToLoad;
1349 + if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") {
1350 + paneToLoad = document.getElementById(window.arguments[0]);
1351 + this.lastSelected = paneToLoad.id;
1353 + else if (lastPane)
1354 + paneToLoad = lastPane;
1355 + else
1356 + paneToLoad = panes[0];
1358 + for (var i = 0; i < panes.length; ++i) {
1359 + this._makePaneButton(panes[i]);
1360 + if (panes[i].loaded) {
1361 + // Inline pane content, fire load event to force initialization.
1362 + this._fireEvent("paneload", panes[i]);
1365 + this.showPane(paneToLoad);
1367 + if (panes.length == 1)
1368 + this._selector.setAttribute("collapsed", "true");
1369 + ]]>
1370 + </constructor>
1372 + <destructor>
1373 + <![CDATA[
1374 + // Release timers to avoid reference cycles.
1375 + if (this._animateTimer) {
1376 + this._animateTimer.cancel();
1377 + this._animateTimer = null;
1379 + if (this._fadeTimer) {
1380 + this._fadeTimer.cancel();
1381 + this._fadeTimer = null;
1383 + ]]>
1384 + </destructor>
1386 + <field name="instantApply">false</field>
1388 + <property name="preferencePanes"
1389 + onget="return this.getElementsByTagName('prefpane');"/>
1391 + <property name="type" onget="return this.getAttribute('type');"/>
1392 + <property name="_paneDeck"
1393 + onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/>
1394 + <property name="_paneDeckContainer"
1395 + onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/>
1396 + <property name="_selector"
1397 + onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/>
1398 + <property name="lastSelected"
1399 + onget="return this.getAttribute('lastSelected');">
1400 + <setter>
1401 + this.setAttribute("lastSelected", val);
1402 + document.persist(this.id, "lastSelected");
1403 + return val;
1404 + </setter>
1405 + </property>
1406 + <property name="currentPane"
1407 + onset="return this._currentPane = val;">
1408 + <getter>
1409 + if (!this._currentPane)
1410 + this._currentPane = this.preferencePanes[0];
1412 + return this._currentPane;
1413 + </getter>
1414 + </property>
1415 + <field name="_currentPane">null</field>
1418 + <method name="_makePaneButton">
1419 + <parameter name="aPaneElement"/>
1420 + <body>
1421 + <![CDATA[
1422 + var radio = document.createElement("radio");
1423 + radio.setAttribute("pane", aPaneElement.id);
1424 + radio.setAttribute("label", aPaneElement.label);
1425 + // Expose preference group choice to accessibility APIs as an unchecked list item
1426 + // The parent group is exposed to accessibility APIs as a list
1427 + if (aPaneElement.image)
1428 + radio.setAttribute("src", aPaneElement.image);
1429 + radio.style.listStyleImage = aPaneElement.style.listStyleImage;
1430 + this._selector.appendChild(radio);
1431 + return radio;
1432 + ]]>
1433 + </body>
1434 + </method>
1436 + <method name="showPane">
1437 + <parameter name="aPaneElement"/>
1438 + <body>
1439 + <![CDATA[
1440 + if (!aPaneElement)
1441 + return;
1443 + this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id);
1444 + if (!aPaneElement.loaded) {
1445 + function OverlayLoadObserver(aPane)
1447 + this._pane = aPane;
1449 + OverlayLoadObserver.prototype = {
1450 + _outer: this,
1451 + observe: function (aSubject, aTopic, aData)
1453 + this._pane.loaded = true;
1454 + this._outer._fireEvent("paneload", this._pane);
1455 + this._outer._selectPane(this._pane);
1457 + };
1459 + var obs = new OverlayLoadObserver(aPaneElement);
1460 + document.loadOverlay(aPaneElement.src, obs);
1462 + else
1463 + this._selectPane(aPaneElement);
1464 + ]]>
1465 + </body>
1466 + </method>
1468 + <method name="_fireEvent">
1469 + <parameter name="aEventName"/>
1470 + <parameter name="aTarget"/>
1471 + <body>
1472 + <![CDATA[
1473 + // Panel loaded, synthesize a load event.
1474 + try {
1475 + var event = document.createEvent("Events");
1476 + event.initEvent(aEventName, true, true);
1477 + var cancel = !aTarget.dispatchEvent(event);
1478 + if (aTarget.hasAttribute("on" + aEventName)) {
1479 + var fn = new Function ("event", aTarget.getAttribute("on" + aEventName));
1480 + var rv = fn.call(aTarget, event);
1481 + if (rv == false)
1482 + cancel = true;
1484 + return !cancel;
1486 + catch (e) {
1487 + Components.utils.reportError(e);
1489 + return false;
1490 + ]]>
1491 + </body>
1492 + </method>
1494 + <field name="_initialized">false</field>
1495 + <method name="_selectPane">
1496 + <parameter name="aPaneElement"/>
1497 + <body>
1498 + <![CDATA[
1499 +#ifdef XP_MACOSX
1500 + var paneTitle = aPaneElement.label;
1501 + if (paneTitle != "")
1502 + document.title = paneTitle;
1503 +#endif
1504 + var helpButton = document.documentElement.getButton("help");
1505 + if (aPaneElement.helpTopic)
1506 + helpButton.hidden = false;
1507 + else
1508 + helpButton.hidden = true;
1510 + // Find this pane's index in the deck and set the deck's
1511 + // selectedIndex to that value to switch to it.
1512 + var prefpanes = this.preferencePanes;
1513 + for (var i = 0; i < prefpanes.length; ++i) {
1514 + if (prefpanes[i] == aPaneElement) {
1515 + this._paneDeck.selectedIndex = i;
1517 + if (this.type != "child") {
1518 + if (aPaneElement.hasAttribute("flex") && this._shouldAnimate &&
1519 + prefpanes.length > 1)
1520 + aPaneElement.removeAttribute("flex");
1521 + // Calling sizeToContent after the first prefpane is loaded
1522 + // will size the windows contents so style information is
1523 + // available to calculate correct sizing.
1524 + if (!this._initialized && prefpanes.length > 1) {
1525 + if (this._shouldAnimate)
1526 + this.style.minHeight = 0;
1527 + window.sizeToContent();
1530 + var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
1531 + oldPane.selected = !(aPaneElement.selected = true);
1532 + this.lastSelected = aPaneElement.id;
1533 + this.currentPane = aPaneElement;
1534 + this._initialized = true;
1536 + // Only animate if we've switched between prefpanes
1537 + if (this._shouldAnimate && oldPane.id != aPaneElement.id) {
1538 + aPaneElement.style.opacity = 0.0;
1539 + this.animate(oldPane, aPaneElement);
1541 + else if (!this._shouldAnimate && prefpanes.length > 1) {
1542 + var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer, "").height);
1543 + var verticalPadding = parseInt(window.getComputedStyle(aPaneElement, "").paddingTop);
1544 + verticalPadding += parseInt(window.getComputedStyle(aPaneElement, "").paddingBottom);
1545 + if (aPaneElement.contentHeight > targetHeight - verticalPadding) {
1546 + // To workaround the bottom border of a groupbox from being
1547 + // cutoff an hbox with a class of bottomBox may enclose it.
1548 + // This needs to include its padding to resize properly.
1549 + // See bug 394433
1550 + var bottomPadding = 0;
1551 + var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0];
1552 + if (bottomBox)
1553 + bottomPadding = parseInt(window.getComputedStyle(bottomBox, "").paddingBottom);
1554 + window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight;
1557 + // XXX rstrong - extend the contents of the prefpane to
1558 + // prevent elements from being cutoff (see bug 349098).
1559 + if (aPaneElement.contentHeight + verticalPadding < targetHeight)
1560 + aPaneElement._content.style.height = targetHeight - verticalPadding + "px";
1563 + break;
1566 + ]]>
1567 + </body>
1568 + </method>
1570 + <property name="_shouldAnimate">
1571 + <getter>
1572 + <![CDATA[
1573 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1574 + .getService(Components.interfaces.nsIPrefBranch);
1575 +#ifdef XP_MACOSX
1576 + var animate = true;
1577 +#else
1578 + var animate = false;
1579 +#endif
1580 + try {
1581 + animate = psvc.getBoolPref("browser.preferences.animateFadeIn");
1583 + catch (e) { }
1584 + return animate;
1585 + ]]>
1586 + </getter>
1587 + </property>
1589 + <method name="animate">
1590 + <parameter name="aOldPane"/>
1591 + <parameter name="aNewPane"/>
1592 + <body>
1593 + <![CDATA[
1594 + // if we are already resizing, use currentHeight
1595 + var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight;
1597 + this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1;
1598 + var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
1599 + this._animateRemainder = sizeDelta % this._animateIncrement;
1601 + this._setUpAnimationTimer(oldHeight);
1602 + ]]>
1603 + </body>
1604 + </method>
1606 + <property name="_sizeIncrement">
1607 + <getter>
1608 + <![CDATA[
1609 + var lastSelectedPane = document.getElementById(this.lastSelected);
1610 + var increment = this._animateIncrement * this._multiplier;
1611 + var newHeight = this._currentHeight + increment;
1612 + if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) ||
1613 + (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight))
1614 + return 0;
1616 + if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) ||
1617 + (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight))
1618 + increment = this._animateRemainder * this._multiplier;
1619 + return increment;
1620 + ]]>
1621 + </getter>
1622 + </property>
1624 + <method name="notify">
1625 + <parameter name="aTimer"/>
1626 + <body>
1627 + <![CDATA[
1628 + if (!document)
1629 + aTimer.cancel();
1631 + if (aTimer == this._animateTimer) {
1632 + var increment = this._sizeIncrement;
1633 + if (increment != 0) {
1634 + window.innerHeight += increment;
1635 + this._currentHeight += increment;
1637 + else {
1638 + aTimer.cancel();
1639 + this._setUpFadeTimer();
1641 + } else if (aTimer == this._fadeTimer) {
1642 + var elt = document.getElementById(this.lastSelected);
1643 + var newOpacity = parseFloat(window.getComputedStyle(elt, "").opacity) + this._fadeIncrement;
1644 + if (newOpacity < 1.0)
1645 + elt.style.opacity = newOpacity;
1646 + else {
1647 + aTimer.cancel();
1648 + elt.style.opacity = 1.0;
1651 + ]]>
1652 + </body>
1653 + </method>
1655 + <method name="_setUpAnimationTimer">
1656 + <parameter name="aStartHeight"/>
1657 + <body>
1658 + <![CDATA[
1659 + if (!this._animateTimer)
1660 + this._animateTimer = Components.classes["@mozilla.org/timer;1"]
1661 + .createInstance(Components.interfaces.nsITimer);
1662 + else
1663 + this._animateTimer.cancel();
1664 + this._currentHeight = aStartHeight;
1666 + this._animateTimer.initWithCallback(this, this._animateDelay,
1667 + Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
1668 + ]]>
1669 + </body>
1670 + </method>
1672 + <method name="_setUpFadeTimer">
1673 + <body>
1674 + <![CDATA[
1675 + if (!this._fadeTimer)
1676 + this._fadeTimer = Components.classes["@mozilla.org/timer;1"]
1677 + .createInstance(Components.interfaces.nsITimer);
1678 + else
1679 + this._fadeTimer.cancel();
1681 + this._fadeTimer.initWithCallback(this, this._fadeDelay,
1682 + Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
1683 + ]]>
1684 + </body>
1685 + </method>
1687 + <field name="_animateTimer">null</field>
1688 + <field name="_fadeTimer">null</field>
1689 + <field name="_animateDelay">15</field>
1690 + <field name="_animateIncrement">40</field>
1691 + <field name="_fadeDelay">5</field>
1692 + <field name="_fadeIncrement">0.40</field>
1693 + <field name="_animateRemainder">0</field>
1694 + <field name="_currentHeight">0</field>
1695 + <field name="_multiplier">0</field>
1697 + <method name="addPane">
1698 + <parameter name="aPaneElement"/>
1699 + <body>
1700 + <![CDATA[
1701 + this.appendChild(aPaneElement);
1703 + // Set up pane button
1704 + this._makePaneButton(aPaneElement);
1705 + ]]>
1706 + </body>
1707 + </method>
1709 + <method name="openSubDialog">
1710 + <parameter name="aURL"/>
1711 + <parameter name="aFeatures"/>
1712 + <parameter name="aParams"/>
1713 + <body>
1714 + return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
1715 + </body>
1716 + </method>
1718 + <method name="openWindow">
1719 + <parameter name="aWindowType"/>
1720 + <parameter name="aURL"/>
1721 + <parameter name="aFeatures"/>
1722 + <parameter name="aParams"/>
1723 + <body>
1724 + <![CDATA[
1725 + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
1726 + .getService(Components.interfaces.nsIWindowMediator);
1727 + var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null;
1728 + if (win) {
1729 + if ("initWithParams" in win)
1730 + win.initWithParams(aParams);
1731 + win.focus();
1733 + else {
1734 + var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : "");
1735 + var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener;
1736 + win = parentWindow.openDialog(aURL, "_blank", features, aParams);
1738 + return win;
1739 + ]]>
1740 + </body>
1741 + </method>
1742 + </implementation>
1743 + <handlers>
1744 + <handler event="dialogaccept">
1745 + <![CDATA[
1746 + if (!this._fireEvent("beforeaccept", this))
1747 + return;
1749 + if (this.type == "child" && window.opener) {
1750 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1751 + .getService(Components.interfaces.nsIPrefBranch);
1752 + var instantApply = psvc.getBoolPref("browser.preferences.instantApply");
1753 + if (instantApply) {
1754 + var panes = this.preferencePanes;
1755 + for (var i = 0; i < panes.length; ++i)
1756 + panes[i].writePreferences(true);
1758 + else {
1759 + // Clone all the preferences elements from the child document and
1760 + // insert them into the pane collection of the parent.
1761 + var pdoc = window.opener.document;
1762 + if (pdoc.documentElement.localName == "prefwindow") {
1763 + var currentPane = pdoc.documentElement.currentPane;
1764 + var id = window.location.href + "#childprefs";
1765 + var childPrefs = pdoc.getElementById(id);
1766 + if (!childPrefs) {
1767 + var childPrefs = pdoc.createElement("preferences");
1768 + currentPane.appendChild(childPrefs);
1769 + childPrefs.id = id;
1771 + var panes = this.preferencePanes;
1772 + for (var i = 0; i < panes.length; ++i) {
1773 + var preferences = panes[i].preferences;
1774 + for (var j = 0; j < preferences.length; ++j) {
1775 + // Try to find a preference element for the same preference.
1776 + var preference = null;
1777 + var parentPreferences = pdoc.getElementsByTagName("preferences");
1778 + for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
1779 + var parentPrefs = parentPreferences[k]
1780 + .getElementsByAttribute("name", preferences[j].name);
1781 + for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
1782 + if (parentPrefs[l].localName == "preference")
1783 + preference = parentPrefs[l];
1786 + if (!preference) {
1787 + // No matching preference in the parent window.
1788 + preference = pdoc.createElement("preference");
1789 + childPrefs.appendChild(preference);
1790 + preference.name = preferences[j].name;
1791 + preference.type = preferences[j].type;
1792 + preference.inverted = preferences[j].inverted;
1793 + preference.readonly = preferences[j].readonly;
1794 + preference.disabled = preferences[j].disabled;
1796 + preference.value = preferences[j].value;
1802 + else {
1803 + var panes = this.preferencePanes;
1804 + for (var i = 0; i < panes.length; ++i)
1805 + panes[i].writePreferences(false);
1807 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1808 + .getService(Components.interfaces.nsIPrefService);
1809 + psvc.savePrefFile(null);
1811 + ]]>
1812 + </handler>
1813 + <handler event="command">
1814 + if (event.originalTarget.hasAttribute("pane")) {
1815 + var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
1816 + this.showPane(pane);
1818 + </handler>
1820 + <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing">
1821 + <![CDATA[
1822 + if (this.instantApply)
1823 + window.close();
1824 + event.stopPropagation();
1825 + event.preventDefault();
1826 + ]]>
1827 + </handler>
1829 + <handler event="keypress"
1830 +#ifdef XP_MACOSX
1831 + key="&openHelpMac.commandkey;" modifiers="accel"
1832 +#else
1833 + keycode="&openHelp.commandkey;"
1834 +#endif
1835 + phase="capturing">
1836 + <![CDATA[
1837 + var helpButton = this.getButton("help");
1838 + if (helpButton.disabled || helpButton.hidden)
1839 + return;
1840 + this._fireEvent("dialoghelp", this);
1841 + event.stopPropagation();
1842 + event.preventDefault();
1843 + ]]>
1844 + </handler>
1845 + </handlers>
1846 + </binding>
1848 + <binding id="prefpane">
1849 + <resources>
1850 + <stylesheet src="chrome://global/skin/preferences.css"/>
1851 + </resources>
1852 + <content>
1853 + <xul:vbox class="content-box" xbl:inherits="flex">
1854 + <children/>
1855 + </xul:vbox>
1856 + </content>
1857 + <implementation>
1858 + <method name="writePreferences">
1859 + <parameter name="aFlushToDisk"/>
1860 + <body>
1861 + <![CDATA[
1862 + // Write all values to preferences.
1863 + var preferences = this.preferences;
1864 + for (var i = 0; i < preferences.length; ++i) {
1865 + var preference = preferences[i];
1866 + preference.batching = true;
1867 + preference.valueFromPreferences = preference.value;
1868 + preference.batching = false;
1870 + if (aFlushToDisk) {
1871 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1872 + .getService(Components.interfaces.nsIPrefService);
1873 + psvc.savePrefFile(null);
1875 + ]]>
1876 + </body>
1877 + </method>
1879 + <property name="src"
1880 + onget="return this.getAttribute('src');"
1881 + onset="this.setAttribute('src', val); return val;"/>
1882 + <property name="selected"
1883 + onget="return this.getAttribute('selected') == 'true';"
1884 + onset="this.setAttribute('selected', val); return val;"/>
1885 + <property name="image"
1886 + onget="return this.getAttribute('image');"
1887 + onset="this.setAttribute('image', val); return val;"/>
1888 + <property name="label"
1889 + onget="return this.getAttribute('label');"
1890 + onset="this.setAttribute('label', val); return val;"/>
1892 + <property name="preferenceElements"
1893 + onget="return this.getElementsByAttribute('preference', '*');"/>
1894 + <property name="preferences"
1895 + onget="return this.getElementsByTagName('preference');"/>
1897 + <property name="helpTopic">
1898 + <getter>
1899 + <![CDATA[
1900 + // if there are tabs, and the selected tab provides a helpTopic, return that
1901 + var box = this.getElementsByTagName("tabbox");
1902 + if (box[0]) {
1903 + var tab = box[0].selectedTab;
1904 + if (tab && tab.hasAttribute("helpTopic"))
1905 + return tab.getAttribute("helpTopic");
1908 + // otherwise, return the helpTopic of the current panel
1909 + return this.getAttribute("helpTopic");
1910 + ]]>
1911 + </getter>
1912 + </property>
1914 + <field name="_loaded">false</field>
1915 + <property name="loaded"
1916 + onget="return !this.src ? true : this._loaded;"
1917 + onset="this._loaded = val; return val;"/>
1919 + <method name="preferenceForElement">
1920 + <parameter name="aElement"/>
1921 + <body>
1922 + return document.getElementById(aElement.getAttribute("preference"));
1923 + </body>
1924 + </method>
1926 + <method name="getPreferenceElement">
1927 + <parameter name="aStartElement"/>
1928 + <body>
1929 + <![CDATA[
1930 + var temp = aStartElement;
1931 + while (temp && temp.nodeType == Node.ELEMENT_NODE &&
1932 + !temp.hasAttribute("preference"))
1933 + temp = temp.parentNode;
1934 + return temp.nodeType == Node.ELEMENT_NODE ? temp : aStartElement;
1935 + ]]>
1936 + </body>
1937 + </method>
1939 + <method name="userChangedValue">
1940 + <parameter name="aElement"/>
1941 + <body>
1942 + <![CDATA[
1943 + var element = this.getPreferenceElement(aElement);
1944 + if (element.hasAttribute("preference")) {
1945 + var preference = document.getElementById(element.getAttribute("preference"));
1946 + var prefVal = preference.getElementValue(element);
1947 + preference.value = prefVal;
1949 + ]]>
1950 + </body>
1951 + </method>
1953 + <property name="contentHeight">
1954 + <getter>
1955 + var targetHeight = parseInt(window.getComputedStyle(this._content, "").height);
1956 + targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop);
1957 + targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom);
1958 + return targetHeight;
1959 + </getter>
1960 + </property>
1961 + <field name="_content">
1962 + document.getAnonymousElementByAttribute(this, "class", "content-box");
1963 + </field>
1964 + </implementation>
1965 + <handlers>
1966 + <handler event="command">
1967 + // This "command" event handler tracks changes made to preferences by
1968 + // the user in this window.
1969 + this.userChangedValue(event.target);
1970 + </handler>
1971 + <handler event="select">
1972 + // This "select" event handler tracks changes made to colorpicker
1973 + // preferences by the user in this window.
1974 + if (event.target.localName == "colorpicker")
1975 + this.userChangedValue(event.target);
1976 + </handler>
1977 + <handler event="change">
1978 + // This "change" event handler tracks changes made to preferences by
1979 + // the user in this window.
1980 + this.userChangedValue(event.target);
1981 + </handler>
1982 + <handler event="input">
1983 + // This "input" event handler tracks changes made to preferences by
1984 + // the user in this window.
1985 + this.userChangedValue(event.target);
1986 + </handler>
1987 + <handler event="paneload">
1988 + <![CDATA[
1989 + // Initialize all values from preferences.
1990 + var elements = this.preferenceElements;
1991 + for (var i = 0; i < elements.length; ++i) {
1992 + try {
1993 + var preference = this.preferenceForElement(elements[i]);
1994 + preference.setElementValue(elements[i]);
1996 + catch (e) {
1997 + dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n");
2000 + ]]>
2001 + </handler>
2002 + </handlers>
2003 + </binding>
2005 + <binding id="panebutton" extends="chrome://global/content/bindings/radio.xml#radio">
2006 + <resources>
2007 + <stylesheet src="chrome://global/skin/preferences.css"/>
2008 + </resources>
2009 + <content>
2010 + <xul:image class="paneButtonIcon" xbl:inherits="src"/>
2011 + <xul:label class="paneButtonLabel" xbl:inherits="value=label"/>
2012 + </content>
2013 + <implementation implements="nsIAccessible">
2014 + <property name="accessibleType" readonly="true">
2015 + <getter>
2016 + <![CDATA[
2017 + return Components.interfaces.nsIAccessibleProvider.XULListitem;
2018 + ]]>
2019 + </getter>
2020 + </property>
2021 + </implementation>
2022 + </binding>
2024 +</bindings>
2026 +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2027 +# ***** BEGIN LICENSE BLOCK *****
2028 +# Version: MPL 1.1/GPL 2.0/LGPL 2.1
2030 +# The contents of this file are subject to the Mozilla Public License Version
2031 +# 1.1 (the "License"); you may not use this file except in compliance with
2032 +# the License. You may obtain a copy of the License at
2033 +# http://www.mozilla.org/MPL/
2035 +# Software distributed under the License is distributed on an "AS IS" basis,
2036 +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2037 +# for the specific language governing rights and limitations under the
2038 +# License.
2040 +# The Original Code is the Preferences System.
2042 +# The Initial Developer of the Original Code is
2043 +# Ben Goodger.
2044 +# Portions created by the Initial Developer are Copyright (C) 2005
2045 +# the Initial Developer. All Rights Reserved.
2047 +# Contributor(s):
2048 +# Ben Goodger <ben@mozilla.org>
2049 +# Josh Aas <josh@mozilla.com>
2051 +# Alternatively, the contents of this file may be used under the terms of
2052 +# either the GNU General Public License Version 2 or later (the "GPL"), or
2053 +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2054 +# in which case the provisions of the GPL or the LGPL are applicable instead
2055 +# of those above. If you wish to allow use of your version of this file only
2056 +# under the terms of either the GPL or the LGPL, and not to allow others to
2057 +# use your version of this file under the terms of the MPL, indicate your
2058 +# decision by deleting the provisions above and replace them with the notice
2059 +# and other provisions required by the GPL or the LGPL. If you do not delete
2060 +# the provisions above, a recipient may use your version of this file under
2061 +# the terms of any one of the MPL, the GPL or the LGPL.
2063 +# ***** END LICENSE BLOCK *****
2066 +# This is PrefWindow 6. The Code Could Well Be Ready, Are You?
2068 +# Historical References:
2069 +# PrefWindow V (February 1, 2003)
2070 +# PrefWindow IV (April 24, 2000)
2071 +# PrefWindow III (January 6, 2000)
2072 +# PrefWindow II (???)
2073 +# PrefWindow I (June 4, 1999)
2075 diff --git a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
2076 --- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
2077 +++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
2078 @@ -44,32 +44,35 @@
2079 #include "nsIURI.h"
2080 #include "nsReadableUtils.h"
2081 #include "nsArrayUtils.h"
2082 #include "prnetdb.h"
2083 #include "prenv.h"
2084 #include "nsPrintfCString.h"
2085 #include "nsNetUtil.h"
2086 #include "nsISupportsPrimitives.h"
2087 +#include "nsVoidArray.h"
2088 +#include "nsKDEUtils.h"
2090 class nsUnixSystemProxySettings : public nsISystemProxySettings {
2091 public:
2092 NS_DECL_ISUPPORTS
2093 NS_DECL_NSISYSTEMPROXYSETTINGS
2095 nsUnixSystemProxySettings() {}
2096 nsresult Init();
2098 private:
2099 ~nsUnixSystemProxySettings() {}
2101 nsCOMPtr<nsIGConfService> mGConf;
2102 PRBool IsProxyMode(const char* aMode);
2103 nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, nsACString& aResult);
2104 nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult);
2105 + nsresult GetProxyFromKDE(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult);
2108 NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
2110 nsresult
2111 nsUnixSystemProxySettings::Init()
2113 // If this is a GNOME session, load gconf and try to use its preferences.
2114 @@ -407,16 +410,19 @@ nsUnixSystemProxySettings::GetProxyForUR
2115 nsCAutoString host;
2116 rv = aURI->GetHost(host);
2117 NS_ENSURE_SUCCESS(rv, rv);
2119 PRInt32 port;
2120 rv = aURI->GetPort(&port);
2121 NS_ENSURE_SUCCESS(rv, rv);
2123 + if( nsKDEUtils::kdeSupport())
2124 + return GetProxyFromKDE( scheme, host, port, aResult );
2126 if (!mGConf)
2127 return GetProxyFromEnvironment(scheme, host, port, aResult);
2129 return GetProxyFromGConf(scheme, host, port, aResult);
2132 #define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\
2133 { 0x0fa3158c, 0xd5a7, 0x43de, \
2134 diff --git a/toolkit/xre/Makefile.in b/toolkit/xre/Makefile.in
2135 --- a/toolkit/xre/Makefile.in
2136 +++ b/toolkit/xre/Makefile.in
2137 @@ -97,17 +97,18 @@ CMMSRCS = nsNativeAppSupportCocoa.mm
2138 else
2139 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
2140 CPPSRCS += nsNativeAppSupportOS2.cpp
2141 else
2142 ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
2143 CPPSRCS += nsNativeAppSupportBeOS.cpp
2144 else
2145 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
2146 -CPPSRCS += nsNativeAppSupportUnix.cpp
2147 +CPPSRCS += nsNativeAppSupportUnix.cpp nsKDEUtils.cpp
2148 +EXPORTS += nsKDEUtils.h
2149 else
2150 ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
2151 CPPSRCS += nsNativeAppSupportQt.cpp
2152 CPPSRCS += nsQAppInstance.cpp
2153 EXPORTS += nsQAppInstance.h
2154 else
2155 CPPSRCS += nsNativeAppSupportDefault.cpp
2156 endif
2157 diff --git a/toolkit/xre/nsKDEUtils.cpp b/toolkit/xre/nsKDEUtils.cpp
2158 new file mode 100644
2159 --- /dev/null
2160 +++ b/toolkit/xre/nsKDEUtils.cpp
2161 @@ -0,0 +1,334 @@
2162 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2163 +/* ***** BEGIN LICENSE BLOCK *****
2164 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2166 + * The contents of this file are subject to the Mozilla Public License Version
2167 + * 1.1 (the "License"); you may not use this file except in compliance with
2168 + * the License. You may obtain a copy of the License at
2169 + * http://www.mozilla.org/MPL/
2171 + * Software distributed under the License is distributed on an "AS IS" basis,
2172 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2173 + * for the specific language governing rights and limitations under the
2174 + * License.
2176 + * The Original Code is Unix Native App Support.
2178 + * The Initial Developer of the Original Code is
2179 + * Mozilla Corporation.
2180 + * Portions created by the Initial Developer are Copyright (C) 2007
2181 + * the Initial Developer. All Rights Reserved.
2183 + * Contributor(s):
2185 + * Alternatively, the contents of this file may be used under the terms of
2186 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2187 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2188 + * in which case the provisions of the GPL or the LGPL are applicable instead
2189 + * of those above. If you wish to allow use of your version of this file only
2190 + * under the terms of either the GPL or the LGPL, and not to allow others to
2191 + * use your version of this file under the terms of the MPL, indicate your
2192 + * decision by deleting the provisions above and replace them with the notice
2193 + * and other provisions required by the GPL or the LGPL. If you do not delete
2194 + * the provisions above, a recipient may use your version of this file under
2195 + * the terms of any one of the MPL, the GPL or the LGPL.
2197 + * ***** END LICENSE BLOCK ***** */
2199 +#include "nsKDEUtils.h"
2200 +#include "nsIWidget.h"
2202 +#include <gtk/gtk.h>
2204 +#include <limits.h>
2205 +#include <stdio.h>
2206 +#include <sys/wait.h>
2207 +#include <unistd.h>
2208 +#include <X11/Xlib.h>
2210 +//#define DEBUG_KDE
2211 +#ifdef DEBUG_KDE
2212 +#define KMOZILLAHELPER "kmozillahelper"
2213 +#else
2214 +// not need for lib64, it's a binary
2215 +#define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper"
2216 +#endif
2218 +#define KMOZILLAHELPER_VERSION 6
2219 +#define MAKE_STR2( n ) #n
2220 +#define MAKE_STR( n ) MAKE_STR2( n )
2222 +static bool getKdeSession()
2224 + Display* dpy = XOpenDisplay( NULL );
2225 + if( dpy == NULL )
2226 + return false;
2227 + Atom kde_full_session = XInternAtom( dpy, "KDE_FULL_SESSION", True );
2228 + bool kde = false;
2229 + if( kde_full_session != None )
2231 + int cnt;
2232 + if( Atom* props = XListProperties( dpy, DefaultRootWindow( dpy ), &cnt ))
2234 + for( int i = 0;
2235 + i < cnt;
2236 + ++i )
2238 + if( props[ i ] == kde_full_session )
2240 + kde = true;
2241 +#ifdef DEBUG_KDE
2242 + fprintf( stderr, "KDE SESSION %d\n", kde );
2243 +#endif
2244 + break;
2247 + XFree( props );
2250 + XCloseDisplay( dpy );
2251 + return kde;
2254 +static bool getKdeSupport()
2256 + nsCStringArray command;
2257 + command.AppendCString( NS_LITERAL_CSTRING( "CHECK" ));
2258 + command.AppendCString( NS_LITERAL_CSTRING( MAKE_STR( KMOZILLAHELPER_VERSION )));
2259 + bool kde = nsKDEUtils::command( command );
2260 +#ifdef DEBUG_KDE
2261 + fprintf( stderr, "KDE RUNNING %d\n", kde );
2262 +#endif
2263 + return kde;
2266 +nsKDEUtils::nsKDEUtils()
2267 + : commandFile( NULL )
2268 + , replyFile( NULL )
2272 +nsKDEUtils::~nsKDEUtils()
2274 +// closeHelper(); not actually useful, exiting will close the fd too
2277 +nsKDEUtils* nsKDEUtils::self()
2279 + static nsKDEUtils s;
2280 + return &s;
2283 +static bool helperRunning = false;
2284 +static bool helperFailed = false;
2286 +bool nsKDEUtils::kdeSession()
2288 + static bool session = getKdeSession();
2289 + return session;
2292 +bool nsKDEUtils::kdeSupport()
2294 + static bool support = kdeSession() && getKdeSupport();
2295 + return support && helperRunning;
2298 +struct nsKDECommandData
2300 + FILE* file;
2301 + nsCStringArray* output;
2302 + GMainLoop* loop;
2303 + bool success;
2304 + };
2306 +static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data )
2308 + nsKDECommandData* p = static_cast< nsKDECommandData* >( data );
2309 + char buf[ 8192 ]; // TODO big enough
2310 + bool command_done = false;
2311 + bool command_failed = false;
2312 + while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL )
2313 + { // TODO what if the kernel splits a line into two chunks?
2314 +//#ifdef DEBUG_KDE
2315 +// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file ));
2316 +//#endif
2317 + if( char* eol = strchr( buf, '\n' ))
2318 + *eol = '\0';
2319 + command_done = ( strcmp( buf, "\\1" ) == 0 );
2320 + command_failed = ( strcmp( buf, "\\0" ) == 0 );
2321 + nsCAutoString line( buf );
2322 + line.ReplaceSubstring( "\\n", "\n" );
2323 + line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape
2324 + if( p->output && !( command_done || command_failed ))
2325 + p->output->AppendCString( nsCString( buf )); // TODO utf8?
2327 + bool quit = false;
2328 + if( feof( p->file ) || command_failed )
2330 + quit = true;
2331 + p->success = false;
2333 + if( command_done )
2334 + { // reading one reply finished
2335 + quit = true;
2336 + p->success = true;
2338 + if( quit )
2340 + if( p->loop )
2341 + g_main_loop_quit( p->loop );
2342 + return FALSE;
2344 + return TRUE;
2347 +bool nsKDEUtils::command( const nsCStringArray& command, nsCStringArray* output )
2349 + return self()->internalCommand( command, NULL, false, output );
2352 +bool nsKDEUtils::commandBlockUi( const nsCStringArray& command, const GtkWindow* parent, nsCStringArray* output )
2354 + return self()->internalCommand( command, parent, true, output );
2357 +bool nsKDEUtils::internalCommand( const nsCStringArray& command, const GtkWindow* parent, bool blockUi,
2358 + nsCStringArray* output )
2360 + if( !startHelper())
2361 + return false;
2362 + // if Gtk has meanwhile gotten a grab (bnc#555202, somehow the file dialog
2363 + // is called with a delay), then do not do anything, as this app would keep
2364 + // the grabs but block waiting for the helper, which would be unable to do
2365 + // anything because of the grab
2366 + if( blockUi && gdk_pointer_is_grabbed())
2367 + return false;
2368 + feedCommand( command );
2369 + // do not store the data in 'this' but in extra structure, just in case there
2370 + // is reentrancy (can there be? the event loop is re-entered)
2371 + nsKDECommandData data;
2372 + data.file = replyFile;
2373 + data.output = output;
2374 + data.success = false;
2375 + if( blockUi )
2377 + data.loop = g_main_loop_new( NULL, FALSE );
2378 + GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
2379 + if( parent && parent->group )
2380 + gtk_window_group_add_window( parent->group, GTK_WINDOW( window ));
2381 + gtk_widget_realize( window );
2382 + gtk_widget_set_sensitive( window, TRUE );
2383 + gtk_grab_add( window );
2384 + GIOChannel* channel = g_io_channel_unix_new( fileno( data.file ));
2385 + g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data );
2386 + g_io_channel_unref( channel );
2387 + g_main_loop_run( data.loop );
2388 + g_main_loop_unref( data.loop );
2389 + gtk_grab_remove( window );
2390 + gtk_widget_destroy( window );
2392 + else
2394 + data.loop = NULL;
2395 + while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data ))
2398 + return data.success;
2401 +bool nsKDEUtils::startHelper()
2403 + if( helperRunning )
2404 + return true;
2405 + if( helperFailed )
2406 + return false;
2407 + helperFailed = true;
2408 + int fdcommand[ 2 ];
2409 + int fdreply[ 2 ];
2410 + if( pipe( fdcommand ) < 0 )
2411 + return false;
2412 + if( pipe( fdreply ) < 0 )
2414 + close( fdcommand[ 0 ] );
2415 + close( fdcommand[ 1 ] );
2416 + return false;
2418 + char* args[ 2 ] = { const_cast< char* >( KMOZILLAHELPER ), NULL };
2419 + switch( fork())
2421 + case -1:
2423 + close( fdcommand[ 0 ] );
2424 + close( fdcommand[ 1 ] );
2425 + close( fdreply[ 0 ] );
2426 + close( fdreply[ 1 ] );
2427 + return false;
2429 + case 0: // child
2431 + if( dup2( fdcommand[ 0 ], STDIN_FILENO ) < 0 )
2432 + _exit( 1 );
2433 + if( dup2( fdreply[ 1 ], STDOUT_FILENO ) < 0 )
2434 + _exit( 1 );
2435 + int maxfd = 1024; // close all other fds
2436 + struct rlimit rl;
2437 + if( getrlimit( RLIMIT_NOFILE, &rl ) == 0 )
2438 + maxfd = rl.rlim_max;
2439 + for( int i = 3;
2440 + i < maxfd;
2441 + ++i )
2442 + close( i );
2443 +#ifdef DEBUG_KDE
2444 + execvp( KMOZILLAHELPER, args );
2445 +#else
2446 + execv( KMOZILLAHELPER, args );
2447 +#endif
2448 + _exit( 1 ); // failed
2450 + default: // parent
2452 + commandFile = fdopen( fdcommand[ 1 ], "w" );
2453 + replyFile = fdopen( fdreply[ 0 ], "r" );
2454 + close( fdcommand[ 0 ] );
2455 + close( fdreply[ 1 ] );
2456 + if( commandFile == NULL || replyFile == NULL )
2458 + closeHelper();
2459 + return false;
2461 + // ok, helper ready, getKdeRunning() will check if it works
2464 + helperFailed = false;
2465 + helperRunning = true;
2466 + return true;
2469 +void nsKDEUtils::closeHelper()
2471 + if( commandFile != NULL )
2472 + fclose( commandFile ); // this will also make the helper quit
2473 + if( replyFile != NULL )
2474 + fclose( replyFile );
2475 + helperRunning = false;
2478 +void nsKDEUtils::feedCommand( const nsCStringArray& command )
2480 + for( int i = 0;
2481 + i < command.Count();
2482 + ++i )
2484 + nsCString line = *command[ i ];
2485 + line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape
2486 + line.ReplaceSubstring( "\n", "\\n" );
2487 +#ifdef DEBUG_KDE
2488 + fprintf( stderr, "COMM: %s\n", line.get());
2489 +#endif
2490 + fputs( line.get(), commandFile );
2491 + fputs( "\n", commandFile );
2493 + fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data
2494 + fflush( commandFile );
2496 diff --git a/toolkit/xre/nsKDEUtils.h b/toolkit/xre/nsKDEUtils.h
2497 new file mode 100644
2498 --- /dev/null
2499 +++ b/toolkit/xre/nsKDEUtils.h
2500 @@ -0,0 +1,77 @@
2501 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2503 + * ***** BEGIN LICENSE BLOCK *****
2504 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2506 + * The contents of this file are subject to the Mozilla Public License Version
2507 + * 1.1 (the "License"); you may not use this file except in compliance with
2508 + * the License. You may obtain a copy of the License at
2509 + * http://www.mozilla.org/MPL/
2511 + * Software distributed under the License is distributed on an "AS IS" basis,
2512 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2513 + * for the specific language governing rights and limitations under the
2514 + * License.
2516 + * The Original Code is Mozilla Communicator client code.
2518 + * The Initial Developer of the Original Code is
2519 + * Netscape Communications Corporation.
2520 + * Portions created by the Initial Developer are Copyright (C) 1998
2521 + * the Initial Developer. All Rights Reserved.
2523 + * Contributor(s):
2525 + * Alternatively, the contents of this file may be used under the terms of
2526 + * either of the GNU General Public License Version 2 or later (the "GPL"),
2527 + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2528 + * in which case the provisions of the GPL or the LGPL are applicable instead
2529 + * of those above. If you wish to allow use of your version of this file only
2530 + * under the terms of either the GPL or the LGPL, and not to allow others to
2531 + * use your version of this file under the terms of the MPL, indicate your
2532 + * decision by deleting the provisions above and replace them with the notice
2533 + * and other provisions required by the GPL or the LGPL. If you do not delete
2534 + * the provisions above, a recipient may use your version of this file under
2535 + * the terms of any one of the MPL, the GPL or the LGPL.
2537 + * ***** END LICENSE BLOCK ***** */
2539 +#ifndef nsKDEUtils_h__
2540 +#define nsKDEUtils_h__
2542 +#include "nsStringGlue.h"
2543 +#include "nsVoidArray.h"
2544 +#include <stdio.h>
2546 +typedef struct _GtkWindow GtkWindow;
2548 +class NS_EXPORT nsKDEUtils
2550 + public:
2551 + /* Returns true if running inside a KDE session (regardless of whether there is KDE
2552 + support available for Firefox). This should be used e.g. when determining
2553 + dialog button order but not for code that requires the KDE support. */
2554 + static bool kdeSession();
2555 + /* Returns true if running inside a KDE session and KDE support is available
2556 + for Firefox. This should be used everywhere where the external helper is needed. */
2557 + static bool kdeSupport();
2558 + /* Executes the given helper command, returns true if helper returned success. */
2559 + static bool command( const nsCStringArray& command, nsCStringArray* output = NULL );
2560 + /* Like command(), but additionally blocks the parent widget like if there was
2561 + a modal dialog shown and enters the event loop (i.e. there are still paint updates,
2562 + this is for commands that take long). */
2563 + static bool commandBlockUi( const nsCStringArray& command, const GtkWindow* parent, nsCStringArray* output = NULL );
2564 + private:
2565 + nsKDEUtils();
2566 + ~nsKDEUtils();
2567 + static nsKDEUtils* self();
2568 + bool startHelper();
2569 + void closeHelper();
2570 + void feedCommand( const nsCStringArray& command );
2571 + bool internalCommand( const nsCStringArray& command, const GtkWindow* parent, bool isParent,
2572 + nsCStringArray* output );
2573 + FILE* commandFile;
2574 + FILE* replyFile;
2575 + };
2577 +#endif // nsKDEUtils
2578 diff --git a/uriloader/exthandler/Makefile.in b/uriloader/exthandler/Makefile.in
2579 --- a/uriloader/exthandler/Makefile.in
2580 +++ b/uriloader/exthandler/Makefile.in
2581 @@ -94,18 +94,19 @@ LOCAL_INCLUDES += -I$(topsrcdir)/dom/bas
2582 -I$(topsrcdir)/dom/ipc \
2583 -I$(topsrcdir)/content/base/src \
2584 -I$(topsrcdir)/content/events/src \
2585 -I$(topsrcdir)/netwerk/base/src \
2586 -I$(topsrcdir)/netwerk/protocol/http
2587 endif
2589 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
2590 -OSHELPER += nsGNOMERegistry.cpp
2591 +OSHELPER += nsCommonRegistry.cpp nsGNOMERegistry.cpp nsKDERegistry.cpp
2592 OSHELPER += nsMIMEInfoUnix.cpp
2593 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
2594 endif
2596 ifeq ($(MOZ_WIDGET_TOOLKIT),android)
2597 OSHELPER += nsMIMEInfoAndroid.cpp
2598 OSHELPER += nsAndroidHandlerApp.cpp
2599 OSHELPER += nsExternalSharingAppService.cpp
2600 EXPORTS += nsExternalSharingAppService.h
2601 OSHELPER += nsExternalURLHandlerService.cpp
2602 diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp
2603 new file mode 100644
2604 --- /dev/null
2605 +++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp
2606 @@ -0,0 +1,87 @@
2607 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2608 +/* ***** BEGIN LICENSE BLOCK *****
2609 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2611 + * The contents of this file are subject to the Mozilla Public License Version
2612 + * 1.1 (the "License"); you may not use this file except in compliance with
2613 + * the License. You may obtain a copy of the License at
2614 + * http://www.mozilla.org/MPL/
2616 + * Software distributed under the License is distributed on an "AS IS" basis,
2617 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2618 + * for the specific language governing rights and limitations under the
2619 + * License.
2621 + * The Original Code is the GNOME helper app implementation.
2623 + * The Initial Developer of the Original Code is
2624 + * IBM Corporation.
2625 + * Portions created by the Initial Developer are Copyright (C) 2003
2626 + * the Initial Developer. All Rights Reserved.
2628 + * Contributor(s):
2629 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2631 + * Alternatively, the contents of this file may be used under the terms of
2632 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2633 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2634 + * in which case the provisions of the GPL or the LGPL are applicable instead
2635 + * of those above. If you wish to allow use of your version of this file only
2636 + * under the terms of either the GPL or the LGPL, and not to allow others to
2637 + * use your version of this file under the terms of the MPL, indicate your
2638 + * decision by deleting the provisions above and replace them with the notice
2639 + * and other provisions required by the GPL or the LGPL. If you do not delete
2640 + * the provisions above, a recipient may use your version of this file under
2641 + * the terms of any one of the MPL, the GPL or the LGPL.
2643 + * ***** END LICENSE BLOCK ***** */
2645 +#include "nsCommonRegistry.h"
2647 +#include "nsGNOMERegistry.h"
2648 +#include "nsKDERegistry.h"
2649 +#include "nsString.h"
2650 +#include "nsVoidArray.h"
2651 +#include "nsKDEUtils.h"
2653 +/* static */ PRBool
2654 +nsCommonRegistry::HandlerExists(const char *aProtocolScheme)
2656 + if( nsKDEUtils::kdeSupport())
2657 + return nsKDERegistry::HandlerExists( aProtocolScheme );
2658 + return nsGNOMERegistry::HandlerExists( aProtocolScheme );
2661 +/* static */ nsresult
2662 +nsCommonRegistry::LoadURL(nsIURI *aURL)
2664 + if( nsKDEUtils::kdeSupport())
2665 + return nsKDERegistry::LoadURL( aURL );
2666 + return nsGNOMERegistry::LoadURL( aURL );
2669 +/* static */ void
2670 +nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme,
2671 + nsAString& aDesc)
2673 + if( nsKDEUtils::kdeSupport())
2674 + return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc );
2675 + return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc );
2679 +/* static */ already_AddRefed<nsMIMEInfoBase>
2680 +nsCommonRegistry::GetFromExtension(const nsACString& aFileExt)
2682 + if( nsKDEUtils::kdeSupport())
2683 + return nsKDERegistry::GetFromExtension( aFileExt );
2684 + return nsGNOMERegistry::GetFromExtension( aFileExt );
2687 +/* static */ already_AddRefed<nsMIMEInfoBase>
2688 +nsCommonRegistry::GetFromType(const nsACString& aMIMEType)
2690 + if( nsKDEUtils::kdeSupport())
2691 + return nsKDERegistry::GetFromType( aMIMEType );
2692 + return nsGNOMERegistry::GetFromType( aMIMEType );
2694 diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h
2695 new file mode 100644
2696 --- /dev/null
2697 +++ b/uriloader/exthandler/unix/nsCommonRegistry.h
2698 @@ -0,0 +1,56 @@
2699 +/* ***** BEGIN LICENSE BLOCK *****
2700 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2702 + * The contents of this file are subject to the Mozilla Public License Version
2703 + * 1.1 (the "License"); you may not use this file except in compliance with
2704 + * the License. You may obtain a copy of the License at
2705 + * http://www.mozilla.org/MPL/
2707 + * Software distributed under the License is distributed on an "AS IS" basis,
2708 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2709 + * for the specific language governing rights and limitations under the
2710 + * License.
2712 + * The Original Code is the GNOME helper app implementation.
2714 + * The Initial Developer of the Original Code is
2715 + * IBM Corporation.
2716 + * Portions created by the Initial Developer are Copyright (C) 2003
2717 + * the Initial Developer. All Rights Reserved.
2719 + * Contributor(s):
2720 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2722 + * Alternatively, the contents of this file may be used under the terms of
2723 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2724 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2725 + * in which case the provisions of the GPL or the LGPL are applicable instead
2726 + * of those above. If you wish to allow use of your version of this file only
2727 + * under the terms of either the GPL or the LGPL, and not to allow others to
2728 + * use your version of this file under the terms of the MPL, indicate your
2729 + * decision by deleting the provisions above and replace them with the notice
2730 + * and other provisions required by the GPL or the LGPL. If you do not delete
2731 + * the provisions above, a recipient may use your version of this file under
2732 + * the terms of any one of the MPL, the GPL or the LGPL.
2734 + * ***** END LICENSE BLOCK ***** */
2736 +#include "nsIURI.h"
2737 +#include "nsCOMPtr.h"
2739 +class nsMIMEInfoBase;
2741 +class nsCommonRegistry
2743 + public:
2744 + static PRBool HandlerExists(const char *aProtocolScheme);
2746 + static nsresult LoadURL(nsIURI *aURL);
2748 + static void GetAppDescForScheme(const nsACString& aScheme,
2749 + nsAString& aDesc);
2751 + static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt);
2753 + static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType);
2755 diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp
2756 new file mode 100644
2757 --- /dev/null
2758 +++ b/uriloader/exthandler/unix/nsKDERegistry.cpp
2759 @@ -0,0 +1,119 @@
2760 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2761 +/* ***** BEGIN LICENSE BLOCK *****
2762 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2764 + * The contents of this file are subject to the Mozilla Public License Version
2765 + * 1.1 (the "License"); you may not use this file except in compliance with
2766 + * the License. You may obtain a copy of the License at
2767 + * http://www.mozilla.org/MPL/
2769 + * Software distributed under the License is distributed on an "AS IS" basis,
2770 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2771 + * for the specific language governing rights and limitations under the
2772 + * License.
2774 + * The Original Code is the GNOME helper app implementation.
2776 + * The Initial Developer of the Original Code is
2777 + * IBM Corporation.
2778 + * Portions created by the Initial Developer are Copyright (C) 2003
2779 + * the Initial Developer. All Rights Reserved.
2781 + * Contributor(s):
2782 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2784 + * Alternatively, the contents of this file may be used under the terms of
2785 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2786 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2787 + * in which case the provisions of the GPL or the LGPL are applicable instead
2788 + * of those above. If you wish to allow use of your version of this file only
2789 + * under the terms of either the GPL or the LGPL, and not to allow others to
2790 + * use your version of this file under the terms of the MPL, indicate your
2791 + * decision by deleting the provisions above and replace them with the notice
2792 + * and other provisions required by the GPL or the LGPL. If you do not delete
2793 + * the provisions above, a recipient may use your version of this file under
2794 + * the terms of any one of the MPL, the GPL or the LGPL.
2796 + * ***** END LICENSE BLOCK ***** */
2798 +#include "nsKDERegistry.h"
2799 +#include "prlink.h"
2800 +#include "prmem.h"
2801 +#include "nsString.h"
2802 +#include "nsILocalFile.h"
2803 +#include "nsMIMEInfoUnix.h"
2804 +#include "nsAutoPtr.h"
2805 +#include "nsKDEUtils.h"
2807 +/* static */ PRBool
2808 +nsKDERegistry::HandlerExists(const char *aProtocolScheme)
2810 + nsCStringArray command;
2811 + command.AppendCString( NS_LITERAL_CSTRING( "HANDLEREXISTS" ));
2812 + command.AppendCString( nsCAutoString( aProtocolScheme ));
2813 + return nsKDEUtils::command( command );
2816 +/* static */ nsresult
2817 +nsKDERegistry::LoadURL(nsIURI *aURL)
2819 + nsCStringArray command;
2820 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
2821 + nsCString url;
2822 + aURL->GetSpec( url );
2823 + command.AppendCString( url );
2824 + return nsKDEUtils::command( command );
2827 +/* static */ void
2828 +nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme,
2829 + nsAString& aDesc)
2831 + nsCStringArray command;
2832 + command.AppendCString( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" ));
2833 + command.AppendCString( aScheme );
2834 + nsCStringArray output;
2835 + if( nsKDEUtils::command( command, &output ) && output.Count() == 1 )
2836 + CopyUTF8toUTF16( *output[ 0 ], aDesc );
2840 +/* static */ already_AddRefed<nsMIMEInfoBase>
2841 +nsKDERegistry::GetFromExtension(const nsACString& aFileExt)
2843 + NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot");
2844 + nsCStringArray command;
2845 + command.AppendCString( NS_LITERAL_CSTRING( "GETFROMEXTENSION" ));
2846 + command.AppendCString( aFileExt );
2847 + return GetFromHelper( command );
2850 +/* static */ already_AddRefed<nsMIMEInfoBase>
2851 +nsKDERegistry::GetFromType(const nsACString& aMIMEType)
2853 + nsCStringArray command;
2854 + command.AppendCString( NS_LITERAL_CSTRING( "GETFROMTYPE" ));
2855 + command.AppendCString( aMIMEType );
2856 + return GetFromHelper( command );
2859 +/* static */ already_AddRefed<nsMIMEInfoBase>
2860 +nsKDERegistry::GetFromHelper(const nsCStringArray& command)
2862 + nsCStringArray output;
2863 + if( nsKDEUtils::command( command, &output ) && output.Count() == 3 )
2865 + nsCString mimetype = *output[ 0 ];
2866 + nsRefPtr<nsMIMEInfoUnix> mimeInfo = new nsMIMEInfoUnix( mimetype );
2867 + NS_ENSURE_TRUE(mimeInfo, nsnull);
2868 + nsCString description = *output[ 1 ];
2869 + mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description));
2870 + nsCString handlerAppName = *output[ 2 ];
2871 + mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName));
2872 + mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault);
2873 + nsMIMEInfoBase* retval;
2874 + NS_ADDREF((retval = mimeInfo));
2875 + return retval;
2877 + return nsnull;
2879 diff --git a/uriloader/exthandler/unix/nsKDERegistry.h b/uriloader/exthandler/unix/nsKDERegistry.h
2880 new file mode 100644
2881 --- /dev/null
2882 +++ b/uriloader/exthandler/unix/nsKDERegistry.h
2883 @@ -0,0 +1,61 @@
2884 +/* ***** BEGIN LICENSE BLOCK *****
2885 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2887 + * The contents of this file are subject to the Mozilla Public License Version
2888 + * 1.1 (the "License"); you may not use this file except in compliance with
2889 + * the License. You may obtain a copy of the License at
2890 + * http://www.mozilla.org/MPL/
2892 + * Software distributed under the License is distributed on an "AS IS" basis,
2893 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2894 + * for the specific language governing rights and limitations under the
2895 + * License.
2897 + * The Original Code is the GNOME helper app implementation.
2899 + * The Initial Developer of the Original Code is
2900 + * IBM Corporation.
2901 + * Portions created by the Initial Developer are Copyright (C) 2003
2902 + * the Initial Developer. All Rights Reserved.
2904 + * Contributor(s):
2905 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2907 + * Alternatively, the contents of this file may be used under the terms of
2908 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2909 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2910 + * in which case the provisions of the GPL or the LGPL are applicable instead
2911 + * of those above. If you wish to allow use of your version of this file only
2912 + * under the terms of either the GPL or the LGPL, and not to allow others to
2913 + * use your version of this file under the terms of the MPL, indicate your
2914 + * decision by deleting the provisions above and replace them with the notice
2915 + * and other provisions required by the GPL or the LGPL. If you do not delete
2916 + * the provisions above, a recipient may use your version of this file under
2917 + * the terms of any one of the MPL, the GPL or the LGPL.
2919 + * ***** END LICENSE BLOCK ***** */
2921 +#include "nsIURI.h"
2922 +#include "nsCOMPtr.h"
2924 +class nsMIMEInfoBase;
2925 +class nsCAutoString;
2926 +class nsCStringArray;
2928 +class nsKDERegistry
2930 + public:
2931 + static PRBool HandlerExists(const char *aProtocolScheme);
2933 + static nsresult LoadURL(nsIURI *aURL);
2935 + static void GetAppDescForScheme(const nsACString& aScheme,
2936 + nsAString& aDesc);
2938 + static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt);
2940 + static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType);
2941 + private:
2942 + static already_AddRefed<nsMIMEInfoBase> GetFromHelper(const nsCStringArray& command);
2945 diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
2946 --- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
2947 +++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
2948 @@ -50,30 +50,33 @@
2949 #include <QString>
2950 #if (MOZ_ENABLE_CONTENTACTION)
2951 #include <contentaction/contentaction.h>
2952 #include "nsContentHandlerApp.h"
2953 #endif
2954 #endif
2956 #include "nsMIMEInfoUnix.h"
2957 -#include "nsGNOMERegistry.h"
2958 +#include "nsCommonRegistry.h"
2959 #include "nsIGIOService.h"
2960 #include "nsNetCID.h"
2961 #include "nsIIOService.h"
2962 #include "nsIGnomeVFSService.h"
2963 #include "nsAutoPtr.h"
2964 #ifdef MOZ_ENABLE_DBUS
2965 #include "nsDBusHandlerApp.h"
2966 #endif
2967 +#if defined(XP_UNIX) && !defined(XP_MACOSX)
2968 +#include "nsKDEUtils.h"
2969 +#endif
2971 nsresult
2972 nsMIMEInfoUnix::LoadUriInternal(nsIURI * aURI)
2974 - nsresult rv = nsGNOMERegistry::LoadURL(aURI);
2975 + nsresult rv = nsCommonRegistry::LoadURL(aURI);
2977 #if (MOZ_PLATFORM_MAEMO == 5) && defined (MOZ_ENABLE_GNOMEVFS)
2978 if (NS_FAILED(rv)){
2979 HildonURIAction *action = hildon_uri_get_default_action(mSchemeOrType.get(), nsnull);
2980 if (action) {
2981 nsCAutoString spec;
2982 aURI->GetAsciiSpec(spec);
2983 if (hildon_uri_open(spec.get(), action, nsnull))
2984 @@ -95,22 +98,22 @@
2986 return rv;
2989 NS_IMETHODIMP
2990 nsMIMEInfoUnix::GetHasDefaultHandler(PRBool *_retval)
2992 *_retval = PR_FALSE;
2993 - nsRefPtr<nsMIMEInfoBase> mimeInfo = nsGNOMERegistry::GetFromType(mSchemeOrType);
2994 + nsRefPtr<nsMIMEInfoBase> mimeInfo = nsCommonRegistry::GetFromType(mSchemeOrType);
2995 if (!mimeInfo) {
2996 nsCAutoString ext;
2997 nsresult rv = GetPrimaryExtension(ext);
2998 if (NS_SUCCEEDED(rv)) {
2999 - mimeInfo = nsGNOMERegistry::GetFromExtension(ext);
3000 + mimeInfo = nsCommonRegistry::GetFromExtension(ext);
3003 if (mimeInfo)
3004 *_retval = PR_TRUE;
3006 if (*_retval)
3007 return NS_OK;
3009 @@ -153,16 +156,33 @@
3010 ContentAction::Action::defaultActionForFile(uri, QString(mSchemeOrType.get()));
3011 if (action.isValid()) {
3012 action.trigger();
3013 return NS_OK;
3015 return NS_ERROR_FAILURE;
3016 #endif
3018 + if( nsKDEUtils::kdeSupport()) {
3019 + PRBool supports;
3020 + if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) {
3021 + nsCStringArray command;
3022 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
3023 + command.AppendCString( nativePath );
3024 + command.AppendCString( NS_LITERAL_CSTRING( "MIMETYPE" ));
3025 + command.AppendCString( mSchemeOrType );
3026 + if( nsKDEUtils::command( command ))
3027 + return NS_OK;
3029 + if (!mDefaultApplication)
3030 + return NS_ERROR_FILE_NOT_FOUND;
3032 + return LaunchWithIProcess(mDefaultApplication, nativePath);
3035 nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3036 nsCAutoString uriSpec;
3037 if (giovfs) {
3038 // nsGIOMimeApp->Launch wants a URI string instead of local file
3039 nsresult rv;
3040 nsCOMPtr<nsIIOService> ioservice = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
3041 NS_ENSURE_SUCCESS(rv, rv);
3042 nsCOMPtr<nsIURI> uri;
3043 @@ -180,17 +200,17 @@
3044 /* Fallback to GnomeVFS */
3045 nsCOMPtr<nsIGnomeVFSMimeApp> app;
3046 if (NS_SUCCEEDED(gnomevfs->GetAppForMimeType(mSchemeOrType, getter_AddRefs(app))) && app)
3047 return app->Launch(nativePath);
3050 // If we haven't got an app we try to get a valid one by searching for the
3051 // extension mapped type
3052 - nsRefPtr<nsMIMEInfoBase> mimeInfo = nsGNOMERegistry::GetFromExtension(nativePath);
3053 + nsRefPtr<nsMIMEInfoBase> mimeInfo = nsCommonRegistry::GetFromExtension(nativePath);
3054 if (mimeInfo) {
3055 nsCAutoString type;
3056 mimeInfo->GetType(type);
3057 if (giovfs) {
3058 nsCOMPtr<nsIGIOMimeApp> app;
3059 if (NS_SUCCEEDED(giovfs->GetAppForMimeType(type, getter_AddRefs(app))) && app)
3060 return app->Launch(uriSpec);
3061 } else if (gnomevfs) {
3062 diff --git a/uriloader/exthandler/unix/nsOSHelperAppService.cpp b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
3063 --- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp
3064 +++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
3065 @@ -44,17 +44,17 @@
3066 #if defined(MOZ_ENABLE_CONTENTACTION)
3067 #include <contentaction/contentaction.h>
3068 #include <QString>
3069 #endif
3071 #include "nsOSHelperAppService.h"
3072 #include "nsMIMEInfoUnix.h"
3073 #ifdef MOZ_WIDGET_GTK2
3074 -#include "nsGNOMERegistry.h"
3075 +#include "nsCommonRegistry.h"
3076 #endif
3077 #include "nsISupports.h"
3078 #include "nsString.h"
3079 #include "nsReadableUtils.h"
3080 #include "nsUnicharUtils.h"
3081 #include "nsXPIDLString.h"
3082 #include "nsIURL.h"
3083 #include "nsIFileStreams.h"
3084 @@ -1219,29 +1219,29 @@ nsresult nsOSHelperAppService::OSProtoco
3085 ContentAction::Action::defaultActionForScheme(QString(aProtocolScheme) + ':');
3087 if (action.isValid())
3088 *aHandlerExists = PR_TRUE;
3089 #endif
3091 #ifdef MOZ_WIDGET_GTK2
3092 // Check the GConf registry for a protocol handler
3093 - *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme);
3094 + *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme);
3095 #if (MOZ_PLATFORM_MAEMO == 5) && defined (MOZ_ENABLE_GNOMEVFS)
3096 *aHandlerExists = nsMIMEInfoUnix::HandlerExists(aProtocolScheme);
3097 #endif
3098 #endif
3100 return NS_OK;
3103 NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription(const nsACString& aScheme, nsAString& _retval)
3105 #ifdef MOZ_WIDGET_GTK2
3106 - nsGNOMERegistry::GetAppDescForScheme(aScheme, _retval);
3107 + nsCommonRegistry::GetAppDescForScheme(aScheme, _retval);
3108 return _retval.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK;
3109 #else
3110 return NS_ERROR_NOT_AVAILABLE;
3111 #endif
3114 nsresult nsOSHelperAppService::GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile)
3116 @@ -1327,17 +1327,17 @@ nsOSHelperAppService::GetFromExtension(c
3117 minorType,
3118 mime_types_description,
3119 PR_TRUE);
3121 if (NS_FAILED(rv) || majorType.IsEmpty()) {
3123 #ifdef MOZ_WIDGET_GTK2
3124 LOG(("Looking in GNOME registry\n"));
3125 - nsMIMEInfoBase *gnomeInfo = nsGNOMERegistry::GetFromExtension(aFileExt).get();
3126 + nsMIMEInfoBase *gnomeInfo = nsCommonRegistry::GetFromExtension(aFileExt).get();
3127 if (gnomeInfo) {
3128 LOG(("Got MIMEInfo from GNOME registry\n"));
3129 return gnomeInfo;
3131 #endif
3133 rv = LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt),
3134 majorType,
3135 @@ -1453,17 +1453,17 @@ nsOSHelperAppService::GetFromType(const
3136 #ifdef MOZ_WIDGET_GTK2
3137 nsMIMEInfoBase *gnomeInfo = nsnull;
3138 if (handler.IsEmpty()) {
3139 // No useful data yet. Check the GNOME registry. Unfortunately, newer
3140 // GNOME versions no longer have type-to-extension mappings, so we might
3141 // get back a MIMEInfo without any extensions set. In that case we'll have
3142 // to look in our mime.types files for the extensions.
3143 LOG(("Looking in GNOME registry\n"));
3144 - gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType).get();
3145 + gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType).get();
3146 if (gnomeInfo && gnomeInfo->HasExtensions()) {
3147 LOG(("Got MIMEInfo from GNOME registry, and it has extensions set\n"));
3148 return gnomeInfo;
3151 #endif
3153 // Now look up our extensions
3154 diff --git a/widget/src/gtk2/Makefile.in b/widget/src/gtk2/Makefile.in
3155 --- a/widget/src/gtk2/Makefile.in
3156 +++ b/widget/src/gtk2/Makefile.in
3157 @@ -157,11 +157,14 @@ endif
3159 DEFINES += -DCAIRO_GFX
3161 INCLUDES += \
3162 -I$(srcdir)/../xpwidgets \
3163 -I$(srcdir)/../shared \
3164 -I$(topsrcdir)/other-licenses/atk-1.0 \
3165 $(NULL)
3167 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
3169 ifdef MOZ_X11
3170 INCLUDES += -I$(srcdir)/../shared/x11
3171 endif
3172 diff --git a/widget/src/gtk2/nsFilePicker.cpp b/widget/src/gtk2/nsFilePicker.cpp
3173 --- a/widget/src/gtk2/nsFilePicker.cpp
3174 +++ b/widget/src/gtk2/nsFilePicker.cpp
3175 @@ -31,16 +31,17 @@
3176 * decision by deleting the provisions above and replace them with the notice
3177 * and other provisions required by the GPL or the LGPL. If you do not delete
3178 * the provisions above, a recipient may use your version of this file under
3179 * the terms of any one of the MPL, the GPL or the LGPL.
3181 * ***** END LICENSE BLOCK ***** */
3183 #include <gtk/gtk.h>
3184 +#include <gdk/gdkx.h>
3186 #include "nsIFileURL.h"
3187 #include "nsIURI.h"
3188 #include "nsIWidget.h"
3189 #include "nsILocalFile.h"
3190 #include "nsIStringBundle.h"
3192 #include "nsArrayEnumerator.h"
3193 @@ -50,16 +51,17 @@
3194 #include "nsReadableUtils.h"
3195 #include "mozcontainer.h"
3197 #include "prmem.h"
3198 #include "prlink.h"
3200 #include "nsFilePicker.h"
3201 #include "nsAccessibilityHelper.h"
3202 +#include "nsKDEUtils.h"
3204 #if (MOZ_PLATFORM_MAEMO == 5)
3205 #include <hildon-fm-2/hildon/hildon-file-chooser-dialog.h>
3206 #endif
3208 #define MAX_PREVIEW_SIZE 180
3210 nsILocalFile *nsFilePicker::mPrevDisplayDirectory = nsnull;
3211 @@ -271,17 +273,19 @@ nsFilePicker::AppendFilters(PRInt32 aFil
3212 return nsBaseFilePicker::AppendFilters(aFilterMask);
3215 NS_IMETHODIMP
3216 nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
3218 if (aFilter.EqualsLiteral("..apps")) {
3219 // No platform specific thing we can do here, really....
3220 - return NS_OK;
3221 + // Unless it's KDE.
3222 + if( mMode != modeOpen || !nsKDEUtils::kdeSupport())
3223 + return NS_OK;
3226 nsCAutoString filter, name;
3227 CopyUTF16toUTF8(aFilter, filter);
3228 CopyUTF16toUTF8(aTitle, name);
3230 mFilters.AppendElement(filter);
3231 mFilterNames.AppendElement(name);
3232 @@ -419,16 +423,19 @@ confirm_overwrite_file(GtkWidget *parent
3233 gtk_widget_destroy(dialog);
3235 return result;
3238 NS_IMETHODIMP
3239 nsFilePicker::Show(PRInt16 *aReturn)
3241 + if( nsKDEUtils::kdeSupport())
3242 + return kdeFileDialog( aReturn );
3244 NS_ENSURE_ARG_POINTER(aReturn);
3246 nsXPIDLCString title;
3247 title.Adopt(ToNewUTF8String(mTitle));
3249 GtkWindow *parent_widget = get_gtk_window_for_nsiwidget(mParentWidget);
3251 GtkFileChooserAction action = GetGtkFileChooserAction(mMode);
3252 @@ -569,8 +576,234 @@ nsFilePicker::Show(PRInt16 *aReturn)
3253 *aReturn = nsIFilePicker::returnCancel;
3254 break;
3257 gtk_widget_destroy(file_chooser);
3259 return NS_OK;
3262 +nsCString nsFilePicker::kdeMakeFilter( int index )
3264 + nsCString buf = mFilters[ index ];
3265 + for( PRUint32 i = 0;
3266 + i < buf.Length();
3267 + ++i )
3268 + if( buf[ i ] == ';' ) // KDE separates just using spaces
3269 + buf.SetCharAt( ' ', i );
3270 + if (!mFilterNames[index].IsEmpty())
3272 + buf += "|";
3273 + buf += mFilterNames[index].get();
3275 + return buf;
3278 +static PRInt32 windowToXid( nsIWidget* widget )
3280 + GtkWindow *parent_widget = get_gtk_window_for_nsiwidget( widget );
3281 + GdkWindow* gdk_window = gtk_widget_get_window( gtk_widget_get_toplevel( GTK_WIDGET( parent_widget )));
3282 + return GDK_WINDOW_XID( gdk_window );
3285 +NS_IMETHODIMP nsFilePicker::kdeFileDialog(PRInt16 *aReturn)
3287 + NS_ENSURE_ARG_POINTER(aReturn);
3289 + if( mMode == modeOpen && mFilters.Length() == 1 && mFilters[ 0 ].EqualsLiteral( "..apps" ))
3290 + return kdeAppsDialog( aReturn );
3292 + nsXPIDLCString title;
3293 + title.Adopt(ToNewUTF8String(mTitle));
3295 + const char* arg = NULL;
3296 + if( mAllowURLs )
3298 + switch( mMode )
3300 + case nsIFilePicker::modeOpen:
3301 + case nsIFilePicker::modeOpenMultiple:
3302 + arg = "GETOPENURL";
3303 + break;
3304 + case nsIFilePicker::modeSave:
3305 + arg = "GETSAVEURL";
3306 + break;
3307 + case nsIFilePicker::modeGetFolder:
3308 + arg = "GETDIRECTORYURL";
3309 + break;
3312 + else
3314 + switch( mMode )
3316 + case nsIFilePicker::modeOpen:
3317 + case nsIFilePicker::modeOpenMultiple:
3318 + arg = "GETOPENFILENAME";
3319 + break;
3320 + case nsIFilePicker::modeSave:
3321 + arg = "GETSAVEFILENAME";
3322 + break;
3323 + case nsIFilePicker::modeGetFolder:
3324 + arg = "GETDIRECTORYFILENAME";
3325 + break;
3329 + nsCAutoString directory;
3330 + if (mDisplayDirectory) {
3331 + mDisplayDirectory->GetNativePath(directory);
3332 + } else if (mPrevDisplayDirectory) {
3333 + mPrevDisplayDirectory->GetNativePath(directory);
3336 + nsCAutoString startdir;
3337 + if (!directory.IsEmpty()) {
3338 + startdir = directory;
3340 + if (mMode == nsIFilePicker::modeSave) {
3341 + if( !startdir.IsEmpty())
3343 + startdir += "/";
3344 + startdir += ToNewUTF8String(mDefault);
3346 + else
3347 + startdir = ToNewUTF8String(mDefault);
3349 + if( startdir.IsEmpty())
3350 + startdir = ".";
3352 + nsCAutoString filters;
3353 + PRInt32 count = mFilters.Length();
3354 + if( count == 0 ) //just in case
3355 + filters = "*";
3356 + else
3358 + filters = kdeMakeFilter( 0 );
3359 + for (PRInt32 i = 1; i < count; ++i)
3361 + filters += "\n";
3362 + filters += kdeMakeFilter( i );
3366 + nsCStringArray command;
3367 + command.AppendCString( nsCAutoString( arg ));
3368 + command.AppendCString( startdir );
3369 + if( mMode != nsIFilePicker::modeGetFolder )
3371 + command.AppendCString( filters );
3372 + nsCAutoString selected;
3373 + selected.AppendInt( mSelectedType );
3374 + command.AppendCString( selected );
3376 + command.AppendCString( title );
3377 + if( mMode == nsIFilePicker::modeOpenMultiple )
3378 + command.AppendCString( NS_LITERAL_CSTRING( "MULTIPLE" ));
3379 + if( PRInt32 xid = windowToXid( mParentWidget ))
3381 + command.AppendCString( NS_LITERAL_CSTRING( "PARENT" ));
3382 + nsCAutoString parent;
3383 + parent.AppendInt( xid );
3384 + command.AppendCString( parent );
3387 + nsCStringArray output;
3388 + if( nsKDEUtils::commandBlockUi( command, get_gtk_window_for_nsiwidget( mParentWidget ), &output ))
3390 + *aReturn = nsIFilePicker::returnOK;
3391 + mFiles.Clear();
3392 + if( mMode != nsIFilePicker::modeGetFolder )
3394 + mSelectedType = atoi( output[ 0 ]->get());
3395 + output.RemoveCStringAt( 0 );
3397 + if (mMode == nsIFilePicker::modeOpenMultiple)
3399 + mFileURL.Truncate();
3400 + PRUint32 count = output.Count();
3401 + for( PRUint32 i = 0;
3402 + i < count;
3403 + ++i )
3405 + nsCOMPtr<nsILocalFile> localfile;
3406 + nsresult rv = NS_NewNativeLocalFile( *output[ i ],
3407 + PR_FALSE,
3408 + getter_AddRefs(localfile));
3409 + if (NS_SUCCEEDED(rv))
3410 + mFiles.AppendObject(localfile);
3413 + else
3415 + if( output.Count() == 0 )
3416 + mFileURL = nsCString();
3417 + else if( mAllowURLs )
3418 + mFileURL = *output[ 0 ];
3419 + else // GetFile() actually requires it to be url even for local files :-/
3421 + mFileURL = nsCString( "file://" );
3422 + mFileURL.Append( *output[ 0 ] );
3425 + // Remember last used directory.
3426 + nsCOMPtr<nsILocalFile> file;
3427 + GetFile(getter_AddRefs(file));
3428 + if (file) {
3429 + nsCOMPtr<nsIFile> dir;
3430 + file->GetParent(getter_AddRefs(dir));
3431 + nsCOMPtr<nsILocalFile> localDir(do_QueryInterface(dir));
3432 + if (localDir) {
3433 + localDir.swap(mPrevDisplayDirectory);
3436 + if (mMode == nsIFilePicker::modeSave)
3438 + nsCOMPtr<nsILocalFile> file;
3439 + GetFile(getter_AddRefs(file));
3440 + if (file)
3442 + PRBool exists = PR_FALSE;
3443 + file->Exists(&exists);
3444 + if (exists) // TODO do overwrite check in the helper app
3445 + *aReturn = nsIFilePicker::returnReplace;
3449 + else
3451 + *aReturn = nsIFilePicker::returnCancel;
3453 + return NS_OK;
3457 +NS_IMETHODIMP nsFilePicker::kdeAppsDialog(PRInt16 *aReturn)
3459 + NS_ENSURE_ARG_POINTER(aReturn);
3461 + nsXPIDLCString title;
3462 + title.Adopt(ToNewUTF8String(mTitle));
3464 + nsCStringArray command;
3465 + command.AppendCString( NS_LITERAL_CSTRING( "APPSDIALOG" ));
3466 + command.AppendCString( title );
3467 + if( PRInt32 xid = windowToXid( mParentWidget ))
3469 + command.AppendCString( NS_LITERAL_CSTRING( "PARENT" ));
3470 + nsCAutoString parent;
3471 + parent.AppendInt( xid );
3472 + command.AppendCString( parent );
3475 + nsCStringArray output;
3476 + if( nsKDEUtils::commandBlockUi( command, get_gtk_window_for_nsiwidget( mParentWidget ), &output ))
3478 + *aReturn = nsIFilePicker::returnOK;
3479 + mFileURL = output.Count() > 0 ? *output[ 0 ] : nsCString();
3481 + else
3483 + *aReturn = nsIFilePicker::returnCancel;
3485 + return NS_OK;
3487 diff --git a/widget/src/gtk2/nsFilePicker.h b/widget/src/gtk2/nsFilePicker.h
3488 --- a/widget/src/gtk2/nsFilePicker.h
3489 +++ b/widget/src/gtk2/nsFilePicker.h
3490 @@ -89,11 +89,17 @@ protected:
3491 nsString mDefault;
3492 nsString mDefaultExtension;
3494 nsTArray<nsCString> mFilters;
3495 nsTArray<nsCString> mFilterNames;
3497 private:
3498 static nsILocalFile *mPrevDisplayDirectory;
3500 + bool kdeRunning();
3501 + bool getKdeRunning();
3502 + NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn);
3503 + NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn);
3504 + nsCString kdeMakeFilter( int index );
3507 #endif
3508 diff --git a/xpcom/components/Makefile.in b/xpcom/components/Makefile.in
3509 --- a/xpcom/components/Makefile.in
3510 +++ b/xpcom/components/Makefile.in
3511 @@ -94,10 +94,11 @@ FORCE_STATIC_LIB = 1
3513 # Force use of PIC
3514 FORCE_USE_PIC = 1
3515 include $(topsrcdir)/config/rules.mk
3517 DEFINES += -D_IMPL_NS_COM
3519 ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
3520 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
3521 CXXFLAGS += $(MOZ_GTK2_CFLAGS)
3522 endif
3523 diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp
3524 --- a/xpcom/components/ManifestParser.cpp
3525 +++ b/xpcom/components/ManifestParser.cpp
3526 @@ -55,16 +55,17 @@
3527 #include "nsTextFormatter.h"
3528 #include "nsVersionComparator.h"
3529 #include "nsXPCOMCIDInternal.h"
3531 #include "nsIConsoleService.h"
3532 #include "nsIScriptError.h"
3533 #include "nsIXULAppInfo.h"
3534 #include "nsIXULRuntime.h"
3535 +#include "nsKDEUtils.h"
3537 struct ManifestDirective
3539 const char* directive;
3540 int argc;
3542 // Some directives should only be delivered for NS_COMPONENT_LOCATION
3543 // manifests.
3544 @@ -422,16 +423,17 @@
3546 NS_NAMED_LITERAL_STRING(kPlatform, "platform");
3547 NS_NAMED_LITERAL_STRING(kContentAccessible, "contentaccessible");
3548 NS_NAMED_LITERAL_STRING(kApplication, "application");
3549 NS_NAMED_LITERAL_STRING(kAppVersion, "appversion");
3550 NS_NAMED_LITERAL_STRING(kOs, "os");
3551 NS_NAMED_LITERAL_STRING(kOsVersion, "osversion");
3552 NS_NAMED_LITERAL_STRING(kABI, "abi");
3553 + NS_NAMED_LITERAL_STRING(kDesktop, "desktop");
3555 // Obsolete
3556 NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers");
3558 nsAutoString appID;
3559 nsAutoString appVersion;
3560 nsAutoString osTarget;
3561 nsAutoString abi;
3562 @@ -461,35 +463,39 @@
3563 CopyUTF8toUTF16(s, abi);
3564 abi.Insert(PRUnichar('_'), 0);
3565 abi.Insert(osTarget, 0);
3570 nsAutoString osVersion;
3571 + nsAutoString desktop;
3572 #if defined(XP_WIN)
3573 OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
3574 if (GetVersionEx(&info)) {
3575 nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
3576 info.dwMajorVersion,
3577 info.dwMinorVersion);
3579 + desktop = NS_LITERAL_STRING("win");
3580 #elif defined(XP_MACOSX)
3581 SInt32 majorVersion, minorVersion;
3582 if ((Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) &&
3583 (Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) {
3584 nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
3585 majorVersion,
3586 minorVersion);
3588 + desktop = NS_LITERAL_STRING("macosx");
3589 #elif defined(MOZ_WIDGET_GTK2)
3590 nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
3591 gtk_major_version,
3592 gtk_minor_version);
3593 + desktop = nsKDEUtils::kdeSession() ? NS_LITERAL_STRING("kde") : NS_LITERAL_STRING("gnome");
3594 #endif
3596 // Because contracts must be registered after CIDs, we save and process them
3597 // at the end.
3598 nsTArray<CachedDirective> contracts;
3600 char *token;
3601 char *newline = buf;
3602 @@ -558,24 +564,26 @@
3603 bool ok = true;
3604 TriState stAppVersion = eUnspecified;
3605 TriState stApp = eUnspecified;
3606 TriState stOsVersion = eUnspecified;
3607 TriState stOs = eUnspecified;
3608 TriState stABI = eUnspecified;
3609 bool platform = false;
3610 bool contentAccessible = false;
3611 + TriState stDesktop = eUnspecified;
3613 while (NULL != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && ok) {
3614 ToLowerCase(token);
3615 NS_ConvertASCIItoUTF16 wtoken(token);
3617 if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
3618 CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
3619 CheckStringFlag(kABI, wtoken, abi, stABI) ||
3620 + CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) ||
3621 CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) ||
3622 CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion))
3623 continue;
3625 if (directive->contentflags &&
3626 (CheckFlag(kPlatform, wtoken, platform) ||
3627 CheckFlag(kContentAccessible, wtoken, contentAccessible)))
3628 continue;
3629 @@ -593,16 +601,17 @@
3630 token);
3631 ok = false;
3634 if (!ok ||
3635 stApp == eBad ||
3636 stAppVersion == eBad ||
3637 stOs == eBad ||
3638 stOsVersion == eBad ||
3639 + stDesktop == eBad ||
3640 stABI == eBad)
3641 continue;
3643 if (directive->regfunc) {
3644 #ifdef MOZ_IPC
3645 if (GeckoProcessType_Default != XRE_GetProcessType())
3646 continue;
3647 diff --git a/xpcom/io/Makefile.in b/xpcom/io/Makefile.in
3648 --- a/xpcom/io/Makefile.in
3649 +++ b/xpcom/io/Makefile.in
3650 @@ -192,17 +192,17 @@ include $(topsrcdir)/ipc/chromium/chromi
3651 DEFINES += -D_IMPL_NS_COM
3653 ifeq ($(OS_ARCH),Linux)
3654 ifneq (,$(findstring lib64,$(libdir)))
3655 DEFINES += -DHAVE_USR_LIB64_DIR
3656 endif
3657 endif
3659 -LOCAL_INCLUDES += -I..
3660 +LOCAL_INCLUDES += -I.. -I$(topsrcdir)/toolkit/xre
3662 ifeq ($(MOZ_PLATFORM_MAEMO),5)
3663 CFLAGS += $(MOZ_DBUS_CFLAGS)
3664 CXXFLAGS += $(MOZ_DBUS_CFLAGS)
3665 endif
3667 ifdef MOZ_PLATFORM_MAEMO
3668 CFLAGS += $(MOZ_PLATFORM_MAEMO_CFLAGS) $(MOZ_QT_CFLAGS)
3669 diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp
3670 --- a/xpcom/io/nsLocalFileUnix.cpp
3671 +++ b/xpcom/io/nsLocalFileUnix.cpp
3672 @@ -93,16 +93,17 @@
3673 #include "prproces.h"
3674 #include "nsIDirectoryEnumerator.h"
3675 #include "nsISimpleEnumerator.h"
3676 #include "nsITimelineService.h"
3678 #ifdef MOZ_WIDGET_GTK2
3679 #include "nsIGIOService.h"
3680 #include "nsIGnomeVFSService.h"
3681 +#include "nsKDEUtils.h"
3682 #endif
3684 #ifdef XP_MACOSX
3685 #include <Carbon/Carbon.h>
3686 #include "CocoaFileUtils.h"
3687 #include "prmem.h"
3688 #include "plbase64.h"
3690 @@ -1822,44 +1823,50 @@ nsLocalFile::Launch()
3692 return NS_OK;
3694 #else
3695 NS_IMETHODIMP
3696 nsLocalFile::Reveal()
3698 #ifdef MOZ_WIDGET_GTK2
3699 - nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3700 - nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
3701 - if (!giovfs && !gnomevfs)
3702 - return NS_ERROR_FAILURE;
3704 + nsCAutoString url;
3705 PRBool isDirectory;
3706 if (NS_FAILED(IsDirectory(&isDirectory)))
3707 return NS_ERROR_FAILURE;
3709 if (isDirectory) {
3710 - if (giovfs)
3711 - return giovfs->ShowURIForInput(mPath);
3712 - else
3713 - /* Fallback to GnomeVFS */
3714 - return gnomevfs->ShowURIForInput(mPath);
3715 + url = mPath;
3716 } else {
3717 nsCOMPtr<nsIFile> parentDir;
3718 nsCAutoString dirPath;
3719 if (NS_FAILED(GetParent(getter_AddRefs(parentDir))))
3720 return NS_ERROR_FAILURE;
3721 if (NS_FAILED(parentDir->GetNativePath(dirPath)))
3722 return NS_ERROR_FAILURE;
3724 - if (giovfs)
3725 - return giovfs->ShowURIForInput(dirPath);
3726 - else
3727 - return gnomevfs->ShowURIForInput(dirPath);
3728 + url = dirPath;
3731 + if(nsKDEUtils::kdeSupport()) {
3732 + nsCStringArray command;
3733 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
3734 + command.AppendCString( url );
3735 + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
3738 + nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3739 + nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
3740 + if (!giovfs && !gnomevfs)
3741 + return NS_ERROR_FAILURE;
3743 + if (giovfs)
3744 + return giovfs->ShowURIForInput(url);
3745 + else
3746 + return gnomevfs->ShowURIForInput(url);
3747 #elif defined(XP_MACOSX)
3748 CFURLRef url;
3749 if (NS_SUCCEEDED(GetCFURL(&url))) {
3750 nsresult rv = CocoaFileUtils::RevealFileInFinder(url);
3751 ::CFRelease(url);
3752 return rv;
3754 return NS_ERROR_FAILURE;
3755 @@ -1885,16 +1892,23 @@ nsLocalFile::Launch()
3757 if (nsnull == connection)
3758 return NS_ERROR_FAILURE;
3760 if (hildon_mime_open_file(connection, mPath.get()) != kHILDON_SUCCESS)
3761 return NS_ERROR_FAILURE;
3762 return NS_OK;
3763 #else
3764 + if( nsKDEUtils::kdeSupport()) {
3765 + nsCStringArray command;
3766 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
3767 + command.AppendCString( mPath );
3768 + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
3771 nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3772 nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
3773 if (giovfs) {
3774 return giovfs->ShowURIForInput(mPath);
3775 } else if (gnomevfs) {
3776 /* GnomeVFS fallback */
3777 return gnomevfs->ShowURIForInput(mPath);