<commit_before>Modules.VERSION = '2.4.2';
Modules.UTILS = true;
Modules.BASEUTILS = true;

// xmlHttpRequest(url, callback, method) - aid for quickly using the nsIXMLHttpRequest interface
//	url - (string) to send the request
//	callback - (function) to be called after request is completed; expects callback(xmlhttp, e) where xmlhttp = xmlhttprequest return object and e = event object
//	(optional) method - either (string) "POST" or (string) "GET"
this.xmlHttpRequest = function(url, callback, method) {
	if(!method) { method = "GET"; }

	var xmlhttp = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
	xmlhttp.open(method, url);
	if(url.endsWith('.json')) {
		xmlhttp.overrideMimeType("application/json");
	}
	xmlhttp.onreadystatechange = function(e) { callback(xmlhttp, e); };
	xmlhttp.send();
	return xmlhttp;
};

// aSync(aFunc, aDelay) - lets me run aFunc asynchronously, basically it's a one shot timer with a delay of aDelay msec
//	aFunc - (function) to be called asynchronously
//	(optional) aDelay - (int) msec to set the timer, defaults to 0msec
this.aSync = function(aFunc, aDelay) {
	var newTimer = {
		timer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer),
		handler: aFunc.bind(self),
		cancel: function() {
			this.timer.cancel();
		}
	};
	newTimer.timer.init(newTimer.handler, (!aDelay) ? 0 : aDelay, Ci.nsITimer.TYPE_ONE_SHOT);
	return newTimer;
};

// dispatch(obj, properties) - creates and dispatches an event and returns (bool) whether preventDefault was not called on it
//	obj - (xul element) object to dispatch the event from, it will be e.target
//	properties - (obj) expecting the following sub properties defining the following event characteristics:
//		type - (str) the event type
//		(optional) bubbles - (bool) defaults to true
//		(optional) cancelable - (bool) defaults to true
//		(optional) detail - to be passed to the event
this.dispatch = function(obj, properties) {
	if(!obj || !obj.dispatchEvent
	|| (!obj.ownerDocument && !obj.document && (!obj.content || !obj.content.document))
	|| !properties || !properties.type) { return false; }

	var bubbles = properties.bubbles || true;
	var cancelable = properties.cancelable || true;
	var detail = properties.detail || undefined;

	var doc = (obj.ownerDocument) ? obj.ownerDocument : (obj.document) ? obj.document : obj.content.document; // last one's for content processes
	var event = doc.createEvent('CustomEvent');
	event.initCustomEvent(properties.type, bubbles, cancelable, detail);
	return obj.dispatchEvent(event);
};

// askForOwner(aNode) - dispatches an event to node, where anyone can set event.detail to any value
// for example, to get the id of the trigger node that opened a popup or panel programmatically
//	aNode - (xul element) the object node to ask about
this.askForOwner = function(aNode) {
	if(!aNode || (!aNode.ownerDocument && !aNode.document) || !aNode.dispatchEvent) { return null; }

	var owner = null;
	var event = (aNode.ownerDocument) ? aNode.ownerDocument.createEvent('CustomEvent') : aNode.document.createEvent('CustomEvent');
	event.__defineGetter__('detail', function() { return owner; });
	event.__defineSetter__('detail', function(v) { return owner = v; });
	event.initCustomEvent('AskingForNodeOwner', true, false, owner);
	aNode.dispatchEvent(event);
	return owner;
};

// compareFunction(a, b, strict) - returns (bool) if a === b
//	a - (function) to compare
//	b - (function) to compare
//	(optional) strict - false compares function source as (string), true does not, defaults to false
this.compareFunction = function(a, b, strict) {
	if(a === b || (!strict && a.toSource() == b.toSource())) {
		return true;
	}
	return false;
};

// isAncestor(aNode, aParent) - Checks if aNode decends from aParent
//	aNode - (xul element) node to check for ancestry
//	aParent - (xul element) node to check if ancestor of aNode
//	(dont set) aWindow - to be used internally by isAncestor()
this.isAncestor = function(aNode, aParent, aWindow) {
	if(!aNode || !aParent) { return false; };

	if(aNode == aParent) { return true; }

	var ownDocument = aNode.ownerDocument || aNode.document;
	if(ownDocument && ownDocument == aParent) { return true; }
	if(aNode.compareDocumentPosition && (aNode.compareDocumentPosition(aParent) & aNode.DOCUMENT_POSITION_CONTAINS)) { return true; }

	var browserNodes = (aParent.tagName == 'browser') ? [aParent] : aParent.getElementsByTagName('browser');
	for(var browser of browserNodes) {
		try { if(isAncestor(aNode, browser.contentDocument, browser.contentWindow)) { return true; } }
		catch(ex) { /* this will fail in e10s */ }
	}

	if(!aWindow) { return false; }
	for(var frame of aWindow.frames) {
		if(isAncestor(aNode, frame.document, frame)) { return true; }
	}
	return false;
};

// hideIt(aNode, show) - in theory this should collapse whatever I want
//	aNode - (xul element) node to collapse
//	(optional) show - false collapses aNode, true 'un'collapses it, defaults to false
this.hideIt = function(aNode, show) {
	toggleAttribute(aNode, 'collapsed', !show);
};

// trim(str) - trims whitespaces from a string (found in http://blog.stevenlevithan.com/archives/faster-trim-javascript -> trim3())
//	str - (string) to trim
this.trim = function(str) {
	if(typeof(str) != 'string') {
		return '';
	}

	return str.substring(Math.max(str.search(/\S/), 0), str.search(/\S\s*$/) + 1);
};

// replaceObjStrings(node, prop) - replace all objName and objPathString references in the node attributes and its children with the proper names
//	node - (xul element) to replace the strings in
//	(optional) prop - (string) if specified, instead of checking attributes, it will check for node.prop for occurences of what needs to be replaced. This will not check child nodes.
this.replaceObjStrings = function(node, prop) {
	if(!node) { return; }

	if(prop) {
		if(!node[prop]) { return; }

		while(node[prop].indexOf('objName') > -1) {
			node[prop] = node[prop].replace('objName', objName);
		}
		while(node[prop].indexOf('objPathString') > -1) {
			node[prop] = node[prop].replace('objPathString', objPathString);
		}

		return;
	}

	if(node.attributes) {
		for(var a=0; a<node.attributes.length; a++) {
			while(node.attributes[a].value.indexOf('objName') > -1) {
				node.attributes[a].value = node.attributes[a].value.replace('objName', objName);
			}
			while(node.attributes[a].value.indexOf('objPathString') > -1) {
				node.attributes[a].value = node.attributes[a].value.replace('objPathString', objPathString);
			}
		}
	}

	var curChild = node.firstChild;
	while(curChild) {
		replaceObjStrings(curChild);
		curChild = curChild.nextSibling;
	}
};
<commit_msg>move askForOwner into dispatch<commit_after>Modules.VERSION = '2.5.0';
Modules.UTILS = true;
Modules.BASEUTILS = true;

// xmlHttpRequest(url, callback, method) - aid for quickly using the nsIXMLHttpRequest interface
//	url - (string) to send the request
//	callback - (function) to be called after request is completed; expects callback(xmlhttp, e) where xmlhttp = xmlhttprequest return object and e = event object
//	(optional) method - either (string) "POST" or (string) "GET"
this.xmlHttpRequest = function(url, callback, method) {
	if(!method) { method = "GET"; }

	var xmlhttp = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
	xmlhttp.open(method, url);
	if(url.endsWith('.json')) {
		xmlhttp.overrideMimeType("application/json");
	}
	xmlhttp.onreadystatechange = function(e) { callback(xmlhttp, e); };
	xmlhttp.send();
	return xmlhttp;
};

// aSync(aFunc, aDelay) - lets me run aFunc asynchronously, basically it's a one shot timer with a delay of aDelay msec
//	aFunc - (function) to be called asynchronously
//	(optional) aDelay - (int) msec to set the timer, defaults to 0msec
this.aSync = function(aFunc, aDelay) {
	var newTimer = {
		timer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer),
		handler: aFunc.bind(self),
		cancel: function() {
			this.timer.cancel();
		}
	};
	newTimer.timer.init(newTimer.handler, (!aDelay) ? 0 : aDelay, Ci.nsITimer.TYPE_ONE_SHOT);
	return newTimer;
};

// dispatch(obj, properties) - creates and dispatches an event and returns (bool) whether preventDefault was not called on it
//	aNode - (xul element) object to dispatch the event from, it will be e.target
//	props - (obj) expecting the following sub properties defining the following event characteristics:
//		type - (str) the event type
//		(optional) bubbles - (bool) defaults to true
//		(optional) cancelable - (bool) defaults to true
//		(optional) detail - to be passed to the event
//		(optional) asking - (bool) if true, will return the .detail property of the event, which can be modified by listeners; defaults to false, .detail defaults to undefined
this.dispatch = function(aNode, props) {
	if(!aNode || !aNode.dispatchEvent
	|| (!aNode.ownerDocument && !aNode.document && (!aNode.content || !aNode.content.document))
	|| !props || !props.type) { return false; }

	var bubbles = props.bubbles || true;
	var cancelable = props.cancelable || !props.asking;
	var detail = props.detail || undefined;

	var doc = (aNode.ownerDocument) ? aNode.ownerDocument : (aNode.document) ? aNode.document : aNode.content.document; // last one's for content processes
	var event = doc.createEvent('CustomEvent');

	if(props.asking) {
		event.__defineGetter__('detail', function() { return detail; });
		event.__defineSetter__('detail', function(v) { return detail = v; });
	}

	event.initCustomEvent(props.type, bubbles, cancelable, detail);
	var ret = aNode.dispatchEvent(event);
	return (props.asking) ? detail : ret;
};

