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:
tony@ponderer.org 2007-06-03 19:54:30 -07:00
Родитель 7e1e7f7fde
Коммит c153be75a2
6 изменённых файлов: 53 добавлений и 677 удалений

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

@ -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