home *** CD-ROM | disk | FTP | other *** search
/ ftp.swcp.com / ftp.swcp.com.zip / ftp.swcp.com / mac / mozilla-macos9-1.3.1.sea.bin / Mozilla1.3.1 / Chrome / comm.jar / content / navigator / nsBrowserStatusHandler.js < prev    next >
Text File  |  2003-06-08  |  15KB  |  438 lines

  1. /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: NPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Netscape Public License
  6.  * Version 1.1 (the "License"); you may not use this file except in
  7.  * compliance with the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/NPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is mozilla.org code.
  16.  *
  17.  * The Initial Developer of the Original Code is 
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 1998
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *   Blake Ross <blakeross@telocity.com>
  24.  *   Peter Annema <disttsc@bart.nl>
  25.  *
  26.  * Alternatively, the contents of this file may be used under the terms of
  27.  * either the GNU General Public License Version 2 or later (the "GPL"), or 
  28.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29.  * in which case the provisions of the GPL or the LGPL are applicable instead
  30.  * of those above. If you wish to allow use of your version of this file only
  31.  * under the terms of either the GPL or the LGPL, and not to allow others to
  32.  * use your version of this file under the terms of the NPL, indicate your
  33.  * decision by deleting the provisions above and replace them with the notice
  34.  * and other provisions required by the GPL or the LGPL. If you do not delete
  35.  * the provisions above, a recipient may use your version of this file under
  36.  * the terms of any one of the NPL, the GPL or the LGPL.
  37.  *
  38.  * ***** END LICENSE BLOCK ***** */
  39.  
  40. function nsBrowserStatusHandler()
  41. {
  42.   this.init();
  43. }
  44.  
  45. nsBrowserStatusHandler.prototype =
  46. {
  47.   userTyped :
  48.   {
  49.     _value : false,
  50.     browser : null,
  51.  
  52.     get value() {
  53.       if (this.browser != getBrowser().mCurrentBrowser)
  54.         this._value = false;
  55.       
  56.       return this._value;
  57.     },
  58.  
  59.     set value(aValue) {
  60.       if (this._value != aValue) {
  61.         this._value = aValue;
  62.         this.browser = aValue ? getBrowser().mCurrentBrowser : null;
  63.       }
  64.  
  65.       return aValue;
  66.     }
  67.   },
  68.  
  69.   // Stored Status, Link and Loading values
  70.   status : "",
  71.   defaultStatus : "",
  72.   jsStatus : "",
  73.   jsDefaultStatus : "",
  74.   overLink : "",
  75.  
  76.   hideAboutBlank : true,
  77.  
  78.   locationChanged : false,  
  79.  
  80.   QueryInterface : function(aIID)
  81.   {
  82.     if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
  83.         aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
  84.         aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
  85.         aIID.equals(Components.interfaces.nsISupports))
  86.       return this;
  87.     throw Components.results.NS_NOINTERFACE;
  88.   },
  89.  
  90.   init : function()
  91.   {
  92.     this.urlBar          = document.getElementById("urlbar");
  93.     this.throbberElement = document.getElementById("navigator-throbber");
  94.     this.statusMeter     = document.getElementById("statusbar-icon");
  95.     this.stopButton      = document.getElementById("stop-button");
  96.     this.stopMenu        = document.getElementById("menuitem-stop");
  97.     this.stopContext     = document.getElementById("context-stop");
  98.     this.statusTextField = document.getElementById("statusbar-display");
  99.     this.isImage         = document.getElementById("isImage");
  100.     this.securityButton  = document.getElementById("security-button");
  101.  
  102.     // Initialize the security button's state and tooltip text
  103.     const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
  104.     this.onSecurityChange(null, null, nsIWebProgressListener.STATE_IS_INSECURE);
  105.   },
  106.  
  107.   destroy : function()
  108.   {
  109.     // XXXjag to avoid leaks :-/, see bug 60729
  110.     this.urlBar          = null;
  111.     this.throbberElement = null;
  112.     this.statusMeter     = null;
  113.     this.stopButton      = null;
  114.     this.stopMenu        = null;
  115.     this.stopContext     = null;
  116.     this.statusTextField = null;
  117.     this.isImage         = null;
  118.     this.securityButton  = null;
  119.     this.userTyped       = null;
  120.   },
  121.  
  122.   setJSStatus : function(status)
  123.   {
  124.     this.jsStatus = status;
  125.     this.updateStatusField();
  126.   },
  127.  
  128.   setJSDefaultStatus : function(status)
  129.   {
  130.     this.jsDefaultStatus = status;
  131.     this.updateStatusField();
  132.   },
  133.  
  134.   setDefaultStatus : function(status)
  135.   {
  136.     this.defaultStatus = status;
  137.     this.updateStatusField();
  138.   },
  139.  
  140.   setOverLink : function(link)
  141.   {
  142.     this.overLink = link;
  143.     // clear out 'Done' (or other message) on first hover
  144.     if (this.defaultStatus)
  145.       this.defaultStatus = "";
  146.     this.updateStatusField();
  147.     if (link)
  148.       this.statusTextField.setAttribute('crop', 'center');
  149.     else
  150.       this.statusTextField.setAttribute('crop', 'end');
  151.   },
  152.  
  153.   updateStatusField : function()
  154.   {
  155.     var text = this.overLink || this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
  156.  
  157.     // check the current value so we don't trigger an attribute change
  158.     // and cause needless (slow!) UI updates
  159.     if (this.statusTextField.label != text)
  160.       this.statusTextField.label = text;
  161.   },
  162.  
  163.   mimeTypeIsTextBased : function(contentType)
  164.   {
  165.     return /^text\/|\+xml$/.test(contentType) ||
  166.            contentType == "application/x-javascript" ||
  167.            contentType == "application/xml" ||
  168.            contentType == "mozilla.application/cached-xul";
  169.   },
  170.  
  171.   onLinkIconAvailable : function(aHref) {
  172.     if (gProxyFavIcon && pref.getBoolPref("browser.chrome.site_icons"))
  173.     {
  174.       gProxyFavIcon.setAttribute("src", aHref);
  175.  
  176.       // update any bookmarks with new icon reference
  177.       if (!gBookmarksService)
  178.         gBookmarksService = Components.classes["@mozilla.org/browser/bookmarks-service;1"]
  179.                                       .getService(Components.interfaces.nsIBookmarksService);
  180.       gBookmarksService.updateBookmarkIcon(this.urlBar.value, aHref);
  181.     }
  182.   },
  183.  
  184.   onProgressChange : function (aWebProgress, aRequest,
  185.                                aCurSelfProgress, aMaxSelfProgress,
  186.                                aCurTotalProgress, aMaxTotalProgress)
  187.   {
  188.     if (aMaxTotalProgress > 0) {
  189.       // This is highly optimized.  Don't touch this code unless
  190.       // you are intimately familiar with the cost of setting
  191.       // attrs on XUL elements. -- hyatt
  192.       var percentage = (aCurTotalProgress * 100) / aMaxTotalProgress;
  193.       this.statusMeter.value = percentage;
  194.     } 
  195.   },
  196.  
  197.   onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
  198.   {  
  199.     const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
  200.     const nsIChannel = Components.interfaces.nsIChannel;
  201.     var ctype;
  202.     if (aStateFlags & nsIWebProgressListener.STATE_START) {
  203.       // This (thanks to the filter) is a network start or the first
  204.       // stray request (the first request outside of the document load),
  205.       // initialize the throbber and his friends.
  206.  
  207.       // Call start document load listeners (only if this is a network load)
  208.       if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK &&
  209.           aRequest && aWebProgress.DOMWindow == content)
  210.         this.startDocumentLoad(aRequest);
  211.  
  212.       // Turn the throbber on.
  213.       this.throbberElement.setAttribute("busy", "true");
  214.  
  215.       // XXX: These need to be based on window activity...
  216.       this.stopButton.disabled = false;
  217.       this.stopMenu.removeAttribute('disabled');
  218.       this.stopContext.removeAttribute('disabled');
  219.  
  220.       this.locationChanged = false;        
  221.     }
  222.     else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
  223.       if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
  224.         if (aRequest) {
  225.           if (aWebProgress.DOMWindow == content)
  226.             this.endDocumentLoad(aRequest, aStatus);
  227.         }
  228.       }
  229.  
  230.       // This (thanks to the filter) is a network stop or the last
  231.       // request stop outside of loading the document, stop throbbers
  232.       // and progress bars and such
  233.       if (aRequest) {
  234.         var msg = "";
  235.         // Get the channel if the request is a channel
  236.         var channel;
  237.         try {
  238.           channel = aRequest.QueryInterface(nsIChannel);
  239.         }
  240.         catch(e) { };
  241.  
  242.         if (channel) {
  243.           var location = channel.URI.spec;
  244.           if (location != "about:blank") {
  245.             const kErrorBindingAborted = 2152398850;
  246.             const kErrorNetTimeout = 2152398862;
  247.             switch (aStatus) {
  248.               case kErrorBindingAborted:
  249.                 msg = gNavigatorBundle.getString("nv_stopped");
  250.                 break;
  251.               case kErrorNetTimeout:
  252.                 msg = gNavigatorBundle.getString("nv_timeout");
  253.                 break;
  254.             }
  255.           }
  256.         }
  257.         // If msg is false then we did not have an error (channel may have
  258.         // been null, in the case of a stray image load).
  259.         if (!msg) {
  260.           msg = gNavigatorBundle.getString("nv_done");
  261.         }
  262.         this.status = "";
  263.         this.setDefaultStatus(msg);
  264.         
  265.         //if the location hasn't been changed, the document may be null(eg a full-page plugin),
  266.         //we may not be able to get the correct content-type. 
  267.         //so we need to skip the test and keep the menu status.
  268.         //otherwise(this.locationChanged = true), test normally.
  269.         if (channel && this.locationChanged) {
  270.           try {
  271.             ctype = channel.contentType;
  272.             if (this.mimeTypeIsTextBased(ctype))
  273.               this.isImage.removeAttribute('disabled');
  274.             else
  275.               this.isImage.setAttribute('disabled', 'true');
  276.           }
  277.           catch (e) {}
  278.         }
  279.       }
  280.  
  281.       // Turn the progress meter and throbber off.
  282.       this.statusMeter.value = 0;  // be sure to clear the progress bar
  283.       this.throbberElement.removeAttribute("busy");
  284.  
  285.       // XXX: These need to be based on window activity...
  286.       // XXXjag: <command id="cmd_stop"/> ?
  287.       this.stopButton.disabled = true;
  288.       this.stopMenu.setAttribute('disabled', 'true');
  289.       this.stopContext.setAttribute('disabled', 'true');
  290.     }
  291.   },
  292.  
  293.   onLocationChange : function(aWebProgress, aRequest, aLocation)
  294.   {
  295.     this.setOverLink("");
  296.  
  297.     var location = "";
  298.  
  299.     if (aLocation) {
  300.       try {
  301.         if (!gURIFixup)
  302.           gURIFixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
  303.                                 .getService(Components.interfaces.nsIURIFixup);
  304.         // If the url has "wyciwyg://" as the protocol, strip it off.
  305.         // Nobody wants to see it on the urlbar for dynamically generated
  306.         // pages.
  307.         location = gURIFixup.createExposableURI(aLocation).spec;
  308.       }
  309.       catch(ex) {
  310.         location = aLocation.spec;
  311.       }
  312.     }
  313.  
  314.     if (this.hideAboutBlank) {
  315.       this.hideAboutBlank = false;
  316.       if (location == "about:blank")
  317.         location = "";
  318.     }
  319.  
  320.     // Disable menu entries for images, enable otherwise
  321.     if (content.document && this.mimeTypeIsTextBased(content.document.contentType))
  322.       this.isImage.removeAttribute('disabled');
  323.     else
  324.       this.isImage.setAttribute('disabled', 'true');
  325.  
  326.     // We should probably not do this if the value has changed since the user
  327.     // searched
  328.     // Update urlbar only if a new page was loaded on the primary content area
  329.     // Do not update urlbar if there was a subframe navigation
  330.  
  331.     if (aWebProgress.DOMWindow == content) {
  332.       if (!this.userTyped.value) {
  333.         this.urlBar.value = location;
  334.         // the above causes userTyped.value to become true, reset it
  335.         this.userTyped.value = false;
  336.       }
  337.  
  338.       SetPageProxyState("valid", aLocation);
  339.     }
  340.     UpdateBackForwardButtons();
  341.  
  342.     var blank = (location == "about:blank") || (location == "");
  343.     var browser = getBrowser().mCurrentBrowser;
  344.  
  345.     //clear popupDomain accordingly so that icon will go away when visiting
  346.     //an unblocked site after a blocked site. note: if a popup is blocked 
  347.     //the icon will stay as long as we are in the same domain.
  348.     if (blank ||
  349.         !("popupDomain" in browser) ||
  350.         aLocation.hostPort != browser.popupDomain) {
  351.       browser.popupDomain = null;
  352.     }
  353.  
  354.     var popupIcon = document.getElementById("popupIcon");
  355.     popupIcon.hidden = !browser.popupDomain;
  356.  
  357.     this.locationChanged = true;    
  358.   },
  359.  
  360.   onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
  361.   {
  362.     this.status = aMessage;
  363.     this.updateStatusField();
  364.   },
  365.  
  366.   onSecurityChange : function(aWebProgress, aRequest, aState)
  367.   {
  368.     const wpl = Components.interfaces.nsIWebProgressListener;
  369.  
  370.     switch (aState) {
  371.       case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_HIGH:
  372.         this.securityButton.setAttribute("level", "high");
  373.         break;
  374.       case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_LOW:
  375.         this.securityButton.setAttribute("level", "low");
  376.         break;
  377.       case wpl.STATE_IS_BROKEN:
  378.         this.securityButton.setAttribute("level", "broken");
  379.         break;
  380.       case wpl.STATE_IS_INSECURE:
  381.       default:
  382.         this.securityButton.removeAttribute("level");
  383.         break;
  384.     }
  385.  
  386.     var securityUI = getBrowser().securityUI;
  387.     if (securityUI)
  388.       this.securityButton.setAttribute("tooltiptext", securityUI.tooltipText);
  389.     else
  390.       this.securityButton.removeAttribute("tooltiptext");
  391.   },
  392.  
  393.   startDocumentLoad : function(aRequest)
  394.   {
  395.     // Reset so we can see if the user typed after the document load
  396.     // starting and the location changing.
  397.     this.userTyped.value = false;
  398.  
  399.     const nsIChannel = Components.interfaces.nsIChannel;
  400.     var urlStr = aRequest.QueryInterface(nsIChannel).URI.spec;
  401.     var observerService = Components.classes["@mozilla.org/observer-service;1"]
  402.                                     .getService(Components.interfaces.nsIObserverService);
  403.     try {
  404.       observerService.notifyObservers(_content, "StartDocumentLoad", urlStr);
  405.     } catch (e) {
  406.     }
  407.   },
  408.  
  409.   endDocumentLoad : function(aRequest, aStatus)
  410.   {
  411.     const nsIChannel = Components.interfaces.nsIChannel;
  412.     var urlStr = aRequest.QueryInterface(nsIChannel).originalURI.spec;
  413.  
  414.     if (Components.isSuccessCode(aStatus))
  415.       dump("Document "+urlStr+" loaded successfully\n"); // per QA request
  416.     else {
  417.       // per QA request
  418.       var e = new Components.Exception("", aStatus);
  419.       var name = e.name;
  420.       dump("Error loading URL "+urlStr+" : "+
  421.            Number(aStatus).toString(16));
  422.       if (name)
  423.            dump(" ("+name+")");
  424.       dump('\n'); 
  425.     }
  426.  
  427.     var observerService = Components.classes["@mozilla.org/observer-service;1"]
  428.                                     .getService(Components.interfaces.nsIObserverService);
  429.  
  430.     var notification = Components.isSuccessCode(aStatus) ? "EndDocumentLoad" : "FailDocumentLoad";
  431.     try {
  432.       observerService.notifyObservers(_content, notification, urlStr);
  433.     } catch (e) {
  434.     }
  435.   }
  436. }
  437.  
  438.