# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. // The warden checks request to see if they are for phishy pages. It // does so by querying our locally stored blacklists. // // When the warden notices a problem, it queries all browser views // (each of which corresopnds to an open browser window) to see // whether one of them can handle it. A browser view can handle a // problem if its browser window has an HTMLDocument loaded with the // given URL and that Document hasn't already been flagged as a // problem. For every problematic URL we notice loading, at most one // Document is flagged as problematic. Otherwise you can get into // trouble if multiple concurrent phishy pages load with the same URL. // // Since we check URLs very early in the request cycle (in a progress // listener), the URL might not yet be associated with a Document when // we determine that it is phishy. So the the warden retries finding // a browser view to handle the problem until one can, or until it // determines it should give up (see complicated logic below). // // The warden has displayers that the browser view uses to render // different kinds of warnings (e.g., one that's shown before a page // loads as opposed to one that's shown after the page has already // loaded). // // Note: There is a single warden for the whole application. // // TODO better way to expose displayers/views to browser view const kPhishWardenEnabledPref = "browser.safebrowsing.enabled"; /** * Abtracts the checking of user/browser actions for signs of * phishing. * * @param progressListener nsIDocNavStartProgressListener * @param tabbrowser XUL tabbrowser element * @constructor */ function PROT_PhishingWarden() { PROT_ListWarden.call(this); this.debugZone = "phishwarden"; // Use this to query preferences this.prefs_ = new G_Preferences(); // We need to know whether we're enabled and whether we're in advanced // mode, so reflect the appropriate preferences into our state. // Global preference to enable the phishing warden this.phishWardenEnabled_ = this.prefs_.getPref(kPhishWardenEnabledPref, null); // Get notifications when the phishing warden enabled pref changes var phishWardenPrefObserver = BindToObject(this.onPhishWardenEnabledPrefChanged, this); this.prefs_.addObserver(kPhishWardenEnabledPref, phishWardenPrefObserver); G_Debug(this, "phishWarden initialized"); } PROT_PhishingWarden.inherits(PROT_ListWarden); PROT_PhishingWarden.prototype.QueryInterface = function(iid) { if (iid.equals(Ci.nsISupports) || iid.equals(Ci.nsISupportsWeakReference)) return this; throw Components.results.NS_ERROR_NO_INTERFACE; } /** * Cleanup on shutdown. */ PROT_PhishingWarden.prototype.shutdown = function() { this.prefs_.removeAllObservers(); this.listManager_ = null; } /** * When a preference (either advanced features or the phishwarden * enabled) changes, we might have to start or stop asking for updates. * * This is a little tricky; we start or stop management only when we * have complete information we can use to determine whether we * should. It could be the case that one pref or the other isn't set * yet (e.g., they haven't opted in/out of advanced features). So do * nothing unless we have both pref values -- we get notifications for * both, so eventually we will start correctly. */ PROT_PhishingWarden.prototype.maybeToggleUpdateChecking = function() { var phishWardenEnabled = this.prefs_.getPref(kPhishWardenEnabledPref, null); G_Debug(this, "Maybe toggling update checking. " + "Warden enabled? " + phishWardenEnabled); // Do nothing unless both prefs are set. They can be null (unset), true, or // false. if (phishWardenEnabled === null) return; // We update and save to disk all tables if (phishWardenEnabled === true) { this.enableBlacklistTableUpdates(); this.enableWhitelistTableUpdates(); } else { // Anti-phishing is off, disable table updates this.disableBlacklistTableUpdates(); this.disableWhitelistTableUpdates(); } } /** * Deal with a user changing the pref that says whether we should * enable the phishing warden (i.e., that SafeBrowsing is active) * * @param prefName Name of the pref holding the value indicating whether * we should enable the phishing warden */ PROT_PhishingWarden.prototype.onPhishWardenEnabledPrefChanged = function( prefName) { // Just to be safe, ignore changes to sub prefs. if (prefName != "browser.safebrowsing.enabled") return; this.phishWardenEnabled_ = this.prefs_.getPref(prefName, this.phishWardenEnabled_); this.maybeToggleUpdateChecking(); }