// compareFunction(a, b, strict) - returns (bool) if a === b
//	a - (function) to compare
//	b - (function) to compare
//	(optional) strict - false compares function source as (string), true does not, defaults to false
this.compareFunction = function(a, b, strict) {
	if(a === b || (!strict && a.toSource() == b.toSource())) {
		return true;
	}
	return false;
};

// isAncestor(aNode, aParent) - Checks if aNode decends from aParent
//	aNode - (xul element) node to check for ancestry
//	aParent - (xul element) node to check if ancestor of aNode
//	(dont set) aWindow - to be used internally by isAncestor()
this.isAncestor = function(aNode, aParent, aWindow) {
	if(!aNode || !aParent) { return false; };

	if(aNode == aParent) { return true; }

	var ownDocument = aNode.ownerDocument || aNode.document;
	if(ownDocument && ownDocument == aParent) { return true; }
	if(aNode.compareDocumentPosition && (aNode.compareDocumentPosition(aParent) & aNode.DOCUMENT_POSITION_CONTAINS)) { return true; }

	var browserNodes = (aParent.tagName == 'browser') ? [aParent] : aParent.getElementsByTagName('browser');
	for(var browser of browserNodes) {
		try { if(isAncestor(aNode, browser.contentDocument, browser.contentWindow)) { return true; } }
		catch(ex) { /* this will fail in e10s */ }
	}

	if(!aWindow) { return false; }
	for(var frame of aWindow.frames) {
		if(isAncestor(aNode, frame.document, frame)) { return true; }
	}
	return false;
};

// hideIt(aNode, show) - in theory this should collapse whatever I want
//	aNode - (xul element) node to collapse
//	(optional) show - false collapses aNode, true 'un'collapses it, defaults to false
this.hideIt = function(aNode, show) {
	toggleAttribute(aNode, 'collapsed', !show);
};

// trim(str) - trims whitespaces from a string (found in http://blog.stevenlevithan.com/archives/faster-trim-javascript -> trim3())
//	str - (string) to trim
this.trim = function(str) {
	if(typeof(str) != 'string') {
		return '';
	}

	return str.substring(Math.max(str.search(/\S/), 0), str.search(/\S\s*$/) + 1);
};

// replaceObjStrings(node, prop) - replace all objName and objPathString references in the node attributes and its children with the proper names
//	node - (xul element) to replace the strings in
//	(optional) prop - (string) if specified, instead of checking attributes, it will check for node.prop for occurences of what needs to be replaced. This will not check child nodes.
this.replaceObjStrings = function(node, prop) {
	if(!node) { return; }

	if(prop) {
		if(!node[prop]) { return; }

		while(node[prop].indexOf('objName') > -1) {
			node[prop] = node[prop].replace('objName', objName);
		}
		while(node[prop].indexOf('objPathString') > -1) {
			node[prop] = node[prop].replace('objPathString', objPathString);
		}

		return;
	}

	if(node.attributes) {
		for(var a=0; a<node.attributes.length; a++) {
			while(node.attributes[a].value.indexOf('objName') > -1) {
				node.attributes[a].value = node.attributes[a].value.replace('objName', objName);
			}
			while(node.attributes[a].value.indexOf('objPathString') > -1) {
				node.attributes[a].value = node.attributes[a].value.replace('objPathString', objPathString);
			}
		}
	}

	var curChild = node.firstChild;
	while(curChild) {
		replaceObjStrings(curChild);
		curChild = curChild.nextSibling;
	}
};
<|endoftext|>


<commit_before>/**
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */
'use strict';

import $ from 'jquery';
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/messaging';
import {MaterialUtils} from './Utils';
import page from 'page';

/**
 * Handles notifications.
 */
export default class Messaging {
  /**
   * Inititializes the notifications utility.
   * @constructor
   */
  constructor(firebaseHelper) {
    this.firebaseHelper = firebaseHelper;

    // Firebase SDK
    this.auth = firebase.auth();
    try {
      this.messaging = firebase.messaging();
    } catch(e) {
      if (e.code === 'messaging/unsupported-browser') {
        console.warn('This BRowser does not suport FCM. Notifications won\'t be available.', e);
      } else {
        throw e;
      }
    }

    // DOM Elements
    this.enableNotificationsContainer = $('.fp-notifications');
    this.enableNotificationsCheckbox = $('#notifications');
    this.enableNotificationsLabel = $('.mdl-switch__label', this.enableNotificationsContainer);

    this.toast = $('.mdl-js-snackbar');

    // Event bindings
    this.enableNotificationsCheckbox.change(() => this.onEnableNotificationsChange());
    this.auth.onAuthStateChanged(() => this.trackNotificationsEnabledStatus());
    if (this.messaging) {
      this.messaging.onTokenRefresh(() => this.saveToken());
      this.messaging.onMessage((payload) => this.onMessage(payload));
    }
  }

  /**
   * Saves the token to the database if available. If not request permissions.
   */
  async saveToken() {
    try {
      const currentToken = await this.messaging.getToken();
      if (currentToken) {
        await this.firebaseHelper.saveNotificationToken(currentToken);
        console.log('Notification Token saved to database');
      } else {
        this.requestPermission();
      }
    } catch(err) {
      console.error('Unable to get messaging token.', err);
    }
  }

  /**
   * Requests permission to send notifications on this browser.
   */
  async requestPermission() {
    console.log('Requesting permission...');
    // TODO: Blackout the entire screen and show a message saying why we need the permissions.
    //       e.g. "If you would like to receive notifications on this device, grant permission above."
    try {
      await this.messaging.requestPermission();
      console.log('Notification permission granted.');
      this.saveToken();
    } catch(err) {
      console.error('Unable to get permission to notify.', err);
    }
  }

  /**
   * Called when the app is in focus.
   */
  onMessage(payload) {
    console.log('Notifications received.', payload);

    // If we get a notification while focus on the app
    if (payload.notification) {
      const userId = payload.notification.click_action.split('/user/')[1];

      let data = {
        message: payload.notification.body,
        actionHandler: () => page(`/user/${userId}`),
        actionText: 'Profile',
        timeout: 10000,
      };
      MaterialUtils.showSnackbar(this.toast, data);
    }
  }

  /**
   * Triggered when the user changes the "Notifications Enabled" checkbox.
   */
  onEnableNotificationsChange() {
    const checked = this.enableNotificationsCheckbox.prop('checked');
    this.enableNotificationsCheckbox.prop('disabled', true);

    return this.firebaseHelper.toggleNotificationEnabled(checked);
  }

  /**
   * Starts tracking the "Notifications Enabled" checkbox status.
   */
  trackNotificationsEnabledStatus() {
    if (this.auth.currentUser) {
      this.firebaseHelper.registerToNotificationEnabledStatusUpdate((data) => {
        this.enableNotificationsCheckbox.prop('checked', data.val() !== null);
        this.enableNotificationsCheckbox.prop('disabled', false);
        this.enableNotificationsLabel.text(data.val() ? 'Notifications Enabled' : 'Enable Notifications');
        MaterialUtils.refreshSwitchState(this.enableNotificationsContainer);

        if (data.val() && this.messaging) {
          this.saveToken();
        }
      });
    }
  }
}
<commit_msg>Fixed typo<commit_after>/**
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */
'use strict';

import $ from 'jquery';
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/messaging';
import {MaterialUtils} from './Utils';
import page from 'page';

/**
 * Handles notifications.
 */
export default class Messaging {
  /**
   * Inititializes the notifications utility.
   * @constructor
   */
  constructor(firebaseHelper) {
    this.firebaseHelper = firebaseHelper;

    // Firebase SDK
    this.auth = firebase.auth();
    try {
      this.messaging = firebase.messaging();
    } catch(e) {
      if (e.code === 'messaging/unsupported-browser') {
        console.warn('This Browser does not suport FCM. Notifications won\'t be available.', e);
      } else {
        throw e;
      }
    }

    // DOM Elements
    this.enableNotificationsContainer = $('.fp-notifications');
    this.enableNotificationsCheckbox = $('#notifications');
    this.enableNotificationsLabel = $('.mdl-switch__label', this.enableNotificationsContainer);

    this.toast = $('.mdl-js-snackbar');

    // Event bindings
    this.enableNotificationsCheckbox.change(() => this.onEnableNotificationsChange());
    this.auth.onAuthStateChanged(() => this.trackNotificationsEnabledStatus());
    if (this.messaging) {
      this.messaging.onTokenRefresh(() => this.saveToken());
      this.messaging.onMessage((payload) => this.onMessage(payload));
    }
  }

  /**
   * Saves the token to the database if available. If not request permissions.
   */
  async saveToken() {
    try {
      const currentToken = await this.messaging.getToken();
      if (currentToken) {
        await this.firebaseHelper.saveNotificationToken(currentToken);
        console.log('Notification Token saved to database');
      } else {
        this.requestPermission();
      }
    } catch(err) {
      console.error('Unable to get messaging token.', err);
    }
  }

  /**
   * Requests permission to send notifications on this browser.
   */
  async requestPermission() {
    console.log('Requesting permission...');
    // TODO: Blackout the entire screen and show a message saying why we need the permissions.
    //       e.g. "If you would like to receive notifications on this device, grant permission above."
    try {
      await this.messaging.requestPermission();
      console.log('Notification permission granted.');
      this.saveToken();
    } catch(err) {
      console.error('Unable to get permission to notify.', err);
    }
  }

