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