зеркало из https://github.com/mozilla/gecko-dev.git
Bug 383001 - Include a minimal G_TabbedBrowserWatcher at the single place it's actually neededpatch by Simon Bünzli, r=me
This commit is contained in:
Родитель
7e1e7f7fde
Коммит
c153be75a2
|
@ -84,7 +84,6 @@ function PROT_Application() {
|
|||
#endif
|
||||
|
||||
// expose some classes
|
||||
this.G_TabbedBrowserWatcher = G_TabbedBrowserWatcher;
|
||||
this.PROT_Controller = PROT_Controller;
|
||||
this.PROT_PhishingWarden = PROT_PhishingWarden;
|
||||
|
||||
|
|
|
@ -53,11 +53,6 @@
|
|||
// etc.) and let's the BrowserView know about any user action
|
||||
// having to do with the problems it is tracking.
|
||||
//
|
||||
// - from the TabbedBrowserWatcher. When the BrowserView is keeping
|
||||
// track of a problematic document it listens for interesting
|
||||
// events affecting it, for example pagehide (at which point
|
||||
// we presumably hide the warning if we're showing it).
|
||||
//
|
||||
// The BrowserView associates at most one "problem" with each Document
|
||||
// in the browser window. It keeps state about which Documents are
|
||||
// problematic by storing a "problem queue" on each browser (tab).
|
||||
|
@ -115,45 +110,13 @@
|
|||
* aware of the problem.
|
||||
*
|
||||
* @constructor
|
||||
* @param tabWatcher Reference to the TabbedBrowserWatcher we'll use to query
|
||||
* @param tabBrowser Reference to the main tabbrowser we'll use to query
|
||||
* for information about active tabs/browsers.
|
||||
* @param doc Reference to the XUL Document (browser window) in which the
|
||||
* tabwatcher is watching
|
||||
*/
|
||||
function PROT_BrowserView(tabWatcher, doc) {
|
||||
function PROT_BrowserView(tabBrowser) {
|
||||
this.debugZone = "browserview";
|
||||
this.tabWatcher_ = tabWatcher;
|
||||
this.doc_ = doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if we have any Documents with a given (problematic) URL that
|
||||
* haven't yet been marked as problems. Called as a subroutine by
|
||||
* tryToHandleProblemRequest().
|
||||
*
|
||||
* @param url String containing the URL to look for
|
||||
*
|
||||
* @returns Reference to an unhandled Document with the problem URL or null
|
||||
*/
|
||||
PROT_BrowserView.prototype.getFirstUnhandledDocWithURL_ = function(url) {
|
||||
var docs = this.tabWatcher_.getDocumentsFromURL(url);
|
||||
if (!docs.length)
|
||||
return null;
|
||||
|
||||
for (var i = 0; i < docs.length; i++) {
|
||||
// We only care about top level documents (i.e., we don't care about
|
||||
// frames).
|
||||
if (docs[i].defaultView.top != docs[i].defaultView)
|
||||
continue;
|
||||
|
||||
var browser = this.tabWatcher_.getBrowserFromDocument(docs[i]);
|
||||
G_Assert(this, !!browser, "Found doc but can't find browser???");
|
||||
var alreadyHandled = this.getProblem_(docs[i], browser);
|
||||
|
||||
if (!alreadyHandled)
|
||||
return docs[i];
|
||||
}
|
||||
return null;
|
||||
this.tabBrowser_ = tabBrowser;
|
||||
this.doc_ = this.tabBrowser_.ownerDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -172,16 +135,19 @@ PROT_BrowserView.prototype.getFirstUnhandledDocWithURL_ = function(url) {
|
|||
*/
|
||||
PROT_BrowserView.prototype.tryToHandleProblemRequest = function(warden,
|
||||
request) {
|
||||
// XXX: pass around the URL instead of the request. request.name isn't
|
||||
// really supposed to be used and isn't guaranteed to give the URL.
|
||||
var url = request.name;
|
||||
var browsers = this.tabBrowser_.browsers;
|
||||
for (var i = 0; i < browsers.length; i++) {
|
||||
var browser = browsers[i];
|
||||
var doc = browser.contentDocument;
|
||||
|
||||
var doc = this.getFirstUnhandledDocWithURL_(request.name);
|
||||
if (doc) {
|
||||
var browser = this.tabWatcher_.getBrowserFromDocument(doc);
|
||||
G_Assert(this, !!browser, "Couldn't get browser from problem doc???");
|
||||
G_Assert(this, !this.getProblem_(doc, browser),
|
||||
"Doc is supposedly unhandled, but has state?");
|
||||
|
||||
this.isProblemDocument_(browser, doc, warden);
|
||||
return true;
|
||||
// We only care about top level documents (and not about frames)
|
||||
if (doc.location.href == url && !this.getProblem_(doc, browser)) {
|
||||
this.isProblemDocument_(browser, doc, warden);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -403,7 +369,7 @@ PROT_BrowserView.prototype.unqueueNextProblem_ = function(browser) {
|
|||
// Thanks to bryner for helping to track the bfcache bug down.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=319646
|
||||
|
||||
if (this.tabWatcher_.getCurrentBrowser() === browser)
|
||||
if (this.tabBrowser_.selectedBrowser === browser)
|
||||
new G_Alarm(BindToObject(this.problemBrowserMaybeSelected,
|
||||
this,
|
||||
browser),
|
||||
|
@ -549,7 +515,7 @@ PROT_BrowserView.prototype.problemBrowserUnselected = function(browser) {
|
|||
PROT_BrowserView.prototype.problemBrowserMaybeSelected = function(browser) {
|
||||
var problem = this.getCurrentProblem_(browser);
|
||||
|
||||
if (this.tabWatcher_.getCurrentBrowser() === browser &&
|
||||
if (this.tabBrowser_.selectedBrowser === browser &&
|
||||
problem &&
|
||||
problem.displayer_.isActive())
|
||||
this.problemBrowserSelected(browser);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Fritz Schneider <fritz@google.com> (original author)
|
||||
* Simon Bünzli <zeniko@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -58,12 +59,11 @@
|
|||
* @constructor
|
||||
* @param win Reference to the Window (browser window context) we should
|
||||
* attach to
|
||||
* @param tabWatcher Reference to the TabbedBrowserWatcher object
|
||||
* the controller should use to receive events about tabs.
|
||||
* @param tabBrowser Reference to the window's main tabbrowser object.
|
||||
* @param phishingWarden Reference to the PhishingWarden we should register
|
||||
* our browserview with
|
||||
*/
|
||||
function PROT_Controller(win, tabWatcher, phishingWarden) {
|
||||
function PROT_Controller(win, tabBrowser, phishingWarden) {
|
||||
this.debugZone = "controller";
|
||||
|
||||
this.win_ = win;
|
||||
|
@ -73,11 +73,12 @@ function PROT_Controller(win, tabWatcher, phishingWarden) {
|
|||
this.prefs_ = new G_Preferences();
|
||||
|
||||
// Set us up to receive the events we want.
|
||||
this.tabWatcher_ = tabWatcher;
|
||||
this.onTabSwitchCallback_ = BindToObject(this.onTabSwitch, this);
|
||||
this.tabWatcher_.registerListener("tabswitch",
|
||||
this.onTabSwitchCallback_);
|
||||
this.tabBrowser_ = tabBrowser;
|
||||
this.onTabSwitchClosure_ = BindToObject(this.onTabSwitch, this);
|
||||
this.tabBrowser_.mTabBox.addEventListener("select", this.onTabSwitchClosure_, true);
|
||||
|
||||
// Used to determine when the user has switched tabs
|
||||
this.lastTab_ = tabBrowser.selectedBrowser;
|
||||
|
||||
// Install our command controllers. These commands are issued from
|
||||
// various places in our UI, including our preferences dialog, the
|
||||
|
@ -96,8 +97,7 @@ function PROT_Controller(win, tabWatcher, phishingWarden) {
|
|||
|
||||
// This guy embodies the logic of when to display warnings
|
||||
// (displayers embody the how).
|
||||
this.browserView_ = new PROT_BrowserView(this.tabWatcher_,
|
||||
this.win_.document);
|
||||
this.browserView_ = new PROT_BrowserView(this.tabBrowser_);
|
||||
|
||||
// We need to let the phishing warden know about this browser view so it
|
||||
// can be given the opportunity to handle problem documents. We also need
|
||||
|
@ -105,10 +105,6 @@ function PROT_Controller(win, tabWatcher, phishingWarden) {
|
|||
// is going away.
|
||||
this.phishingWarden_.addBrowserView(this.browserView_);
|
||||
|
||||
this.windowWatcher_ =
|
||||
Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Components.interfaces.nsIWindowWatcher);
|
||||
|
||||
G_Debug(this, "Controller initialized.");
|
||||
}
|
||||
|
||||
|
@ -126,23 +122,19 @@ PROT_Controller.prototype.shutdown = function(e) {
|
|||
this.commandController_ = null;
|
||||
}
|
||||
|
||||
|
||||
// No need to drain the browser view's problem queue explicitly; it will
|
||||
// receive pagehides for all the browsers in its queues as they're torn
|
||||
// down, and it will remove them.
|
||||
this.browserView_ = null;
|
||||
|
||||
if (this.tabWatcher_) {
|
||||
this.tabWatcher_.removeListener("tabswitch",
|
||||
this.onTabSwitchCallback_);
|
||||
this.tabWatcher_.shutdown();
|
||||
}
|
||||
if (this.tabBrowser_)
|
||||
this.tabBrowser_.mTabBox.removeEventListener("select", this.onTabSwitchClosure_, true);
|
||||
// Break circular refs so we can be gc'ed.
|
||||
this.tabBrowser_ = this.lastTab_ = null;
|
||||
|
||||
this.win_.removeEventListener("unload", this.onShutdown_, false);
|
||||
this.prefs_ = null;
|
||||
|
||||
this.windowWatcher_ = null;
|
||||
|
||||
G_Debug(this, "Controller shut down.");
|
||||
}
|
||||
|
||||
|
@ -151,7 +143,7 @@ PROT_Controller.prototype.shutdown = function(e) {
|
|||
* again.
|
||||
*/
|
||||
PROT_Controller.prototype.onUserShowWarning = function() {
|
||||
var browser = this.tabWatcher_.getCurrentBrowser();
|
||||
var browser = this.tabBrowser_.selectedBrowser;
|
||||
this.browserView_.explicitShow(browser);
|
||||
}
|
||||
|
||||
|
@ -164,7 +156,7 @@ PROT_Controller.prototype.onUserShowWarning = function() {
|
|||
*/
|
||||
PROT_Controller.prototype.onUserAcceptWarning = function() {
|
||||
G_Debug(this, "User accepted warning.");
|
||||
var browser = this.tabWatcher_.getCurrentBrowser();
|
||||
var browser = this.tabBrowser_.selectedBrowser;
|
||||
G_Assert(this, !!browser, "Couldn't get current browser?!?");
|
||||
G_Assert(this, this.browserView_.hasProblem(browser),
|
||||
"User accept fired, but browser doesn't have warning showing?!?");
|
||||
|
@ -182,7 +174,7 @@ PROT_Controller.prototype.onUserAcceptWarning = function() {
|
|||
*/
|
||||
PROT_Controller.prototype.onUserDeclineWarning = function() {
|
||||
G_Debug(this, "User declined warning.");
|
||||
var browser = this.tabWatcher_.getCurrentBrowser();
|
||||
var browser = this.tabBrowser_.selectedBrowser;
|
||||
G_Assert(this, this.browserView_.hasProblem(browser),
|
||||
"User decline fired, but browser doesn't have warning showing?!?");
|
||||
this.browserView_.declineAction(browser);
|
||||
|
@ -199,9 +191,22 @@ PROT_Controller.prototype.onUserDeclineWarning = function() {
|
|||
* point. But one thing at a time.
|
||||
*/
|
||||
PROT_Controller.prototype.onTabSwitch = function(e) {
|
||||
if (this.browserView_.hasProblem(e.fromBrowser))
|
||||
this.browserView_.problemBrowserUnselected(e.fromBrowser);
|
||||
// Filter spurious events
|
||||
// The event target is usually tabs but can be tabpanels when tabs were opened
|
||||
// programatically via tabbrowser.addTab().
|
||||
if (!e.target || (e.target.localName != "tabs" && e.target.localName != "tabpanels"))
|
||||
return;
|
||||
|
||||
if (this.browserView_.hasProblem(e.toBrowser))
|
||||
this.browserView_.problemBrowserSelected(e.toBrowser);
|
||||
var fromBrowser = this.lastTab_;
|
||||
var toBrowser = this.tabBrowser_.selectedBrowser;
|
||||
|
||||
if (fromBrowser != toBrowser) {
|
||||
this.lastTab_ = toBrowser;
|
||||
|
||||
if (this.browserView_.hasProblem(fromBrowser))
|
||||
this.browserView_.problemBrowserUnselected(fromBrowser);
|
||||
|
||||
if (this.browserView_.hasProblem(toBrowser))
|
||||
this.browserView_.problemBrowserSelected(toBrowser);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,584 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 Google Safe Browsing.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Google Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fritz Schneider <fritz@google.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
// This file implements a G_TabbedBrowserWatcher, an object
|
||||
// encapsulating and abstracting the mechanics of working with tabs
|
||||
// and the documents within them. The watcher provides notification of
|
||||
// various DOM-related events (a document loaded, a document unloaded,
|
||||
// tab was created/destroyed, user switched tabs, etc.) as well as
|
||||
// commonly required methods (get me the current tab, find the tab to
|
||||
// which this document belongs, etc.).
|
||||
//
|
||||
// This class does not do progresslistener-based notifications; for that,
|
||||
// use the NavWatcher.
|
||||
//
|
||||
// Note: I use "browser" and "tab" interchangeably.
|
||||
//
|
||||
// This class adds a level of indirection to event registration. You
|
||||
// initialize it with a tabbedbrowser, and then register to hear
|
||||
// events from it instead of from the tabbedbrowser or browser itself.
|
||||
// Your handlers are invoked with a custom object as an argument (see
|
||||
// below). This object contains useful information such as a reference
|
||||
// to the browser in which the event is happening and whether the
|
||||
// event is occurring on the top-level document in that browser.
|
||||
//
|
||||
// The events you can register to hear are:
|
||||
//
|
||||
// EVENT DESCRIPTION
|
||||
// ----- -----------
|
||||
// load Fires when a page is shown in the browser window and
|
||||
// this page wasn't in the bfcache
|
||||
//
|
||||
// unload Fires when a page is nav'd away from in the browser window
|
||||
// and the page isn't going into the bfcache
|
||||
//
|
||||
// pageshow Fires when a page is shown in the browser window, whether
|
||||
// it came from bfcache or not. (There is a "persisted"
|
||||
// property we can get from the event object if we'd like.
|
||||
// It indicates whether the page was loaded from bfcache.
|
||||
// If false then we known load recently fired).
|
||||
//
|
||||
// pagehide Fires when a page is nav'd away from in the browser,
|
||||
// whether its going into the bfcache or not. (There is
|
||||
// a persisted property here as well that we're not
|
||||
// propagating -- when its true the page is going into
|
||||
// the bfcache, else it's not, and unload will shortly
|
||||
// fire).
|
||||
//
|
||||
// domcontentloaded BROKEN BROKEN BROKEN BROKEN BROKEN BROKEN BROKEN BROKEN
|
||||
// Fires when a doc's DOM is ready, but its externally linked
|
||||
// content hasn't necessarily loaded. This event is
|
||||
// currently broken: it doesn't fire when using the
|
||||
// forward/back buttons in conjunction with the bfcache.
|
||||
// Bryner is working on a fix.
|
||||
//
|
||||
// tabload Fires when a new tab has been created (but doesn't
|
||||
// necessarily have content loaded in it)
|
||||
//
|
||||
// tabunload Fires when a tab is being destroyed (and might have had
|
||||
// the content it contains destroyed)
|
||||
//
|
||||
// tabswitch Fires when the user switches tabs
|
||||
//
|
||||
// tabmove Fires when a user drags a tab to a different position
|
||||
//
|
||||
//
|
||||
// For pageshow, pagehide, load, unload, and domcontentloaded, the event
|
||||
// object you'll receive has the following properties:
|
||||
//
|
||||
// doc -- reference to Document on which the event fired
|
||||
// browser -- the browser in which the document resides
|
||||
// isTop -- boolean indicating if it is the top-level document
|
||||
// inSelected -- boolean indicating if it is in the currently selected tab
|
||||
//
|
||||
// For tabload and unload it has:
|
||||
//
|
||||
// browser -- reference to the browser that is loading or closing
|
||||
//
|
||||
// For tabswitch it has:
|
||||
//
|
||||
// fromBrowser -- reference to the browser user is switching from
|
||||
// toBrowser -- reference to the browser user is switching to
|
||||
//
|
||||
// For tabmove it has:
|
||||
//
|
||||
// tab -- the tab that was moved (Note that this is the actual
|
||||
// tab widget that holds the document title, not the
|
||||
// browser object. We use this because it's the target
|
||||
// of the DOMNodeInserted event.)
|
||||
// fromIndex -- the tab index before the move
|
||||
// toIndex -- the tab index after the move
|
||||
//
|
||||
//
|
||||
// The order of events is: tabload
|
||||
// domcontentloaded
|
||||
// load
|
||||
// pageshow
|
||||
// -- --
|
||||
// pagehide
|
||||
// unload
|
||||
// tabunload
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// function handler(e /*event object*/) {
|
||||
// foo(e.browser);
|
||||
// };
|
||||
// var watcher = new G_TabbedBrowserWatcher(document.getElementById(gBrowser));
|
||||
// watcher.registerListener("load", handler); // register for events
|
||||
// watcher.removeListener("load", handler); // unregister
|
||||
//
|
||||
//
|
||||
// TODO, BUGS, ISSUES, COMPLICATIONS:
|
||||
//
|
||||
// The only major problem is in closing tabs:
|
||||
//
|
||||
// + When you close a tab, the reference to the Document you get in the
|
||||
// unload event is undefined. We pass this along. This could easily
|
||||
// be fixed by not listening for unload at all, but instead inferring
|
||||
// it from the information in pagehide, and then firing our own "fake"
|
||||
// unload after firing pagehide.
|
||||
//
|
||||
// + There's no docshell during the pagehide event, so we can't determine
|
||||
// if the document is top-level. We pass undefined in this case.
|
||||
//
|
||||
// + Though the browser reference during tabunload will be valid, its
|
||||
// members most likely have already been torn down. Use it in an
|
||||
// objectsafemap to keep state if you need its members.
|
||||
//
|
||||
// + The event listener DOMNodeInserted has the potential to cause
|
||||
// performance problems if there are too many events fired. It
|
||||
// should be ok, since we inserted it as far as possible into
|
||||
// the xul tree.
|
||||
//
|
||||
//
|
||||
// TODO: need better enforcement of unique names. Two tabbedbrowserwatchers
|
||||
// with the same name will clobber each other because they use that
|
||||
// name to mark browsers they've seen.
|
||||
//
|
||||
// TODO: the functions that iterate of windows and documents badly need
|
||||
// to be made cleaner. Right now we have multiple implementations
|
||||
// that essentially do the same thing :(
|
||||
//
|
||||
// But good enough for government work.
|
||||
|
||||
/**
|
||||
* Encapsulates tab-related information. You can use the
|
||||
* G_TabbedBrowserWatcher to watch for events on tabs as well as to
|
||||
* retrieve tab-related data (such as what tab is currently showing).
|
||||
* It receives many event notifications from G_BrowserWatchers it
|
||||
* attaches to newly opening tabs.
|
||||
*
|
||||
* @param tabBrowser A reference to the tabbed browser you wish to watch.
|
||||
*
|
||||
* @param name String containing a probabilistically unique name. Used to
|
||||
* ensure that each tabbedbrowserwatcher can uniquely mark
|
||||
* browser it has "seen."
|
||||
*
|
||||
* @param opt_filterAboutBlank Boolean indicating whether to filter events
|
||||
* for about:blank. These events are often
|
||||
* spurious since about:blank is the default
|
||||
* page for an empty browser.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
function G_TabbedBrowserWatcher(tabBrowser, name, opt_filterAboutBlank) {
|
||||
this.debugZone = "tabbedbrowserwatcher";
|
||||
this.tabBrowser_ = tabBrowser;
|
||||
this.filterAboutBlank_ = !!opt_filterAboutBlank;
|
||||
this.events = G_TabbedBrowserWatcher.events; // Convenience pointer
|
||||
this.eventListeners_ = {};
|
||||
for (var e in this.events)
|
||||
this.eventListeners_[this.events[e]] = [];
|
||||
|
||||
// We need some way to tell if we've seen a browser before, so we
|
||||
// set a property on it with a probabilistically unique string. The
|
||||
// string is a combination of a static string and one passed in by
|
||||
// the caller.
|
||||
G_Assert(this, typeof name == "string" && !!name,
|
||||
"Need a probabilistically unique name");
|
||||
this.name_ = name;
|
||||
this.mark_ = G_TabbedBrowserWatcher.mark_ + "-" + this.name_;
|
||||
|
||||
this.tabbox_ = this.getTabBrowser().mTabBox;
|
||||
|
||||
// There's no tabswitch event in Firefox, so we fake it by watching
|
||||
// for selects on the tabbox.
|
||||
this.onTabSwitchClosure_ = BindToObject(this.onTabSwitch, this);
|
||||
this.tabbox_.addEventListener("select",
|
||||
this.onTabSwitchClosure_, true);
|
||||
|
||||
// Used to determine when the user has switched tabs
|
||||
this.lastTab_ = this.getCurrentBrowser();
|
||||
}
|
||||
|
||||
// Events for which listeners can register
|
||||
G_TabbedBrowserWatcher.events = {
|
||||
TABSWITCH: "tabswitch",
|
||||
};
|
||||
|
||||
// We mark new tabs as we see them
|
||||
G_TabbedBrowserWatcher.mark_ = "watcher-marked";
|
||||
|
||||
/**
|
||||
* Remove all the event handlers and clean up circular refs.
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.shutdown = function() {
|
||||
G_Debug(this, "Removing event listeners");
|
||||
if (this.tabbox_) {
|
||||
this.tabbox_.removeEventListener("select",
|
||||
this.onTabSwitchClosure_, true);
|
||||
// Break circular ref so we can be gc'ed.
|
||||
this.tabbox_ = null;
|
||||
}
|
||||
// Break circular ref so we can be gc'ed.
|
||||
if (this.lastTab_) {
|
||||
this.lastTab_ = null;
|
||||
}
|
||||
|
||||
if (this.tabBrowser_) {
|
||||
this.tabBrowser_ = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if we've seen a browser before
|
||||
*
|
||||
* @param browser Browser to check
|
||||
* @returns Boolean indicating if we've attached a BrowserWatcher to this
|
||||
* browser
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.isInstrumented_ = function(browser) {
|
||||
return !!browser[this.mark_];
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches a BrowserWatcher to a browser and marks it as seen
|
||||
*
|
||||
* @param browser Browser to which to attach a G_BrowserWatcher
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.instrumentBrowser_ = function(browser) {
|
||||
G_Assert(this, !this.isInstrumented_(browser),
|
||||
"Browser already instrumented!");
|
||||
|
||||
// The browserwatcher will hook itself into the browser and its parent (us)
|
||||
new G_BrowserWatcher(this, browser);
|
||||
browser[this.mark_] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register to receive events of a particular type
|
||||
*
|
||||
* @param eventType String indicating the event (see
|
||||
* G_TabbedBrowserWatcher.events)
|
||||
* @param listener Function to invoke when the event occurs. See top-
|
||||
* level comments for parameters.
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.registerListener = function(eventType,
|
||||
listener) {
|
||||
if (!(eventType in this.eventListeners_))
|
||||
throw new Error("Unknown event type: " + eventType);
|
||||
|
||||
this.eventListeners_[eventType].push(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a listener.
|
||||
*
|
||||
* @param eventType String one of G_TabbedBrowserWatcher.events' members
|
||||
* @param listener Function to remove as listener
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.removeListener = function(eventType,
|
||||
listener) {
|
||||
if (!(eventType in this.eventListeners_))
|
||||
throw new Error("Unknown event type: " + eventType);
|
||||
|
||||
var ix = this.eventListeners_[eventType].indexOf(listener);
|
||||
if (ix > -1)
|
||||
this.eventListeners_[eventType].splice(ix, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an event to all listeners for that type.
|
||||
*
|
||||
* @param eventType String indicating the event to trigger
|
||||
* @param e Object to pass to each listener (NOT copied -- be careful)
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.fire = function(eventType, e) {
|
||||
if (!(eventType in this.eventListeners_))
|
||||
throw new Error("Unknown event type: " + eventType);
|
||||
|
||||
this.eventListeners_[eventType].forEach(function(listener) { listener(e); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to send a document-related event. We use this
|
||||
* convenience function because the event constructing logic and
|
||||
* parameters are the same for all these events. (Document-related
|
||||
* events are load, unload, pagehide, pageshow, and domcontentloaded).
|
||||
*
|
||||
* @param eventType String indicating the type of event to fire (one of
|
||||
* the document-related events)
|
||||
*
|
||||
* @param doc Reference to the HTMLDocument the event is occuring to
|
||||
*
|
||||
* @param browser Reference to the browser in which the document is contained
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.fireDocEvent_ = function(eventType,
|
||||
doc,
|
||||
browser) {
|
||||
// If we've already shutdown, don't bother firing any events.
|
||||
if (!this.tabBrowser_) {
|
||||
G_Debug(this, "Firing event after shutdown: " + eventType);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Could be that the browser's contentDocument has already been torn
|
||||
// down. If so, this throws, and we can't tell without keeping more
|
||||
// state whether doc was the top frame.
|
||||
var isTop = (doc == browser.contentDocument);
|
||||
} catch(e) {
|
||||
var isTop = undefined;
|
||||
}
|
||||
|
||||
var inSelected = (browser == this.getCurrentBrowser());
|
||||
|
||||
var location = doc ? doc.location.href : undefined;
|
||||
|
||||
// Only send notifications for about:config's if we're supposed to
|
||||
if (!this.filterAboutBlank_ || location != "about:blank") {
|
||||
|
||||
G_Debug(this, "firing " + eventType + " for " + location +
|
||||
(isTop ? " (isTop)" : "") + (inSelected ? " (inSelected)" : ""));
|
||||
this.fire(eventType, { "doc": doc,
|
||||
"isTop": isTop,
|
||||
"inSelected": inSelected,
|
||||
"browser": browser});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the user might have switched tabs
|
||||
*
|
||||
* @param e Event object
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.onTabSwitch = function(e) {
|
||||
// Filter spurious events
|
||||
// The event target is usually tabs but can be tabpanels when tabs were opened
|
||||
// programatically via tabbrowser.addTab().
|
||||
if (e.target == null ||
|
||||
(e.target.localName != "tabs" && e.target.localName != "tabpanels"))
|
||||
return;
|
||||
|
||||
var fromBrowser = this.lastTab_;
|
||||
var toBrowser = this.getCurrentBrowser();
|
||||
|
||||
if (fromBrowser != toBrowser) {
|
||||
this.lastTab_ = toBrowser;
|
||||
G_Debug(this, "firing tabswitch");
|
||||
this.fire(this.events.TABSWITCH, { "fromBrowser": fromBrowser,
|
||||
"toBrowser": toBrowser });
|
||||
}
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
|
||||
/**
|
||||
* Returns a reference to the tabbed browser this G_TabbedBrowserWatcher
|
||||
* was initialized with.
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.getTabBrowser = function() {
|
||||
return this.tabBrowser_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the currently selected tab.
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.getCurrentBrowser = function() {
|
||||
return this.getTabBrowser().selectedBrowser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the top window in the currently selected tab.
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.getCurrentWindow = function() {
|
||||
return this.getCurrentBrowser().contentWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the browser corresponding to a Document
|
||||
*
|
||||
* @param doc Document we want the browser for
|
||||
* @returns Reference to the browser in which the given document is found
|
||||
* or null if not found
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.getBrowserFromDocument = function(doc) {
|
||||
// Could instead get the top window of the browser in which the doc
|
||||
// is found via doc.defaultView.top, but sometimes the document
|
||||
// isn't in a browser at all (it's being unloaded, for example), so
|
||||
// defaultView won't be valid.
|
||||
|
||||
// Helper: return true if doc is a sub-document of win
|
||||
function docInWindow(doc, win) {
|
||||
if (win.document == doc)
|
||||
return true;
|
||||
|
||||
if (win.frames)
|
||||
for (var i = 0; i < win.frames.length; i++)
|
||||
if (docInWindow(doc, win.frames[i]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var browsers = this.getTabBrowser().browsers;
|
||||
for (var i = 0; i < browsers.length; i++)
|
||||
if (docInWindow(doc, browsers[i].contentWindow))
|
||||
return browsers[i];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the Document that has the given URL loaded. Returns on the
|
||||
* _first_ such document found, so be careful.
|
||||
*
|
||||
* TODO make doc/window searches more elegant, and don't use inner functions
|
||||
*
|
||||
* @param url String indicating the URL we're searching for
|
||||
* @param opt_browser Optional reference to a browser. If given, the
|
||||
* search will be confined to only this browser.
|
||||
* @returns Reference to the Document with that URL or null if not found
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.getDocumentFromURL = function(url,
|
||||
opt_browser) {
|
||||
|
||||
// Helper function: return the Document in win that has location of url
|
||||
function docWithURL(win, url) {
|
||||
if (win.document.location.href == url)
|
||||
return win.document;
|
||||
|
||||
if (win.frames)
|
||||
for (var i = 0; i < win.frames.length; i++) {
|
||||
var rv = docWithURL(win.frames[i], url);
|
||||
if (rv)
|
||||
return rv;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (opt_browser)
|
||||
return docWithURL(opt_browser.contentWindow, url);
|
||||
|
||||
var browsers = this.getTabBrowser().browsers;
|
||||
for (var i=0; i < browsers.length; i++) {
|
||||
var rv = docWithURL(browsers[i].contentWindow, url);
|
||||
if (rv)
|
||||
return rv;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the all Documents that have the given URL loaded.
|
||||
*
|
||||
* TODO make doc/window searches more elegant, and don't use inner functions
|
||||
*
|
||||
* @param url String indicating the URL we're searching for
|
||||
*
|
||||
* @param opt_browser Optional reference to a browser. If given, the
|
||||
* search will be confined to only this browser.
|
||||
*
|
||||
* @returns Array of Documents with the given URL (zero length if none found)
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.getDocumentsFromURL = function(url,
|
||||
opt_browser) {
|
||||
|
||||
var docs = [];
|
||||
|
||||
// Helper function: add Docs in win with the location of url
|
||||
function getDocsWithURL(win, url) {
|
||||
if (win.document.location.href == url)
|
||||
docs.push(win.document);
|
||||
|
||||
if (win.frames)
|
||||
for (var i = 0; i < win.frames.length; i++)
|
||||
getDocsWithURL(win.frames[i], url);
|
||||
}
|
||||
|
||||
if (opt_browser)
|
||||
return getDocsWithURL(opt_browser.contentWindow, url);
|
||||
|
||||
var browsers = this.getTabBrowser().browsers;
|
||||
for (var i=0; i < browsers.length; i++)
|
||||
getDocsWithURL(browsers[i].contentWindow, url);
|
||||
|
||||
return docs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the browser in which a Window resides.
|
||||
*
|
||||
* @param sub Window to find
|
||||
* @returns Reference to the browser in which sub resides, else null
|
||||
* if not found
|
||||
*/
|
||||
G_TabbedBrowserWatcher.prototype.getBrowserFromWindow = function(sub) {
|
||||
|
||||
// Helpfer function: return true if sub is a sub-window of win
|
||||
function containsSubWindow(sub, win) {
|
||||
if (win == sub)
|
||||
return true;
|
||||
|
||||
if (win.frames)
|
||||
for (var i=0; i < win.frames.length; i++)
|
||||
if (containsSubWindow(sub, win.frames[i]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var browsers = this.getTabBrowser().browsers;
|
||||
for (var i=0; i < browsers.length; i++)
|
||||
if (containsSubWindow(sub, browsers[i].contentWindow))
|
||||
return browsers[i];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the XUL <tab> tag corresponding to a given browser.
|
||||
*
|
||||
* @param tabBrowser Reference to the tabbed browser in which browser lives
|
||||
* @param browser Reference to the browser we wish to find the tab of
|
||||
* @returns Reference to the browser's tab element, or null
|
||||
* @static
|
||||
*/
|
||||
G_TabbedBrowserWatcher.getTabElementFromBrowser = function(tabBrowser,
|
||||
browser) {
|
||||
|
||||
for (var i=0; i < tabBrowser.browsers.length; i++)
|
||||
if (tabBrowser.browsers[i] == browser)
|
||||
return tabBrowser.mTabContainer.childNodes[i];
|
||||
|
||||
return null;
|
||||
}
|
|
@ -71,11 +71,9 @@ var safebrowsing = {
|
|||
|
||||
// Each new browser window needs its own controller.
|
||||
|
||||
var contentArea = document.getElementById("content");
|
||||
|
||||
safebrowsing.progressListener.QueryInterface(Ci.nsIWebProgressListener);
|
||||
var phishWarden = new appContext.PROT_PhishingWarden(
|
||||
safebrowsing.progressListener, document.getElementById("content"));
|
||||
safebrowsing.progressListener, getBrowser());
|
||||
safebrowsing.phishWarden = phishWarden;
|
||||
|
||||
// Register tables
|
||||
|
@ -88,14 +86,8 @@ var safebrowsing = {
|
|||
|
||||
// Download/update lists if we're in non-enhanced mode
|
||||
phishWarden.maybeToggleUpdateChecking();
|
||||
var tabWatcher = new appContext.G_TabbedBrowserWatcher(
|
||||
contentArea,
|
||||
"safebrowsing-watcher",
|
||||
true /*ignore about:blank*/);
|
||||
safebrowsing.controller = new appContext.PROT_Controller(
|
||||
window,
|
||||
tabWatcher,
|
||||
phishWarden);
|
||||
window, getBrowser(), phishWarden);
|
||||
|
||||
// Remove the global progress listener. The phishingWarden moves
|
||||
// the progress listener to the tabbrowser so we don't need it anymore.
|
||||
|
|
|
@ -10,8 +10,6 @@ Function.prototype.inherits = function(parentCtor) {
|
|||
this.prototype = new tempCtor();
|
||||
}
|
||||
|
||||
#include ../content/moz/tabbedbrowserwatcher.js
|
||||
|
||||
#include ../content/application.js
|
||||
#include ../content/browser-view.js
|
||||
#include ../content/controller.js
|
||||
|
|
Загрузка…
Ссылка в новой задаче