home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / xulrunner-1.9.0.14 / chrome / toolkit.jar / content / global / bindings / browser.xml < prev    next >
Encoding:
Extensible Markup Language  |  2008-03-05  |  35.5 KB  |  1,029 lines

  1. <?xml version="1.0"?>
  2.  
  3. <!-- ***** BEGIN LICENSE BLOCK *****
  4.    - Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5.    -
  6.    - The contents of this file are subject to the Mozilla Public License Version
  7.    - 1.1 (the "License"); you may not use this file except in compliance with
  8.    - the License. You may obtain a copy of the License at
  9.    - http://www.mozilla.org/MPL/
  10.    -
  11.    - Software distributed under the License is distributed on an "AS IS" basis,
  12.    - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13.    - for the specific language governing rights and limitations under the
  14.    - License.
  15.    -
  16.    - The Original Code is this file as it was released on March 28, 2001.
  17.    -
  18.    - The Initial Developer of the Original Code is
  19.    - Peter Annema.
  20.    - Portions created by the Initial Developer are Copyright (C) 2001
  21.    - the Initial Developer. All Rights Reserved.
  22.    -
  23.    - Contributor(s):
  24.    -   Peter Annema <disttsc@bart.nl> (Original Author of <browser>)
  25.    -   Peter Parente <parente@cs.unc.edu>
  26.    -   Christopher Thomas <cst@yecc.com>
  27.    -   Michael Ventnor <m.ventnor@gmail.com>
  28.    -
  29.    - Alternatively, the contents of this file may be used under the terms of
  30.    - either the GNU General Public License Version 2 or later (the "GPL"), or
  31.    - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  32.    - in which case the provisions of the GPL or the LGPL are applicable instead
  33.    - of those above. If you wish to allow use of your version of this file only
  34.    - under the terms of either the GPL or the LGPL, and not to allow others to
  35.    - use your version of this file under the terms of the MPL, indicate your
  36.    - decision by deleting the provisions above and replace them with the notice
  37.    - and other provisions required by the GPL or the LGPL. If you do not delete
  38.    - the provisions above, a recipient may use your version of this file under
  39.    - the terms of any one of the MPL, the GPL or the LGPL.
  40.    -
  41.    - ***** END LICENSE BLOCK ***** -->
  42.  
  43. <!DOCTYPE bindings [
  44.   <!ENTITY % findBarDTD SYSTEM "chrome://global/locale/findbar.dtd" >
  45.   %findBarDTD;
  46. ]>
  47.  
  48. <bindings id="browserBindings"
  49.           xmlns="http://www.mozilla.org/xbl"
  50.           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  51.  
  52.   <binding id="browser" extends="xul:browser">
  53.     <implementation type="application/javascript" implements="nsIAccessibleProvider, nsIObserver, nsIDOMEventListener">
  54.       <property name="accessibleType" readonly="true">
  55.         <getter>
  56.           <![CDATA[
  57.             return Components.interfaces.nsIAccessibleProvider.OuterDoc;
  58.           ]]>
  59.         </getter>
  60.       </property>
  61.  
  62.       <property name="autoscrollEnabled">
  63.         <getter>
  64.           <![CDATA[
  65.             if (this.getAttribute("autoscroll") == "false")
  66.               return false;
  67.             
  68.             var enabled = true;
  69.             try {
  70.               enabled = this.mPrefs.getBoolPref("general.autoScroll");
  71.             }
  72.             catch(ex) {
  73.             }
  74.             
  75.             return enabled;
  76.           ]]>
  77.         </getter>
  78.       </property>
  79.  
  80.       <property name="canGoBack"
  81.                 onget="return this.webNavigation.canGoBack;"
  82.                 readonly="true"/>
  83.  
  84.       <property name="canGoForward"
  85.                 onget="return this.webNavigation.canGoForward;"
  86.                 readonly="true"/>
  87.  
  88.       <method name="goBack">
  89.         <body>
  90.           <![CDATA[
  91.             var webNavigation = this.webNavigation;
  92.             if (webNavigation.canGoBack) {
  93.               try {
  94.                 this.userTypedClear++;
  95.                 webNavigation.goBack();
  96.               } finally {
  97.                 if (this.userTypedClear)
  98.                   this.userTypedClear--;
  99.               }
  100.             }
  101.           ]]>
  102.         </body>
  103.       </method>
  104.  
  105.       <method name="goForward">
  106.         <body>
  107.           <![CDATA[
  108.             var webNavigation = this.webNavigation;
  109.             if (webNavigation.canGoForward) {
  110.               try {
  111.                 this.userTypedClear++;
  112.                 webNavigation.goForward();
  113.               } finally {
  114.                 if (this.userTypedClear)
  115.                   this.userTypedClear--;
  116.               }
  117.             }
  118.           ]]>
  119.         </body>
  120.       </method>
  121.  
  122.       <method name="reload">
  123.         <body>
  124.           <![CDATA[
  125.             const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
  126.             const flags = nsIWebNavigation.LOAD_FLAGS_NONE;
  127.             this.reloadWithFlags(flags);
  128.           ]]>
  129.         </body>
  130.       </method>
  131.  
  132.       <method name="reloadWithFlags">
  133.         <parameter name="aFlags"/>
  134.         <body>
  135.           <![CDATA[
  136.             this.webNavigation.reload(aFlags);
  137.           ]]>
  138.         </body>
  139.       </method>
  140.  
  141.       <method name="stop">
  142.         <body>
  143.           <![CDATA[
  144.             const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
  145.             const flags = nsIWebNavigation.STOP_ALL;
  146.             this.webNavigation.stop(flags);
  147.           ]]>
  148.         </body>
  149.       </method>
  150.  
  151.       <!-- throws exception for unknown schemes -->
  152.       <method name="loadURI">
  153.         <parameter name="aURI"/>
  154.         <parameter name="aReferrerURI"/>
  155.         <parameter name="aCharset"/>
  156.         <body>
  157.           <![CDATA[
  158.             const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
  159.             const flags = nsIWebNavigation.LOAD_FLAGS_NONE;
  160.             this.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset);
  161.           ]]>
  162.         </body>
  163.       </method>
  164.  
  165.       <!-- throws exception for unknown schemes -->
  166.       <method name="loadURIWithFlags">
  167.         <parameter name="aURI"/>
  168.         <parameter name="aFlags"/>
  169.         <parameter name="aReferrerURI"/>
  170.         <parameter name="aCharset"/>
  171.         <parameter name="aPostData"/>
  172.         <body>
  173.           <![CDATA[
  174.             if (!aURI)
  175.               aURI = "about:blank";
  176.  
  177.             if (aCharset) {
  178.               try { 
  179.                 this.documentCharsetInfo.parentCharset = this.mAtomService.getAtom(aCharset);
  180.               }
  181.               catch (e) {
  182.               }
  183.             }
  184.             try {
  185.               this.userTypedClear++;
  186.               this.webNavigation.loadURI(aURI, aFlags, aReferrerURI, aPostData, null);
  187.             } finally {
  188.               if (this.userTypedClear)
  189.                 this.userTypedClear--;
  190.             }
  191.           ]]>
  192.         </body>
  193.       </method>
  194.  
  195.       <method name="goHome">
  196.         <body>
  197.           <![CDATA[
  198.             try {
  199.               this.loadURI(this.homePage);
  200.             }
  201.             catch (e) {
  202.             }
  203.           ]]>
  204.         </body>
  205.       </method>
  206.  
  207.       <property name="homePage">
  208.         <getter>
  209.           <![CDATA[
  210.             var uri;
  211.  
  212.             if (this.hasAttribute("homepage"))
  213.               uri = this.getAttribute("homepage");
  214.             else
  215.               uri = "http://www.mozilla.org/"; // widget pride
  216.  
  217.             return uri;
  218.           ]]>
  219.         </getter>
  220.         <setter>
  221.           <![CDATA[
  222.             this.setAttribute("homepage", val);
  223.             return val;
  224.           ]]>
  225.         </setter>
  226.       </property>
  227.  
  228.       <method name="gotoIndex">
  229.         <parameter name="aIndex"/>
  230.         <body>
  231.           <![CDATA[
  232.             try {
  233.               this.userTypedClear++;
  234.               this.webNavigation.gotoIndex(aIndex);
  235.             } finally {
  236.               if (this.userTypedClear)
  237.                 this.userTypedClear--;
  238.             }
  239.           ]]>
  240.         </body>
  241.       </method>
  242.  
  243.       <property name="currentURI"
  244.                 onget="return this.webNavigation.currentURI;"
  245.                 readonly="true"/>
  246.  
  247.       <property name="preferences"
  248.                 onget="return Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefService);"
  249.                 readonly="true"/>
  250.  
  251.       <field name="_docShell">null</field>
  252.  
  253.       <property name="docShell"
  254.                 onget="return this._docShell || (this._docShell = this.boxObject.QueryInterface(Components.interfaces.nsIContainerBoxObject).docShell);"
  255.                 readonly="true"/>
  256.  
  257.       <property name="webNavigation"
  258.                 onget="return this.docShell.QueryInterface(Components.interfaces.nsIWebNavigation);"
  259.                 readonly="true"/>
  260.  
  261.       <field name="_webBrowserFind">null</field>
  262.  
  263.       <property name="webBrowserFind"
  264.                 readonly="true">
  265.         <getter>
  266.         <![CDATA[
  267.           if (!this._webBrowserFind)
  268.             this._webBrowserFind = this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebBrowserFind);
  269.           return this._webBrowserFind;
  270.         ]]>
  271.         </getter>
  272.       </property>
  273.  
  274.       <method name="getTabBrowser">
  275.         <body>
  276.           <![CDATA[
  277.             var tabBrowser = this.parentNode;
  278.             while (tabBrowser && tabBrowser.localName != "tabbrowser")
  279.               tabBrowser = tabBrowser.parentNode;
  280.             return tabBrowser;
  281.           ]]>
  282.         </body>
  283.       </method>
  284.  
  285.       <field name="_fastFind">null</field>
  286.       <property name="fastFind"
  287.                 readonly="true">
  288.         <getter>
  289.         <![CDATA[
  290.           if (!this._fastFind) {
  291.             if (!("@mozilla.org/typeaheadfind;1" in Components.classes))
  292.               return null;
  293.  
  294.             var tabBrowser = this.getTabBrowser();
  295.             if (tabBrowser)
  296.               return this._fastFind = tabBrowser.fastFind;
  297.  
  298.             if (!this.docShell)
  299.               return null;
  300.  
  301.             this._fastFind = Components.classes["@mozilla.org/typeaheadfind;1"]
  302.                                        .createInstance(Components.interfaces.nsITypeAheadFind);                                
  303.             this._fastFind.init(this.docShell);
  304.           }
  305.           return this._fastFind;
  306.         ]]>
  307.         </getter>
  308.       </property>
  309.       
  310.       <property name="webProgress"
  311.                 readonly="true"
  312.                 onget="return this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);"/>
  313.  
  314.       <property name="contentWindow"
  315.                 readonly="true"
  316.                 onget="return this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindow);"/>
  317.  
  318.       <property name="sessionHistory"
  319.                 onget="return this.webNavigation.sessionHistory;"
  320.                 readonly="true"/>
  321.  
  322.       <property name="markupDocumentViewer"
  323.                 onget="return this.docShell.contentViewer.QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);"
  324.                 readonly="true"/>
  325.  
  326.       <property name="contentViewerEdit"
  327.                 onget="return this.docShell.contentViewer.QueryInterface(Components.interfaces.nsIContentViewerEdit);"
  328.                 readonly="true"/>
  329.  
  330.       <property name="contentViewerFile"
  331.                 onget="return this.docShell.contentViewer.QueryInterface(Components.interfaces.nsIContentViewerFile);"
  332.                 readonly="true"/>
  333.  
  334.       <property name="documentCharsetInfo"
  335.                 onget="return this.docShell.documentCharsetInfo;"
  336.                 readonly="true"/>
  337.  
  338.       <property name="contentDocument"
  339.                 onget="return this.webNavigation.document;"
  340.                 readonly="true"/>
  341.  
  342.       <property name="contentTitle"
  343.                 onget="return this.contentDocument.title;"
  344.                 readonly="true"/>
  345.  
  346.       <property name="contentPrincipal"
  347.                 onget="return this.contentDocument.nodePrincipal;"
  348.                 readonly="true"/>
  349.  
  350.       <field name="mPrefs" readonly="true">
  351.         Components.classes['@mozilla.org/preferences-service;1']
  352.                   .getService(Components.interfaces.nsIPrefService)
  353.                   .getBranch(null);
  354.       </field>
  355.  
  356.       <field name="mAtomService" readonly="true">
  357.         Components.classes['@mozilla.org/atom-service;1']
  358.                   .getService(Components.interfaces.nsIAtomService);
  359.       </field>
  360.  
  361.       <field name="_mStrBundle">null</field>
  362.  
  363.       <property name="mStrBundle">
  364.         <getter>
  365.         <![CDATA[
  366.           if (!this._mStrBundle) {
  367.             // need to create string bundle manually instead of using <xul:stringbundle/>
  368.             // see bug 63370 for details
  369.             var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
  370.                                   .getService(Components.interfaces.nsILocaleService);
  371.             var stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"]
  372.                                   .getService(Components.interfaces.nsIStringBundleService);
  373.             var bundleURL = "chrome://global/locale/browser.properties";
  374.             this._mStrBundle = stringBundleService.createBundle(bundleURL, localeService.getApplicationLocale());
  375.           }
  376.           return this._mStrBundle;
  377.         ]]></getter>
  378.       </property>
  379.  
  380.       <method name="addProgressListener">
  381.         <parameter name="aListener"/>
  382.         <body>
  383.           <![CDATA[
  384.             this.webProgress.addProgressListener(aListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
  385.           ]]>
  386.         </body>
  387.       </method>
  388.  
  389.       <method name="removeProgressListener">
  390.         <parameter name="aListener"/>
  391.         <body>
  392.           <![CDATA[
  393.             this.webProgress.removeProgressListener(aListener);
  394.          ]]>
  395.         </body>
  396.       </method>
  397.  
  398.       <method name="attachFormFill">
  399.         <body>
  400.           <![CDATA[
  401.           if (!this.mFormFillAttached && this.hasAttribute("autocompletepopup")) {
  402.             // hoop up the form fill autocomplete controller
  403.             var controller = Components.classes["@mozilla.org/satchel/form-fill-controller;1"].
  404.                                getService(Components.interfaces.nsIFormFillController);
  405.  
  406.             var popup = document.getElementById(this.getAttribute("autocompletepopup"));
  407.             if (popup) {
  408.               controller.attachToBrowser(this.docShell, popup.QueryInterface(Components.interfaces.nsIAutoCompletePopup));
  409.               this.mFormFillAttached = true;
  410.             }
  411.           }
  412.           ]]>
  413.         </body>
  414.       </method>
  415.  
  416.       <method name="detachFormFill">
  417.         <body>
  418.           <![CDATA[
  419.           if (this.mFormFillAttached) {
  420.             // hoop up the form fill autocomplete controller
  421.             var controller = Components.classes["@mozilla.org/satchel/form-fill-controller;1"].
  422.                                getService(Components.interfaces.nsIFormFillController);
  423.             controller.detachFromBrowser(this.docShell);
  424.             
  425.             this.mFormFillAttached = false;
  426.           }
  427.           ]]>
  428.         </body>
  429.       </method>
  430.       
  431.       <method name="findChildShell">
  432.         <parameter name="aDocShell"/>
  433.         <parameter name="aSoughtURI"/>
  434.         <body>
  435.           <![CDATA[
  436.             if (aDocShell.QueryInterface(Components.interfaces.nsIWebNavigation)
  437.                          .currentURI.spec == aSoughtURI.spec)
  438.               return aDocShell;
  439.             var node = aDocShell.QueryInterface(
  440.                                    Components.interfaces.nsIDocShellTreeNode);
  441.             for (var i = 0; i < node.childCount; ++i) {
  442.               var docShell = node.getChildAt(i);
  443.               docShell = this.findChildShell(docShell, aSoughtURI);
  444.               if (docShell)
  445.                 return docShell;
  446.             }
  447.             return null;
  448.           ]]>
  449.         </body>
  450.       </method>
  451.  
  452.       <method name="onPageShow">
  453.         <parameter name="aEvent"/>
  454.         <body>
  455.           <![CDATA[
  456.             this.attachFormFill();
  457.             if (this.pageReport) {
  458.               var i = 0;
  459.               while (i < this.pageReport.length) {
  460.                 // Filter out irrelevant reports.
  461.                 if (this.pageReport[i].requestingWindow &&
  462.                     (this.pageReport[i].requestingWindow.document ==
  463.                      this.pageReport[i].requestingDocument))
  464.                   i++;
  465.                 else
  466.                   this.pageReport.splice(i, 1);
  467.               }
  468.               if (this.pageReport.length == 0) {
  469.                 this.pageReport = null;
  470.                 this.updatePageReport();
  471.               }
  472.             }
  473.          ]]>
  474.         </body>
  475.       </method>
  476.  
  477.       <method name="onPageHide">
  478.         <parameter name="aEvent"/>
  479.         <body>
  480.           <![CDATA[
  481.             if (this.pageReport) {
  482.               this.pageReport = null;
  483.               this.updatePageReport();
  484.             }
  485.             // Delete the feeds cache if we're hiding the topmost page
  486.             // (as opposed to one of its iframes).
  487.             if (this.feeds && aEvent.target == this.contentDocument)
  488.               this.feeds = null;
  489.             if (!this.docShell || !this.fastFind)
  490.               return;
  491.             var tabBrowser = this.getTabBrowser();
  492.             if (!tabBrowser || tabBrowser.mCurrentBrowser == this)
  493.               this.fastFind.setDocShell(this.docShell);
  494.  
  495.             if (this._scrollingView)
  496.               this._autoScrollPopup.hidePopup();
  497.          ]]>
  498.         </body>
  499.       </method>
  500.  
  501.       <method name="updatePageReport">
  502.         <body>
  503.           <![CDATA[
  504.             var event = document.createEvent("Events");
  505.             event.initEvent("DOMUpdatePageReport", true, true);
  506.             this.dispatchEvent(event);
  507.           ]]>
  508.         </body>
  509.       </method>
  510.  
  511.       <method name="onPopupBlocked">
  512.         <parameter name="evt"/>
  513.         <body>
  514.           <![CDATA[
  515.             if (!this.pageReport) {
  516.               this.pageReport = new Array();
  517.             }
  518.  
  519.             var obj = { requestingWindow: evt.requestingWindow,
  520.                         // Record the current document in the requesting window
  521.                         // before it can change.
  522.                         requestingDocument: evt.requestingWindow.document,
  523.                         popupWindowURI: evt.popupWindowURI,
  524.                         popupWindowFeatures: evt.popupWindowFeatures,
  525.                         popupWindowName: evt.popupWindowName };
  526.  
  527.             this.pageReport.push(obj);
  528.             this.pageReport.reported = false;
  529.             this.updatePageReport();
  530.           ]]> 
  531.         </body>
  532.       </method>
  533.  
  534.       <field name="pageReport">null</field>
  535.  
  536.       <field name="mDragDropHandler">
  537.         null
  538.       </field>
  539.  
  540.       <property name="securityUI">
  541.         <getter>
  542.           <![CDATA[
  543.             if (!this.docShell.securityUI) {
  544.               const SECUREBROWSERUI_CONTRACTID = "@mozilla.org/secure_browser_ui;1";
  545.               if (!this.hasAttribute("disablesecurity") &&
  546.                   SECUREBROWSERUI_CONTRACTID in Components.classes) {
  547.                 var securityUI = Components.classes[SECUREBROWSERUI_CONTRACTID]
  548.                                            .createInstance(Components.interfaces.nsISecureBrowserUI);
  549.                 securityUI.init(this.contentWindow);
  550.               }
  551.             }
  552.             
  553.             return this.docShell.securityUI;
  554.           ]]>
  555.         </getter>
  556.         <setter>
  557.           <![CDATA[
  558.             this.docShell.securityUI = val;
  559.           ]]>
  560.         </setter>
  561.       </property>
  562.  
  563.       <!--
  564.         This field tracks the location bar state. The value that the user typed
  565.         in to the location bar may not be changed while this field is zero.
  566.         However invoking a load will temporarily increase this field to allow
  567.         the location bar to be updated to the new URL.
  568.  
  569.         Case 1: Anchor scroll
  570.           The user appends the anchor to the URL. This sets the location bar
  571.           into typed state, and disables changes to the location bar. The user
  572.           then requests the scroll. loadURIWithFlags temporarily increases the
  573.           flag by 1 so that the anchor scroll's location change resets the
  574.           location bar state.
  575.  
  576.         Case 2: Interrupted load
  577.           The user types in and submits the URL. This triggers an asynchronous
  578.           network load which increases the flag by 2. (The temporary increase
  579.           from loadURIWithFlags is not noticeable in this case.) When the load
  580.           is interrupted the flag returns to zero, and the location bar stays
  581.           in typed state.
  582.  
  583.         Case 3: New load
  584.           This works like case 2, but as the load is not interrupted the
  585.           location changes while the flag is still 2 thus resetting the
  586.           location bar state.
  587.  
  588.         Case 4: Corrected load
  589.           This is a combination of case 2 and case 3, except that the original
  590.           load is interrupted by the new load. Normally cancelling and starting
  591.           a new load would reset the flag to 0 and then increase it to 2 again.
  592.           However both actions occur as a consequence of the loadURIWithFlags
  593.           invocation, which adds its temporary increase in to the mix. Since
  594.           the new URL would have been typed in the flag would have been reset
  595.           before loadURIWithFlags incremented it. The interruption resets the
  596.           flag to 0 and increases it to 2. Although loadURIWithFlags will
  597.           decrement the flag it remains at 1 thus allowing the location bar
  598.           state to be reset when the new load changes the location.
  599.           This case also applies when loading into a new browser, as this
  600.           interrupts the default load of about:blank.
  601.       -->
  602.       <field name="userTypedClear">
  603.         1
  604.       </field>
  605.  
  606.       <field name="_userTypedValue">
  607.         null
  608.       </field>
  609.  
  610.       <property name="userTypedValue"
  611.                 onget="return this._userTypedValue;"
  612.                 onset="this.userTypedClear = 0; return this._userTypedValue = val;"/>
  613.  
  614.       <field name="mFormFillAttached">
  615.         false
  616.       </field>
  617.       
  618.       <field name="focusedWindow">
  619.         null
  620.       </field>
  621.  
  622.       <field name="focusedElement">
  623.         null
  624.       </field>
  625.       
  626.       <field name="isShowingMessage">
  627.         false
  628.       </field>
  629.  
  630.       <field name="mIconURL">null</field>
  631.  
  632.       <field name="mDestroyed">false</field>
  633.  
  634.       <constructor>
  635.         <![CDATA[
  636.           try {
  637.             if (!this.hasAttribute("disablehistory")) {
  638.               var os = Components.classes["@mozilla.org/observer-service;1"]
  639.                                  .getService(Components.interfaces.nsIObserverService);
  640.               os.addObserver(this, "browser:purge-session-history", false);
  641.               // wire up session history
  642.               this.webNavigation.sessionHistory = 
  643.                       Components.classes["@mozilla.org/browser/shistory;1"]
  644.                                 .createInstance(Components.interfaces.nsISHistory);
  645.               // enable global history
  646.               this.docShell.QueryInterface(Components.interfaces.nsIDocShellHistory).useGlobalHistory = true;
  647.             }
  648.           }
  649.           catch (e) {
  650.             Components.utils.reportError(e);
  651.           }
  652.           try {
  653.             this.mDragDropHandler = Components.classes["@mozilla.org:/content/content-area-dragdrop;1"].createInstance(Components.interfaces.nsIDragDropHandler);
  654.             this.mDragDropHandler.hookupTo(this, null);
  655.           }
  656.           catch (e) {
  657.           }
  658.           try {
  659.             var securityUI = this.securityUI;
  660.           }
  661.           catch (e) {
  662.           }
  663.  
  664.           // Listen for first load for lazy attachment to form fill controller
  665.           this.addEventListener("pageshow", this.onPageShow, true);
  666.           this.addEventListener("pagehide", this.onPageHide, true);
  667.           this.addEventListener("DOMPopupBlocked", this.onPopupBlocked, true);
  668.         ]]>
  669.       </constructor>
  670.       
  671.       <destructor>
  672.         <![CDATA[
  673.           this.destroy();
  674.         ]]>
  675.       </destructor>
  676.  
  677.       <!-- This is necessary because the destructor doesn't always get called when
  678.            we are removed from a tabbrowser. This will be explicitly called by tabbrowser -->
  679.       <method name="destroy">
  680.         <body>
  681.           <![CDATA[
  682.           if (this.mDestroyed)
  683.             return;
  684.           this.mDestroyed = true;
  685.  
  686.           if (!this.hasAttribute("disablehistory")) {
  687.             var os = Components.classes["@mozilla.org/observer-service;1"]
  688.                                .getService(Components.interfaces.nsIObserverService);
  689.             try {
  690.               os.removeObserver(this, "browser:purge-session-history");
  691.             } catch (ex) {
  692.               // It's not clear why this sometimes throws an exception.
  693.             }
  694.           }
  695.  
  696.           if (this.mDragDropHandler)
  697.             this.mDragDropHandler.detach();
  698.           this.mDragDropHandler = null;
  699.  
  700.           this.detachFormFill();
  701.           
  702.           this._fastFind = null;
  703.           this._webBrowserFind = null;
  704.  
  705.           this.removeEventListener("pageshow", this.onPageShow, true);
  706.           this.removeEventListener("pagehide", this.onPageHide, true);
  707.           this.removeEventListener("DOMPopupBlocked", this.onPopupBlocked, true);
  708.  
  709.           if (this._autoScrollNeedsCleanup) {
  710.             // we polluted the global scope, so clean it up
  711.             this._autoScrollPopup.parentNode.removeChild(this._autoScrollPopup);
  712.           }
  713.           ]]>
  714.         </body>
  715.       </method>
  716.       
  717.       <method name="observe">
  718.         <parameter name="aSubject"/>
  719.         <parameter name="aTopic"/>
  720.         <parameter name="aState"/>
  721.         <body>
  722.           <![CDATA[
  723.             if (aTopic != "browser:purge-session-history" || !this.sessionHistory)
  724.               return;
  725.               
  726.             // place the entry at current index at the end of the history list, so it won't get removed
  727.             if (this.sessionHistory.index < this.sessionHistory.count - 1) {
  728.               var indexEntry = this.sessionHistory.getEntryAtIndex(this.sessionHistory.index, false);
  729.               this.sessionHistory.QueryInterface(Components.interfaces.nsISHistoryInternal);
  730.               indexEntry.QueryInterface(Components.interfaces.nsISHEntry);
  731.               this.sessionHistory.addEntry(indexEntry, true);
  732.             }
  733.             
  734.             var purge = this.sessionHistory.count;
  735.             if (this.currentURI != "about:blank")
  736.               --purge; // Don't remove the page the user's staring at from shistory
  737.             
  738.             if (purge > 0)
  739.               this.sessionHistory.PurgeHistory(purge);
  740.           ]]>
  741.         </body>
  742.       </method>
  743.           
  744.       <field name="_AUTOSCROLL_SPEED">3</field>
  745.       <field name="_AUTOSCROLL_SNAP">10</field>
  746.       <field name="_scrollingView">null</field>
  747.       <field name="_autoScrollTimer">null</field>
  748.       <field name="_startX">null</field>
  749.       <field name="_startY">null</field>
  750.       <field name="_screenX">null</field>
  751.       <field name="_screenY">null</field>
  752.       <field name="_autoScrollPopup">null</field>
  753.       <field name="_autoScrollNeedsCleanup">false</field>
  754.  
  755.       <method name="stopScroll">
  756.         <body>
  757.           <![CDATA[
  758.             if (this._scrollingView) {
  759.               this._scrollingView = null;
  760.               window.removeEventListener("mousemove", this, true);
  761.               window.removeEventListener("mousedown", this, true);
  762.               window.removeEventListener("mouseup", this, true);
  763.               window.removeEventListener("contextmenu", this, true);
  764.               clearInterval(this._autoScrollTimer);
  765.             }
  766.          ]]>
  767.        </body>
  768.      </method>
  769.  
  770.       <method name="_createAutoScrollPopup">
  771.         <body>
  772.           <![CDATA[
  773.             const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  774.             var popup = document.createElementNS(XUL_NS, "popup");
  775.             popup.id = "autoscroller";
  776.             return popup;
  777.           ]]>
  778.         </body>
  779.       </method>
  780.      
  781.       <method name="startScroll">
  782.         <parameter name="event"/>
  783.         <body>
  784.           <![CDATA[
  785.             if (!this._autoScrollPopup) {
  786.               if (this.hasAttribute("autoscrollpopup")) {
  787.                 // our creator provided a popup to share
  788.                 this._autoScrollPopup = document.getElementById(this.getAttribute("autoscrollpopup"));
  789.               }
  790.               else {
  791.                 // we weren't provided a popup; we have to use the global scope
  792.                 this._autoScrollPopup = this._createAutoScrollPopup();
  793.                 document.documentElement.appendChild(this._autoScrollPopup);
  794.                 this._autoScrollNeedsCleanup = true;
  795.               }
  796.             }
  797.  
  798.             this._autoScrollPopup.addEventListener("popuphidden", this, true);
  799.  
  800.             // we need these attributes so themers don't need to create per-platform packages
  801.             if (screen.colorDepth > 8) { // need high color for transparency
  802.               // Exclude second-rate platforms
  803.               this._autoScrollPopup.setAttribute("transparent", !/BeOS|OS\/2|Photon/.test(navigator.appVersion));
  804.               // Enable translucency on Windows and Mac
  805.               this._autoScrollPopup.setAttribute("translucent", /Win|Mac/.test(navigator.platform));
  806.             }
  807.  
  808.             this._scrollingView = event.originalTarget.ownerDocument.defaultView;
  809.             if (this._scrollingView.scrollMaxX > 0) {
  810.               this._autoScrollPopup.setAttribute("scrolldir", this._scrollingView.scrollMaxY > 0 ? "NSEW" : "EW");
  811.             }
  812.             else if (this._scrollingView.scrollMaxY > 0) {
  813.               this._autoScrollPopup.setAttribute("scrolldir", "NS");
  814.             }
  815.             else {
  816.               this._scrollingView = null; // abort scrolling
  817.               return;
  818.             }
  819.  
  820.             document.popupNode = null;
  821.             this._autoScrollPopup.showPopup(document.documentElement,
  822.                                             event.screenX,
  823.                                             event.screenY,
  824.                                             "popup", null, null);
  825.             this._ignoreMouseEvents = true;
  826.             this._startX = event.screenX;
  827.             this._startY = event.screenY;
  828.             this._screenX = event.screenX;
  829.             this._screenY = event.screenY;
  830.  
  831.             window.addEventListener("mousemove", this, true);
  832.             window.addEventListener("mousedown", this, true);
  833.             window.addEventListener("mouseup", this, true);
  834.             window.addEventListener("contextmenu", this, true);
  835.  
  836.             this._scrollErrorX = 0;
  837.             this._scrollErrorY = 0;
  838.  
  839.             this._autoScrollTimer = setInterval(function(self) { self.autoScrollLoop(); },
  840.                                                 20, this);
  841.          ]]>
  842.        </body>
  843.      </method>
  844.  
  845.      <method name="_roundToZero">
  846.        <parameter name="num"/>
  847.        <body>
  848.          <![CDATA[
  849.             if (num > 0)
  850.               return Math.floor(num);
  851.             return Math.ceil(num);
  852.          ]]>
  853.        </body>
  854.      </method>
  855.  
  856.      <method name="_accelerate">
  857.        <parameter name="curr"/>
  858.        <parameter name="start"/>
  859.        <body>
  860.          <![CDATA[
  861.             const speed = 12;
  862.             var val = (curr - start) / speed;
  863.  
  864.             if (val > 1)
  865.               return val * Math.sqrt(val) - 1;
  866.             if (val < -1)
  867.               return val * Math.sqrt(-val) + 1;
  868.             return 0;
  869.          ]]>
  870.        </body>
  871.      </method>
  872.  
  873.      <method name="autoScrollLoop">
  874.        <body>
  875.          <![CDATA[
  876.            var x = this._accelerate(this._screenX, this._startX);
  877.            var y = this._accelerate(this._screenY, this._startY);
  878.  
  879.            var desiredScrollX = this._scrollErrorX + x;
  880.            var actualScrollX = this._roundToZero(desiredScrollX);
  881.            this._scrollErrorX = (desiredScrollX - actualScrollX);
  882.            var desiredScrollY = this._scrollErrorY + y;
  883.            var actualScrollY = this._roundToZero(desiredScrollY);
  884.            this._scrollErrorY = (desiredScrollY - actualScrollY);
  885.  
  886.            this._scrollingView.scrollBy(actualScrollX, actualScrollY);
  887.          ]]>
  888.        </body>
  889.      </method>
  890.      <method name="isAutoscrollBlocker">
  891.        <parameter name="node"/>
  892.        <body>
  893.          <![CDATA[
  894.            var mmPaste = false;
  895.            var mmScrollbarPosition = false;
  896.  
  897.            try {
  898.              mmPaste = this.mPrefs.getBoolPref("middlemouse.paste");
  899.            }
  900.            catch (ex) {
  901.            }
  902.  
  903.            try {
  904.              mmScrollbarPosition = this.mPrefs.getBoolPref("middlemouse.scrollbarPosition");
  905.            }
  906.            catch (ex) {
  907.            }
  908.  
  909.            while (node) {
  910.              if ((node instanceof HTMLAnchorElement || node instanceof HTMLAreaElement) && node.hasAttribute("href"))
  911.                return true;
  912.  
  913.              if (mmPaste && (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement))
  914.                return true;
  915.  
  916.              if (node instanceof XULElement && mmScrollbarPosition
  917.                  && (node.localName == "scrollbar" || node.localName == "scrollcorner"))
  918.                return true;
  919.  
  920.              node = node.parentNode;
  921.            }
  922.            return false;
  923.          ]]>
  924.        </body>
  925.      </method>
  926.  
  927.       <method name="handleEvent">
  928.         <parameter name="aEvent"/>
  929.         <body>
  930.         <![CDATA[
  931.           if (this._scrollingView) {
  932.             switch(aEvent.type) {
  933.               case "mousemove": {
  934.                 this._screenX = aEvent.screenX;
  935.                 this._screenY = aEvent.screenY;
  936.  
  937.                 var x = this._screenX - this._startX;
  938.                 var y = this._screenY - this._startY;
  939.         
  940.                 if ((x > this._AUTOSCROLL_SNAP || x < -this._AUTOSCROLL_SNAP) ||
  941.                     (y > this._AUTOSCROLL_SNAP || y < -this._AUTOSCROLL_SNAP))
  942.                   this._ignoreMouseEvents = false;
  943.                 break;
  944.               }
  945.               case "mouseup":
  946.               case "mousedown":
  947.               case "contextmenu": {
  948.                 if (!this._ignoreMouseEvents)
  949.                   this._autoScrollPopup.hidePopup();
  950.                 this._ignoreMouseEvents = false;
  951.                 break;
  952.               }
  953.               case "popuphidden": {
  954.                 this._autoScrollPopup.removeEventListener("popuphidden", this, true);
  955.                 this.stopScroll();
  956.                 break;
  957.               }
  958.             }
  959.           }
  960.         ]]>
  961.         </body>
  962.       </method>
  963.     </implementation>
  964.  
  965.     <handlers>
  966.       <handler event="keypress" keycode="VK_F7" group="system">
  967.         <![CDATA[
  968.           if (event.getPreventDefault() || !event.isTrusted)
  969.             return;
  970.  
  971.           // Toggle browse with caret mode
  972.           var browseWithCaretOn = false;
  973.           var warn = true;
  974.  
  975.           try {
  976.             warn = this.mPrefs.getBoolPref("accessibility.warn_on_browsewithcaret");
  977.           } catch (ex) {
  978.           }
  979.  
  980.           try {
  981.             browseWithCaretOn = this.mPrefs.getBoolPref("accessibility.browsewithcaret");
  982.           } catch (ex) {
  983.           }
  984.           if (warn && !browseWithCaretOn) {
  985.             var checkValue = {value:false};
  986.             promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
  987.  
  988.             var buttonPressed = promptService.confirmEx(window, 
  989.               this.mStrBundle.GetStringFromName('browsewithcaret.checkWindowTitle'), 
  990.               this.mStrBundle.GetStringFromName('browsewithcaret.checkLabel'),
  991.               promptService.STD_YES_NO_BUTTONS,
  992.               null, null, null, this.mStrBundle.GetStringFromName('browsewithcaret.checkMsg'),
  993.               checkValue);
  994.             if (buttonPressed != 0)
  995.               return;
  996.             if (checkValue.value) {
  997.               try {
  998.                 this.mPrefs.setBoolPref("accessibility.warn_on_browsewithcaret", false);
  999.               }
  1000.               catch (ex) {
  1001.               }
  1002.             }
  1003.           }
  1004.  
  1005.           // Toggle the pref
  1006.           try {
  1007.             this.mPrefs.setBoolPref("accessibility.browsewithcaret",!browseWithCaretOn);
  1008.           } catch (ex) {
  1009.           }
  1010.         ]]>
  1011.       </handler>
  1012.       <handler event="mousedown" phase="capturing">
  1013.         <![CDATA[
  1014.           if (!this._scrollingView && event.button == 1) {
  1015.             if (!this.autoscrollEnabled  ||
  1016.                 this.currentURI.spec == "about:blank"|| 
  1017.                 this.isAutoscrollBlocker(event.originalTarget))
  1018.               return;
  1019.  
  1020.             this.startScroll(event);
  1021.           }
  1022.         ]]>
  1023.       </handler>
  1024.     </handlers>
  1025.  
  1026.   </binding>
  1027.  
  1028. </bindings>
  1029.