~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/xpfe/browser/resources/content/nsBrowserStatusHandler.js

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
  // Stored Status, Link and Loading values
 
48
  status : "",
 
49
  defaultStatus : "",
 
50
  jsStatus : "",
 
51
  jsDefaultStatus : "",
 
52
  overLink : "",
 
53
 
 
54
  QueryInterface : function(aIID)
 
55
  {
 
56
    if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
 
57
        aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
 
58
        aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
 
59
        aIID.equals(Components.interfaces.nsISupports))
 
60
      return this;
 
61
    throw Components.results.NS_NOINTERFACE;
 
62
  },
 
63
 
 
64
  init : function()
 
65
  {
 
66
    this.urlBar          = document.getElementById("urlbar");
 
67
    this.throbberElement = document.getElementById("navigator-throbber");
 
68
    this.statusMeter     = document.getElementById("statusbar-icon");
 
69
    this.stopButton      = document.getElementById("stop-button");
 
70
    this.stopMenu        = document.getElementById("menuitem-stop");
 
71
    this.stopContext     = document.getElementById("context-stop");
 
72
    this.statusTextField = document.getElementById("statusbar-display");
 
73
    this.isImage         = document.getElementById("isImage");
 
74
    this.securityButton  = document.getElementById("security-button");
 
75
 
 
76
    // Initialize the security button's state and tooltip text
 
77
    const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
 
78
    this.onSecurityChange(null, null, nsIWebProgressListener.STATE_IS_INSECURE);
 
79
  },
 
80
 
 
81
  destroy : function()
 
82
  {
 
83
    // XXXjag to avoid leaks :-/, see bug 60729
 
84
    this.urlBar          = null;
 
85
    this.throbberElement = null;
 
86
    this.statusMeter     = null;
 
87
    this.stopButton      = null;
 
88
    this.stopMenu        = null;
 
89
    this.stopContext     = null;
 
90
    this.statusTextField = null;
 
91
    this.isImage         = null;
 
92
    this.securityButton  = null;
 
93
  },
 
94
 
 
95
  setJSStatus : function(status)
 
96
  {
 
97
    this.jsStatus = status;
 
98
    this.updateStatusField();
 
99
  },
 
100
 
 
101
  setJSDefaultStatus : function(status)
 
102
  {
 
103
    this.jsDefaultStatus = status;
 
104
    this.updateStatusField();
 
105
  },
 
106
 
 
107
  setDefaultStatus : function(status)
 
108
  {
 
109
    this.defaultStatus = status;
 
110
    this.updateStatusField();
 
111
  },
 
112
 
 
113
  setOverLink : function(link)
 
114
  {
 
115
    this.overLink = link;
 
116
    // clear out 'Done' (or other message) on first hover
 
117
    if (this.defaultStatus)
 
118
      this.defaultStatus = "";
 
119
    this.updateStatusField();
 
120
    if (link)
 
121
      this.statusTextField.setAttribute('crop', 'center');
 
122
    else
 
123
      this.statusTextField.setAttribute('crop', 'end');
 
124
  },
 
125
 
 
126
  updateStatusField : function()
 
127
  {
 
128
    var text = this.overLink || this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
 
129
 
 
130
    // check the current value so we don't trigger an attribute change
 
131
    // and cause needless (slow!) UI updates
 
132
    if (this.statusTextField.label != text)
 
133
      this.statusTextField.label = text;
 
134
  },
 
135
 
 
136
  mimeTypeIsTextBased : function(contentType)
 
137
  {
 
138
    return /^text\/|\+xml$/.test(contentType) ||
 
139
           contentType == "application/x-javascript" ||
 
140
           contentType == "application/xml" ||
 
141
           contentType == "mozilla.application/cached-xul";
 
142
  },
 
143
 
 
144
  onLinkIconAvailable : function(aHref)
 
