1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/url-classifier/content/moz/alarm.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,148 @@ 1.4 +# This Source Code Form is subject to the terms of the Mozilla Public 1.5 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + 1.8 + 1.9 +// An Alarm fires a callback after a certain amount of time, or at 1.10 +// regular intervals. It's a convenient replacement for 1.11 +// setTimeout/Interval when you don't want to bind to a specific 1.12 +// window. 1.13 +// 1.14 +// The ConditionalAlarm is an Alarm that cancels itself if its callback 1.15 +// returns a value that type-converts to true. 1.16 +// 1.17 +// Example: 1.18 +// 1.19 +// function foo() { dump('hi'); }; 1.20 +// new G_Alarm(foo, 10*1000); // Fire foo in 10 seconds 1.21 +// new G_Alarm(foo, 10*1000, true /*repeat*/); // Fire foo every 10 seconds 1.22 +// new G_Alarm(foo, 10*1000, true, 7); // Fire foo every 10 seconds 1.23 +// // seven times 1.24 +// new G_ConditionalAlarm(foo, 1000, true); // Fire every sec until foo()==true 1.25 +// 1.26 +// // Fire foo every 10 seconds until foo returns true or until it fires seven 1.27 +// // times, whichever happens first. 1.28 +// new G_ConditionalAlarm(foo, 10*1000, true /*repeating*/, 7); 1.29 +// 1.30 +// TODO: maybe pass an isFinal flag to the callback if they opted to 1.31 +// set maxTimes and this is the last iteration? 1.32 + 1.33 + 1.34 +/** 1.35 + * Set an alarm to fire after a given amount of time, or at specific 1.36 + * intervals. 1.37 + * 1.38 + * @param callback Function to call when the alarm fires 1.39 + * @param delayMS Number indicating the length of the alarm period in ms 1.40 + * @param opt_repeating Boolean indicating whether this should fire 1.41 + * periodically 1.42 + * @param opt_maxTimes Number indicating a maximum number of times to 1.43 + * repeat (obviously only useful when opt_repeating==true) 1.44 + */ 1.45 +function G_Alarm(callback, delayMS, opt_repeating, opt_maxTimes) { 1.46 + this.debugZone = "alarm"; 1.47 + this.callback_ = callback; 1.48 + this.repeating_ = !!opt_repeating; 1.49 + this.timer_ = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); 1.50 + var type = opt_repeating ? 1.51 + this.timer_.TYPE_REPEATING_SLACK : 1.52 + this.timer_.TYPE_ONE_SHOT; 1.53 + this.maxTimes_ = opt_maxTimes ? opt_maxTimes : null; 1.54 + this.nTimes_ = 0; 1.55 + 1.56 + this.observerServiceObserver_ = new G_ObserverServiceObserver( 1.57 + 'xpcom-shutdown', 1.58 + BindToObject(this.cancel, this)); 1.59 + 1.60 + // Ask the timer to use nsITimerCallback (.notify()) when ready 1.61 + this.timer_.initWithCallback(this, delayMS, type); 1.62 +} 1.63 + 1.64 +/** 1.65 + * Cancel this timer 1.66 + */ 1.67 +G_Alarm.prototype.cancel = function() { 1.68 + if (!this.timer_) { 1.69 + return; 1.70 + } 1.71 + 1.72 + this.timer_.cancel(); 1.73 + // Break circular reference created between this.timer_ and the G_Alarm 1.74 + // instance (this) 1.75 + this.timer_ = null; 1.76 + this.callback_ = null; 1.77 + 1.78 + // We don't need the shutdown observer anymore 1.79 + this.observerServiceObserver_.unregister(); 1.80 +} 1.81 + 1.82 +/** 1.83 + * Invoked by the timer when it fires 1.84 + * 1.85 + * @param timer Reference to the nsITimer which fired (not currently 1.86 + * passed along) 1.87 + */ 1.88 +G_Alarm.prototype.notify = function(timer) { 1.89 + // fire callback and save results 1.90 + var ret = this.callback_(); 1.91 + 1.92 + // If they've given us a max number of times to fire, enforce it 1.93 + this.nTimes_++; 1.94 + if (this.repeating_ && 1.95 + typeof this.maxTimes_ == "number" 1.96 + && this.nTimes_ >= this.maxTimes_) { 1.97 + this.cancel(); 1.98 + } else if (!this.repeating_) { 1.99 + // Clear out the callback closure for TYPE_ONE_SHOT timers 1.100 + this.cancel(); 1.101 + } 1.102 + // We don't cancel/cleanup timers that repeat forever until either 1.103 + // xpcom-shutdown occurs or cancel() is called explicitly. 1.104 + 1.105 + return ret; 1.106 +} 1.107 + 1.108 +G_Alarm.prototype.setDelay = function(delay) { 1.109 + this.timer_.delay = delay; 1.110 +} 1.111 + 1.112 +/** 1.113 + * XPCOM cruft 1.114 + */ 1.115 +G_Alarm.prototype.QueryInterface = function(iid) { 1.116 + if (iid.equals(Components.interfaces.nsISupports) || 1.117 + iid.equals(Components.interfaces.nsITimerCallback)) 1.118 + return this; 1.119 + 1.120 + throw Components.results.NS_ERROR_NO_INTERFACE; 1.121 +} 1.122 + 1.123 + 1.124 +/** 1.125 + * An alarm with the additional property that it cancels itself if its 1.126 + * callback returns true. 1.127 + * 1.128 + * For parameter documentation, see G_Alarm 1.129 + */ 1.130 +function G_ConditionalAlarm(callback, delayMS, opt_repeating, opt_maxTimes) { 1.131 + G_Alarm.call(this, callback, delayMS, opt_repeating, opt_maxTimes); 1.132 + this.debugZone = "conditionalalarm"; 1.133 +} 1.134 + 1.135 +G_ConditionalAlarm.inherits(G_Alarm); 1.136 + 1.137 +/** 1.138 + * Invoked by the timer when it fires 1.139 + * 1.140 + * @param timer Reference to the nsITimer which fired (not currently 1.141 + * passed along) 1.142 + */ 1.143 +G_ConditionalAlarm.prototype.notify = function(timer) { 1.144 + // Call G_Alarm::notify 1.145 + var rv = G_Alarm.prototype.notify.call(this, timer); 1.146 + 1.147 + if (this.repeating_ && rv) { 1.148 + G_Debug(this, "Callback of a repeating alarm returned true; cancelling."); 1.149 + this.cancel(); 1.150 + } 1.151 +}