<commit_before>"use strict";

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _react = require("react");

var _react2 = _interopRequireDefault(_react);

var _ButtonIcon = require("../SLDSIcon/ButtonIcon");

var _ButtonIcon2 = _interopRequireDefault(_ButtonIcon);

var _trigger = require("../SLDSPopoverTooltip/trigger");

var _trigger2 = _interopRequireDefault(_trigger);

var _lodash = require("lodash.omit");

var _lodash2 = _interopRequireDefault(_lodash);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*
                                                                                Copyright (c) 2015, salesforce.com, inc. All rights reserved.

                                                                                Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
                                                                                Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
                                                                                Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
                                                                                Neither the name of salesforce.com, inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

                                                                                THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                                                                                */

var classNames = require("classnames");

var displayName = 'SLDSButton';
var propTypes = {
  /**
   * Text that is visually hidden but read aloud by screenreaders to tell the user what the icon means.
   * If the button has an icon and a visible label, you can omit the assistiveText prop and use the label prop.
   */
  assistiveText: _react2.default.PropTypes.string,
  disabled: _react2.default.PropTypes.bool,
  /**
   * Please reference Lightning Design System Buttons > Hint.
   */
  hint: _react2.default.PropTypes.bool,
  /**
   * Name of the icon. Visit Lightning Design System Icons to reference icon names.
   */
  iconName: _react2.default.PropTypes.string,
  /**
   * If omitted, icon position is centered.
   */
  iconPosition: _react2.default.PropTypes.oneOf(["left", "right"]),
  iconSize: _react2.default.PropTypes.oneOf(["x-small", "small", "medium", "large"]),
  /**
   * For icon variants, please reference Lightning Design System Icons.
   */
  iconVariant: _react2.default.PropTypes.oneOf(["bare", "container", "border", "border-filled", "small", "more"]),
  /**
   * Visible label on the button. If the button is an icon button with no label, you must use the assistiveText prop.
   */
  label: _react2.default.PropTypes.string,
  onClick: _react2.default.PropTypes.func,
  /**
   * If true, button scales to 100% width on small form factors.
   */
  responsive: _react2.default.PropTypes.bool,
  /**
   * Write "-1" if you don't want the user to tab to the button.
   */
  tabIndex: _react2.default.PropTypes.string,
  tooltip: _react2.default.PropTypes.node,
  /**
   * Use icon-inverse for white icons.
   */
  variant: _react2.default.PropTypes.oneOf(["base", "neutral", "brand", "destructive", "icon", "inverse", "icon-inverse"])
};
var defaultProps = {
  disabled: false,
  hint: false,
  iconSize: "medium",
  responsive: false,
  variant: "neutral"
};

/**
 * The SLDSButton component is the Lightning Design System Button component. The SLDSButton should be used for label buttons, icon buttons, or buttons that have both labels and icons.
 * Either a label or assistiveText is required; see the Prop Details table below.
 * For buttons that maintain selected/unselected states, use the SLDSButtonStateful component.
 */

var SLDSButton = function (_SLDSTooltipTrigger) {
  _inherits(SLDSButton, _SLDSTooltipTrigger);

  function SLDSButton(props) {
    _classCallCheck(this, SLDSButton);

    var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(SLDSButton).call(this, props));

    _this.state = { active: false };
    return _this;
  }

  _createClass(SLDSButton, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      _get(Object.getPrototypeOf(SLDSButton.prototype), "componentDidMount", this).call(this);
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      _get(Object.getPrototypeOf(SLDSButton.prototype), "componentWillUnmount", this).call(this);
    }
  }, {
    key: "handleClick",
    value: function handleClick() {
      if (this.props.onClick) this.props.onClick();
      this.setState({ active: !this.state.active });
    }
  }, {
    key: "getClassName",
    value: function getClassName() {
      var _classNames;

      var iconOnly = this.props.variant === 'icon' ? true : false;
      var base = this.props.variant === 'base' ? true : false;

      return classNames(this.props.className, "slds-button", (_classNames = {}, _defineProperty(_classNames, "slds-button--" + this.props.variant, !base && !iconOnly), _defineProperty(_classNames, "slds-button--icon-" + this.props.iconVariant, this.props.iconVariant), _defineProperty(_classNames, "slds-max-small-button--stretch", this.props.responsive), _classNames));
    }
  }, {
    key: "renderIcon",
    value: function renderIcon(name) {
      if (this.props.iconName) {
        var iconSize = this.props.iconSize === '' ? null : this.props.iconSize;
        return _react2.default.createElement(_ButtonIcon2.default, {
          hint: this.props.hint,
          name: name,
          position: this.props.iconPosition,
          size: iconSize
        });
      }
    }
  }, {
    key: "renderIconMore",
    value: function renderIconMore() {
      if (this.props.iconVariant === "more") {
        return _react2.default.createElement(_ButtonIcon2.default, {
          name: "down",
          size: "x-small"
        });
      }
    }
  }, {
    key: "renderLabel",
    value: function renderLabel() {
      var iconOnly = this.props.variant === "icon" || this.props.variant === "icon-inverse";
      return iconOnly && this.props.assistiveText ? _react2.default.createElement(
        "span",
        { className: "slds-assistive-text" },
        this.props.assistiveText
      ) : _react2.default.createElement(
        "span",
        null,
        this.props.label
      );
    }
  }, {
    key: "render",
    value: function render() {
      var props = (0, _lodash2.default)(this.props, ["className", "label", "onClick"]);
      if (this.props.disabled) props["disabled"] = "disabled";

      return _react2.default.createElement(
        "button",
        _extends({ className: this.getClassName(), onClick: this.handleClick.bind(this) }, props),
        this.props.iconPosition === "right" ? this.renderLabel() : null,
        this.renderIcon(this.props.iconName),
        this.renderIconMore(),
        this.props.iconPosition !== "right" ? this.renderLabel() : null,
        this.props.children,
        this.getTooltip()
      );
    }
  }]);

  return SLDSButton;
}(_trigger2.default);

SLDSButton.displayName = displayName;
SLDSButton.propTypes = propTypes;
SLDSButton.defaultProps = defaultProps;

module.exports = SLDSButton;<commit_msg>fixing button2<commit_after>"use strict";

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _react = require("react");

var _react2 = _interopRequireDefault(_react);

var _ButtonIcon = require("../SLDSIcon/ButtonIcon");

var _ButtonIcon2 = _interopRequireDefault(_ButtonIcon);

var _trigger = require("../SLDSPopoverTooltip/trigger");

var _trigger2 = _interopRequireDefault(_trigger);

var _lodash = require("lodash.omit");

var _lodash2 = _interopRequireDefault(_lodash);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*
                                                                                Copyright (c) 2015, salesforce.com, inc. All rights reserved.

                                                                                Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
                                                                                Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
                                                                                Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
                                                                                Neither the name of salesforce.com, inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

                                                                                THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                                                                                */

var classNames = require("classnames");

var displayName = 'SLDSButton';
var propTypes = {
  /**
   * Text that is visually hidden but read aloud by screenreaders to tell the user what the icon means.
   * If the button has an icon and a visible label, you can omit the assistiveText prop and use the label prop.
   */
  assistiveText: _react2.default.PropTypes.string,
  disabled: _react2.default.PropTypes.bool,
  /**
   * Please reference Lightning Design System Buttons > Hint.
   */
  hint: _react2.default.PropTypes.bool,
  /**
   * Name of the icon. Visit Lightning Design System Icons to reference icon names.
   */
  iconName: _react2.default.PropTypes.string,
  /**
   * If omitted, icon position is centered.
   */
  iconPosition: _react2.default.PropTypes.oneOf(["left", "right"]),
  iconSize: _react2.default.PropTypes.oneOf(["x-small", "small", "medium", "large"]),
  /**
   * For icon variants, please reference Lightning Design System Icons.
   */
  iconVariant: _react2.default.PropTypes.oneOf(["bare", "container", "border", "border-filled", "small", "more"]),
  /**
   * Visible label on the button. If the button is an icon button with no label, you must use the assistiveText prop.
   */
  label: _react2.default.PropTypes.string,
  onClick: _react2.default.PropTypes.func,
  /**
   * If true, button scales to 100% width on small form factors.
   */
  responsive: _react2.default.PropTypes.bool,
  /**
   * Write "-1" if you don't want the user to tab to the button.
   */
  tabIndex: _react2.default.PropTypes.string,
  tooltip: _react2.default.PropTypes.node,
  /**
   * Use icon-inverse for white icons.
   */
  variant: _react2.default.PropTypes.oneOf(["base", "neutral", "brand", "destructive", "icon", "inverse", "icon-inverse"])
};
var defaultProps = {
  disabled: false,
  hint: false,
  iconSize: "medium",
  responsive: false,
  variant: "neutral"
};

/**
 * The SLDSButton component is the Lightning Design System Button component. The SLDSButton should be used for label buttons, icon buttons, or buttons that have both labels and icons.
 * Either a label or assistiveText is required; see the Prop Details table below.
 * For buttons that maintain selected/unselected states, use the SLDSButtonStateful component.
 */

var SLDSButton = function (_SLDSTooltipTrigger) {
  _inherits(SLDSButton, _SLDSTooltipTrigger);

  function SLDSButton(props) {
    _classCallCheck(this, SLDSButton);

    var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(SLDSButton).call(this, props));

    _this.state = { active: false };
    return _this;
  }

  _createClass(SLDSButton, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      _get(Object.getPrototypeOf(SLDSButton.prototype), "componentDidMount", this).call(this);
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      _get(Object.getPrototypeOf(SLDSButton.prototype), "componentWillUnmount", this).call(this);
    }
  }, {
    key: "handleClick",
    value: function handleClick(e) {
      if (this.props.onClick) this.props.onClick(e);
      this.setState({ active: !this.state.active });
    }
  }, {
    key: "getClassName",
    value: function getClassName() {
      var _classNames;

      var iconOnly = this.props.variant === 'icon' ? true : false;
      var base = this.props.variant === 'base' ? true : false;

      return classNames(this.props.className, "slds-button", (_classNames = {}, _defineProperty(_classNames, "slds-button--" + this.props.variant, !base && !iconOnly), _defineProperty(_classNames, "slds-button--icon-" + this.props.iconVariant, this.props.iconVariant), _defineProperty(_classNames, "slds-max-small-button--stretch", this.props.responsive), _classNames));
    }
  }, {
    key: "renderIcon",
    value: function renderIcon(name) {
      if (this.props.iconName) {
        var iconSize = this.props.iconSize === '' ? null : this.props.iconSize;
        return _react2.default.createElement(_ButtonIcon2.default, {
          hint: this.props.hint,
          name: name,
          position: this.props.iconPosition,
          size: iconSize
        });
      }
    }
  }, {
    key: "renderIconMore",
    value: function renderIconMore() {
      if (this.props.iconVariant === "more") {
        return _react2.default.createElement(_ButtonIcon2.default, {
          name: "down",
          size: "x-small"
        });
      }
    }
  }, {
    key: "renderLabel",
    value: function renderLabel() {
      var iconOnly = this.props.variant === "icon" || this.props.variant === "icon-inverse";
      return iconOnly && this.props.assistiveText ? _react2.default.createElement(
        "span",
        { className: "slds-assistive-text" },
        this.props.assistiveText
      ) : _react2.default.createElement(
        "span",
        null,
        this.props.label
      );
    }
  }, {
    key: "render",
    value: function render() {
      var props = (0, _lodash2.default)(this.props, ["className", "label", "onClick"]);
      if (this.props.disabled) props["disabled"] = "disabled";

      return _react2.default.createElement(
        "button",
        _extends({ className: this.getClassName(), onClick: this.handleClick.bind(this) }, props),
        this.props.iconPosition === "right" ? this.renderLabel() : null,
        this.renderIcon(this.props.iconName),
        this.renderIconMore(),
        this.props.iconPosition !== "right" ? this.renderLabel() : null,
        this.props.children,
        this.getTooltip()
      );
    }
  }]);

  return SLDSButton;
}(_trigger2.default);