145
  {
 
146
    if (gProxyFavIcon && pref.getBoolPref("browser.chrome.site_icons")) {
 
147
      var browser = getBrowser();
 
148
      if (browser.userTypedValue === null)
 
149
        gProxyFavIcon.setAttribute("src", aHref);
 
150
 
 
151
      // update any bookmarks with new icon reference
 
152
      if (!gBookmarksService)
 
153
        gBookmarksService = Components.classes["@mozilla.org/browser/bookmarks-service;1"]
 
154
                                      .getService(Components.interfaces.nsIBookmarksService);
 
155
      gBookmarksService.updateBookmarkIcon(browser.currentURI.spec, aHref);
 
156
    }
 
157
  },
 
158
 
 
159
  onProgressChange : function (aWebProgress, aRequest,
 
160
                               aCurSelfProgress, aMaxSelfProgress,
 
161
                               aCurTotalProgress, aMaxTotalProgress)
 
162
  {
 
163
    if (aMaxTotalProgress > 0) {
 
164
      // This is highly optimized.  Don't touch this code unless
 
165
      // you are intimately familiar with the cost of setting
 
166
      // attrs on XUL elements. -- hyatt
 
167
      var percentage = (aCurTotalProgress * 100) / aMaxTotalProgress;
 
168
      this.statusMeter.value = percentage;
 
169
    } 
 
170
  },
 
171
 
 
172
  onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
 
173
  {  
 
174
    const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
 
175
    const nsIChannel = Components.interfaces.nsIChannel;
 
176
    var ctype;
 
177
    if (aStateFlags & nsIWebProgressListener.STATE_START) {
 
178
      // This (thanks to the filter) is a network start or the first
 
179
      // stray request (the first request outside of the document load),
 
180
      // initialize the throbber and his friends.
 
181
 
 
182
      // Call start document load listeners (only if this is a network load)
 
183
      if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK &&
 
184
          aRequest && aWebProgress.DOMWindow == content)
 
185
        this.startDocumentLoad(aRequest);
 
186
 
 
187
      // Turn the throbber on.
 
188
      this.throbberElement.setAttribute("busy", "true");
 
189
 
 
190
      // XXX: These need to be based on window activity...
 
191
      this.stopButton.disabled = false;
 
192
      this.stopMenu.removeAttribute('disabled');
 
193
      this.stopContext.removeAttribute('disabled');
 
194
    }
 
195
    else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
 
196
      if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
 
197
        if (aRequest) {
 
198
          if (aWebProgress.DOMWindow == content)
 
199
            this.endDocumentLoad(aRequest, aStatus);
 
200
        }
 
201
      }
 
202
 
 
203
      // This (thanks to the filter) is a network stop or the last
 
204
      // request stop outside of loading the document, stop throbbers
 
205
      // and progress bars and such
 
206
      if (aRequest) {
 
207
        var msg = "";
 
208
        // Get the channel if the request is a channel
 
209
        var channel;
 
210
        try {
 
211
          channel = aRequest.QueryInterface(nsIChannel);
 
212
        }
 
213
        catch(e) { };
 
214
 
 
215
        if (channel) {
 
216
          var location = channel.URI.spec;
 
217
          if (location != "about:blank") {
 
218
            const kErrorBindingAborted = 0x804B0002;
 
219
            const kErrorNetTimeout = 0x804B000E;
 
220
            switch (aStatus) {
 
221
              case kErrorBindingAborted:
 
222
                msg = gNavigatorBundle.getString("nv_stopped");
 
223
                break;
 
224
              case kErrorNetTimeout:
 
225
                msg = gNavigatorBundle.getString("nv_timeout");
 
226
                break;
 
227
            }
 
228
          }
 
229
        }
 
230
        // If msg is false then we did not have an error (channel may have
 
231
        // been null, in the case of a stray image load).
 
232
        if (!msg) {
 
233
          msg = gNavigatorBundle.getString("nv_done");
 
234
        }
 
235
        this.status = "";
 
236
        this.setDefaultStatus(msg);
 
237
        
 
238
        // Disable menu entries for images, enable otherwise
 
239
        if (content.document && this.mimeTypeIsTextBased(content.document.contentType))
 
240
          this.isImage.removeAttribute('disabled');
 
241
        else
 
242
          this.isImage.setAttribute('disabled', 'true');
 
243
      }
 
