toolkit/components/url-classifier/content/moz/alarm.js

changeset 0
6474c204b198
     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 +}

mercurial