SLDSButton.displayName = displayName;
SLDSButton.propTypes = propTypes;
SLDSButton.defaultProps = defaultProps;

module.exports = SLDSButton;<|endoftext|>


<commit_before>var uuid = require('node-uuid');

module.exports = {
  loadPriority:  400,
  initialize: function(api, next){

    api.connections = {

      middleware: {},
      globalMiddleware: [],

      allowedVerbs: [
        'quit',
        'exit',
        'documentation',
        'paramAdd',
        'paramDelete',
        'paramView',
        'paramsView',
        'paramsDelete',
        'roomAdd',
        'roomLeave',
        'roomView',
        'detailsView',
        'say'
      ],

      connections: {},

      apply: function(connectionId, method, args, callback){
        if(args === undefined && callback === undefined && typeof method === 'function'){
          callback = method; args = null; method = null;
        }
        api.redis.doCluster('api.connections.applyCatch', [connectionId, method, args], connectionId, callback);
      },

      applyCatch: function(connectionId, method, args, callback){
        var connection = api.connections.connections[connectionId];
        if(method && args){
          if(method === 'sendMessage' || method === 'sendFile'){
            connection[method](args);
          }else{
            connection[method].apply(connection, args);
          }
        }
        if(typeof callback === 'function'){
          process.nextTick(function(){
            callback(cleanConnection(connection));
          });
        }
      },

      addMiddleware: function(data){
        if(!data.name){ throw new Error('middleware.name is required'); }
        if(!data.priority){ data.priority = api.config.general.defaultMiddlewarePriority; }
        data.priority = Number(data.priority);
        api.connections.middleware[data.name] = data;

        this.globalMiddleware.push(data.name);
        this.globalMiddleware.sort(function(a,b){
          if(api.connections.middleware[a].priority > api.connections.middleware[b].priority){
            return 1;
          }else{
            return -1;
          }
        });
      }
    };

    var cleanConnection = function(connection){
      var clean = {};
      for(var i in connection){
        if(i !== 'rawConnection'){
          clean[i] = connection[i];
        }
      }
      return clean;
    }

    // {type: type, remotePort: remotePort, remoteIP: remoteIP, rawConnection: rawConnection}
    // id is optional and will be generated if missing
    api.connection = function(data){
      var self = this;
      self.setup(data)
      api.connections.connections[self.id] = self;

      api.connections.globalMiddleware.forEach(function(middlewareName){
        if(typeof api.connections.middleware[middlewareName].create === 'function'){
          api.connections.middleware[middlewareName].create(self);
        }
      });
    }

    api.connection.prototype.setup = function(data){
      var self = this;
      if(data.id){
        self.id = data.id;
      } else {
        self.id = self.generateID();
      }
      self.connectedAt = new Date().getTime();

      ['type', 'rawConnection'].forEach(function(req){
        if(data[req] === null || data[req] === undefined){ throw new Error(req + ' is required to create a new connection object') }
        self[req] = data[req];
      });

      ['remotePort', 'remoteIP'].forEach(function(req){
        if(data[req] === null || data[req] === undefined){
          if(api.config.general.enforceConnectionProperties === true){
            throw new Error(req + ' is required to create a new connection object')
          }else{
            data[req] = 0; // could be a random uuid as well?
          }
        }
        self[req] = data[req];
      });

      var connectionDefaults = {
        error: null,
        fingerprint: null,
        rooms: [],
        params: {},
        pendingActions: 0,
        totalActions: 0,
        messageCount: 0,
        canChat: false
      }

      for(var i in connectionDefaults){
        if(self[i] === undefined && data[i] !== undefined){ self[i] = data[i]; }
        if(self[i] === undefined){ self[i] = connectionDefaults[i]; }
      }
    }

    api.connection.prototype.generateID = function(){
      return uuid.v4();
    }

    api.connection.prototype.sendMessage = function(message){
      throw new Error('I should be replaced with a connection-specific method ['+message+']');
    }

    api.connection.prototype.sendFile = function(path){
      throw new Error('I should be replaced with a connection-specific method ['+path+']');
    }

    api.connection.prototype.destroy = function(callback){
      var self = this;
      self.destroyed = true;

      api.connections.globalMiddleware.forEach(function(middlewareName){
        if(typeof api.connections.middleware[middlewareName].destroy === 'function'){
          api.connections.middleware[middlewareName].destroy(self);
        }
      });

      if(self.canChat === true){
        self.rooms.forEach(function(room){
          api.chatRoom.removeMember(self.id, room);
        });
      }
      delete api.connections.connections[self.id];
      var server = api.servers.servers[self.type];
      if(server){
        if(server.attributes.logExits === true){
          server.log('connection closed', 'info', {to: self.remoteIP});
        }
        if(typeof server.goodbye === 'function'){ server.goodbye(self); }
      }
      if(typeof callback === 'function'){ callback() }
    }

    api.connection.prototype.set = function(key, value){
      var self = this;
      self[key] = value;
    }

    api.connection.prototype.verbs = function(verb, words, callback){
      var self = this;
      var key, value, room;
      var server = api.servers.servers[self.type];
      var allowedVerbs = server.attributes.verbs;
      if(typeof words === 'function' && !callback){
        callback = words;
        words = [];
      }
      if(!(words instanceof Array)){
        words = [words];
      }
      if(server && allowedVerbs.indexOf(verb) >= 0){
        server.log('verb', 'debug', {verb: verb, to: self.remoteIP, params: JSON.stringify(words)});
        if(verb === 'quit' || verb === 'exit'){
          server.goodbye(self);

        } else if(verb === 'paramAdd'){
          key = words[0];
          value = words[1];
          if(words[0].indexOf('=') >= 0){
            var parts = words[0].split('=');
            key = parts[0];
            value = parts[1];
          }
          if(api.config.general.disableParamScrubbing || api.params.postVariables.indexOf(key) > 0){
            self.params[key] = value;
          }
          if(typeof callback === 'function'){ callback(null, null); }
        } else if(verb === 'paramDelete'){
          key = words[0];
          delete self.params[key];
          if(typeof callback === 'function'){ callback(null, null); }

        } else if(verb === 'paramView'){
          key = words[0];
          if(typeof callback === 'function'){ callback(null, self.params[key]); }

        } else if(verb === 'paramsView'){
          if(typeof callback === 'function'){ callback(null, self.params); }

        } else if(verb === 'paramsDelete'){
          for(var i in self.params){
            delete self.params[i];
          }
          if(typeof callback === 'function'){ callback(null, null); }

        } else if(verb === 'roomAdd'){
          room = words[0];
          api.chatRoom.addMember(self.id, room, function(err, didHappen){
            if(typeof callback === 'function'){ callback(err, didHappen); }
          });

        } else if(verb === 'roomLeave'){
          room = words[0];
          api.chatRoom.removeMember(self.id, room, function(err, didHappen){
            if(typeof callback === 'function'){ callback(err, didHappen); }
          });

        } else if(verb === 'roomView'){
          room = words[0];
          if(self.rooms.indexOf(room) > -1){
            api.chatRoom.roomStatus(room, function(err, roomStatus){
              if(typeof callback === 'function'){ callback(err, roomStatus); }
            });
          }else{
            if(typeof callback === 'function'){ callback('not member of room ' + room); }
          }

        } else if(verb === 'detailsView'){
          var details            = {};
          details.id             = self.id;
          details.fingerprint    = self.fingerprint;
          details.remoteIP       = self.remoteIP;
          details.remotePort     = self.remotePort;
          details.params         = self.params;
          details.connectedAt    = self.connectedAt;
          details.rooms          = self.rooms;
          details.totalActions   = self.totalActions;
          details.pendingActions = self.pendingActions;
          if(typeof callback === 'function'){ callback(null, details); }

        } else if(verb === 'documentation'){
          if(typeof callback === 'function'){ callback(null, api.documentation.documentation); }

        } else if(verb === 'say'){
          room = words.shift();
          api.chatRoom.broadcast(self, room, words.join(' '), function(err){
            if(typeof callback === 'function'){ callback(err); }
          });

        } else {
          if(typeof callback === 'function'){ callback(api.config.errors.verbNotFound(verb), null); }
        }
      } else {
        if(typeof callback === 'function'){ callback(api.config.errors.verbNotAllowed(verb), null); }
      }
    }

    next();
  }
}<commit_msg>fix(initializers): paramAdd with no params raises TypeError<commit_after>var uuid = require('node-uuid');