  /**
   * Called when the app is in focus.
   */
  onMessage(payload) {
    console.log('Notifications received.', payload);

    // If we get a notification while focus on the app
    if (payload.notification) {
      const userId = payload.notification.click_action.split('/user/')[1];

      let data = {
        message: payload.notification.body,
        actionHandler: () => page(`/user/${userId}`),
        actionText: 'Profile',
        timeout: 10000,
      };
      MaterialUtils.showSnackbar(this.toast, data);
    }
  }

  /**
   * Triggered when the user changes the "Notifications Enabled" checkbox.
   */
  onEnableNotificationsChange() {
    const checked = this.enableNotificationsCheckbox.prop('checked');
    this.enableNotificationsCheckbox.prop('disabled', true);

    return this.firebaseHelper.toggleNotificationEnabled(checked);
  }

  /**
   * Starts tracking the "Notifications Enabled" checkbox status.
   */
  trackNotificationsEnabledStatus() {
    if (this.auth.currentUser) {
      this.firebaseHelper.registerToNotificationEnabledStatusUpdate((data) => {
        this.enableNotificationsCheckbox.prop('checked', data.val() !== null);
        this.enableNotificationsCheckbox.prop('disabled', false);
        this.enableNotificationsLabel.text(data.val() ? 'Notifications Enabled' : 'Enable Notifications');
        MaterialUtils.refreshSwitchState(this.enableNotificationsContainer);

        if (data.val() && this.messaging) {
          this.saveToken();
        }
      });
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @type {number}
 * @const
 */
var FEEDBACK_WIDTH = 500;
/**
 * @type {number}
 * @const
 */
var FEEDBACK_HEIGHT = 585;

var initialFeedbackInfo = null;

// To generate a hashed extension ID, use a sha-256 hash, all in lower case.
// Example:
//   echo -n 'abcdefghijklmnopqrstuvwxyzabcdef' | sha1sum | \
//       awk '{print toupper($1)}'
var whitelistedExtensionIds = [
  '12E618C3C6E97495AAECF2AC12DEB082353241C6', // QuickOffice
  '3727DD3E564B6055387425027AD74C58784ACC15', // QuickOffice
  '2FC374607C2DF285634B67C64A2E356C607091C3', // QuickOffice
  '2843C1E82A9B6C6FB49308FDDF4E157B6B44BC2B', // G+ Photos
  '5B5DA6D054D10DB917AF7D9EAE3C56044D1B0B03', // G+ Photos
  '986913085E3E3C3AFDE9B7A943149C4D3F4C937B', // Feedback Extension
  '7AE714FFD394E073F0294CFA134C9F91DB5FBAA4', // Connectivity Diagnostics
  'C7DA3A55C2355F994D3FDDAD120B426A0DF63843', // Connectivity Diagnostics
  '75E3CFFFC530582C583E4690EF97C70B9C8423B7', // Connectivity Diagnostics
  '32A1BA997F8AB8DE29ED1BA94AAF00CF2A3FEFA7', // Connectivity Diagnostics
  'A291B26E088FA6BA53FFD72F0916F06EBA7C585A', // Chrome OS Recovery Tool
  'D7986543275120831B39EF28D1327552FC343960', // Chrome OS Recovery Tool
  '8EBDF73405D0B84CEABB8C7513C9B9FA9F1DC2CE', // GetHelp app.
  '97B23E01B2AA064E8332EE43A7A85C628AADC3F2', // Chrome Remote Desktop Dev
  '9E527CDA9D7C50844E8A5DB964A54A640AE48F98', // Chrome Remote Desktop Stable
  'DF52618D0B040D8A054D8348D2E84DDEEE5974E7', // Chrome Remote Desktop QA
  '269D721F163E587BC53C6F83553BF9CE2BB143CD', // Chrome Remote Desktop QA backup
  'C449A798C495E6CF7D6AF10162113D564E67AD12', // Chrome Remote Desktop Apps V2
  '981974CD1832B87BE6B21BE78F7249BB501E0DE6', // Play Movies Dev
  '32FD7A816E47392C92D447707A89EB07EEDE6FF7', // Play Movies Nightly
  '3F3CEC4B9B2B5DC2F820CE917AABDF97DB2F5B49', // Play Movies Beta
  'F92FAC70AB68E1778BF62D9194C25979596AA0E6', // Play Movies Stable
  '0F585FB1D0FDFBEBCE1FEB5E9DFFB6DA476B8C9B', // Hangouts Extension
  '2D22CDB6583FD0A13758AEBE8B15E45208B4E9A7', // Hangouts Extension
  '49DA0B9CCEEA299186C6E7226FD66922D57543DC', // Hangouts Extension
  'E7E2461CE072DF036CF9592740196159E2D7C089', // Hangouts Extension
  'A74A4D44C7CFCD8844830E6140C8D763E12DD8F3', // Hangouts Extension
  '312745D9BF916161191143F6490085EEA0434997', // Hangouts Extension
  '53041A2FA309EECED01FFC751E7399186E860B2C', // Hangouts Extension
  '0F42756099D914A026DADFA182871C015735DD95', // Hangouts Extension
  '1B7734733E207CCE5C33BFAA544CA89634BF881F', // GLS nightly
  'E2ACA3D943A3C96310523BCDFD8C3AF68387E6B7', // GLS stable
  '11B478CEC461C766A2DC1E5BEEB7970AE06DC9C2', // http://crbug.com/463552
  '0EFB879311E9EFBB7C45251F89EC655711B1F6ED', // http://crbug.com/463552
  '9193D3A51E2FE33B496CDA53EA330423166E7F02', // http://crbug.com/463552
  'F9119B8B18C7C82B51E7BC6FF816B694F2EC3E89', // http://crbug.com/463552
  'BA007D8D52CC0E2632EFCA03ACD003B0F613FD71', // http://crbug.com/470411
  '5260FA31DE2007A837B7F7B0EB4A47CE477018C8', // http://crbug.com/470411
  '4F4A25F31413D9B9F80E61D096DEB09082515267', // http://crbug.com/470411
  'FBA0DE4D3EFB5485FC03760F01F821466907A743', // http://crbug.com/470411
  'E216473E4D15C5FB14522D32C5F8DEAAB2CECDC6', // http://crbug.com/470411
  '676A08383D875E51CE4C2308D875AE77199F1413', // http://crbug.com/473845
  '869A23E11B308AF45A68CC386C36AADA4BE44A01', // http://crbug.com/473845
];

/**
 * Function to determine whether or not a given extension id is whitelisted to
 * invoke the feedback UI. If the extension is whitelisted, the callback to
 * start the Feedback UI will be called.
 * @param {string} id the id of the sender extension.
 * @param {Function} startFeedbackCallback The callback function that will
 *     will start the feedback UI.
 * @param {Object} feedbackInfo The feedback info object to pass to the
 *     start feedback UI callback.
 */
function senderWhitelisted(id, startFeedbackCallback, feedbackInfo) {
  crypto.subtle.digest('SHA-1', new TextEncoder().encode(id)).then(
      function(hashBuffer) {
    var hashString = '';
    var hashView = new Uint8Array(hashBuffer);
    for (var i = 0; i < hashView.length; ++i) {
      var n = hashView[i];
      hashString += n < 0x10 ? '0' : '';
      hashString += n.toString(16);
    }
    if (whitelistedExtensionIds.indexOf(hashString.toUpperCase()) != -1)
      startFeedbackCallback(feedbackInfo);
  });
}

/**
 * Callback which gets notified once our feedback UI has loaded and is ready to
 * receive its initial feedback info object.
 * @param {Object} request The message request object.
 * @param {Object} sender The sender of the message.
 * @param {function(Object)} sendResponse Callback for sending a response.
 */
function feedbackReadyHandler(request, sender, sendResponse) {
  if (request.ready) {
    chrome.runtime.sendMessage(
        {sentFromEventPage: true, data: initialFeedbackInfo});
  }
}

/**
 * Callback which gets notified if another extension is requesting feedback.
 * @param {Object} request The message request object.
 * @param {Object} sender The sender of the message.
 * @param {function(Object)} sendResponse Callback for sending a response.
 */
function requestFeedbackHandler(request, sender, sendResponse) {
  if (request.requestFeedback)
    senderWhitelisted(sender.id, startFeedbackUI, request.feedbackInfo);
}

/**
 * Callback which starts up the feedback UI.
 * @param {Object} feedbackInfo Object containing any initial feedback info.
 */
function startFeedbackUI(feedbackInfo) {
  initialFeedbackInfo = feedbackInfo;
  var win = chrome.app.window.get('default_window');
  if (win) {
    win.show();
    return;
  }
  chrome.app.window.create('html/default.html', {
      frame: 'none',
      id: 'default_window',
      width: FEEDBACK_WIDTH,
      height: FEEDBACK_HEIGHT,
      hidden: true,
      resizable: false },
      function(appWindow) {});
}

chrome.runtime.onMessage.addListener(feedbackReadyHandler);
chrome.runtime.onMessageExternal.addListener(requestFeedbackHandler);
chrome.feedbackPrivate.onFeedbackRequested.addListener(startFeedbackUI);
<commit_msg>Adding extensions ids to Chrome Feedback whitelist.<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @type {number}
 * @const
 */
var FEEDBACK_WIDTH = 500;
/**
 * @type {number}
 * @const
 */
var FEEDBACK_HEIGHT = 585;

var initialFeedbackInfo = null;

// To generate a hashed extension ID, use a sha-256 hash, all in lower case.
// Example:
//   echo -n 'abcdefghijklmnopqrstuvwxyzabcdef' | sha1sum | \
//       awk '{print toupper($1)}'
var whitelistedExtensionIds = [
  '12E618C3C6E97495AAECF2AC12DEB082353241C6', // QuickOffice
  '3727DD3E564B6055387425027AD74C58784ACC15', // QuickOffice
  '2FC374607C2DF285634B67C64A2E356C607091C3', // QuickOffice
  '2843C1E82A9B6C6FB49308FDDF4E157B6B44BC2B', // G+ Photos
  '5B5DA6D054D10DB917AF7D9EAE3C56044D1B0B03', // G+ Photos
  '986913085E3E3C3AFDE9B7A943149C4D3F4C937B', // Feedback Extension
  '7AE714FFD394E073F0294CFA134C9F91DB5FBAA4', // Connectivity Diagnostics
  'C7DA3A55C2355F994D3FDDAD120B426A0DF63843', // Connectivity Diagnostics
  '75E3CFFFC530582C583E4690EF97C70B9C8423B7', // Connectivity Diagnostics
  '32A1BA997F8AB8DE29ED1BA94AAF00CF2A3FEFA7', // Connectivity Diagnostics
  'A291B26E088FA6BA53FFD72F0916F06EBA7C585A', // Chrome OS Recovery Tool
  'D7986543275120831B39EF28D1327552FC343960', // Chrome OS Recovery Tool
  '8EBDF73405D0B84CEABB8C7513C9B9FA9F1DC2CE', // GetHelp app.
  '97B23E01B2AA064E8332EE43A7A85C628AADC3F2', // Chrome Remote Desktop Dev
  '9E527CDA9D7C50844E8A5DB964A54A640AE48F98', // Chrome Remote Desktop Stable
  'DF52618D0B040D8A054D8348D2E84DDEEE5974E7', // Chrome Remote Desktop QA
  '269D721F163E587BC53C6F83553BF9CE2BB143CD', // Chrome Remote Desktop QA backup
  'C449A798C495E6CF7D6AF10162113D564E67AD12', // Chrome Remote Desktop Apps V2
  '981974CD1832B87BE6B21BE78F7249BB501E0DE6', // Play Movies Dev
  '32FD7A816E47392C92D447707A89EB07EEDE6FF7', // Play Movies Nightly
  '3F3CEC4B9B2B5DC2F820CE917AABDF97DB2F5B49', // Play Movies Beta
  'F92FAC70AB68E1778BF62D9194C25979596AA0E6', // Play Movies Stable
  '0F585FB1D0FDFBEBCE1FEB5E9DFFB6DA476B8C9B', // Hangouts Extension
  '2D22CDB6583FD0A13758AEBE8B15E45208B4E9A7', // Hangouts Extension
  '49DA0B9CCEEA299186C6E7226FD66922D57543DC', // Hangouts Extension
  'E7E2461CE072DF036CF9592740196159E2D7C089', // Hangouts Extension
  'A74A4D44C7CFCD8844830E6140C8D763E12DD8F3', // Hangouts Extension
  '312745D9BF916161191143F6490085EEA0434997', // Hangouts Extension
  '53041A2FA309EECED01FFC751E7399186E860B2C', // Hangouts Extension
  '0F42756099D914A026DADFA182871C015735DD95', // Hangouts Extension
  '1B7734733E207CCE5C33BFAA544CA89634BF881F', // GLS nightly
  'E2ACA3D943A3C96310523BCDFD8C3AF68387E6B7', // GLS stable
  '11B478CEC461C766A2DC1E5BEEB7970AE06DC9C2', // http://crbug.com/463552
  '0EFB879311E9EFBB7C45251F89EC655711B1F6ED', // http://crbug.com/463552
  '9193D3A51E2FE33B496CDA53EA330423166E7F02', // http://crbug.com/463552
  'F9119B8B18C7C82B51E7BC6FF816B694F2EC3E89', // http://crbug.com/463552
  'BA007D8D52CC0E2632EFCA03ACD003B0F613FD71', // http://crbug.com/470411
  '5260FA31DE2007A837B7F7B0EB4A47CE477018C8', // http://crbug.com/470411
  '4F4A25F31413D9B9F80E61D096DEB09082515267', // http://crbug.com/470411
  'FBA0DE4D3EFB5485FC03760F01F821466907A743', // http://crbug.com/470411
  'E216473E4D15C5FB14522D32C5F8DEAAB2CECDC6', // http://crbug.com/470411
  '676A08383D875E51CE4C2308D875AE77199F1413', // http://crbug.com/473845
  '869A23E11B308AF45A68CC386C36AADA4BE44A01', // http://crbug.com/473845
  'A4577D8C2AF4CF26F40CBCA83FFA4251D6F6C8F8', // http://crbug.com/478929
  'A8208CCC87F8261AFAEB6B85D5E8D47372DDEA6B', // http://crbug.com/478929
];

/**
 * Function to determine whether or not a given extension id is whitelisted to
 * invoke the feedback UI. If the extension is whitelisted, the callback to
 * start the Feedback UI will be called.
 * @param {string} id the id of the sender extension.
 * @param {Function} startFeedbackCallback The callback function that will
 *     will start the feedback UI.
 * @param {Object} feedbackInfo The feedback info object to pass to the
 *     start feedback UI callback.
 */
function senderWhitelisted(id, startFeedbackCallback, feedbackInfo) {
  crypto.subtle.digest('SHA-1', new TextEncoder().encode(id)).then(
      function(hashBuffer) {
    var hashString = '';
    var hashView = new Uint8Array(hashBuffer);
    for (var i = 0; i < hashView.length; ++i) {
      var n = hashView[i];
      hashString += n < 0x10 ? '0' : '';
      hashString += n.toString(16);
    }
    if (whitelistedExtensionIds.indexOf(hashString.toUpperCase()) != -1)
      startFeedbackCallback(feedbackInfo);
  });
}

/**
 * Callback which gets notified once our feedback UI has loaded and is ready to
 * receive its initial feedback info object.
 * @param {Object} request The message request object.
 * @param {Object} sender The sender of the message.
 * @param {function(Object)} sendResponse Callback for sending a response.
 */
function feedbackReadyHandler(request, sender, sendResponse) {
  if (request.ready) {
    chrome.runtime.sendMessage(
        {sentFromEventPage: true, data: initialFeedbackInfo});
  }
}

/**
 * Callback which gets notified if another extension is requesting feedback.
 * @param {Object} request The message request object.
 * @param {Object} sender The sender of the message.
 * @param {function(Object)} sendResponse Callback for sending a response.
 */
function requestFeedbackHandler(request, sender, sendResponse) {
  if (request.requestFeedback)
    senderWhitelisted(sender.id, startFeedbackUI, request.feedbackInfo);
}

/**
 * Callback which starts up the feedback UI.
 * @param {Object} feedbackInfo Object containing any initial feedback info.
 */
function startFeedbackUI(feedbackInfo) {
  initialFeedbackInfo = feedbackInfo;
  var win = chrome.app.window.get('default_window');
  if (win) {
    win.show();
    return;
  }
  chrome.app.window.create('html/default.html', {
      frame: 'none',
      id: 'default_window',
      width: FEEDBACK_WIDTH,
      height: FEEDBACK_HEIGHT,
      hidden: true,
      resizable: false },
      function(appWindow) {});
}

chrome.runtime.onMessage.addListener(feedbackReadyHandler);
chrome.runtime.onMessageExternal.addListener(requestFeedbackHandler);
chrome.feedbackPrivate.onFeedbackRequested.addListener(startFeedbackUI);
<|endoftext|>


<commit_before>goog.provide('ol.interaction.KeyboardZoom');

goog.require('goog.asserts');
goog.require('goog.events.KeyHandler.EventType');
goog.require('ol.events.ConditionType');
goog.require('ol.events.condition');
goog.require('ol.interaction.Interaction');

/**
 * @classdesc
 * Allows the user to zoom the map using keyboard + and -.
 * Note that, although this interaction is by default included in maps,
 * the keys can only be used when browser focus is on the element to which
 * the keyboard events are attached. By default, this is the map div,
 * though you can change this with the `keyboardEventTarget` in
 * {@link ol.Map}. `document` never loses focus but, for any other element,
 * focus will have to be on, and returned to, this element if the keys are to
 * function.
 * See also {@link ol.interaction.KeyboardPan}.
 *
 * @constructor
 * @param {olx.interaction.KeyboardZoomOptions=} opt_options Options.
 * @extends {ol.interaction.Interaction}
 * @api stable
 */
ol.interaction.KeyboardZoom = function(opt_options) {

  goog.base(this, {
    handleEvent: ol.interaction.KeyboardZoom.handleEvent
  });

  var options = goog.isDef(opt_options) ? opt_options : {};

  /**
   * @private
   * @type {ol.events.ConditionType}
   */
  this.condition_ = goog.isDef(options.condition) ? options.condition :
          ol.events.condition.targetNotEditable;

  /**
   * @private
   * @type {number}
   */
  this.delta_ = goog.isDef(options.delta) ? options.delta : 1;

  /**
   * @private
   * @type {number}
   */
  this.duration_ = goog.isDef(options.duration) ? options.duration : 100;

};
goog.inherits(ol.interaction.KeyboardZoom, ol.interaction.Interaction);

/**
 * Handles the {@link ol.MapBrowserEvent map browser event} if it was a
 * `KeyEvent`, and decides whether to zoom in or out (depending on whether the
 * key pressed was '+' or '-').
 * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
 * @return {boolean} `false` to stop event propagation.
 * @this {ol.interaction.KeyboardZoom}
 * @api
 */
ol.interaction.KeyboardZoom.handleEvent = function(mapBrowserEvent) {
  var stopEvent = false;
  if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) {
    var keyEvent = /** @type {goog.events.KeyEvent} */
        (mapBrowserEvent.browserEvent);
    var charCode = keyEvent.charCode;
    if (this.condition_(mapBrowserEvent) &&
        (charCode == '+'.charCodeAt(0) || charCode == '-'.charCodeAt(0))) {
      var map = mapBrowserEvent.map;
      var delta = (charCode == '+'.charCodeAt(0)) ? this.delta_ : -this.delta_;
      map.render();
      var view = map.getView();
      goog.asserts.assert(!goog.isNull(view), 'view should not be null');
      ol.interaction.Interaction.zoomByDelta(
          map, view, delta, undefined, this.duration_);
      mapBrowserEvent.preventDefault();
      stopEvent = true;
    }
  }
  return !stopEvent;
};
<commit_msg>Remove goog.isDef from keyboardzoominteraction<commit_after>goog.provide('ol.interaction.KeyboardZoom');

goog.require('goog.asserts');
goog.require('goog.events.KeyHandler.EventType');
goog.require('ol.events.ConditionType');
goog.require('ol.events.condition');
goog.require('ol.interaction.Interaction');

/**
 * @classdesc
 * Allows the user to zoom the map using keyboard + and -.
 * Note that, although this interaction is by default included in maps,
 * the keys can only be used when browser focus is on the element to which
 * the keyboard events are attached. By default, this is the map div,
 * though you can change this with the `keyboardEventTarget` in
 * {@link ol.Map}. `document` never loses focus but, for any other element,
 * focus will have to be on, and returned to, this element if the keys are to
 * function.
 * See also {@link ol.interaction.KeyboardPan}.
 *
 * @constructor
 * @param {olx.interaction.KeyboardZoomOptions=} opt_options Options.
 * @extends {ol.interaction.Interaction}
 * @api stable
 */
ol.interaction.KeyboardZoom = function(opt_options) {

  goog.base(this, {
    handleEvent: ol.interaction.KeyboardZoom.handleEvent
  });

  var options = opt_options ? opt_options : {};

  /**
   * @private
   * @type {ol.events.ConditionType}
   */
  this.condition_ = options.condition ? options.condition :
          ol.events.condition.targetNotEditable;

  /**
   * @private
   * @type {number}
   */
  this.delta_ = options.delta ? options.delta : 1;

  /**
   * @private
   * @type {number}
   */
  this.duration_ = options.duration ? options.duration : 100;

};
goog.inherits(ol.interaction.KeyboardZoom, ol.interaction.Interaction);

/**
 * Handles the {@link ol.MapBrowserEvent map browser event} if it was a
 * `KeyEvent`, and decides whether to zoom in or out (depending on whether the
 * key pressed was '+' or '-').
 * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
 * @return {boolean} `false` to stop event propagation.
 * @this {ol.interaction.KeyboardZoom}
 * @api
 */
ol.interaction.KeyboardZoom.handleEvent = function(mapBrowserEvent) {
  var stopEvent = false;
  if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) {
    var keyEvent = /** @type {goog.events.KeyEvent} */
        (mapBrowserEvent.browserEvent);
    var charCode = keyEvent.charCode;
    if (this.condition_(mapBrowserEvent) &&
        (charCode == '+'.charCodeAt(0) || charCode == '-'.charCodeAt(0))) {
      var map = mapBrowserEvent.map;
      var delta = (charCode == '+'.charCodeAt(0)) ? this.delta_ : -this.delta_;
      map.render();
      var view = map.getView();
      goog.asserts.assert(!goog.isNull(view), 'view should not be null');
      ol.interaction.Interaction.zoomByDelta(
          map, view, delta, undefined, this.duration_);
      mapBrowserEvent.preventDefault();
      stopEvent = true;
    }
  }
  return !stopEvent;
};
<|endoftext|>


<commit_before>'use strict';

class Validator {

