Move browser's nsIWebProgressListener implementation into js. More work for bug 46200, r=ben, r=adamlock, sr=alecf.

This commit is contained in:
disttsc%bart.nl 2006-09-14 05:57:07 +00:00
Родитель 76e5bb8686
Коммит 08423a7206
3 изменённых файлов: 308 добавлений и 225 удалений

Просмотреть файл

@ -35,14 +35,8 @@ var pref = Components.classes["@mozilla.org/preferences;1"]
var appCore = null;
//cached elements/fields
//cached elements
var gBrowser = null;
var statusTextFld = null;
var statusMeter = null;
var throbberElement = null;
var stopButton = null;
var stopMenu = null;
var stopContext = null;
// focused frame URL
var gFocusedURL = null;
@ -130,217 +124,6 @@ function UpdateInternetSearchResults(event)
}
}
function nsXULBrowserWindow()
{
this.defaultStatus = gNavigatorBundle.getString("defaultStatus");
}
nsXULBrowserWindow.prototype =
{
useRealProgressFlag : false,
totalRequests : 0,
finishedRequests : 0,
// Stored Status, Link and Loading values
status : "",
defaultStatus : "",
jsStatus : "",
jsDefaultStatus : "",
overLink : "",
startTime : 0,
statusTimeoutInEffect : false,
hideAboutBlank : true,
QueryInterface : function(iid)
{
if (iid.equals(Components.interfaces.nsIXULBrowserWindow))
return this;
throw Components.results.NS_NOINTERFACE;
},
setJSStatus : function(status)
{
this.jsStatus = status;
this.updateStatusField();
// set empty so defaults show up next change
this.jsStatus = "";
},
setJSDefaultStatus : function(status)
{
this.jsDefaultStatus = status;
this.updateStatusField();
},
setDefaultStatus : function(status)
{
this.defaultStatus = status;
this.updateStatusField();
},
setOverLink : function(link, b)
{
this.overLink = link;
this.updateStatusField();
// set empty so defaults show up next change
this.overLink = "";
},
updateStatusField : function()
{
var text = this.overLink || this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
if (!statusTextFld)
statusTextFld = document.getElementById("statusbar-display");
// check the current value so we don't trigger an attribute change
// and cause needless (slow!) UI updates
if (statusTextFld.label != text) {
statusTextFld.label = text;
}
},
onProgress : function (request, current, max)
{
if (!this.useRealProgressFlag && request)
return;
if (!statusMeter)
statusMeter = document.getElementById("statusbar-icon");
if (max > 0) {
statusMeter.mode = "normal";
// This is highly optimized. Don't touch this code unless
// you are intimately familiar with the cost of setting
// attrs on XUL elements. -- hyatt
var percentage = (current * 100) / max ;
statusMeter.value = percentage;
} else {
statusMeter.mode = "undetermined";
}
},
onStateChange : function(request, state)
{
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
if (!throbberElement)
throbberElement = document.getElementById("navigator-throbber");
if (!statusMeter)
statusMeter = document.getElementById("statusbar-icon");
if (!stopButton)
stopButton = document.getElementById("stop-button");
if (!stopMenu)
stopMenu = document.getElementById("menuitem-stop");
if (!stopContext)
stopContext = document.getElementById("context-stop");
if (state & nsIWebProgressListener.STATE_START) {
if (state & nsIWebProgressListener.STATE_IS_NETWORK) {
// Remember when loading commenced.
this.startTime = (new Date()).getTime();
// Turn progress meter on.
statusMeter.mode = "undetermined";
throbberElement.setAttribute("busy", true);
// XXX: These need to be based on window activity...
stopButton.setAttribute("disabled", false);
stopMenu.setAttribute("disabled", false);
stopContext.setAttribute("disabled", false);
// Initialize the progress stuff...
this.useRealProgressFlag = false;
this.totalRequests = 0;
this.finishedRequests = 0;
}
if (state & nsIWebProgressListener.STATE_IS_REQUEST) {
this.totalRequests += 1;
}
}
else if (state & nsIWebProgressListener.STATE_STOP) {
if (state & nsIWebProgressListener.STATE_IS_REQUEST) {
this.finishedRequests += 1;
if (!this.useRealProgressFlag)
this.onProgress(null, this.finishedRequests, this.totalRequests);
}
if (state & nsIWebProgressListener.STATE_IS_NETWORK) {
var channel = request.QueryInterface(Components.interfaces.nsIChannel);
var location = channel.URI.spec;
var msg = "";
if (location != "about:blank") {
// Record page loading time.
var elapsed = ((new Date()).getTime() - this.startTime) / 1000;
msg = gNavigatorBundle.getString("nv_done");
msg = msg.replace(/%elapsed%/, elapsed);
}
this.status = "";
this.setDefaultStatus(msg);
// Turn progress meter off.
statusMeter.mode = "normal";
statusMeter.value = 0; // be sure to clear the progress bar
throbberElement.removeAttribute("busy");
// XXX: These need to be based on window activity...
stopButton.setAttribute("disabled", true);
stopMenu.setAttribute("disabled", true);
stopContext.setAttribute("disabled", true);
}
}
else if (state & nsIWebProgressListener.STATE_TRANSFERRING) {
if (state & nsIWebProgressListener.STATE_IS_DOCUMENT) {
var channel = request.QueryInterface(Components.interfaces.nsIChannel);
var ctype=channel.contentType;
if (ctype != "text/html")
this.useRealProgressFlag = true;
statusMeter.mode = "normal";
}
if (state & nsIWebProgressListener.STATE_IS_REQUEST) {
if (!this.useRealProgressFlag)
this.onProgress(null, this.finishedRequests, this.totalRequests);
}
}
},
onLocationChange : function(location)
{
if (this.hideAboutBlank) {
this.hideAboutBlank = false;
if (location == "about:blank")
location = "";
}
// We should probably not do this if the value has changed since the user
// searched
gURLBar.value = location;
UpdateBackForwardButtons();
},
onStatus : function(request, status, msg)
{
if (!this.statusTimeoutInEffect) {
this.statusTimeoutInEffect = true;
this.status = msg;
this.updateStatusField();
setTimeout(updateStatus, 400);
}
}
}
function updateStatus()
{
window.XULBrowserWindow.statusTimeoutInEffect = false;
}
function getBrowser()
{
if (!gBrowser)
@ -463,7 +246,7 @@ function Startup()
}
// initialize observers and listeners
window.XULBrowserWindow = new nsXULBrowserWindow();
window.XULBrowserWindow = new nsBrowserStatusHandler();
window.buttonPrefListener = new nsButtonPrefListener();
// XXXjag hack for directory.xul/js
@ -499,7 +282,7 @@ function Startup()
// hook up UI through progress listener
var interfaceRequestor = getBrowser().docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
var webProgress = interfaceRequestor.getInterface(Components.interfaces.nsIWebProgress);
webProgress.addProgressListener(appCore);
webProgress.addProgressListener(window.XULBrowserWindow);
// XXXjag see bug 68662
getBrowser().boxObject.setPropertyAsSupports("listenerkungfu", appCore);
@ -558,10 +341,13 @@ function Shutdown()
try {
var interfaceRequestor = browser.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
var webProgress = interfaceRequestor.getInterface(Components.interfaces.nsIWebProgress);
webProgress.removeProgressListener(appCore);
webProgress.removeProgressListener(window.XULBrowserWindow);
} catch (ex) {
}
window.XULBrowserWindow.destroy();
window.XULBrowserWindow = null;
try {
// If bookmarks are dirty, flush 'em to disk
var bmks = Components.classes["@mozilla.org/browser/bookmarks-service;1"]

Просмотреть файл

@ -64,6 +64,7 @@ Contributor(s): ______________________________________. -->
<script type="application/x-javascript" src="chrome://communicator/content/contentAreaDD.js"/>
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarksOverlay.js"/>
<script type="application/x-javascript" src="chrome://navigator/content/navigator.js"/>
<script type="application/x-javascript" src="chrome://navigator/content/nsBrowserStatusHandler.js"/>
<script type="application/x-javascript" src="tooltip.js"/>
<script type="application/x-javascript" src="navigatorDD.js"/>
<!-- UI services -->
@ -145,12 +146,12 @@ Contributor(s): ______________________________________. -->
<hbox id="nav-bar-inner" flex="1">
<hbox id="urlbar-group" class="box-toolbar-group chromeclass-location" flex="1">
<hbox autostretch="never" valign="middle" flex="1" id="urlbar-container">
<image id="page-proxy-button" ondraggesture="nsDragAndDrop.startDrag(event, proxyIconDNDObserver);"/>
<textbox autocomplete="true" timeout="300" class="plain"
searchSessionType="urlbar" id="urlbar" tooltip="aTooltip" tooltiptext="&locationBar.tooltip;"
<image id="page-proxy-button" ondraggesture="nsDragAndDrop.startDrag(event, proxyIconDNDObserver);"/>
<textbox autocomplete="true" timeout="300" class="plain"
searchSessionType="urlbar" id="urlbar" tooltip="aTooltip" tooltiptext="&locationBar.tooltip;"
onclick="if (event.button == 0) URLBarLeftClickHandler(event);"
onblur="URLBarBlurHandler(event);"
onkeypress="if( event.keyCode == 13 ) { addToUrlbarHistory(); BrowserLoadURL(); }" flex="1"/>
onkeypress="if (event.keyCode == 13) { addToUrlbarHistory(); BrowserLoadURL(); }" flex="1"/>
</hbox>
<menubutton class="menubutton-icon" id="ubhist">
<menupopup id="ubhist-popup" popupalign="topright" popupanchor="bottomright"

Просмотреть файл

@ -0,0 +1,296 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Blake Ross <blakeross@telocity.com>
* Peter Annema <disttsc@bart.nl>
*/
function nsBrowserStatusHandler()
{
this.init();
}
nsBrowserStatusHandler.prototype =
{
useRealProgressFlag : false,
totalRequests : 0,
finishedRequests : 0,
// Stored Status, Link and Loading values
status : "",
defaultStatus : "",
jsStatus : "",
jsDefaultStatus : "",
overLink : "",
startTime : 0,
statusTimeoutInEffect : false,
hideAboutBlank : true,
QueryInterface : function(aIID)
{
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
init : function()
{
// XXXjag is this still needed? It's currently just ""
this.defaultStatus = gNavigatorBundle.getString("defaultStatus");
this.urlBar = document.getElementById("urlbar");
this.throbberElement = document.getElementById("navigator-throbber");
this.statusMeter = document.getElementById("statusbar-icon");
this.stopButton = document.getElementById("stop-button");
this.stopMenu = document.getElementById("menuitem-stop");
this.stopContext = document.getElementById("context-stop");
this.statusTextField = document.getElementById("statusbar-display");
},
destroy : function()
{
// XXXjag to avoid leaks :-/, see bug 60729
this.urlBar = null;
this.throbberElement = null;
this.statusMeter = null;
this.stopButton = null;
this.stopMenu = null;
this.stopContext = null;
this.statusTextField = null;
},
setJSStatus : function(status)
{
this.jsStatus = status;
this.updateStatusField();
// set empty so defaults show up next change
this.jsStatus = "";
},
setJSDefaultStatus : function(status)
{
this.jsDefaultStatus = status;
this.updateStatusField();
},
setDefaultStatus : function(status)
{
this.defaultStatus = status;
this.updateStatusField();
},
setOverLink : function(link, b)
{
this.overLink = link;
this.updateStatusField();
// set empty so defaults show up next change
this.overLink = "";
},
updateStatusField : function()
{
var text = this.overLink || this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
// check the current value so we don't trigger an attribute change
// and cause needless (slow!) UI updates
if (this.statusTextField.label != text) {
this.statusTextField.label = text;
}
},
onProgressChange : function (aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress)
{
if (!this.useRealProgressFlag && aRequest)
return;
if (aMaxTotalProgress > 0) {
this.statusMeter.mode = "normal";
// This is highly optimized. Don't touch this code unless
// you are intimately familiar with the cost of setting
// attrs on XUL elements. -- hyatt
var percentage = (aCurTotalProgress * 100) / aMaxTotalProgress;
this.statusMeter.value = percentage;
} else {
this.statusMeter.mode = "undetermined";
}
},
onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
{
if (!aRequest)
return;
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
const nsIChannel = Components.interfaces.nsIChannel;
var domWindow;
if (aStateFlags & nsIWebProgressListener.STATE_START) {
if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
// Remember when loading commenced.
this.startTime = (new Date()).getTime();
domWindow = aWebProgress.DOMWindow;
if (domWindow == _content)
this.startDocumentLoad(aRequest);
// Turn progress meter on.
this.statusMeter.mode = "undetermined";
this.throbberElement.setAttribute("busy", true);
// XXX: These need to be based on window activity...
this.stopButton.disabled = false;
this.stopMenu.disabled = false;
this.stopContext.disabled = false;
// Initialize the progress stuff...
this.useRealProgressFlag = false;
this.totalRequests = 0;
this.finishedRequests = 0;
}
if (aStateFlags & nsIWebProgressListener.STATE_IS_REQUEST) {
this.totalRequests += 1;
}
}
else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
if (aStateFlags & nsIWebProgressListener.STATE_IS_REQUEST) {
this.finishedRequests += 1;
if (!this.useRealProgressFlag)
this.onProgressChange(null, null, 0, 0, this.finishedRequests, this.totalRequests);
}
if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
domWindow = aWebProgress.DOMWindow;
if (domWindow == domWindow.top)
this.endDocumentLoad(aRequest, aStatus);
var location = aRequest.QueryInterface(nsIChannel).URI.spec;
var msg = "";
if (location != "about:blank") {
// Record page loading time.
var elapsed = ((new Date()).getTime() - this.startTime) / 1000;
msg = gNavigatorBundle.getString("nv_done");
msg = msg.replace(/%elapsed%/, elapsed);
}
this.status = "";
this.setDefaultStatus(msg);
// Turn progress meter off.
this.statusMeter.mode = "normal";
this.statusMeter.value = 0; // be sure to clear the progress bar
this.throbberElement.removeAttribute("busy");
// XXX: These need to be based on window activity...
// XXXjag: <command id="cmd_stop"/> ?
this.stopButton.disabled = true;
this.stopMenu.disabled = true;
this.stopContext.disabled = true;
}
}
else if (aStateFlags & nsIWebProgressListener.STATE_TRANSFERRING) {
if (aStateFlags & nsIWebProgressListener.STATE_IS_DOCUMENT) {
var ctype = aRequest.QueryInterface(nsIChannel).contentType;
if (ctype != "text/html")
this.useRealProgressFlag = true;
this.statusMeter.mode = "normal";
}
if (aStateFlags & nsIWebProgressListener.STATE_IS_REQUEST) {
if (!this.useRealProgressFlag)
this.onProgressChange(null, null, 0, 0, this.finishedRequests, this.totalRequests);
}
}
},
onLocationChange : function(aWebProgress, aRequest, aLocation)
{
var location = aLocation.spec;
if (this.hideAboutBlank) {
this.hideAboutBlank = false;
if (location == "about:blank")
location = "";
}
// We should probably not do this if the value has changed since the user
// searched
this.urlBar.value = location;
UpdateBackForwardButtons();
},
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
{
if (!this.statusTimeoutInEffect) {
this.statusTimeoutInEffect = true;
this.status = aMessage;
this.updateStatusField();
setTimeout(function(aClosure) { aClosure.statusTimeoutInEffect = false; }, 400, this);
}
},
onSecurityChange : function(aWebProgress, aRequest, aState)
{
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
startDocumentLoad : function(aRequest)
{
const nsIChannel = Components.interfaces.nsIChannel;
var urlStr = aRequest.QueryInterface(nsIChannel).URI.spec;
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
try {
observerService.Notify(_content, "StartDocumentLoad", urlStr);
} catch (e) {
}
},
endDocumentLoad : function(aRequest, aStatus)
{
const nsIChannel = Components.interfaces.nsIChannel;
var urlStr = aRequest.QueryInterface(nsIChannel).originalURI.spec;
if (Components.isSuccessCode(aStatus))
dump("Document "+urlStr+" loaded successfully\n"); // per QA request
else
dump("Error loading URL "+urlStr+" : "+aStatus+"\n"); // per QA request
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
var notification = Components.isSuccessCode(aStatus) ? "FailDocumentLoad" : "EndDocumentLoad";
try {
observerService.Notify(_content, notification, urlStr);
} catch (e) {
}
}
}