module.exports = {
  loadPriority:  400,
  initialize: function(api, next){

    api.connections = {

      middleware: {},
      globalMiddleware: [],

      allowedVerbs: [
        'quit',
        'exit',
        'documentation',
        'paramAdd',
        'paramDelete',
        'paramView',
        'paramsView',
        'paramsDelete',
        'roomAdd',
        'roomLeave',
        'roomView',
        'detailsView',
        'say'
      ],

      connections: {},

      apply: function(connectionId, method, args, callback){
        if(args === undefined && callback === undefined && typeof method === 'function'){
          callback = method; args = null; method = null;
        }
        api.redis.doCluster('api.connections.applyCatch', [connectionId, method, args], connectionId, callback);
      },

      applyCatch: function(connectionId, method, args, callback){
        var connection = api.connections.connections[connectionId];
        if(method && args){
          if(method === 'sendMessage' || method === 'sendFile'){
            connection[method](args);
          }else{
            connection[method].apply(connection, args);
          }
        }
        if(typeof callback === 'function'){
          process.nextTick(function(){
            callback(cleanConnection(connection));
          });
        }
      },

      addMiddleware: function(data){
        if(!data.name){ throw new Error('middleware.name is required'); }
        if(!data.priority){ data.priority = api.config.general.defaultMiddlewarePriority; }
        data.priority = Number(data.priority);
        api.connections.middleware[data.name] = data;

        this.globalMiddleware.push(data.name);
        this.globalMiddleware.sort(function(a,b){
          if(api.connections.middleware[a].priority > api.connections.middleware[b].priority){
            return 1;
          }else{
            return -1;
          }
        });
      }
    };

    var cleanConnection = function(connection){
      var clean = {};
      for(var i in connection){
        if(i !== 'rawConnection'){
          clean[i] = connection[i];
        }
      }
      return clean;
    }

    // {type: type, remotePort: remotePort, remoteIP: remoteIP, rawConnection: rawConnection}
    // id is optional and will be generated if missing
    api.connection = function(data){
      var self = this;
      self.setup(data)
      api.connections.connections[self.id] = self;

      api.connections.globalMiddleware.forEach(function(middlewareName){
        if(typeof api.connections.middleware[middlewareName].create === 'function'){
          api.connections.middleware[middlewareName].create(self);
        }
      });
    }

    api.connection.prototype.setup = function(data){
      var self = this;
      if(data.id){
        self.id = data.id;
      } else {
        self.id = self.generateID();
      }
      self.connectedAt = new Date().getTime();

      ['type', 'rawConnection'].forEach(function(req){
        if(data[req] === null || data[req] === undefined){ throw new Error(req + ' is required to create a new connection object') }
        self[req] = data[req];
      });

      ['remotePort', 'remoteIP'].forEach(function(req){
        if(data[req] === null || data[req] === undefined){
          if(api.config.general.enforceConnectionProperties === true){
            throw new Error(req + ' is required to create a new connection object')
          }else{
            data[req] = 0; // could be a random uuid as well?
          }
        }
        self[req] = data[req];
      });

      var connectionDefaults = {
        error: null,
        fingerprint: null,
        rooms: [],
        params: {},
        pendingActions: 0,
        totalActions: 0,
        messageCount: 0,
        canChat: false
      }

      for(var i in connectionDefaults){
        if(self[i] === undefined && data[i] !== undefined){ self[i] = data[i]; }
        if(self[i] === undefined){ self[i] = connectionDefaults[i]; }
      }
    }

    api.connection.prototype.generateID = function(){
      return uuid.v4();
    }

    api.connection.prototype.sendMessage = function(message){
      throw new Error('I should be replaced with a connection-specific method ['+message+']');
    }

    api.connection.prototype.sendFile = function(path){
      throw new Error('I should be replaced with a connection-specific method ['+path+']');
    }

    api.connection.prototype.destroy = function(callback){
      var self = this;
      self.destroyed = true;

      api.connections.globalMiddleware.forEach(function(middlewareName){
        if(typeof api.connections.middleware[middlewareName].destroy === 'function'){
          api.connections.middleware[middlewareName].destroy(self);
        }
      });

      if(self.canChat === true){
        self.rooms.forEach(function(room){
          api.chatRoom.removeMember(self.id, room);
        });
      }
      delete api.connections.connections[self.id];
      var server = api.servers.servers[self.type];
      if(server){
        if(server.attributes.logExits === true){
          server.log('connection closed', 'info', {to: self.remoteIP});
        }
        if(typeof server.goodbye === 'function'){ server.goodbye(self); }
      }
      if(typeof callback === 'function'){ callback() }
    }

    api.connection.prototype.set = function(key, value){
      var self = this;
      self[key] = value;
    }

    api.connection.prototype.verbs = function(verb, words, callback){
      var self = this;
      var key, value, room;
      var server = api.servers.servers[self.type];
      var allowedVerbs = server.attributes.verbs;
      if(typeof words === 'function' && !callback){
        callback = words;
        words = [];
      }
      if(!(words instanceof Array)){
        words = [words];
      }
      if(server && allowedVerbs.indexOf(verb) >= 0){
        server.log('verb', 'debug', {verb: verb, to: self.remoteIP, params: JSON.stringify(words)});
        if(verb === 'quit' || verb === 'exit'){
          server.goodbye(self);

        } else if(verb === 'paramAdd'){
          key = words[0];
          value = words[1];
          if((words[0]) && (words[0].indexOf('=') >= 0)){
            var parts = words[0].split('=');
            key = parts[0];
            value = parts[1];
          }
          if(api.config.general.disableParamScrubbing || api.params.postVariables.indexOf(key) > 0){
            self.params[key] = value;
          }
          if(typeof callback === 'function'){ callback(null, null); }
        } else if(verb === 'paramDelete'){
          key = words[0];
          delete self.params[key];
          if(typeof callback === 'function'){ callback(null, null); }

        } else if(verb === 'paramView'){
          key = words[0];
          if(typeof callback === 'function'){ callback(null, self.params[key]); }

        } else if(verb === 'paramsView'){
          if(typeof callback === 'function'){ callback(null, self.params); }

        } else if(verb === 'paramsDelete'){
          for(var i in self.params){
            delete self.params[i];
          }
          if(typeof callback === 'function'){ callback(null, null); }

        } else if(verb === 'roomAdd'){
          room = words[0];
          api.chatRoom.addMember(self.id, room, function(err, didHappen){
            if(typeof callback === 'function'){ callback(err, didHappen); }
          });

        } else if(verb === 'roomLeave'){
          room = words[0];
          api.chatRoom.removeMember(self.id, room, function(err, didHappen){
            if(typeof callback === 'function'){ callback(err, didHappen); }
          });

        } else if(verb === 'roomView'){
          room = words[0];
          if(self.rooms.indexOf(room) > -1){
            api.chatRoom.roomStatus(room, function(err, roomStatus){
              if(typeof callback === 'function'){ callback(err, roomStatus); }
            });
          }else{
            if(typeof callback === 'function'){ callback('not member of room ' + room); }
          }

        } else if(verb === 'detailsView'){
          var details            = {};
          details.id             = self.id;
          details.fingerprint    = self.fingerprint;
          details.remoteIP       = self.remoteIP;
          details.remotePort     = self.remotePort;
          details.params         = self.params;
          details.connectedAt    = self.connectedAt;
          details.rooms          = self.rooms;
          details.totalActions   = self.totalActions;
          details.pendingActions = self.pendingActions;
          if(typeof callback === 'function'){ callback(null, details); }

        } else if(verb === 'documentation'){
          if(typeof callback === 'function'){ callback(null, api.documentation.documentation); }

        } else if(verb === 'say'){
          room = words.shift();
          api.chatRoom.broadcast(self, room, words.join(' '), function(err){
            if(typeof callback === 'function'){ callback(err); }
          });

        } else {
          if(typeof callback === 'function'){ callback(api.config.errors.verbNotFound(verb), null); }
        }
      } else {
        if(typeof callback === 'function'){ callback(api.config.errors.verbNotAllowed(verb), null); }
      }
    }

    next();
  }
}
<|endoftext|>


<commit_before>var CandyShop = (function(self) { return self; }(CandyShop || {}));

CandyShop.Emphasis = (function(self, Candy, $) {

	// textile, bbcode, old html, escaped old html, new html, escaped new html
	self.styles = [
		{ plain: '*bold*', regex: /((^|\s|\>)\*(.*?)\*(\s|\<|$))/gm, plain: "$2*$3*$4", xhtml: "$2$3$4" },
		{ plain: '[b]bold[/b]', regex: /(\[b\](.*?)\[\/b\])/igm, plain: "*$2*", xhtml: "$2" },
		{ plain: '<b>bold</b>', regex: /(\<b\>(.*?)\<\/b\>)/igm, plain: "*$2*", xhtml: "$2" },
		{ plain: '<strong>bold</strong>', regex: /(\<strong\>(.*?)\<\/strong\>)/igm, plain: "*$2*", xhtml: "$2" },
		{ plain: '_italic_', regex: /((^|\s|\>)\_(.*?)\_(\s|\<|$))/gm, plain: "$2_$3_$4", xhtml: "$2$3$4" },
		{ plain: '[i]italic[/i]', regex: /(\[i\](.*?)\[\/i\])/igm, plain: "_$2_", xhtml: "$2" },
		{ plain: '<i>italic</i>', regex: /(\<i\>(.*?)\<\/i\>)/igm, plain: "_$2_", xhtml: "$2" },
		{ plain: '<em>italic</em>', regex: /(\<em\>(.*?)\<\/em\>)/igm, plain: "_$2_", xhtml: "$2" },
		{ plain: '-strikethrough-', regex: /((^|\s|\>)\-(.*?)\-(\s|\<|$))/gm, plain: "$2-$3-$4", xhtml: "$2$3$4" },
		{ plain: '[s]strikethrough[/s]', regex: /(\[s\](.*?)\[\/s\])/igm, plain: "-$2-", xhtml: "$2" },
		{ plain: '<s>strikethrough</s>', regex: /(\<s\>(.*?)\<\/s\>)/igm, plain: "-$2-", xhtml: "$2" },
		{ plain: '<del>strikethrough</del>', regex: /(\<del\>(.*?)\<\/del\>)/igm, plain: "-$2-", xhtml: "$2" },
		{ plain: '+underline+', regex: /((^|\s|\>)\+(.*?)\+(\s|\<|$))/gm, plain: "$2+$3+$4", xhtml: "$2$3$4" },
		{ plain: '[u]underline[/u]', regex: /(\[u\](.*?)\[\/u\])/igm, plain: "+$2+", xhtml: "$2" },
		{ plain: '<u>underline</u>', regex: /(\<u\>(.*?)\<\/u\>)/igm, plain: "+$2+", xhtml: "$2" },
		{ plain: '<ins>underline</ins>', regex: /(\<ins\>(.*?)\<\/ins\>)/igm, plain: "+$2+", xhtml: "$2" }
		]

	self.init = function() {

		$(Candy).on('candy:view.message.before-send', function(e, args) {
			var workingPlainMessage = args.message;
			var workingXhtmlMessage = args.message;

			if(args.xhtmlMessage) {
				var workingXhtmlMessage = args.xhtmlMessage;
			}

			$.each(self.styles, function(index, value){
				workingPlainMessage = workingPlainMessage.replace(value.regex, value.plain)
				workingXhtmlMessage = workingXhtmlMessage.replace(value.regex, value.xhtml)
			});

			if( workingPlainMessage != workingXhtmlMessage) {
				// strophe currently requires that xhtml have a root element. Apparently.
				// Force one node, with no external text
				if( !workingXhtmlMessage.match(/^<.*>$/) || $(workingXhtmlMessage).length != 1 ) {
					workingXhtmlMessage = "" + workingXhtmlMessage + "";
				}
				args.message = workingPlainMessage;
				args.xhtmlMessage = workingXhtmlMessage;
			}
		});

	};

	return self;
}(CandyShop.Emphasis || {}, Candy, jQuery));
<commit_msg>indentation & semicolon<commit_after>var CandyShop = (function(self) { return self; }(CandyShop || {}));

