dom/wifi/StateMachine.jsm

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 "use strict";
     9 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
    11 Cu.import("resource://gre/modules/Services.jsm");
    13 this.EXPORTED_SYMBOLS = ["StateMachine"];
    15 const DEBUG = false;
    17 this.StateMachine = function(aDebugTag) {
    18   function debug(aMsg) {
    19     dump('-------------- StateMachine:' + aDebugTag + ': ' + aMsg);
    20   }
    22   var sm = {};
    24   var _initialState;
    25   var _curState;
    26   var _prevState;
    27   var _paused;
    28   var _eventQueue = [];
    29   var _deferredEventQueue = [];
    30   var _defaultEventHandler;
    32   // Public interfaces.
    34   sm.setDefaultEventHandler = function(aDefaultEventHandler) {
    35     _defaultEventHandler = aDefaultEventHandler;
    36   };
    38   sm.start = function(aInitialState) {
    39     _initialState = aInitialState;
    40     sm.gotoState(_initialState);
    41   };
    43   sm.sendEvent = function (aEvent) {
    44     if (!_initialState) {
    45       if (DEBUG) {
    46         debug('StateMachine is not running. Call StateMachine.start() first.');
    47       }
    48       return;
    49     }
    50     _eventQueue.push(aEvent);
    51     asyncCall(handleFirstEvent);
    52   };
    54   sm.getPreviousState = function() {
    55     return _prevState;
    56   };
    58   sm.getCurrentState = function() {
    59     return _curState;
    60   };
    62   // State object maker.
    63   // @param aName string for this state's name.
    64   // @param aDelegate object:
    65   //    .handleEvent: required.
    66   //    .enter: called before entering this state (optional).
    67   //    .exit: called before exiting this state (optional).
    68   sm.makeState = function (aName, aDelegate) {
    69     if (!aDelegate.handleEvent) {
    70       throw "handleEvent is a required delegate function.";
    71     }
    72     var nop = function() {};
    73     return {
    74       name: aName,
    75       enter: (aDelegate.enter || nop),
    76       exit: (aDelegate.exit || nop),
    77       handleEvent: aDelegate.handleEvent
    78     };
    79   };
    81   sm.deferEvent = function (aEvent) {
    82     // The definition of a 'deferred event' is:
    83     //     We are not able to handle this event now but after receiving
    84     //     certain event or entering a new state, we might be able to handle
    85     //     it. For example, we couldn't handle CONNECT_EVENT in the
    86     //     diconnecting state. But once we finish doing "disconnecting", we
    87     //     could then handle CONNECT_EVENT!
    88     //
    89     // So, the deferred event may be handled in the following cases:
    90     //     1. Once we entered a new state.
    91     //     2. Once we handled a regular event.
    92     if (DEBUG) {
    93       debug('Deferring event: ' + JSON.stringify(aEvent));
    94     }
    95     _deferredEventQueue.push(aEvent);
    96   };
    98   // Goto the new state. If the current state is null, the exit
    99   // function won't be called.
   100   sm.gotoState = function (aNewState) {
   101     if (_curState) {
   102       if (DEBUG) {
   103         debug("exiting state: " + _curState.name);
   104       }
   105       _curState.exit();
   106     }
   108     _prevState = _curState;
   109     _curState = aNewState;
   111     if (DEBUG) {
   112       debug("entering state: " + _curState.name);
   113     }
   114     _curState.enter();
   116     // We are in the new state now. We got a chance to handle the
   117     // deferred events.
   118     handleDeferredEvents();
   120     sm.resume();
   121   };
   123   // No incoming event will be handled after you call pause().
   124   // (But they will be queued.)
   125   sm.pause = function() {
   126     _paused = true;
   127   };
   129   // Continue to handle incoming events.
   130   sm.resume = function() {
   131     _paused = false;
   132     asyncCall(handleFirstEvent);
   133   };
   135   //----------------------------------------------------------
   136   // Private stuff
   137   //----------------------------------------------------------
   139   function asyncCall(f) {
   140     Services.tm.currentThread.dispatch(f, Ci.nsIThread.DISPATCH_NORMAL);
   141   }
   143   function handleFirstEvent() {
   144     var hadDeferredEvents;
   146     if (0 === _eventQueue.length) {
   147       return;
   148     }
   150     if (_paused) {
   151       return; // The state machine is paused now.
   152     }
   154     hadDeferredEvents = _deferredEventQueue.length > 0;
   156     handleOneEvent(_eventQueue.shift()); // The handler may defer this event.
   158     // We've handled one event. If we had deferred events before, now is
   159     // a good chance to handle them.
   160     if (hadDeferredEvents) {
   161       handleDeferredEvents();
   162     }
   164     // Continue to handle the next regular event.
   165     handleFirstEvent();
   166   }
   168   function handleDeferredEvents() {
   169     if (_deferredEventQueue.length && DEBUG) {
   170       debug('Handle deferred events: ' + _deferredEventQueue.length);
   171     }
   172     for (let i = 0; i < _deferredEventQueue.length; i++) {
   173       handleOneEvent(_deferredEventQueue.shift());
   174     }
   175   }
   177   function handleOneEvent(aEvent)
   178   {
   179     if (DEBUG) {
   180       debug('Handling event: ' + JSON.stringify(aEvent));
   181     }
   183     var handled = _curState.handleEvent(aEvent);
   185     if (undefined === handled) {
   186       throw "handleEvent returns undefined: " + _curState.name;
   187     }
   188     if (!handled) {
   189       // Event is not handled in the current state. Try handleEventCommon().
   190       handled = (_defaultEventHandler ? _defaultEventHandler(aEvent) : handled);
   191     }
   192     if (undefined === handled) {
   193       throw "handleEventCommon returns undefined: " + _curState.name;
   194     }
   195     if (!handled) {
   196       if (DEBUG) {
   197         debug('!!!!!!!!! FIXME !!!!!!!!! Event not handled: ' + JSON.stringify(aEvent));
   198       }
   199     }
   201     return handled;
   202   }
   204   return sm;
   205 };

mercurial