244
 
 
245
      // Turn the progress meter and throbber off.
 
246
      this.statusMeter.value = 0;  // be sure to clear the progress bar
 
247
      this.throbberElement.removeAttribute("busy");
 
248
 
 
249
      // XXX: These need to be based on window activity...
 
250
      // XXXjag: <command id="cmd_stop"/> ?
 
251
      this.stopButton.disabled = true;
 
252
      this.stopMenu.setAttribute('disabled', 'true');
 
253
      this.stopContext.setAttribute('disabled', 'true');
 
254
    }
 
255
  },
 
256
 
 
257
  onLocationChange : function(aWebProgress, aRequest, aLocation)
 
258
  {
 
259
    // XXX temporary hack for bug 104532.
 
260
    // Depends heavily on setOverLink implementation
 
261
    if (!aRequest)
 
262
      this.status = this.jsStatus = this.jsDefaultStatus = "";
 
263
 
 
264
    this.setOverLink("");
 
265
 
 
266
    var locationURI = null;
 
267
    var location = "";    
 
268
 
 
269
    if (aLocation) {
 
270
      try {
 
271
        if (!gURIFixup)
 
272
          gURIFixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
 
273
                                .getService(Components.interfaces.nsIURIFixup);
 
274
        // If the url has "wyciwyg://" as the protocol, strip it off.
 
275
        // Nobody wants to see it on the urlbar for dynamically generated
 
276
        // pages.
 
277
        locationURI = gURIFixup.createExposableURI(aLocation);
 
278
        location = locationURI.spec;
 
279
      }
 
280
      catch(ex) {
 
281
        location = aLocation.spec;
 
282
      }
 
283
    }
 
284
 
 
285
    if (!getWebNavigation().canGoBack && location == "about:blank")
 
286
      location = "";
 
287
 
 
288
    // Disable menu entries for images, enable otherwise
 
289
    if (content.document && this.mimeTypeIsTextBased(content.document.contentType))
 
290
      this.isImage.removeAttribute('disabled');
 
291
    else
 
292
      this.isImage.setAttribute('disabled', 'true');
 
293
 
 
294
    // We should probably not do this if the value has changed since the user
 
295
    // searched
 
296
    // Update urlbar only if a new page was loaded on the primary content area
 
297
    // Do not update urlbar if there was a subframe navigation
 
298
 
 
299
    var browser = getBrowser().selectedBrowser;
 
300
    if (aWebProgress.DOMWindow == content) {
 
301
      // The document loaded correctly, clear the value if we should
 
302
      if (browser.userTypedClear > 0)
 
303
        browser.userTypedValue = null;
 
304
 
 
305
      var userTypedValue = browser.userTypedValue;
 
306
      if (userTypedValue === null) {
 
307
        this.urlBar.value = location;
 
308
        if (this.urlBar.value != location) {
 
309
          this.urlBar.value = ""; // hack for bug 249322
 
310
          this.urlBar.value = location;
 
311
        }
 
312
        SetPageProxyState("valid", aLocation);
 
313
 
 
314
        // Setting the urlBar value in some cases causes userTypedValue to
 
315
        // become set because of oninput, so reset it to null
 
316
        browser.userTypedValue = null;
 
317
      } else {
 
318
        this.urlBar.value = userTypedValue;
 
319
        SetPageProxyState("invalid", null);
 
320
      }
 
321
    }
 
322
    UpdateBackForwardButtons();
 
323
 
 
324
    var blank = (location == "about:blank") || (location == "");
 
325
 
 
326
    //clear popupDomain accordingly so that icon will go away when visiting
 
327
    //an unblocked site after a blocked site. note: if a popup is blocked 
 
328
    //the icon will stay as long as we are in the same domain.    
 
329
 
 
330
    if (blank ||
 
331
        !("popupDomain" in browser)) {
 
332
      browser.popupDomain = null;
 
333
    }
 
334
    else {
 
335
      var hostPort = "";
 
336
      try {
 
337
        hostPort = locationURI.hostPort;
 
338
      }
 
339
      catch(ex) { }
 
340
      if (hostPort != browser.popupDomain)
 
341
        browser.popupDomain = null;
 
342
    }
 
343
 
 
344
    var popupIcon = document.getElementById("popupIcon");
 
345
    popupIcon.hidden = !browser.popupDomain;
 
346
  },
 