CandyShop.Emphasis = (function(self, Candy, $) {

	// textile, bbcode, old html, escaped old html, new html, escaped new html
	self.styles = [
		{ plain: '*bold*', regex: /((^|\s|\>)\*(.*?)\*(\s|\<|$))/gm, plain: "$2*$3*$4", xhtml: "$2$3$4" },
		{ plain: '[b]bold[/b]', regex: /(\[b\](.*?)\[\/b\])/igm, plain: "*$2*", xhtml: "$2" },
		{ plain: '<b>bold</b>', regex: /(\<b\>(.*?)\<\/b\>)/igm, plain: "*$2*", xhtml: "$2" },
		{ plain: '<strong>bold</strong>', regex: /(\<strong\>(.*?)\<\/strong\>)/igm, plain: "*$2*", xhtml: "$2" },
		{ plain: '_italic_', regex: /((^|\s|\>)\_(.*?)\_(\s|\<|$))/gm, plain: "$2_$3_$4", xhtml: "$2$3$4" },
		{ plain: '[i]italic[/i]', regex: /(\[i\](.*?)\[\/i\])/igm, plain: "_$2_", xhtml: "$2" },
		{ plain: '<i>italic</i>', regex: /(\<i\>(.*?)\<\/i\>)/igm, plain: "_$2_", xhtml: "$2" },
		{ plain: '<em>italic</em>', regex: /(\<em\>(.*?)\<\/em\>)/igm, plain: "_$2_", xhtml: "$2" },
		{ plain: '-strikethrough-', regex: /((^|\s|\>)\-(.*?)\-(\s|\<|$))/gm, plain: "$2-$3-$4", xhtml: "$2$3$4" },
		{ plain: '[s]strikethrough[/s]', regex: /(\[s\](.*?)\[\/s\])/igm, plain: "-$2-", xhtml: "$2" },
		{ plain: '<s>strikethrough</s>', regex: /(\<s\>(.*?)\<\/s\>)/igm, plain: "-$2-", xhtml: "$2" },
		{ plain: '<del>strikethrough</del>', regex: /(\<del\>(.*?)\<\/del\>)/igm, plain: "-$2-", xhtml: "$2" },
		{ plain: '+underline+', regex: /((^|\s|\>)\+(.*?)\+(\s|\<|$))/gm, plain: "$2+$3+$4", xhtml: "$2$3$4" },
		{ plain: '[u]underline[/u]', regex: /(\[u\](.*?)\[\/u\])/igm, plain: "+$2+", xhtml: "$2" },
		{ plain: '<u>underline</u>', regex: /(\<u\>(.*?)\<\/u\>)/igm, plain: "+$2+", xhtml: "$2" },
		{ plain: '<ins>underline</ins>', regex: /(\<ins\>(.*?)\<\/ins\>)/igm, plain: "+$2+", xhtml: "$2" }
	];

	self.init = function() {

		$(Candy).on('candy:view.message.before-send', function(e, args) {
			var workingPlainMessage = args.message;
			var workingXhtmlMessage = args.message;

			if(args.xhtmlMessage) {
				var workingXhtmlMessage = args.xhtmlMessage;
			}

			$.each(self.styles, function(index, value){
				workingPlainMessage = workingPlainMessage.replace(value.regex, value.plain)
				workingXhtmlMessage = workingXhtmlMessage.replace(value.regex, value.xhtml)
			});

			if( workingPlainMessage != workingXhtmlMessage) {
				// strophe currently requires that xhtml have a root element. Apparently.
				// Force one node, with no external text
				if( !workingXhtmlMessage.match(/^<.*>$/) || $(workingXhtmlMessage).length != 1 ) {
					workingXhtmlMessage = "" + workingXhtmlMessage + "";
				}
				args.message = workingPlainMessage;
				args.xhtmlMessage = workingXhtmlMessage;
			}
		});

	};

	return self;
}(CandyShop.Emphasis || {}, Candy, jQuery));
<|endoftext|>


<commit_before>'use strict'

import React from 'react'
import {connect} from 'react-redux'
import {login} from '../actions/auth'
import {pushPath} from 'redux-simple-router'

export const Login = React.createClass({
  componentDidMount() {
    const {isLoggedIn, dispatch} = this.props

    if (isLoggedIn) {
      dispatch(pushPath('/'))
    }
  },

  handleSubmit (event) {
    event.preventDefault()

    const {email, pass} = this.refs
    const {dispatch} = this.props

    dispatch(login(email.value, pass.value))
    email.value = ''
    pass.value = ''
  },

  render () {
    const {hasError, niceError} = this.props
    let heading = hasError ? niceError : 'Login'

    return (

            <form className="login-form col-xs-12 col-md-6 col-lg-4 txt-left form-full-width form-panel" onSubmit={this.handleSubmit}>

                {heading}

              <input ref="email" type="email" placeholder="Email" className="input-large" required />
              <input ref="pass" type="password" placeholder="Password" className="input-large" required />
              <button type="submit" className="btn btn-large submit">Submit</button>
            </form>

    )
  }
})

export default connect((state) => {
  const {hasError, niceError, isLoggedIn} = state.auth

  return {
    hasError: hasError,
    niceError: niceError,
    isLoggedIn: isLoggedIn
  }
})(Login)
<commit_msg>Small readability change based on feedback<commit_after>'use strict'

import React from 'react'
import {connect} from 'react-redux'
import {login} from '../actions/auth'
import {pushPath} from 'redux-simple-router'

export const Login = React.createClass({
  componentDidMount() {
    const {isLoggedIn, dispatch} = this.props

    if (isLoggedIn) {
      dispatch(pushPath('/'))
    }
  },

  handleSubmit (event) {
    event.preventDefault()

    const {email, pass} = this.refs
    const {dispatch} = this.props

    dispatch(login(email.value, pass.value))

    email.value = ''
    pass.value = ''
  },

  render () {
    const {hasError, niceError} = this.props
    let heading = hasError ? niceError : 'Login'

    return (

            <form className="login-form col-xs-12 col-md-6 col-lg-4 txt-left form-full-width form-panel" onSubmit={this.handleSubmit}>

                {heading}

              <input ref="email" type="email" placeholder="Email" className="input-large" required />
              <input ref="pass" type="password" placeholder="Password" className="input-large" required />
              <button type="submit" className="btn btn-large submit">Submit</button>
            </form>

    )
  }
})

export default connect((state) => {
  const {hasError, niceError, isLoggedIn} = state.auth

  return {
    hasError: hasError,
    niceError: niceError,
    isLoggedIn: isLoggedIn
  }
})(Login)
<|endoftext|>


<commit_before>import './compatibility'
import contentScriptInjector from './contentScriptInjector'
import specialPages from './specialPages'
import { defaultInterfaceSettings } from './defaults'
import disconnectingPortErrorCheck from './disconnectingPortErrorCheck'
import Logger from './logger'

const logger = new Logger()

const contentConnections = {}
const devtoolsConnections = {}
let sidebarConnection = null  // FIXME appears in Chrome; need to remove null?
let popupConnection = null
let activeTabId = null

//
// Message routing
//

function sendLandmarksToGUIs(fromTabId, message) {
	if (popupConnection) popupConnection.postMessage(message)
	if (sidebarConnection && fromTabId === activeTabId) {
		sidebarConnection.postMessage(message)
	}
	if (devtoolsConnections.hasOwnProperty(fromTabId)) {
		devtoolsConnections[fromTabId].postMessage(message)
	}
}

function sendNullLandmarksToGUIs() {
	sendLandmarksToGUIs(activeTabId, { name: 'landmarks', data: null })
}

function getLandmarksForActiveTab() {
	if (contentConnections.hasOwnProperty(activeTabId)) {
		contentConnections[activeTabId].postMessage({ name: 'get-landmarks' } )
	} else {
		sendNullLandmarksToGUIs()
	}
}

function sendToActiveContentScriptIfExists(message) {
	// The check is needed when a keyboard command is used
	if (contentConnections.hasOwnProperty(activeTabId)) {
		contentConnections[activeTabId].postMessage(message)
	}
}

function updateBrowserActionBadge(tabId, numberOfLandmarks) {
	browser.browserAction.setBadgeText({
		text: numberOfLandmarks <= 0 ? '' : String(numberOfLandmarks),
		tabId: tabId
	})
}

//
// Setting up and handling connections
//

browser.runtime.onConnect.addListener(function(connectingPort) {
	// Disconnection management

	function contentDisconnect(disconnectingPort) {
		logger.log(`Content script for tab ${disconnectingPort.sender.tab.id} disconnected`)
		disconnectingPortErrorCheck(disconnectingPort)
		delete contentConnections[disconnectingPort.sender.tab.id]
	}

	function devtoolsDisconnect(tabId) {
		logger.log(`DevTools page for tab ${tabId} disconnected`)
		delete devtoolsConnections[tabId]
	}

	// Message listeners

	function contentListener(message, sendingPort) {
		const tabId = sendingPort.sender.tab.id

		switch (message.name) {
			case 'landmarks':
				logger.log(`Got ${message.data.length} landmarks from ${sendingPort.sender.tab.url}`)
				sendLandmarksToGUIs(tabId, message)
				updateBrowserActionBadge(tabId, message.data.length)
				break
			default:
				throw Error(`Unknown message ${JSON.stringify(message)} from content script in ${sendingPort.sender.tab.id}`)
		}
	}

	function popupAndSidebarListener(message) {  // also gets: sendingPort
		switch (message.name) {
			case 'get-landmarks':
				logger.log('Popup or sidebar requested landmarks')
				getLandmarksForActiveTab()
				break
			case 'focus-landmark':
				sendToActiveContentScriptIfExists(message)
				break
			default:
				throw Error(`Unknown message ${JSON.stringify(message)} from sidebar or popup`)
		}
	}

	function devtoolsListner(message) {
		switch (message.name) {
			case 'init':
				logger.log(`DevTools page for tab ${message.tabId} connected`)
				devtoolsConnections[message.tabId] = connectingPort
				connectingPort.onDisconnect.addListener(function(disconnectingPort) {
					disconnectingPortErrorCheck(disconnectingPort)
					devtoolsDisconnect(message.tabId)
				})
				break
			case 'get-landmarks':
				logger.log('DevTools requested landmarks')
				getLandmarksForActiveTab()
				break
			case 'focus-landmark':
				sendToActiveContentScriptIfExists(message)
				break
			default:
				throw Error(`Unkown message from devtools: ${JSON.stringify(message)}`)
		}
	}

	function splashListener(message, sendingPort) {
		switch (message.name) {
			case 'get-commands':
				browser.commands.getAll(function(commands) {
					sendingPort.postMessage({
						name: 'splash-populate-commands',
						commands: commands
					})
				})
				break
			case 'splash-open-configure-shortcuts':
				// This should only appear on Chrome/Opera
				browser.tabs.create({
					url: BROWSER === 'chrome' ? 'chrome://extensions/configureCommands' : 'opera://settings/configureCommands'
				})
				break
			default:
				throw Error(`Unkown message from devtools: ${JSON.stringify(message)}`)
		}
	}

	// Connection management

	switch (connectingPort.name) {
		case 'content':
			logger.log(`Content script for tab ${connectingPort.sender.tab.id} ${connectingPort.sender.tab.url} connected`)
			contentConnections[connectingPort.sender.tab.id] = connectingPort
			connectingPort.onMessage.addListener(contentListener)
			connectingPort.onDisconnect.addListener(contentDisconnect)
			break
		case 'devtools':
			connectingPort.onMessage.addListener(devtoolsListner)
			break
		case 'popup':
			if (popupConnection !== null) {
				throw Error('Existing pop-up connection')
			}
			popupConnection = connectingPort
			connectingPort.onMessage.addListener(popupAndSidebarListener)
			connectingPort.onDisconnect.addListener(function() {
				popupConnection = null
			})
			break
		case 'sidebar':
			if (sidebarConnection !== null) {
				throw Error('Existing sidebar connection')
			}
			sidebarConnection = connectingPort
			connectingPort.onMessage.addListener(popupAndSidebarListener)
			connectingPort.onDisconnect.addListener(function() {
				sidebarConnection = null
			})
			break
		case 'splash':
			connectingPort.onMessage.addListener(splashListener)
			break
		default:
			throw Error(`Unkown connection type ${connectingPort.name}`)
	}
})