  /**
   * Create new validator instance
   * @param  {object} schema
   * @param  {mixed}  data
   * @return {Validator}
   */
  constructor(schema, data){
    this.schema = schema;
    this.data = data;
    this.errors = [];

    this.validate(this.schema, this.data);
  }

  /**
   * Is the value a string?
   * @param  {mixed}  value
   * @return {Boolean}
   */
  isString(value){
    return typeof value === 'string' || (value && value.prototype ? value.prototype.constructor === String : false) ? true : false;
  }

  /**
   * Is the value a number
   * @param  {mixed}  value
   * @return {Boolean}
   */
  isNumber(value){
    return typeof value === 'number' || (value && value.prototype ? value.prototype.constructor === Number : false) ? true : false;
  }

  /**
   * Is the value a boolean
   * @param  {mixed}  value
   * @return {Boolean}
   */
  isBoolean(value){
    return typeof value === 'boolean' || (value && value.prototype ? value.prototype.constructor === Boolean : false) ? true : false;
  }

  /**
   * Is the value an array
   * @param  {mixed}  value
   * @return {Boolean}
   */
  isArray(value){
    return Array.isArray(value) || (value && value.prototype ? value.prototype.constructor === Array : false);
  }

  /**
   * Is the value an object
   * @param  {mixed}  value
   * @return {Boolean}
   */
  isObject(value){
    return typeof value === 'object' && !(value instanceof Array) || (value && value.prototype ? value.prototype.constructor === Object : false) ? true : false;
  }

