mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
366 lines
13 KiB
JavaScript
366 lines
13 KiB
JavaScript
/*
|
|
#ifdef 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 Content Preferences (cpref).
|
|
*
|
|
* The Initial Developer of the Original Code is Mozilla.
|
|
* Portions created by the Initial Developer are Copyright (C) 2006
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Myk Melez <myk@mozilla.org>
|
|
* Dão Gottwald <dao@mozilla.com>
|
|
* Ehsan Akhgari <ehsan.akhgari@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
|
|
* 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 *****
|
|
#endif
|
|
*/
|
|
|
|
// One of the possible values for the mousewheel.* preferences.
|
|
// From nsEventStateManager.cpp.
|
|
const MOUSE_SCROLL_ZOOM = 3;
|
|
|
|
/**
|
|
* Controls the "full zoom" setting and its site-specific preferences.
|
|
*/
|
|
var FullZoom = {
|
|
// Identifies the setting in the content prefs database.
|
|
name: "browser.content.full-zoom",
|
|
|
|
// The global value (if any) for the setting. Lazily loaded from the service
|
|
// when first requested, then updated by the pref change listener as it changes.
|
|
// If there is no global value, then this should be undefined.
|
|
get globalValue() {
|
|
var globalValue = Services.contentPrefs.getPref(null, this.name);
|
|
if (typeof globalValue != "undefined")
|
|
globalValue = this._ensureValid(globalValue);
|
|
delete this.globalValue;
|
|
return this.globalValue = globalValue;
|
|
},
|
|
|
|
// browser.zoom.siteSpecific preference cache
|
|
_siteSpecificPref: undefined,
|
|
|
|
// browser.zoom.updateBackgroundTabs preference cache
|
|
updateBackgroundTabs: undefined,
|
|
|
|
// whether we are in private browsing mode
|
|
_inPrivateBrowsing: false,
|
|
|
|
get siteSpecific() {
|
|
return !this._inPrivateBrowsing && this._siteSpecificPref;
|
|
},
|
|
|
|
//**************************************************************************//
|
|
// nsISupports
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener,
|
|
Ci.nsIObserver,
|
|
Ci.nsIContentPrefObserver,
|
|
Ci.nsISupportsWeakReference,
|
|
Ci.nsISupports]),
|
|
|
|
//**************************************************************************//
|
|
// Initialization & Destruction
|
|
|
|
init: function FullZoom_init() {
|
|
// Listen for scrollwheel events so we can save scrollwheel-based changes.
|
|
window.addEventListener("DOMMouseScroll", this, false);
|
|
|
|
// Register ourselves with the service so we know when our pref changes.
|
|
Services.contentPrefs.addObserver(this.name, this);
|
|
|
|
// We disable site-specific preferences in Private Browsing mode, because the
|
|
// content preferences module is disabled
|
|
Services.obs.addObserver(this, "private-browsing", true);
|
|
|
|
// Retrieve the initial status of the Private Browsing mode.
|
|
this._inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
|
|
getService(Ci.nsIPrivateBrowsingService).
|
|
privateBrowsingEnabled;
|
|
|
|
this._siteSpecificPref =
|
|
gPrefService.getBoolPref("browser.zoom.siteSpecific");
|
|
this.updateBackgroundTabs =
|
|
gPrefService.getBoolPref("browser.zoom.updateBackgroundTabs");
|
|
// Listen for changes to the browser.zoom branch so we can enable/disable
|
|
// updating background tabs and per-site saving and restoring of zoom levels.
|
|
gPrefService.addObserver("browser.zoom.", this, true);
|
|
},
|
|
|
|
destroy: function FullZoom_destroy() {
|
|
Services.obs.removeObserver(this, "private-browsing");
|
|
gPrefService.removeObserver("browser.zoom.", this);
|
|
Services.contentPrefs.removeObserver(this.name, this);
|
|
window.removeEventListener("DOMMouseScroll", this, false);
|
|
},
|
|
|
|
|
|
//**************************************************************************//
|
|
// Event Handlers
|
|
|
|
// nsIDOMEventListener
|
|
|
|
handleEvent: function FullZoom_handleEvent(event) {
|
|
switch (event.type) {
|
|
case "DOMMouseScroll":
|
|
this._handleMouseScrolled(event);
|
|
break;
|
|
}
|
|
},
|
|
|
|
_handleMouseScrolled: function FullZoom__handleMouseScrolled(event) {
|
|
// Construct the "mousewheel action" pref key corresponding to this event.
|
|
// Based on nsEventStateManager::GetBasePrefKeyForMouseWheel.
|
|
var pref = "mousewheel";
|
|
if (event.axis == event.HORIZONTAL_AXIS)
|
|
pref += ".horizscroll";
|
|
|
|
if (event.shiftKey)
|
|
pref += ".withshiftkey";
|
|
else if (event.ctrlKey)
|
|
pref += ".withcontrolkey";
|
|
else if (event.altKey)
|
|
pref += ".withaltkey";
|
|
else if (event.metaKey)
|
|
pref += ".withmetakey";
|
|
else
|
|
pref += ".withnokey";
|
|
|
|
pref += ".action";
|
|
|
|
// Don't do anything if this isn't a "zoom" scroll event.
|
|
var isZoomEvent = false;
|
|
try {
|
|
isZoomEvent = (gPrefService.getIntPref(pref) == MOUSE_SCROLL_ZOOM);
|
|
} catch (e) {}
|
|
if (!isZoomEvent)
|
|
return;
|
|
|
|
// XXX Lazily cache all the possible action prefs so we don't have to get
|
|
// them anew from the pref service for every scroll event? We'd have to
|
|
// make sure to observe them so we can update the cache when they change.
|
|
|
|
// We have to call _applySettingToPref in a timeout because we handle
|
|
// the event before the event state manager has a chance to apply the zoom
|
|
// during nsEventStateManager::PostHandleEvent.
|
|
window.setTimeout(function (self) { self._applySettingToPref() }, 0, this);
|
|
},
|
|
|
|
// nsIObserver
|
|
|
|
observe: function (aSubject, aTopic, aData) {
|
|
switch (aTopic) {
|
|
case "nsPref:changed":
|
|
switch (aData) {
|
|
case "browser.zoom.siteSpecific":
|
|
this._siteSpecificPref =
|
|
gPrefService.getBoolPref("browser.zoom.siteSpecific");
|
|
break;
|
|
case "browser.zoom.updateBackgroundTabs":
|
|
this.updateBackgroundTabs =
|
|
gPrefService.getBoolPref("browser.zoom.updateBackgroundTabs");
|
|
break;
|
|
}
|
|
break;
|
|
case "private-browsing":
|
|
switch (aData) {
|
|
case "enter":
|
|
this._inPrivateBrowsing = true;
|
|
break;
|
|
case "exit":
|
|
this._inPrivateBrowsing = false;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
},
|
|
|
|
// nsIContentPrefObserver
|
|
|
|
onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) {
|
|
if (aGroup == Services.contentPrefs.grouper.group(gBrowser.currentURI))
|
|
this._applyPrefToSetting(aValue);
|
|
else if (aGroup == null) {
|
|
this.globalValue = this._ensureValid(aValue);
|
|
|
|
// If the current page doesn't have a site-specific preference,
|
|
// then its zoom should be set to the new global preference now that
|
|
// the global preference has changed.
|
|
if (!Services.contentPrefs.hasPref(gBrowser.currentURI, this.name))
|
|
this._applyPrefToSetting();
|
|
}
|
|
},
|
|
|
|
onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) {
|
|
if (aGroup == Services.contentPrefs.grouper.group(gBrowser.currentURI))
|
|
this._applyPrefToSetting();
|
|
else if (aGroup == null) {
|
|
this.globalValue = undefined;
|
|
|
|
// If the current page doesn't have a site-specific preference,
|
|
// then its zoom should be set to the default preference now that
|
|
// the global preference has changed.
|
|
if (!Services.contentPrefs.hasPref(gBrowser.currentURI, this.name))
|
|
this._applyPrefToSetting();
|
|
}
|
|
},
|
|
|
|
// location change observer
|
|
|
|
/**
|
|
* Called when the location of a tab changes.
|
|
* When that happens, we need to update the current zoom level if appropriate.
|
|
*
|
|
* @param aURI
|
|
* A URI object representing the new location.
|
|
* @param aIsTabSwitch
|
|
* Whether this location change has happened because of a tab switch.
|
|
* @param aBrowser
|
|
* (optional) browser object displaying the document
|
|
*/
|
|
onLocationChange: function FullZoom_onLocationChange(aURI, aIsTabSwitch, aBrowser) {
|
|
if (!aURI || (aIsTabSwitch && !this.siteSpecific))
|
|
return;
|
|
|
|
// Avoid the cps roundtrip and apply the default/global pref.
|
|
if (aURI.spec == "about:blank") {
|
|
this._applyPrefToSetting(undefined, aBrowser);
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
Services.contentPrefs.getPref(aURI, this.name, function (aResult) {
|
|
// Check that we're still where we expect to be in case this took a while.
|
|
let browser = aBrowser || gBrowser.selectedBrowser;
|
|
if (aURI.equals(browser.currentURI)) {
|
|
self._applyPrefToSetting(aResult, browser);
|
|
}
|
|
});
|
|
},
|
|
|
|
// update state of zoom type menu item
|
|
|
|
updateMenu: function FullZoom_updateMenu() {
|
|
var menuItem = document.getElementById("toggle_zoom");
|
|
|
|
menuItem.setAttribute("checked", !ZoomManager.useFullZoom);
|
|
},
|
|
|
|
//**************************************************************************//
|
|
// Setting & Pref Manipulation
|
|
|
|
reduce: function FullZoom_reduce() {
|
|
ZoomManager.reduce();
|
|
this._applySettingToPref();
|
|
},
|
|
|
|
enlarge: function FullZoom_enlarge() {
|
|
ZoomManager.enlarge();
|
|
this._applySettingToPref();
|
|
},
|
|
|
|
reset: function FullZoom_reset() {
|
|
if (typeof this.globalValue != "undefined")
|
|
ZoomManager.zoom = this.globalValue;
|
|
else
|
|
ZoomManager.reset();
|
|
|
|
this._removePref();
|
|
},
|
|
|
|
/**
|
|
* Set the zoom level for the current tab.
|
|
*
|
|
* Per nsPresContext::setFullZoom, we can set the zoom to its current value
|
|
* without significant impact on performance, as the setting is only applied
|
|
* if it differs from the current setting. In fact getting the zoom and then
|
|
* checking ourselves if it differs costs more.
|
|
*
|
|
* And perhaps we should always set the zoom even if it was more expensive,
|
|
* since DocumentViewerImpl::SetTextZoom claims that child documents can have
|
|
* a different text zoom (although it would be unusual), and it implies that
|
|
* those child text zooms should get updated when the parent zoom gets set,
|
|
* and perhaps the same is true for full zoom
|
|
* (although DocumentViewerImpl::SetFullZoom doesn't mention it).
|
|
*
|
|
* So when we apply new zoom values to the browser, we simply set the zoom.
|
|
* We don't check first to see if the new value is the same as the current
|
|
* one.
|
|
**/
|
|
_applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue, aBrowser) {
|
|
if ((!this.siteSpecific && !this._inPrivateBrowsing) ||
|
|
gInPrintPreviewMode)
|
|
return;
|
|
|
|
var browser = aBrowser || (gBrowser && gBrowser.selectedBrowser);
|
|
try {
|
|
if (browser.contentDocument instanceof Ci.nsIImageDocument ||
|
|
this._inPrivateBrowsing)
|
|
ZoomManager.setZoomForBrowser(browser, 1);
|
|
else if (typeof aValue != "undefined")
|
|
ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue));
|
|
else if (typeof this.globalValue != "undefined")
|
|
ZoomManager.setZoomForBrowser(browser, this.globalValue);
|
|
else
|
|
ZoomManager.setZoomForBrowser(browser, 1);
|
|
}
|
|
catch(ex) {}
|
|
},
|
|
|
|
_applySettingToPref: function FullZoom__applySettingToPref() {
|
|
if (!this.siteSpecific || gInPrintPreviewMode ||
|
|
content.document instanceof Ci.nsIImageDocument)
|
|
return;
|
|
|
|
var zoomLevel = ZoomManager.zoom;
|
|
Services.contentPrefs.setPref(gBrowser.currentURI, this.name, zoomLevel);
|
|
},
|
|
|
|
_removePref: function FullZoom__removePref() {
|
|
if (!(content.document instanceof Ci.nsIImageDocument))
|
|
Services.contentPrefs.removePref(gBrowser.currentURI, this.name);
|
|
},
|
|
|
|
|
|
//**************************************************************************//
|
|
// Utilities
|
|
|
|
_ensureValid: function FullZoom__ensureValid(aValue) {
|
|
if (isNaN(aValue))
|
|
return 1;
|
|
|
|
if (aValue < ZoomManager.MIN)
|
|
return ZoomManager.MIN;
|
|
|
|
if (aValue > ZoomManager.MAX)
|
|
return ZoomManager.MAX;
|
|
|
|
return aValue;
|
|
}
|
|
};
|