if (BROWSER === 'firefox' || BROWSER === 'opera') {
	//
	// Sidebar handling
	//

	// If the user has elected to use the sidebar, the pop-up is disabled, and
	// we will receive events, which we can then use to open the sidebar.
	//
	// Have to do this in a really hacky way at the moment due to
	// https://bugzilla.mozilla.org/show_bug.cgi?id=1438465
	// https://bugzilla.mozilla.org/show_bug.cgi?id=1398833
	//
	// Also Opera doesn't have open().

	// eslint-disable-next-line no-inner-declarations
	function openSidebarWhenClicked() {
		browser.browserAction.onClicked.removeListener(openSidebarWhenClicked)
		browser.sidebarAction.open()
		browser.browserAction.onClicked.addListener(closeSidebarWhenClicked)
	}

	// eslint-disable-next-line no-inner-declarations
	function closeSidebarWhenClicked() {
		browser.browserAction.onClicked.removeListener(closeSidebarWhenClicked)
		browser.sidebarAction.close()
		browser.browserAction.onClicked.addListener(openSidebarWhenClicked)
	}

	// eslint-disable-next-line no-inner-declarations
	function switchInterface(mode) {
		switch (mode) {
			case 'sidebar':
				browser.browserAction.setPopup({ popup: '' })

				if (BROWSER === 'firefox') {
					// The sidebar will be closed because we are setting
					// "open_at_install" to false. It might be nice to actually
					// show the sidebar at install, but isOpen() isn't usable
					// because it breaks propogation of the user input event.
					browser.browserAction.onClicked.addListener(
						openSidebarWhenClicked)
				}
				break
			case 'popup':
				// On Firefox this could be set to null to return to the
				// default popup. However Chrome/Opera doesn't support this.
				browser.browserAction.setPopup({ popup: 'popup.html' })

				if (BROWSER === 'firefox') {
					browser.browserAction.onClicked.removeListener(
						openSidebarWhenClicked)
					browser.browserAction.onClicked.removeListener(
						closeSidebarWhenClicked)
				}
				break
			default:
				throw Error(`Invalid interface "${mode}" given`)
		}
	}

	browser.storage.sync.get(defaultInterfaceSettings, function(items) {
		switchInterface(items.interface)
	})

	browser.storage.onChanged.addListener(function(changes) {
		if (changes.hasOwnProperty('interface')) {
			switchInterface(changes.interface.newValue)
		}
	})
}

//
// Keyboard shortcut handling
//

browser.commands.onCommand.addListener(function(command) {
	switch (command) {
		case 'next-landmark':
		case 'prev-landmark':
		case 'main-landmark':
		case 'show-all-landmarks':
			sendToActiveContentScriptIfExists({ name: command })
			break
		default:
			throw Error(`Unknown command ${JSON.stringify(command)}`)
	}
})

//
// Navigation and tab activation events
//

// Listen for URL change events on all tabs and disable the browser action if
// the URL does not start with 'http://' or 'https://' (or 'file://', for
// local pages).
//
// Note: This used to be wrapped in a query for the active tab, but on browser
//       startup, URL changes are going on in all tabs.
browser.webNavigation.onBeforeNavigate.addListener(function(details) {
	if (details.frameId > 0) return
	browser.browserAction.disable(details.tabId)
	browser.browserAction.setBadgeText({
		text: '',
		tabId: details.tabId
	})
})

browser.webNavigation.onCompleted.addListener(function(details) {
	if (details.frameId > 0) return
	checkBrowserActionState(details.tabId, details.url)
})

function checkBrowserActionState(tabId, url) {
	if (/^(https?|file):\/\//.test(url)) {  // TODO DRY
		for (const specialPage of specialPages) {  // TODO DRY
			if (specialPage.test(url)) {
				browser.browserAction.disable(tabId)
				return
			}
		}
		browser.browserAction.enable(tabId)
	} else {
		browser.browserAction.disable(tabId)

		// We may've moved from a page that allowed content scripts to one that
		// does not. If the sidebar/DevTools are open, they need to be updated.
		sendNullLandmarksToGUIs()
	}
}

// If the page uses 'single-page app' techniques to load in new components --
// as YouTube and GitHub do -- then the landmarks can change. We assume that if
// the structure of the page is changing so much that it is effectively a new
// page, then the developer would've followed best practice and used the
// History API to update the URL of the page, so that this 'new' page can be
// recognised as such and be bookmarked by the user. Therefore we monitor for
// use of the History API to trigger a new search for landmarks on the page.
//
// Thanks: http://stackoverflow.com/a/36818991/1485308
//
// Note: The original code had a fliter such that this would only fire if the
//       URLs of the current tab and the details object matched. This seems to
//       work very well on most pages, but I noticed at least one case where it
//       did not (moving to a repo's Graphs page on GitHub). Seeing as this
//       only sends a short message to the content script, I've removed the
//       'same URL' filtering.
//
// TODO: In some circumstances (most GitHub transitions, this fires two times on
//       Firefox and three times on Chrome. For YouTube, some transitions only
//       cause this to fire once. Need to investigate this more...
browser.webNavigation.onHistoryStateUpdated.addListener(function(details) {
	if (details.frameId > 0) return
	if (contentConnections.hasOwnProperty(activeTabId)) {  // could be special page
		contentConnections[activeTabId].postMessage({ name: 'trigger-refresh' })
	}
})

browser.tabs.onActivated.addListener(function(activeInfo) {
	activeTabId = activeInfo.tabId
	if (popupConnection) {
		getLandmarksForActiveTab()
	}
	if (BROWSER === 'firefox' || BROWSER === 'opera') {
		if (sidebarConnection) {
			getLandmarksForActiveTab()
		}
	}
	if (BROWSER === 'firefox' || BROWSER === 'chrome' || BROWSER === 'opera') {
		if (devtoolsConnections.hasOwnProperty(activeTabId)) {
			getLandmarksForActiveTab()
		}
	}
})

//
// Install and update
//

browser.runtime.onInstalled.addListener(function(details) {
	if (details.reason === 'install' || details.reason === 'update') {
		// Show website and get it to display an appropriate notice
		const baseUrl = 'http://matatk.agrip.org.uk/landmarks/#!'
		browser.tabs.create({
			url: baseUrl + details.reason
		})
	}
})

//
// Actions when the extension starts up
//

// When the extension is loaded, if it's loaded into a page that is not an
// HTTP(S) page, then we need to disable the browser action button.  This is
// not done by default on Chrome or Firefox.
browser.tabs.query({}, function(tabs) {
	for (const i in tabs) {
		checkBrowserActionState(tabs[i].id, tabs[i].url)
	}
})

if (BROWSER !== 'firefox') {
	contentScriptInjector()
}

if (BROWSER === 'firefox') {
	// Firefox loads content scripts into existing tabs before the background
	// script. That means they'll start before we've run, and fail to connect
	// here. Therefore we need to send a message to the content scripts to tell
	// them we're here and listening now.
	// Thanks https://bugzilla.mozilla.org/show_bug.cgi?id=1474727#c3
	browser.tabs.query({}, function(tabs) {
		for (const i in tabs) {
			const tabId = tabs[i].id
			const url = tabs[i].url

			if (/^(https?|file):\/\//.test(url)) {  // TODO DRY
				for (const specialPage of specialPages) {  // TODO DRY
					if (specialPage.test(url)) return
				}

				// The page is a page on which Landmarks runs. Let the content
				// script know that the background page has started up.
				logger.log(`Sending connection request to tab ${tabId}`)
				browser.tabs.sendMessage(tabId, { name: 'FirefoxWorkaround' })
			}
		}
	})
}
<commit_msg>Code clean-up in support of #195<commit_after>import './compatibility'
import contentScriptInjector from './contentScriptInjector'
import specialPages from './specialPages'
import { defaultInterfaceSettings } from './defaults'
import disconnectingPortErrorCheck from './disconnectingPortErrorCheck'
import Logger from './logger'

const logger = new Logger()

const contentConnections = {}
const devtoolsConnections = {}
let sidebarConnection = null
let popupConnection = null
let activeTabId = null

//
// Message routing
//

function sendLandmarksToGUIs(fromTabId, message) {
	if (popupConnection) {
		popupConnection.postMessage(message)
	}
	if (BROWSER === 'firefox' || BROWSER === 'opera') {
		if (sidebarConnection && fromTabId === activeTabId) {
			sidebarConnection.postMessage(message)
		}
	}
	if (BROWSER === 'firefox' || BROWSER === 'chrome' || BROWSER === 'opera') {
		if (devtoolsConnections.hasOwnProperty(fromTabId)) {
			devtoolsConnections[fromTabId].postMessage(message)
		}
	}
}

function sendNullLandmarksToGUIs() {
	sendLandmarksToGUIs(activeTabId, { name: 'landmarks', data: null })
}

function getLandmarksForActiveTab() {
	if (contentConnections.hasOwnProperty(activeTabId)) {
		contentConnections[activeTabId].postMessage({ name: 'get-landmarks' } )
	} else {
		sendNullLandmarksToGUIs()
	}
}

function sendToActiveContentScriptIfExists(message) {
	// The check is needed when a keyboard command is used
	if (contentConnections.hasOwnProperty(activeTabId)) {
		contentConnections[activeTabId].postMessage(message)
	}
}

function updateBrowserActionBadge(tabId, numberOfLandmarks) {
	browser.browserAction.setBadgeText({
		text: numberOfLandmarks <= 0 ? '' : String(numberOfLandmarks),
		tabId: tabId
	})
}

//
// Setting up and handling connections
//