  /**
   * Check if a key is in the schema
   * @param  {string}   key
   * @param  {mixed}    schema
   * @return {Boolean}
   */
  isKeyInSchema(key, schema){
    if(schema[key]){
      return true;
    } else {
      this.errors.push({ msg: 'The key '+key+' is not defined in the schema' });
      return false;
    }
  }

  /**
   * Validate a value as a string
   * @param  {string} key
   * @param  {mixed}  value
   * @return {void}
   */
  validateString(key, value){
    if(!this.isString(value)){
      this.errors.push({ msg: 'The key '+key+' should be a string' });
    }
  }

  /**
   * Validate a value as a number
   * @param  {string} key
   * @param  {mixed}  value
   * @return {void}
   */
  validateNumber(key, value){
    if(!this.isNumber(value)){
      this.errors.push({ msg: 'The key '+key+' should be a number' });
    }
  }

  /**
   * Validate a value as a boolean
   * @param  {string} key
   * @param  {mixed}  value
   * @return {void}
   */
  validateBoolean(key, value){
    if(!this.isBoolean(value)){
      this.errors.push({ msg: 'The key '+key+' should be a boolean' });
    }
  }

  /**
   * Validate a value as an array
   * @param  {string} key
   * @param  {mixed}  value
   * @return {void}
   */
  validateArray(key, value){
    if(!this.isArray(value)){
      this.errors.push({ msg: 'The key '+key+' should be an array' });
    }
  }

  /**
   * Validate a value as an object
   * @param  {string} key
   * @param  {mixed}  value
   * @return {void}
   */
  validateObject(key, value){
    if(!this.isObject(value)){
      this.errors.push({ msg: 'The key '+key+' should be an object' });
    }
  }

  /**
   * Compare the data against the schema
   * @param  {mixed} item
   * @param  {mixed} schema
   * @return {void}
   */
  compare(item, schema){
    for(let key in schema){
      if(this.isString(schema[key])){
        this.validateString(key, item[key]);
      }

      if(this.isNumber(schema[key])){
        this.validateNumber(key, item[key]);
      }

      if(this.isBoolean(schema[key])){
        this.validateBoolean(key, item[key]);
      }

      if(this.isArray(schema[key])){
        this.validateArray(key, item[key]);
      }

      if(this.isObject(schema[key])){
        this.validateObject(key, item[key]);
      }
    }
  }

  /**
   * Validate the schema against the base data
   * @param  {mixed} schema
   * @param  {mixed} data
   * @return {void}
   */
  validate(schema, data){
    if(this.isArray(schema)){
      schema = schema[0];
    }

    if(!this.isArray(data)){
      data = [data];
    }

    for(let i = 0, item; item = data[i]; i++){
      for(let key in item){
        this.isKeyInSchema(key, schema);

        if(this.isArray(schema[key]) && (schema[key].prototype ? schema[key].prototype.constructor !== Array : true)){
          this.validate(schema[key], item[key]);
        }

        // TODO finish object
        if(this.isObject(schema[key]) && Object.keys(schema[key]).length > 0){
          this.validate(schema[key], item[key]);
        }
      }

      this.compare(item, schema);
    }

    return this;
  }

}

module.exports = Validator;
<commit_msg>Fixed minor typos<commit_after>'use strict';

class Validator {

  /**
   * Create new validator instance
   * @param  {Object} schema
   * @param  {Mixed}  data
   * @return {Validator}
   */
  constructor(schema, data){
    this.schema = schema;
    this.data = data;
    this.errors = [];

    this.validate(this.schema, this.data);
  }

  /**
   * Is the value a string?
   * @param  {Mixed}  value
   * @return {Boolean}
   */
  isString(value){
    return typeof value === 'string' || (value && value.prototype ? value.prototype.constructor === String : false) ? true : false;
  }

  /**
   * Is the value a number
   * @param  {Mixed}  value
   * @return {Boolean}
   */
  isNumber(value){
    return typeof value === 'number' || (value && value.prototype ? value.prototype.constructor === Number : false) ? true : false;
  }

