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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6 // An Alarm fires a callback after a certain amount of time, or at
     7 // regular intervals. It's a convenient replacement for
     8 // setTimeout/Interval when you don't want to bind to a specific
     9 // window.
    10 //
    11 // The ConditionalAlarm is an Alarm that cancels itself if its callback 
    12 // returns a value that type-converts to true.
    13 //
    14 // Example:
    15 //
    16 //  function foo() { dump('hi'); };
    17 //  new G_Alarm(foo, 10*1000);                   // Fire foo in 10 seconds
    18 //  new G_Alarm(foo, 10*1000, true /*repeat*/);  // Fire foo every 10 seconds
    19 //  new G_Alarm(foo, 10*1000, true, 7);          // Fire foo every 10 seconds
    20 //                                               // seven times
    21 //  new G_ConditionalAlarm(foo, 1000, true); // Fire every sec until foo()==true
    22 //
    23 //  // Fire foo every 10 seconds until foo returns true or until it fires seven
    24 //  // times, whichever happens first.
    25 //  new G_ConditionalAlarm(foo, 10*1000, true /*repeating*/, 7);
    26 //
    27 // TODO: maybe pass an isFinal flag to the callback if they opted to
    28 // set maxTimes and this is the last iteration?
    31 /**
    32  * Set an alarm to fire after a given amount of time, or at specific 
    33  * intervals.
    34  *
    35  * @param callback Function to call when the alarm fires
    36  * @param delayMS Number indicating the length of the alarm period in ms
    37  * @param opt_repeating Boolean indicating whether this should fire 
    38  *                      periodically
    39  * @param opt_maxTimes Number indicating a maximum number of times to 
    40  *                     repeat (obviously only useful when opt_repeating==true)
    41  */
    42 function G_Alarm(callback, delayMS, opt_repeating, opt_maxTimes) {
    43   this.debugZone = "alarm";
    44   this.callback_ = callback;
    45   this.repeating_ = !!opt_repeating;
    46   this.timer_ = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
    47   var type = opt_repeating ? 
    48              this.timer_.TYPE_REPEATING_SLACK : 
    49              this.timer_.TYPE_ONE_SHOT;
    50   this.maxTimes_ = opt_maxTimes ? opt_maxTimes : null;
    51   this.nTimes_ = 0;
    53   this.observerServiceObserver_ = new G_ObserverServiceObserver(
    54                                         'xpcom-shutdown',
    55                                         BindToObject(this.cancel, this));
    57   // Ask the timer to use nsITimerCallback (.notify()) when ready
    58   this.timer_.initWithCallback(this, delayMS, type);
    59 }
    61 /**
    62  * Cancel this timer 
    63  */
    64 G_Alarm.prototype.cancel = function() {
    65   if (!this.timer_) {
    66     return;
    67   }
    69   this.timer_.cancel();
    70   // Break circular reference created between this.timer_ and the G_Alarm
    71   // instance (this)
    72   this.timer_ = null;
    73   this.callback_ = null;
    75   // We don't need the shutdown observer anymore
    76   this.observerServiceObserver_.unregister();
    77 }
    79 /**
    80  * Invoked by the timer when it fires
    81  * 
    82  * @param timer Reference to the nsITimer which fired (not currently 
    83  *              passed along)
    84  */
    85 G_Alarm.prototype.notify = function(timer) {
    86   // fire callback and save results
    87   var ret = this.callback_();
    89   // If they've given us a max number of times to fire, enforce it
    90   this.nTimes_++;
    91   if (this.repeating_ && 
    92       typeof this.maxTimes_ == "number" 
    93       && this.nTimes_ >= this.maxTimes_) {
    94     this.cancel();
    95   } else if (!this.repeating_) {
    96     // Clear out the callback closure for TYPE_ONE_SHOT timers
    97     this.cancel();
    98   }
    99   // We don't cancel/cleanup timers that repeat forever until either
   100   // xpcom-shutdown occurs or cancel() is called explicitly.
   102   return ret;
   103 }
   105 G_Alarm.prototype.setDelay = function(delay) {
   106   this.timer_.delay = delay;
   107 }
   109 /**
   110  * XPCOM cruft
   111  */
   112 G_Alarm.prototype.QueryInterface = function(iid) {
   113   if (iid.equals(Components.interfaces.nsISupports) ||
   114       iid.equals(Components.interfaces.nsITimerCallback))
   115     return this;
   117   throw Components.results.NS_ERROR_NO_INTERFACE;
   118 }
   121 /**
   122  * An alarm with the additional property that it cancels itself if its 
   123  * callback returns true.
   124  *
   125  * For parameter documentation, see G_Alarm
   126  */
   127 function G_ConditionalAlarm(callback, delayMS, opt_repeating, opt_maxTimes) {
   128   G_Alarm.call(this, callback, delayMS, opt_repeating, opt_maxTimes);
   129   this.debugZone = "conditionalalarm";
   130 }
   132 G_ConditionalAlarm.inherits(G_Alarm);
   134 /**
   135  * Invoked by the timer when it fires
   136  * 
   137  * @param timer Reference to the nsITimer which fired (not currently 
   138  *              passed along)
   139  */
   140 G_ConditionalAlarm.prototype.notify = function(timer) {
   141   // Call G_Alarm::notify
   142   var rv = G_Alarm.prototype.notify.call(this, timer);
   144   if (this.repeating_ && rv) {
   145     G_Debug(this, "Callback of a repeating alarm returned true; cancelling.");
   146     this.cancel();
   147   }
   148 }

mercurial