browser.runtime.onConnect.addListener(function(connectingPort) {
	// Disconnection management

	function contentDisconnect(disconnectingPort) {
		logger.log(`Content script for tab ${disconnectingPort.sender.tab.id} disconnected`)
		disconnectingPortErrorCheck(disconnectingPort)
		delete contentConnections[disconnectingPort.sender.tab.id]
	}

	const devtoolsDisconnect =
		(BROWSER === 'firefox' || BROWSER === 'chrome' || BROWSER === 'opera')
			? function devtoolsDisconnect(tabId) {
				logger.log(`DevTools page for tab ${tabId} disconnected`)
				delete devtoolsConnections[tabId]
			}
			: null

	// Message listeners

	function contentListener(message, sendingPort) {
		const tabId = sendingPort.sender.tab.id

		switch (message.name) {
			case 'landmarks':
				logger.log(`Got ${message.data.length} landmarks from ${sendingPort.sender.tab.url}`)
				sendLandmarksToGUIs(tabId, message)
				updateBrowserActionBadge(tabId, message.data.length)
				break
			default:
				throw Error(`Unknown message ${JSON.stringify(message)} from content script in ${sendingPort.sender.tab.id}`)
		}
	}

	function popupAndSidebarListener(message) {  // also gets: sendingPort
		switch (message.name) {
			case 'get-landmarks':
				logger.log('Popup or sidebar requested landmarks')
				getLandmarksForActiveTab()
				break
			case 'focus-landmark':
				sendToActiveContentScriptIfExists(message)
				break
			default:
				throw Error(`Unknown message ${JSON.stringify(message)} from sidebar or popup`)
		}
	}

	const devtoolsListner =
		(BROWSER === 'firefox' || BROWSER === 'chrome' || BROWSER === 'opera')
			? function(message) {
				switch (message.name) {
					case 'init':
						logger.log(`DevTools page for tab ${message.tabId} connected`)
						devtoolsConnections[message.tabId] = connectingPort
						connectingPort.onDisconnect.addListener(function(disconnectingPort) {
							disconnectingPortErrorCheck(disconnectingPort)
							devtoolsDisconnect(message.tabId)
						})
						break
					case 'get-landmarks':
						logger.log('DevTools requested landmarks')
						getLandmarksForActiveTab()
						break
					case 'focus-landmark':
						sendToActiveContentScriptIfExists(message)
						break
					default:
						throw Error(`Unkown message from devtools: ${JSON.stringify(message)}`)
				}
			}
			: null

	function splashListener(message, sendingPort) {
		switch (message.name) {
			case 'get-commands':
				browser.commands.getAll(function(commands) {
					sendingPort.postMessage({
						name: 'splash-populate-commands',
						commands: commands
					})
				})
				break
			case 'splash-open-configure-shortcuts':
				// This should only appear on Chrome/Opera
				browser.tabs.create({
					url: BROWSER === 'chrome' ? 'chrome://extensions/configureCommands' : 'opera://settings/configureCommands'
				})
				break
			default:
				throw Error(`Unkown message from splash: ${JSON.stringify(message)}`)
		}
	}

	// Connection management

	switch (connectingPort.name) {
		case 'content':
			logger.log(`Content script for tab ${connectingPort.sender.tab.id} ${connectingPort.sender.tab.url} connected`)
			contentConnections[connectingPort.sender.tab.id] = connectingPort
			connectingPort.onMessage.addListener(contentListener)
			connectingPort.onDisconnect.addListener(contentDisconnect)
			break
		case 'devtools':
			if (BROWSER === 'firefox' || BROWSER === 'chrome' || BROWSER === 'opera') {
				connectingPort.onMessage.addListener(devtoolsListner)
			}
			break
		case 'popup':
			if (popupConnection !== null) {
				throw Error('Existing pop-up connection')
			}
			popupConnection = connectingPort
			connectingPort.onMessage.addListener(popupAndSidebarListener)
			connectingPort.onDisconnect.addListener(function() {
				popupConnection = null
			})
			break
		case 'sidebar':
			if (BROWSER === 'firefox' || BROWSER === 'opera') {
				if (sidebarConnection !== null) {
					throw Error('Existing sidebar connection')
				}
				sidebarConnection = connectingPort
				connectingPort.onMessage.addListener(popupAndSidebarListener)
				connectingPort.onDisconnect.addListener(function() {
					sidebarConnection = null
				})
			}
			break
		case 'splash':
			connectingPort.onMessage.addListener(splashListener)
			break
		default:
			throw Error(`Unkown connection type ${connectingPort.name}`)
	}
})

if (BROWSER === 'firefox' || BROWSER === 'opera') {
	//
	// Sidebar handling
	//

	// If the user has elected to use the sidebar, the pop-up is disabled, and
	// we will receive events, which we can then use to open the sidebar.
	//
	// Have to do this in a really hacky way at the moment due to
	// https://bugzilla.mozilla.org/show_bug.cgi?id=1438465
	// https://bugzilla.mozilla.org/show_bug.cgi?id=1398833
	//
	// Also Opera doesn't have open().

	// eslint-disable-next-line no-inner-declarations
	function openSidebarWhenClicked() {
		browser.browserAction.onClicked.removeListener(openSidebarWhenClicked)
		browser.sidebarAction.open()
		browser.browserAction.onClicked.addListener(closeSidebarWhenClicked)
	}

	// eslint-disable-next-line no-inner-declarations
	function closeSidebarWhenClicked() {
		browser.browserAction.onClicked.removeListener(closeSidebarWhenClicked)
		browser.sidebarAction.close()
		browser.browserAction.onClicked.addListener(openSidebarWhenClicked)
	}

	// eslint-disable-next-line no-inner-declarations
	function switchInterface(mode) {
		switch (mode) {
			case 'sidebar':
				browser.browserAction.setPopup({ popup: '' })

				if (BROWSER === 'firefox') {
					// The sidebar will be closed because we are setting
					// "open_at_install" to false. It might be nice to actually
					// show the sidebar at install, but isOpen() isn't usable
					// because it breaks propogation of the user input event.
					browser.browserAction.onClicked.addListener(
						openSidebarWhenClicked)
				}
				break
			case 'popup':
				// On Firefox this could be set to null to return to the
				// default popup. However Chrome/Opera doesn't support this.
				browser.browserAction.setPopup({ popup: 'popup.html' })

				if (BROWSER === 'firefox') {
					browser.browserAction.onClicked.removeListener(
						openSidebarWhenClicked)
					browser.browserAction.onClicked.removeListener(
						closeSidebarWhenClicked)
				}
				break
			default:
				throw Error(`Invalid interface "${mode}" given`)
		}
	}

	browser.storage.sync.get(defaultInterfaceSettings, function(items) {
		switchInterface(items.interface)
	})

	browser.storage.onChanged.addListener(function(changes) {
		if (changes.hasOwnProperty('interface')) {
			switchInterface(changes.interface.newValue)
		}
	})
}

//
// Keyboard shortcut handling
//

browser.commands.onCommand.addListener(function(command) {
	switch (command) {
		case 'next-landmark':
		case 'prev-landmark':
		case 'main-landmark':
		case 'show-all-landmarks':
			sendToActiveContentScriptIfExists({ name: command })
			break
		default:
			throw Error(`Unknown command ${JSON.stringify(command)}`)
	}
})

//
// Navigation and tab activation events
//

// Listen for URL change events on all tabs and disable the browser action if
// the URL does not start with 'http://' or 'https://' (or 'file://', for
// local pages).
//
// Note: This used to be wrapped in a query for the active tab, but on browser
//       startup, URL changes are going on in all tabs.
browser.webNavigation.onBeforeNavigate.addListener(function(details) {
	if (details.frameId > 0) return
	browser.browserAction.disable(details.tabId)
	browser.browserAction.setBadgeText({
		text: '',
		tabId: details.tabId
	})
})

browser.webNavigation.onCompleted.addListener(function(details) {
	if (details.frameId > 0) return
	checkBrowserActionState(details.tabId, details.url)
})

function checkBrowserActionState(tabId, url) {
	if (/^(https?|file):\/\//.test(url)) {  // TODO DRY
		for (const specialPage of specialPages) {  // TODO DRY
			if (specialPage.test(url)) {
				browser.browserAction.disable(tabId)
				return
			}
		}
		browser.browserAction.enable(tabId)
	} else {
		browser.browserAction.disable(tabId)

		// We may've moved from a page that allowed content scripts to one that
		// does not. If the sidebar/DevTools are open, they need to be updated.
		sendNullLandmarksToGUIs()
	}
}

// If the page uses 'single-page app' techniques to load in new components --
// as YouTube and GitHub do -- then the landmarks can change. We assume that if
// the structure of the page is changing so much that it is effectively a new
// page, then the developer would've followed best practice and used the
// History API to update the URL of the page, so that this 'new' page can be
// recognised as such and be bookmarked by the user. Therefore we monitor for
// use of the History API to trigger a new search for landmarks on the page.
//
// Thanks: http://stackoverflow.com/a/36818991/1485308
//
// Note: The original code had a fliter such that this would only fire if the
//       URLs of the current tab and the details object matched. This seems to
//       work very well on most pages, but I noticed at least one case where it
//       did not (moving to a repo's Graphs page on GitHub). Seeing as this
//       only sends a short message to the content script, I've removed the
//       'same URL' filtering.
//
// TODO: In some circumstances (most GitHub transitions, this fires two times on
//       Firefox and three times on Chrome. For YouTube, some transitions only
//       cause this to fire once. Need to investigate this more...
browser.webNavigation.onHistoryStateUpdated.addListener(function(details) {
	if (details.frameId > 0) return
	if (contentConnections.hasOwnProperty(activeTabId)) {  // could be special page
		contentConnections[activeTabId].postMessage({ name: 'trigger-refresh' })
	}
})

browser.tabs.onActivated.addListener(function(activeInfo) {
	activeTabId = activeInfo.tabId
	if (popupConnection) {
		getLandmarksForActiveTab()
	}
	if (BROWSER === 'firefox' || BROWSER === 'opera') {
		if (sidebarConnection) {
			getLandmarksForActiveTab()
		}
	}
	if (BROWSER === 'firefox' || BROWSER === 'chrome' || BROWSER === 'opera') {
		if (devtoolsConnections.hasOwnProperty(activeTabId)) {
			getLandmarksForActiveTab()
		}
	}
})

//
// Install and update
//

browser.runtime.onInstalled.addListener(function(details) {
	if (details.reason === 'install' || details.reason === 'update') {
		// Show website and get it to display an appropriate notice
		const baseUrl = 'http://matatk.agrip.org.uk/landmarks/#!'
		browser.tabs.create({
			url: baseUrl + details.reason
		})
	}
})

//
// Actions when the extension starts up
//

// When the extension is loaded, if it's loaded into a page that is not an
// HTTP(S) page, then we need to disable the browser action button.  This is
// not done by default on Chrome or Firefox.
browser.tabs.query({}, function(tabs) {
	for (const i in tabs) {
		checkBrowserActionState(tabs[i].id, tabs[i].url)
	}
})

if (BROWSER !== 'firefox') {
	contentScriptInjector()
}

