|  | @@ -1,300 +1,273 @@
 | 
	
		
			
				|  |  | -// Avoid running repeatedly due to new `document.documentElement`
 | 
	
		
			
				|  |  | -if (window.VM) return;
 | 
	
		
			
				|  |  | -window.VM = 1;
 | 
	
		
			
				|  |  | +(function injectContent() {
 | 
	
		
			
				|  |  | +  // Avoid running repeatedly due to new `document.documentElement`
 | 
	
		
			
				|  |  | +  if (window.VM) return;
 | 
	
		
			
				|  |  | +  window.VM = 1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -function getUniqId() {
 | 
	
		
			
				|  |  | -  return Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function noop() {}
 | 
	
		
			
				|  |  | -function includes(arr, item) {
 | 
	
		
			
				|  |  | -  for (var i = arr.length; i --;) {
 | 
	
		
			
				|  |  | -    if (arr[i] === item) return true;
 | 
	
		
			
				|  |  | +  function getUniqId() {
 | 
	
		
			
				|  |  | +    return Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function forEach(arr, func) {
 | 
	
		
			
				|  |  | -  var length = arr && arr.length || 0;
 | 
	
		
			
				|  |  | -  for (var i = 0; i < length; i ++) func(arr[i], i, arr);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function map(arr, func) {
 | 
	
		
			
				|  |  | -  var comm = this;
 | 
	
		
			
				|  |  | -  var res = [];
 | 
	
		
			
				|  |  | -  comm.forEach(arr, function (item, i) {
 | 
	
		
			
				|  |  | -    res.push(func(item, i, arr));
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  return res;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * http://www.webtoolkit.info/javascript-utf8.html
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -function utf8decode(utftext) {
 | 
	
		
			
				|  |  | -  var string = '';
 | 
	
		
			
				|  |  | -  var i = 0;
 | 
	
		
			
				|  |  | -  var c = 0, c2 = 0, c3 = 0;
 | 
	
		
			
				|  |  | -  while ( i < utftext.length ) {
 | 
	
		
			
				|  |  | -    c = utftext.charCodeAt(i);
 | 
	
		
			
				|  |  | -    if (c < 128) {
 | 
	
		
			
				|  |  | -      string += String.fromCharCode(c);
 | 
	
		
			
				|  |  | -      i ++;
 | 
	
		
			
				|  |  | -    } else if (c > 191 && c < 224) {
 | 
	
		
			
				|  |  | -      c2 = utftext.charCodeAt(i + 1);
 | 
	
		
			
				|  |  | -      string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
 | 
	
		
			
				|  |  | -      i += 2;
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      c2 = utftext.charCodeAt(i + 1);
 | 
	
		
			
				|  |  | -      c3 = utftext.charCodeAt(i + 2);
 | 
	
		
			
				|  |  | -      string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
 | 
	
		
			
				|  |  | -      i += 3;
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +  * http://www.webtoolkit.info/javascript-utf8.html
 | 
	
		
			
				|  |  | +  */
 | 
	
		
			
				|  |  | +  function utf8decode(utftext) {
 | 
	
		
			
				|  |  | +    /* eslint-disable no-bitwise */
 | 
	
		
			
				|  |  | +    let string = '';
 | 
	
		
			
				|  |  | +    let i = 0;
 | 
	
		
			
				|  |  | +    let c1 = 0;
 | 
	
		
			
				|  |  | +    let c2 = 0;
 | 
	
		
			
				|  |  | +    let c3 = 0;
 | 
	
		
			
				|  |  | +    while (i < utftext.length) {
 | 
	
		
			
				|  |  | +      c1 = utftext.charCodeAt(i);
 | 
	
		
			
				|  |  | +      if (c1 < 128) {
 | 
	
		
			
				|  |  | +        string += String.fromCharCode(c1);
 | 
	
		
			
				|  |  | +        i += 1;
 | 
	
		
			
				|  |  | +      } else if (c1 > 191 && c1 < 224) {
 | 
	
		
			
				|  |  | +        c2 = utftext.charCodeAt(i + 1);
 | 
	
		
			
				|  |  | +        string += String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
 | 
	
		
			
				|  |  | +        i += 2;
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        c2 = utftext.charCodeAt(i + 1);
 | 
	
		
			
				|  |  | +        c3 = utftext.charCodeAt(i + 2);
 | 
	
		
			
				|  |  | +        string += String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
 | 
	
		
			
				|  |  | +        i += 3;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    return string;
 | 
	
		
			
				|  |  | +    /* eslint-enable no-bitwise */
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return string;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -function sendMessage(data) {
 | 
	
		
			
				|  |  | -  return browser.runtime.sendMessage(data);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function getPopup(){
 | 
	
		
			
				|  |  | -  // XXX: only scripts run in top level window are counted
 | 
	
		
			
				|  |  | -  top === window && sendMessage({
 | 
	
		
			
				|  |  | -    cmd: 'SetPopup',
 | 
	
		
			
				|  |  | -    data: {
 | 
	
		
			
				|  |  | -      ids: ids,
 | 
	
		
			
				|  |  | -      menus: menus,
 | 
	
		
			
				|  |  | -    },
 | 
	
		
			
				|  |  | -  })
 | 
	
		
			
				|  |  | -  .catch(noop);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -var badge = {
 | 
	
		
			
				|  |  | -  number: 0,
 | 
	
		
			
				|  |  | -  ready: false,
 | 
	
		
			
				|  |  | -  willSet: false,
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -function getBadge() {
 | 
	
		
			
				|  |  | -  badge.willSet = true;
 | 
	
		
			
				|  |  | -  setBadge();
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function setBadge() {
 | 
	
		
			
				|  |  | -  if (badge.ready && badge.willSet) {
 | 
	
		
			
				|  |  | -    // XXX: only scripts run in top level window are counted
 | 
	
		
			
				|  |  | -    top === window && sendMessage({cmd: 'SetBadge', data: badge.number});
 | 
	
		
			
				|  |  | +  function sendMessage(data) {
 | 
	
		
			
				|  |  | +    return browser.runtime.sendMessage(data);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * @desc Wrap methods to prevent unexpected modifications.
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -function getWrapper() {
 | 
	
		
			
				|  |  | -  // http://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects
 | 
	
		
			
				|  |  | -  // http://developer.mozilla.org/docs/Web/API/Window
 | 
	
		
			
				|  |  | -  var comm = this;
 | 
	
		
			
				|  |  | -  var wrapper = {};
 | 
	
		
			
				|  |  | -  // `eval` should be called directly so that it is run in current scope
 | 
	
		
			
				|  |  | -  wrapper.eval = eval;
 | 
	
		
			
				|  |  | -  // Wrap methods
 | 
	
		
			
				|  |  | -  comm.forEach([
 | 
	
		
			
				|  |  | -    // 'uneval',
 | 
	
		
			
				|  |  | -    'isFinite',
 | 
	
		
			
				|  |  | -    'isNaN',
 | 
	
		
			
				|  |  | -    'parseFloat',
 | 
	
		
			
				|  |  | -    'parseInt',
 | 
	
		
			
				|  |  | -    'decodeURI',
 | 
	
		
			
				|  |  | -    'decodeURIComponent',
 | 
	
		
			
				|  |  | -    'encodeURI',
 | 
	
		
			
				|  |  | -    'encodeURIComponent',
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    'addEventListener',
 | 
	
		
			
				|  |  | -    'alert',
 | 
	
		
			
				|  |  | -    'atob',
 | 
	
		
			
				|  |  | -    'blur',
 | 
	
		
			
				|  |  | -    'btoa',
 | 
	
		
			
				|  |  | -    'clearInterval',
 | 
	
		
			
				|  |  | -    'clearTimeout',
 | 
	
		
			
				|  |  | -    'close',
 | 
	
		
			
				|  |  | -    'confirm',
 | 
	
		
			
				|  |  | -    'dispatchEvent',
 | 
	
		
			
				|  |  | -    'fetch',
 | 
	
		
			
				|  |  | -    'find',
 | 
	
		
			
				|  |  | -    'focus',
 | 
	
		
			
				|  |  | -    'getComputedStyle',
 | 
	
		
			
				|  |  | -    'getSelection',
 | 
	
		
			
				|  |  | -    'matchMedia',
 | 
	
		
			
				|  |  | -    'moveBy',
 | 
	
		
			
				|  |  | -    'moveTo',
 | 
	
		
			
				|  |  | -    'open',
 | 
	
		
			
				|  |  | -    'openDialog',
 | 
	
		
			
				|  |  | -    'postMessage',
 | 
	
		
			
				|  |  | -    'print',
 | 
	
		
			
				|  |  | -    'prompt',
 | 
	
		
			
				|  |  | -    'removeEventListener',
 | 
	
		
			
				|  |  | -    'requestAnimationFrame',
 | 
	
		
			
				|  |  | -    'resizeBy',
 | 
	
		
			
				|  |  | -    'resizeTo',
 | 
	
		
			
				|  |  | -    'scroll',
 | 
	
		
			
				|  |  | -    'scrollBy',
 | 
	
		
			
				|  |  | -    'scrollByLines',
 | 
	
		
			
				|  |  | -    'scrollByPages',
 | 
	
		
			
				|  |  | -    'scrollTo',
 | 
	
		
			
				|  |  | -    'setInterval',
 | 
	
		
			
				|  |  | -    'setTimeout',
 | 
	
		
			
				|  |  | -    'stop',
 | 
	
		
			
				|  |  | -  ], function (name) {
 | 
	
		
			
				|  |  | -    var method = window[name];
 | 
	
		
			
				|  |  | -    if (method) wrapper[name] = function () {
 | 
	
		
			
				|  |  | -      return method.apply(window, arguments);
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  function defineProtectedProperty(name) {
 | 
	
		
			
				|  |  | -    var modified = false;
 | 
	
		
			
				|  |  | -    var value;
 | 
	
		
			
				|  |  | -    Object.defineProperty(wrapper, name, {
 | 
	
		
			
				|  |  | -      get: function () {
 | 
	
		
			
				|  |  | -        if (!modified) value = window[name];
 | 
	
		
			
				|  |  | -        return value === window ? wrapper : value;
 | 
	
		
			
				|  |  | -      },
 | 
	
		
			
				|  |  | -      set: function (val) {
 | 
	
		
			
				|  |  | -        modified = true;
 | 
	
		
			
				|  |  | -        value = val;
 | 
	
		
			
				|  |  | -      },
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  function defineReactedProperty(name) {
 | 
	
		
			
				|  |  | -    Object.defineProperty(wrapper, name, {
 | 
	
		
			
				|  |  | -      get: function () {
 | 
	
		
			
				|  |  | -        var value = window[name];
 | 
	
		
			
				|  |  | -        return value === window ? wrapper : value;
 | 
	
		
			
				|  |  | -      },
 | 
	
		
			
				|  |  | -      set: function (val) {
 | 
	
		
			
				|  |  | -        window[name] = val;
 | 
	
		
			
				|  |  | -      },
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | +  const badge = {
 | 
	
		
			
				|  |  | +    number: 0,
 | 
	
		
			
				|  |  | +    ready: false,
 | 
	
		
			
				|  |  | +    willSet: false,
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +  function getBadge() {
 | 
	
		
			
				|  |  | +    badge.willSet = true;
 | 
	
		
			
				|  |  | +    setBadge();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  // Wrap properties
 | 
	
		
			
				|  |  | -  comm.forEach(comm.props, function (name) {
 | 
	
		
			
				|  |  | -    if (wrapper[name]) return;
 | 
	
		
			
				|  |  | -    if (name.slice(0, 2) === 'on') defineReactedProperty(name);
 | 
	
		
			
				|  |  | -    else defineProtectedProperty(name);
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  return wrapper;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -// Communicator
 | 
	
		
			
				|  |  | -var comm = {
 | 
	
		
			
				|  |  | -  vmid: 'VM_' + getUniqId(),
 | 
	
		
			
				|  |  | -  state: 0,
 | 
	
		
			
				|  |  | -  utf8decode: utf8decode,
 | 
	
		
			
				|  |  | -  getUniqId: getUniqId,
 | 
	
		
			
				|  |  | -  props: Object.getOwnPropertyNames(window),
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Array functions
 | 
	
		
			
				|  |  | -  // Notice: avoid using prototype functions since they may be changed by page scripts
 | 
	
		
			
				|  |  | -  includes: includes,
 | 
	
		
			
				|  |  | -  forEach: forEach,
 | 
	
		
			
				|  |  | -  map: map,
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  init: function (srcId, destId) {
 | 
	
		
			
				|  |  | -    var comm = this;
 | 
	
		
			
				|  |  | -    comm.sid = comm.vmid + srcId;
 | 
	
		
			
				|  |  | -    comm.did = comm.vmid + destId;
 | 
	
		
			
				|  |  | -    var handle = comm['handle' + srcId];
 | 
	
		
			
				|  |  | -    document.addEventListener(comm.sid, function (e) {
 | 
	
		
			
				|  |  | -      var data = JSON.parse(e.detail);
 | 
	
		
			
				|  |  | -      handle.call(comm, data);
 | 
	
		
			
				|  |  | -    }, false);
 | 
	
		
			
				|  |  | -    comm.load = comm.checkLoad = function () {};
 | 
	
		
			
				|  |  | -    // check whether the page is injectable via <script>, whether limited by CSP
 | 
	
		
			
				|  |  | -    try {
 | 
	
		
			
				|  |  | -      comm.injectable = (0, eval)('true');
 | 
	
		
			
				|  |  | -    } catch (e) {
 | 
	
		
			
				|  |  | -      comm.injectable = false;
 | 
	
		
			
				|  |  | +  function setBadge() {
 | 
	
		
			
				|  |  | +    if (badge.ready && badge.willSet) {
 | 
	
		
			
				|  |  | +      // XXX: only scripts run in top level window are counted
 | 
	
		
			
				|  |  | +      if (top === window) sendMessage({ cmd: 'SetBadge', data: badge.number });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | -  post: function (data) {
 | 
	
		
			
				|  |  | -    // Firefox issue: data must be stringified to avoid cross-origin problem
 | 
	
		
			
				|  |  | -    var e = new CustomEvent(this.did, {detail: JSON.stringify(data)});
 | 
	
		
			
				|  |  | -    document.dispatchEvent(e);
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | -  handleR: function (obj) {
 | 
	
		
			
				|  |  | -    var comm = this;
 | 
	
		
			
				|  |  | -    var maps = {
 | 
	
		
			
				|  |  | -      LoadScript: comm.loadScript.bind(comm),
 | 
	
		
			
				|  |  | -      Command: function (data) {
 | 
	
		
			
				|  |  | -        var func = comm.command[data];
 | 
	
		
			
				|  |  | -        func && func();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function handleWeb(obj) {
 | 
	
		
			
				|  |  | +    const comm = this;
 | 
	
		
			
				|  |  | +    const handlers = {
 | 
	
		
			
				|  |  | +      LoadScripts(data) {
 | 
	
		
			
				|  |  | +        comm.onLoadScripts(data);
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      Command(data) {
 | 
	
		
			
				|  |  | +        const func = comm.command[data];
 | 
	
		
			
				|  |  | +        if (func) func();
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  | -      GotRequestId: function (id) {
 | 
	
		
			
				|  |  | -        comm.qrequests.shift().start(id);
 | 
	
		
			
				|  |  | +      GotRequestId(id) {
 | 
	
		
			
				|  |  | +        const req = comm.qrequests.shift();
 | 
	
		
			
				|  |  | +        req.start(req, id);
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  | -      HttpRequested: function (r) {
 | 
	
		
			
				|  |  | -        var req = comm.requests[r.id];
 | 
	
		
			
				|  |  | -        if (req) req.callback(r);
 | 
	
		
			
				|  |  | +      HttpRequested(res) {
 | 
	
		
			
				|  |  | +        const req = comm.requests[res.id];
 | 
	
		
			
				|  |  | +        if (req) req.callback(req, res);
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  | -      UpdateValues: function (data) {
 | 
	
		
			
				|  |  | -        var values = comm.values;
 | 
	
		
			
				|  |  | +      UpdateValues(data) {
 | 
	
		
			
				|  |  | +        const { values } = comm.values;
 | 
	
		
			
				|  |  |          if (values && values[data.uri]) values[data.uri] = data.values;
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  | -      NotificationClicked: function (id) {
 | 
	
		
			
				|  |  | -        var options = comm.notif[id];
 | 
	
		
			
				|  |  | +      NotificationClicked(id) {
 | 
	
		
			
				|  |  | +        const options = comm.notif[id];
 | 
	
		
			
				|  |  |          if (options) {
 | 
	
		
			
				|  |  | -          var onclick = options.onclick;
 | 
	
		
			
				|  |  | -          onclick && onclick();
 | 
	
		
			
				|  |  | +          const { onclick } = options;
 | 
	
		
			
				|  |  | +          if (onclick) onclick();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  | -      NotificationClosed: function (id) {
 | 
	
		
			
				|  |  | -        var options = comm.notif[id];
 | 
	
		
			
				|  |  | +      NotificationClosed(id) {
 | 
	
		
			
				|  |  | +        const options = comm.notif[id];
 | 
	
		
			
				|  |  |          if (options) {
 | 
	
		
			
				|  |  |            delete comm.notif[id];
 | 
	
		
			
				|  |  | -          var ondone = options.ondone;
 | 
	
		
			
				|  |  | -          ondone && ondone();
 | 
	
		
			
				|  |  | +          const { ondone } = options;
 | 
	
		
			
				|  |  | +          if (ondone) ondone();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        // advanced inject
 | 
	
		
			
				|  |  | -      Injected: function (id) {
 | 
	
		
			
				|  |  | -        var obj = comm.ainject[id];
 | 
	
		
			
				|  |  | -        var func = window['VM_' + id];
 | 
	
		
			
				|  |  | -        delete window['VM_' + id];
 | 
	
		
			
				|  |  | +      Injected(id) {
 | 
	
		
			
				|  |  | +        const item = comm.ainject[id];
 | 
	
		
			
				|  |  | +        const func = window[`VM_${id}`];
 | 
	
		
			
				|  |  | +        delete window[`VM_${id}`];
 | 
	
		
			
				|  |  |          delete comm.ainject[id];
 | 
	
		
			
				|  |  | -        if (obj && func) comm.runCode(obj[0], func, obj[1], obj[2]);
 | 
	
		
			
				|  |  | +        if (item && func) comm.runCode(item[0], func, item[1], item[2]);
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | -    var func = maps[obj.cmd];
 | 
	
		
			
				|  |  | -    if (func) func(obj.data);
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | -  runCode: function (name, func, args, thisObj) {
 | 
	
		
			
				|  |  | -    try {
 | 
	
		
			
				|  |  | -      func.apply(thisObj, args);
 | 
	
		
			
				|  |  | -    } catch (e) {
 | 
	
		
			
				|  |  | -      var msg = 'Error running script: ' + name + '\n' + e;
 | 
	
		
			
				|  |  | -      if (e.message) msg += '\n' + e.message;
 | 
	
		
			
				|  |  | -      console.error(msg);
 | 
	
		
			
				|  |  | +    const handle = handlers[obj.cmd];
 | 
	
		
			
				|  |  | +    if (handle) handle(obj.data);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +  * @desc Wrap methods to prevent unexpected modifications.
 | 
	
		
			
				|  |  | +  */
 | 
	
		
			
				|  |  | +  function getWrapper() {
 | 
	
		
			
				|  |  | +    // http://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects
 | 
	
		
			
				|  |  | +    // http://developer.mozilla.org/docs/Web/API/Window
 | 
	
		
			
				|  |  | +    const comm = this;
 | 
	
		
			
				|  |  | +    const wrapper = {};
 | 
	
		
			
				|  |  | +    comm.forEach([
 | 
	
		
			
				|  |  | +      // `eval` should be called directly so that it is run in current scope
 | 
	
		
			
				|  |  | +      'eval',
 | 
	
		
			
				|  |  | +    ], name => {
 | 
	
		
			
				|  |  | +      wrapper[name] = window[name];
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    comm.forEach([
 | 
	
		
			
				|  |  | +      // 'uneval',
 | 
	
		
			
				|  |  | +      'isFinite',
 | 
	
		
			
				|  |  | +      'isNaN',
 | 
	
		
			
				|  |  | +      'parseFloat',
 | 
	
		
			
				|  |  | +      'parseInt',
 | 
	
		
			
				|  |  | +      'decodeURI',
 | 
	
		
			
				|  |  | +      'decodeURIComponent',
 | 
	
		
			
				|  |  | +      'encodeURI',
 | 
	
		
			
				|  |  | +      'encodeURIComponent',
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      'addEventListener',
 | 
	
		
			
				|  |  | +      'alert',
 | 
	
		
			
				|  |  | +      'atob',
 | 
	
		
			
				|  |  | +      'blur',
 | 
	
		
			
				|  |  | +      'btoa',
 | 
	
		
			
				|  |  | +      'clearInterval',
 | 
	
		
			
				|  |  | +      'clearTimeout',
 | 
	
		
			
				|  |  | +      'close',
 | 
	
		
			
				|  |  | +      'confirm',
 | 
	
		
			
				|  |  | +      'dispatchEvent',
 | 
	
		
			
				|  |  | +      'fetch',
 | 
	
		
			
				|  |  | +      'find',
 | 
	
		
			
				|  |  | +      'focus',
 | 
	
		
			
				|  |  | +      'getComputedStyle',
 | 
	
		
			
				|  |  | +      'getSelection',
 | 
	
		
			
				|  |  | +      'matchMedia',
 | 
	
		
			
				|  |  | +      'moveBy',
 | 
	
		
			
				|  |  | +      'moveTo',
 | 
	
		
			
				|  |  | +      'open',
 | 
	
		
			
				|  |  | +      'openDialog',
 | 
	
		
			
				|  |  | +      'postMessage',
 | 
	
		
			
				|  |  | +      'print',
 | 
	
		
			
				|  |  | +      'prompt',
 | 
	
		
			
				|  |  | +      'removeEventListener',
 | 
	
		
			
				|  |  | +      'requestAnimationFrame',
 | 
	
		
			
				|  |  | +      'resizeBy',
 | 
	
		
			
				|  |  | +      'resizeTo',
 | 
	
		
			
				|  |  | +      'scroll',
 | 
	
		
			
				|  |  | +      'scrollBy',
 | 
	
		
			
				|  |  | +      'scrollByLines',
 | 
	
		
			
				|  |  | +      'scrollByPages',
 | 
	
		
			
				|  |  | +      'scrollTo',
 | 
	
		
			
				|  |  | +      'setInterval',
 | 
	
		
			
				|  |  | +      'setTimeout',
 | 
	
		
			
				|  |  | +      'stop',
 | 
	
		
			
				|  |  | +    ], name => {
 | 
	
		
			
				|  |  | +      const method = window[name];
 | 
	
		
			
				|  |  | +      if (method) {
 | 
	
		
			
				|  |  | +        wrapper[name] = (...args) => method.apply(window, args);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    function defineProtectedProperty(name) {
 | 
	
		
			
				|  |  | +      let modified = false;
 | 
	
		
			
				|  |  | +      let value;
 | 
	
		
			
				|  |  | +      Object.defineProperty(wrapper, name, {
 | 
	
		
			
				|  |  | +        get() {
 | 
	
		
			
				|  |  | +          if (!modified) value = window[name];
 | 
	
		
			
				|  |  | +          return value === window ? wrapper : value;
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        set(val) {
 | 
	
		
			
				|  |  | +          modified = true;
 | 
	
		
			
				|  |  | +          value = val;
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    function defineReactedProperty(name) {
 | 
	
		
			
				|  |  | +      Object.defineProperty(wrapper, name, {
 | 
	
		
			
				|  |  | +        get() {
 | 
	
		
			
				|  |  | +          const value = window[name];
 | 
	
		
			
				|  |  | +          return value === window ? wrapper : value;
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        set(val) {
 | 
	
		
			
				|  |  | +          window[name] = val;
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    // Wrap properties
 | 
	
		
			
				|  |  | +    comm.forEach(comm.props, name => {
 | 
	
		
			
				|  |  | +      if (name in wrapper) return;
 | 
	
		
			
				|  |  | +      if (name.slice(0, 2) === 'on') defineReactedProperty(name);
 | 
	
		
			
				|  |  | +      else defineProtectedProperty(name);
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    return wrapper;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function initHandler(src, dest) {
 | 
	
		
			
				|  |  | +    const comm = this;
 | 
	
		
			
				|  |  | +    comm.sid = comm.vmid + src;
 | 
	
		
			
				|  |  | +    comm.did = comm.vmid + dest;
 | 
	
		
			
				|  |  | +    const handle = comm[`handle_${src}`];
 | 
	
		
			
				|  |  | +    document.addEventListener(comm.sid, e => {
 | 
	
		
			
				|  |  | +      const data = JSON.parse(e.detail);
 | 
	
		
			
				|  |  | +      handle.call(comm, data);
 | 
	
		
			
				|  |  | +    }, false);
 | 
	
		
			
				|  |  | +    comm.load = comm.noop;
 | 
	
		
			
				|  |  | +    comm.checkLoad = comm.noop;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function postData(data) {
 | 
	
		
			
				|  |  | +    const comm = this;
 | 
	
		
			
				|  |  | +    // Firefox issue: data must be stringified to avoid cross-origin problem
 | 
	
		
			
				|  |  | +    const e = new CustomEvent(comm.did, { detail: JSON.stringify(data) });
 | 
	
		
			
				|  |  | +    document.dispatchEvent(e);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function getRequest(arg) {
 | 
	
		
			
				|  |  | +    const comm = this;
 | 
	
		
			
				|  |  | +    init();
 | 
	
		
			
				|  |  | +    return comm.getRequest(arg);
 | 
	
		
			
				|  |  | +    function init() {
 | 
	
		
			
				|  |  | +      comm.requests = {};
 | 
	
		
			
				|  |  | +      comm.qrequests = [];
 | 
	
		
			
				|  |  | +      comm.getRequest = details => {
 | 
	
		
			
				|  |  | +        const req = {
 | 
	
		
			
				|  |  | +          details,
 | 
	
		
			
				|  |  | +          callback,
 | 
	
		
			
				|  |  | +          start,
 | 
	
		
			
				|  |  | +          req: {
 | 
	
		
			
				|  |  | +            abort: reqAbort,
 | 
	
		
			
				|  |  | +          },
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        details.url = getFullUrl(details.url);
 | 
	
		
			
				|  |  | +        comm.qrequests.push(req);
 | 
	
		
			
				|  |  | +        comm.post({ cmd: 'GetRequestId' });
 | 
	
		
			
				|  |  | +        return req.req;
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | -  initRequest: function () {
 | 
	
		
			
				|  |  | -    // request functions
 | 
	
		
			
				|  |  | -    function reqAbort(){
 | 
	
		
			
				|  |  | -      comm.post({cmd: 'AbortRequest', data: this.id});
 | 
	
		
			
				|  |  | +    function reqAbort() {
 | 
	
		
			
				|  |  | +      comm.post({ cmd: 'AbortRequest', data: this.id });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      function parseData(req, details) {
 | 
	
		
			
				|  |  |        if (req.resType) {
 | 
	
		
			
				|  |  |          // blob or arraybuffer
 | 
	
		
			
				|  |  | -        var data = req.data.response.split(',');
 | 
	
		
			
				|  |  | -        var mimetype = data[0].match(/^data:(.*?);base64$/);
 | 
	
		
			
				|  |  | +        let data = req.data.response.split(',');
 | 
	
		
			
				|  |  | +        const mimetype = data[0].match(/^data:(.*?);base64$/);
 | 
	
		
			
				|  |  |          if (!mimetype) {
 | 
	
		
			
				|  |  |            // invalid
 | 
	
		
			
				|  |  |            req.data.response = null;
 | 
	
		
			
				|  |  |          } else {
 | 
	
		
			
				|  |  |            data = window.atob(data[1]);
 | 
	
		
			
				|  |  | -          var arr = new window.Uint8Array(data.length);
 | 
	
		
			
				|  |  | -          for (var i = 0; i < data.length; i ++) arr[i] = data.charCodeAt(i);
 | 
	
		
			
				|  |  | -          if (details.responseType == 'blob') {
 | 
	
		
			
				|  |  | +          const arr = new window.Uint8Array(data.length);
 | 
	
		
			
				|  |  | +          for (let i = 0; i < data.length; i += 1) arr[i] = data.charCodeAt(i);
 | 
	
		
			
				|  |  | +          if (details.responseType === 'blob') {
 | 
	
		
			
				|  |  |              // blob
 | 
	
		
			
				|  |  | -            return new Blob([arr], {type: mimetype});
 | 
	
		
			
				|  |  | -          } else {
 | 
	
		
			
				|  |  | -            // arraybuffer
 | 
	
		
			
				|  |  | -            return arr.buffer;
 | 
	
		
			
				|  |  | +            return new Blob([arr], { type: mimetype });
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  | +          // arraybuffer
 | 
	
		
			
				|  |  | +          return arr.buffer;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -      } else if (details.responseType == 'json') {
 | 
	
		
			
				|  |  | +      } else if (details.responseType === 'json') {
 | 
	
		
			
				|  |  |          // json
 | 
	
		
			
				|  |  |          return JSON.parse(req.data.response);
 | 
	
		
			
				|  |  |        } else {
 | 
	
	
		
			
				|  | @@ -303,106 +276,74 @@ var comm = {
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      // request object functions
 | 
	
		
			
				|  |  | -    function callback(req) {
 | 
	
		
			
				|  |  | -      var t = this;
 | 
	
		
			
				|  |  | -      var cb = t.details['on' + req.type];
 | 
	
		
			
				|  |  | +    function callback(req, res) {
 | 
	
		
			
				|  |  | +      const cb = req.details[`on${res.type}`];
 | 
	
		
			
				|  |  |        if (cb) {
 | 
	
		
			
				|  |  | -        if (req.data.response) {
 | 
	
		
			
				|  |  | -          if (!t.data) t.data = [parseData(req, t.details)];
 | 
	
		
			
				|  |  | -          req.data.response = t.data[0];
 | 
	
		
			
				|  |  | +        if (res.data.response) {
 | 
	
		
			
				|  |  | +          if (!req.data) req.data = [parseData(res, req.details)];
 | 
	
		
			
				|  |  | +          res.data.response = req.data[0];
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        cb(req.data);
 | 
	
		
			
				|  |  | +        cb(res.data);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      if (req.type == 'loadend') delete comm.requests[t.id];
 | 
	
		
			
				|  |  | +      if (res.type === 'loadend') delete comm.requests[req.id];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    function start(id) {
 | 
	
		
			
				|  |  | -      var t = this;
 | 
	
		
			
				|  |  | -      var data = {
 | 
	
		
			
				|  |  | -        id: id,
 | 
	
		
			
				|  |  | -        method: t.details.method,
 | 
	
		
			
				|  |  | -        url: t.details.url,
 | 
	
		
			
				|  |  | -        data: t.details.data,
 | 
	
		
			
				|  |  | -        //async: !t.details.synchronous,
 | 
	
		
			
				|  |  | -        user: t.details.user,
 | 
	
		
			
				|  |  | -        password: t.details.password,
 | 
	
		
			
				|  |  | -        headers: t.details.headers,
 | 
	
		
			
				|  |  | -        overrideMimeType: t.details.overrideMimeType,
 | 
	
		
			
				|  |  | +    function start(req, id) {
 | 
	
		
			
				|  |  | +      const data = {
 | 
	
		
			
				|  |  | +        id,
 | 
	
		
			
				|  |  | +        method: req.details.method,
 | 
	
		
			
				|  |  | +        url: req.details.url,
 | 
	
		
			
				|  |  | +        data: req.details.data,
 | 
	
		
			
				|  |  | +        // async: !req.details.synchronous,
 | 
	
		
			
				|  |  | +        user: req.details.user,
 | 
	
		
			
				|  |  | +        password: req.details.password,
 | 
	
		
			
				|  |  | +        headers: req.details.headers,
 | 
	
		
			
				|  |  | +        overrideMimeType: req.details.overrideMimeType,
 | 
	
		
			
				|  |  |        };
 | 
	
		
			
				|  |  | -      t.id = id;
 | 
	
		
			
				|  |  | -      comm.requests[id] = t;
 | 
	
		
			
				|  |  | -      if (comm.includes(['arraybuffer', 'blob'], t.details.responseType)) {
 | 
	
		
			
				|  |  | +      req.id = id;
 | 
	
		
			
				|  |  | +      comm.requests[id] = req;
 | 
	
		
			
				|  |  | +      if (comm.includes(['arraybuffer', 'blob'], req.details.responseType)) {
 | 
	
		
			
				|  |  |          data.responseType = 'blob';
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      comm.post({cmd: 'HttpRequest', data: data});
 | 
	
		
			
				|  |  | +      comm.post({ cmd: 'HttpRequest', data });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      function getFullUrl(url) {
 | 
	
		
			
				|  |  | -      var a = document.createElement('a');
 | 
	
		
			
				|  |  | +      const a = document.createElement('a');
 | 
	
		
			
				|  |  |        a.setAttribute('href', url);
 | 
	
		
			
				|  |  |        return a.href;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    var comm = this;
 | 
	
		
			
				|  |  | -    comm.requests = {};
 | 
	
		
			
				|  |  | -    comm.qrequests = [];
 | 
	
		
			
				|  |  | -    comm.Request = function (details) {
 | 
	
		
			
				|  |  | -      var t = {
 | 
	
		
			
				|  |  | -        details: details,
 | 
	
		
			
				|  |  | -        callback: callback,
 | 
	
		
			
				|  |  | -        start: start,
 | 
	
		
			
				|  |  | -        req: {
 | 
	
		
			
				|  |  | -          abort: reqAbort,
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -      };
 | 
	
		
			
				|  |  | -      details.url = getFullUrl(details.url);
 | 
	
		
			
				|  |  | -      comm.qrequests.push(t);
 | 
	
		
			
				|  |  | -      comm.post({cmd: 'GetRequestId'});
 | 
	
		
			
				|  |  | -      return t.req;
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | -  getWrapper: getWrapper,
 | 
	
		
			
				|  |  | -  wrapGM: function (script, cache) {
 | 
	
		
			
				|  |  | -    function getValues() {
 | 
	
		
			
				|  |  | -      return comm.values[script.uri];
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    function propertyToString() {
 | 
	
		
			
				|  |  | -      return '[Violentmonkey property]';
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    function addProperty(name, prop, obj) {
 | 
	
		
			
				|  |  | -      if ('value' in prop) prop.writable = false;
 | 
	
		
			
				|  |  | -      prop.configurable = false;
 | 
	
		
			
				|  |  | -      Object.defineProperty(obj, name, prop);
 | 
	
		
			
				|  |  | -      if (typeof obj[name] == 'function') obj[name].toString = propertyToString;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    function saveValues() {
 | 
	
		
			
				|  |  | -      comm.post({
 | 
	
		
			
				|  |  | -        cmd: 'SetValue',
 | 
	
		
			
				|  |  | -        data: {
 | 
	
		
			
				|  |  | -          uri: script.uri,
 | 
	
		
			
				|  |  | -          values: getValues(),
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -      });
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function wrapGM(script, cache) {
 | 
	
		
			
				|  |  |      // Add GM functions
 | 
	
		
			
				|  |  |      // Reference: http://wiki.greasespot.net/Greasemonkey_Manual:API
 | 
	
		
			
				|  |  | -    var comm = this;
 | 
	
		
			
				|  |  | -    var gm = {};
 | 
	
		
			
				|  |  | -    var grant = script.meta.grant || [];
 | 
	
		
			
				|  |  | -    var urls = {};
 | 
	
		
			
				|  |  | -    if (!grant.length || grant.length == 1 && grant[0] == 'none') {
 | 
	
		
			
				|  |  | +    const comm = this;
 | 
	
		
			
				|  |  | +    const gm = {};
 | 
	
		
			
				|  |  | +    const grant = script.meta.grant || [];
 | 
	
		
			
				|  |  | +    const urls = {};
 | 
	
		
			
				|  |  | +    if (!grant.length || (grant.length === 1 && grant[0] === 'none')) {
 | 
	
		
			
				|  |  |        // @grant none
 | 
	
		
			
				|  |  |        grant.pop();
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -      gm['window'] = comm.getWrapper();
 | 
	
		
			
				|  |  | +      gm.window = comm.getWrapper();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      if (!comm.includes(grant, 'unsafeWindow')) grant.push('unsafeWindow');
 | 
	
		
			
				|  |  |      if (!comm.includes(grant, 'GM_info')) grant.push('GM_info');
 | 
	
		
			
				|  |  | -    var resources = script.meta.resources || {};
 | 
	
		
			
				|  |  | -    var gm_funcs = {
 | 
	
		
			
				|  |  | -      unsafeWindow: {value: window},
 | 
	
		
			
				|  |  | +    const resources = script.meta.resources || {};
 | 
	
		
			
				|  |  | +    const dataEncoders = {
 | 
	
		
			
				|  |  | +      o: val => JSON.stringify(val),
 | 
	
		
			
				|  |  | +      '': val => val.toString(),
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    const dataDecoders = {
 | 
	
		
			
				|  |  | +      n: val => Number(val),
 | 
	
		
			
				|  |  | +      b: val => val === 'true',
 | 
	
		
			
				|  |  | +      o: val => JSON.parse(val),
 | 
	
		
			
				|  |  | +      '': val => val,
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    const gmFunctions = {
 | 
	
		
			
				|  |  | +      unsafeWindow: { value: window },
 | 
	
		
			
				|  |  |        GM_info: {
 | 
	
		
			
				|  |  | -        get: function () {
 | 
	
		
			
				|  |  | -          var m = script.code.match(/\/\/\s+==UserScript==\s+([\s\S]*?)\/\/\s+==\/UserScript==\s/);
 | 
	
		
			
				|  |  | -          var data = {
 | 
	
		
			
				|  |  | +        get() {
 | 
	
		
			
				|  |  | +          const matches = script.code.match(/\/\/\s+==UserScript==\s+([\s\S]*?)\/\/\s+==\/UserScript==\s/);
 | 
	
		
			
				|  |  | +          const data = {
 | 
	
		
			
				|  |  |              description: script.meta.description || '',
 | 
	
		
			
				|  |  |              excludes: script.meta.exclude.concat(),
 | 
	
		
			
				|  |  |              includes: script.meta.include.concat(),
 | 
	
	
		
			
				|  | @@ -414,159 +355,146 @@ var comm = {
 | 
	
		
			
				|  |  |              unwrap: false,
 | 
	
		
			
				|  |  |              version: script.meta.version || '',
 | 
	
		
			
				|  |  |            };
 | 
	
		
			
				|  |  | -          var obj = {};
 | 
	
		
			
				|  |  | -          addProperty('scriptMetaStr', {value: m ? m[1] : ''}, obj);
 | 
	
		
			
				|  |  | +          const obj = {};
 | 
	
		
			
				|  |  | +          addProperty('scriptMetaStr', { value: matches ? matches[1] : '' }, obj);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |            // whether update is allowed
 | 
	
		
			
				|  |  | -          addProperty('scriptWillUpdate', {value: !!script.update}, obj);
 | 
	
		
			
				|  |  | +          addProperty('scriptWillUpdate', { value: !!script.update }, obj);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |            // Violentmonkey specific data
 | 
	
		
			
				|  |  | -          addProperty('version', {value: comm.version}, obj);
 | 
	
		
			
				|  |  | -          addProperty('scriptHandler', {value: 'Violentmonkey'}, obj);
 | 
	
		
			
				|  |  | +          addProperty('version', { value: comm.version }, obj);
 | 
	
		
			
				|  |  | +          addProperty('scriptHandler', { value: 'Violentmonkey' }, obj);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |            // script object
 | 
	
		
			
				|  |  | -          addProperty('script', {value:{}}, obj);
 | 
	
		
			
				|  |  | -          var i;
 | 
	
		
			
				|  |  | -          for (i in data) addProperty(i, {value: data[i]}, obj.script);
 | 
	
		
			
				|  |  | -          for (i in script.meta.resources) {
 | 
	
		
			
				|  |  | -            addProperty(i, {value: script.meta.resources[i]}, obj.script.resources);
 | 
	
		
			
				|  |  | -          }
 | 
	
		
			
				|  |  | +          addProperty('script', { value: {} }, obj);
 | 
	
		
			
				|  |  | +          comm.forEach(Object.keys(resources), name => {
 | 
	
		
			
				|  |  | +            addProperty(name, { value: resources[name] }, data.resources);
 | 
	
		
			
				|  |  | +          });
 | 
	
		
			
				|  |  | +          comm.forEach(Object.keys(data), name => {
 | 
	
		
			
				|  |  | +            addProperty(name, { value: data[name] }, obj.script);
 | 
	
		
			
				|  |  | +          });
 | 
	
		
			
				|  |  |            return obj;
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_deleteValue: {
 | 
	
		
			
				|  |  | -        value: function (key) {
 | 
	
		
			
				|  |  | -          var values = getValues();
 | 
	
		
			
				|  |  | +        value(key) {
 | 
	
		
			
				|  |  | +          const values = getValues();
 | 
	
		
			
				|  |  |            delete values[key];
 | 
	
		
			
				|  |  |            saveValues();
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_getValue: {
 | 
	
		
			
				|  |  | -        value: function (key, val) {
 | 
	
		
			
				|  |  | -          var values = getValues();
 | 
	
		
			
				|  |  | -          var v = values[key];
 | 
	
		
			
				|  |  | -          if (v) {
 | 
	
		
			
				|  |  | -            var type = v[0];
 | 
	
		
			
				|  |  | -            v = v.slice(1);
 | 
	
		
			
				|  |  | -            switch (type) {
 | 
	
		
			
				|  |  | -            case 'n':
 | 
	
		
			
				|  |  | -              val = Number(v);
 | 
	
		
			
				|  |  | -              break;
 | 
	
		
			
				|  |  | -            case 'b':
 | 
	
		
			
				|  |  | -              val = v == 'true';
 | 
	
		
			
				|  |  | -              break;
 | 
	
		
			
				|  |  | -            case 'o':
 | 
	
		
			
				|  |  | -              try {
 | 
	
		
			
				|  |  | -                val = JSON.parse(v);
 | 
	
		
			
				|  |  | -              } catch (e) {
 | 
	
		
			
				|  |  | -                console.warn(e);
 | 
	
		
			
				|  |  | -              }
 | 
	
		
			
				|  |  | -              break;
 | 
	
		
			
				|  |  | -            default:
 | 
	
		
			
				|  |  | -              val = v;
 | 
	
		
			
				|  |  | +        value(key, def) {
 | 
	
		
			
				|  |  | +          const values = getValues();
 | 
	
		
			
				|  |  | +          const raw = values[key];
 | 
	
		
			
				|  |  | +          if (raw) {
 | 
	
		
			
				|  |  | +            const type = raw[0];
 | 
	
		
			
				|  |  | +            const handle = dataDecoders[type] || dataDecoders[''];
 | 
	
		
			
				|  |  | +            let value = raw.slice(1);
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +              value = handle(value);
 | 
	
		
			
				|  |  | +            } catch (e) {
 | 
	
		
			
				|  |  | +              console.warn(e);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +            return value;
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  | -          return val;
 | 
	
		
			
				|  |  | +          return def;
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_listValues: {
 | 
	
		
			
				|  |  | -        value: function () {
 | 
	
		
			
				|  |  | -          return Object.getOwnPropertyNames(getValues());
 | 
	
		
			
				|  |  | +        value() {
 | 
	
		
			
				|  |  | +          return Object.keys(getValues());
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_setValue: {
 | 
	
		
			
				|  |  | -        value: function (key, val) {
 | 
	
		
			
				|  |  | -          var type = (typeof val)[0];
 | 
	
		
			
				|  |  | -          switch (type) {
 | 
	
		
			
				|  |  | -          case 'o':
 | 
	
		
			
				|  |  | -            val = type + JSON.stringify(val);
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -          default:
 | 
	
		
			
				|  |  | -            val = type + val;
 | 
	
		
			
				|  |  | -          }
 | 
	
		
			
				|  |  | -          var values = getValues();
 | 
	
		
			
				|  |  | -          values[key] = val;
 | 
	
		
			
				|  |  | +        value(key, val) {
 | 
	
		
			
				|  |  | +          const type = (typeof val)[0];
 | 
	
		
			
				|  |  | +          const handle = dataEncoders[type] || dataEncoders[''];
 | 
	
		
			
				|  |  | +          let value = val;
 | 
	
		
			
				|  |  | +          value = type + handle(value);
 | 
	
		
			
				|  |  | +          const values = getValues();
 | 
	
		
			
				|  |  | +          values[key] = value;
 | 
	
		
			
				|  |  |            saveValues();
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_getResourceText: {
 | 
	
		
			
				|  |  | -        value: function (name) {
 | 
	
		
			
				|  |  | -          for (var i in resources) if (name == i) {
 | 
	
		
			
				|  |  | -            var text = cache[resources[i]];
 | 
	
		
			
				|  |  | -            if (text) text = comm.utf8decode(window.atob(text));
 | 
	
		
			
				|  |  | +        value(name) {
 | 
	
		
			
				|  |  | +          if (name in resources) {
 | 
	
		
			
				|  |  | +            const uri = resources[name];
 | 
	
		
			
				|  |  | +            const raw = cache[uri];
 | 
	
		
			
				|  |  | +            const text = raw && comm.utf8decode(window.atob(raw));
 | 
	
		
			
				|  |  |              return text;
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_getResourceURL: {
 | 
	
		
			
				|  |  | -        value: function (name) {
 | 
	
		
			
				|  |  | -          for (var k in resources) if (name == k) {
 | 
	
		
			
				|  |  | -            var key = resources[k];
 | 
	
		
			
				|  |  | -            var url = urls[key];
 | 
	
		
			
				|  |  | -            if (!url) {
 | 
	
		
			
				|  |  | -              var cc = cache[key];
 | 
	
		
			
				|  |  | -              if (cc) {
 | 
	
		
			
				|  |  | +        value(name) {
 | 
	
		
			
				|  |  | +          if (name in resources) {
 | 
	
		
			
				|  |  | +            const key = resources[name];
 | 
	
		
			
				|  |  | +            let blobUrl = urls[key];
 | 
	
		
			
				|  |  | +            if (!blobUrl) {
 | 
	
		
			
				|  |  | +              const raw = cache[key];
 | 
	
		
			
				|  |  | +              if (raw) {
 | 
	
		
			
				|  |  |                  // Binary string is not supported by blob constructor,
 | 
	
		
			
				|  |  |                  // so we have to transform it into array buffer.
 | 
	
		
			
				|  |  | -                var bin = window.atob(cc);
 | 
	
		
			
				|  |  | -                var arr = new window.Uint8Array(bin.length);
 | 
	
		
			
				|  |  | -                for (var i = 0; i < bin.length; i ++) {
 | 
	
		
			
				|  |  | -                  arr[i] = bin.charCodeAt(i);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                var b = new Blob([arr]);
 | 
	
		
			
				|  |  | -                urls[key] = url = URL.createObjectURL(b);
 | 
	
		
			
				|  |  | +                const bin = window.atob(raw);
 | 
	
		
			
				|  |  | +                const arr = new window.Uint8Array(bin.length);
 | 
	
		
			
				|  |  | +                for (let i = 0; i < bin.length; i += 1) arr[i] = bin.charCodeAt(i);
 | 
	
		
			
				|  |  | +                const blob = new Blob([arr]);
 | 
	
		
			
				|  |  | +                blobUrl = URL.createObjectURL(blob);
 | 
	
		
			
				|  |  | +                urls[key] = blobUrl;
 | 
	
		
			
				|  |  |                } else {
 | 
	
		
			
				|  |  | -                url = key;
 | 
	
		
			
				|  |  | +                blobUrl = key;
 | 
	
		
			
				|  |  |                }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            return url;
 | 
	
		
			
				|  |  | +            return blobUrl;
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_addStyle: {
 | 
	
		
			
				|  |  | -        value: function (css) {
 | 
	
		
			
				|  |  | -          comm.post({cmd: 'AddStyle', data: css});
 | 
	
		
			
				|  |  | +        value(data) {
 | 
	
		
			
				|  |  | +          comm.post({ cmd: 'AddStyle', data });
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_log: {
 | 
	
		
			
				|  |  | -        value: function (data) {
 | 
	
		
			
				|  |  | -          console.log(data);  // eslint-disable-line no-console
 | 
	
		
			
				|  |  | +        value(data) {
 | 
	
		
			
				|  |  | +          console.log(`[Violentmonkey][${script.meta.name || 'No name'}]`, data);  // eslint-disable-line no-console
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_openInTab: {
 | 
	
		
			
				|  |  | -        value: function (url, background) {
 | 
	
		
			
				|  |  | -          comm.post({cmd: 'OpenTab', data: {url: url, active: !background}});
 | 
	
		
			
				|  |  | +        value(url, background) {
 | 
	
		
			
				|  |  | +          comm.post({ cmd: 'OpenTab', data: { url, active: !background } });
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_registerMenuCommand: {
 | 
	
		
			
				|  |  | -        value: function (cap, func, acc) {
 | 
	
		
			
				|  |  | +        value(cap, func, acc) {
 | 
	
		
			
				|  |  |            comm.command[cap] = func;
 | 
	
		
			
				|  |  | -          comm.post({cmd: 'RegisterMenu', data: [cap, acc]});
 | 
	
		
			
				|  |  | +          comm.post({ cmd: 'RegisterMenu', data: [cap, acc] });
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_xmlhttpRequest: {
 | 
	
		
			
				|  |  | -        value: function (details) {
 | 
	
		
			
				|  |  | -          if (!comm.Request) comm.initRequest();
 | 
	
		
			
				|  |  | -          return comm.Request(details);
 | 
	
		
			
				|  |  | +        value(details) {
 | 
	
		
			
				|  |  | +          return comm.getRequest(details);
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_notification: {
 | 
	
		
			
				|  |  | -        value: function (text, title, image, onclick) {
 | 
	
		
			
				|  |  | -          if (!text) {
 | 
	
		
			
				|  |  | -            throw 'Invalid parameters.';
 | 
	
		
			
				|  |  | -          }
 | 
	
		
			
				|  |  | -          var options = typeof text === 'object' ? text : {
 | 
	
		
			
				|  |  | -            text: text,
 | 
	
		
			
				|  |  | -            title: title,
 | 
	
		
			
				|  |  | -            image: image,
 | 
	
		
			
				|  |  | -            onclick: onclick,
 | 
	
		
			
				|  |  | +        value(text, title, image, onclick) {
 | 
	
		
			
				|  |  | +          const options = typeof text === 'object' ? text : {
 | 
	
		
			
				|  |  | +            text,
 | 
	
		
			
				|  |  | +            title,
 | 
	
		
			
				|  |  | +            image,
 | 
	
		
			
				|  |  | +            onclick,
 | 
	
		
			
				|  |  |            };
 | 
	
		
			
				|  |  | -          var id = comm.notif[''] = (comm.notif[''] || 0) + 1;
 | 
	
		
			
				|  |  | +          if (!options.text) {
 | 
	
		
			
				|  |  | +            throw new Error('GM_notification: `text` is required!');
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          const id = (comm.notif[''] || 0) + 1;
 | 
	
		
			
				|  |  | +          comm.notif[''] = id;
 | 
	
		
			
				|  |  |            comm.notif[id] = options;
 | 
	
		
			
				|  |  |            comm.post({
 | 
	
		
			
				|  |  |              cmd: 'Notification',
 | 
	
		
			
				|  |  |              data: {
 | 
	
		
			
				|  |  | -              id: id,
 | 
	
		
			
				|  |  | +              id,
 | 
	
		
			
				|  |  |                text: options.text,
 | 
	
		
			
				|  |  |                title: options.title,
 | 
	
		
			
				|  |  |                image: options.image,
 | 
	
	
		
			
				|  | @@ -575,255 +503,315 @@ var comm = {
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        GM_setClipboard: {
 | 
	
		
			
				|  |  | -        value: function (text, type) {
 | 
	
		
			
				|  |  | +        value(data, type) {
 | 
	
		
			
				|  |  |            comm.post({
 | 
	
		
			
				|  |  |              cmd: 'SetClipboard',
 | 
	
		
			
				|  |  | -            data: {
 | 
	
		
			
				|  |  | -              type: type,
 | 
	
		
			
				|  |  | -              data: text,
 | 
	
		
			
				|  |  | -            },
 | 
	
		
			
				|  |  | +            data: { type, data },
 | 
	
		
			
				|  |  |            });
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | -    comm.forEach(grant, function (name) {
 | 
	
		
			
				|  |  | -      var prop = gm_funcs[name];
 | 
	
		
			
				|  |  | -      prop && addProperty(name, prop, gm);
 | 
	
		
			
				|  |  | +    comm.forEach(grant, name => {
 | 
	
		
			
				|  |  | +      const prop = gmFunctions[name];
 | 
	
		
			
				|  |  | +      if (prop) addProperty(name, prop, gm);
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |      return gm;
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | -  loadScript: function (data) {
 | 
	
		
			
				|  |  | -    function buildCode(script) {
 | 
	
		
			
				|  |  | -      var require = script.meta.require || [];
 | 
	
		
			
				|  |  | -      var wrapper = comm.wrapGM(script, data.cache);
 | 
	
		
			
				|  |  | -      // Must use Object.getOwnPropertyNames to list unenumerable properties
 | 
	
		
			
				|  |  | -      var wrapperKeys = Object.getOwnPropertyNames(wrapper);
 | 
	
		
			
				|  |  | -      var code = [
 | 
	
		
			
				|  |  | -        comm.map(wrapperKeys, function (name) {
 | 
	
		
			
				|  |  | -          return 'this["' + name + '"]=' + name;
 | 
	
		
			
				|  |  | -        }).join(';') + ';with(this)!function(){',
 | 
	
		
			
				|  |  | -      ];
 | 
	
		
			
				|  |  | -      comm.forEach(require, function (key) {
 | 
	
		
			
				|  |  | -        var script = data.require[key];
 | 
	
		
			
				|  |  | -        if (script) {
 | 
	
		
			
				|  |  | -          code.push(script);
 | 
	
		
			
				|  |  | -          // Add `;` to a new line in case script ends with comment lines
 | 
	
		
			
				|  |  | -          code.push(';');
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -      });
 | 
	
		
			
				|  |  | -      // wrap code to make 'use strict' work
 | 
	
		
			
				|  |  | -      code.push('!function(){' + script.code + '\n}.call(this)');
 | 
	
		
			
				|  |  | -      code.push('}.call(this);');
 | 
	
		
			
				|  |  | -      code = code.join('\n');
 | 
	
		
			
				|  |  | -      var name = script.custom.name || script.meta.name || script.id;
 | 
	
		
			
				|  |  | -      var args = comm.map(wrapperKeys, function (key) {return wrapper[key];});
 | 
	
		
			
				|  |  | -      var thisObj = wrapper.window || wrapper;
 | 
	
		
			
				|  |  | -      if (comm.injectable) {
 | 
	
		
			
				|  |  | -        // normal injection
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -          var func = Function.apply(null, wrapperKeys.concat([code]));
 | 
	
		
			
				|  |  | -        } catch (e) {
 | 
	
		
			
				|  |  | -          console.error('Syntax error in script: ' + name + '\n' + e.message);
 | 
	
		
			
				|  |  | -          return;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        comm.runCode(name, func, args, thisObj);
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        // advanced injection
 | 
	
		
			
				|  |  | -        var id = comm.getUniqId();
 | 
	
		
			
				|  |  | -        comm.ainject[id] = [name, args, thisObj];
 | 
	
		
			
				|  |  | -        comm.post({cmd: 'Inject', data: [id, wrapperKeys, code]});
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | +    function getValues() {
 | 
	
		
			
				|  |  | +      return comm.values[script.uri];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    function run(list) {
 | 
	
		
			
				|  |  | -      while (list.length) buildCode(list.shift());
 | 
	
		
			
				|  |  | +    function propertyToString() {
 | 
	
		
			
				|  |  | +      return '[Violentmonkey property]';
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    function addProperty(name, prop, obj) {
 | 
	
		
			
				|  |  | +      if ('value' in prop) prop.writable = false;
 | 
	
		
			
				|  |  | +      prop.configurable = false;
 | 
	
		
			
				|  |  | +      Object.defineProperty(obj, name, prop);
 | 
	
		
			
				|  |  | +      if (typeof obj[name] === 'function') obj[name].toString = propertyToString;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    function saveValues() {
 | 
	
		
			
				|  |  | +      comm.post({
 | 
	
		
			
				|  |  | +        cmd: 'SetValue',
 | 
	
		
			
				|  |  | +        data: {
 | 
	
		
			
				|  |  | +          uri: script.uri,
 | 
	
		
			
				|  |  | +          values: getValues(),
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    var comm = this;
 | 
	
		
			
				|  |  | -    var start = [];
 | 
	
		
			
				|  |  | -    var idle = [];
 | 
	
		
			
				|  |  | -    var end = [];
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function onLoadScripts(data) {
 | 
	
		
			
				|  |  | +    const comm = this;
 | 
	
		
			
				|  |  | +    const start = [];
 | 
	
		
			
				|  |  | +    const idle = [];
 | 
	
		
			
				|  |  | +    const end = [];
 | 
	
		
			
				|  |  |      comm.command = {};
 | 
	
		
			
				|  |  |      comm.notif = {};
 | 
	
		
			
				|  |  |      comm.ainject = {};
 | 
	
		
			
				|  |  |      comm.version = data.version;
 | 
	
		
			
				|  |  |      comm.values = {};
 | 
	
		
			
				|  |  |      // reset load and checkLoad
 | 
	
		
			
				|  |  | -    comm.load = function () {
 | 
	
		
			
				|  |  | +    comm.load = () => {
 | 
	
		
			
				|  |  |        run(end);
 | 
	
		
			
				|  |  |        setTimeout(run, 0, idle);
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | -    comm.checkLoad = function () {
 | 
	
		
			
				|  |  | -      if (!comm.state && comm.includes(['interactive', 'complete'], document.readyState))
 | 
	
		
			
				|  |  | -        comm.state = 1;
 | 
	
		
			
				|  |  | +    comm.checkLoad = () => {
 | 
	
		
			
				|  |  | +      if (!comm.state && comm.includes(['interactive', 'complete'], document.readyState)) comm.state = 1;
 | 
	
		
			
				|  |  |        if (comm.state) comm.load();
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | -    var listMap = {
 | 
	
		
			
				|  |  | +    const listMap = {
 | 
	
		
			
				|  |  |        'document-start': start,
 | 
	
		
			
				|  |  |        'document-idle': idle,
 | 
	
		
			
				|  |  |        'document-end': end,
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | -    comm.forEach(data.scripts, function (script) {
 | 
	
		
			
				|  |  | +    comm.forEach(data.scripts, script => {
 | 
	
		
			
				|  |  |        comm.values[script.uri] = data.values[script.uri] || {};
 | 
	
		
			
				|  |  |        if (script && script.enabled) {
 | 
	
		
			
				|  |  | -        var list = listMap[script.custom['run-at'] || script.meta['run-at']] || end;
 | 
	
		
			
				|  |  | +        const list = listMap[script.custom['run-at'] || script.meta['run-at']] || end;
 | 
	
		
			
				|  |  |          list.push(script);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |      run(start);
 | 
	
		
			
				|  |  |      comm.checkLoad();
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -var menus = [];
 | 
	
		
			
				|  |  | -var ids = [];
 | 
	
		
			
				|  |  | -function injectScript(data) {
 | 
	
		
			
				|  |  | -  // data: [id, wrapperKeys, code]
 | 
	
		
			
				|  |  | -  var func = function (id, did, cb) {
 | 
	
		
			
				|  |  | -    Object.defineProperty(window, 'VM_' + id, {
 | 
	
		
			
				|  |  | -      value: cb,
 | 
	
		
			
				|  |  | -      configurable: true,
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -    var e = new CustomEvent(did, {detail: {cmd: 'Injected', data: id}});
 | 
	
		
			
				|  |  | -    document.dispatchEvent(e);
 | 
	
		
			
				|  |  | -  };
 | 
	
		
			
				|  |  | -  inject('!' + func.toString() + '(' + JSON.stringify(data[0]) + ',' + JSON.stringify(comm.did) + ',function(' + data[1].join(',') + '){' + data[2] + '})');
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function handleC(req) {
 | 
	
		
			
				|  |  | -  if (!req) {
 | 
	
		
			
				|  |  | -    console.error('[Violentmonkey] Invalid data! There might be unsupported data format.');
 | 
	
		
			
				|  |  | -    return;
 | 
	
		
			
				|  |  | +    function buildCode(script) {
 | 
	
		
			
				|  |  | +      const requireKeys = script.meta.require || [];
 | 
	
		
			
				|  |  | +      const wrapper = comm.wrapGM(script, data.cache);
 | 
	
		
			
				|  |  | +      // Must use Object.getOwnPropertyNames to list unenumerable properties
 | 
	
		
			
				|  |  | +      const wrapperKeys = Object.getOwnPropertyNames(wrapper);
 | 
	
		
			
				|  |  | +      const wrapperInit = comm.map(wrapperKeys, name => `this["${name}"]=${name}`).join(';');
 | 
	
		
			
				|  |  | +      const codeSlices = [`${wrapperInit};with(this)!function(){`];
 | 
	
		
			
				|  |  | +      comm.forEach(requireKeys, key => {
 | 
	
		
			
				|  |  | +        const requireCode = data.require[key];
 | 
	
		
			
				|  |  | +        if (requireCode) {
 | 
	
		
			
				|  |  | +          codeSlices.push(requireCode);
 | 
	
		
			
				|  |  | +          // Add `;` to a new line in case script ends with comment lines
 | 
	
		
			
				|  |  | +          codeSlices.push(';');
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +      // wrap code to make 'use strict' work
 | 
	
		
			
				|  |  | +      codeSlices.push(`!function(){${script.code$}\n}.call(this)`);
 | 
	
		
			
				|  |  | +      codeSlices.push('}.call(this);');
 | 
	
		
			
				|  |  | +      const code = codeSlices.join('\n');
 | 
	
		
			
				|  |  | +      const name = script.custom.name || script.meta.name || script.id;
 | 
	
		
			
				|  |  | +      const args = comm.map(wrapperKeys, key => wrapper[key]);
 | 
	
		
			
				|  |  | +      const thisObj = wrapper.window || wrapper;
 | 
	
		
			
				|  |  | +      const id = comm.getUniqId();
 | 
	
		
			
				|  |  | +      comm.ainject[id] = [name, args, thisObj];
 | 
	
		
			
				|  |  | +      comm.post({ cmd: 'Inject', data: [id, wrapperKeys, code] });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    function run(list) {
 | 
	
		
			
				|  |  | +      while (list.length) buildCode(list.shift());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  var maps = {
 | 
	
		
			
				|  |  | -    GetRequestId: getRequestId,
 | 
	
		
			
				|  |  | -    HttpRequest: httpRequest,
 | 
	
		
			
				|  |  | -    AbortRequest: abortRequest,
 | 
	
		
			
				|  |  | -    Inject: injectScript,
 | 
	
		
			
				|  |  | -    OpenTab: function (data) {
 | 
	
		
			
				|  |  | -      sendMessage({cmd: 'OpenTab', data: data});
 | 
	
		
			
				|  |  | +  // Communicator
 | 
	
		
			
				|  |  | +  const comm = {
 | 
	
		
			
				|  |  | +    vmid: `VM_${getUniqId()}`,
 | 
	
		
			
				|  |  | +    state: 0,
 | 
	
		
			
				|  |  | +    utf8decode,
 | 
	
		
			
				|  |  | +    getUniqId,
 | 
	
		
			
				|  |  | +    props: Object.getOwnPropertyNames(window),
 | 
	
		
			
				|  |  | +    noop() {},
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Array functions
 | 
	
		
			
				|  |  | +    // Notice: avoid using prototype functions since they may be changed by page scripts
 | 
	
		
			
				|  |  | +    forEach(arr, func) {
 | 
	
		
			
				|  |  | +      const length = arr && arr.length;
 | 
	
		
			
				|  |  | +      for (let i = 0; i < length; i += 1) func(arr[i], i, arr);
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | -    SetValue: function (data) {
 | 
	
		
			
				|  |  | -      sendMessage({cmd: 'SetValue', data: data});
 | 
	
		
			
				|  |  | +    includes(arr, item) {
 | 
	
		
			
				|  |  | +      const length = arr && arr.length;
 | 
	
		
			
				|  |  | +      for (let i = 0; i < length; i += 1) {
 | 
	
		
			
				|  |  | +        if (arr[i] === item) return true;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | -    RegisterMenu: function (data) {
 | 
	
		
			
				|  |  | -      if (window.top === window) menus.push(data);
 | 
	
		
			
				|  |  | -      getPopup();
 | 
	
		
			
				|  |  | +    map(arr, func) {
 | 
	
		
			
				|  |  | +      const res = [];
 | 
	
		
			
				|  |  | +      this.forEach(arr, (item, i) => {
 | 
	
		
			
				|  |  | +        res.push(func(item, i, arr));
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +      return res;
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | -    AddStyle: function (css) {
 | 
	
		
			
				|  |  | -      if (document.head) {
 | 
	
		
			
				|  |  | -        var style = document.createElement('style');
 | 
	
		
			
				|  |  | -        style.innerHTML = css;
 | 
	
		
			
				|  |  | -        document.head.appendChild(style);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    init: initHandler,
 | 
	
		
			
				|  |  | +    post: postData,
 | 
	
		
			
				|  |  | +    runCode(name, func, args, thisObj) {
 | 
	
		
			
				|  |  | +      try {
 | 
	
		
			
				|  |  | +        func.apply(thisObj, args);
 | 
	
		
			
				|  |  | +      } catch (e) {
 | 
	
		
			
				|  |  | +        let msg = `Error running script: ${name}\n${e}`;
 | 
	
		
			
				|  |  | +        if (e.message) msg = `${msg}\n${e.message}`;
 | 
	
		
			
				|  |  | +        console.error(msg);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | -    Notification: onNotificationCreate,
 | 
	
		
			
				|  |  | -    SetClipboard: function (data) {
 | 
	
		
			
				|  |  | -      sendMessage({cmd: 'SetClipboard', data: data});
 | 
	
		
			
				|  |  | -    },
 | 
	
		
			
				|  |  | +    getRequest,
 | 
	
		
			
				|  |  | +    getWrapper,
 | 
	
		
			
				|  |  | +    wrapGM,
 | 
	
		
			
				|  |  | +    onLoadScripts,
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  | -  var func = maps[req.cmd];
 | 
	
		
			
				|  |  | -  if (func) func(req.data);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -var notifications = {};
 | 
	
		
			
				|  |  | -function onNotificationCreate(options) {
 | 
	
		
			
				|  |  | -  sendMessage({cmd: 'Notification', data: options})
 | 
	
		
			
				|  |  | -  .then(function (nid) {
 | 
	
		
			
				|  |  | -    notifications[nid] = options.id;
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function onNotificationClick(nid) {
 | 
	
		
			
				|  |  | -  var id = notifications[nid];
 | 
	
		
			
				|  |  | -  id && comm.post({cmd: 'NotificationClicked', data: id});
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function onNotificationClose(nid) {
 | 
	
		
			
				|  |  | -  var id = notifications[nid];
 | 
	
		
			
				|  |  | -  if (id) {
 | 
	
		
			
				|  |  | -    comm.post({cmd: 'NotificationClosed', data: id});
 | 
	
		
			
				|  |  | -    delete notifications[nid];
 | 
	
		
			
				|  |  | +  const ids = [];
 | 
	
		
			
				|  |  | +  const menus = [];
 | 
	
		
			
				|  |  | +  function injectScript(data) {
 | 
	
		
			
				|  |  | +    // data: [id, wrapperKeys, code]
 | 
	
		
			
				|  |  | +    const func = (scriptId, destId, cb) => {
 | 
	
		
			
				|  |  | +      Object.defineProperty(window, `VM_${scriptId}`, {
 | 
	
		
			
				|  |  | +        value: cb,
 | 
	
		
			
				|  |  | +        configurable: true,
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +      const e = new CustomEvent(destId, { detail: { cmd: 'Injected', data: scriptId } });
 | 
	
		
			
				|  |  | +      document.dispatchEvent(e);
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    inject(`!${func.toString()}(${JSON.stringify(data[0])},${JSON.stringify(comm.did)},function(${data[1].join(',')}){${data[2]}})`);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function handleContent(req) {
 | 
	
		
			
				|  |  | +    if (!req) {
 | 
	
		
			
				|  |  | +      console.error('[Violentmonkey] Invalid data! There might be unsupported data format.');
 | 
	
		
			
				|  |  | +      return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    const handlers = {
 | 
	
		
			
				|  |  | +      GetRequestId: getRequestId,
 | 
	
		
			
				|  |  | +      HttpRequest: httpRequest,
 | 
	
		
			
				|  |  | +      AbortRequest: abortRequest,
 | 
	
		
			
				|  |  | +      Inject: injectScript,
 | 
	
		
			
				|  |  | +      OpenTab(data) {
 | 
	
		
			
				|  |  | +        sendMessage({ cmd: 'OpenTab', data });
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      SetValue(data) {
 | 
	
		
			
				|  |  | +        sendMessage({ cmd: 'SetValue', data });
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      RegisterMenu(data) {
 | 
	
		
			
				|  |  | +        if (window.top === window) menus.push(data);
 | 
	
		
			
				|  |  | +        getPopup();
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      AddStyle(css) {
 | 
	
		
			
				|  |  | +        if (document.head) {
 | 
	
		
			
				|  |  | +          const style = document.createElement('style');
 | 
	
		
			
				|  |  | +          style.innerHTML = css;
 | 
	
		
			
				|  |  | +          document.head.appendChild(style);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      Notification: onNotificationCreate,
 | 
	
		
			
				|  |  | +      SetClipboard(data) {
 | 
	
		
			
				|  |  | +        sendMessage({ cmd: 'SetClipboard', data });
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    const handle = handlers[req.cmd];
 | 
	
		
			
				|  |  | +    if (handle) handle(req.data);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function getPopup() {
 | 
	
		
			
				|  |  | +    // XXX: only scripts run in top level window are counted
 | 
	
		
			
				|  |  | +    if (top === window) {
 | 
	
		
			
				|  |  | +      sendMessage({
 | 
	
		
			
				|  |  | +        cmd: 'SetPopup',
 | 
	
		
			
				|  |  | +        data: { ids, menus },
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  | +      .catch(comm.noop);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Messages
 | 
	
		
			
				|  |  | -browser.runtime.onMessage.addListener(function (req, src) {
 | 
	
		
			
				|  |  | -  var handlers = {
 | 
	
		
			
				|  |  | -    Command: function (data) {
 | 
	
		
			
				|  |  | -      comm.post({cmd: 'Command', data: data});
 | 
	
		
			
				|  |  | -    },
 | 
	
		
			
				|  |  | -    GetPopup: getPopup,
 | 
	
		
			
				|  |  | -    GetBadge: getBadge,
 | 
	
		
			
				|  |  | -    HttpRequested: httpRequested,
 | 
	
		
			
				|  |  | -    UpdateValues: function (data) {
 | 
	
		
			
				|  |  | -      comm.post({cmd: 'UpdateValues', data: data});
 | 
	
		
			
				|  |  | -    },
 | 
	
		
			
				|  |  | -    NotificationClick: onNotificationClick,
 | 
	
		
			
				|  |  | -    NotificationClose: onNotificationClose,
 | 
	
		
			
				|  |  | -  };
 | 
	
		
			
				|  |  | -  var func = handlers[req.cmd];
 | 
	
		
			
				|  |  | -  if (func) func(req.data, src);
 | 
	
		
			
				|  |  | -});
 | 
	
		
			
				|  |  | +  const notifications = {};
 | 
	
		
			
				|  |  | +  function onNotificationCreate(options) {
 | 
	
		
			
				|  |  | +    sendMessage({ cmd: 'Notification', data: options })
 | 
	
		
			
				|  |  | +    .then(nid => { notifications[nid] = options.id; });
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function onNotificationClick(nid) {
 | 
	
		
			
				|  |  | +    const id = notifications[nid];
 | 
	
		
			
				|  |  | +    if (id) comm.post({ cmd: 'NotificationClicked', data: id });
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function onNotificationClose(nid) {
 | 
	
		
			
				|  |  | +    const id = notifications[nid];
 | 
	
		
			
				|  |  | +    if (id) {
 | 
	
		
			
				|  |  | +      comm.post({ cmd: 'NotificationClosed', data: id });
 | 
	
		
			
				|  |  | +      delete notifications[nid];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Requests
 | 
	
		
			
				|  |  | -var requests = {};
 | 
	
		
			
				|  |  | -function getRequestId() {
 | 
	
		
			
				|  |  | -  sendMessage({cmd: 'GetRequestId'}).then(function (id) {
 | 
	
		
			
				|  |  | -    requests[id] = 1;
 | 
	
		
			
				|  |  | -    comm.post({cmd: 'GotRequestId', data: id});
 | 
	
		
			
				|  |  | +  // Messages
 | 
	
		
			
				|  |  | +  browser.runtime.onMessage.addListener((req, src) => {
 | 
	
		
			
				|  |  | +    const handlers = {
 | 
	
		
			
				|  |  | +      Command(data) {
 | 
	
		
			
				|  |  | +        comm.post({ cmd: 'Command', data });
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      GetPopup: getPopup,
 | 
	
		
			
				|  |  | +      GetBadge: getBadge,
 | 
	
		
			
				|  |  | +      HttpRequested: httpRequested,
 | 
	
		
			
				|  |  | +      UpdateValues(data) {
 | 
	
		
			
				|  |  | +        comm.post({ cmd: 'UpdateValues', data });
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      NotificationClick: onNotificationClick,
 | 
	
		
			
				|  |  | +      NotificationClose: onNotificationClose,
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    const handle = handlers[req.cmd];
 | 
	
		
			
				|  |  | +    if (handle) handle(req.data, src);
 | 
	
		
			
				|  |  |    });
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function httpRequest(details) {
 | 
	
		
			
				|  |  | -  sendMessage({cmd: 'HttpRequest', data: details});
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function httpRequested(data) {
 | 
	
		
			
				|  |  | -  if (requests[data.id]) {
 | 
	
		
			
				|  |  | -    if (data.type == 'loadend') delete requests[data.id];
 | 
	
		
			
				|  |  | -    comm.post({cmd: 'HttpRequested', data: data});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Requests
 | 
	
		
			
				|  |  | +  const requests = {};
 | 
	
		
			
				|  |  | +  function getRequestId() {
 | 
	
		
			
				|  |  | +    sendMessage({ cmd: 'GetRequestId' })
 | 
	
		
			
				|  |  | +    .then(id => {
 | 
	
		
			
				|  |  | +      requests[id] = 1;
 | 
	
		
			
				|  |  | +      comm.post({ cmd: 'GotRequestId', data: id });
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function httpRequest(details) {
 | 
	
		
			
				|  |  | +    sendMessage({ cmd: 'HttpRequest', data: details });
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function httpRequested(data) {
 | 
	
		
			
				|  |  | +    if (requests[data.id]) {
 | 
	
		
			
				|  |  | +      if (data.type === 'loadend') delete requests[data.id];
 | 
	
		
			
				|  |  | +      comm.post({ cmd: 'HttpRequested', data });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function abortRequest(id) {
 | 
	
		
			
				|  |  | +    sendMessage({ cmd: 'AbortRequest', data: id });
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function abortRequest(id) {
 | 
	
		
			
				|  |  | -  sendMessage({cmd: 'AbortRequest', data: id});
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -function objEncode(obj) {
 | 
	
		
			
				|  |  | -  var list = [];
 | 
	
		
			
				|  |  | -  for (var i in obj) {
 | 
	
		
			
				|  |  | -    if (!obj.hasOwnProperty(i)) continue;
 | 
	
		
			
				|  |  | -    if (typeof obj[i] == 'function') {
 | 
	
		
			
				|  |  | -      list.push(i + ':' + obj[i].toString());
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      list.push(i + ':' + JSON.stringify(obj[i]));
 | 
	
		
			
				|  |  | +  function objEncode(obj) {
 | 
	
		
			
				|  |  | +    const list = Object.keys(obj).map(name => {
 | 
	
		
			
				|  |  | +      const value = obj[name];
 | 
	
		
			
				|  |  | +      const jsonKey = JSON.stringify(name);
 | 
	
		
			
				|  |  | +      if (typeof value === 'function') return `${jsonKey}:${value.toString()}`;
 | 
	
		
			
				|  |  | +      return `${jsonKey}:${JSON.stringify(value)}`;
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    return `{${list.join(',')}}`;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  function inject(code) {
 | 
	
		
			
				|  |  | +    const script = document.createElement('script');
 | 
	
		
			
				|  |  | +    const doc = document.body || document.documentElement;
 | 
	
		
			
				|  |  | +    script.innerHTML = code;
 | 
	
		
			
				|  |  | +    doc.appendChild(script);
 | 
	
		
			
				|  |  | +    try {
 | 
	
		
			
				|  |  | +      doc.removeChild(script);
 | 
	
		
			
				|  |  | +    } catch (e) {
 | 
	
		
			
				|  |  | +      // ignore if body is changed and script is detached
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return '{' + list.join(',') + '}';
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function inject(code) {
 | 
	
		
			
				|  |  | -  var script = document.createElement('script');
 | 
	
		
			
				|  |  | -  var doc = document.body || document.documentElement;
 | 
	
		
			
				|  |  | -  script.innerHTML = code;
 | 
	
		
			
				|  |  | -  doc.appendChild(script);
 | 
	
		
			
				|  |  | -  try {
 | 
	
		
			
				|  |  | -    doc.removeChild(script);
 | 
	
		
			
				|  |  | -  } catch (e) {
 | 
	
		
			
				|  |  | -    // ignore if body is changed and script is detached
 | 
	
		
			
				|  |  | +  function loadScripts(data) {
 | 
	
		
			
				|  |  | +    comm.forEach(data.scripts, script => {
 | 
	
		
			
				|  |  | +      ids.push(script.id);
 | 
	
		
			
				|  |  | +      if (script.enabled) badge.number += 1;
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    comm.post({ cmd: 'LoadScripts', data });
 | 
	
		
			
				|  |  | +    badge.ready = true;
 | 
	
		
			
				|  |  | +    getPopup();
 | 
	
		
			
				|  |  | +    setBadge();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function loadScript(data) {
 | 
	
		
			
				|  |  | -  forEach(data.scripts, function (script) {
 | 
	
		
			
				|  |  | -    ids.push(script.id);
 | 
	
		
			
				|  |  | -    if (script.enabled) badge.number ++;
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  comm.post({cmd: 'LoadScript', data: data});
 | 
	
		
			
				|  |  | -  badge.ready = true;
 | 
	
		
			
				|  |  | -  getPopup();
 | 
	
		
			
				|  |  | -  setBadge();
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function initCommunicator() {
 | 
	
		
			
				|  |  | -  var C = 'C';
 | 
	
		
			
				|  |  | -  var R = 'R';
 | 
	
		
			
				|  |  | -  inject(
 | 
	
		
			
				|  |  | -    '!function(c,R,C){c.init(R,C);document.addEventListener("DOMContentLoaded",function(e){c.state=1;c.load();},false);c.checkLoad();}(' +
 | 
	
		
			
				|  |  | -    objEncode(comm) + ',"' + R + '","' + C + '")'
 | 
	
		
			
				|  |  | -  );
 | 
	
		
			
				|  |  | -  comm.handleC = handleC;
 | 
	
		
			
				|  |  | -  comm.init(C, R);
 | 
	
		
			
				|  |  | -  sendMessage({cmd: 'GetInjected', data: location.href}).then(loadScript);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -initCommunicator();
 | 
	
		
			
				|  |  | +  function initCommunicator() {
 | 
	
		
			
				|  |  | +    const contentId = getUniqId();
 | 
	
		
			
				|  |  | +    const webId = getUniqId();
 | 
	
		
			
				|  |  | +    comm[`handle_${webId}`] = handleWeb;
 | 
	
		
			
				|  |  | +    const initWeb = (comm, webId, contentId) => { // eslint-disable-line no-shadow
 | 
	
		
			
				|  |  | +      comm.init(webId, contentId);
 | 
	
		
			
				|  |  | +      document.addEventListener('DOMContentLoaded', () => {
 | 
	
		
			
				|  |  | +        comm.state = 1;
 | 
	
		
			
				|  |  | +        comm.load();
 | 
	
		
			
				|  |  | +      }, false);
 | 
	
		
			
				|  |  | +      comm.checkLoad();
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    inject(`(${initWeb.toString()})(${objEncode(comm)},${JSON.stringify(webId)},${JSON.stringify(contentId)})`);
 | 
	
		
			
				|  |  | +    comm[`handle_${contentId}`] = handleContent;
 | 
	
		
			
				|  |  | +    comm.init(contentId, webId);
 | 
	
		
			
				|  |  | +    sendMessage({ cmd: 'GetInjected', data: location.href }).then(loadScripts);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  initCommunicator();
 | 
	
		
			
				|  |  | +}());
 |