/* ***** 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 storagePolicy.js. * * The Initial Developer of the Original Code is * the Mozilla Foundation. * Portions created by the Initial Developer are Copyright (C) 2011 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Tim Taubert * * 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 ***** */ // ********** // Title: storagePolicy.js // ########## // Class: StoragePolicy // Singleton for implementing a storage policy for sensitive data. let StoragePolicy = { // Pref that controls whether we can store SSL content on disk PREF_DISK_CACHE_SSL: "browser.cache.disk_cache_ssl", // Used to keep track of disk_cache_ssl preference _enablePersistentHttpsCaching: null, // Used to keep track of browsers whose data we shouldn't store permanently _deniedBrowsers: [], // ---------- // Function: toString // Prints [StoragePolicy] for debug use. toString: function StoragePolicy_toString() { return "[StoragePolicy]"; }, // ---------- // Function: init // Initializes the StoragePolicy object. init: function StoragePolicy_init() { // store the preference value this._enablePersistentHttpsCaching = Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL); Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false); // tabs are already loaded before UI is initialized so cache-control // values are unknown. We add browsers with https to the list for now. if (!this._enablePersistentHttpsCaching) Array.forEach(gBrowser.browsers, this._initializeBrowser.bind(this)); // make sure to remove tab browsers when tabs get closed this._onTabClose = this._onTabClose.bind(this); gBrowser.tabContainer.addEventListener("TabClose", this._onTabClose, false); let mm = gWindow.messageManager; // add message listeners for storage granted this._onGranted = this._onGranted.bind(this); mm.addMessageListener("Panorama:StoragePolicy:granted", this._onGranted); // add message listeners for storage denied this._onDenied = this._onDenied.bind(this); mm.addMessageListener("Panorama:StoragePolicy:denied", this._onDenied); }, // ---------- // Function: _initializeBrowser // Initializes the given browser and checks if we need to add it to our // internal exclusion list. _initializeBrowser: function StoragePolicy__initializeBrowser(browser) { let self = this; function checkExclusion() { if (browser.currentURI.schemeIs("https")) self._deniedBrowsers.push(browser); } function waitForDocumentLoad() { let mm = browser.messageManager; mm.addMessageListener("Panorama:DOMContentLoaded", function onLoad(cx) { mm.removeMessageListener(cx.name, onLoad); checkExclusion(browser); }); } this._isDocumentLoaded(browser, function (isLoaded) { if (isLoaded) checkExclusion(); else waitForDocumentLoad(); }); }, // ---------- // Function: _isDocumentLoaded // Check if the given browser's document is loaded. _isDocumentLoaded: function StoragePolicy__isDocumentLoaded(browser, callback) { let mm = browser.messageManager; let message = "Panorama:isDocumentLoaded"; mm.addMessageListener(message, function onMessage(cx) { mm.removeMessageListener(cx.name, onMessage); callback(cx.json.isLoaded); }); mm.sendAsyncMessage(message); }, // ---------- // Function: uninit // Is called by UI.init() when the browser windows is closed. uninit: function StoragePolicy_uninit() { Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this); gBrowser.removeTabsProgressListener(this); gBrowser.tabContainer.removeEventListener("TabClose", this._onTabClose, false); let mm = gWindow.messageManager; // remove message listeners mm.removeMessageListener("Panorama:StoragePolicy:granted", this._onGranted); mm.removeMessageListener("Panorama:StoragePolicy:denied", this._onDenied); }, // ---------- // Function: _onGranted // Handle the 'granted' message and remove the given browser from the list // of denied browsers. _onGranted: function StoragePolicy__onGranted(cx) { let index = this._deniedBrowsers.indexOf(cx.target); if (index > -1) this._deniedBrowsers.splice(index, 1); }, // ---------- // Function: _onDenied // Handle the 'denied' message and add the given browser to the list of denied // browsers. _onDenied: function StoragePolicy__onDenied(cx) { // exclusion is optional because cache-control is not no-store or public and // the protocol is https. don't exclude when persistent https caching is // enabled. if ("https" == cx.json.reason && this._enablePersistentHttpsCaching) return; let browser = cx.target; if (this._deniedBrowsers.indexOf(browser) == -1) this._deniedBrowsers.push(browser); }, // ---------- // Function: _onTabClose // Remove the browser from our internal exclusion list when a tab gets closed. _onTabClose: function StoragePolicy__onTabClose(event) { let browser = event.target.linkedBrowser; let index = this._deniedBrowsers.indexOf(browser); if (index > -1) this._deniedBrowsers.splice(index, 1); }, // ---------- // Function: canStoreThumbnailForTab // Returns whether we're allowed to store the thumbnail of the given tab. canStoreThumbnailForTab: function StoragePolicy_canStoreThumbnailForTab(tab) { // deny saving thumbnails in private browsing mode if (gPrivateBrowsing.privateBrowsingEnabled && UI._privateBrowsing.transitionMode != "enter") return false; return (this._deniedBrowsers.indexOf(tab.linkedBrowser) == -1); }, // ---------- // Function: observe // Observe pref changes. observe: function StoragePolicy_observe(subject, topic, data) { this._enablePersistentHttpsCaching = Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL); } };