if (BROWSER === 'firefox') {
	// Firefox loads content scripts into existing tabs before the background
	// script. That means they'll start before we've run, and fail to connect
	// here. Therefore we need to send a message to the content scripts to tell
	// them we're here and listening now.
	// Thanks https://bugzilla.mozilla.org/show_bug.cgi?id=1474727#c3
	browser.tabs.query({}, function(tabs) {
		for (const i in tabs) {
			const tabId = tabs[i].id
			const url = tabs[i].url

			if (/^(https?|file):\/\//.test(url)) {  // TODO DRY
				for (const specialPage of specialPages) {  // TODO DRY
					if (specialPage.test(url)) return
				}

				// The page is a page on which Landmarks runs. Let the content
				// script know that the background page has started up.
				logger.log(`Sending connection request to tab ${tabId}`)
				browser.tabs.sendMessage(tabId, { name: 'FirefoxWorkaround' })
			}
		}
	})
}
<|endoftext|>


<commit_before>// Copyright 2012 WebDriver committers
// Copyright 2012 Software Freedom Conservancy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Synthetic events for fun and profit.
 */

goog.provide('webdriver.atoms.inputs');

goog.require('bot.Keyboard');
goog.require('bot.Mouse');
goog.require('bot.action');
goog.require('goog.array');

/**
 * Send keyboard input to a particular element.
 *
 * @param {!Element} element The element to send the keyboard input to.
 * @param {Array.<!bot.Keyboard.Key>=} opt_state The keyboard to use, or
 *     construct one.
 * @param {...(string|!Array.<string>)} var_args What to type.
 * @return {Array.<!bot.Keyboard.Key>} The keyboard state.
 */
webdriver.atoms.inputs.sendKeys = function(element, opt_state, var_args) {
  var keyboard = new bot.Keyboard(opt_state);
  var to_type = goog.array.slice(arguments, 2);
  var flattened = goog.array.flatten(to_type);

  if (!element) {
    element = bot.dom.getActiveElement(document);
  }
  bot.action.type(element, flattened, keyboard);

  return keyboard.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.sendKeys',
                  webdriver.atoms.inputs.sendKeys);

/**
 * Click on an element.
 *
 * @param {!Element} element The element to click.
 * @return {!bot.Mouse.State} The mouse state.
 * @return {Object} The mouse state.
 */
webdriver.atoms.inputs.click = function(element, opt_state) {
  var mouse = new bot.Mouse(opt_state);
  if (!element) {
    element = mouse.getElement();
  }
  bot.action.click(element, null, mouse);
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.click',
                  webdriver.atoms.inputs.click);

/**
 * Move the mouse to a specific element and/or coordinate location.
 *
 * @param {!Element} element The element to move the mouse to.
 * @param {number} x_offset The x coordinate to use as an offset.
 * @param {number} y_offset The y coordinate to use as an offset.
 * @param {bot.Mouse.State=} opt_state The serialized state of the mouse.
 * @return {!bot.Mouse.State} The mouse state.
 */
webdriver.atoms.inputs.mouseMove = function(element, x_offset, y_offset,
    opt_state) {
  var mouse = new bot.Mouse(opt_state);
  var target = element || mouse.getElement();

  var offset_specified = (x_offset != null) && (y_offset != null);
  x_offset = x_offset || 0;
  y_offset = y_offset || 0;

  // If we have specified an element and no offset, we should
  // move the mouse to the center of the specified element.
  if (element) {
    if (!offset_specified) {
      var source_element_size = bot.action.getInteractableSize_(element);
      x_offset = Math.floor(source_element_size.width / 2);
      y_offset = Math.floor(source_element_size.height / 2);
    }
  } else {
    // Moving to an absolute offset from the current target element,
    // so we have to account for the existing offset of the current
    // mouse position to the element origin (upper-left corner).
    var pos = goog.style.getClientPosition(target);
    x_offset += (mouse.clientXY_.x - pos.x);
    y_offset += (mouse.clientXY_.y - pos.y);
  }

  var doc = goog.dom.getOwnerDocument(target);
  var win = goog.dom.getWindow(doc);
  var inViewAfterScroll = bot.action.scrollIntoView(
      target,
      new goog.math.Coordinate(x_offset, y_offset));

  var coords = new goog.math.Coordinate(x_offset, y_offset);
  mouse.move(target, coords);
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.mouseMove',
                  webdriver.atoms.inputs.mouseMove);

/**
* Presses the primary mouse button at the current location.
*
* @param {Object} opt_state The serialized state of the mouse.
* @return {Object} The mouse state.
*/
webdriver.atoms.inputs.mouseButtonDown = function(opt_state) {
  var mouse = new bot.Mouse(opt_state);
  mouse.pressButton(bot.Mouse.Button.LEFT);
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.mouseButtonDown',
                  webdriver.atoms.inputs.mouseButtonDown);

/**
* Releases the primary mouse button at the current location.
*
* @param {Object} opt_state The serialized state of the mouse.
* @return {Object} The mouse state.
*/
webdriver.atoms.inputs.mouseButtonUp = function(opt_state) {
  var mouse = new bot.Mouse(opt_state);
  mouse.releaseButton();
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.mouseButtonUp',
                  webdriver.atoms.inputs.mouseButtonUp);

/**
* Double-clicks primary mouse button at the current location.
*
* @param {Object} opt_state The serialized state of the mouse.
* @return {Object} The mouse state.
*/
webdriver.atoms.inputs.doubleClick = function(opt_state) {
  var mouse = new bot.Mouse(opt_state);
  mouse.pressButton(bot.Mouse.Button.LEFT);
  mouse.releaseButton();
  mouse.pressButton(bot.Mouse.Button.LEFT);
  mouse.releaseButton();
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.doubleClick',
                  webdriver.atoms.inputs.doubleClick);

/**
* Right-clicks mouse button at the current location.
*
* @param {Object)} opt_state The serialized state of the mouse.
* @return {Object} The mouse state.
*/
webdriver.atoms.inputs.rightClick = function (opt_state) {
  var mouse = new bot.Mouse(opt_state);
  mouse.pressButton(bot.Mouse.Button.RIGHT);
  mouse.releaseButton();
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.rightClick',
                  webdriver.atoms.inputs.rightClick);
<commit_msg>JimEvans: webdriver.atoms.inputs.type should call webdriver.atoms.element.type instead of the raw bot.action.type<commit_after>// Copyright 2012 WebDriver committers
// Copyright 2012 Software Freedom Conservancy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Synthetic events for fun and profit.
 */

goog.provide('webdriver.atoms.inputs');

goog.require('bot.Keyboard');
goog.require('bot.Mouse');
goog.require('bot.action');
goog.require('goog.array');
goog.require('webdriver.atoms.element');

/**
 * Send keyboard input to a particular element.
 *
 * @param {!Element} element The element to send the keyboard input to.
 * @param {Array.<!bot.Keyboard.Key>=} opt_state The keyboard to use, or
 *     construct one.
 * @param {...(string|!Array.<string>)} var_args What to type.
 * @return {Array.<!bot.Keyboard.Key>} The keyboard state.
 */
webdriver.atoms.inputs.sendKeys = function(element, opt_state, var_args) {
  var keyboard = new bot.Keyboard(opt_state);
  var to_type = goog.array.slice(arguments, 2);
  var flattened = goog.array.flatten(to_type);
  if (!element) {
    element = bot.dom.getActiveElement(document);
  }
  webdriver.atoms.element.type(element, flattened, keyboard);

  return keyboard.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.sendKeys',
                  webdriver.atoms.inputs.sendKeys);

/**
 * Click on an element.
 *
 * @param {!Element} element The element to click.
 * @return {!bot.Mouse.State} The mouse state.
 * @return {Object} The mouse state.
 */
webdriver.atoms.inputs.click = function(element, opt_state) {
  var mouse = new bot.Mouse(opt_state);
  if (!element) {
    element = mouse.getElement();
  }
  bot.action.click(element, null, mouse);
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.click',
                  webdriver.atoms.inputs.click);

/**
 * Move the mouse to a specific element and/or coordinate location.
 *
 * @param {!Element} element The element to move the mouse to.
 * @param {number} x_offset The x coordinate to use as an offset.
 * @param {number} y_offset The y coordinate to use as an offset.
 * @param {bot.Mouse.State=} opt_state The serialized state of the mouse.
 * @return {!bot.Mouse.State} The mouse state.
 */
webdriver.atoms.inputs.mouseMove = function(element, x_offset, y_offset,
    opt_state) {
  var mouse = new bot.Mouse(opt_state);
  var target = element || mouse.getElement();

  var offset_specified = (x_offset != null) && (y_offset != null);
  x_offset = x_offset || 0;
  y_offset = y_offset || 0;

  // If we have specified an element and no offset, we should
  // move the mouse to the center of the specified element.
  if (element) {
    if (!offset_specified) {
      var source_element_size = bot.action.getInteractableSize_(element);
      x_offset = Math.floor(source_element_size.width / 2);
      y_offset = Math.floor(source_element_size.height / 2);
    }
  } else {
    // Moving to an absolute offset from the current target element,
    // so we have to account for the existing offset of the current
    // mouse position to the element origin (upper-left corner).
    var pos = goog.style.getClientPosition(target);
    x_offset += (mouse.clientXY_.x - pos.x);
    y_offset += (mouse.clientXY_.y - pos.y);
  }

  var doc = goog.dom.getOwnerDocument(target);
  var win = goog.dom.getWindow(doc);
  var inViewAfterScroll = bot.action.scrollIntoView(
      target,
      new goog.math.Coordinate(x_offset, y_offset));

  var coords = new goog.math.Coordinate(x_offset, y_offset);
  mouse.move(target, coords);
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.mouseMove',
                  webdriver.atoms.inputs.mouseMove);

/**
* Presses the primary mouse button at the current location.
*
* @param {Object} opt_state The serialized state of the mouse.
* @return {Object} The mouse state.
*/
webdriver.atoms.inputs.mouseButtonDown = function(opt_state) {
  var mouse = new bot.Mouse(opt_state);
  mouse.pressButton(bot.Mouse.Button.LEFT);
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.mouseButtonDown',
                  webdriver.atoms.inputs.mouseButtonDown);

/**
* Releases the primary mouse button at the current location.
*
* @param {Object} opt_state The serialized state of the mouse.
* @return {Object} The mouse state.
*/
webdriver.atoms.inputs.mouseButtonUp = function(opt_state) {
  var mouse = new bot.Mouse(opt_state);
  mouse.releaseButton();
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.mouseButtonUp',
                  webdriver.atoms.inputs.mouseButtonUp);

/**
* Double-clicks primary mouse button at the current location.
*
* @param {Object} opt_state The serialized state of the mouse.
* @return {Object} The mouse state.
*/
webdriver.atoms.inputs.doubleClick = function(opt_state) {
  var mouse = new bot.Mouse(opt_state);
  mouse.pressButton(bot.Mouse.Button.LEFT);
  mouse.releaseButton();
  mouse.pressButton(bot.Mouse.Button.LEFT);
  mouse.releaseButton();
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.doubleClick',
                  webdriver.atoms.inputs.doubleClick);

