mozilla-kde.patch
changeset 1032 8220ea23b47d
parent 1021 1307721d2345
child 1033 51bfdd19b9e9
equal deleted inserted replaced
1031:4b419fce88dc 1032:8220ea23b47d
     1 # HG changeset patch
     1 # HG changeset patch
     2 # Parent  5be2231eadfb6de978e93c0ba95469e8a4d54cb0
     2 # Parent  0a40cd14044b87117b99763e7a155b6deb5ab180
     3 Description: Add KDE integration to Firefox (toolkit parts)
     3 Description: Add KDE integration to Firefox (toolkit parts)
     4 Author: Wolfgang Rosenauer <wolfgang@rosenauer.org>
     4 Author: Wolfgang Rosenauer <wolfgang@rosenauer.org>
     5 Author: Lubos Lunak <lunak@suse.com>
     5 Author: Lubos Lunak <lunak@suse.com>
     6 Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=140751
     6 Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=140751
     7      https://bugzilla.novell.com/show_bug.cgi?id=170055
     7      https://bugzilla.novell.com/show_bug.cgi?id=170055
     8 
     8 
     9 diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp
     9 diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp
    10 --- a/modules/libpref/Preferences.cpp
    10 --- a/modules/libpref/Preferences.cpp
    11 +++ b/modules/libpref/Preferences.cpp
    11 +++ b/modules/libpref/Preferences.cpp
    12 @@ -75,16 +75,17 @@
    12 @@ -76,16 +76,17 @@
    13  #include "nsXPCOMCID.h"
    13  #include "nsXPCOMCID.h"
    14  #include "nsXPCOM.h"
    14  #include "nsXPCOM.h"
    15  #include "nsXULAppAPI.h"
    15  #include "nsXULAppAPI.h"
    16  #include "nsZipArchive.h"
    16  #include "nsZipArchive.h"
    17  #include "plbase64.h"
    17  #include "plbase64.h"
    18  #include "PLDHashTable.h"
    18  #include "PLDHashTable.h"
    19  #include "plstr.h"
    19  #include "plstr.h"
    20  #include "prlink.h"
    20  #include "prlink.h"
    21 +#include "nsKDEUtils.h"
    21 +#include "nsKDEUtils.h"
    22  
    22  
    23  #ifdef MOZ_CRASHREPORTER
       
    24  #include "nsICrashReporter.h"
       
    25  #endif
       
    26  
       
    27  #ifdef XP_WIN
    23  #ifdef XP_WIN
    28  #include "windows.h"
    24  #include "windows.h"
    29  #endif
    25  #endif
    30 @@ -4324,16 +4325,34 @@ pref_LoadPrefsInDirList(const char* aLis
    26  
    31  {
    27  using namespace mozilla;
    32    nsresult rv;
    28  
    33    nsCOMPtr<nsIProperties> dirSvc(
    29  #ifdef DEBUG
    34      do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
    30 @@ -4235,25 +4236,37 @@ Preferences::InitInitialObjects()
    35    if (NS_FAILED(rv)) {
       
    36      return rv;
       
    37    }
       
    38  
       
    39 +  // make sure we load these special files after all the others
       
    40 +  static const char* specialFiles[] = {
       
    41 +#if defined(XP_UNIX)
       
    42 +    ""
       
    43 +#endif
       
    44 +  };
       
    45 +
       
    46 +  if (nsKDEUtils::kdeSession()) {
       
    47 +    for(int i = 0;
       
    48 +        i < MOZ_ARRAY_LENGTH(specialFiles);
       
    49 +        ++i ) {
       
    50 +      if (*specialFiles[ i ] == '\0') {
       
    51 +        specialFiles[ i ] = "kde.js";
       
    52 +        break;
       
    53 +      }
       
    54 +    }
       
    55 +  }
       
    56 +
       
    57    nsCOMPtr<nsISimpleEnumerator> list;
       
    58    dirSvc->Get(aListId, NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(list));
       
    59    if (!list) {
       
    60      return NS_OK;
       
    61    }
       
    62  
       
    63    bool hasMore;
       
    64    while (NS_SUCCEEDED(list->HasMoreElements(&hasMore)) && hasMore) {
       
    65 @@ -4344,17 +4363,17 @@ pref_LoadPrefsInDirList(const char* aLis
       
    66      }
       
    67  
       
    68      nsCOMPtr<nsIFile> path = do_QueryInterface(elem);
       
    69      if (!path) {
       
    70        continue;
       
    71      }
       
    72  
       
    73      // Do we care if a file provided by this process fails to load?
       
    74 -    pref_LoadPrefsInDir(path, nullptr, 0);
       
    75 +    pref_LoadPrefsInDir(path, specialFiles, ArrayLength(specialFiles));
       
    76    }
       
    77  
       
    78    return NS_OK;
       
    79  }
       
    80  
       
    81  static nsresult
       
    82  pref_ReadPrefFromJar(nsZipArchive* aJarReader, const char* aName)
       
    83  {
       
    84 @@ -4461,25 +4480,37 @@ pref_InitInitialObjects()
       
    85    // application pref files for backwards compatibility.
    31    // application pref files for backwards compatibility.
    86    static const char* specialFiles[] = {
    32    static const char* specialFiles[] = {
    87  #if defined(XP_MACOSX)
    33  #if defined(XP_MACOSX)
    88      "macprefs.js"
    34      "macprefs.js"
    89  #elif defined(XP_WIN)
    35  #elif defined(XP_WIN)
   117      NS_WARNING("Error parsing application default preferences.");
    63      NS_WARNING("Error parsing application default preferences.");
   118    }
    64    }
   119  
    65  
   120    // Load jar:$app/omni.jar!/defaults/preferences/*.js
    66    // Load jar:$app/omni.jar!/defaults/preferences/*.js
   121    // or jar:$gre/omni.jar!/defaults/preferences/*.js.
    67    // or jar:$gre/omni.jar!/defaults/preferences/*.js.
       
    68 @@ -4302,17 +4315,17 @@ Preferences::InitInitialObjects()
       
    69        }
       
    70  
       
    71        nsCOMPtr<nsIFile> path = do_QueryInterface(elem);
       
    72        if (!path) {
       
    73          continue;
       
    74        }
       
    75  
       
    76        // Do we care if a file provided by this process fails to load?
       
    77 -      pref_LoadPrefsInDir(path, nullptr, 0);
       
    78 +      pref_LoadPrefsInDir(path, specialFiles, ArrayLength(specialFiles));
       
    79      }
       
    80    }
       
    81  
       
    82  #ifdef MOZ_WIDGET_ANDROID
       
    83    // Set up the correct default for toolkit.telemetry.enabled. If this build
       
    84    // has MOZ_TELEMETRY_ON_BY_DEFAULT *or* we're on the beta channel, telemetry
       
    85    // is on by default, otherwise not. This is necessary so that beta users who
       
    86    // are testing final release builds don't flipflop defaults.
   122 diff --git a/modules/libpref/moz.build b/modules/libpref/moz.build
    87 diff --git a/modules/libpref/moz.build b/modules/libpref/moz.build
   123 --- a/modules/libpref/moz.build
    88 --- a/modules/libpref/moz.build
   124 +++ b/modules/libpref/moz.build
    89 +++ b/modules/libpref/moz.build
   125 @@ -27,16 +27,20 @@ XPIDL_MODULE = 'pref'
    90 @@ -27,16 +27,20 @@ XPIDL_MODULE = 'pref'
   126  EXPORTS.mozilla += [
    91  EXPORTS.mozilla += [
   203 +
   168 +
   204  CXXFLAGS += CONFIG['TK_CFLAGS']
   169  CXXFLAGS += CONFIG['TK_CFLAGS']
   205 diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn
   170 diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn
   206 --- a/toolkit/content/jar.mn
   171 --- a/toolkit/content/jar.mn
   207 +++ b/toolkit/content/jar.mn
   172 +++ b/toolkit/content/jar.mn
   208 @@ -75,29 +75,33 @@ toolkit.jar:
   173 @@ -67,16 +67,18 @@ toolkit.jar:
       
   174     content/global/bindings/checkbox.xml        (widgets/checkbox.xml)
   209     content/global/bindings/colorpicker.xml     (widgets/colorpicker.xml)
   175     content/global/bindings/colorpicker.xml     (widgets/colorpicker.xml)
   210     content/global/bindings/datekeeper.js       (widgets/datekeeper.js)
   176     content/global/bindings/datekeeper.js       (widgets/datekeeper.js)
   211     content/global/bindings/datepicker.js       (widgets/datepicker.js)
   177     content/global/bindings/datepicker.js       (widgets/datepicker.js)
   212     content/global/bindings/datetimepicker.xml  (widgets/datetimepicker.xml)
       
   213     content/global/bindings/datetimepopup.xml   (widgets/datetimepopup.xml)
   178     content/global/bindings/datetimepopup.xml   (widgets/datetimepopup.xml)
   214     content/global/bindings/datetimebox.xml     (widgets/datetimebox.xml)
   179     content/global/bindings/datetimebox.xml     (widgets/datetimebox.xml)
   215     content/global/bindings/datetimebox.css     (widgets/datetimebox.css)
   180     content/global/bindings/datetimebox.css     (widgets/datetimebox.css)
   216  *  content/global/bindings/dialog.xml          (widgets/dialog.xml)
   181  *  content/global/bindings/dialog.xml          (widgets/dialog.xml)
   217 +*  content/global/bindings/dialog-kde.xml      (widgets/dialog-kde.xml)
   182 +*  content/global/bindings/dialog-kde.xml      (widgets/dialog-kde.xml)
   218 +% override chrome://global/content/bindings/dialog.xml chrome://global/content/bindings/dialog-kde.xml desktop=kde
   183 +% override chrome://global/content/bindings/dialog.xml chrome://global/content/bindings/dialog-kde.xml desktop=kde
   219     content/global/bindings/editor.xml          (widgets/editor.xml)
   184     content/global/bindings/editor.xml          (widgets/editor.xml)
   220     content/global/bindings/expander.xml        (widgets/expander.xml)
       
   221     content/global/bindings/filefield.xml       (widgets/filefield.xml)
   185     content/global/bindings/filefield.xml       (widgets/filefield.xml)
   222  *  content/global/bindings/findbar.xml         (widgets/findbar.xml)
   186  *  content/global/bindings/findbar.xml         (widgets/findbar.xml)
   223     content/global/bindings/general.xml         (widgets/general.xml)
   187     content/global/bindings/general.xml         (widgets/general.xml)
   224     content/global/bindings/groupbox.xml        (widgets/groupbox.xml)
   188     content/global/bindings/groupbox.xml        (widgets/groupbox.xml)
   225     content/global/bindings/listbox.xml         (widgets/listbox.xml)
   189     content/global/bindings/listbox.xml         (widgets/listbox.xml)
   226     content/global/bindings/menu.xml            (widgets/menu.xml)
   190     content/global/bindings/menu.xml            (widgets/menu.xml)
   227     content/global/bindings/menulist.xml        (widgets/menulist.xml)
   191     content/global/bindings/menulist.xml        (widgets/menulist.xml)
   228     content/global/bindings/notification.xml    (widgets/notification.xml)
       
   229     content/global/bindings/numberbox.xml       (widgets/numberbox.xml)
       
   230     content/global/bindings/popup.xml           (widgets/popup.xml)
       
   231  *  content/global/bindings/preferences.xml     (widgets/preferences.xml)
       
   232 +*  content/global/bindings/preferences-kde.xml (widgets/preferences-kde.xml)
       
   233 +% override chrome://global/content/bindings/preferences.xml chrome://global/content/bindings/preferences-kde.xml desktop=kde
       
   234     content/global/bindings/progressmeter.xml   (widgets/progressmeter.xml)
       
   235     content/global/bindings/radio.xml           (widgets/radio.xml)
       
   236     content/global/bindings/remote-browser.xml  (widgets/remote-browser.xml)
       
   237     content/global/bindings/resizer.xml         (widgets/resizer.xml)
       
   238     content/global/bindings/richlistbox.xml     (widgets/richlistbox.xml)
       
   239     content/global/bindings/scale.xml           (widgets/scale.xml)
       
   240     content/global/bindings/scrollbar.xml       (widgets/scrollbar.xml)
       
   241     content/global/bindings/scrollbox.xml       (widgets/scrollbox.xml)
       
   242 diff --git a/toolkit/content/widgets/dialog-kde.xml b/toolkit/content/widgets/dialog-kde.xml
   192 diff --git a/toolkit/content/widgets/dialog-kde.xml b/toolkit/content/widgets/dialog-kde.xml
   243 new file mode 100644
   193 new file mode 100644
   244 --- /dev/null
   194 --- /dev/null
   245 +++ b/toolkit/content/widgets/dialog-kde.xml
   195 +++ b/toolkit/content/widgets/dialog-kde.xml
   246 @@ -0,0 +1,459 @@
   196 @@ -0,0 +1,477 @@
   247 +<?xml version="1.0"?>
   197 +<?xml version="1.0"?>
   248 +<!-- This Source Code Form is subject to the terms of the Mozilla Public
   198 +<!-- This Source Code Form is subject to the terms of the Mozilla Public
   249 +   - License, v. 2.0. If a copy of the MPL was not distributed with this
   199 +   - License, v. 2.0. If a copy of the MPL was not distributed with this
   250 +   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
   200 +   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
   251 +
   201 +
       
   202 +<!DOCTYPE bindings [
       
   203 +  <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
       
   204 +  %globalKeysDTD;
       
   205 +]>
   252 +
   206 +
   253 +<bindings id="dialogBindings"
   207 +<bindings id="dialogBindings"
   254 +          xmlns="http://www.mozilla.org/xbl"
   208 +          xmlns="http://www.mozilla.org/xbl"
   255 +          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   209 +          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   256 +          xmlns:xbl="http://www.mozilla.org/xbl">
   210 +          xmlns:xbl="http://www.mozilla.org/xbl">
   293 +        <xul:button dlgtype="cancel" class="dialog-button"/>
   247 +        <xul:button dlgtype="cancel" class="dialog-button"/>
   294 +        <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
   248 +        <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
   295 +        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
   249 +        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
   296 +#endif
   250 +#endif
   297 +      </xul:hbox>
   251 +      </xul:hbox>
       
   252 +
       
   253 +    <xul:keyset>
       
   254 +      <xul:key phase="capturing" oncommand="document.documentElement.openHelp(event)"
       
   255 +#ifdef XP_MACOSX
       
   256 +           key="&openHelpMac.commandkey;" modifiers="accel"/>
       
   257 +#else
       
   258 +           keycode="&openHelp.commandkey;"/>
       
   259 +#endif
       
   260 +    </xul:keyset>
       
   261 +
   298 +    </content>
   262 +    </content>
   299 +
   263 +
   300 +    <implementation>
   264 +    <implementation>
   301 +      <field name="_mStrBundle">null</field>
   265 +      <field name="_mStrBundle">null</field>
   302 +      <field name="_closeHandler">(function(event) {
   266 +      <field name="_closeHandler">(function(event) {
   311 +      <property name="defaultButton">
   275 +      <property name="defaultButton">
   312 +        <getter>
   276 +        <getter>
   313 +        <![CDATA[
   277 +        <![CDATA[
   314 +          if (this.hasAttribute("defaultButton"))
   278 +          if (this.hasAttribute("defaultButton"))
   315 +            return this.getAttribute("defaultButton");
   279 +            return this.getAttribute("defaultButton");
   316 +          return "accept";  // default to the accept button
   280 +          return "accept"; // default to the accept button
   317 +        ]]>
   281 +        ]]>
   318 +        </getter>
   282 +        </getter>
   319 +        <setter>
   283 +        <setter>
   320 +        <![CDATA[
   284 +        <![CDATA[
   321 +          this._setDefaultButton(val);
   285 +          this._setDefaultButton(val);
   458 +            } catch (e) { }
   422 +            } catch (e) { }
   459 +          }
   423 +          }
   460 +
   424 +
   461 +          // Give focus after onload completes, see bug 103197.
   425 +          // Give focus after onload completes, see bug 103197.
   462 +          setTimeout(focusInit, 0);
   426 +          setTimeout(focusInit, 0);
       
   427 +        ]]>
       
   428 +        </body>
       
   429 +      </method>
       
   430 +
       
   431 +      <method name="openHelp">
       
   432 +        <parameter name="event"/>
       
   433 +        <body>
       
   434 +        <![CDATA[
       
   435 +          var helpButton = document.documentElement.getButton("help");
       
   436 +          if (helpButton.disabled || helpButton.hidden)
       
   437 +            return;
       
   438 +          this._fireButtonEvent("help");
       
   439 +          event.stopPropagation();
       
   440 +          event.preventDefault();
   463 +        ]]>
   441 +        ]]>
   464 +        </body>
   442 +        </body>
   465 +      </method>
   443 +      </method>
   466 +
   444 +
   467 +      <property name="mStrBundle">
   445 +      <property name="mStrBundle">
   690 +#endif
   668 +#endif
   691 +    </handlers>
   669 +    </handlers>
   692 +
   670 +
   693 +  </binding>
   671 +  </binding>
   694 +
   672 +
   695 +  <binding id="dialogheader">
       
   696 +    <resources>
       
   697 +      <stylesheet src="chrome://global/skin/dialog.css"/>
       
   698 +    </resources>
       
   699 +    <content>
       
   700 +      <xul:label class="dialogheader-title" xbl:inherits="value=title,crop" crop="right" flex="1"/>
       
   701 +      <xul:label class="dialogheader-description" xbl:inherits="value=description"/>
       
   702 +    </content>
       
   703 +  </binding>
       
   704 +
       
   705 +</bindings>
   673 +</bindings>
   706 diff --git a/toolkit/content/widgets/preferences-kde.xml b/toolkit/content/widgets/preferences-kde.xml
       
   707 new file mode 100644
       
   708 --- /dev/null
       
   709 +++ b/toolkit/content/widgets/preferences-kde.xml
       
   710 @@ -0,0 +1,1409 @@
       
   711 +<?xml version="1.0"?>
       
   712 +
       
   713 +<!DOCTYPE bindings [
       
   714 +  <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
       
   715 +  %preferencesDTD;
       
   716 +  <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
       
   717 +  %globalKeysDTD;
       
   718 +]>
       
   719 +
       
   720 +<bindings id="preferencesBindings"
       
   721 +          xmlns="http://www.mozilla.org/xbl"
       
   722 +          xmlns:xbl="http://www.mozilla.org/xbl"
       
   723 +          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
       
   724 +
       
   725 +#
       
   726 +# = Preferences Window Framework
       
   727 +#
       
   728 +#   The syntax for use looks something like:
       
   729 +#
       
   730 +#   <prefwindow>
       
   731 +#     <prefpane id="prefPaneA">
       
   732 +#       <preferences>
       
   733 +#         <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/>
       
   734 +#         <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/>
       
   735 +#       </preferences>
       
   736 +#       <checkbox label="Preference" preference="preference1"/>
       
   737 +#     </prefpane>
       
   738 +#   </prefwindow>
       
   739 +#
       
   740 +
       
   741 +  <binding id="preferences">
       
   742 +    <implementation implements="nsIObserver">
       
   743 +      <method name="_constructAfterChildren">
       
   744 +      <body>
       
   745 +      <![CDATA[
       
   746 +      // This method will be called after the last of the child
       
   747 +      // <preference> elements is constructed. Its purpose is to propagate
       
   748 +      // the values to the associated form elements. Sometimes the code for
       
   749 +      // some <preference> initializers depend on other <preference> elements
       
   750 +      // being initialized so we wait and call updateElements on all of them
       
   751 +      // once the last one has been constructed. See bugs 997570 and 992185.
       
   752 +
       
   753 +      var elements = this.getElementsByTagName("preference");
       
   754 +      for (let element of elements) {
       
   755 +        element.updateElements();
       
   756 +      }
       
   757 +
       
   758 +      this._constructAfterChildrenCalled = true;
       
   759 +      ]]>
       
   760 +      </body>
       
   761 +      </method>
       
   762 +      <method name="observe">
       
   763 +        <parameter name="aSubject"/>
       
   764 +        <parameter name="aTopic"/>
       
   765 +        <parameter name="aData"/>
       
   766 +        <body>
       
   767 +        <![CDATA[
       
   768 +          for (var i = 0; i < this.childNodes.length; ++i) {
       
   769 +            var preference = this.childNodes[i];
       
   770 +            if (preference.name == aData) {
       
   771 +              preference.value = preference.valueFromPreferences;
       
   772 +            }
       
   773 +          }
       
   774 +        ]]>
       
   775 +        </body>
       
   776 +      </method>
       
   777 +
       
   778 +      <method name="fireChangedEvent">
       
   779 +        <parameter name="aPreference"/>
       
   780 +        <body>
       
   781 +        <![CDATA[
       
   782 +          // Value changed, synthesize an event
       
   783 +          try {
       
   784 +            var event = document.createEvent("Events");
       
   785 +            event.initEvent("change", true, true);
       
   786 +            aPreference.dispatchEvent(event);
       
   787 +          } catch (e) {
       
   788 +            Components.utils.reportError(e);
       
   789 +          }
       
   790 +        ]]>
       
   791 +        </body>
       
   792 +      </method>
       
   793 +
       
   794 +      <field name="service">
       
   795 +        Components.classes["@mozilla.org/preferences-service;1"]
       
   796 +                  .getService(Components.interfaces.nsIPrefService);
       
   797 +      </field>
       
   798 +      <field name="rootBranch">
       
   799 +        Components.classes["@mozilla.org/preferences-service;1"]
       
   800 +                  .getService(Components.interfaces.nsIPrefBranch);
       
   801 +      </field>
       
   802 +      <field name="defaultBranch">
       
   803 +        this.service.getDefaultBranch("");
       
   804 +      </field>
       
   805 +      <field name="rootBranchInternal">
       
   806 +        Components.classes["@mozilla.org/preferences-service;1"]
       
   807 +                  .getService(Components.interfaces.nsIPrefBranch);
       
   808 +      </field>
       
   809 +      <property name="type" readonly="true">
       
   810 +        <getter>
       
   811 +          <![CDATA[
       
   812 +            return document.documentElement.type || "";
       
   813 +          ]]>
       
   814 +        </getter>
       
   815 +      </property>
       
   816 +      <property name="instantApply" readonly="true">
       
   817 +        <getter>
       
   818 +          <![CDATA[
       
   819 +            var doc = document.documentElement;
       
   820 +            return this.type == "child" ? doc.instantApply
       
   821 +                                        : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply");
       
   822 +          ]]>
       
   823 +        </getter>
       
   824 +      </property>
       
   825 +
       
   826 +      <!-- We want to call _constructAfterChildren after all child
       
   827 +           <preference> elements have been constructed. To do this, we get
       
   828 +           and store the node list of all child <preference> elements in the
       
   829 +           constructor, and maintain a count which is incremented in the
       
   830 +           constructor of <preference>. _constructAfterChildren is called
       
   831 +           when the count matches the length of the list. -->
       
   832 +      <field name="_constructedChildrenCount">0</field>
       
   833 +      <field name="_preferenceChildren">null</field>
       
   834 +      <!-- Some <preference> elements are added dynamically after
       
   835 +           _constructAfterChildren has already been called - we want to
       
   836 +           avoid looping over all of them again in this case so we remember
       
   837 +           if we already called it. -->
       
   838 +      <field name="_constructAfterChildrenCalled">false</field>
       
   839 +      <constructor>
       
   840 +      <![CDATA[
       
   841 +        this._preferenceChildren = this.getElementsByTagName("preference");
       
   842 +      ]]>
       
   843 +      </constructor>
       
   844 +    </implementation>
       
   845 +  </binding>
       
   846 +
       
   847 +  <binding id="preference">
       
   848 +    <implementation>
       
   849 +      <constructor>
       
   850 +      <![CDATA[
       
   851 +        // if the element has been inserted without the name attribute set,
       
   852 +        // we have nothing to do here
       
   853 +        if (!this.name)
       
   854 +          return;
       
   855 +
       
   856 +        this.preferences.rootBranchInternal
       
   857 +            .addObserver(this.name, this.preferences);
       
   858 +        // In non-instant apply mode, we must try and use the last saved state
       
   859 +        // from any previous opens of a child dialog instead of the value from
       
   860 +        // preferences, to pick up any edits a user may have made.
       
   861 +
       
   862 +        var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
       
   863 +                    .getService(Components.interfaces.nsIScriptSecurityManager);
       
   864 +        if (this.preferences.type == "child" &&
       
   865 +            !this.instantApply && window.opener &&
       
   866 +            secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) {
       
   867 +          var pdoc = window.opener.document;
       
   868 +
       
   869 +          // Try to find a preference element for the same preference.
       
   870 +          var preference = null;
       
   871 +          var parentPreferences = pdoc.getElementsByTagName("preferences");
       
   872 +          for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
       
   873 +            var parentPrefs = parentPreferences[k]
       
   874 +                                    .getElementsByAttribute("name", this.name);
       
   875 +            for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
       
   876 +              if (parentPrefs[l].localName == "preference")
       
   877 +                preference = parentPrefs[l];
       
   878 +            }
       
   879 +          }
       
   880 +
       
   881 +          // Don't use the value setter here, we don't want updateElements to be prematurely fired.
       
   882 +          this._value = preference ? preference.value : this.valueFromPreferences;
       
   883 +        } else {
       
   884 +          this._value = this.valueFromPreferences;
       
   885 +        }
       
   886 +        if (this.preferences._constructAfterChildrenCalled) {
       
   887 +          // This <preference> was added after _constructAfterChildren() was already called.
       
   888 +          // We can directly call updateElements().
       
   889 +          this.updateElements();
       
   890 +          return;
       
   891 +        }
       
   892 +        this.preferences._constructedChildrenCount++;
       
   893 +        if (this.preferences._constructedChildrenCount ==
       
   894 +            this.preferences._preferenceChildren.length) {
       
   895 +          // This is the last <preference>, time to updateElements() on all of them.
       
   896 +          this.preferences._constructAfterChildren();
       
   897 +        }
       
   898 +      ]]>
       
   899 +      </constructor>
       
   900 +      <destructor>
       
   901 +        this.preferences.rootBranchInternal
       
   902 +            .removeObserver(this.name, this.preferences);
       
   903 +      </destructor>
       
   904 +      <field name="_constructed">false</field>
       
   905 +      <property name="instantApply">
       
   906 +        <getter>
       
   907 +          if (this.getAttribute("instantApply") == "false")
       
   908 +            return false;
       
   909 +          return this.getAttribute("instantApply") == "true" || this.preferences.instantApply;
       
   910 +        </getter>
       
   911 +      </property>
       
   912 +
       
   913 +      <property name="preferences" onget="return this.parentNode"/>
       
   914 +      <property name="name" onget="return this.getAttribute('name');">
       
   915 +        <setter>
       
   916 +          if (val == this.name)
       
   917 +            return val;
       
   918 +
       
   919 +          this.preferences.rootBranchInternal
       
   920 +              .removeObserver(this.name, this.preferences);
       
   921 +          this.setAttribute("name", val);
       
   922 +          this.preferences.rootBranchInternal
       
   923 +              .addObserver(val, this.preferences);
       
   924 +
       
   925 +          return val;
       
   926 +        </setter>
       
   927 +      </property>
       
   928 +      <property name="type" onget="return this.getAttribute('type');"
       
   929 +                            onset="this.setAttribute('type', val); return val;"/>
       
   930 +      <property name="inverted" onget="return this.getAttribute('inverted') == 'true';"
       
   931 +                                onset="this.setAttribute('inverted', val); return val;"/>
       
   932 +      <property name="readonly" onget="return this.getAttribute('readonly') == 'true';"
       
   933 +                                onset="this.setAttribute('readonly', val); return val;"/>
       
   934 +
       
   935 +      <field name="_value">null</field>
       
   936 +      <method name="_setValue">
       
   937 +        <parameter name="aValue"/>
       
   938 +        <body>
       
   939 +        <![CDATA[
       
   940 +          if (this.value !== aValue) {
       
   941 +            this._value = aValue;
       
   942 +            if (this.instantApply)
       
   943 +              this.valueFromPreferences = aValue;
       
   944 +            this.preferences.fireChangedEvent(this);
       
   945 +          }
       
   946 +          return aValue;
       
   947 +        ]]>
       
   948 +        </body>
       
   949 +      </method>
       
   950 +      <property name="value" onget="return this._value" onset="return this._setValue(val);"/>
       
   951 +
       
   952 +      <property name="locked">
       
   953 +        <getter>
       
   954 +          return this.preferences.rootBranch.prefIsLocked(this.name);
       
   955 +        </getter>
       
   956 +      </property>
       
   957 +
       
   958 +      <property name="disabled">
       
   959 +        <getter>
       
   960 +          return this.getAttribute("disabled") == "true";
       
   961 +        </getter>
       
   962 +        <setter>
       
   963 +        <![CDATA[
       
   964 +          if (val)
       
   965 +            this.setAttribute("disabled", "true");
       
   966 +          else
       
   967 +            this.removeAttribute("disabled");
       
   968 +
       
   969 +          if (!this.id)
       
   970 +            return val;
       
   971 +
       
   972 +          var elements = document.getElementsByAttribute("preference", this.id);
       
   973 +          for (var i = 0; i < elements.length; ++i) {
       
   974 +            elements[i].disabled = val;
       
   975 +
       
   976 +            var labels = document.getElementsByAttribute("control", elements[i].id);
       
   977 +            for (var j = 0; j < labels.length; ++j)
       
   978 +              labels[j].disabled = val;
       
   979 +          }
       
   980 +
       
   981 +          return val;
       
   982 +        ]]>
       
   983 +        </setter>
       
   984 +      </property>
       
   985 +
       
   986 +      <property name="tabIndex">
       
   987 +        <getter>
       
   988 +          return parseInt(this.getAttribute("tabindex"));
       
   989 +        </getter>
       
   990 +        <setter>
       
   991 +        <![CDATA[
       
   992 +          if (val)
       
   993 +            this.setAttribute("tabindex", val);
       
   994 +          else
       
   995 +            this.removeAttribute("tabindex");
       
   996 +
       
   997 +          if (!this.id)
       
   998 +            return val;
       
   999 +
       
  1000 +          var elements = document.getElementsByAttribute("preference", this.id);
       
  1001 +          for (var i = 0; i < elements.length; ++i) {
       
  1002 +            elements[i].tabIndex = val;
       
  1003 +
       
  1004 +            var labels = document.getElementsByAttribute("control", elements[i].id);
       
  1005 +            for (var j = 0; j < labels.length; ++j)
       
  1006 +              labels[j].tabIndex = val;
       
  1007 +          }
       
  1008 +
       
  1009 +          return val;
       
  1010 +        ]]>
       
  1011 +        </setter>
       
  1012 +      </property>
       
  1013 +
       
  1014 +      <property name="hasUserValue">
       
  1015 +        <getter>
       
  1016 +        <![CDATA[
       
  1017 +          return this.preferences.rootBranch.prefHasUserValue(this.name) &&
       
  1018 +                 this.value !== undefined;
       
  1019 +        ]]>
       
  1020 +        </getter>
       
  1021 +      </property>
       
  1022 +
       
  1023 +      <method name="reset">
       
  1024 +        <body>
       
  1025 +          // defer reset until preference update
       
  1026 +          this.value = undefined;
       
  1027 +        </body>
       
  1028 +      </method>
       
  1029 +
       
  1030 +      <field name="_useDefault">false</field>
       
  1031 +      <property name="defaultValue">
       
  1032 +        <getter>
       
  1033 +        <![CDATA[
       
  1034 +          this._useDefault = true;
       
  1035 +          var val = this.valueFromPreferences;
       
  1036 +          this._useDefault = false;
       
  1037 +          return val;
       
  1038 +        ]]>
       
  1039 +        </getter>
       
  1040 +      </property>
       
  1041 +
       
  1042 +      <property name="_branch">
       
  1043 +        <getter>
       
  1044 +          return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch;
       
  1045 +        </getter>
       
  1046 +      </property>
       
  1047 +
       
  1048 +      <field name="batching">false</field>
       
  1049 +
       
  1050 +      <method name="_reportUnknownType">
       
  1051 +        <body>
       
  1052 +        <![CDATA[
       
  1053 +          var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
       
  1054 +                                         .getService(Components.interfaces.nsIConsoleService);
       
  1055 +          var msg = "<preference> with id='" + this.id + "' and name='" +
       
  1056 +                    this.name + "' has unknown type '" + this.type + "'.";
       
  1057 +          consoleService.logStringMessage(msg);
       
  1058 +        ]]>
       
  1059 +        </body>
       
  1060 +      </method>
       
  1061 +
       
  1062 +      <property name="valueFromPreferences">
       
  1063 +        <getter>
       
  1064 +        <![CDATA[
       
  1065 +          try {
       
  1066 +            // Force a resync of value with preferences.
       
  1067 +            switch (this.type) {
       
  1068 +            case "int":
       
  1069 +              return this._branch.getIntPref(this.name);
       
  1070 +            case "bool":
       
  1071 +              var val = this._branch.getBoolPref(this.name);
       
  1072 +              return this.inverted ? !val : val;
       
  1073 +            case "wstring":
       
  1074 +              return this._branch
       
  1075 +                         .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString)
       
  1076 +                         .data;
       
  1077 +            case "string":
       
  1078 +            case "unichar":
       
  1079 +              return this._branch.getStringPref(this.name);
       
  1080 +            case "fontname":
       
  1081 +              var family = this._branch.getStringPref(this.name);
       
  1082 +              var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
       
  1083 +                                             .createInstance(Components.interfaces.nsIFontEnumerator);
       
  1084 +              return fontEnumerator.getStandardFamilyName(family);
       
  1085 +            case "file":
       
  1086 +              var f = this._branch
       
  1087 +                          .getComplexValue(this.name, Components.interfaces.nsIFile);
       
  1088 +              return f;
       
  1089 +            default:
       
  1090 +              this._reportUnknownType();
       
  1091 +            }
       
  1092 +          } catch (e) { }
       
  1093 +          return null;
       
  1094 +        ]]>
       
  1095 +        </getter>
       
  1096 +        <setter>
       
  1097 +        <![CDATA[
       
  1098 +          // Exit early if nothing to do.
       
  1099 +          if (this.readonly || this.valueFromPreferences == val)
       
  1100 +            return val;
       
  1101 +
       
  1102 +          // The special value undefined means 'reset preference to default'.
       
  1103 +          if (val === undefined) {
       
  1104 +            this.preferences.rootBranch.clearUserPref(this.name);
       
  1105 +            return val;
       
  1106 +          }
       
  1107 +
       
  1108 +          // Force a resync of preferences with value.
       
  1109 +          switch (this.type) {
       
  1110 +          case "int":
       
  1111 +            this.preferences.rootBranch.setIntPref(this.name, val);
       
  1112 +            break;
       
  1113 +          case "bool":
       
  1114 +            this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val);
       
  1115 +            break;
       
  1116 +          case "wstring":
       
  1117 +            var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
       
  1118 +                                .createInstance(Components.interfaces.nsIPrefLocalizedString);
       
  1119 +            pls.data = val;
       
  1120 +            this.preferences.rootBranch
       
  1121 +                .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls);
       
  1122 +            break;
       
  1123 +          case "string":
       
  1124 +          case "unichar":
       
  1125 +          case "fontname":
       
  1126 +            this.preferences.rootBranch.setStringPref(this.name, val);
       
  1127 +            break;
       
  1128 +          case "file":
       
  1129 +            var lf;
       
  1130 +            if (typeof(val) == "string") {
       
  1131 +              lf = Components.classes["@mozilla.org/file/local;1"]
       
  1132 +                             .createInstance(Components.interfaces.nsIFile);
       
  1133 +              lf.persistentDescriptor = val;
       
  1134 +              if (!lf.exists())
       
  1135 +                lf.initWithPath(val);
       
  1136 +            } else
       
  1137 +              lf = val.QueryInterface(Components.interfaces.nsIFile);
       
  1138 +            this.preferences.rootBranch
       
  1139 +                .setComplexValue(this.name, Components.interfaces.nsIFile, lf);
       
  1140 +            break;
       
  1141 +          default:
       
  1142 +            this._reportUnknownType();
       
  1143 +          }
       
  1144 +          if (!this.batching)
       
  1145 +            this.preferences.service.savePrefFile(null);
       
  1146 +          return val;
       
  1147 +        ]]>
       
  1148 +        </setter>
       
  1149 +      </property>
       
  1150 +
       
  1151 +      <method name="setElementValue">
       
  1152 +        <parameter name="aElement"/>
       
  1153 +        <body>
       
  1154 +        <![CDATA[
       
  1155 +          if (this.locked)
       
  1156 +            aElement.disabled = true;
       
  1157 +
       
  1158 +          if (!this.isElementEditable(aElement))
       
  1159 +            return;
       
  1160 +
       
  1161 +          var rv = undefined;
       
  1162 +          if (aElement.hasAttribute("onsyncfrompreference")) {
       
  1163 +            // Value changed, synthesize an event
       
  1164 +            try {
       
  1165 +              var event = document.createEvent("Events");
       
  1166 +              event.initEvent("syncfrompreference", true, true);
       
  1167 +              var f = new Function("event",
       
  1168 +                                   aElement.getAttribute("onsyncfrompreference"));
       
  1169 +              rv = f.call(aElement, event);
       
  1170 +            } catch (e) {
       
  1171 +              Components.utils.reportError(e);
       
  1172 +            }
       
  1173 +          }
       
  1174 +          var val = rv;
       
  1175 +          if (val === undefined)
       
  1176 +            val = this.instantApply ? this.valueFromPreferences : this.value;
       
  1177 +          // if the preference is marked for reset, show default value in UI
       
  1178 +          if (val === undefined)
       
  1179 +            val = this.defaultValue;
       
  1180 +
       
  1181 +          /**
       
  1182 +           * Initialize a UI element property with a value. Handles the case
       
  1183 +           * where an element has not yet had a XBL binding attached for it and
       
  1184 +           * the property setter does not yet exist by setting the same attribute
       
  1185 +           * on the XUL element using DOM apis and assuming the element's
       
  1186 +           * constructor or property getters appropriately handle this state.
       
  1187 +           */
       
  1188 +          function setValue(element, attribute, value) {
       
  1189 +            if (attribute in element)
       
  1190 +              element[attribute] = value;
       
  1191 +            else
       
  1192 +              element.setAttribute(attribute, value);
       
  1193 +          }
       
  1194 +          if (aElement.localName == "checkbox" ||
       
  1195 +              aElement.localName == "listitem")
       
  1196 +            setValue(aElement, "checked", val);
       
  1197 +          else if (aElement.localName == "colorpicker")
       
  1198 +            setValue(aElement, "color", val);
       
  1199 +          else if (aElement.localName == "textbox") {
       
  1200 +            // XXXmano Bug 303998: Avoid a caret placement issue if either the
       
  1201 +            // preference observer or its setter calls updateElements as a result
       
  1202 +            // of the input event handler.
       
  1203 +            if (aElement.value !== val)
       
  1204 +              setValue(aElement, "value", val);
       
  1205 +          } else
       
  1206 +            setValue(aElement, "value", val);
       
  1207 +        ]]>
       
  1208 +        </body>
       
  1209 +      </method>
       
  1210 +
       
  1211 +      <method name="getElementValue">
       
  1212 +        <parameter name="aElement"/>
       
  1213 +        <body>
       
  1214 +        <![CDATA[
       
  1215 +          if (aElement.hasAttribute("onsynctopreference")) {
       
  1216 +            // Value changed, synthesize an event
       
  1217 +            try {
       
  1218 +              var event = document.createEvent("Events");
       
  1219 +              event.initEvent("synctopreference", true, true);
       
  1220 +              var f = new Function("event",
       
  1221 +                                   aElement.getAttribute("onsynctopreference"));
       
  1222 +              var rv = f.call(aElement, event);
       
  1223 +              if (rv !== undefined)
       
  1224 +                return rv;
       
  1225 +            } catch (e) {
       
  1226 +              Components.utils.reportError(e);
       
  1227 +            }
       
  1228 +          }
       
  1229 +
       
  1230 +          /**
       
  1231 +           * Read the value of an attribute from an element, assuming the
       
  1232 +           * attribute is a property on the element's node API. If the property
       
  1233 +           * is not present in the API, then assume its value is contained in
       
  1234 +           * an attribute, as is the case before a binding has been attached.
       
  1235 +           */
       
  1236 +          function getValue(element, attribute) {
       
  1237 +            if (attribute in element)
       
  1238 +              return element[attribute];
       
  1239 +            return element.getAttribute(attribute);
       
  1240 +          }
       
  1241 +          if (aElement.localName == "checkbox" ||
       
  1242 +              aElement.localName == "listitem")
       
  1243 +            var value = getValue(aElement, "checked");
       
  1244 +          else if (aElement.localName == "colorpicker")
       
  1245 +            value = getValue(aElement, "color");
       
  1246 +          else
       
  1247 +            value = getValue(aElement, "value");
       
  1248 +
       
  1249 +          switch (this.type) {
       
  1250 +          case "int":
       
  1251 +            return parseInt(value, 10) || 0;
       
  1252 +          case "bool":
       
  1253 +            return typeof(value) == "boolean" ? value : value == "true";
       
  1254 +          }
       
  1255 +          return value;
       
  1256 +        ]]>
       
  1257 +        </body>
       
  1258 +      </method>
       
  1259 +
       
  1260 +      <method name="isElementEditable">
       
  1261 +        <parameter name="aElement"/>
       
  1262 +        <body>
       
  1263 +        <![CDATA[
       
  1264 +          switch (aElement.localName) {
       
  1265 +          case "checkbox":
       
  1266 +          case "colorpicker":
       
  1267 +          case "radiogroup":
       
  1268 +          case "textbox":
       
  1269 +          case "listitem":
       
  1270 +          case "listbox":
       
  1271 +          case "menulist":
       
  1272 +            return true;
       
  1273 +          }
       
  1274 +          return aElement.getAttribute("preference-editable") == "true";
       
  1275 +        ]]>
       
  1276 +        </body>
       
  1277 +      </method>
       
  1278 +
       
  1279 +      <method name="updateElements">
       
  1280 +        <body>
       
  1281 +        <![CDATA[
       
  1282 +          if (!this.id)
       
  1283 +            return;
       
  1284 +
       
  1285 +          // This "change" event handler tracks changes made to preferences by
       
  1286 +          // sources other than the user in this window.
       
  1287 +          var elements = document.getElementsByAttribute("preference", this.id);
       
  1288 +          for (var i = 0; i < elements.length; ++i)
       
  1289 +            this.setElementValue(elements[i]);
       
  1290 +        ]]>
       
  1291 +        </body>
       
  1292 +      </method>
       
  1293 +    </implementation>
       
  1294 +
       
  1295 +    <handlers>
       
  1296 +      <handler event="change">
       
  1297 +        this.updateElements();
       
  1298 +      </handler>
       
  1299 +    </handlers>
       
  1300 +  </binding>
       
  1301 +
       
  1302 +  <binding id="prefwindow"
       
  1303 +           extends="chrome://global/content/bindings/dialog.xml#dialog">
       
  1304 +    <resources>
       
  1305 +      <stylesheet src="chrome://global/skin/preferences.css"/>
       
  1306 +    </resources>
       
  1307 +    <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY"
       
  1308 +             closebuttonlabel="&preferencesCloseButton.label;"
       
  1309 +             closebuttonaccesskey="&preferencesCloseButton.accesskey;"
       
  1310 +             role="dialog"
       
  1311 +#ifdef XP_WIN
       
  1312 +             title="&preferencesDefaultTitleWin.title;">
       
  1313 +#else
       
  1314 +             title="&preferencesDefaultTitleMac.title;">
       
  1315 +#endif
       
  1316 +      <xul:windowdragbox orient="vertical">
       
  1317 +        <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
       
  1318 +                        role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
       
  1319 +      </xul:windowdragbox>
       
  1320 +      <xul:hbox flex="1" class="paneDeckContainer">
       
  1321 +        <xul:deck anonid="paneDeck" flex="1">
       
  1322 +          <children includes="prefpane"/>
       
  1323 +        </xul:deck>
       
  1324 +      </xul:hbox>
       
  1325 +      <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" pack="end">
       
  1326 +#ifndef XP_UNIX
       
  1327 +        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
       
  1328 +        <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
       
  1329 +        <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
       
  1330 +        <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
       
  1331 +        <xul:spacer anonid="spacer" flex="1"/>
       
  1332 +        <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
       
  1333 +        <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
       
  1334 +#else
       
  1335 +        <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
       
  1336 +        <xul:spacer anonid="spacer" flex="1"/>
       
  1337 +        <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
       
  1338 +        <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
       
  1339 +        <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
       
  1340 +        <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
       
  1341 +        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
       
  1342 +#endif
       
  1343 +      </xul:hbox>
       
  1344 +      <xul:hbox>
       
  1345 +        <children/>
       
  1346 +      </xul:hbox>
       
  1347 +    </content>
       
  1348 +    <implementation implements="nsITimerCallback">
       
  1349 +      <constructor>
       
  1350 +      <![CDATA[
       
  1351 +        if (this.type != "child") {
       
  1352 +          if (!this._instantApplyInitialized) {
       
  1353 +            let psvc = Components.classes["@mozilla.org/preferences-service;1"]
       
  1354 +                                 .getService(Components.interfaces.nsIPrefBranch);
       
  1355 +            this.instantApply = psvc.getBoolPref("browser.preferences.instantApply");
       
  1356 +          }
       
  1357 +          if (this.instantApply) {
       
  1358 +            var docElt = document.documentElement;
       
  1359 +            var acceptButton = docElt.getButton("accept");
       
  1360 +            acceptButton.hidden = true;
       
  1361 +            var cancelButton  = docElt.getButton("cancel");
       
  1362 +            if (/Mac/.test(navigator.platform)) {
       
  1363 +              // no buttons on Mac except Help
       
  1364 +              cancelButton.hidden = true;
       
  1365 +              // Move Help button to the end
       
  1366 +              document.getAnonymousElementByAttribute(this, "anonid", "spacer").hidden = true;
       
  1367 +              // Also, don't fire onDialogAccept on enter
       
  1368 +              acceptButton.disabled = true;
       
  1369 +            } else {
       
  1370 +              // morph the Cancel button into the Close button
       
  1371 +              cancelButton.setAttribute("icon", "close");
       
  1372 +              cancelButton.label = docElt.getAttribute("closebuttonlabel");
       
  1373 +              cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey");
       
  1374 +            }
       
  1375 +          }
       
  1376 +        }
       
  1377 +        this.setAttribute("animated", this._shouldAnimate ? "true" : "false");
       
  1378 +        var panes = this.preferencePanes;
       
  1379 +
       
  1380 +        var lastPane = null;
       
  1381 +        if (this.lastSelected) {
       
  1382 +          lastPane = document.getElementById(this.lastSelected);
       
  1383 +          if (!lastPane) {
       
  1384 +            this.lastSelected = "";
       
  1385 +          }
       
  1386 +        }
       
  1387 +
       
  1388 +        var paneToLoad;
       
  1389 +        if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") {
       
  1390 +          paneToLoad = document.getElementById(window.arguments[0]);
       
  1391 +          this.lastSelected = paneToLoad.id;
       
  1392 +        } else if (lastPane)
       
  1393 +          paneToLoad = lastPane;
       
  1394 +        else
       
  1395 +          paneToLoad = panes[0];
       
  1396 +
       
  1397 +        for (var i = 0; i < panes.length; ++i) {
       
  1398 +          this._makePaneButton(panes[i]);
       
  1399 +          if (panes[i].loaded) {
       
  1400 +            // Inline pane content, fire load event to force initialization.
       
  1401 +            this._fireEvent("paneload", panes[i]);
       
  1402 +          }
       
  1403 +        }
       
  1404 +        this.showPane(paneToLoad);
       
  1405 +
       
  1406 +        if (panes.length == 1)
       
  1407 +          this._selector.setAttribute("collapsed", "true");
       
  1408 +      ]]>
       
  1409 +      </constructor>
       
  1410 +
       
  1411 +      <destructor>
       
  1412 +      <![CDATA[
       
  1413 +        // Release timers to avoid reference cycles.
       
  1414 +        if (this._animateTimer) {
       
  1415 +          this._animateTimer.cancel();
       
  1416 +          this._animateTimer = null;
       
  1417 +        }
       
  1418 +        if (this._fadeTimer) {
       
  1419 +          this._fadeTimer.cancel();
       
  1420 +          this._fadeTimer = null;
       
  1421 +        }
       
  1422 +      ]]>
       
  1423 +      </destructor>
       
  1424 +
       
  1425 +      <!-- Derived bindings can set this to true to cause us to skip
       
  1426 +           reading the browser.preferences.instantApply pref in the constructor.
       
  1427 +           Then they can set instantApply to their wished value. -->
       
  1428 +      <field name="_instantApplyInitialized">false</field>
       
  1429 +      <!-- Controls whether changed pref values take effect immediately. -->
       
  1430 +      <field name="instantApply">false</field>
       
  1431 +
       
  1432 +      <property name="preferencePanes"
       
  1433 +                onget="return this.getElementsByTagName('prefpane');"/>
       
  1434 +
       
  1435 +      <property name="type" onget="return this.getAttribute('type');"/>
       
  1436 +      <property name="_paneDeck"
       
  1437 +                onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/>
       
  1438 +      <property name="_paneDeckContainer"
       
  1439 +                onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/>
       
  1440 +      <property name="_selector"
       
  1441 +                onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/>
       
  1442 +      <property name="lastSelected"
       
  1443 +                onget="return this.getAttribute('lastSelected');">
       
  1444 +        <setter>
       
  1445 +          this.setAttribute("lastSelected", val);
       
  1446 +          document.persist(this.id, "lastSelected");
       
  1447 +          return val;
       
  1448 +        </setter>
       
  1449 +      </property>
       
  1450 +      <property name="currentPane"
       
  1451 +                onset="return this._currentPane = val;">
       
  1452 +        <getter>
       
  1453 +          if (!this._currentPane)
       
  1454 +            this._currentPane = this.preferencePanes[0];
       
  1455 +
       
  1456 +          return this._currentPane;
       
  1457 +        </getter>
       
  1458 +      </property>
       
  1459 +      <field name="_currentPane">null</field>
       
  1460 +
       
  1461 +
       
  1462 +      <method name="_makePaneButton">
       
  1463 +        <parameter name="aPaneElement"/>
       
  1464 +        <body>
       
  1465 +        <![CDATA[
       
  1466 +          var radio = document.createElement("radio");
       
  1467 +          radio.setAttribute("pane", aPaneElement.id);
       
  1468 +          radio.setAttribute("label", aPaneElement.label);
       
  1469 +          // Expose preference group choice to accessibility APIs as an unchecked list item
       
  1470 +          // The parent group is exposed to accessibility APIs as a list
       
  1471 +          if (aPaneElement.image)
       
  1472 +            radio.setAttribute("src", aPaneElement.image);
       
  1473 +          radio.style.listStyleImage = aPaneElement.style.listStyleImage;
       
  1474 +          this._selector.appendChild(radio);
       
  1475 +          return radio;
       
  1476 +        ]]>
       
  1477 +        </body>
       
  1478 +      </method>
       
  1479 +
       
  1480 +      <method name="showPane">
       
  1481 +        <parameter name="aPaneElement"/>
       
  1482 +        <body>
       
  1483 +        <![CDATA[
       
  1484 +          if (!aPaneElement)
       
  1485 +            return;
       
  1486 +
       
  1487 +          this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id);
       
  1488 +          if (!aPaneElement.loaded) {
       
  1489 +            let OverlayLoadObserver = function(aPane) {
       
  1490 +              this._pane = aPane;
       
  1491 +            }
       
  1492 +            OverlayLoadObserver.prototype = {
       
  1493 +              _outer: this,
       
  1494 +              observe(aSubject, aTopic, aData) {
       
  1495 +                this._pane.loaded = true;
       
  1496 +                this._outer._fireEvent("paneload", this._pane);
       
  1497 +                this._outer._selectPane(this._pane);
       
  1498 +              }
       
  1499 +            };
       
  1500 +
       
  1501 +            var obs = new OverlayLoadObserver(aPaneElement);
       
  1502 +            document.loadOverlay(aPaneElement.src, obs);
       
  1503 +          } else
       
  1504 +            this._selectPane(aPaneElement);
       
  1505 +        ]]>
       
  1506 +        </body>
       
  1507 +      </method>
       
  1508 +
       
  1509 +      <method name="_fireEvent">
       
  1510 +        <parameter name="aEventName"/>
       
  1511 +        <parameter name="aTarget"/>
       
  1512 +        <body>
       
  1513 +        <![CDATA[
       
  1514 +          // Panel loaded, synthesize a load event.
       
  1515 +          try {
       
  1516 +            var event = document.createEvent("Events");
       
  1517 +            event.initEvent(aEventName, true, true);
       
  1518 +            var cancel = !aTarget.dispatchEvent(event);
       
  1519 +            if (aTarget.hasAttribute("on" + aEventName)) {
       
  1520 +              var fn = new Function("event", aTarget.getAttribute("on" + aEventName));
       
  1521 +              var rv = fn.call(aTarget, event);
       
  1522 +              if (rv == false)
       
  1523 +                cancel = true;
       
  1524 +            }
       
  1525 +            return !cancel;
       
  1526 +          } catch (e) {
       
  1527 +            Components.utils.reportError(e);
       
  1528 +          }
       
  1529 +          return false;
       
  1530 +        ]]>
       
  1531 +        </body>
       
  1532 +      </method>
       
  1533 +
       
  1534 +      <field name="_initialized">false</field>
       
  1535 +      <method name="_selectPane">
       
  1536 +        <parameter name="aPaneElement"/>
       
  1537 +        <body>
       
  1538 +        <![CDATA[
       
  1539 +          if (/Mac/.test(navigator.platform)) {
       
  1540 +            var paneTitle = aPaneElement.label;
       
  1541 +            if (paneTitle != "")
       
  1542 +              document.title = paneTitle;
       
  1543 +          }
       
  1544 +          var helpButton = document.documentElement.getButton("help");
       
  1545 +          if (aPaneElement.helpTopic)
       
  1546 +            helpButton.hidden = false;
       
  1547 +          else
       
  1548 +            helpButton.hidden = true;
       
  1549 +
       
  1550 +          // Find this pane's index in the deck and set the deck's
       
  1551 +          // selectedIndex to that value to switch to it.
       
  1552 +          var prefpanes = this.preferencePanes;
       
  1553 +          for (var i = 0; i < prefpanes.length; ++i) {
       
  1554 +            if (prefpanes[i] == aPaneElement) {
       
  1555 +              this._paneDeck.selectedIndex = i;
       
  1556 +
       
  1557 +              if (this.type != "child") {
       
  1558 +                if (aPaneElement.hasAttribute("flex") && this._shouldAnimate &&
       
  1559 +                    prefpanes.length > 1)
       
  1560 +                  aPaneElement.removeAttribute("flex");
       
  1561 +                // Calling sizeToContent after the first prefpane is loaded
       
  1562 +                // will size the windows contents so style information is
       
  1563 +                // available to calculate correct sizing.
       
  1564 +                if (!this._initialized && prefpanes.length > 1) {
       
  1565 +                  if (this._shouldAnimate)
       
  1566 +                    this.style.minHeight = 0;
       
  1567 +                  window.sizeToContent();
       
  1568 +                }
       
  1569 +
       
  1570 +                var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
       
  1571 +                oldPane.selected = !(aPaneElement.selected = true);
       
  1572 +                this.lastSelected = aPaneElement.id;
       
  1573 +                this.currentPane = aPaneElement;
       
  1574 +                this._initialized = true;
       
  1575 +
       
  1576 +                // Only animate if we've switched between prefpanes
       
  1577 +                if (this._shouldAnimate && oldPane.id != aPaneElement.id) {
       
  1578 +                  aPaneElement.style.opacity = 0.0;
       
  1579 +                  this.animate(oldPane, aPaneElement);
       
  1580 +                } else if (!this._shouldAnimate && prefpanes.length > 1) {
       
  1581 +                  var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer).height);
       
  1582 +                  var verticalPadding = parseInt(window.getComputedStyle(aPaneElement).paddingTop);
       
  1583 +                  verticalPadding += parseInt(window.getComputedStyle(aPaneElement).paddingBottom);
       
  1584 +                  if (aPaneElement.contentHeight > targetHeight - verticalPadding) {
       
  1585 +                    // To workaround the bottom border of a groupbox from being
       
  1586 +                    // cutoff an hbox with a class of bottomBox may enclose it.
       
  1587 +                    // This needs to include its padding to resize properly.
       
  1588 +                    // See bug 394433
       
  1589 +                    var bottomPadding = 0;
       
  1590 +                    var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0];
       
  1591 +                    if (bottomBox)
       
  1592 +                      bottomPadding = parseInt(window.getComputedStyle(bottomBox).paddingBottom);
       
  1593 +                    window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight;
       
  1594 +                  }
       
  1595 +
       
  1596 +                  // XXX rstrong - extend the contents of the prefpane to
       
  1597 +                  // prevent elements from being cutoff (see bug 349098).
       
  1598 +                  if (aPaneElement.contentHeight + verticalPadding < targetHeight)
       
  1599 +                    aPaneElement._content.style.height = targetHeight - verticalPadding + "px";
       
  1600 +                }
       
  1601 +              }
       
  1602 +              break;
       
  1603 +            }
       
  1604 +          }
       
  1605 +        ]]>
       
  1606 +        </body>
       
  1607 +      </method>
       
  1608 +
       
  1609 +      <property name="_shouldAnimate">
       
  1610 +        <getter>
       
  1611 +        <![CDATA[
       
  1612 +          var psvc = Components.classes["@mozilla.org/preferences-service;1"]
       
  1613 +                               .getService(Components.interfaces.nsIPrefBranch);
       
  1614 +          return psvc.getBoolPref("browser.preferences.animateFadeIn",
       
  1615 +                                  /Mac/.test(navigator.platform));
       
  1616 +        ]]>
       
  1617 +        </getter>
       
  1618 +      </property>
       
  1619 +
       
  1620 +      <method name="animate">
       
  1621 +        <parameter name="aOldPane"/>
       
  1622 +        <parameter name="aNewPane"/>
       
  1623 +        <body>
       
  1624 +        <![CDATA[
       
  1625 +          // if we are already resizing, use currentHeight
       
  1626 +          var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight;
       
  1627 +
       
  1628 +          this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1;
       
  1629 +          var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
       
  1630 +          this._animateRemainder = sizeDelta % this._animateIncrement;
       
  1631 +
       
  1632 +          this._setUpAnimationTimer(oldHeight);
       
  1633 +        ]]>
       
  1634 +        </body>
       
  1635 +      </method>
       
  1636 +
       
  1637 +      <property name="_sizeIncrement">
       
  1638 +        <getter>
       
  1639 +        <![CDATA[
       
  1640 +          var lastSelectedPane = document.getElementById(this.lastSelected);
       
  1641 +          var increment = this._animateIncrement * this._multiplier;
       
  1642 +          var newHeight = this._currentHeight + increment;
       
  1643 +          if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) ||
       
  1644 +              (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight))
       
  1645 +            return 0;
       
  1646 +
       
  1647 +          if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) ||
       
  1648 +              (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight))
       
  1649 +            increment = this._animateRemainder * this._multiplier;
       
  1650 +          return increment;
       
  1651 +        ]]>
       
  1652 +        </getter>
       
  1653 +      </property>
       
  1654 +
       
  1655 +      <method name="notify">
       
  1656 +        <parameter name="aTimer"/>
       
  1657 +        <body>
       
  1658 +        <![CDATA[
       
  1659 +          if (!document)
       
  1660 +            aTimer.cancel();
       
  1661 +
       
  1662 +          if (aTimer == this._animateTimer) {
       
  1663 +            var increment = this._sizeIncrement;
       
  1664 +            if (increment != 0) {
       
  1665 +              window.innerHeight += increment;
       
  1666 +              this._currentHeight += increment;
       
  1667 +            } else {
       
  1668 +              aTimer.cancel();
       
  1669 +              this._setUpFadeTimer();
       
  1670 +            }
       
  1671 +          } else if (aTimer == this._fadeTimer) {
       
  1672 +            var elt = document.getElementById(this.lastSelected);
       
  1673 +            var newOpacity = parseFloat(window.getComputedStyle(elt).opacity) + this._fadeIncrement;
       
  1674 +            if (newOpacity < 1.0)
       
  1675 +              elt.style.opacity = newOpacity;
       
  1676 +            else {
       
  1677 +              aTimer.cancel();
       
  1678 +              elt.style.opacity = 1.0;
       
  1679 +            }
       
  1680 +          }
       
  1681 +        ]]>
       
  1682 +        </body>
       
  1683 +      </method>
       
  1684 +
       
  1685 +      <method name="_setUpAnimationTimer">
       
  1686 +        <parameter name="aStartHeight"/>
       
  1687 +        <body>
       
  1688 +        <![CDATA[
       
  1689 +          if (!this._animateTimer)
       
  1690 +            this._animateTimer = Components.classes["@mozilla.org/timer;1"]
       
  1691 +                                           .createInstance(Components.interfaces.nsITimer);
       
  1692 +          else
       
  1693 +            this._animateTimer.cancel();
       
  1694 +          this._currentHeight = aStartHeight;
       
  1695 +
       
  1696 +          this._animateTimer.initWithCallback(this, this._animateDelay,
       
  1697 +                                              Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
       
  1698 +        ]]>
       
  1699 +        </body>
       
  1700 +      </method>
       
  1701 +
       
  1702 +      <method name="_setUpFadeTimer">
       
  1703 +        <body>
       
  1704 +        <![CDATA[
       
  1705 +          if (!this._fadeTimer)
       
  1706 +            this._fadeTimer = Components.classes["@mozilla.org/timer;1"]
       
  1707 +                                        .createInstance(Components.interfaces.nsITimer);
       
  1708 +          else
       
  1709 +            this._fadeTimer.cancel();
       
  1710 +
       
  1711 +          this._fadeTimer.initWithCallback(this, this._fadeDelay,
       
  1712 +                                           Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
       
  1713 +        ]]>
       
  1714 +        </body>
       
  1715 +      </method>
       
  1716 +
       
  1717 +      <field name="_animateTimer">null</field>
       
  1718 +      <field name="_fadeTimer">null</field>
       
  1719 +      <field name="_animateDelay">15</field>
       
  1720 +      <field name="_animateIncrement">40</field>
       
  1721 +      <field name="_fadeDelay">5</field>
       
  1722 +      <field name="_fadeIncrement">0.40</field>
       
  1723 +      <field name="_animateRemainder">0</field>
       
  1724 +      <field name="_currentHeight">0</field>
       
  1725 +      <field name="_multiplier">0</field>
       
  1726 +
       
  1727 +      <method name="addPane">
       
  1728 +        <parameter name="aPaneElement"/>
       
  1729 +        <body>
       
  1730 +        <![CDATA[
       
  1731 +          this.appendChild(aPaneElement);
       
  1732 +
       
  1733 +          // Set up pane button
       
  1734 +          this._makePaneButton(aPaneElement);
       
  1735 +        ]]>
       
  1736 +        </body>
       
  1737 +      </method>
       
  1738 +
       
  1739 +      <method name="openSubDialog">
       
  1740 +        <parameter name="aURL"/>
       
  1741 +        <parameter name="aFeatures"/>
       
  1742 +        <parameter name="aParams"/>
       
  1743 +        <body>
       
  1744 +          return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
       
  1745 +        </body>
       
  1746 +      </method>
       
  1747 +
       
  1748 +      <method name="openWindow">
       
  1749 +        <parameter name="aWindowType"/>
       
  1750 +        <parameter name="aURL"/>
       
  1751 +        <parameter name="aFeatures"/>
       
  1752 +        <parameter name="aParams"/>
       
  1753 +        <body>
       
  1754 +        <![CDATA[
       
  1755 +          var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
       
  1756 +                             .getService(Components.interfaces.nsIWindowMediator);
       
  1757 +          var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null;
       
  1758 +          if (win) {
       
  1759 +            if ("initWithParams" in win)
       
  1760 +              win.initWithParams(aParams);
       
  1761 +            win.focus();
       
  1762 +          } else {
       
  1763 +            var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : "");
       
  1764 +            var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener;
       
  1765 +            win = parentWindow.openDialog(aURL, "_blank", features, aParams);
       
  1766 +          }
       
  1767 +          return win;
       
  1768 +        ]]>
       
  1769 +        </body>
       
  1770 +      </method>
       
  1771 +    </implementation>
       
  1772 +    <handlers>
       
  1773 +      <handler event="dialogaccept">
       
  1774 +      <![CDATA[
       
  1775 +        if (!this._fireEvent("beforeaccept", this)) {
       
  1776 +          return false;
       
  1777 +        }
       
  1778 +
       
  1779 +        var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
       
  1780 +                    .getService(Components.interfaces.nsIScriptSecurityManager);
       
  1781 +        if (this.type == "child" && window.opener &&
       
  1782 +            secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) {
       
  1783 +          var pdocEl = window.opener.document.documentElement;
       
  1784 +          if (pdocEl.instantApply) {
       
  1785 +            let panes = this.preferencePanes;
       
  1786 +            for (let i = 0; i < panes.length; ++i)
       
  1787 +              panes[i].writePreferences(true);
       
  1788 +          } else {
       
  1789 +            // Clone all the preferences elements from the child document and
       
  1790 +            // insert them into the pane collection of the parent.
       
  1791 +            var pdoc = window.opener.document;
       
  1792 +            if (pdoc.documentElement.localName == "prefwindow") {
       
  1793 +              var currentPane = pdoc.documentElement.currentPane;
       
  1794 +              var id = window.location.href + "#childprefs";
       
  1795 +              var childPrefs = pdoc.getElementById(id);
       
  1796 +              if (!childPrefs) {
       
  1797 +                childPrefs = pdoc.createElement("preferences");
       
  1798 +                currentPane.appendChild(childPrefs);
       
  1799 +                childPrefs.id = id;
       
  1800 +              }
       
  1801 +              let panes = this.preferencePanes;
       
  1802 +              for (let i = 0; i < panes.length; ++i) {
       
  1803 +                var preferences = panes[i].preferences;
       
  1804 +                for (var j = 0; j < preferences.length; ++j) {
       
  1805 +                  // Try to find a preference element for the same preference.
       
  1806 +                  var preference = null;
       
  1807 +                  var parentPreferences = pdoc.getElementsByTagName("preferences");
       
  1808 +                  for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
       
  1809 +                    var parentPrefs = parentPreferences[k]
       
  1810 +                                         .getElementsByAttribute("name", preferences[j].name);
       
  1811 +                    for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
       
  1812 +                      if (parentPrefs[l].localName == "preference")
       
  1813 +                        preference = parentPrefs[l];
       
  1814 +                    }
       
  1815 +                  }
       
  1816 +                  if (!preference) {
       
  1817 +                    // No matching preference in the parent window.
       
  1818 +                    preference = pdoc.createElement("preference");
       
  1819 +                    childPrefs.appendChild(preference);
       
  1820 +                    preference.name     = preferences[j].name;
       
  1821 +                    preference.type     = preferences[j].type;
       
  1822 +                    preference.inverted = preferences[j].inverted;
       
  1823 +                    preference.readonly = preferences[j].readonly;
       
  1824 +                    preference.disabled = preferences[j].disabled;
       
  1825 +                  }
       
  1826 +                  preference.value = preferences[j].value;
       
  1827 +                }
       
  1828 +              }
       
  1829 +            }
       
  1830 +          }
       
  1831 +        } else {
       
  1832 +          let panes = this.preferencePanes;
       
  1833 +          for (var i = 0; i < panes.length; ++i)
       
  1834 +            panes[i].writePreferences(false);
       
  1835 +
       
  1836 +          let psvc = Components.classes["@mozilla.org/preferences-service;1"]
       
  1837 +                               .getService(Components.interfaces.nsIPrefService);
       
  1838 +          psvc.savePrefFile(null);
       
  1839 +        }
       
  1840 +
       
  1841 +        return true;
       
  1842 +      ]]>
       
  1843 +      </handler>
       
  1844 +      <handler event="command">
       
  1845 +        if (event.originalTarget.hasAttribute("pane")) {
       
  1846 +          var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
       
  1847 +          this.showPane(pane);
       
  1848 +        }
       
  1849 +      </handler>
       
  1850 +
       
  1851 +      <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing">
       
  1852 +      <![CDATA[
       
  1853 +        if (this.instantApply)
       
  1854 +          window.close();
       
  1855 +        event.stopPropagation();
       
  1856 +        event.preventDefault();
       
  1857 +      ]]>
       
  1858 +      </handler>
       
  1859 +
       
  1860 +      <handler event="keypress"
       
  1861 +#ifdef XP_MACOSX
       
  1862 +               key="&openHelpMac.commandkey;" modifiers="accel"
       
  1863 +#else
       
  1864 +               keycode="&openHelp.commandkey;"
       
  1865 +#endif
       
  1866 +               phase="capturing">
       
  1867 +      <![CDATA[
       
  1868 +        var helpButton = this.getButton("help");
       
  1869 +        if (helpButton.disabled || helpButton.hidden)
       
  1870 +          return;
       
  1871 +        this._fireEvent("dialoghelp", this);
       
  1872 +        event.stopPropagation();
       
  1873 +        event.preventDefault();
       
  1874 +      ]]>
       
  1875 +      </handler>
       
  1876 +    </handlers>
       
  1877 +  </binding>
       
  1878 +
       
  1879 +  <binding id="prefpane">
       
  1880 +    <resources>
       
  1881 +      <stylesheet src="chrome://global/skin/preferences.css"/>
       
  1882 +    </resources>
       
  1883 +    <content>
       
  1884 +      <xul:vbox class="content-box" xbl:inherits="flex">
       
  1885 +        <children/>
       
  1886 +      </xul:vbox>
       
  1887 +    </content>
       
  1888 +    <implementation>
       
  1889 +      <method name="writePreferences">
       
  1890 +        <parameter name="aFlushToDisk"/>
       
  1891 +        <body>
       
  1892 +        <![CDATA[
       
  1893 +          // Write all values to preferences.
       
  1894 +          if (this._deferredValueUpdateElements.size) {
       
  1895 +            this._finalizeDeferredElements();
       
  1896 +          }
       
  1897 +
       
  1898 +          var preferences = this.preferences;
       
  1899 +          for (var i = 0; i < preferences.length; ++i) {
       
  1900 +            var preference = preferences[i];
       
  1901 +            preference.batching = true;
       
  1902 +            preference.valueFromPreferences = preference.value;
       
  1903 +            preference.batching = false;
       
  1904 +          }
       
  1905 +          if (aFlushToDisk) {
       
  1906 +            var psvc = Components.classes["@mozilla.org/preferences-service;1"]
       
  1907 +                                 .getService(Components.interfaces.nsIPrefService);
       
  1908 +            psvc.savePrefFile(null);
       
  1909 +          }
       
  1910 +        ]]>
       
  1911 +        </body>
       
  1912 +      </method>
       
  1913 +
       
  1914 +      <property name="src"
       
  1915 +                onget="return this.getAttribute('src');"
       
  1916 +                onset="this.setAttribute('src', val); return val;"/>
       
  1917 +      <property name="selected"
       
  1918 +                onget="return this.getAttribute('selected') == 'true';"
       
  1919 +                onset="this.setAttribute('selected', val); return val;"/>
       
  1920 +      <property name="image"
       
  1921 +                onget="return this.getAttribute('image');"
       
  1922 +                onset="this.setAttribute('image', val); return val;"/>
       
  1923 +      <property name="label"
       
  1924 +                onget="return this.getAttribute('label');"
       
  1925 +                onset="this.setAttribute('label', val); return val;"/>
       
  1926 +
       
  1927 +      <property name="preferenceElements"
       
  1928 +                onget="return this.getElementsByAttribute('preference', '*');"/>
       
  1929 +      <property name="preferences"
       
  1930 +                onget="return this.getElementsByTagName('preference');"/>
       
  1931 +
       
  1932 +      <property name="helpTopic">
       
  1933 +        <getter>
       
  1934 +        <![CDATA[
       
  1935 +          // if there are tabs, and the selected tab provides a helpTopic, return that
       
  1936 +          var box = this.getElementsByTagName("tabbox");
       
  1937 +          if (box[0]) {
       
  1938 +            var tab = box[0].selectedTab;
       
  1939 +            if (tab && tab.hasAttribute("helpTopic"))
       
  1940 +              return tab.getAttribute("helpTopic");
       
  1941 +          }
       
  1942 +
       
  1943 +          // otherwise, return the helpTopic of the current panel
       
  1944 +          return this.getAttribute("helpTopic");
       
  1945 +        ]]>
       
  1946 +        </getter>
       
  1947 +      </property>
       
  1948 +
       
  1949 +      <field name="_loaded">false</field>
       
  1950 +      <property name="loaded"
       
  1951 +                onget="return !this.src ? true : this._loaded;"
       
  1952 +                onset="this._loaded = val; return val;"/>
       
  1953 +
       
  1954 +      <method name="preferenceForElement">
       
  1955 +        <parameter name="aElement"/>
       
  1956 +        <body>
       
  1957 +          return document.getElementById(aElement.getAttribute("preference"));
       
  1958 +        </body>
       
  1959 +      </method>
       
  1960 +
       
  1961 +      <method name="getPreferenceElement">
       
  1962 +        <parameter name="aStartElement"/>
       
  1963 +        <body>
       
  1964 +        <![CDATA[
       
  1965 +          var temp = aStartElement;
       
  1966 +          while (temp && temp.nodeType == Node.ELEMENT_NODE &&
       
  1967 +                 !temp.hasAttribute("preference"))
       
  1968 +            temp = temp.parentNode;
       
  1969 +          return temp && temp.nodeType == Node.ELEMENT_NODE ?
       
  1970 +                 temp : aStartElement;
       
  1971 +        ]]>
       
  1972 +        </body>
       
  1973 +      </method>
       
  1974 +
       
  1975 +      <property name="DeferredTask" readonly="true">
       
  1976 +        <getter><![CDATA[
       
  1977 +          let module = {};
       
  1978 +          Components.utils.import("resource://gre/modules/DeferredTask.jsm", module);
       
  1979 +          Object.defineProperty(this, "DeferredTask", {
       
  1980 +            configurable: true,
       
  1981 +            enumerable: true,
       
  1982 +            writable: true,
       
  1983 +            value: module.DeferredTask
       
  1984 +          });
       
  1985 +          return module.DeferredTask;
       
  1986 +        ]]></getter>
       
  1987 +      </property>
       
  1988 +      <method name="_deferredValueUpdate">
       
  1989 +        <parameter name="aElement"/>
       
  1990 +        <body>
       
  1991 +        <![CDATA[
       
  1992 +          delete aElement._deferredValueUpdateTask;
       
  1993 +          let preference = document.getElementById(aElement.getAttribute("preference"));
       
  1994 +          let prefVal = preference.getElementValue(aElement);
       
  1995 +          preference.value = prefVal;
       
  1996 +          this._deferredValueUpdateElements.delete(aElement);
       
  1997 +        ]]>
       
  1998 +        </body>
       
  1999 +      </method>
       
  2000 +      <field name="_deferredValueUpdateElements">
       
  2001 +        new Set();
       
  2002 +      </field>
       
  2003 +      <method name="_finalizeDeferredElements">
       
  2004 +        <body>
       
  2005 +        <![CDATA[
       
  2006 +          for (let el of this._deferredValueUpdateElements) {
       
  2007 +            if (el._deferredValueUpdateTask) {
       
  2008 +              el._deferredValueUpdateTask.finalize();
       
  2009 +            }
       
  2010 +          }
       
  2011 +        ]]>
       
  2012 +        </body>
       
  2013 +      </method>
       
  2014 +      <method name="userChangedValue">
       
  2015 +        <parameter name="aElement"/>
       
  2016 +        <body>
       
  2017 +        <![CDATA[
       
  2018 +          let element = this.getPreferenceElement(aElement);
       
  2019 +          if (element.hasAttribute("preference")) {
       
  2020 +            if (element.getAttribute("delayprefsave") != "true") {
       
  2021 +              var preference = document.getElementById(element.getAttribute("preference"));
       
  2022 +              var prefVal = preference.getElementValue(element);
       
  2023 +              preference.value = prefVal;
       
  2024 +            } else {
       
  2025 +              if (!element._deferredValueUpdateTask) {
       
  2026 +                element._deferredValueUpdateTask = new this.DeferredTask(this._deferredValueUpdate.bind(this, element), 1000);
       
  2027 +                this._deferredValueUpdateElements.add(element);
       
  2028 +              } else {
       
  2029 +                // Each time the preference is changed, restart the delay.
       
  2030 +                element._deferredValueUpdateTask.disarm();
       
  2031 +              }
       
  2032 +              element._deferredValueUpdateTask.arm();
       
  2033 +            }
       
  2034 +          }
       
  2035 +        ]]>
       
  2036 +        </body>
       
  2037 +      </method>
       
  2038 +
       
  2039 +      <property name="contentHeight">
       
  2040 +        <getter>
       
  2041 +          var targetHeight = parseInt(window.getComputedStyle(this._content).height);
       
  2042 +          targetHeight += parseInt(window.getComputedStyle(this._content).marginTop);
       
  2043 +          targetHeight += parseInt(window.getComputedStyle(this._content).marginBottom);
       
  2044 +          return targetHeight;
       
  2045 +        </getter>
       
  2046 +      </property>
       
  2047 +      <field name="_content">
       
  2048 +        document.getAnonymousElementByAttribute(this, "class", "content-box");
       
  2049 +      </field>
       
  2050 +    </implementation>
       
  2051 +    <handlers>
       
  2052 +      <handler event="command">
       
  2053 +        // This "command" event handler tracks changes made to preferences by
       
  2054 +        // the user in this window.
       
  2055 +        if (event.sourceEvent)
       
  2056 +          event = event.sourceEvent;
       
  2057 +        this.userChangedValue(event.target);
       
  2058 +      </handler>
       
  2059 +      <handler event="select">
       
  2060 +        // This "select" event handler tracks changes made to colorpicker
       
  2061 +        // preferences by the user in this window.
       
  2062 +        if (event.target.localName == "colorpicker")
       
  2063 +          this.userChangedValue(event.target);
       
  2064 +      </handler>
       
  2065 +      <handler event="change">
       
  2066 +        // This "change" event handler tracks changes made to preferences by
       
  2067 +        // the user in this window.
       
  2068 +        this.userChangedValue(event.target);
       
  2069 +      </handler>
       
  2070 +      <handler event="input">
       
  2071 +        // This "input" event handler tracks changes made to preferences by
       
  2072 +        // the user in this window.
       
  2073 +        this.userChangedValue(event.target);
       
  2074 +      </handler>
       
  2075 +      <handler event="paneload">
       
  2076 +      <![CDATA[
       
  2077 +        // Initialize all values from preferences.
       
  2078 +        var elements = this.preferenceElements;
       
  2079 +        for (var i = 0; i < elements.length; ++i) {
       
  2080 +          try {
       
  2081 +            var preference = this.preferenceForElement(elements[i]);
       
  2082 +            preference.setElementValue(elements[i]);
       
  2083 +          } catch (e) {
       
  2084 +            dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n");
       
  2085 +          }
       
  2086 +        }
       
  2087 +      ]]>
       
  2088 +      </handler>
       
  2089 +    </handlers>
       
  2090 +  </binding>
       
  2091 +
       
  2092 +  <binding id="panebutton" role="xul:listitem"
       
  2093 +           extends="chrome://global/content/bindings/radio.xml#radio">
       
  2094 +    <resources>
       
  2095 +      <stylesheet src="chrome://global/skin/preferences.css"/>
       
  2096 +    </resources>
       
  2097 +    <content>
       
  2098 +      <xul:image class="paneButtonIcon" xbl:inherits="src"/>
       
  2099 +      <xul:label class="paneButtonLabel" xbl:inherits="value=label"/>
       
  2100 +    </content>
       
  2101 +  </binding>
       
  2102 +
       
  2103 +</bindings>
       
  2104 +
       
  2105 +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       
  2106 +# This Source Code Form is subject to the terms of the Mozilla Public
       
  2107 +# License, v. 2.0. If a copy of the MPL was not distributed with this
       
  2108 +# file, You can obtain one at http://mozilla.org/MPL/2.0/.
       
  2109 +
       
  2110 +#
       
  2111 +# This is PrefWindow 6. The Code Could Well Be Ready, Are You?
       
  2112 +#
       
  2113 +#    Historical References:
       
  2114 +#    PrefWindow V   (February 1, 2003)
       
  2115 +#    PrefWindow IV  (April 24, 2000)
       
  2116 +#    PrefWindow III (January 6, 2000)
       
  2117 +#    PrefWindow II  (???)
       
  2118 +#    PrefWindow I   (June 4, 1999)
       
  2119 +#
       
  2120 diff --git a/toolkit/mozapps/downloads/nsHelperAppDlg.js b/toolkit/mozapps/downloads/nsHelperAppDlg.js
   674 diff --git a/toolkit/mozapps/downloads/nsHelperAppDlg.js b/toolkit/mozapps/downloads/nsHelperAppDlg.js
  2121 --- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
   675 --- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
  2122 +++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
   676 +++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
  2123 @@ -626,17 +626,17 @@ nsUnknownContentTypeDialog.prototype = {
   677 @@ -626,17 +626,17 @@ nsUnknownContentTypeDialog.prototype = {
  2124        else
   678        else
  2325 +
   879 +
  2326 diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build
   880 diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build
  2327 --- a/toolkit/xre/moz.build
   881 --- a/toolkit/xre/moz.build
  2328 +++ b/toolkit/xre/moz.build
   882 +++ b/toolkit/xre/moz.build
  2329 @@ -61,17 +61,19 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
   883 @@ -61,17 +61,19 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
  2330          '../components/printingui/mac',
   884          '../components/printingui',
  2331      ]
   885      ]
  2332  elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit':
   886  elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit':
  2333      UNIFIED_SOURCES += [
   887      UNIFIED_SOURCES += [
  2334          'nsNativeAppSupportDefault.cpp',
   888          'nsNativeAppSupportDefault.cpp',
  2335          'UIKitDirProvider.mm',
   889          'UIKitDirProvider.mm',
  2753 +++ b/uriloader/exthandler/moz.build
  1307 +++ b/uriloader/exthandler/moz.build
  2754 @@ -77,17 +77,19 @@ else:
  1308 @@ -77,17 +77,19 @@ else:
  2755      SOURCES += [
  1309      SOURCES += [
  2756          osdir + '/nsOSHelperAppService.cpp',
  1310          osdir + '/nsOSHelperAppService.cpp',
  2757      ]
  1311      ]
  2758      if CONFIG['GNU_CXX']:
  1312      if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
  2759          CXXFLAGS += ['-Wno-error=shadow']
  1313          CXXFLAGS += ['-Wno-error=shadow']
  2760  
  1314  
  2761  if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
  1315  if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
  2762      UNIFIED_SOURCES += [
  1316      UNIFIED_SOURCES += [
  2763 +        'unix/nsCommonRegistry.cpp',
  1317 +        'unix/nsCommonRegistry.cpp',
  2764          'unix/nsGNOMERegistry.cpp',
  1318          'unix/nsGNOMERegistry.cpp',
  2765 +	'unix/nsKDERegistry.cpp',
  1319 +        'unix/nsKDERegistry.cpp',
  2766          'unix/nsMIMEInfoUnix.cpp',
  1320          'unix/nsMIMEInfoUnix.cpp',
  2767      ]
  1321      ]
  2768  elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
  1322  elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
  2769      UNIFIED_SOURCES += [
  1323      UNIFIED_SOURCES += [
  2770          'android/nsAndroidHandlerApp.cpp',
  1324          'android/nsAndroidHandlerApp.cpp',
  2771          'android/nsExternalSharingAppService.cpp',
  1325          'android/nsExternalSharingAppService.cpp',
  2772          'android/nsExternalURLHandlerService.cpp',
  1326          'android/nsExternalURLHandlerService.cpp',
  2773          'android/nsMIMEInfoAndroid.cpp',
  1327          'android/nsMIMEInfoAndroid.cpp',
  2774 @@ -129,16 +131,17 @@ include('/ipc/chromium/chromium-config.m
  1328 @@ -124,16 +126,17 @@ include('/ipc/chromium/chromium-config.m
  2775  FINAL_LIBRARY = 'xul'
  1329  FINAL_LIBRARY = 'xul'
  2776  
  1330  
  2777  LOCAL_INCLUDES += [
  1331  LOCAL_INCLUDES += [
  2778      '/docshell/base',
  1332      '/docshell/base',
  2779      '/dom/base',
  1333      '/dom/base',
  2785  
  1339  
  2786  if CONFIG['MOZ_ENABLE_DBUS']:
  1340  if CONFIG['MOZ_ENABLE_DBUS']:
  2787      CXXFLAGS += CONFIG['TK_CFLAGS']
  1341      CXXFLAGS += CONFIG['TK_CFLAGS']
  2788      CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
  1342      CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
  2789  
  1343  
  2790  if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
  1344  if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
  2791      CXXFLAGS += CONFIG['TK_CFLAGS']
  1345      CXXFLAGS += CONFIG['TK_CFLAGS']
  2792 diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp
  1346 diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp
  2793 new file mode 100644
  1347 new file mode 100644
  2794 --- /dev/null
  1348 --- /dev/null
  2795 +++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp
  1349 +++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp
  3071        *_retval = true;
  1625        *_retval = true;
  3072    }
  1626    }
  3073  
  1627  
  3074    if (*_retval)
  1628    if (*_retval)
  3075      return NS_OK;
  1629      return NS_OK;
  3076 @@ -79,16 +82,33 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns
  1630 @@ -59,16 +62,33 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns
  3077      ContentAction::Action::defaultActionForFile(uri, QString(mSchemeOrType.get()));
  1631    // either /etc/mailcap or ${HOME}/.mailcap, in which case we don't want to
  3078    if (action.isValid()) {
  1632    // give the GNOME answer.
  3079      action.trigger();
  1633    if (mDefaultApplication)
  3080      return NS_OK;
  1634      return nsMIMEInfoImpl::LaunchDefaultWithFile(aFile);
  3081    }
  1635  
  3082    return NS_ERROR_FAILURE;
  1636    nsAutoCString nativePath;
  3083  #endif
  1637    aFile->GetNativePath(nativePath);
  3084  
  1638  
  3085 +  if( nsKDEUtils::kdeSupport()) {
  1639 +  if( nsKDEUtils::kdeSupport()) {
  3086 +    bool supports;
  1640 +    bool supports;
  3087 +    if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) {
  1641 +    if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) {
  3088 +      nsTArray<nsCString> command;
  1642 +      nsTArray<nsCString> command;
  3206        return gnomeInfo.forget();
  1760        return gnomeInfo.forget();
  3207      }
  1761      }
  3208 diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build
  1762 diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build
  3209 --- a/widget/gtk/moz.build
  1763 --- a/widget/gtk/moz.build
  3210 +++ b/widget/gtk/moz.build
  1764 +++ b/widget/gtk/moz.build
  3211 @@ -109,16 +109,17 @@ else:
  1765 @@ -121,16 +121,17 @@ else:
  3212  include('/ipc/chromium/chromium-config.mozbuild')
  1766  include('/ipc/chromium/chromium-config.mozbuild')
  3213  
  1767  
  3214  FINAL_LIBRARY = 'xul'
  1768  FINAL_LIBRARY = 'xul'
  3215  
  1769  
  3216  LOCAL_INCLUDES += [
  1770  LOCAL_INCLUDES += [
  3575 +  bool getKdeRunning();
  2129 +  bool getKdeRunning();
  3576 +  NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn);
  2130 +  NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn);
  3577 +  NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn);
  2131 +  NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn);
  3578 +  nsCString kdeMakeFilter( int index );
  2132 +  nsCString kdeMakeFilter( int index );
  3579 +
  2133 +
  3580  #if (MOZ_WIDGET_GTK == 3)
  2134  #ifdef MOZ_WIDGET_GTK
  3581    GtkFileChooserWidget *mFileChooserDelegate;
  2135    GtkFileChooserWidget *mFileChooserDelegate;
  3582  #endif
  2136  #endif
  3583  };
  2137  };
  3584  
  2138  
  3585  #endif
  2139  #endif
  3754  #include <Carbon/Carbon.h>
  2308  #include <Carbon/Carbon.h>
  3755  #include "CocoaFileUtils.h"
  2309  #include "CocoaFileUtils.h"
  3756  #include "prmem.h"
  2310  #include "prmem.h"
  3757  #include "plbase64.h"
  2311  #include "plbase64.h"
  3758  
  2312  
  3759 @@ -1938,59 +1939,74 @@ nsLocalFile::SetPersistentDescriptor(con
  2313 @@ -1934,59 +1935,74 @@ nsLocalFile::SetPersistentDescriptor(con
  3760    return InitWithNativePath(aPersistentDescriptor);
  2314    return InitWithNativePath(aPersistentDescriptor);
  3761  #endif
  2315  #endif
  3762  }
  2316  }
  3763  
  2317  
  3764  NS_IMETHODIMP
  2318  NS_IMETHODIMP
  3833    if (!giovfs) {
  2387    if (!giovfs) {
  3834      return NS_ERROR_FAILURE;
  2388      return NS_ERROR_FAILURE;
  3835    }
  2389    }
  3836  
  2390  
  3837    return giovfs->ShowURIForInput(mPath);
  2391    return giovfs->ShowURIForInput(mPath);
  3838  #elif defined(MOZ_ENABLE_CONTENTACTION)
  2392  #elif defined(MOZ_WIDGET_ANDROID)
  3839    QUrl uri = QUrl::fromLocalFile(QString::fromUtf8(mPath.get()));
  2393    // Try to get a mimetype, if this fails just use the file uri alone