  /**
   * Is the value a boolean
   * @param  {Mixed}  value
   * @return {Boolean}
   */
  isBoolean(value){
    return typeof value === 'boolean' || (value && value.prototype ? value.prototype.constructor === Boolean : false) ? true : false;
  }

  /**
   * Is the value an array
   * @param  {Mixed}  value
   * @return {Boolean}
   */
  isArray(value){
    return Array.isArray(value) || (value && value.prototype ? value.prototype.constructor === Array : false);
  }

  /**
   * Is the value an object
   * @param  {Mixed}  value
   * @return {Boolean}
   */
  isObject(value){
    return typeof value === 'object' && !(value instanceof Array) || (value && value.prototype ? value.prototype.constructor === Object : false) ? true : false;
  }

  /**
   * Check if a key is in the schema
   * @param  {String}   key
   * @param  {Mixed}    schema
   * @return {Boolean}
   */
  isKeyInSchema(key, schema){
    if(schema[key]){
      return true;
    } else {
      this.errors.push({ msg: 'The key '+key+' is not defined in the schema' });
      return false;
    }
  }

  /**
   * Validate a value as a string
   * @param  {String} key
   * @param  {Mixed}  value
   * @return {Undefined}
   */
  validateString(key, value){
    if(!this.isString(value)){
      this.errors.push({ msg: 'The key '+key+' should be a string' });
    }
  }

  /**
   * Validate a value as a number
   * @param  {String} key
   * @param  {Mixed}  value
   * @return {Undefined}
   */
  validateNumber(key, value){
    if(!this.isNumber(value)){
      this.errors.push({ msg: 'The key '+key+' should be a number' });
    }
  }

  /**
   * Validate a value as a boolean
   * @param  {String} key
   * @param  {Mixed}  value
   * @return {Undefined}
   */
  validateBoolean(key, value){
    if(!this.isBoolean(value)){
      this.errors.push({ msg: 'The key '+key+' should be a boolean' });
    }
  }

  /**
   * Validate a value as an array
   * @param  {String} key
   * @param  {Mixed}  value
   * @return {Undefined}
   */
  validateArray(key, value){
    if(!this.isArray(value)){
      this.errors.push({ msg: 'The key '+key+' should be an array' });
    }
  }

  /**
   * Validate a value as an object
   * @param  {String} key
   * @param  {Mixed}  value
   * @return {Undefined}
   */
  validateObject(key, value){
    if(!this.isObject(value)){
      this.errors.push({ msg: 'The key '+key+' should be an object' });
    }
  }

  /**
   * Compare the data against the schema
   * @param  {Mixed} item
   * @param  {Mixed} schema
   * @return {Undefined}
   */
  compare(item, schema){
    for(let key in schema){
      if(this.isString(schema[key])){
        this.validateString(key, item[key]);
      }

      if(this.isNumber(schema[key])){
        this.validateNumber(key, item[key]);
      }

      if(this.isBoolean(schema[key])){
        this.validateBoolean(key, item[key]);
      }

      if(this.isArray(schema[key])){
        this.validateArray(key, item[key]);
      }

      if(this.isObject(schema[key])){
        this.validateObject(key, item[key]);
      }
    }
  }