347
 
 
348
  onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
 
349
  {
 
350
    this.status = aMessage;
 
351
    this.updateStatusField();
 
352
  },
 
353
 
 
354
  onSecurityChange : function(aWebProgress, aRequest, aState)
 
355
  {
 
356
    const wpl = Components.interfaces.nsIWebProgressListener;
 
357
 
 
358
    switch (aState) {
 
359
      case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_HIGH:
 
360
        this.securityButton.setAttribute("level", "high");
 
361
        break;
 
362
      case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_LOW:
 
363
        this.securityButton.setAttribute("level", "low");
 
364
        break;
 
365
      case wpl.STATE_IS_BROKEN:
 
366
        this.securityButton.setAttribute("level", "broken");
 
367
        break;
 
368
      case wpl.STATE_IS_INSECURE:
 
369
      default:
 
370
        this.securityButton.removeAttribute("level");
 
371
        break;
 
372
    }
 
373
 
 
374
    var securityUI = getBrowser().securityUI;
 
375
    if (securityUI)
 
376
      this.securityButton.setAttribute("tooltiptext", securityUI.tooltipText);
 
377
    else
 
378
      this.securityButton.removeAttribute("tooltiptext");
 
379
  },
 
380
 
 
381
  startDocumentLoad : function(aRequest)
 
382
  {
 
383
    // It's okay to clear what the user typed when we start
 
384
    // loading a document. If the user types, this flag gets
 
385
    // set to false, if the document load ends without an
 
386
    // onLocationChange, this flag also gets set to false
 
387
    // (so we keep it while switching tabs after failed load
 
388
    getBrowser().userTypedClear++;
 
389
 
 
390
    const nsIChannel = Components.interfaces.nsIChannel;
 
391
    var urlStr = aRequest.QueryInterface(nsIChannel).URI.spec;
 
392
    var observerService = Components.classes["@mozilla.org/observer-service;1"]
 
393
                                    .getService(Components.interfaces.nsIObserverService);
 
394
    try {
 
395
      observerService.notifyObservers(_content, "StartDocumentLoad", urlStr);
 
396
    } catch (e) {
 
397
    }
 
398
  },
 
399
 
 
400
  endDocumentLoad : function(aRequest, aStatus)
 
401
  {
 
402
    // The document is done loading, it's okay to clear
 
403
    // the value again.
 
404
    if (getBrowser().userTypedClear > 0)
 
405
      getBrowser().userTypedClear--;
 
406
 
 
407
    const nsIChannel = Components.interfaces.nsIChannel;
 
408
    var urlStr = aRequest.QueryInterface(nsIChannel).originalURI.spec;
 
409
 
 
410
    if (Components.isSuccessCode(aStatus))
 
411
      dump("Document "+urlStr+" loaded successfully\n"); // per QA request
 
412
    else {
 
413
      // per QA request
 
414
      var e = new Components.Exception("", aStatus);
 
415
      var name = e.name;
 
416
      dump("Error loading URL "+urlStr+" : "+
 
417
           Number(aStatus).toString(16));
 
418
      if (name)
 
419
           dump(" ("+name+")");
 
420
      dump('\n'); 
 
421
    }
 
422
 
 
423
    var observerService = Components.classes["@mozilla.org/observer-service;1"]
 
424
                                    .getService(Components.interfaces.nsIObserverService);
 
425
 
 
426
    var notification = Components.isSuccessCode(aStatus) ? "EndDocumentLoad" : "FailDocumentLoad";
 
427
    try {
 
428
      observerService.notifyObservers(_content, notification, urlStr);
 
429
    } catch (e) {
 
430
    }
 
431
  }
 
432
}
 
433