summaryrefslogtreecommitdiffstats
path: root/toolkit/components/url-classifier/content/moz/alarm.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/url-classifier/content/moz/alarm.js')
-rw-r--r--toolkit/components/url-classifier/content/moz/alarm.js157
1 files changed, 157 insertions, 0 deletions
diff --git a/toolkit/components/url-classifier/content/moz/alarm.js b/toolkit/components/url-classifier/content/moz/alarm.js
new file mode 100644
index 000000000..7de067546
--- /dev/null
+++ b/toolkit/components/url-classifier/content/moz/alarm.js
@@ -0,0 +1,157 @@
+# 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/.
+
+
+// An Alarm fires a callback after a certain amount of time, or at
+// regular intervals. It's a convenient replacement for
+// setTimeout/Interval when you don't want to bind to a specific
+// window.
+//
+// The ConditionalAlarm is an Alarm that cancels itself if its callback
+// returns a value that type-converts to true.
+//
+// Example:
+//
+// function foo() { dump('hi'); };
+// new G_Alarm(foo, 10*1000); // Fire foo in 10 seconds
+// new G_Alarm(foo, 10*1000, true /*repeat*/); // Fire foo every 10 seconds
+// new G_Alarm(foo, 10*1000, true, 7); // Fire foo every 10 seconds
+// // seven times
+// new G_ConditionalAlarm(foo, 1000, true); // Fire every sec until foo()==true
+//
+// // Fire foo every 10 seconds until foo returns true or until it fires seven
+// // times, whichever happens first.
+// new G_ConditionalAlarm(foo, 10*1000, true /*repeating*/, 7);
+//
+// TODO: maybe pass an isFinal flag to the callback if they opted to
+// set maxTimes and this is the last iteration?
+
+
+/**
+ * Set an alarm to fire after a given amount of time, or at specific
+ * intervals.
+ *
+ * @param callback Function to call when the alarm fires
+ * @param delayMS Number indicating the length of the alarm period in ms
+ * @param opt_repeating Boolean indicating whether this should fire
+ * periodically
+ * @param opt_maxTimes Number indicating a maximum number of times to
+ * repeat (obviously only useful when opt_repeating==true)
+ */
+this.G_Alarm =
+function G_Alarm(callback, delayMS, opt_repeating, opt_maxTimes) {
+ this.debugZone = "alarm";
+ this.callback_ = callback;
+ this.repeating_ = !!opt_repeating;
+ this.timer_ = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ var type = opt_repeating ?
+ this.timer_.TYPE_REPEATING_SLACK :
+ this.timer_.TYPE_ONE_SHOT;
+ this.maxTimes_ = opt_maxTimes ? opt_maxTimes : null;
+ this.nTimes_ = 0;
+
+ this.observerServiceObserver_ = new G_ObserverServiceObserver(
+ 'xpcom-shutdown',
+ BindToObject(this.cancel, this));
+
+ // Ask the timer to use nsITimerCallback (.notify()) when ready
+ this.timer_.initWithCallback(this, delayMS, type);
+}
+
+/**
+ * Cancel this timer
+ */
+G_Alarm.prototype.cancel = function() {
+ if (!this.timer_) {
+ return;
+ }
+
+ this.timer_.cancel();
+ // Break circular reference created between this.timer_ and the G_Alarm
+ // instance (this)
+ this.timer_ = null;
+ this.callback_ = null;
+
+ // We don't need the shutdown observer anymore
+ this.observerServiceObserver_.unregister();
+}
+
+/**
+ * Invoked by the timer when it fires
+ *
+ * @param timer Reference to the nsITimer which fired (not currently
+ * passed along)
+ */
+G_Alarm.prototype.notify = function(timer) {
+ // fire callback and save results
+ var ret = this.callback_();
+
+ // If they've given us a max number of times to fire, enforce it
+ this.nTimes_++;
+ if (this.repeating_ &&
+ typeof this.maxTimes_ == "number"
+ && this.nTimes_ >= this.maxTimes_) {
+ this.cancel();
+ } else if (!this.repeating_) {
+ // Clear out the callback closure for TYPE_ONE_SHOT timers
+ this.cancel();
+ }
+ // We don't cancel/cleanup timers that repeat forever until either
+ // xpcom-shutdown occurs or cancel() is called explicitly.
+
+ return ret;
+}
+
+G_Alarm.prototype.setDelay = function(delay) {
+ this.timer_.delay = delay;
+}
+
+/**
+ * XPCOM cruft
+ */
+G_Alarm.prototype.QueryInterface = function(iid) {
+ if (iid.equals(Components.interfaces.nsISupports) ||
+ iid.equals(Components.interfaces.nsITimerCallback))
+ return this;
+
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+}
+
+
+/**
+ * An alarm with the additional property that it cancels itself if its
+ * callback returns true.
+ *
+ * For parameter documentation, see G_Alarm
+ */
+this.G_ConditionalAlarm =
+function G_ConditionalAlarm(callback, delayMS, opt_repeating, opt_maxTimes) {
+ G_Alarm.call(this, callback, delayMS, opt_repeating, opt_maxTimes);
+ this.debugZone = "conditionalalarm";
+}
+
+G_ConditionalAlarm.inherits = function(parentCtor) {
+ var tempCtor = function(){};
+ tempCtor.prototype = parentCtor.prototype;
+ this.superClass_ = parentCtor.prototype;
+ this.prototype = new tempCtor();
+}
+
+G_ConditionalAlarm.inherits(G_Alarm);
+
+/**
+ * Invoked by the timer when it fires
+ *
+ * @param timer Reference to the nsITimer which fired (not currently
+ * passed along)
+ */
+G_ConditionalAlarm.prototype.notify = function(timer) {
+ // Call G_Alarm::notify
+ var rv = G_Alarm.prototype.notify.call(this, timer);
+
+ if (this.repeating_ && rv) {
+ G_Debug(this, "Callback of a repeating alarm returned true; cancelling.");
+ this.cancel();
+ }
+}