  /**
   * Validate the schema against the base data
   * @param  {Mixed} schema
   * @param  {Mixed} data
   * @return {Undefined}
   */
  validate(schema, data){
    if(this.isArray(schema)){
      schema = schema[0];
    }

    if(!this.isArray(data)){
      data = [data];
    }

    for(let i = 0, item; item = data[i]; i++){
      for(let key in item){
        this.isKeyInSchema(key, schema);

        if(this.isArray(schema[key]) && (schema[key].prototype ? schema[key].prototype.constructor !== Array : true)){
          this.validate(schema[key], item[key]);
        }

        // TODO finish object
        if(this.isObject(schema[key]) && Object.keys(schema[key]).length > 0){
          this.validate(schema[key], item[key]);
        }
      }

      this.compare(item, schema);
    }

    return this;
  }

}

module.exports = Validator;
<|endoftext|>


<commit_before>/**
 * OpenEyes
 *
 * (C) Moorfields Eye Hospital NHS Foundation Trust, 2008-2011
 * (C) OpenEyes Foundation, 2011-2013
 * This file is part of OpenEyes.
 * OpenEyes is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * OpenEyes is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with OpenEyes in a file titled COPYING. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package OpenEyes
 * @link http://www.openeyes.org.uk
 * @author OpenEyes <info@openeyes.org.uk>
 * @copyright Copyright (c) 2008-2011, Moorfields Eye Hospital NHS Foundation Trust
 * @copyright Copyright (c) 2011-2013, OpenEyes Foundation
 * @license http://www.gnu.org/licenses/gpl-3.0.html The GNU General Public License V3.0
 */

$(document).ready(function() {

	$(this).on('init', '.multi-select', function() {
		$('.multi-select-selections.sortable').sortable();
	});

	$('.multi-select-selections.sortable').sortable();

	// Prevent the events from being bound multiple times.
	if ($(this).data('multi-select-events')) {
		return;
	}
	$(this).data('multi-select-events', true);

	$(this).on('click', '.multi-select .remove-all', function(e) {
		e.preventDefault();
		var container = $(this).closest('.multi-select');
		container.find('.remove-one').trigger('click');
	});

	$(this).on('change', 'select.MultiSelectList', function() {

		var select = $(this);
		var selected = select.children('option:selected');

		if (selected.val().length >0) {

			var container = select.closest('.multi-select');
			var selections = container.find('.multi-select-selections');
			var inputField = container.find('.multi-select-list-name');
			var fieldName = inputField.attr('name').match(/\[MultiSelectList_(.*?)\]$/)[1];
			var noSelectionsMsg = container.find('.no-selections-msg');
			var removeAll = container.find('.remove-all');
			var options = container.data('options');

			var attrs = {};
			$(selected[0].attributes).each(function() {
				attrs[this.nodeName] = this.nodeValue;
			});

			var inp_str = '<input type="hidden" name="'+fieldName+'[]"';
			for (var key in attrs) {
				inp_str += ' ' + key + '="' + attrs[key] + '"';
			}
			inp_str += ' />';

			var input = $(inp_str);

			var remote_data = {
				'href': '#',
				'class': 'MultiSelectRemove remove-one '+selected.val(),
				'text': 'Remove',
				'data-name': fieldName+'[]',
				'data-text': selected.text()
			};

			if ($(this).hasClass('linked-fields')) {
				remote_data['class'] += ' linked-fields';
				remote_data['data-linked-fields'] = $(this).data('linked-fields');
				remote_data['data-linked-values'] = $(this).data('linked-values');
			}

			var remove = $('', remote_data);

			var item = $('
'+selected.text()+'
');
			item.append(remove);
			item.append(input);

			selections
			.append(item)
			.removeClass('hide');

			noSelectionsMsg.addClass('hide');
			removeAll.removeClass('hide');

			selected.remove();
			select.val('');

			if (options.sorted) {
				selections.append(selections.find('li').sort(function(a,b) {
					return $.trim($(a).find('.text').text()) > $.trim($(b).find('.text').text());
				}));
			}
		}

		select.trigger('MultiSelectChanged');
		return false;
	});

	$(this).on('click', 'a.MultiSelectRemove', 'click',function(e) {
		e.preventDefault();
		var anchor = $(this);
		var container = anchor.closest('.multi-select');
		var selections = container.find('.multi-select-selections');
		var noSelectionsMsg = container.find('.no-selections-msg');
		var removeAll = container.find('.remove-all');
		var input = anchor.closest('li').find('input');

		var attrs = {};
		$(input[0].attributes).each(function() {
			if (this.nodeName != 'type' && this.nodeName != 'name') {
				attrs[this.nodeName] = this.nodeValue;
			}
		});

		var text = anchor.data('text');
		var select = container.find('select');

		var attr_str = '';
		for (var key in attrs) {
			attr_str += ' ' + key + '="' + attrs[key] + '"';
		}

		select.append('<option' + attr_str + '>'+text+'</option>');
		sort_selectbox(select);

		anchor.closest('li').remove();
		input.remove();

		if (!selections.children().length) {
			selections.add(removeAll).addClass('hide');
			noSelectionsMsg.removeClass('hide');
		}

		if ($(this).hasClass('linked-fields')) {
			if (inArray($(this).data('text'),$(this).data('linked-values').split(','))) {
				var element_name = container.children('input[type="hidden"]').attr('name').replace(/\[.*$/,'');
				var fields = $(this).data('linked-fields').split(',');
				var values = $(this).data('linked-values').split(',');

				for (var i in fields) {
					if (values.length == 1 || i == arrayIndex($(this).data('text'),values)) {
						hide_linked_field(element_name,fields[i]);
					}
				}
			}
		}

		select.trigger('MultiSelectChanged');

		return false;
	});
});
<commit_msg>[OE-5254] fixed display order problem<commit_after>/**
 * OpenEyes
 *
 * (C) Moorfields Eye Hospital NHS Foundation Trust, 2008-2011
 * (C) OpenEyes Foundation, 2011-2013
 * This file is part of OpenEyes.
 * OpenEyes is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * OpenEyes is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with OpenEyes in a file titled COPYING. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package OpenEyes
 * @link http://www.openeyes.org.uk
 * @author OpenEyes <info@openeyes.org.uk>
 * @copyright Copyright (c) 2008-2011, Moorfields Eye Hospital NHS Foundation Trust
 * @copyright Copyright (c) 2011-2013, OpenEyes Foundation
 * @license http://www.gnu.org/licenses/gpl-3.0.html The GNU General Public License V3.0
 */

$(document).ready(function() {

	// Prevent the events from being bound multiple times.
	if ($(this).data('multi-select-events')) {
		return;
	}
	$(this).data('multi-select-events', true);

	$(this).on('click', '.multi-select .remove-all', function(e) {
		e.preventDefault();
		var container = $(this).closest('.multi-select');
		container.find('.remove-one').trigger('click');
	});

	$(this).on('change', 'select.MultiSelectList', function() {

		var select = $(this);
		var selected = select.children('option:selected');

		if (selected.val().length >0) {

			var container = select.closest('.multi-select');
			var selections = container.find('.multi-select-selections');
			var inputField = container.find('.multi-select-list-name');
			var fieldName = inputField.attr('name').match(/\[MultiSelectList_(.*?)\]$/)[1];
			var noSelectionsMsg = container.find('.no-selections-msg');
			var removeAll = container.find('.remove-all');
			var options = container.data('options');

			var attrs = {};
			$(selected[0].attributes).each(function() {
				attrs[this.nodeName] = this.nodeValue;
			});

			var inp_str = '<input type="hidden" name="'+fieldName+'[]"';
			for (var key in attrs) {
				inp_str += ' ' + key + '="' + attrs[key] + '"';
			}
			inp_str += ' />';

			var input = $(inp_str);

			var remote_data = {
				'href': '#',
				'class': 'MultiSelectRemove remove-one '+selected.val(),
				'text': 'Remove',
				'data-name': fieldName+'[]',
				'data-text': selected.text()
			};

			if ($(this).hasClass('linked-fields')) {
				remote_data['class'] += ' linked-fields';
				remote_data['data-linked-fields'] = $(this).data('linked-fields');
				remote_data['data-linked-values'] = $(this).data('linked-values');
			}

			var remove = $('', remote_data);

			var item = $('
'+selected.text()+'
');
			item.append(remove);
			item.append(input);

			selections
				.append(item)
				.removeClass('hide');

			noSelectionsMsg.addClass('hide');
			removeAll.removeClass('hide');

			selected.remove();
			select.val('');

			if (options.sorted) {
				selections.append(selections.find('li').sort(function(a,b) {
					return $.trim($(a).find('.text').text()) > $.trim($(b).find('.text').text());
				}));
			}
		}

		select.trigger('MultiSelectChanged');
		return false;
	});

	$(this).on('click', 'a.MultiSelectRemove', 'click',function(e) {
		e.preventDefault();
		var anchor = $(this);
		var container = anchor.closest('.multi-select');
		var selections = container.find('.multi-select-selections');
		var noSelectionsMsg = container.find('.no-selections-msg');
		var removeAll = container.find('.remove-all');
		var input = anchor.closest('li').find('input');

		var attrs = {};
		$(input[0].attributes).each(function() {
			if (this.nodeName != 'type' && this.nodeName != 'name') {
				attrs[this.nodeName] = this.nodeValue;
			}
		});

		var text = anchor.data('text');
		var select = container.find('select');

		var attr_str = '';
		for (var key in attrs) {
			attr_str += ' ' + key + '="' + attrs[key] + '"';
		}

		select.append('<option' + attr_str + '>'+text+'</option>');
		sort_selectbox(select);

		if (attr_str.match(/display_order/)) {
			select.append(select.find('option').sort(function(a,b) {
				return parseInt($(a).data('display_order')) > parseInt($(b).data('display_order'));
			}));
		}

		select.val('');

		anchor.closest('li').remove();
		input.remove();

		if (!selections.children().length) {
			selections.add(removeAll).addClass('hide');
			noSelectionsMsg.removeClass('hide');
		}

		if ($(this).hasClass('linked-fields')) {
			if (inArray($(this).data('text'),$(this).data('linked-values').split(','))) {
				var element_name = container.children('input[type="hidden"]').attr('name').replace(/\[.*$/,'');
				var fields = $(this).data('linked-fields').split(',');
				var values = $(this).data('linked-values').split(',');

				for (var i in fields) {
					if (values.length == 1 || i == arrayIndex($(this).data('text'),values)) {
						hide_linked_field(element_name,fields[i]);
					}
				}
			}
		}

		select.trigger('MultiSelectChanged');

		return false;
	});
});
<|endoftext|>


<commit_before>module.exports = DefaultFormatter;

var traverse = require("../../traverse");
var util     = require("../../util");
var t        = require("../../types");
var _        = require("lodash");

function DefaultFormatter(file) {
  this.file = file;

  this.localExports = this.getLocalExports();
  this.localImports = this.getLocalImports();

  this.remapAssignments();

  this.checkCollisions();
}

DefaultFormatter.prototype.getLocalExports = function () {
  var localExports = {};

  traverse(this.file.ast, {
    enter: function (node) {
      var declar = node && node.declaration;
      if (t.isExportDeclaration(node) && declar && t.isStatement(declar)) {
        _.extend(localExports, t.getIds(declar, true));
      }
    }
  });

  return localExports;
};

DefaultFormatter.prototype.getLocalImports = function () {
  var localImports = {};

  traverse(this.file.ast, {
    enter: function (node) {
      if (t.isImportDeclaration(node)) {
        _.extend(localImports, t.getIds(node, true));
      }
    }
  });

  return localImports;
};

DefaultFormatter.prototype.checkCollisions = function () {
  // todo: all check export collissions

  var localImports = this.localImports;
  var file = this.file;

  var isLocalReference = function (node, scope) {
    return t.isIdentifier(node) && _.has(localImports, node.name) && localImports[node.name] !== node;
  };

  var check = function (node) {
    if (isLocalReference(node)) {
      throw file.errorWithNode(node, "Illegal assignment of module import");
    }
  };

  traverse(file.ast, {
    enter: function (node, parent, scope) {
      if (t.isAssignmentExpression(node)) {

        var left = node.left;
        if (t.isMemberExpression(left)) {
          while (left.object) left = left.object;
        }

        check(left);
      } else if (t.isDeclaration(node)) {
        _.each(t.getIds(node, true), check);
      }
    }
  });
};

DefaultFormatter.prototype.remapExportAssignment = function (node) {
  return t.assignmentExpression(
    "=",
    node.left,
    t.assignmentExpression(
      node.operator,
      t.memberExpression(t.identifier("exports"), node.left),
      node.right
    )
  );
};

DefaultFormatter.prototype.remapAssignments = function () {
  var localExports = this.localExports;
  var self = this;

  var isLocalReference = function (node, scope) {
    var name = node.name;
    return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.get(name, true);
  };

  traverse(this.file.ast, {
    enter: function (node, parent, scope) {
      if (t.isUpdateExpression(node) && isLocalReference(node.argument, scope)) {
        this.skip();

        // expand to long file assignment expression
        var assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.literal(1));

        // remap this assignment expression
        var remapped = self.remapExportAssignment(assign);

        // we don't need to change the result
        if (t.isExpressionStatement(parent) || node.prefix) {
          return remapped;
        }

        var nodes = [];
        nodes.push(remapped);

        var operator;
        if (node.operator === "--") {
          operator = "+";
        } else { // "++"
          operator = "-";
        }
        nodes.push(t.binaryExpression(operator, node.argument, t.literal(1)));

        return t.sequenceExpression(nodes);
      }

      if (t.isAssignmentExpression(node) && isLocalReference(node.left, scope)) {
        this.skip();
        return self.remapExportAssignment(node);
      }
    }
  });
};

DefaultFormatter.prototype.getModuleName = function () {
  var opts = this.file.opts;
  var filenameRelative = opts.filenameRelative;
  var moduleName = "";

  if (opts.moduleRoot) {
    moduleName = opts.moduleRoot + "/";
  }

  if (!opts.filenameRelative) {
    return moduleName + opts.filename.replace(/^\//, "");
  }

  if (opts.sourceRoot) {
    // remove sourceRoot from filename
    var sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?");
    filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
  }

  // remove extension
  filenameRelative = filenameRelative.replace(/\.(.*?)$/, "");

  moduleName += filenameRelative;

  return moduleName;
};

DefaultFormatter.prototype._pushStatement = function (ref, nodes) {
  if (t.isClass(ref) || t.isFunction(ref)) {
    if (ref.id) {
      nodes.push(t.toStatement(ref));
      ref = ref.id;
    }
  }

  return ref;
};

DefaultFormatter.prototype._hoistExport = function (declar, assign, priority) {
  if (t.isFunctionDeclaration(declar)) {
    assign._blockHoist = priority || 2;
  }

  return assign;
};

DefaultFormatter.prototype._exportSpecifier = function (getRef, specifier, node, nodes) {
  var inherits = false;
  if (node.specifiers.length === 1) inherits = node;

  if (node.source) {
    if (t.isExportBatchSpecifier(specifier)) {
      // export * from "foo";
      nodes.push(this._exportsWildcard(getRef(), node));
    } else {
      var ref;
      if (t.isSpecifierDefault(specifier) && !this.noInteropRequire) {
        // importing a default so we need to normalise it
        ref = t.callExpression(this.file.addHelper("interop-require"), [getRef()]);
      } else {
        ref = t.memberExpression(getRef(), specifier.id);
      }

      // export { foo } from "test";
      nodes.push(this._exportsAssign(
        t.getSpecifierName(specifier),
        ref,
        node
      ));
    }
  } else {
    // export { foo };
    nodes.push(this._exportsAssign(t.getSpecifierName(specifier), specifier.id, node));
  }
};

DefaultFormatter.prototype._exportsWildcard = function (objectIdentifier) {
  return t.expressionStatement(t.callExpression(this.file.addHelper("exports-wildcard"), [
    t.callExpression(this.file.addHelper("interop-require-wildcard"), [objectIdentifier])
  ]));
};

DefaultFormatter.prototype._exportsAssign = function (id, init) {
  return util.template("exports-assign", {
    VALUE: init,
    KEY:   id
  }, true);
};

DefaultFormatter.prototype.exportDeclaration = function (node, nodes) {
  var declar = node.declaration;

  var id = declar.id;

  if (node.default) {
    id = t.identifier("default");
  }

  var assign;

  if (t.isVariableDeclaration(declar)) {
    for (var i in declar.declarations) {
      var decl = declar.declarations[i];

      decl.init = this._exportsAssign(decl.id, decl.init, node).expression;

      var newDeclar = t.variableDeclaration(declar.kind, [decl]);
      if (i === "0") t.inherits(newDeclar, declar);
      nodes.push(newDeclar);
    }
  } else {
    var ref = declar;

    if (t.isFunctionDeclaration(declar) || t.isClassDeclaration(declar)) {
      ref = declar.id;
      nodes.push(declar);
    }

    assign = this._exportsAssign(id, ref, node);

    nodes.push(assign);

    this._hoistExport(declar, assign);
  }
};
<commit_msg>fixing linting errors<commit_after>module.exports = DefaultFormatter;

var traverse = require("../../traverse");
var util     = require("../../util");
var t        = require("../../types");
var _        = require("lodash");

function DefaultFormatter(file) {
  this.file = file;

  this.localExports = this.getLocalExports();
  this.localImports = this.getLocalImports();

  this.remapAssignments();

  this.checkCollisions();
}

DefaultFormatter.prototype.getLocalExports = function () {
  var localExports = {};

  traverse(this.file.ast, {
    enter: function (node) {
      var declar = node && node.declaration;
      if (t.isExportDeclaration(node) && declar && t.isStatement(declar)) {
        _.extend(localExports, t.getIds(declar, true));
      }
    }
  });

  return localExports;
};

DefaultFormatter.prototype.getLocalImports = function () {
  var localImports = {};

  traverse(this.file.ast, {
    enter: function (node) {
      if (t.isImportDeclaration(node)) {
        _.extend(localImports, t.getIds(node, true));
      }
    }
  });

  return localImports;
};

DefaultFormatter.prototype.checkCollisions = function () {
  // todo: all check export collissions

  var localImports = this.localImports;
  var file = this.file;

  var isLocalReference = function (node) {
    return t.isIdentifier(node) && _.has(localImports, node.name) && localImports[node.name] !== node;
  };

  var check = function (node) {
    if (isLocalReference(node)) {
      throw file.errorWithNode(node, "Illegal assignment of module import");
    }
  };

  traverse(file.ast, {
    enter: function (node) {
      if (t.isAssignmentExpression(node)) {

        var left = node.left;
        if (t.isMemberExpression(left)) {
          while (left.object) left = left.object;
        }

        check(left);
      } else if (t.isDeclaration(node)) {
        _.each(t.getIds(node, true), check);
      }
    }
  });
};

DefaultFormatter.prototype.remapExportAssignment = function (node) {
  return t.assignmentExpression(
    "=",
    node.left,
    t.assignmentExpression(
      node.operator,
      t.memberExpression(t.identifier("exports"), node.left),
      node.right
    )
  );
};

DefaultFormatter.prototype.remapAssignments = function () {
  var localExports = this.localExports;
  var self = this;

  var isLocalReference = function (node, scope) {
    var name = node.name;
    return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.get(name, true);
  };

  traverse(this.file.ast, {
    enter: function (node, parent, scope) {
      if (t.isUpdateExpression(node) && isLocalReference(node.argument, scope)) {
        this.skip();

        // expand to long file assignment expression
        var assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.literal(1));

        // remap this assignment expression
        var remapped = self.remapExportAssignment(assign);

        // we don't need to change the result
        if (t.isExpressionStatement(parent) || node.prefix) {
          return remapped;
        }

        var nodes = [];
        nodes.push(remapped);

        var operator;
        if (node.operator === "--") {
          operator = "+";
        } else { // "++"
          operator = "-";
        }
        nodes.push(t.binaryExpression(operator, node.argument, t.literal(1)));

        return t.sequenceExpression(nodes);
      }

      if (t.isAssignmentExpression(node) && isLocalReference(node.left, scope)) {
        this.skip();
        return self.remapExportAssignment(node);
      }
    }
  });
};

DefaultFormatter.prototype.getModuleName = function () {
  var opts = this.file.opts;
  var filenameRelative = opts.filenameRelative;
  var moduleName = "";

  if (opts.moduleRoot) {
    moduleName = opts.moduleRoot + "/";
  }

  if (!opts.filenameRelative) {
    return moduleName + opts.filename.replace(/^\//, "");
  }

  if (opts.sourceRoot) {
    // remove sourceRoot from filename
    var sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?");
    filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
  }

  // remove extension
  filenameRelative = filenameRelative.replace(/\.(.*?)$/, "");

  moduleName += filenameRelative;

  return moduleName;
};

DefaultFormatter.prototype._pushStatement = function (ref, nodes) {
  if (t.isClass(ref) || t.isFunction(ref)) {
    if (ref.id) {
      nodes.push(t.toStatement(ref));
      ref = ref.id;
    }
  }

  return ref;
};

DefaultFormatter.prototype._hoistExport = function (declar, assign, priority) {
  if (t.isFunctionDeclaration(declar)) {
    assign._blockHoist = priority || 2;
  }

  return assign;
};

DefaultFormatter.prototype._exportSpecifier = function (getRef, specifier, node, nodes) {
  var inherits = false;
  if (node.specifiers.length === 1) inherits = node;

  if (node.source) {
    if (t.isExportBatchSpecifier(specifier)) {
      // export * from "foo";
      nodes.push(this._exportsWildcard(getRef(), node));
    } else {
      var ref;
      if (t.isSpecifierDefault(specifier) && !this.noInteropRequire) {
        // importing a default so we need to normalise it
        ref = t.callExpression(this.file.addHelper("interop-require"), [getRef()]);
      } else {
        ref = t.memberExpression(getRef(), specifier.id);
      }

      // export { foo } from "test";
      nodes.push(this._exportsAssign(
        t.getSpecifierName(specifier),
        ref,
        node
      ));
    }
  } else {
    // export { foo };
    nodes.push(this._exportsAssign(t.getSpecifierName(specifier), specifier.id, node));
  }
};

DefaultFormatter.prototype._exportsWildcard = function (objectIdentifier) {
  return t.expressionStatement(t.callExpression(this.file.addHelper("exports-wildcard"), [
    t.callExpression(this.file.addHelper("interop-require-wildcard"), [objectIdentifier])
  ]));
};

DefaultFormatter.prototype._exportsAssign = function (id, init) {
  return util.template("exports-assign", {
    VALUE: init,
    KEY:   id
  }, true);
};

DefaultFormatter.prototype.exportDeclaration = function (node, nodes) {
  var declar = node.declaration;

  var id = declar.id;

  if (node.default) {
    id = t.identifier("default");
  }

  var assign;

  if (t.isVariableDeclaration(declar)) {
    for (var i in declar.declarations) {
      var decl = declar.declarations[i];

      decl.init = this._exportsAssign(decl.id, decl.init, node).expression;

      var newDeclar = t.variableDeclaration(declar.kind, [decl]);
      if (i === "0") t.inherits(newDeclar, declar);
      nodes.push(newDeclar);
    }
  } else {
    var ref = declar;

    if (t.isFunctionDeclaration(declar) || t.isClassDeclaration(declar)) {
      ref = declar.id;
      nodes.push(declar);
    }

    assign = this._exportsAssign(id, ref, node);

    nodes.push(assign);

    this._hoistExport(declar, assign);
  }
};
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import { HTTP } from 'meteor/http';
import { Settings } from '/lib/collections';

export default function () {

  Meteor.methods({
    /**
     * Send Slack message if webhook URL is configured
     * @param  {String} message - message for Slack bot to send
     * @return {Object} response from Slack API
     */
    'util/slackMessage'(message) {
      check(message, String);

      const slackWebhookUrl = Settings.get('slackWebhookUrl');

      if (process.env.SLACK_ENABLED && slackWebhookUrl) {
        return HTTP.call('POST', slackWebhookUrl, {
          headers: {
            'Content-Type': 'application/json'
          },
          data: {
            username: 'Launchdock',
            text: message
          }
        });
      }
    }
  });

}
<commit_msg>add logging to Slack message method<commit_after>import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import { HTTP } from 'meteor/http';
import { Settings } from '/lib/collections';

export default function () {

  Meteor.methods({
    /**
     * Send Slack message if webhook URL is configured
     * @param  {String} message - message for Slack bot to send
     * @return {Object} response from Slack API
     */
    'util/slackMessage'(message) {
      check(message, String);

      const logger = Logger.child({
        meteor_method: 'util/slackMessage',
        meteor_method_args: [message],
        userId: this.userId
      });

      const slackWebhookUrl = Settings.get('slackWebhookUrl');

      if (process.env.SLACK_ENABLED && slackWebhookUrl) {
        logger.info({ message }, 'Sending Slack message');

        return HTTP.call('POST', slackWebhookUrl, {
          headers: {
            'Content-Type': 'application/json'
          },
          data: {
            username: 'Launchdock',
            text: message
          }
        });
      }

      logger.warn({ message }, 'Slack is either not enabled or not configured. Message not sent');

      return true;
    }
  });

}
<|endoftext|>