/**
* Right-clicks mouse button at the current location.
*
* @param {Object)} opt_state The serialized state of the mouse.
* @return {Object} The mouse state.
*/
webdriver.atoms.inputs.rightClick = function (opt_state) {
  var mouse = new bot.Mouse(opt_state);
  mouse.pressButton(bot.Mouse.Button.RIGHT);
  mouse.releaseButton();
  return mouse.getState();
};
goog.exportSymbol('webdriver.atoms.inputs.rightClick',
                  webdriver.atoms.inputs.rightClick);
<|endoftext|>


<commit_before>#!/usr/bin/env node

var exec = require('child_process').exec;
var urlParse = require('url').parse;

var budo = require('budo');

function execCmd (cmd) {
  var p = exec(cmd);
  p.stderr.pipe(process.stderr);
  p.stdout.pipe(process.stdout);
  return p;
}

var consts = {
  NAME: 'AFRAME',
  ENTRY: './src/index.js',
  DIST: 'dist/aframe.js',
  BUILD: 'build/aframe.js',
  WATCH: 'examples/**/*',  // Additional files to watch for LiveReload
  PORT: 9000
};

var opts = {
  debug: process.env.NODE_ENVIRONMENT !== 'production',
  verbose: true,
  live: true,
  stream: process.stdout,
  host: process.env.HOST,
  port: process.env.PORT || consts.PORT,
  watchGlob: consts.WATCH,
  browserifyArgs: ['-s', consts.NAME],
  middleware: function (req, res, next) {
    // Route `dist/aframe.js` to `build/aframe.js` so we can
    // dev against the examples :)
    var path = urlParse(req.url).pathname;
    if (path.indexOf('/' + consts.DIST) !== -1) {
      req.url = req.url.replace('/dist/', '/build/');
    }
    // TODO: Consider adding middleware that targets specific directories
    // (such that editing `examples/a.html` doesn't reload `examples/b.html`).
    next();
  }
};

var app = budo(consts.ENTRY + ':' + consts.BUILD, opts);
app.on('update', function () {
  execCmd('semistandard -v $(git ls-files "*.js") | snazzy');
});
<commit_msg>fix broken `snazzy` pipe (fixes #976)<commit_after>#!/usr/bin/env node

var exec = require('child_process').exec;
var urlParse = require('url').parse;

var budo = require('budo');

function execCmd (cmd) {
  var p = exec(cmd);
  p.stderr.pipe(process.stderr);
  p.stdout.pipe(process.stdout);
  return p;
}

var consts = {
  NAME: 'AFRAME',
  ENTRY: './src/index.js',
  DIST: 'dist/aframe.js',
  BUILD: 'build/aframe.js',
  WATCH: 'examples/**/*',  // Additional files to watch for LiveReload
  PORT: 9000
};

var opts = {
  debug: process.env.NODE_ENVIRONMENT !== 'production',
  verbose: true,
  live: true,
  stream: process.stdout,
  host: process.env.HOST,
  port: process.env.PORT || consts.PORT,
  watchGlob: consts.WATCH,
  browserifyArgs: ['-s', consts.NAME],
  middleware: function (req, res, next) {
    // Route `dist/aframe.js` to `build/aframe.js` so we can
    // dev against the examples :)
    var path = urlParse(req.url).pathname;
    if (path.indexOf('/' + consts.DIST) !== -1) {
      req.url = req.url.replace('/dist/', '/build/');
    }
    // TODO: Consider adding middleware that targets specific directories
    // (such that editing `examples/a.html` doesn't reload `examples/b.html`).
    next();
  }
};

var app = budo(consts.ENTRY + ':' + consts.BUILD, opts);
app.on('update', function () {
  execCmd('semistandard -v $(git ls-files "*.js") | standard-reporter --stylish');
});
<|endoftext|>


<commit_before>// jme.rcpt_to.mailboxes
// Description: Requires recipients to exist in a config file.

var loadConfig = function(plugin, connection) {
	var config		= plugin.config.get('jme.mailbox_accounts', 'json') || {};
	var returnValue = false;

	var authMethod = config['authMethod'] || "file";
	if (authMethod == "file") {
		connection.logdebug(plugin, "Using file-auth");
		if (config['accounts']) {
			returnValue = config['accounts'];
		} else {
			connection.logdebug(plugin, "Error! No accounts table in config file!");
		}
	}
	return returnValue;
};

var hostInConfig = function(plugin, connection, config, host) {
	if (config[host]) {
		return true;
	} else {
		connection.logdebug(plugin, "Host " + host + " not local (no forwarding)");
		return false;
	}
};

var checkValidMailbox = function(next, connection, params) {
	var rcpt        = params[0];
	var address     = rcpt.address();
	// We don't do any '-' matchng on this address
	// It *must* be already be stripped before it gets here
	var user        = rcpt.user;
	var host        = rcpt.host;
	var config		= loadConfig(this, connection);
	var returnValue;

	if(config && !connection.transaction.notes.pipe) {
		if(hostInConfig(this, connection, config, host)) {
			config = config[host];
			connection.loginfo(this, "Checking account for: " + address);

			if (config[user]) {
				connection.logdebug(this, "User " + address + " exists");
			} else {
				// Maybe we should bounce instead?
				connection.logdebug(this, "User " + address + " does not exist");
				returnValue = "User does not exist!";
			}
		} else {
			returnValue = "Forwarding not enabled for " + host;
		}
	} else {
		connection.transaction.notes.discard = true;
	}

	if(returnValue) {
		return next(DENY, returnValue);
	} else {
		return next(OK);
	}
};

exports.hook_rcpt = checkValidMailbox;
<commit_msg>Added check for local relaying<commit_after>// jme.rcpt_to.mailboxes
// Description: Requires recipients to exist in a config file.

var loadConfig = function(plugin, connection) {
	var config		= plugin.config.get('jme.mailbox_accounts', 'json') || {};
	var returnValue = false;

	var authMethod = config['authMethod'] || "file";
	if (authMethod == "file") {
		connection.logdebug(plugin, "Using file-auth");
		if (config['accounts']) {
			returnValue = config['accounts'];
		} else {
			connection.logdebug(plugin, "Error! No accounts table in config file!");
		}
	}
	return returnValue;
};

var hostInConfig = function(plugin, connection, config, host) {
	if (config[host]) {
		return true;
	} else {
		connection.logdebug(plugin, "Host " + host + " not local (no forwarding)");
		return false;
	}
};

var checkValidMailbox = function(next, connection, params) {
	var rcpt        = params[0];
	var address     = rcpt.address();
	// We don't do any '-' matchng on this address
	// It *must* be already be stripped before it gets here
	var user        = rcpt.user;
	var host        = rcpt.host;
	var config		= loadConfig(this, connection);
	var returnValue;

	if(config && !connection.transaction.notes.pipe) {
		if(hostInConfig(this, connection, config, host)) {
			config = config[host];
			connection.loginfo(this, "Checking account for: " + address);

			if (config[user]) {
				connection.logdebug(this, "User " + address + " exists");
			} else {
				// Maybe we should bounce instead?
				connection.logdebug(this, "User " + address + " does not exist");
				returnValue = "User does not exist!";
			}
		} else if (connection.remote_ip == connection.local_ip) {
			connection.relaying = true;
			connection.logdebug(this, "Forwarding allowed for " +
				connection.remote_ip + " (to " + address + ")");
		} else {
			returnValue = "Forwarding not enabled for " + host;
		}
	} else {
		connection.transaction.notes.discard = true;
	}

	if(returnValue) {
		return next(DENY, returnValue);
	} else {
		return next(OK);
	}
};

exports.hook_rcpt = checkValidMailbox;
<|endoftext|>


<commit_before>var tap = require('tap');
var urlOf = require('./lib/url');
var pass = require('./lib/pass');
var P = require('bluebird');

require('./lib/sharedNemo').then(function(nemo) {
  tap.test('sign up for on-site trial', {
    bail: true
  }, function(t) {
    return P.all([
      nemo.driver.get(urlOf('/onsite')),
      nemo.view.onsite.firstnameWaitVisible().then(pass(t, "form field visible")),
      nemo.view.onsite.firstname().sendKeys("Boops"),
      nemo.view.onsite.lastname().sendKeys("boops"),
      nemo.view.onsite.email().sendKeys("test+" + Date.now() + "@npmjs.com"),
      nemo.view.onsite.phone().sendKeys("415-857-5309"),
      nemo.view.onsite.company().sendKeys("yesallmen.com"),
      nemo.view.onsite.numemployees().sendKeys("2"),
      nemo.view.onsite.submit().click(),
      nemo.view.onsite.agreementWaitVisible().then(pass(t, "navigated to second page")),
      nemo.view.onsite.agreement().sendKeys(" "),
      nemo.view.onsite.submitAgreement().click(),
      nemo.view.onsite.h2WaitVisible(),
      nemo.view.onsite.h2TextEquals('time to check your email').then(pass(t, 'confirmation found'))
    ]).then(function() {
      if (!module.parent) {
        return nemo.driver.quit();
      }
    }).catch(t.error).then(t.end);
  });
});
<commit_msg>cleans up order of operations<commit_after>var tap = require('tap');
var urlOf = require('./lib/url');
var pass = require('./lib/pass');
var P = require('bluebird');

require('./lib/sharedNemo').then(function(nemo) {
  tap.test('sign up for on-site trial', {
    bail: true
  }, function(t) {
    return P.resolve(nemo.driver.get(urlOf('/onsite'))).then(function() {
      return P.all([
        nemo.view.onsite.firstnameWaitVisible().then(pass(t, "form field visible")),
        nemo.view.onsite.firstname().sendKeys("Boops"),
        nemo.view.onsite.lastname().sendKeys("boops"),
        nemo.view.onsite.email().sendKeys("test+" + Date.now() + "@npmjs.com"),
        nemo.view.onsite.phone().sendKeys("415-857-5309"),
        nemo.view.onsite.company().sendKeys("yesallmen.com"),
        nemo.view.onsite.numemployees().sendKeys("2")
      ]);
    }).then(function() {
      return nemo.view.onsite.submit().click();
    }).then(function() {
      return P.all([
        nemo.view.onsite.agreementWaitVisible().then(pass(t, "navigated to second page")),
        nemo.view.onsite.agreement().sendKeys(" "),
        nemo.view.onsite.submitAgreement().click()
      ]);
    }).then(function() {
      return P.all([
        nemo.view.onsite.h2WaitVisible(),
        nemo.view.onsite.h2TextEquals('time to check your email').then(pass(t, 'confirmation found'))
      ]);
    }).then(function() {
      if (!module.parent) {
        return nemo.driver.quit();
      }
    }).catch(t.error).then(t.end);
  });
});
<|endoftext|>