/[packages]/cauldron/firefox/current/SOURCES/mozilla-kde.patch
ViewVC logotype

Contents of /cauldron/firefox/current/SOURCES/mozilla-kde.patch

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.30