Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
code / usr / share / code / resources / electron.asar
Size: Mime:
{"files":{"browser":{"files":{"api":{"files":{"app.js":{"size":3182,"offset":"0"},"auto-updater":{"files":{"auto-updater-native.js":{"size":210,"offset":"3476"},"auto-updater-win.js":{"size":1716,"offset":"3686"},"squirrel-update-win.js":{"size":2734,"offset":"5402"}}},"auto-updater.js":{"size":294,"offset":"3182"},"browser-window.js":{"size":8963,"offset":"8136"},"content-tracing.js":{"size":56,"offset":"17099"},"dialog.js":{"size":5820,"offset":"17155"},"exports":{"files":{"electron.js":{"size":2113,"offset":"22975"}}},"global-shortcut.js":{"size":124,"offset":"25088"},"ipc-main.js":{"size":89,"offset":"25212"},"ipc.js":{"size":244,"offset":"25301"},"menu-item.js":{"size":3479,"offset":"25545"},"menu.js":{"size":8647,"offset":"29024"},"navigation-controller.js":{"size":5486,"offset":"37671"},"power-monitor.js":{"size":215,"offset":"43157"},"power-save-blocker.js":{"size":135,"offset":"43372"},"protocol.js":{"size":1061,"offset":"43507"},"screen.js":{"size":184,"offset":"44568"},"session.js":{"size":888,"offset":"44752"},"tray.js":{"size":717,"offset":"45640"},"web-contents.js":{"size":6735,"offset":"46357"}}},"chrome-extension.js":{"size":4517,"offset":"53092"},"desktop-capturer.js":{"size":2637,"offset":"57609"},"guest-view-manager.js":{"size":6896,"offset":"60246"},"guest-window-manager.js":{"size":4542,"offset":"67142"},"init.js":{"size":5177,"offset":"71684"},"objects-registry.js":{"size":2398,"offset":"76861"},"rpc-server.js":{"size":11835,"offset":"79259"}}},"common":{"files":{"api":{"files":{"callbacks-registry.js":{"size":1523,"offset":"91094"},"clipboard.js":{"size":251,"offset":"92617"},"crash-reporter.js":{"size":2892,"offset":"92868"},"deprecate.js":{"size":2756,"offset":"95760"},"deprecations.js":{"size":231,"offset":"98516"},"exports":{"files":{"electron.js":{"size":1544,"offset":"98747"}}},"native-image.js":{"size":222,"offset":"100291"},"shell.js":{"size":46,"offset":"100513"}}},"init.js":{"size":1652,"offset":"100559"},"reset-search-paths.js":{"size":1047,"offset":"102211"}}},"renderer":{"files":{"api":{"files":{"desktop-capturer.js":{"size":1445,"offset":"103258"},"exports":{"files":{"electron.js":{"size":767,"offset":"104703"}}},"ipc-renderer.js":{"size":508,"offset":"105470"},"ipc.js":{"size":772,"offset":"105978"},"remote.js":{"size":9588,"offset":"106750"},"screen.js":{"size":51,"offset":"116338"},"web-frame.js":{"size":667,"offset":"116389"}}},"chrome-api.js":{"size":291,"offset":"117056"},"init.js":{"size":4314,"offset":"117347"},"inspector.js":{"size":2265,"offset":"121661"},"override.js":{"size":7360,"offset":"123926"},"web-view":{"files":{"guest-view-internal.js":{"size":4041,"offset":"131286"},"web-view-attributes.js":{"size":9962,"offset":"135327"},"web-view-constants.js":{"size":1124,"offset":"145289"},"web-view.js":{"size":16035,"offset":"146413"}}}}}}}'use strict'

const deprecate = require('electron').deprecate
const session = require('electron').session
const Menu = require('electron').Menu
const EventEmitter = require('events').EventEmitter

const bindings = process.atomBinding('app')
const downloadItemBindings = process.atomBinding('download_item')
const app = bindings.app

Object.setPrototypeOf(app, EventEmitter.prototype)

app.setApplicationMenu = function (menu) {
  return Menu.setApplicationMenu(menu)
}

app.getApplicationMenu = function () {
  return Menu.getApplicationMenu()
}

app.commandLine = {
  appendSwitch: bindings.appendSwitch,
  appendArgument: bindings.appendArgument
}

if (process.platform === 'darwin') {
  app.dock = {
    bounce: function (type) {
      if (type == null) {
        type = 'informational'
      }
      return bindings.dockBounce(type)
    },
    cancelBounce: bindings.dockCancelBounce,
    setBadge: bindings.dockSetBadgeText,
    getBadge: bindings.dockGetBadgeText,
    hide: bindings.dockHide,
    show: bindings.dockShow,
    setMenu: bindings.dockSetMenu,
    setIcon: bindings.dockSetIcon
  }
}

var appPath = null

app.setAppPath = function (path) {
  appPath = path
}

app.getAppPath = function () {
  return appPath
}

// Routes the events to webContents.
var ref1 = ['login', 'certificate-error', 'select-client-certificate']
var fn = function (name) {
  return app.on(name, function (event, webContents, ...args) {
    return webContents.emit.apply(webContents, [name, event].concat(args))
  })
}
var i, len
for (i = 0, len = ref1.length; i < len; i++) {
  fn(ref1[i])
}

// Deprecated.

app.getHomeDir = deprecate('app.getHomeDir', 'app.getPath', function () {
  return this.getPath('home')
})

app.getDataPath = deprecate('app.getDataPath', 'app.getPath', function () {
  return this.getPath('userData')
})

app.setDataPath = deprecate('app.setDataPath', 'app.setPath', function (path) {
  return this.setPath('userData', path)
})

app.resolveProxy = deprecate('app.resolveProxy', 'session.defaultSession.resolveProxy', function (url, callback) {
  return session.defaultSession.resolveProxy(url, callback)
})

deprecate.rename(app, 'terminate', 'quit')

deprecate.event(app, 'finish-launching', 'ready', function () {
  // give default app a chance to setup default menu.
  setImmediate(() => {
    this.emit('finish-launching')
  })
})

deprecate.event(app, 'activate-with-no-open-windows', 'activate', function (event, hasVisibleWindows) {
  if (!hasVisibleWindows) {
    return this.emit('activate-with-no-open-windows', event)
  }
})

deprecate.event(app, 'select-certificate', 'select-client-certificate')

// Wrappers for native classes.
var wrapDownloadItem = function (downloadItem) {
  // downloadItem is an EventEmitter.
  Object.setPrototypeOf(downloadItem, EventEmitter.prototype)

  // Deprecated.
  deprecate.property(downloadItem, 'url', 'getURL')
  deprecate.property(downloadItem, 'filename', 'getFilename')
  deprecate.property(downloadItem, 'mimeType', 'getMimeType')
  return deprecate.rename(downloadItem, 'getUrl', 'getURL')
}

downloadItemBindings._setWrapDownloadItem(wrapDownloadItem)

// Only one App object pemitted.
module.exports = app
const deprecate = require('electron').deprecate
const autoUpdater = process.platform === 'win32' ? require('./auto-updater/auto-updater-win') : require('./auto-updater/auto-updater-native')

// Deprecated.
deprecate.rename(autoUpdater, 'setFeedUrl', 'setFeedURL')

module.exports = autoUpdater
const EventEmitter = require('events').EventEmitter
const autoUpdater = process.atomBinding('auto_updater').autoUpdater

Object.setPrototypeOf(autoUpdater, EventEmitter.prototype)

module.exports = autoUpdater
'use strict'

const app = require('electron').app
const EventEmitter = require('events').EventEmitter
const squirrelUpdate = require('./squirrel-update-win')
const util = require('util')

function AutoUpdater () {
  EventEmitter.call(this)
}

util.inherits(AutoUpdater, EventEmitter)

AutoUpdater.prototype.quitAndInstall = function () {
  squirrelUpdate.processStart()
  return app.quit()
}

AutoUpdater.prototype.setFeedURL = function (updateURL) {
  this.updateURL = updateURL
}

AutoUpdater.prototype.checkForUpdates = function () {
  if (!this.updateURL) {
    return this.emitError('Update URL is not set')
  }
  if (!squirrelUpdate.supported()) {
    return this.emitError('Can not find Squirrel')
  }
  this.emit('checking-for-update')
  squirrelUpdate.download(this.updateURL, (error, update) => {
    if (error != null) {
      return this.emitError(error)
    }
    if (update == null) {
      return this.emit('update-not-available')
    }
    this.emit('update-available')
    squirrelUpdate.update(this.updateURL, (error) => {
      var date, releaseNotes, version
      if (error != null) {
        return this.emitError(error)
      }
      releaseNotes = update.releaseNotes
      version = update.version

      // Following information is not available on Windows, so fake them.
      date = new Date()
      this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => {
        this.quitAndInstall()
      })
    })
  })
}

// Private: Emit both error object and message, this is to keep compatibility
// with Old APIs.
AutoUpdater.prototype.emitError = function (message) {
  return this.emit('error', new Error(message), message)
}

module.exports = new AutoUpdater()
const fs = require('fs')
const path = require('path')
const spawn = require('child_process').spawn

// i.e. my-app/app-0.1.13/
const appFolder = path.dirname(process.execPath)

// i.e. my-app/Update.exe
const updateExe = path.resolve(appFolder, '..', 'Update.exe')

const exeName = path.basename(process.execPath)

// Spawn a command and invoke the callback when it completes with an error
// and the output from standard out.
var spawnUpdate = function (args, detached, callback) {
  var error, errorEmitted, spawnedProcess, stderr, stdout
  try {
    spawnedProcess = spawn(updateExe, args, {
      detached: detached
    })
  } catch (error1) {
    error = error1

    // Shouldn't happen, but still guard it.
    process.nextTick(function () {
      return callback(error)
    })
    return
  }
  stdout = ''
  stderr = ''
  spawnedProcess.stdout.on('data', function (data) {
    stdout += data
  })
  spawnedProcess.stderr.on('data', function (data) {
    stderr += data
  })
  errorEmitted = false
  spawnedProcess.on('error', function (error) {
    errorEmitted = true
    return callback(error)
  })
  return spawnedProcess.on('exit', function (code, signal) {
    // We may have already emitted an error.
    if (errorEmitted) {
      return
    }

    // Process terminated with error.
    if (code !== 0) {
      return callback('Command failed: ' + (signal != null ? signal : code) + '\n' + stderr)
    }

    // Success.
    return callback(null, stdout)
  })
}

// Start an instance of the installed app.
exports.processStart = function () {
  return spawnUpdate(['--processStart', exeName], true, function () {})
}

// Download the releases specified by the URL and write new results to stdout.
exports.download = function (updateURL, callback) {
  return spawnUpdate(['--download', updateURL], false, function (error, stdout) {
    var json, ref, ref1, update
    if (error != null) {
      return callback(error)
    }
    try {
      // Last line of output is the JSON details about the releases
      json = stdout.trim().split('\n').pop()
      update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : void 0 : void 0 : void 0
    } catch (jsonError) {
      return callback('Invalid result:\n' + stdout)
    }
    return callback(null, update)
  })
}

// Update the application to the latest remote version specified by URL.
exports.update = function (updateURL, callback) {
  return spawnUpdate(['--update', updateURL], false, callback)
}

// Is the Update.exe installed with the current application?
exports.supported = function () {
  try {
    fs.accessSync(updateExe, fs.R_OK)
    return true
  } catch (error) {
    return false
  }
}
'use strict'

const ipcMain = require('electron').ipcMain
const deprecate = require('electron').deprecate
const EventEmitter = require('events').EventEmitter
const {BrowserWindow, _setDeprecatedOptionsCheck} = process.atomBinding('window')

Object.setPrototypeOf(BrowserWindow.prototype, EventEmitter.prototype)

BrowserWindow.prototype._init = function () {
  // avoid recursive require.
  var app, menu
  app = require('electron').app

  // Simulate the application menu on platforms other than OS X.
  if (process.platform !== 'darwin') {
    menu = app.getApplicationMenu()
    if (menu != null) {
      this.setMenu(menu)
    }
  }

  // Make new windows requested by links behave like "window.open"
  this.webContents.on('-new-window', (event, url, frameName, disposition) => {
    var options
    options = {
      show: true,
      width: 800,
      height: 600
    }
    return ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, disposition, options)
  })

  // window.resizeTo(...)
  // window.moveTo(...)
  this.webContents.on('move', (event, size) => {
    this.setBounds(size)
  })

  // Hide the auto-hide menu when webContents is focused.
  this.webContents.on('activate', () => {
    if (process.platform !== 'darwin' && this.isMenuBarAutoHide() && this.isMenuBarVisible()) {
      this.setMenuBarVisibility(false)
    }
  })

  // Forward the crashed event.
  this.webContents.on('crashed', () => {
    this.emit('crashed')
  })

  // Change window title to page title.
  this.webContents.on('page-title-updated', (event, title) => {
    // The page-title-updated event is not emitted immediately (see #3645), so
    // when the callback is called the BrowserWindow might have been closed.
    if (this.isDestroyed()) return

    // Route the event to BrowserWindow.
    this.emit('page-title-updated', event, title)
    if (!event.defaultPrevented) this.setTitle(title)
  })

  // Sometimes the webContents doesn't get focus when window is shown, so we have
  // to force focusing on webContents in this case. The safest way is to focus it
  // when we first start to load URL, if we do it earlier it won't have effect,
  // if we do it later we might move focus in the page.
  // Though this hack is only needed on OS X when the app is launched from
  // Finder, we still do it on all platforms in case of other bugs we don't know.
  this.webContents.once('load-url', function () {
    this.focus()
  })

  // Redirect focus/blur event to app instance too.
  this.on('blur', (event) => {
    app.emit('browser-window-blur', event, this)
  })
  this.on('focus', (event) => {
    app.emit('browser-window-focus', event, this)
  })

  // Subscribe to visibilityState changes and pass to renderer process.
  let isVisible = this.isVisible() && !this.isMinimized()
  let visibilityChanged = () => {
    let newState = this.isVisible() && !this.isMinimized()
    if (isVisible !== newState) {
      isVisible = newState
      this.webContents.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', isVisible ? 'visible' : 'hidden')
    }
  }
  this.on('show', visibilityChanged)
  this.on('hide', visibilityChanged)
  this.on('minimize', visibilityChanged)
  this.on('restore', visibilityChanged)
  this.on('maximize', visibilityChanged)

  // Notify the creation of the window.
  app.emit('browser-window-created', {}, this)

  // Be compatible with old APIs.
  this.webContents.on('devtools-focused', () => {
    this.emit('devtools-focused')
  })
  this.webContents.on('devtools-opened', () => {
    this.emit('devtools-opened')
  })
  this.webContents.on('devtools-closed', () => {
    this.emit('devtools-closed')
  })

  Object.defineProperty(this, 'devToolsWebContents', {
    enumerable: true,
    configurable: false,
    get: function () {
      return this.webContents.devToolsWebContents
    }
  })
}

BrowserWindow.getFocusedWindow = function () {
  var i, len, window, windows
  windows = BrowserWindow.getAllWindows()
  for (i = 0, len = windows.length; i < len; i++) {
    window = windows[i]
    if (window.isFocused()) {
      return window
    }
  }
  return null
}

BrowserWindow.fromWebContents = function (webContents) {
  var i, len, ref1, window, windows
  windows = BrowserWindow.getAllWindows()
  for (i = 0, len = windows.length; i < len; i++) {
    window = windows[i]
    if ((ref1 = window.webContents) != null ? ref1.equal(webContents) : void 0) {
      return window
    }
  }
}

BrowserWindow.fromDevToolsWebContents = function (webContents) {
  var i, len, ref1, window, windows
  windows = BrowserWindow.getAllWindows()
  for (i = 0, len = windows.length; i < len; i++) {
    window = windows[i]
    if ((ref1 = window.devToolsWebContents) != null ? ref1.equal(webContents) : void 0) {
      return window
    }
  }
}

// Helpers.

BrowserWindow.prototype.loadURL = function () {
  return this.webContents.loadURL.apply(this.webContents, arguments)
}

BrowserWindow.prototype.getURL = function () {
  return this.webContents.getURL()
}

BrowserWindow.prototype.reload = function () {
  return this.webContents.reload.apply(this.webContents, arguments)
}

BrowserWindow.prototype.send = function () {
  return this.webContents.send.apply(this.webContents, arguments)
}

BrowserWindow.prototype.openDevTools = function () {
  return this.webContents.openDevTools.apply(this.webContents, arguments)
}

BrowserWindow.prototype.closeDevTools = function () {
  return this.webContents.closeDevTools()
}

BrowserWindow.prototype.isDevToolsOpened = function () {
  return this.webContents.isDevToolsOpened()
}

BrowserWindow.prototype.isDevToolsFocused = function () {
  return this.webContents.isDevToolsFocused()
}

BrowserWindow.prototype.toggleDevTools = function () {
  return this.webContents.toggleDevTools()
}

BrowserWindow.prototype.inspectElement = function () {
  return this.webContents.inspectElement.apply(this.webContents, arguments)
}

BrowserWindow.prototype.inspectServiceWorker = function () {
  return this.webContents.inspectServiceWorker()
}

// Deprecated.
deprecate.member(BrowserWindow, 'undo', 'webContents')
deprecate.member(BrowserWindow, 'redo', 'webContents')
deprecate.member(BrowserWindow, 'cut', 'webContents')
deprecate.member(BrowserWindow, 'copy', 'webContents')
deprecate.member(BrowserWindow, 'paste', 'webContents')
deprecate.member(BrowserWindow, 'selectAll', 'webContents')
deprecate.member(BrowserWindow, 'reloadIgnoringCache', 'webContents')
deprecate.member(BrowserWindow, 'isLoading', 'webContents')
deprecate.member(BrowserWindow, 'isWaitingForResponse', 'webContents')
deprecate.member(BrowserWindow, 'stop', 'webContents')
deprecate.member(BrowserWindow, 'isCrashed', 'webContents')
deprecate.member(BrowserWindow, 'print', 'webContents')
deprecate.member(BrowserWindow, 'printToPDF', 'webContents')
deprecate.rename(BrowserWindow, 'restart', 'reload')
deprecate.rename(BrowserWindow, 'loadUrl', 'loadURL')
deprecate.rename(BrowserWindow, 'getUrl', 'getURL')

BrowserWindow.prototype.executeJavaScriptInDevTools = deprecate('executeJavaScriptInDevTools', 'devToolsWebContents.executeJavaScript', function (code) {
  var ref1
  return (ref1 = this.devToolsWebContents) != null ? ref1.executeJavaScript(code) : void 0
})

BrowserWindow.prototype.getPageTitle = deprecate('getPageTitle', 'webContents.getTitle', function () {
  var ref1
  return (ref1 = this.webContents) != null ? ref1.getTitle() : void 0
})

const isDeprecatedKey = function (key) {
  return key.indexOf('-') >= 0
}

// Map deprecated key with hyphens to camel case key
const getNonDeprecatedKey = function (deprecatedKey) {
  return deprecatedKey.replace(/-./g, function (match) {
    return match[1].toUpperCase()
  })
}

// TODO Remove for 1.0
const checkForDeprecatedOptions = function (options) {
  if (!options) return ''

  let keysToCheck = Object.keys(options)
  if (options.webPreferences) {
    keysToCheck = keysToCheck.concat(Object.keys(options.webPreferences))
  }

  // Check options for keys with hyphens in them
  let deprecatedKey = keysToCheck.filter(isDeprecatedKey)[0]
  if (deprecatedKey) {
    try {
      deprecate.warn(deprecatedKey, getNonDeprecatedKey(deprecatedKey))
    } catch (error) {
      // Return error message so it can be rethrown via C++
      return error.message
    }
  }

  let webPreferenceOption
  if (options.hasOwnProperty('nodeIntegration')) {
    webPreferenceOption = 'nodeIntegration'
  } else if (options.hasOwnProperty('preload')) {
    webPreferenceOption = 'preload'
  } else if (options.hasOwnProperty('zoomFactor')) {
    webPreferenceOption = 'zoomFactor'
  }
  if (webPreferenceOption) {
    try {
      deprecate.warn(`options.${webPreferenceOption}`, `options.webPreferences.${webPreferenceOption}`)
    } catch (error) {
      // Return error message so it can be rethrown via C++
      return error.message
    }
  }

  return ''
}
_setDeprecatedOptionsCheck(checkForDeprecatedOptions)

module.exports = BrowserWindow
module.exports = process.atomBinding('content_tracing')
'use strict'

const app = require('electron').app
const BrowserWindow = require('electron').BrowserWindow
const binding = process.atomBinding('dialog')
const v8Util = process.atomBinding('v8_util')

var includes = [].includes

var fileDialogProperties = {
  openFile: 1 << 0,
  openDirectory: 1 << 1,
  multiSelections: 1 << 2,
  createDirectory: 1 << 3
}

var messageBoxTypes = ['none', 'info', 'warning', 'error', 'question']

var messageBoxOptions = {
  noLink: 1 << 0
}

var parseArgs = function (window, options, callback, ...args) {
  if (!(window === null || (window != null ? window.constructor : void 0) === BrowserWindow)) {
    // Shift.
    callback = options
    options = window
    window = null
  }

  if ((callback == null) && typeof options === 'function') {
    // Shift.
    callback = options
    options = null
  }

  // Fallback to using very last argument as the callback function
  if ((callback == null) && typeof args[args.length - 1] === 'function') {
    callback = args[args.length - 1]
  }

  return [window, options, callback]
}

var checkAppInitialized = function () {
  if (!app.isReady()) {
    throw new Error('dialog module can only be used after app is ready')
  }
}

module.exports = {
  showOpenDialog: function (...args) {
    var prop, properties, value, wrappedCallback
    checkAppInitialized()
    let [window, options, callback] = parseArgs.apply(null, args)
    if (options == null) {
      options = {
        title: 'Open',
        properties: ['openFile']
      }
    }
    if (options.properties == null) {
      options.properties = ['openFile']
    }
    if (!Array.isArray(options.properties)) {
      throw new TypeError('Properties must be an array')
    }
    properties = 0
    for (prop in fileDialogProperties) {
      value = fileDialogProperties[prop]
      if (includes.call(options.properties, prop)) {
        properties |= value
      }
    }
    if (options.title == null) {
      options.title = ''
    } else if (typeof options.title !== 'string') {
      throw new TypeError('Title must be a string')
    }
    if (options.defaultPath == null) {
      options.defaultPath = ''
    } else if (typeof options.defaultPath !== 'string') {
      throw new TypeError('Default path must be a string')
    }
    if (options.filters == null) {
      options.filters = []
    }
    wrappedCallback = typeof callback === 'function' ? function (success, result) {
      return callback(success ? result : void 0)
    } : null
    return binding.showOpenDialog(String(options.title), String(options.defaultPath), options.filters, properties, window, wrappedCallback)
  },

  showSaveDialog: function (...args) {
    var wrappedCallback
    checkAppInitialized()
    let [window, options, callback] = parseArgs.apply(null, args)
    if (options == null) {
      options = {
        title: 'Save'
      }
    }
    if (options.title == null) {
      options.title = ''
    } else if (typeof options.title !== 'string') {
      throw new TypeError('Title must be a string')
    }
    if (options.defaultPath == null) {
      options.defaultPath = ''
    } else if (typeof options.defaultPath !== 'string') {
      throw new TypeError('Default path must be a string')
    }
    if (options.filters == null) {
      options.filters = []
    }
    wrappedCallback = typeof callback === 'function' ? function (success, result) {
      return callback(success ? result : void 0)
    } : null
    return binding.showSaveDialog(String(options.title), String(options.defaultPath), options.filters, window, wrappedCallback)
  },

  showMessageBox: function (...args) {
    var flags, i, j, len, messageBoxType, ref2, ref3, text
    checkAppInitialized()
    let [window, options, callback] = parseArgs.apply(null, args)
    if (options == null) {
      options = {
        type: 'none'
      }
    }
    if (options.type == null) {
      options.type = 'none'
    }
    messageBoxType = messageBoxTypes.indexOf(options.type)
    if (!(messageBoxType > -1)) {
      throw new TypeError('Invalid message box type')
    }
    if (!Array.isArray(options.buttons)) {
      throw new TypeError('Buttons must be an array')
    }
    if (options.title == null) {
      options.title = ''
    } else if (typeof options.title !== 'string') {
      throw new TypeError('Title must be a string')
    }
    if (options.message == null) {
      options.message = ''
    } else if (typeof options.message !== 'string') {
      throw new TypeError('Message must be a string')
    }
    if (options.detail == null) {
      options.detail = ''
    } else if (typeof options.detail !== 'string') {
      throw new TypeError('Detail must be a string')
    }
    if (options.icon == null) {
      options.icon = null
    }
    if (options.defaultId == null) {
      options.defaultId = -1
    }

    // Choose a default button to get selected when dialog is cancelled.
    if (options.cancelId == null) {
      options.cancelId = 0
      ref2 = options.buttons
      for (i = j = 0, len = ref2.length; j < len; i = ++j) {
        text = ref2[i]
        if ((ref3 = text.toLowerCase()) === 'cancel' || ref3 === 'no') {
          options.cancelId = i
          break
        }
      }
    }
    flags = options.noLink ? messageBoxOptions.noLink : 0
    return binding.showMessageBox(messageBoxType, options.buttons, options.defaultId, options.cancelId, flags, options.title, options.message, options.detail, options.icon, window, callback)
  },

  showErrorBox: function (...args) {
    return binding.showErrorBox.apply(binding, args)
  }
}

// Mark standard asynchronous functions.
var ref1 = ['showMessageBox', 'showOpenDialog', 'showSaveDialog']
var j, len, api
for (j = 0, len = ref1.length; j < len; j++) {
  api = ref1[j]
  v8Util.setHiddenValue(module.exports[api], 'asynchronous', true)
}
const common = require('../../../common/api/exports/electron')

// Import common modules.
common.defineProperties(exports)

Object.defineProperties(exports, {
  // Browser side modules, please sort with alphabet order.
  app: {
    enumerable: true,
    get: function () {
      return require('../app')
    }
  },
  autoUpdater: {
    enumerable: true,
    get: function () {
      return require('../auto-updater')
    }
  },
  BrowserWindow: {
    enumerable: true,
    get: function () {
      return require('../browser-window')
    }
  },
  contentTracing: {
    enumerable: true,
    get: function () {
      return require('../content-tracing')
    }
  },
  dialog: {
    enumerable: true,
    get: function () {
      return require('../dialog')
    }
  },
  ipcMain: {
    enumerable: true,
    get: function () {
      return require('../ipc-main')
    }
  },
  globalShortcut: {
    enumerable: true,
    get: function () {
      return require('../global-shortcut')
    }
  },
  Menu: {
    enumerable: true,
    get: function () {
      return require('../menu')
    }
  },
  MenuItem: {
    enumerable: true,
    get: function () {
      return require('../menu-item')
    }
  },
  powerMonitor: {
    enumerable: true,
    get: function () {
      return require('../power-monitor')
    }
  },
  powerSaveBlocker: {
    enumerable: true,
    get: function () {
      return require('../power-save-blocker')
    }
  },
  protocol: {
    enumerable: true,
    get: function () {
      return require('../protocol')
    }
  },
  screen: {
    enumerable: true,
    get: function () {
      return require('../screen')
    }
  },
  session: {
    enumerable: true,
    get: function () {
      return require('../session')
    }
  },
  Tray: {
    enumerable: true,
    get: function () {
      return require('../tray')
    }
  },

  // The internal modules, invisible unless you know their names.
  NavigationController: {
    get: function () {
      return require('../navigation-controller')
    }
  },
  webContents: {
    get: function () {
      return require('../web-contents')
    }
  }
})
var globalShortcut

globalShortcut = process.atomBinding('global_shortcut').globalShortcut

module.exports = globalShortcut
const EventEmitter = require('events').EventEmitter

module.exports = new EventEmitter()
const deprecate = require('electron').deprecate
const ipcMain = require('electron').ipcMain

// This module is deprecated, we mirror everything from ipcMain.
deprecate.warn('ipc module', 'require("electron").ipcMain')

module.exports = ipcMain
'use strict'

var MenuItem, methodInBrowserWindow, nextCommandId, rolesMap

nextCommandId = 0

// Maps role to methods of webContents
rolesMap = {
  undo: 'undo',
  redo: 'redo',
  cut: 'cut',
  copy: 'copy',
  paste: 'paste',
  selectall: 'selectAll',
  minimize: 'minimize',
  close: 'close',
  delete: 'delete'
}

// Maps methods that should be called directly on the BrowserWindow instance
methodInBrowserWindow = {
  minimize: true,
  close: true
}

MenuItem = (function () {
  MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']

  function MenuItem (options) {
    var click, ref
    const Menu = require('electron').Menu
    click = options.click
    this.selector = options.selector
    this.type = options.type
    this.role = options.role
    this.label = options.label
    this.sublabel = options.sublabel
    this.accelerator = options.accelerator
    this.icon = options.icon
    this.enabled = options.enabled
    this.visible = options.visible
    this.checked = options.checked
    this.submenu = options.submenu
    if ((this.submenu != null) && this.submenu.constructor !== Menu) {
      this.submenu = Menu.buildFromTemplate(this.submenu)
    }
    if ((this.type == null) && (this.submenu != null)) {
      this.type = 'submenu'
    }
    if (this.type === 'submenu' && ((ref = this.submenu) != null ? ref.constructor : void 0) !== Menu) {
      throw new Error('Invalid submenu')
    }
    this.overrideReadOnlyProperty('type', 'normal')
    this.overrideReadOnlyProperty('role')
    this.overrideReadOnlyProperty('accelerator')
    this.overrideReadOnlyProperty('icon')
    this.overrideReadOnlyProperty('submenu')
    this.overrideProperty('label', '')
    this.overrideProperty('sublabel', '')
    this.overrideProperty('enabled', true)
    this.overrideProperty('visible', true)
    this.overrideProperty('checked', false)
    if (MenuItem.types.indexOf(this.type) === -1) {
      throw new Error('Unknown menu type ' + this.type)
    }
    this.commandId = ++nextCommandId
    this.click = (focusedWindow) => {
      // Manually flip the checked flags when clicked.
      var methodName, ref1, ref2
      if ((ref1 = this.type) === 'checkbox' || ref1 === 'radio') {
        this.checked = !this.checked
      }
      if (this.role && rolesMap[this.role] && process.platform !== 'darwin' && (focusedWindow != null)) {
        methodName = rolesMap[this.role]
        if (methodInBrowserWindow[methodName]) {
          return focusedWindow[methodName]()
        } else {
          return (ref2 = focusedWindow.webContents) != null ? ref2[methodName]() : void 0
        }
      } else if (typeof click === 'function') {
        return click(this, focusedWindow)
      } else if (typeof this.selector === 'string' && process.platform === 'darwin') {
        return Menu.sendActionToFirstResponder(this.selector)
      }
    }
  }

  MenuItem.prototype.overrideProperty = function (name, defaultValue) {
    if (defaultValue == null) {
      defaultValue = null
    }
    return this[name] != null ? this[name] : this[name] = defaultValue
  }

  MenuItem.prototype.overrideReadOnlyProperty = function (name, defaultValue) {
    if (defaultValue == null) {
      defaultValue = null
    }
    if (this[name] == null) {
      this[name] = defaultValue
    }
    return Object.defineProperty(this, name, {
      enumerable: true,
      writable: false,
      value: this[name]
    })
  }

  return MenuItem
})()

module.exports = MenuItem
'use strict'

const BrowserWindow = require('electron').BrowserWindow
const MenuItem = require('electron').MenuItem
const EventEmitter = require('events').EventEmitter
const v8Util = process.atomBinding('v8_util')
const bindings = process.atomBinding('menu')

// Automatically generated radio menu item's group id.
var nextGroupId = 0

// Search between separators to find a radio menu item and return its group id,
// otherwise generate a group id.
var generateGroupId = function (items, pos) {
  var i, item, j, k, ref1, ref2, ref3
  if (pos > 0) {
    for (i = j = ref1 = pos - 1; ref1 <= 0 ? j <= 0 : j >= 0; i = ref1 <= 0 ? ++j : --j) {
      item = items[i]
      if (item.type === 'radio') {
        return item.groupId
      }
      if (item.type === 'separator') {
        break
      }
    }
  } else if (pos < items.length) {
    for (i = k = ref2 = pos, ref3 = items.length - 1; ref2 <= ref3 ? k <= ref3 : k >= ref3; i = ref2 <= ref3 ? ++k : --k) {
      item = items[i]
      if (item.type === 'radio') {
        return item.groupId
      }
      if (item.type === 'separator') {
        break
      }
    }
  }
  return ++nextGroupId
}

// Returns the index of item according to |id|.
var indexOfItemById = function (items, id) {
  var i, item, j, len
  for (i = j = 0, len = items.length; j < len; i = ++j) {
    item = items[i]
    if (item.id === id) {
      return i
    }
  }
  return -1
}

// Returns the index of where to insert the item according to |position|.
var indexToInsertByPosition = function (items, position) {
  var insertIndex
  if (!position) {
    return items.length
  }
  const [query, id] = position.split('=')
  insertIndex = indexOfItemById(items, id)
  if (insertIndex === -1 && query !== 'endof') {
    console.warn("Item with id '" + id + "' is not found")
    return items.length
  }
  switch (query) {
    case 'after':
      insertIndex++
      break
    case 'endof':

      // If the |id| doesn't exist, then create a new group with the |id|.
      if (insertIndex === -1) {
        items.push({
          id: id,
          type: 'separator'
        })
        insertIndex = items.length - 1
      }

      // Find the end of the group.
      insertIndex++
      while (insertIndex < items.length && items[insertIndex].type !== 'separator') {
        insertIndex++
      }
  }
  return insertIndex
}

const Menu = bindings.Menu

Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype)

Menu.prototype._init = function () {
  this.commandsMap = {}
  this.groupsMap = {}
  this.items = []
  this.delegate = {
    isCommandIdChecked: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.checked : undefined
    },
    isCommandIdEnabled: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.enabled : undefined
    },
    isCommandIdVisible: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.visible : undefined
    },
    getAcceleratorForCommandId: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.accelerator : undefined
    },
    getIconForCommandId: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.icon : undefined
    },
    executeCommand: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.click(BrowserWindow.getFocusedWindow()) : undefined
    },
    menuWillShow: () => {
      // Make sure radio groups have at least one menu item seleted.
      var checked, group, id, j, len, radioItem, ref1
      ref1 = this.groupsMap
      for (id in ref1) {
        group = ref1[id]
        checked = false
        for (j = 0, len = group.length; j < len; j++) {
          radioItem = group[j]
          if (!radioItem.checked) {
            continue
          }
          checked = true
          break
        }
        if (!checked) {
          v8Util.setHiddenValue(group[0], 'checked', true)
        }
      }
    }
  }
}

Menu.prototype.popup = function (window, x, y, positioningItem) {
  if (typeof window !== 'object' || window.constructor !== BrowserWindow) {
    // Shift.
    positioningItem = y
    y = x
    x = window
    window = BrowserWindow.getFocusedWindow()
  }

  // Default parameters.
  if (typeof x !== 'number') x = -1
  if (typeof y !== 'number') y = -1
  if (typeof positioningItem !== 'number') positioningItem = 0

  this.popupAt(window, x, y, positioningItem)
}

Menu.prototype.append = function (item) {
  return this.insert(this.getItemCount(), item)
}

Menu.prototype.insert = function (pos, item) {
  var base, name
  if ((item != null ? item.constructor : void 0) !== MenuItem) {
    throw new TypeError('Invalid item')
  }
  switch (item.type) {
    case 'normal':
      this.insertItem(pos, item.commandId, item.label)
      break
    case 'checkbox':
      this.insertCheckItem(pos, item.commandId, item.label)
      break
    case 'separator':
      this.insertSeparator(pos)
      break
    case 'submenu':
      this.insertSubMenu(pos, item.commandId, item.label, item.submenu)
      break
    case 'radio':
      // Grouping radio menu items.
      item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos))
      if ((base = this.groupsMap)[name = item.groupId] == null) {
        base[name] = []
      }
      this.groupsMap[item.groupId].push(item)

      // Setting a radio menu item should flip other items in the group.
      v8Util.setHiddenValue(item, 'checked', item.checked)
      Object.defineProperty(item, 'checked', {
        enumerable: true,
        get: function () {
          return v8Util.getHiddenValue(item, 'checked')
        },
        set: () => {
          var j, len, otherItem, ref1
          ref1 = this.groupsMap[item.groupId]
          for (j = 0, len = ref1.length; j < len; j++) {
            otherItem = ref1[j]
            if (otherItem !== item) {
              v8Util.setHiddenValue(otherItem, 'checked', false)
            }
          }
          return v8Util.setHiddenValue(item, 'checked', true)
        }
      })
      this.insertRadioItem(pos, item.commandId, item.label, item.groupId)
  }
  if (item.sublabel != null) {
    this.setSublabel(pos, item.sublabel)
  }
  if (item.icon != null) {
    this.setIcon(pos, item.icon)
  }
  if (item.role != null) {
    this.setRole(pos, item.role)
  }

  // Make menu accessable to items.
  item.overrideReadOnlyProperty('menu', this)

  // Remember the items.
  this.items.splice(pos, 0, item)
  this.commandsMap[item.commandId] = item
}

// Force menuWillShow to be called
Menu.prototype._callMenuWillShow = function () {
  if (this.delegate != null) {
    this.delegate.menuWillShow()
  }
  this.items.forEach(function (item) {
    if (item.submenu != null) {
      item.submenu._callMenuWillShow()
    }
  })
}

var applicationMenu = null

Menu.setApplicationMenu = function (menu) {
  if (!(menu === null || menu.constructor === Menu)) {
    throw new TypeError('Invalid menu')
  }

  // Keep a reference.
  applicationMenu = menu
  if (process.platform === 'darwin') {
    if (menu === null) {
      return
    }
    menu._callMenuWillShow()
    bindings.setApplicationMenu(menu)
  } else {
    BrowserWindow.getAllWindows().forEach(function (window) {
      window.setMenu(menu)
    })
  }
}

Menu.getApplicationMenu = function () {
  return applicationMenu
}

Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder

Menu.buildFromTemplate = function (template) {
  var insertIndex, item, j, k, key, len, len1, menu, menuItem, positionedTemplate
  if (!Array.isArray(template)) {
    throw new TypeError('Invalid template for Menu')
  }
  positionedTemplate = []
  insertIndex = 0
  for (j = 0, len = template.length; j < len; j++) {
    item = template[j]
    if (item.position) {
      insertIndex = indexToInsertByPosition(positionedTemplate, item.position)
    } else {
      // If no |position| is specified, insert after last item.
      insertIndex++
    }
    positionedTemplate.splice(insertIndex, 0, item)
  }
  menu = new Menu()
  for (k = 0, len1 = positionedTemplate.length; k < len1; k++) {
    item = positionedTemplate[k]
    if (typeof item !== 'object') {
      throw new TypeError('Invalid template for MenuItem')
    }
    menuItem = new MenuItem(item)
    for (key in item) {
      // Preserve extra fields specified by user
      if (!menuItem.hasOwnProperty(key)) {
        menuItem[key] = item[key]
      }
    }
    menu.append(menuItem)
  }
  return menu
}

module.exports = Menu
'use strict'

const ipcMain = require('electron').ipcMain

// The history operation in renderer is redirected to browser.
ipcMain.on('ELECTRON_NAVIGATION_CONTROLLER', function (event, method, ...args) {
  var ref
  (ref = event.sender)[method].apply(ref, args)
})

ipcMain.on('ELECTRON_SYNC_NAVIGATION_CONTROLLER', function (event, method, ...args) {
  var ref
  event.returnValue = (ref = event.sender)[method].apply(ref, args)
})

// JavaScript implementation of Chromium's NavigationController.
// Instead of relying on Chromium for history control, we compeletely do history
// control on user land, and only rely on WebContents.loadURL for navigation.
// This helps us avoid Chromium's various optimizations so we can ensure renderer
// process is restarted everytime.
var NavigationController = (function () {
  function NavigationController (webContents) {
    this.webContents = webContents
    this.clearHistory()

    // webContents may have already navigated to a page.
    if (this.webContents._getURL()) {
      this.currentIndex++
      this.history.push(this.webContents._getURL())
    }
    this.webContents.on('navigation-entry-commited', (event, url, inPage, replaceEntry) => {
      var currentEntry
      if (this.inPageIndex > -1 && !inPage) {
        // Navigated to a new page, clear in-page mark.
        this.inPageIndex = -1
      } else if (this.inPageIndex === -1 && inPage) {
        // Started in-page navigations.
        this.inPageIndex = this.currentIndex
      }
      if (this.pendingIndex >= 0) {
        // Go to index.
        this.currentIndex = this.pendingIndex
        this.pendingIndex = -1
        this.history[this.currentIndex] = url
      } else if (replaceEntry) {
        // Non-user initialized navigation.
        this.history[this.currentIndex] = url
      } else {
        // Normal navigation. Clear history.
        this.history = this.history.slice(0, this.currentIndex + 1)
        currentEntry = this.history[this.currentIndex]
        if ((currentEntry != null ? currentEntry.url : void 0) !== url) {
          this.currentIndex++
          return this.history.push(url)
        }
      }
    })
  }

  NavigationController.prototype.loadURL = function (url, options) {
    if (options == null) {
      options = {}
    }
    this.pendingIndex = -1
    this.webContents._loadURL(url, options)
    return this.webContents.emit('load-url', url, options)
  }

  NavigationController.prototype.getURL = function () {
    if (this.currentIndex === -1) {
      return ''
    } else {
      return this.history[this.currentIndex]
    }
  }

  NavigationController.prototype.stop = function () {
    this.pendingIndex = -1
    return this.webContents._stop()
  }

  NavigationController.prototype.reload = function () {
    this.pendingIndex = this.currentIndex
    return this.webContents._loadURL(this.getURL(), {})
  }

  NavigationController.prototype.reloadIgnoringCache = function () {
    this.pendingIndex = this.currentIndex
    return this.webContents._loadURL(this.getURL(), {
      extraHeaders: 'pragma: no-cache\n'
    })
  }

  NavigationController.prototype.canGoBack = function () {
    return this.getActiveIndex() > 0
  }

  NavigationController.prototype.canGoForward = function () {
    return this.getActiveIndex() < this.history.length - 1
  }

  NavigationController.prototype.canGoToIndex = function (index) {
    return index >= 0 && index < this.history.length
  }

  NavigationController.prototype.canGoToOffset = function (offset) {
    return this.canGoToIndex(this.currentIndex + offset)
  }

  NavigationController.prototype.clearHistory = function () {
    this.history = []
    this.currentIndex = -1
    this.pendingIndex = -1
    this.inPageIndex = -1
  }

  NavigationController.prototype.goBack = function () {
    if (!this.canGoBack()) {
      return
    }
    this.pendingIndex = this.getActiveIndex() - 1
    if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) {
      return this.webContents._goBack()
    } else {
      return this.webContents._loadURL(this.history[this.pendingIndex], {})
    }
  }

  NavigationController.prototype.goForward = function () {
    if (!this.canGoForward()) {
      return
    }
    this.pendingIndex = this.getActiveIndex() + 1
    if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) {
      return this.webContents._goForward()
    } else {
      return this.webContents._loadURL(this.history[this.pendingIndex], {})
    }
  }

  NavigationController.prototype.goToIndex = function (index) {
    if (!this.canGoToIndex(index)) {
      return
    }
    this.pendingIndex = index
    return this.webContents._loadURL(this.history[this.pendingIndex], {})
  }

  NavigationController.prototype.goToOffset = function (offset) {
    var pendingIndex
    if (!this.canGoToOffset(offset)) {
      return
    }
    pendingIndex = this.currentIndex + offset
    if (this.inPageIndex > -1 && pendingIndex >= this.inPageIndex) {
      this.pendingIndex = pendingIndex
      return this.webContents._goToOffset(offset)
    } else {
      return this.goToIndex(pendingIndex)
    }
  }

  NavigationController.prototype.getActiveIndex = function () {
    if (this.pendingIndex === -1) {
      return this.currentIndex
    } else {
      return this.pendingIndex
    }
  }

  NavigationController.prototype.length = function () {
    return this.history.length
  }

  return NavigationController
})()

module.exports = NavigationController
const EventEmitter = require('events').EventEmitter
const powerMonitor = process.atomBinding('power_monitor').powerMonitor

Object.setPrototypeOf(powerMonitor, EventEmitter.prototype)

module.exports = powerMonitor
var powerSaveBlocker

powerSaveBlocker = process.atomBinding('power_save_blocker').powerSaveBlocker

module.exports = powerSaveBlocker
const app = require('electron').app

if (!app.isReady()) {
  throw new Error('Can not initialize protocol module before app is ready')
}

const protocol = process.atomBinding('protocol').protocol

// Warn about removed APIs.
var logAndThrow = function (callback, message) {
  console.error(message)
  if (callback) {
    return callback(new Error(message))
  } else {
    throw new Error(message)
  }
}

protocol.registerProtocol = function (scheme, handler, callback) {
  return logAndThrow(callback, 'registerProtocol API has been replaced by the register[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.')
}

protocol.isHandledProtocol = function (scheme, callback) {
  return logAndThrow(callback, 'isHandledProtocol API has been replaced by isProtocolHandled.')
}

protocol.interceptProtocol = function (scheme, handler, callback) {
  return logAndThrow(callback, 'interceptProtocol API has been replaced by the intercept[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.')
}

module.exports = protocol
const EventEmitter = require('events').EventEmitter
const screen = process.atomBinding('screen').screen

Object.setPrototypeOf(screen, EventEmitter.prototype)

module.exports = screen
const EventEmitter = require('events').EventEmitter
const bindings = process.atomBinding('session')
const PERSIST_PREFIX = 'persist:'

// Returns the Session from |partition| string.
exports.fromPartition = function (partition) {
  if (partition == null) {
    partition = ''
  }
  if (partition === '') {
    return exports.defaultSession
  }
  if (partition.startsWith(PERSIST_PREFIX)) {
    return bindings.fromPartition(partition.substr(PERSIST_PREFIX.length), false)
  } else {
    return bindings.fromPartition(partition, true)
  }
}

// Returns the default session.
Object.defineProperty(exports, 'defaultSession', {
  enumerable: true,
  get: function () {
    return bindings.fromPartition('', false)
  }
})

var wrapSession = function (session) {
  // session is an EventEmitter.
  Object.setPrototypeOf(session, EventEmitter.prototype)
}

bindings._setWrapSession(wrapSession)
const deprecate = require('electron').deprecate
const EventEmitter = require('events').EventEmitter
const Tray = process.atomBinding('tray').Tray

Object.setPrototypeOf(Tray.prototype, EventEmitter.prototype)

Tray.prototype._init = function () {
  // Deprecated.
  deprecate.rename(this, 'popContextMenu', 'popUpContextMenu')
  deprecate.event(this, 'clicked', 'click')
  deprecate.event(this, 'double-clicked', 'double-click')
  deprecate.event(this, 'right-clicked', 'right-click')
  return deprecate.event(this, 'balloon-clicked', 'balloon-click')
}

Tray.prototype.setContextMenu = function (menu) {
  this._setContextMenu(menu)

  // Keep a strong reference of menu.
  this.menu = menu
}

module.exports = Tray
'use strict'

const EventEmitter = require('events').EventEmitter
const deprecate = require('electron').deprecate
const ipcMain = require('electron').ipcMain
const NavigationController = require('electron').NavigationController
const Menu = require('electron').Menu

const binding = process.atomBinding('web_contents')
const debuggerBinding = process.atomBinding('debugger')

let nextId = 0

let getNextId = function () {
  return ++nextId
}

let PDFPageSize = {
  A5: {
    custom_display_name: 'A5',
    height_microns: 210000,
    name: 'ISO_A5',
    width_microns: 148000
  },
  A4: {
    custom_display_name: 'A4',
    height_microns: 297000,
    name: 'ISO_A4',
    is_default: 'true',
    width_microns: 210000
  },
  A3: {
    custom_display_name: 'A3',
    height_microns: 420000,
    name: 'ISO_A3',
    width_microns: 297000
  },
  Legal: {
    custom_display_name: 'Legal',
    height_microns: 355600,
    name: 'NA_LEGAL',
    width_microns: 215900
  },
  Letter: {
    custom_display_name: 'Letter',
    height_microns: 279400,
    name: 'NA_LETTER',
    width_microns: 215900
  },
  Tabloid: {
    height_microns: 431800,
    name: 'NA_LEDGER',
    width_microns: 279400,
    custom_display_name: 'Tabloid'
  }
}

// Following methods are mapped to webFrame.
const webFrameMethods = [
  'insertText',
  'setZoomFactor',
  'setZoomLevel',
  'setZoomLevelLimits'
]

let wrapWebContents = function (webContents) {
  // webContents is an EventEmitter.
  var controller, method, name, ref1
  Object.setPrototypeOf(webContents, EventEmitter.prototype)

  // Every remote callback from renderer process would add a listenter to the
  // render-view-deleted event, so ignore the listenters warning.
  webContents.setMaxListeners(0)

  // WebContents::send(channel, args..)
  webContents.send = function (channel, ...args) {
    if (channel == null) {
      throw new Error('Missing required channel argument')
    }
    return this._send(channel, args)
  }

  // The navigation controller.
  controller = new NavigationController(webContents)
  ref1 = NavigationController.prototype
  for (name in ref1) {
    method = ref1[name]
    if (method instanceof Function) {
      (function (name, method) {
        webContents[name] = function () {
          return method.apply(controller, arguments)
        }
      })(name, method)
    }
  }

  // Mapping webFrame methods.
  for (let method of webFrameMethods) {
    webContents[method] = function (...args) {
      this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args)
    }
  }

  const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
    this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
    ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) {
      if (callback) callback(result)
    })
  }

  // Make sure webContents.executeJavaScript would run the code only when the
  // webContents has been loaded.
  webContents.executeJavaScript = function (code, hasUserGesture, callback) {
    let requestId = getNextId()
    if (typeof hasUserGesture === 'function') {
      callback = hasUserGesture
      hasUserGesture = false
    }
    if (this.getURL() && !this.isLoading()) {
      return asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture)
    } else {
      return this.once('did-finish-load', asyncWebFrameMethods.bind(this, requestId, 'executeJavaScript', callback, code, hasUserGesture))
    }
  }

  // Dispatch IPC messages to the ipc module.
  webContents.on('ipc-message', function (event, [channel, ...args]) {
    return ipcMain.emit.apply(ipcMain, [channel, event].concat(args))
  })
  webContents.on('ipc-message-sync', function (event, [channel, ...args]) {
    Object.defineProperty(event, 'returnValue', {
      set: function (value) {
        return event.sendReply(JSON.stringify(value))
      },
      get: function () {
        return undefined
      }
    })
    return ipcMain.emit.apply(ipcMain, [channel, event].concat(args))
  })

  // Handle context menu action request from pepper plugin.
  webContents.on('pepper-context-menu', function (event, params) {
    var menu
    menu = Menu.buildFromTemplate(params.menu)
    return menu.popup(params.x, params.y)
  })

  // The devtools requests the webContents to reload.
  webContents.on('devtools-reload-page', function () {
    webContents.reload()
  })

  // Delays the page-title-updated event to next tick.
  webContents.on('-page-title-updated', function (...args) {
    setImmediate(() => {
      this.emit.apply(this, ['page-title-updated'].concat(args))
    })
  })

  // Deprecated.
  deprecate.rename(webContents, 'loadUrl', 'loadURL')
  deprecate.rename(webContents, 'getUrl', 'getURL')
  deprecate.event(webContents, 'page-title-set', 'page-title-updated', function (...args) {
    return this.emit.apply(this, ['page-title-set'].concat(args))
  })

  webContents.printToPDF = function (options, callback) {
    var printingSetting
    printingSetting = {
      pageRage: [],
      mediaSize: {},
      landscape: false,
      color: 2,
      headerFooterEnabled: false,
      marginsType: 0,
      isFirstRequest: false,
      requestID: getNextId(),
      previewModifiable: true,
      printToPDF: true,
      printWithCloudPrint: false,
      printWithPrivet: false,
      printWithExtension: false,
      deviceName: 'Save as PDF',
      generateDraftData: true,
      fitToPageEnabled: false,
      duplex: 0,
      copies: 1,
      collate: true,
      shouldPrintBackgrounds: false,
      shouldPrintSelectionOnly: false
    }
    if (options.landscape) {
      printingSetting.landscape = options.landscape
    }
    if (options.marginsType) {
      printingSetting.marginsType = options.marginsType
    }
    if (options.printSelectionOnly) {
      printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly
    }
    if (options.printBackground) {
      printingSetting.shouldPrintBackgrounds = options.printBackground
    }
    if (options.pageSize && PDFPageSize[options.pageSize]) {
      printingSetting.mediaSize = PDFPageSize[options.pageSize]
    } else {
      printingSetting.mediaSize = PDFPageSize['A4']
    }
    return this._printToPDF(printingSetting, callback)
  }
}

// Wrapper for native class.
let wrapDebugger = function (webContentsDebugger) {
  // debugger is an EventEmitter.
  Object.setPrototypeOf(webContentsDebugger, EventEmitter.prototype)
}

binding._setWrapWebContents(wrapWebContents)
debuggerBinding._setWrapDebugger(wrapDebugger)

module.exports.create = function (options) {
  if (options == null) {
    options = {}
  }
  return binding.create(options)
}
const electron = require('electron')
const app = electron.app
const fs = require('fs')
const path = require('path')
const url = require('url')

// Mapping between hostname and file path.
var hostPathMap = {}
var hostPathMapNextKey = 0

var getHostForPath = function (path) {
  var key
  key = 'extension-' + (++hostPathMapNextKey)
  hostPathMap[key] = path
  return key
}

var getPathForHost = function (host) {
  return hostPathMap[host]
}

// Cache extensionInfo.
var extensionInfoMap = {}

var getExtensionInfoFromPath = function (srcDirectory) {
  var manifest, page
  manifest = JSON.parse(fs.readFileSync(path.join(srcDirectory, 'manifest.json')))
  if (extensionInfoMap[manifest.name] == null) {
    // We can not use 'file://' directly because all resources in the extension
    // will be treated as relative to the root in Chrome.
    page = url.format({
      protocol: 'chrome-extension',
      slashes: true,
      hostname: getHostForPath(srcDirectory),
      pathname: manifest.devtools_page
    })
    extensionInfoMap[manifest.name] = {
      startPage: page,
      name: manifest.name,
      srcDirectory: srcDirectory,
      exposeExperimentalAPIs: true
    }
    return extensionInfoMap[manifest.name]
  }
}

// The loaded extensions cache and its persistent path.
var loadedExtensions = null
var loadedExtensionsPath = null

app.on('will-quit', function () {
  try {
    loadedExtensions = Object.keys(extensionInfoMap).map(function (key) {
      return extensionInfoMap[key].srcDirectory
    })
    if (loadedExtensions.length > 0) {
      try {
        fs.mkdirSync(path.dirname(loadedExtensionsPath))
      } catch (error) {
        // Ignore error
      }
      fs.writeFileSync(loadedExtensionsPath, JSON.stringify(loadedExtensions))
    } else {
      fs.unlinkSync(loadedExtensionsPath)
    }
  } catch (error) {
    // Ignore error
  }
})

// We can not use protocol or BrowserWindow until app is ready.
app.once('ready', function () {
  var BrowserWindow, chromeExtensionHandler, i, init, len, protocol, srcDirectory
  protocol = electron.protocol
  BrowserWindow = electron.BrowserWindow

  // Load persisted extensions.
  loadedExtensionsPath = path.join(app.getPath('userData'), 'DevTools Extensions')
  try {
    loadedExtensions = JSON.parse(fs.readFileSync(loadedExtensionsPath))
    if (!Array.isArray(loadedExtensions)) {
      loadedExtensions = []
    }

    // Preheat the extensionInfo cache.
    for (i = 0, len = loadedExtensions.length; i < len; i++) {
      srcDirectory = loadedExtensions[i]
      getExtensionInfoFromPath(srcDirectory)
    }
  } catch (error) {
    // Ignore error
  }

  // The chrome-extension: can map a extension URL request to real file path.
  chromeExtensionHandler = function (request, callback) {
    var directory, parsed
    parsed = url.parse(request.url)
    if (!(parsed.hostname && (parsed.path != null))) {
      return callback()
    }
    if (!/extension-\d+/.test(parsed.hostname)) {
      return callback()
    }
    directory = getPathForHost(parsed.hostname)
    if (directory == null) {
      return callback()
    }
    return callback(path.join(directory, parsed.path))
  }
  protocol.registerFileProtocol('chrome-extension', chromeExtensionHandler, function (error) {
    if (error) {
      return console.error('Unable to register chrome-extension protocol')
    }
  })
  BrowserWindow.prototype._loadDevToolsExtensions = function (extensionInfoArray) {
    var ref
    return (ref = this.devToolsWebContents) != null ? ref.executeJavaScript('DevToolsAPI.addExtensions(' + (JSON.stringify(extensionInfoArray)) + ');') : void 0
  }
  BrowserWindow.addDevToolsExtension = function (srcDirectory) {
    var extensionInfo, j, len1, ref, window
    extensionInfo = getExtensionInfoFromPath(srcDirectory)
    if (extensionInfo) {
      ref = BrowserWindow.getAllWindows()
      for (j = 0, len1 = ref.length; j < len1; j++) {
        window = ref[j]
        window._loadDevToolsExtensions([extensionInfo])
      }
      return extensionInfo.name
    }
  }
  BrowserWindow.removeDevToolsExtension = function (name) {
    return delete extensionInfoMap[name]
  }

  // Load persisted extensions when devtools is opened.
  init = BrowserWindow.prototype._init
  BrowserWindow.prototype._init = function () {
    init.call(this)
    return this.on('devtools-opened', function () {
      return this._loadDevToolsExtensions(Object.keys(extensionInfoMap).map(function (key) {
        return extensionInfoMap[key]
      }))
    })
  }
})
'use strict'

const ipcMain = require('electron').ipcMain
const desktopCapturer = process.atomBinding('desktop_capturer').desktopCapturer

var deepEqual = function (opt1, opt2) {
  return JSON.stringify(opt1) === JSON.stringify(opt2)
}

// A queue for holding all requests from renderer process.
var requestsQueue = []

ipcMain.on('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', function (event, captureWindow, captureScreen, thumbnailSize, id) {
  var request
  request = {
    id: id,
    options: {
      captureWindow: captureWindow,
      captureScreen: captureScreen,
      thumbnailSize: thumbnailSize
    },
    webContents: event.sender
  }
  requestsQueue.push(request)
  if (requestsQueue.length === 1) {
    desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize)
  }

  // If the WebContents is destroyed before receiving result, just remove the
  // reference from requestsQueue to make the module not send the result to it.
  return event.sender.once('destroyed', function () {
    request.webContents = null
  })
})

desktopCapturer.emit = function (event, name, sources) {
  // Receiving sources result from main process, now send them back to renderer.
  var handledRequest, i, len, ref, ref1, request, result, source, unhandledRequestsQueue
  handledRequest = requestsQueue.shift(0)
  result = (function () {
    var i, len, results
    results = []
    for (i = 0, len = sources.length; i < len; i++) {
      source = sources[i]
      results.push({
        id: source.id,
        name: source.name,
        thumbnail: source.thumbnail.toDataUrl()
      })
    }
    return results
  })()
  if ((ref = handledRequest.webContents) != null) {
    ref.send('ELECTRON_RENDERER_DESKTOP_CAPTURER_RESULT_' + handledRequest.id, result)
  }

  // Check the queue to see whether there is other same request. If has, handle
  // it for reducing redunplicated `desktopCaptuer.startHandling` calls.
  unhandledRequestsQueue = []
  for (i = 0, len = requestsQueue.length; i < len; i++) {
    request = requestsQueue[i]
    if (deepEqual(handledRequest.options, request.options)) {
      if ((ref1 = request.webContents) != null) {
        ref1.send('ELECTRON_RENDERER_DESKTOP_CAPTURER_RESULT_' + request.id, result)
      }
    } else {
      unhandledRequestsQueue.push(request)
    }
  }
  requestsQueue = unhandledRequestsQueue

  // If the requestsQueue is not empty, start a new request handling.
  if (requestsQueue.length > 0) {
    const {captureWindow, captureScreen, thumbnailSize} = requestsQueue[0].options
    return desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize)
  }
}
'use strict'

const ipcMain = require('electron').ipcMain
const webContents = require('electron').webContents

// Doesn't exist in early initialization.
var webViewManager = null

var supportedWebViewEvents = [
  'load-commit',
  'did-finish-load',
  'did-fail-load',
  'did-frame-finish-load',
  'did-start-loading',
  'did-stop-loading',
  'did-get-response-details',
  'did-get-redirect-request',
  'dom-ready',
  'console-message',
  'devtools-opened',
  'devtools-closed',
  'devtools-focused',
  'new-window',
  'will-navigate',
  'did-navigate',
  'did-navigate-in-page',
  'close',
  'crashed',
  'gpu-crashed',
  'plugin-crashed',
  'destroyed',
  'page-title-updated',
  'page-favicon-updated',
  'enter-html-full-screen',
  'leave-html-full-screen',
  'media-started-playing',
  'media-paused',
  'found-in-page',
  'did-change-theme-color'
]

var nextInstanceId = 0
var guestInstances = {}
var embedderElementsMap = {}
var reverseEmbedderElementsMap = {}

// Moves the last element of array to the first one.
var moveLastToFirst = function (list) {
  return list.unshift(list.pop())
}

// Generate guestInstanceId.
var getNextInstanceId = function () {
  return ++nextInstanceId
}

// Create a new guest instance.
var createGuest = function (embedder, params) {
  var destroy, destroyEvents, event, fn, guest, i, id, j, len, len1, listeners
  if (webViewManager == null) {
    webViewManager = process.atomBinding('web_view_manager')
  }
  id = getNextInstanceId(embedder)
  guest = webContents.create({
    isGuest: true,
    partition: params.partition,
    embedder: embedder
  })
  guestInstances[id] = {
    guest: guest,
    embedder: embedder
  }

  // Destroy guest when the embedder is gone or navigated.
  destroyEvents = ['will-destroy', 'crashed', 'did-navigate']
  destroy = function () {
    if (guestInstances[id] != null) {
      return destroyGuest(embedder, id)
    }
  }
  for (i = 0, len = destroyEvents.length; i < len; i++) {
    event = destroyEvents[i]
    embedder.once(event, destroy)

    // Users might also listen to the crashed event, so We must ensure the guest
    // is destroyed before users' listener gets called. It is done by moving our
    // listener to the first one in queue.
    listeners = embedder._events[event]
    if (Array.isArray(listeners)) {
      moveLastToFirst(listeners)
    }
  }
  guest.once('destroyed', function () {
    var j, len1, results
    results = []
    for (j = 0, len1 = destroyEvents.length; j < len1; j++) {
      event = destroyEvents[j]
      results.push(embedder.removeListener(event, destroy))
    }
    return results
  })

  // Init guest web view after attached.
  guest.once('did-attach', function () {
    var opts
    params = this.attachParams
    delete this.attachParams
    this.viewInstanceId = params.instanceId
    this.setSize({
      normal: {
        width: params.elementWidth,
        height: params.elementHeight
      },
      enableAutoSize: params.autosize,
      min: {
        width: params.minwidth,
        height: params.minheight
      },
      max: {
        width: params.maxwidth,
        height: params.maxheight
      }
    })
    if (params.src) {
      opts = {}
      if (params.httpreferrer) {
        opts.httpReferrer = params.httpreferrer
      }
      if (params.useragent) {
        opts.userAgent = params.useragent
      }
      this.loadURL(params.src, opts)
    }
    guest.allowPopups = params.allowpopups
  })

  // Dispatch events to embedder.
  fn = function (event) {
    return guest.on(event, function (_, ...args) {
      return embedder.send.apply(embedder, ['ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-' + guest.viewInstanceId, event].concat(args))
    })
  }
  for (j = 0, len1 = supportedWebViewEvents.length; j < len1; j++) {
    event = supportedWebViewEvents[j]
    fn(event)
  }

  // Dispatch guest's IPC messages to embedder.
  guest.on('ipc-message-host', function (_, [channel, ...args]) {
    return embedder.send.apply(embedder, ['ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-' + guest.viewInstanceId, channel].concat(args))
  })

  // Autosize.
  guest.on('size-changed', function (_, ...args) {
    return embedder.send.apply(embedder, ['ELECTRON_GUEST_VIEW_INTERNAL_SIZE_CHANGED-' + guest.viewInstanceId].concat(args))
  })
  return id
}

// Attach the guest to an element of embedder.
var attachGuest = function (embedder, elementInstanceId, guestInstanceId, params) {
  var guest, key, oldGuestInstanceId, ref1, webPreferences
  guest = guestInstances[guestInstanceId].guest

  // Destroy the old guest when attaching.
  key = (embedder.getId()) + '-' + elementInstanceId
  oldGuestInstanceId = embedderElementsMap[key]
  if (oldGuestInstanceId != null) {
    // Reattachment to the same guest is not currently supported.
    if (oldGuestInstanceId === guestInstanceId) {
      return
    }
    if (guestInstances[oldGuestInstanceId] == null) {
      return
    }
    destroyGuest(embedder, oldGuestInstanceId)
  }
  webPreferences = {
    guestInstanceId: guestInstanceId,
    nodeIntegration: (ref1 = params.nodeintegration) != null ? ref1 : false,
    plugins: params.plugins,
    webSecurity: !params.disablewebsecurity,
    blinkFeatures: params.blinkfeatures
  }
  if (params.preload) {
    webPreferences.preloadURL = params.preload
  }
  webViewManager.addGuest(guestInstanceId, elementInstanceId, embedder, guest, webPreferences)
  guest.attachParams = params
  embedderElementsMap[key] = guestInstanceId
  reverseEmbedderElementsMap[guestInstanceId] = key
}

// Destroy an existing guest instance.
var destroyGuest = function (embedder, id) {
  var key
  webViewManager.removeGuest(embedder, id)
  guestInstances[id].guest.destroy()
  delete guestInstances[id]
  key = reverseEmbedderElementsMap[id]
  if (key != null) {
    delete reverseEmbedderElementsMap[id]
    return delete embedderElementsMap[key]
  }
}

ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params, requestId) {
  return event.sender.send('ELECTRON_RESPONSE_' + requestId, createGuest(event.sender, params))
})

ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, elementInstanceId, guestInstanceId, params) {
  return attachGuest(event.sender, elementInstanceId, guestInstanceId, params)
})

ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', function (event, id) {
  return destroyGuest(event.sender, id)
})

ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_SET_SIZE', function (event, id, params) {
  var ref1
  return (ref1 = guestInstances[id]) != null ? ref1.guest.setSize(params) : void 0
})

// Returns WebContents from its guest id.
exports.getGuest = function (id) {
  var ref1
  return (ref1 = guestInstances[id]) != null ? ref1.guest : void 0
}

// Returns the embedder of the guest.
exports.getEmbedder = function (id) {
  var ref1
  return (ref1 = guestInstances[id]) != null ? ref1.embedder : void 0
}
'use strict'

const ipcMain = require('electron').ipcMain
const BrowserWindow = require('electron').BrowserWindow

var hasProp = {}.hasOwnProperty
var frameToGuest = {}

// Copy attribute of |parent| to |child| if it is not defined in |child|.
var mergeOptions = function (child, parent) {
  var key, value
  for (key in parent) {
    if (!hasProp.call(parent, key)) continue
    value = parent[key]
    if (!(key in child)) {
      if (typeof value === 'object') {
        child[key] = mergeOptions({}, value)
      } else {
        child[key] = value
      }
    }
  }
  return child
}

// Merge |options| with the |embedder|'s window's options.
var mergeBrowserWindowOptions = function (embedder, options) {
  if (embedder.browserWindowOptions != null) {
    // Inherit the original options if it is a BrowserWindow.
    mergeOptions(options, embedder.browserWindowOptions)
  } else {
    // Or only inherit web-preferences if it is a webview.
    if (options.webPreferences == null) {
      options.webPreferences = {}
    }
    mergeOptions(options.webPreferences, embedder.getWebPreferences())
  }

  // Disable node integration on child window if disabled on parent window
  if (embedder.getWebPreferences().nodeIntegration === false) {
    options.webPreferences.nodeIntegration = false
  }

  return options
}

// Create a new guest created by |embedder| with |options|.
var createGuest = function (embedder, url, frameName, options) {
  var closedByEmbedder, closedByUser, guest, guestId, ref1
  guest = frameToGuest[frameName]
  if (frameName && (guest != null)) {
    guest.loadURL(url)
    return guest.id
  }

  // Remember the embedder window's id.
  if (options.webPreferences == null) {
    options.webPreferences = {}
  }
  options.webPreferences.openerId = (ref1 = BrowserWindow.fromWebContents(embedder)) != null ? ref1.id : void 0
  guest = new BrowserWindow(options)
  guest.loadURL(url)

  // When |embedder| is destroyed we should also destroy attached guest, and if
  // guest is closed by user then we should prevent |embedder| from double
  // closing guest.
  guestId = guest.id
  closedByEmbedder = function () {
    guest.removeListener('closed', closedByUser)
    return guest.destroy()
  }
  closedByUser = function () {
    embedder.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_' + guestId)
    return embedder.removeListener('render-view-deleted', closedByEmbedder)
  }
  embedder.once('render-view-deleted', closedByEmbedder)
  guest.once('closed', closedByUser)
  if (frameName) {
    frameToGuest[frameName] = guest
    guest.frameName = frameName
    guest.once('closed', function () {
      return delete frameToGuest[frameName]
    })
  }
  return guest.id
}

// Routed window.open messages.
ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function (event, url, frameName, disposition, options) {
  options = mergeBrowserWindowOptions(event.sender, options)
  event.sender.emit('new-window', event, url, frameName, disposition, options)
  if ((event.sender.isGuest() && !event.sender.allowPopups) || event.defaultPrevented) {
    event.returnValue = null
  } else {
    event.returnValue = createGuest(event.sender, url, frameName, options)
  }
})

ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', function (event, guestId) {
  var ref1
  return (ref1 = BrowserWindow.fromId(guestId)) != null ? ref1.destroy() : void 0
})

ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', function (event, guestId, method, ...args) {
  var ref1
  event.returnValue = (ref1 = BrowserWindow.fromId(guestId)) != null ? ref1[method].apply(ref1, args) : void 0
})

ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', function (event, guestId, message, targetOrigin, sourceOrigin) {
  var guestContents, ref1, ref2, sourceId
  sourceId = (ref1 = BrowserWindow.fromWebContents(event.sender)) != null ? ref1.id : void 0
  if (sourceId == null) {
    return
  }
  guestContents = (ref2 = BrowserWindow.fromId(guestId)) != null ? ref2.webContents : void 0
  if ((guestContents != null ? guestContents.getURL().indexOf(targetOrigin) : void 0) === 0 || targetOrigin === '*') {
    return guestContents != null ? guestContents.send('ELECTRON_GUEST_WINDOW_POSTMESSAGE', sourceId, message, sourceOrigin) : void 0
  }
})

ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', function (event, guestId, method, ...args) {
  var ref1, ref2
  return (ref1 = BrowserWindow.fromId(guestId)) != null ? (ref2 = ref1.webContents) != null ? ref2[method].apply(ref2, args) : void 0 : void 0
})
'use strict'

const fs = require('fs')
const path = require('path')
const util = require('util')
const Module = require('module')
const v8 = require('v8')

// We modified the original process.argv to let node.js load the atom.js,
// we need to restore it here.
process.argv.splice(1, 1)

// Clear search paths.
require('../common/reset-search-paths')

// Import common settings.
require('../common/init')

var globalPaths = Module.globalPaths

if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) {
  globalPaths.push(path.join(__dirname, 'api'))
}

// Expose public APIs.
globalPaths.push(path.join(__dirname, 'api', 'exports'))

if (process.platform === 'win32') {
  // Redirect node's console to use our own implementations, since node can not
  // handle console output when running as GUI program.
  var consoleLog = function (...args) {
    return process.log(util.format.apply(util, args) + '\n')
  }
  var streamWrite = function (chunk, encoding, callback) {
    if (Buffer.isBuffer(chunk)) {
      chunk = chunk.toString(encoding)
    }
    process.log(chunk)
    if (callback) {
      callback()
    }
    return true
  }
  console.log = console.error = console.warn = consoleLog
  process.stdout.write = process.stderr.write = streamWrite

  // Always returns EOF for stdin stream.
  var Readable = require('stream').Readable
  var stdin = new Readable()
  stdin.push(null)
  process.__defineGetter__('stdin', function () {
    return stdin
  })
}

// Don't quit on fatal error.
process.on('uncaughtException', function (error) {
  // Do nothing if the user has a custom uncaught exception handler.
  var dialog, message, ref, stack
  if (process.listeners('uncaughtException').length > 1) {
    return
  }

  // Show error in GUI.
  dialog = require('electron').dialog
  stack = (ref = error.stack) != null ? ref : error.name + ': ' + error.message
  message = 'Uncaught Exception:\n' + stack
  return dialog.showErrorBox('A JavaScript error occurred in the main process', message)
})

// Emit 'exit' event on quit.
var app = require('electron').app

app.on('quit', function (event, exitCode) {
  return process.emit('exit', exitCode)
})

if (process.platform === 'win32') {
  // If we are a Squirrel.Windows-installed app, set app user model ID
  // so that users don't have to do this.
  //
  // Squirrel packages are always of the form:
  //
  // PACKAGE-NAME
  // - Update.exe
  // - app-VERSION
  //   - OUREXE.exe
  //
  // Squirrel itself will always set the shortcut's App User Model ID to the
  // form `com.squirrel.PACKAGE-NAME.OUREXE`. We need to call
  // app.setAppUserModelId with a matching identifier so that renderer processes
  // will inherit this value.
  var updateDotExe = path.join(
    path.dirname(process.execPath),
    '..',
    'update.exe')

  if (fs.statSyncNoException(updateDotExe)) {
    var packageDir = path.dirname(path.resolve(updateDotExe))
    var packageName = path.basename(packageDir)
    var exeName = path.basename(process.execPath).replace(/\.exe$/i, '')

    app.setAppUserModelId(`com.squirrel.${packageName}.${exeName}`)
  }
}

// Map process.exit to app.exit, which quits gracefully.
process.exit = app.exit

// Load the RPC server.
require('./rpc-server')

// Load the guest view manager.
require('./guest-view-manager')

require('./guest-window-manager')

// Now we try to load app's package.json.
var packageJson = null
var searchPaths = ['app', 'app.asar', 'default_app.asar']
var i, len, packagePath
for (i = 0, len = searchPaths.length; i < len; i++) {
  packagePath = searchPaths[i]
  try {
    packagePath = path.join(process.resourcesPath, packagePath)
    packageJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json')))
    break
  } catch (error) {
    continue
  }
}

if (packageJson == null) {
  process.nextTick(function () {
    return process.exit(1)
  })
  throw new Error('Unable to find a valid app')
}

// Set application's version.
if (packageJson.version != null) {
  app.setVersion(packageJson.version)
}

// Set application's name.
if (packageJson.productName != null) {
  app.setName(packageJson.productName)
} else if (packageJson.name != null) {
  app.setName(packageJson.name)
}

// Set application's desktop name.
if (packageJson.desktopName != null) {
  app.setDesktopName(packageJson.desktopName)
} else {
  app.setDesktopName((app.getName()) + '.desktop')
}

// Set v8 flags
if (packageJson.v8Flags != null) {
  v8.setFlagsFromString(packageJson.v8Flags)
}

// Chrome 42 disables NPAPI plugins by default, reenable them here
app.commandLine.appendSwitch('enable-npapi')

// Set the user path according to application's name.
app.setPath('userData', path.join(app.getPath('appData'), app.getName()))

app.setPath('userCache', path.join(app.getPath('cache'), app.getName()))

app.setAppPath(packagePath)

// Load the chrome extension support.
require('./chrome-extension')

// Load internal desktop-capturer module.
require('./desktop-capturer')

// Set main startup script of the app.
var mainStartupScript = packageJson.main || 'index.js'

// Finally load app's main.js and transfer control to C++.
Module._load(path.join(packagePath, mainStartupScript), Module, true)
'use strict'

const v8Util = process.atomBinding('v8_util')

class ObjectsRegistry {
  constructor () {
    this.nextId = 0

    // Stores all objects by ref-counting.
    // (id) => {object, count}
    this.storage = {}

    // Stores the IDs of objects referenced by WebContents.
    // (webContentsId) => [id]
    this.owners = {}
  }

  // Register a new object and return its assigned ID. If the object is already
  // registered then the already assigned ID would be returned.
  add (webContents, obj) {
    // Get or assign an ID to the object.
    let id = this.saveToStorage(obj)

    // Add object to the set of referenced objects.
    let webContentsId = webContents.getId()
    let owner = this.owners[webContentsId]
    if (!owner) {
      owner = this.owners[webContentsId] = new Set()
      // Clear the storage when webContents is reloaded/navigated.
      webContents.once('render-view-deleted', (event, id) => {
        this.clear(id)
      })
    }
    if (!owner.has(id)) {
      owner.add(id)
      // Increase reference count if not referenced before.
      this.storage[id].count++
    }
    return id
  }

  // Get an object according to its ID.
  get (id) {
    return this.storage[id].object
  }

  // Dereference an object according to its ID.
  remove (webContentsId, id) {
    // Dereference from the storage.
    this.dereference(id)

    // Also remove the reference in owner.
    this.owners[webContentsId].delete(id)
  }

  // Clear all references to objects refrenced by the WebContents.
  clear (webContentsId) {
    let owner = this.owners[webContentsId]
    if (!owner) return

    for (let id of owner) this.dereference(id)

    delete this.owners[webContentsId]
  }

  // Private: Saves the object into storage and assigns an ID for it.
  saveToStorage (object) {
    let id = v8Util.getHiddenValue(object, 'atomId')
    if (!id) {
      id = ++this.nextId
      this.storage[id] = {
        count: 0,
        object: object
      }
      v8Util.setHiddenValue(object, 'atomId', id)
    }
    return id
  }

  // Private: Dereference the object from store.
  dereference (id) {
    let pointer = this.storage[id]
    if (pointer == null) {
      return
    }
    pointer.count -= 1
    if (pointer.count === 0) {
      v8Util.deleteHiddenValue(pointer.object, 'atomId')
      return delete this.storage[id]
    }
  }
}

module.exports = new ObjectsRegistry()
'use strict'

const electron = require('electron')
const ipcMain = electron.ipcMain
const objectsRegistry = require('./objects-registry')
const v8Util = process.atomBinding('v8_util')
const IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap

// The internal properties of Function.
const FUNCTION_PROPERTIES = [
  'length', 'name', 'arguments', 'caller', 'prototype'
]

// The remote functions in renderer processes.
// (webContentsId) => {id: Function}
let rendererFunctions = {}

// Return the description of object's members:
let getObjectMembers = function (object) {
  let names = Object.getOwnPropertyNames(object)
  // For Function, we should not override following properties even though they
  // are "own" properties.
  if (typeof object === 'function') {
    names = names.filter((name) => {
      return !FUNCTION_PROPERTIES.includes(name)
    })
  }
  // Map properties to descriptors.
  return names.map((name) => {
    let descriptor = Object.getOwnPropertyDescriptor(object, name)
    let member = {name, enumerable: descriptor.enumerable, writable: false}
    if (descriptor.get === undefined && typeof object[name] === 'function') {
      member.type = 'method'
    } else {
      if (descriptor.set || descriptor.writable) member.writable = true
      member.type = 'get'
    }
    return member
  })
}

// Return the description of object's prototype.
let getObjectPrototype = function (object) {
  let proto = Object.getPrototypeOf(object)
  if (proto === null || proto === Object.prototype) return null
  return {
    members: getObjectMembers(proto),
    proto: getObjectPrototype(proto)
  }
}

// Convert a real value into meta data.
var valueToMeta = function (sender, value, optimizeSimpleObject) {
  var el, i, len, meta
  if (optimizeSimpleObject == null) {
    optimizeSimpleObject = false
  }
  meta = {
    type: typeof value
  }
  if (Buffer.isBuffer(value)) {
    meta.type = 'buffer'
  }
  if (value === null) {
    meta.type = 'value'
  }
  if (Array.isArray(value)) {
    meta.type = 'array'
  }
  if (value instanceof Error) {
    meta.type = 'error'
  }
  if (value instanceof Date) {
    meta.type = 'date'
  }
  if ((value != null ? value.constructor.name : void 0) === 'Promise') {
    meta.type = 'promise'
  }

  // Treat simple objects as value.
  if (optimizeSimpleObject && meta.type === 'object' && v8Util.getHiddenValue(value, 'simple')) {
    meta.type = 'value'
  }

  // Treat the arguments object as array.
  if (meta.type === 'object' && (value.hasOwnProperty('callee')) && (value.length != null)) {
    meta.type = 'array'
  }
  if (meta.type === 'array') {
    meta.members = []
    for (i = 0, len = value.length; i < len; i++) {
      el = value[i]
      meta.members.push(valueToMeta(sender, el))
    }
  } else if (meta.type === 'object' || meta.type === 'function') {
    meta.name = value.constructor.name

    // Reference the original value if it's an object, because when it's
    // passed to renderer we would assume the renderer keeps a reference of
    // it.
    meta.id = objectsRegistry.add(sender, value)
    meta.members = getObjectMembers(value)
    meta.proto = getObjectPrototype(value)
  } else if (meta.type === 'buffer') {
    meta.value = Array.prototype.slice.call(value, 0)
  } else if (meta.type === 'promise') {
    meta.then = valueToMeta(sender, function (v) { value.then(v) })
  } else if (meta.type === 'error') {
    meta.members = plainObjectToMeta(value)

    // Error.name is not part of own properties.
    meta.members.push({
      name: 'name',
      value: value.name
    })
  } else if (meta.type === 'date') {
    meta.value = value.getTime()
  } else {
    meta.type = 'value'
    meta.value = value
  }
  return meta
}

// Convert object to meta by value.
var plainObjectToMeta = function (obj) {
  return Object.getOwnPropertyNames(obj).map(function (name) {
    return {
      name: name,
      value: obj[name]
    }
  })
}

// Convert Error into meta data.
var exceptionToMeta = function (error) {
  return {
    type: 'exception',
    message: error.message,
    stack: error.stack || error
  }
}

// Convert array of meta data from renderer into array of real values.
var unwrapArgs = function (sender, args) {
  var metaToValue
  metaToValue = function (meta) {
    var i, len, member, ref, returnValue
    switch (meta.type) {
      case 'value':
        return meta.value
      case 'remote-object':
        return objectsRegistry.get(meta.id)
      case 'array':
        return unwrapArgs(sender, meta.value)
      case 'buffer':
        return new Buffer(meta.value)
      case 'date':
        return new Date(meta.value)
      case 'promise':
        return Promise.resolve({
          then: metaToValue(meta.then)
        })
      case 'object': {
        let ret = {}
        Object.defineProperty(ret.constructor, 'name', { value: meta.name })

        ref = meta.members
        for (i = 0, len = ref.length; i < len; i++) {
          member = ref[i]
          ret[member.name] = metaToValue(member.value)
        }
        return ret
      }
      case 'function-with-return-value':
        returnValue = metaToValue(meta.value)
        return function () {
          return returnValue
        }
      case 'function': {
        // Cache the callbacks in renderer.
        let webContentsId = sender.getId()
        let callbacks = rendererFunctions[webContentsId]
        if (!callbacks) {
          callbacks = rendererFunctions[webContentsId] = new IDWeakMap()
          sender.once('render-view-deleted', function (event, id) {
            callbacks.clear()
            delete rendererFunctions[id]
          })
        }

        if (callbacks.has(meta.id)) return callbacks.get(meta.id)

        let callIntoRenderer = function (...args) {
          if ((webContentsId in rendererFunctions) && !sender.isDestroyed()) {
            sender.send('ELECTRON_RENDERER_CALLBACK', meta.id, valueToMeta(sender, args))
          } else {
            throw new Error(`Attempting to call a function in a renderer window that has been closed or released. Function provided here: ${meta.location}.`)
          }
        }
        v8Util.setDestructor(callIntoRenderer, function () {
          if ((webContentsId in rendererFunctions) && !sender.isDestroyed()) {
            sender.send('ELECTRON_RENDERER_RELEASE_CALLBACK', meta.id)
          }
        })
        callbacks.set(meta.id, callIntoRenderer)
        return callIntoRenderer
      }
      default:
        throw new TypeError(`Unknown type: ${meta.type}`)
    }
  }
  return args.map(metaToValue)
}

// Call a function and send reply asynchronously if it's a an asynchronous
// style function and the caller didn't pass a callback.
var callFunction = function (event, func, caller, args) {
  var funcMarkedAsync, funcName, funcPassedCallback, ref, ret
  funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous')
  funcPassedCallback = typeof args[args.length - 1] === 'function'
  try {
    if (funcMarkedAsync && !funcPassedCallback) {
      args.push(function (ret) {
        event.returnValue = valueToMeta(event.sender, ret, true)
      })
      return func.apply(caller, args)
    } else {
      ret = func.apply(caller, args)
      event.returnValue = valueToMeta(event.sender, ret, true)
    }
  } catch (error) {
    // Catch functions thrown further down in function invocation and wrap
    // them with the function name so it's easier to trace things like
    // `Error processing argument -1.`
    funcName = ((ref = func.name) != null) ? ref : 'anonymous'
    throw new Error(`Could not call remote function '${funcName}'. Check that the function signature is correct. Underlying error: ${error.message}`)
  }
}

ipcMain.on('ELECTRON_BROWSER_REQUIRE', function (event, module) {
  try {
    event.returnValue = valueToMeta(event.sender, process.mainModule.require(module))
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_GET_BUILTIN', function (event, module) {
  try {
    event.returnValue = valueToMeta(event.sender, electron[module])
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_GLOBAL', function (event, name) {
  try {
    event.returnValue = valueToMeta(event.sender, global[name])
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_CURRENT_WINDOW', function (event) {
  try {
    event.returnValue = valueToMeta(event.sender, event.sender.getOwnerBrowserWindow())
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_CURRENT_WEB_CONTENTS', function (event) {
  event.returnValue = valueToMeta(event.sender, event.sender)
})

ipcMain.on('ELECTRON_BROWSER_CONSTRUCTOR', function (event, id, args) {
  try {
    args = unwrapArgs(event.sender, args)
    let constructor = objectsRegistry.get(id)

    // Call new with array of arguments.
    // http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
    let obj = new (Function.prototype.bind.apply(constructor, [null].concat(args)))
    event.returnValue = valueToMeta(event.sender, obj)
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_FUNCTION_CALL', function (event, id, args) {
  try {
    args = unwrapArgs(event.sender, args)
    let func = objectsRegistry.get(id)
    return callFunction(event, func, global, args)
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', function (event, id, method, args) {
  try {
    args = unwrapArgs(event.sender, args)
    let constructor = objectsRegistry.get(id)[method]

    // Call new with array of arguments.
    let obj = new (Function.prototype.bind.apply(constructor, [null].concat(args)))
    event.returnValue = valueToMeta(event.sender, obj)
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_MEMBER_CALL', function (event, id, method, args) {
  try {
    args = unwrapArgs(event.sender, args)
    let obj = objectsRegistry.get(id)
    return callFunction(event, obj[method], obj, args)
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_MEMBER_SET', function (event, id, name, value) {
  try {
    let obj = objectsRegistry.get(id)
    obj[name] = value
    event.returnValue = null
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_MEMBER_GET', function (event, id, name) {
  try {
    let obj = objectsRegistry.get(id)
    event.returnValue = valueToMeta(event.sender, obj[name])
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_DEREFERENCE', function (event, id) {
  return objectsRegistry.remove(event.sender.getId(), id)
})

ipcMain.on('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', function (event, guestInstanceId) {
  try {
    let guestViewManager = require('./guest-view-manager')
    event.returnValue = valueToMeta(event.sender, guestViewManager.getGuest(guestInstanceId))
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})

ipcMain.on('ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function (event, requestId, guestInstanceId, method, ...args) {
  try {
    let guestViewManager = require('./guest-view-manager')
    let guest = guestViewManager.getGuest(guestInstanceId)
    if (requestId) {
      const responseCallback = function (result) {
        event.sender.send(`ELECTRON_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, result)
      }
      args.push(responseCallback)
    }
    guest[method].apply(guest, args)
  } catch (error) {
    event.returnValue = exceptionToMeta(error)
  }
})
'use strict'

const v8Util = process.atomBinding('v8_util')

class CallbacksRegistry {
  constructor () {
    this.nextId = 0
    this.callbacks = {}
  }

  add (callback) {
    // The callback is already added.
    var filenameAndLine, id, location, match, ref, regexp, stackString
    id = v8Util.getHiddenValue(callback, 'callbackId')
    if (id != null) {
      return id
    }
    id = ++this.nextId

    // Capture the location of the function and put it in the ID string,
    // so that release errors can be tracked down easily.
    regexp = /at (.*)/gi
    stackString = (new Error()).stack
    while ((match = regexp.exec(stackString)) !== null) {
      location = match[1]
      if (location.indexOf('(native)') !== -1) {
        continue
      }
      if (location.indexOf('electron.asar') !== -1) {
        continue
      }
      ref = /([^\/^\)]*)\)?$/gi.exec(location)
      filenameAndLine = ref[1]
      break
    }
    this.callbacks[id] = callback
    v8Util.setHiddenValue(callback, 'callbackId', id)
    v8Util.setHiddenValue(callback, 'location', filenameAndLine)
    return id
  }

  get (id) {
    var ref
    return (ref = this.callbacks[id]) != null ? ref : function () {}
  }

  call (id, ...args) {
    var ref
    return (ref = this.get(id)).call.apply(ref, [global].concat(args))
  }

  apply (id, ...args) {
    var ref
    return (ref = this.get(id)).apply.apply(ref, [global].concat(args))
  }

  remove (id) {
    return delete this.callbacks[id]
  }
}

module.exports = CallbacksRegistry
if (process.platform === 'linux' && process.type === 'renderer') {
  // On Linux we could not access clipboard in renderer process.
  module.exports = require('electron').remote.clipboard
} else {
  module.exports = process.atomBinding('clipboard')
}
'use strict'

const os = require('os')
const path = require('path')
const spawn = require('child_process').spawn
const electron = require('electron')
const binding = process.atomBinding('crash_reporter')

var CrashReporter = (function () {
  function CrashReporter () {}

  CrashReporter.prototype.start = function (options) {
    var app, args, autoSubmit, companyName, deprecate, env, extra, ignoreSystemCrashHandler, start, submitURL
    if (options == null) {
      options = {}
    }
    this.productName = options.productName
    companyName = options.companyName
    submitURL = options.submitURL
    autoSubmit = options.autoSubmit
    ignoreSystemCrashHandler = options.ignoreSystemCrashHandler
    extra = options.extra

    // Deprecated.
    deprecate = electron.deprecate
    if (options.submitUrl) {
      if (submitURL == null) {
        submitURL = options.submitUrl
      }
      deprecate.warn('submitUrl', 'submitURL')
    }
    app = (process.type === 'browser' ? electron : electron.remote).app
    if (this.productName == null) {
      this.productName = app.getName()
    }
    if (autoSubmit == null) {
      autoSubmit = true
    }
    if (ignoreSystemCrashHandler == null) {
      ignoreSystemCrashHandler = false
    }
    if (extra == null) {
      extra = {}
    }
    if (extra._productName == null) {
      extra._productName = this.productName
    }
    if (extra._companyName == null) {
      extra._companyName = companyName
    }
    if (extra._version == null) {
      extra._version = app.getVersion()
    }
    if (companyName == null) {
      deprecate.log('companyName is now a required option to crashReporter.start')
      return
    }
    if (submitURL == null) {
      deprecate.log('submitURL is now a required option to crashReporter.start')
      return
    }
    start = () => {
      binding.start(this.productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra)
    }
    if (process.platform === 'win32') {
      args = ['--reporter-url=' + submitURL, '--application-name=' + this.productName, '--v=1']
      env = {
        ATOM_SHELL_INTERNAL_CRASH_SERVICE: 1
      }
      spawn(process.execPath, args, {
        env: env,
        detached: true
      })
    }
    return start()
  }

  CrashReporter.prototype.getLastCrashReport = function () {
    var reports
    reports = this.getUploadedReports()
    if (reports.length > 0) {
      return reports[0]
    } else {
      return null
    }
  }

  CrashReporter.prototype.getUploadedReports = function () {
    var log, tmpdir
    tmpdir = process.platform === 'win32' ? os.tmpdir() : '/tmp'
    log = process.platform === 'darwin' ? path.join(tmpdir, this.productName + ' Crashes') : path.join(tmpdir, this.productName + ' Crashes', 'uploads.log')
    return binding._getUploadedReports(log)
  }

  return CrashReporter
})()

module.exports = new CrashReporter()
// Deprecate a method.
const deprecate = function (oldName, newName, fn) {
  var warned
  warned = false
  return function () {
    if (!(warned || process.noDeprecation)) {
      warned = true
      deprecate.warn(oldName, newName)
    }
    return fn.apply(this, arguments)
  }
}

// The method is renamed.
deprecate.rename = function (object, oldName, newName) {
  var newMethod, warned
  warned = false
  newMethod = function () {
    if (!(warned || process.noDeprecation)) {
      warned = true
      deprecate.warn(oldName, newName)
    }
    return this[newName].apply(this, arguments)
  }
  if (typeof object === 'function') {
    object.prototype[oldName] = newMethod
  } else {
    object[oldName] = newMethod
  }
}

// Forward the method to member.
deprecate.member = function (object, method, member) {
  var warned
  warned = false
  object.prototype[method] = function () {
    if (!(warned || process.noDeprecation)) {
      warned = true
      deprecate.warn(method, member + '.' + method)
    }
    return this[member][method].apply(this[member], arguments)
  }
}

// Deprecate a property.
deprecate.property = function (object, property, method) {
  return Object.defineProperty(object, property, {
    get: function () {
      var warned
      warned = false
      if (!(warned || process.noDeprecation)) {
        warned = true
        deprecate.warn(property + ' property', method + ' method')
      }
      return this[method]()
    }
  })
}

// Deprecate an event.
deprecate.event = function (emitter, oldName, newName, fn) {
  var warned
  warned = false
  return emitter.on(newName, function (...args) {
    // there is listeners for old API.
    if (this.listenerCount(oldName) > 0) {
      if (!(warned || process.noDeprecation)) {
        warned = true
        deprecate.warn("'" + oldName + "' event", "'" + newName + "' event")
      }
      if (fn != null) {
        return fn.apply(this, arguments)
      } else {
        return this.emit.apply(this, [oldName].concat(args))
      }
    }
  })
}

// Print deprecation warning.
deprecate.warn = function (oldName, newName) {
  return deprecate.log(oldName + ' is deprecated. Use ' + newName + ' instead.')
}

var deprecationHandler = null

// Print deprecation message.
deprecate.log = function (message) {
  if (typeof deprecationHandler === 'function') {
    deprecationHandler(message)
  } else if (process.throwDeprecation) {
    throw new Error(message)
  } else if (process.traceDeprecation) {
    return console.trace(message)
  } else {
    return console.warn('(electron) ' + message)
  }
}

deprecate.setHandler = function (handler) {
  deprecationHandler = handler
}

deprecate.getHandler = function () {
  return deprecationHandler
}

module.exports = deprecate
'use strict'

const deprecate = require('electron').deprecate

exports.setHandler = function (deprecationHandler) {
  deprecate.setHandler(deprecationHandler)
}

exports.getHandler = function () {
  return deprecate.getHandler()
}
// Do not expose the internal modules to `require`.
const hideInternalModules = function () {
  var globalPaths = require('module').globalPaths
  if (globalPaths.length === 3) {
    // Remove the "common/api/lib" and "browser-or-renderer/api/lib".
    return globalPaths.splice(0, 2)
  }
}

// Attaches properties to |exports|.
exports.defineProperties = function (exports) {
  return Object.defineProperties(exports, {
    hideInternalModules: {
      enumerable: true,
      value: hideInternalModules
    },

    // Common modules, please sort with alphabet order.
    clipboard: {
      // Must be enumerable, otherwise it woulde be invisible to remote module.
      enumerable: true,
      get: function () {
        return require('../clipboard')
      }
    },
    crashReporter: {
      enumerable: true,
      get: function () {
        return require('../crash-reporter')
      }
    },
    deprecations: {
      enumerable: true,
      get: function () {
        return require('../deprecations')
      }
    },
    nativeImage: {
      enumerable: true,
      get: function () {
        return require('../native-image')
      }
    },
    shell: {
      enumerable: true,
      get: function () {
        return require('../shell')
      }
    },

    // The internal modules, invisible unless you know their names.
    CallbacksRegistry: {
      get: function () {
        return require('../callbacks-registry')
      }
    },
    deprecate: {
      get: function () {
        return require('../deprecate')
      }
    }
  })
}
const deprecate = require('electron').deprecate
const nativeImage = process.atomBinding('native_image')

// Deprecated.
deprecate.rename(nativeImage, 'createFromDataUrl', 'createFromDataURL')

module.exports = nativeImage
module.exports = process.atomBinding('shell')
const path = require('path')
const timers = require('timers')
const Module = require('module')

process.atomBinding = function (name) {
  try {
    return process.binding('atom_' + process.type + '_' + name)
  } catch (error) {
    if (/No such module/.test(error.message)) {
      return process.binding('atom_common_' + name)
    }
  }
}

if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) {
  // Add common/api/lib to module search paths.
  Module.globalPaths.push(path.join(__dirname, 'api'))
}

// setImmediate and process.nextTick makes use of uv_check and uv_prepare to
// run the callbacks, however since we only run uv loop on requests, the
// callbacks wouldn't be called until something else activated the uv loop,
// which would delay the callbacks for arbitrary long time. So we should
// initiatively activate the uv loop once setImmediate and process.nextTick is
// called.
var wrapWithActivateUvLoop = function (func) {
  return function () {
    process.activateUvLoop()
    return func.apply(this, arguments)
  }
}

process.nextTick = wrapWithActivateUvLoop(process.nextTick)

global.setImmediate = wrapWithActivateUvLoop(timers.setImmediate)

global.clearImmediate = timers.clearImmediate

if (process.type === 'browser') {
  // setTimeout needs to update the polling timeout of the event loop, when
  // called under Chromium's event loop the node's event loop won't get a chance
  // to update the timeout, so we have to force the node's event loop to
  // recalculate the timeout in browser process.
  global.setTimeout = wrapWithActivateUvLoop(timers.setTimeout)
  global.setInterval = wrapWithActivateUvLoop(timers.setInterval)
}
const path = require('path')
const Module = require('module')

// Clear Node's global search paths.
Module.globalPaths.length = 0

// Clear current and parent(init.coffee)'s search paths.
module.paths = []

module.parent.paths = []

// Prevent Node from adding paths outside this app to search paths.
Module._nodeModulePaths = function (from) {
  var dir, i, part, parts, paths, skipOutsidePaths, splitRe, tip
  from = path.resolve(from)

  // If "from" is outside the app then we do nothing.
  skipOutsidePaths = from.startsWith(process.resourcesPath)

  // Following logoic is copied from module.js.
  splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//
  paths = []
  parts = from.split(splitRe)
  for (tip = i = parts.length - 1; i >= 0; tip = i += -1) {
    part = parts[tip]
    if (part === 'node_modules') {
      continue
    }
    dir = parts.slice(0, tip + 1).join(path.sep)
    if (skipOutsidePaths && !dir.startsWith(process.resourcesPath)) {
      break
    }
    paths.push(path.join(dir, 'node_modules'))
  }
  return paths
}
const ipcRenderer = require('electron').ipcRenderer
const nativeImage = require('electron').nativeImage

var nextId = 0
var includes = [].includes

var getNextId = function () {
  return ++nextId
}

// |options.type| can not be empty and has to include 'window' or 'screen'.
var isValid = function (options) {
  return ((options != null ? options.types : void 0) != null) && Array.isArray(options.types)
}

exports.getSources = function (options, callback) {
  var captureScreen, captureWindow, id
  if (!isValid(options)) {
    return callback(new Error('Invalid options'))
  }
  captureWindow = includes.call(options.types, 'window')
  captureScreen = includes.call(options.types, 'screen')
  if (options.thumbnailSize == null) {
    options.thumbnailSize = {
      width: 150,
      height: 150
    }
  }
  id = getNextId()
  ipcRenderer.send('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', captureWindow, captureScreen, options.thumbnailSize, id)
  return ipcRenderer.once('ELECTRON_RENDERER_DESKTOP_CAPTURER_RESULT_' + id, function (event, sources) {
    var source
    return callback(null, (function () {
      var i, len, results
      results = []
      for (i = 0, len = sources.length; i < len; i++) {
        source = sources[i]
        results.push({
          id: source.id,
          name: source.name,
          thumbnail: nativeImage.createFromDataURL(source.thumbnail)
        })
      }
      return results
    })())
  })
}
const common = require('../../../common/api/exports/electron')

// Import common modules.
common.defineProperties(exports)

Object.defineProperties(exports, {
  // Renderer side modules, please sort with alphabet order.
  desktopCapturer: {
    enumerable: true,
    get: function () {
      return require('../desktop-capturer')
    }
  },
  ipcRenderer: {
    enumerable: true,
    get: function () {
      return require('../ipc-renderer')
    }
  },
  remote: {
    enumerable: true,
    get: function () {
      return require('../remote')
    }
  },
  screen: {
    enumerable: true,
    get: function () {
      return require('../screen')
    }
  },
  webFrame: {
    enumerable: true,
    get: function () {
      return require('../web-frame')
    }
  }
})
'use strict'

const binding = process.atomBinding('ipc')
const v8Util = process.atomBinding('v8_util')

// Created by init.js.
const ipcRenderer = v8Util.getHiddenValue(global, 'ipc')

ipcRenderer.send = function (...args) {
  return binding.send('ipc-message', args)
}

ipcRenderer.sendSync = function (...args) {
  return JSON.parse(binding.sendSync('ipc-message-sync', args))
}

ipcRenderer.sendToHost = function (...args) {
  return binding.send('ipc-message-host', args)
}

module.exports = ipcRenderer
const ipcRenderer = require('electron').ipcRenderer
const deprecate = require('electron').deprecate
const EventEmitter = require('events').EventEmitter

// This module is deprecated, we mirror everything from ipcRenderer.
deprecate.warn('ipc module', 'require("electron").ipcRenderer')

// Routes events of ipcRenderer.
var ipc = new EventEmitter()

ipcRenderer.emit = function (channel, event, ...args) {
  ipc.emit.apply(ipc, [channel].concat(args))
  return EventEmitter.prototype.emit.apply(ipcRenderer, arguments)
}

// Deprecated.
for (var method in ipcRenderer) {
  if (method.startsWith('send')) {
    ipc[method] = ipcRenderer[method]
  }
}

deprecate.rename(ipc, 'sendChannel', 'send')

deprecate.rename(ipc, 'sendChannelSync', 'sendSync')

module.exports = ipc
'use strict'

const ipcRenderer = require('electron').ipcRenderer
const CallbacksRegistry = require('electron').CallbacksRegistry
const v8Util = process.atomBinding('v8_util')
const IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap

const callbacksRegistry = new CallbacksRegistry()

var includes = [].includes

var remoteObjectCache = new IDWeakMap()

// Check for circular reference.
var isCircular = function (field, visited) {
  if (typeof field === 'object') {
    if (includes.call(visited, field)) {
      return true
    }
    visited.push(field)
  }
  return false
}

// Convert the arguments object into an array of meta data.
var wrapArgs = function (args, visited) {
  var valueToMeta
  if (visited == null) {
    visited = []
  }
  valueToMeta = function (value) {
    var field, prop, ret
    if (Array.isArray(value)) {
      return {
        type: 'array',
        value: wrapArgs(value, visited)
      }
    } else if (Buffer.isBuffer(value)) {
      return {
        type: 'buffer',
        value: Array.prototype.slice.call(value, 0)
      }
    } else if (value instanceof Date) {
      return {
        type: 'date',
        value: value.getTime()
      }
    } else if ((value != null ? value.constructor.name : void 0) === 'Promise') {
      return {
        type: 'promise',
        then: valueToMeta(function (v) { value.then(v) })
      }
    } else if ((value != null) && typeof value === 'object' && v8Util.getHiddenValue(value, 'atomId')) {
      return {
        type: 'remote-object',
        id: v8Util.getHiddenValue(value, 'atomId')
      }
    } else if ((value != null) && typeof value === 'object') {
      ret = {
        type: 'object',
        name: value.constructor.name,
        members: []
      }
      for (prop in value) {
        field = value[prop]
        ret.members.push({
          name: prop,
          value: valueToMeta(isCircular(field, visited) ? null : field)
        })
      }
      return ret
    } else if (typeof value === 'function' && v8Util.getHiddenValue(value, 'returnValue')) {
      return {
        type: 'function-with-return-value',
        value: valueToMeta(value())
      }
    } else if (typeof value === 'function') {
      return {
        type: 'function',
        id: callbacksRegistry.add(value),
        location: v8Util.getHiddenValue(value, 'location')
      }
    } else {
      return {
        type: 'value',
        value: value
      }
    }
  }
  return Array.prototype.slice.call(args).map(valueToMeta)
}

// Populate object's members from descriptors.
// The |ref| will be kept referenced by |members|.
// This matches |getObjectMemebers| in rpc-server.
let setObjectMembers = function (ref, object, metaId, members) {
  for (let member of members) {
    if (object.hasOwnProperty(member.name)) continue

    let descriptor = { enumerable: member.enumerable }
    if (member.type === 'method') {
      let remoteMemberFunction = function () {
        if (this && this.constructor === remoteMemberFunction) {
          // Constructor call.
          let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(arguments))
          return metaToValue(ret)
        } else {
          // Call member function.
          let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(arguments))
          return metaToValue(ret)
        }
      }
      descriptor.get = function () {
        remoteMemberFunction.ref = ref  // The member should reference its object.
        return remoteMemberFunction
      }
      // Enable monkey-patch the method
      descriptor.set = function (value) {
        remoteMemberFunction = value
        return value
      }
      descriptor.configurable = true
    } else if (member.type === 'get') {
      descriptor.get = function () {
        return metaToValue(ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_GET', metaId, member.name))
      }

      // Only set setter when it is writable.
      if (member.writable) {
        descriptor.set = function (value) {
          ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_SET', metaId, member.name, value)
          return value
        }
      }
    }

    Object.defineProperty(object, member.name, descriptor)
  }
}

// Populate object's prototype from descriptor.
// This matches |getObjectPrototype| in rpc-server.
let setObjectPrototype = function (ref, object, metaId, descriptor) {
  if (descriptor === null) return
  let proto = {}
  setObjectMembers(ref, proto, metaId, descriptor.members)
  setObjectPrototype(ref, proto, metaId, descriptor.proto)
  Object.setPrototypeOf(object, proto)
}

// Convert meta data from browser into real value.
let metaToValue = function (meta) {
  var el, i, len, ref1, results, ret
  switch (meta.type) {
    case 'value':
      return meta.value
    case 'array':
      ref1 = meta.members
      results = []
      for (i = 0, len = ref1.length; i < len; i++) {
        el = ref1[i]
        results.push(metaToValue(el))
      }
      return results
    case 'buffer':
      return new Buffer(meta.value)
    case 'promise':
      return Promise.resolve({
        then: metaToValue(meta.then)
      })
    case 'error':
      return metaToPlainObject(meta)
    case 'date':
      return new Date(meta.value)
    case 'exception':
      throw new Error(meta.message + '\n' + meta.stack)
    default:
      if (remoteObjectCache.has(meta.id)) return remoteObjectCache.get(meta.id)

      if (meta.type === 'function') {
        // A shadow class to represent the remote function object.
        let remoteFunction = function () {
          if (this && this.constructor === remoteFunction) {
            // Constructor call.
            let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments))
            // Returning object in constructor will replace constructed object
            // with the returned object.
            // http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this
            return metaToValue(obj)
          } else {
            // Function call.
            let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments))
            return metaToValue(obj)
          }
        }
        ret = remoteFunction
      } else {
        ret = {}
      }

      // Populate delegate members.
      setObjectMembers(ret, ret, meta.id, meta.members)
      // Populate delegate prototype.
      setObjectPrototype(ret, ret, meta.id, meta.proto)

      // Set constructor.name to object's name.
      Object.defineProperty(ret.constructor, 'name', { value: meta.name })

      // Track delegate object's life time, and tell the browser to clean up
      // when the object is GCed.
      v8Util.setDestructor(ret, function () {
        ipcRenderer.send('ELECTRON_BROWSER_DEREFERENCE', meta.id)
      })

      // Remember object's id.
      v8Util.setHiddenValue(ret, 'atomId', meta.id)
      remoteObjectCache.set(meta.id, ret)
      return ret
  }
}

// Construct a plain object from the meta.
var metaToPlainObject = function (meta) {
  var i, len, obj, ref1
  obj = (function () {
    switch (meta.type) {
      case 'error':
        return new Error()
      default:
        return {}
    }
  })()
  ref1 = meta.members
  for (i = 0, len = ref1.length; i < len; i++) {
    let {name, value} = ref1[i]
    obj[name] = value
  }
  return obj
}

// Browser calls a callback in renderer.
ipcRenderer.on('ELECTRON_RENDERER_CALLBACK', function (event, id, args) {
  return callbacksRegistry.apply(id, metaToValue(args))
})

// A callback in browser is released.
ipcRenderer.on('ELECTRON_RENDERER_RELEASE_CALLBACK', function (event, id) {
  return callbacksRegistry.remove(id)
})

// List all built-in modules in browser process.
const browserModules = require('../../browser/api/exports/electron')

// And add a helper receiver for each one.
var fn = function (name) {
  return Object.defineProperty(exports, name, {
    get: function () {
      return exports.getBuiltin(name)
    }
  })
}
for (var name in browserModules) {
  fn(name)
}

// Get remote module.
exports.require = function (module) {
  return metaToValue(ipcRenderer.sendSync('ELECTRON_BROWSER_REQUIRE', module))
}

// Alias to remote.require('electron').xxx.
exports.getBuiltin = function (module) {
  return metaToValue(ipcRenderer.sendSync('ELECTRON_BROWSER_GET_BUILTIN', module))
}

// Get current BrowserWindow.
exports.getCurrentWindow = function () {
  return metaToValue(ipcRenderer.sendSync('ELECTRON_BROWSER_CURRENT_WINDOW'))
}

// Get current WebContents object.
exports.getCurrentWebContents = function () {
  return metaToValue(ipcRenderer.sendSync('ELECTRON_BROWSER_CURRENT_WEB_CONTENTS'))
}

// Get a global object in browser.
exports.getGlobal = function (name) {
  return metaToValue(ipcRenderer.sendSync('ELECTRON_BROWSER_GLOBAL', name))
}

// Get the process object in browser.
exports.__defineGetter__('process', function () {
  return exports.getGlobal('process')
})

// Create a funtion that will return the specifed value when called in browser.
exports.createFunctionWithReturnValue = function (returnValue) {
  var func
  func = function () {
    return returnValue
  }
  v8Util.setHiddenValue(func, 'returnValue', true)
  return func
}

// Get the guest WebContents from guestInstanceId.
exports.getGuestWebContents = function (guestInstanceId) {
  var meta
  meta = ipcRenderer.sendSync('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId)
  return metaToValue(meta)
}
module.exports = require('electron').remote.screen
'use strict'

const deprecate = require('electron').deprecate
const EventEmitter = require('events').EventEmitter

const webFrame = process.atomBinding('web_frame').webFrame

// webFrame is an EventEmitter.
Object.setPrototypeOf(webFrame, EventEmitter.prototype)

// Lots of webview would subscribe to webFrame's events.
webFrame.setMaxListeners(0)

// Deprecated.
deprecate.rename(webFrame, 'registerUrlSchemeAsSecure', 'registerURLSchemeAsSecure')
deprecate.rename(webFrame, 'registerUrlSchemeAsBypassingCSP', 'registerURLSchemeAsBypassingCSP')
deprecate.rename(webFrame, 'registerUrlSchemeAsPrivileged', 'registerURLSchemeAsPrivileged')

module.exports = webFrame
const url = require('url')
const chrome = window.chrome = window.chrome || {}

chrome.extension = {
  getURL: function (path) {
    return url.format({
      protocol: window.location.protocol,
      slashes: true,
      hostname: window.location.hostname,
      pathname: path
    })
  }
}
'use strict'

const events = require('events')
const path = require('path')
const Module = require('module')

// We modified the original process.argv to let node.js load the
// atom-renderer.js, we need to restore it here.
process.argv.splice(1, 1)

// Clear search paths.
require('../common/reset-search-paths')

// Import common settings.
require('../common/init')

var globalPaths = Module.globalPaths

if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) {
  globalPaths.push(path.join(__dirname, 'api'))
}

// Expose public APIs.
globalPaths.push(path.join(__dirname, 'api', 'exports'))

// The global variable will be used by ipc for event dispatching
var v8Util = process.atomBinding('v8_util')

v8Util.setHiddenValue(global, 'ipc', new events.EventEmitter())

// Use electron module after everything is ready.
const electron = require('electron')

// Call webFrame method.
electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', (event, method, args) => {
  electron.webFrame[method].apply(electron.webFrame, args)
})

electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (event, requestId, method, args) => {
  const responseCallback = function (result) {
    event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, result)
  }
  args.push(responseCallback)
  electron.webFrame[method].apply(electron.webFrame, args)
})

// Process command line arguments.
var nodeIntegration = 'false'
var preloadScript = null
for (let arg of process.argv) {
  if (arg.indexOf('--guest-instance-id=') === 0) {
    // This is a guest web view.
    process.guestInstanceId = parseInt(arg.substr(arg.indexOf('=') + 1))
  } else if (arg.indexOf('--opener-id=') === 0) {
    // This is a guest BrowserWindow.
    process.openerId = parseInt(arg.substr(arg.indexOf('=') + 1))
  } else if (arg.indexOf('--node-integration=') === 0) {
    nodeIntegration = arg.substr(arg.indexOf('=') + 1)
  } else if (arg.indexOf('--preload=') === 0) {
    preloadScript = arg.substr(arg.indexOf('=') + 1)
  }
}

if (window.location.protocol === 'chrome-devtools:') {
  // Override some inspector APIs.
  require('./inspector')
  nodeIntegration = 'true'
} else if (window.location.protocol === 'chrome-extension:') {
  // Add implementations of chrome API.
  require('./chrome-api')
  nodeIntegration = 'true'
} else {
  // Override default web functions.
  require('./override')

  // Load webview tag implementation.
  if (process.guestInstanceId == null) {
    require('./web-view/web-view')
    require('./web-view/web-view-attributes')
  }
}

if (nodeIntegration === 'true') {
  // Export node bindings to global.
  global.require = require
  global.module = module

  // Set the __filename to the path of html file if it is file: protocol.
  if (window.location.protocol === 'file:') {
    var pathname = process.platform === 'win32' && window.location.pathname[0] === '/' ? window.location.pathname.substr(1) : window.location.pathname
    global.__filename = path.normalize(decodeURIComponent(pathname))
    global.__dirname = path.dirname(global.__filename)

    // Set module's filename so relative require can work as expected.
    module.filename = global.__filename

    // Also search for module under the html file.
    module.paths = module.paths.concat(Module._nodeModulePaths(global.__dirname))
  } else {
    global.__filename = __filename
    global.__dirname = __dirname
  }

  // Redirect window.onerror to uncaughtException.
  window.onerror = function (message, filename, lineno, colno, error) {
    if (global.process.listeners('uncaughtException').length > 0) {
      global.process.emit('uncaughtException', error)
      return true
    } else {
      return false
    }
  }
} else {
  // Delete Node's symbols after the Environment has been loaded.
  process.once('loaded', function () {
    delete global.process
    delete global.setImmediate
    delete global.clearImmediate
    return delete global.global
  })
}

// Load the script specfied by the "preload" attribute.
if (preloadScript) {
  try {
    require(preloadScript)
  } catch (error) {
    if (error.code === 'MODULE_NOT_FOUND') {
      console.error('Unable to load preload script ' + preloadScript)
    } else {
      console.error(error)
      console.error(error.stack)
    }
  }
}
window.onload = function () {
  // Use menu API to show context menu.
  window.InspectorFrontendHost.showContextMenuAtPoint = createMenu

  // Use dialog API to override file chooser dialog.
  return (window.WebInspector.createFileSelectorElement = createFileSelectorElement)
}

var convertToMenuTemplate = function (items) {
  var fn, i, item, len, template
  template = []
  fn = function (item) {
    var transformed
    transformed = item.type === 'subMenu' ? {
      type: 'submenu',
      label: item.label,
      enabled: item.enabled,
      submenu: convertToMenuTemplate(item.subItems)
    } : item.type === 'separator' ? {
      type: 'separator'
    } : item.type === 'checkbox' ? {
      type: 'checkbox',
      label: item.label,
      enabled: item.enabled,
      checked: item.checked
    } : {
      type: 'normal',
      label: item.label,
      enabled: item.enabled
    }
    if (item.id != null) {
      transformed.click = function () {
        window.DevToolsAPI.contextMenuItemSelected(item.id)
        return window.DevToolsAPI.contextMenuCleared()
      }
    }
    return template.push(transformed)
  }
  for (i = 0, len = items.length; i < len; i++) {
    item = items[i]
    fn(item)
  }
  return template
}

var createMenu = function (x, y, items) {
  const remote = require('electron').remote
  const Menu = remote.Menu
  const menu = Menu.buildFromTemplate(convertToMenuTemplate(items))

  // The menu is expected to show asynchronously.
  return setTimeout(function () {
    return menu.popup(remote.getCurrentWindow())
  })
}

var showFileChooserDialog = function (callback) {
  var dialog, files, remote
  remote = require('electron').remote
  dialog = remote.dialog
  files = dialog.showOpenDialog({})
  if (files != null) {
    return callback(pathToHtml5FileObject(files[0]))
  }
}

var pathToHtml5FileObject = function (path) {
  var blob, fs
  fs = require('fs')
  blob = new Blob([fs.readFileSync(path)])
  blob.name = path
  return blob
}

var createFileSelectorElement = function (callback) {
  var fileSelectorElement
  fileSelectorElement = document.createElement('span')
  fileSelectorElement.style.display = 'none'
  fileSelectorElement.click = showFileChooserDialog.bind(this, callback)
  return fileSelectorElement
}
'use strict'

const ipcRenderer = require('electron').ipcRenderer
const remote = require('electron').remote

// Helper function to resolve relative url.
var a = window.top.document.createElement('a')
var resolveURL = function (url) {
  a.href = url
  return a.href
}

// Window object returned by "window.open".
var BrowserWindowProxy = (function () {
  BrowserWindowProxy.proxies = {}

  BrowserWindowProxy.getOrCreate = function (guestId) {
    var base
    return (base = this.proxies)[guestId] != null ? base[guestId] : base[guestId] = new BrowserWindowProxy(guestId)
  }

  BrowserWindowProxy.remove = function (guestId) {
    return delete this.proxies[guestId]
  }

  function BrowserWindowProxy (guestId1) {
    this.guestId = guestId1
    this.closed = false
    ipcRenderer.once('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_' + this.guestId, () => {
      BrowserWindowProxy.remove(this.guestId)
      this.closed = true
    })
  }

  BrowserWindowProxy.prototype.close = function () {
    return ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', this.guestId)
  }

  BrowserWindowProxy.prototype.focus = function () {
    return ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'focus')
  }

  BrowserWindowProxy.prototype.blur = function () {
    return ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'blur')
  }

  Object.defineProperty(BrowserWindowProxy.prototype, 'location', {
    get: function () {
      return ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'getURL')
    },
    set: function (url) {
      return ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'loadURL', url)
    }
  })

  BrowserWindowProxy.prototype.postMessage = function (message, targetOrigin) {
    if (targetOrigin == null) {
      targetOrigin = '*'
    }
    return ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', this.guestId, message, targetOrigin, window.location.origin)
  }

  BrowserWindowProxy.prototype['eval'] = function (...args) {
    return ipcRenderer.send.apply(ipcRenderer, ['ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'executeJavaScript'].concat(args))
  }

  return BrowserWindowProxy
})()

if (process.guestInstanceId == null) {
  // Override default window.close.
  window.close = function () {
    return remote.getCurrentWindow().close()
  }
}

// Make the browser window or guest view emit "new-window" event.
window.open = function (url, frameName, features) {
  var feature, guestId, i, j, len, len1, name, options, ref1, ref2, value
  if (frameName == null) {
    frameName = ''
  }
  if (features == null) {
    features = ''
  }
  options = {}

  // TODO remove hyphenated options in both of the following arrays for 1.0
  const ints = ['x', 'y', 'width', 'height', 'min-width', 'minWidth', 'max-width', 'maxWidth', 'min-height', 'minHeight', 'max-height', 'maxHeight', 'zoom-factor', 'zoomFactor']
  const webPreferences = ['zoom-factor', 'zoomFactor', 'node-integration', 'nodeIntegration', 'preload']
  const disposition = 'new-window'

  // Make sure to get rid of excessive whitespace in the property name
  ref1 = features.split(/,\s*/)
  for (i = 0, len = ref1.length; i < len; i++) {
    feature = ref1[i]
    ref2 = feature.split(/\s*=/)
    name = ref2[0]
    value = ref2[1]
    value = value === 'yes' || value === '1' ? true : value === 'no' || value === '0' ? false : value
    if (webPreferences.includes(name)) {
      if (options.webPreferences == null) {
        options.webPreferences = {}
      }
      options.webPreferences[name] = value
    } else {
      options[name] = value
    }
  }
  if (options.left) {
    if (options.x == null) {
      options.x = options.left
    }
  }
  if (options.top) {
    if (options.y == null) {
      options.y = options.top
    }
  }
  if (options.title == null) {
    options.title = frameName
  }
  if (options.width == null) {
    options.width = 800
  }
  if (options.height == null) {
    options.height = 600
  }

  // Resolve relative urls.
  url = resolveURL(url)
  for (j = 0, len1 = ints.length; j < len1; j++) {
    name = ints[j]
    if (options[name] != null) {
      options[name] = parseInt(options[name], 10)
    }
  }
  guestId = ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', url, frameName, disposition, options)
  if (guestId) {
    return BrowserWindowProxy.getOrCreate(guestId)
  } else {
    return null
  }
}

// Use the dialog API to implement alert().
window.alert = function (message, title) {
  var buttons
  if (arguments.length === 0) {
    message = ''
  }
  if (title == null) {
    title = ''
  }
  buttons = ['OK']
  message = String(message)
  remote.dialog.showMessageBox(remote.getCurrentWindow(), {
    message: message,
    title: title,
    buttons: buttons
  })
}

// And the confirm().
window.confirm = function (message, title) {
  var buttons, cancelId
  if (title == null) {
    title = ''
  }
  buttons = ['OK', 'Cancel']
  cancelId = 1
  return !remote.dialog.showMessageBox(remote.getCurrentWindow(), {
    message: message,
    title: title,
    buttons: buttons,
    cancelId: cancelId
  })
}

// But we do not support prompt().
window.prompt = function () {
  throw new Error('prompt() is and will not be supported.')
}

if (process.openerId != null) {
  window.opener = BrowserWindowProxy.getOrCreate(process.openerId)
}

ipcRenderer.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (event, sourceId, message, sourceOrigin) {
  // Manually dispatch event instead of using postMessage because we also need to
  // set event.source.
  event = document.createEvent('Event')
  event.initEvent('message', false, false)
  event.data = message
  event.origin = sourceOrigin
  event.source = BrowserWindowProxy.getOrCreate(sourceId)
  return window.dispatchEvent(event)
})

// Forward history operations to browser.
var sendHistoryOperation = function (...args) {
  return ipcRenderer.send.apply(ipcRenderer, ['ELECTRON_NAVIGATION_CONTROLLER'].concat(args))
}

var getHistoryOperation = function (...args) {
  return ipcRenderer.sendSync.apply(ipcRenderer, ['ELECTRON_SYNC_NAVIGATION_CONTROLLER'].concat(args))
}

window.history.back = function () {
  return sendHistoryOperation('goBack')
}

window.history.forward = function () {
  return sendHistoryOperation('goForward')
}

window.history.go = function (offset) {
  return sendHistoryOperation('goToOffset', offset)
}

Object.defineProperty(window.history, 'length', {
  get: function () {
    return getHistoryOperation('length')
  }
})

// The initial visibilityState.
let cachedVisibilityState = process.argv.includes('--hidden-page') ? 'hidden' : 'visible'

// Subscribe to visibilityState changes.
ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, visibilityState) {
  if (cachedVisibilityState !== visibilityState) {
    cachedVisibilityState = visibilityState
    document.dispatchEvent(new Event('visibilitychange'))
  }
})

// Make document.hidden and document.visibilityState return the correct value.
Object.defineProperty(document, 'hidden', {
  get: function () {
    return cachedVisibilityState !== 'visible'
  }
})

Object.defineProperty(document, 'visibilityState', {
  get: function () {
    return cachedVisibilityState
  }
})
'use strict'

const ipcRenderer = require('electron').ipcRenderer
const webFrame = require('electron').webFrame

var requestId = 0

var WEB_VIEW_EVENTS = {
  'load-commit': ['url', 'isMainFrame'],
  'did-finish-load': [],
  'did-fail-load': ['errorCode', 'errorDescription', 'validatedURL', 'isMainFrame'],
  'did-frame-finish-load': ['isMainFrame'],
  'did-start-loading': [],
  'did-stop-loading': [],
  'did-get-response-details': ['status', 'newURL', 'originalURL', 'httpResponseCode', 'requestMethod', 'referrer', 'headers', 'resourceType'],
  'did-get-redirect-request': ['oldURL', 'newURL', 'isMainFrame'],
  'dom-ready': [],
  'console-message': ['level', 'message', 'line', 'sourceId'],
  'devtools-opened': [],
  'devtools-closed': [],
  'devtools-focused': [],
  'new-window': ['url', 'frameName', 'disposition', 'options'],
  'will-navigate': ['url'],
  'did-navigate': ['url'],
  'did-navigate-in-page': ['url'],
  'close': [],
  'crashed': [],
  'gpu-crashed': [],
  'plugin-crashed': ['name', 'version'],
  'media-started-playing': [],
  'media-paused': [],
  'did-change-theme-color': ['themeColor'],
  'destroyed': [],
  'page-title-updated': ['title', 'explicitSet'],
  'page-favicon-updated': ['favicons'],
  'enter-html-full-screen': [],
  'leave-html-full-screen': [],
  'found-in-page': ['result']
}

var DEPRECATED_EVENTS = {
  'page-title-updated': 'page-title-set'
}

var dispatchEvent = function (webView, eventName, eventKey, ...args) {
  var domEvent, f, i, j, len, ref1
  if (DEPRECATED_EVENTS[eventName] != null) {
    dispatchEvent.apply(null, [webView, DEPRECATED_EVENTS[eventName], eventKey].concat(args))
  }
  domEvent = new Event(eventName)
  ref1 = WEB_VIEW_EVENTS[eventKey]
  for (i = j = 0, len = ref1.length; j < len; i = ++j) {
    f = ref1[i]
    domEvent[f] = args[i]
  }
  webView.dispatchEvent(domEvent)
  if (eventName === 'load-commit') {
    return webView.onLoadCommit(domEvent)
  }
}

module.exports = {
  registerEvents: function (webView, viewInstanceId) {
    ipcRenderer.on('ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-' + viewInstanceId, function (event, eventName, ...args) {
      return dispatchEvent.apply(null, [webView, eventName, eventName].concat(args))
    })

    ipcRenderer.on('ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-' + viewInstanceId, function (event, channel, ...args) {
      var domEvent = new Event('ipc-message')
      domEvent.channel = channel
      domEvent.args = args
      return webView.dispatchEvent(domEvent)
    })

    return ipcRenderer.on('ELECTRON_GUEST_VIEW_INTERNAL_SIZE_CHANGED-' + viewInstanceId, function (event, ...args) {
      var domEvent, f, i, j, len, ref1
      domEvent = new Event('size-changed')
      ref1 = ['oldWidth', 'oldHeight', 'newWidth', 'newHeight']
      for (i = j = 0, len = ref1.length; j < len; i = ++j) {
        f = ref1[i]
        domEvent[f] = args[i]
      }
      return webView.onSizeChanged(domEvent)
    })
  },
  deregisterEvents: function (viewInstanceId) {
    ipcRenderer.removeAllListeners('ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-' + viewInstanceId)
    ipcRenderer.removeAllListeners('ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-' + viewInstanceId)
    return ipcRenderer.removeAllListeners('ELECTRON_GUEST_VIEW_INTERNAL_SIZE_CHANGED-' + viewInstanceId)
  },
  createGuest: function (params, callback) {
    requestId++
    ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', params, requestId)
    return ipcRenderer.once('ELECTRON_RESPONSE_' + requestId, callback)
  },
  attachGuest: function (elementInstanceId, guestInstanceId, params) {
    ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params)
    return webFrame.attachGuest(elementInstanceId)
  },
  destroyGuest: function (guestInstanceId) {
    return ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId)
  },
  setSize: function (guestInstanceId, params) {
    return ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_SET_SIZE', guestInstanceId, params)
  }
}
'use strict'

const WebViewImpl = require('./web-view')
const guestViewInternal = require('./guest-view-internal')
const webViewConstants = require('./web-view-constants')
const remote = require('electron').remote

// Helper function to resolve url set in attribute.
var a = document.createElement('a')

var resolveURL = function (url) {
  a.href = url
  return a.href
}

// Attribute objects.
// Default implementation of a WebView attribute.
class WebViewAttribute {
  constructor (name, webViewImpl) {
    this.name = name
    this.value = webViewImpl.webviewNode[name] || ''
    this.webViewImpl = webViewImpl
    this.ignoreMutation = false
    this.defineProperty()
  }

  // Retrieves and returns the attribute's value.
  getValue () {
    return this.webViewImpl.webviewNode.getAttribute(this.name) || this.value
  }

  // Sets the attribute's value.
  setValue (value) {
    return this.webViewImpl.webviewNode.setAttribute(this.name, value || '')
  }

  // Changes the attribute's value without triggering its mutation handler.
  setValueIgnoreMutation (value) {
    this.ignoreMutation = true
    this.setValue(value)
    this.ignoreMutation = false
  }

  // Defines this attribute as a property on the webview node.
  defineProperty () {
    return Object.defineProperty(this.webViewImpl.webviewNode, this.name, {
      get: () => {
        return this.getValue()
      },
      set: (value) => {
        return this.setValue(value)
      },
      enumerable: true
    })
  }

  // Called when the attribute's value changes.
  handleMutation () {}
}

// An attribute that is treated as a Boolean.
class BooleanAttribute extends WebViewAttribute {
  getValue () {
    return this.webViewImpl.webviewNode.hasAttribute(this.name)
  }

  setValue (value) {
    if (!value) {
      return this.webViewImpl.webviewNode.removeAttribute(this.name)
    } else {
      return this.webViewImpl.webviewNode.setAttribute(this.name, '')
    }
  }
}

// Attribute used to define the demension limits of autosizing.
class AutosizeDimensionAttribute extends WebViewAttribute {
  getValue () {
    return parseInt(this.webViewImpl.webviewNode.getAttribute(this.name)) || 0
  }

  handleMutation () {
    if (!this.webViewImpl.guestInstanceId) {
      return
    }
    return guestViewInternal.setSize(this.webViewImpl.guestInstanceId, {
      enableAutoSize: this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue(),
      min: {
        width: parseInt(this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0),
        height: parseInt(this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0)
      },
      max: {
        width: parseInt(this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0),
        height: parseInt(this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0)
      }
    })
  }
}

// Attribute that specifies whether the webview should be autosized.
class AutosizeAttribute extends BooleanAttribute {
  constructor (webViewImpl) {
    super(webViewConstants.ATTRIBUTE_AUTOSIZE, webViewImpl)
  }
}

AutosizeAttribute.prototype.handleMutation = AutosizeDimensionAttribute.prototype.handleMutation

// Attribute representing the state of the storage partition.
class PartitionAttribute extends WebViewAttribute {
  constructor (webViewImpl) {
    super(webViewConstants.ATTRIBUTE_PARTITION, webViewImpl)
    this.validPartitionId = true
  }

  handleMutation (oldValue, newValue) {
    newValue = newValue || ''

    // The partition cannot change if the webview has already navigated.
    if (!this.webViewImpl.beforeFirstNavigation) {
      window.console.error(webViewConstants.ERROR_MSG_ALREADY_NAVIGATED)
      this.setValueIgnoreMutation(oldValue)
      return
    }
    if (newValue === 'persist:') {
      this.validPartitionId = false
      return window.console.error(webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE)
    }
  }
}

// Attribute that handles the location and navigation of the webview.
class SrcAttribute extends WebViewAttribute {
  constructor (webViewImpl) {
    super(webViewConstants.ATTRIBUTE_SRC, webViewImpl)
    this.setupMutationObserver()
  }

  getValue () {
    if (this.webViewImpl.webviewNode.hasAttribute(this.name)) {
      return resolveURL(this.webViewImpl.webviewNode.getAttribute(this.name))
    } else {
      return this.value
    }
  }

  setValueIgnoreMutation (value) {
    super.setValueIgnoreMutation(value)

    // takeRecords() is needed to clear queued up src mutations. Without it, it
    // is possible for this change to get picked up asyncronously by src's
    // mutation observer |observer|, and then get handled even though we do not
    // want to handle this mutation.
    return this.observer.takeRecords()
  }

  handleMutation (oldValue, newValue) {
    // Once we have navigated, we don't allow clearing the src attribute.
    // Once <webview> enters a navigated state, it cannot return to a
    // placeholder state.
    if (!newValue && oldValue) {
      // src attribute changes normally initiate a navigation. We suppress
      // the next src attribute handler call to avoid reloading the page
      // on every guest-initiated navigation.
      this.setValueIgnoreMutation(oldValue)
      return
    }
    return this.parse()
  }

  // The purpose of this mutation observer is to catch assignment to the src
  // attribute without any changes to its value. This is useful in the case
  // where the webview guest has crashed and navigating to the same address
  // spawns off a new process.
  setupMutationObserver () {
    var params
    this.observer = new MutationObserver((mutations) => {
      var i, len, mutation, newValue, oldValue
      for (i = 0, len = mutations.length; i < len; i++) {
        mutation = mutations[i]
        oldValue = mutation.oldValue
        newValue = this.getValue()
        if (oldValue !== newValue) {
          return
        }
        this.handleMutation(oldValue, newValue)
      }
    })
    params = {
      attributes: true,
      attributeOldValue: true,
      attributeFilter: [this.name]
    }
    return this.observer.observe(this.webViewImpl.webviewNode, params)
  }

  parse () {
    var guestContents, httpreferrer, opts, useragent
    if (!this.webViewImpl.elementAttached || !this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId || !this.getValue()) {
      return
    }
    if (this.webViewImpl.guestInstanceId == null) {
      if (this.webViewImpl.beforeFirstNavigation) {
        this.webViewImpl.beforeFirstNavigation = false
        this.webViewImpl.createGuest()
      }
      return
    }

    // Navigate to |this.src|.
    opts = {}
    httpreferrer = this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue()
    if (httpreferrer) {
      opts.httpReferrer = httpreferrer
    }
    useragent = this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_USERAGENT].getValue()
    if (useragent) {
      opts.userAgent = useragent
    }
    guestContents = remote.getGuestWebContents(this.webViewImpl.guestInstanceId)
    return guestContents.loadURL(this.getValue(), opts)
  }
}

// Attribute specifies HTTP referrer.
class HttpReferrerAttribute extends WebViewAttribute {
  constructor (webViewImpl) {
    super(webViewConstants.ATTRIBUTE_HTTPREFERRER, webViewImpl)
  }
}

// Attribute specifies user agent
class UserAgentAttribute extends WebViewAttribute {
  constructor (webViewImpl) {
    super(webViewConstants.ATTRIBUTE_USERAGENT, webViewImpl)
  }
}

// Attribute that set preload script.
class PreloadAttribute extends WebViewAttribute {
  constructor (webViewImpl) {
    super(webViewConstants.ATTRIBUTE_PRELOAD, webViewImpl)
  }

  getValue () {
    var preload, protocol
    if (!this.webViewImpl.webviewNode.hasAttribute(this.name)) {
      return this.value
    }
    preload = resolveURL(this.webViewImpl.webviewNode.getAttribute(this.name))
    protocol = preload.substr(0, 5)
    if (protocol !== 'file:') {
      console.error(webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE)
      preload = ''
    }
    return preload
  }
}

// Attribute that specifies the blink features to be enabled.
class BlinkFeaturesAttribute extends WebViewAttribute {
  constructor (webViewImpl) {
    super(webViewConstants.ATTRIBUTE_BLINKFEATURES, webViewImpl)
  }
}

// Sets up all of the webview attributes.
WebViewImpl.prototype.setupWebViewAttributes = function () {
  this.attributes = {}
  this.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE] = new AutosizeAttribute(this)
  this.attributes[webViewConstants.ATTRIBUTE_PARTITION] = new PartitionAttribute(this)
  this.attributes[webViewConstants.ATTRIBUTE_SRC] = new SrcAttribute(this)
  this.attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this)
  this.attributes[webViewConstants.ATTRIBUTE_USERAGENT] = new UserAgentAttribute(this)
  this.attributes[webViewConstants.ATTRIBUTE_NODEINTEGRATION] = new BooleanAttribute(webViewConstants.ATTRIBUTE_NODEINTEGRATION, this)
  this.attributes[webViewConstants.ATTRIBUTE_PLUGINS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_PLUGINS, this)
  this.attributes[webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY] = new BooleanAttribute(webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY, this)
  this.attributes[webViewConstants.ATTRIBUTE_ALLOWPOPUPS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_ALLOWPOPUPS, this)
  this.attributes[webViewConstants.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this)
  this.attributes[webViewConstants.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this)

  const autosizeAttributes = [webViewConstants.ATTRIBUTE_MAXHEIGHT, webViewConstants.ATTRIBUTE_MAXWIDTH, webViewConstants.ATTRIBUTE_MINHEIGHT, webViewConstants.ATTRIBUTE_MINWIDTH]
  autosizeAttributes.forEach((attribute) => {
    this.attributes[attribute] = new AutosizeDimensionAttribute(attribute, this)
  })
}
module.exports = {
  // Attributes.
  ATTRIBUTE_AUTOSIZE: 'autosize',
  ATTRIBUTE_MAXHEIGHT: 'maxheight',
  ATTRIBUTE_MAXWIDTH: 'maxwidth',
  ATTRIBUTE_MINHEIGHT: 'minheight',
  ATTRIBUTE_MINWIDTH: 'minwidth',
  ATTRIBUTE_NAME: 'name',
  ATTRIBUTE_PARTITION: 'partition',
  ATTRIBUTE_SRC: 'src',
  ATTRIBUTE_HTTPREFERRER: 'httpreferrer',
  ATTRIBUTE_NODEINTEGRATION: 'nodeintegration',
  ATTRIBUTE_PLUGINS: 'plugins',
  ATTRIBUTE_DISABLEWEBSECURITY: 'disablewebsecurity',
  ATTRIBUTE_ALLOWPOPUPS: 'allowpopups',
  ATTRIBUTE_PRELOAD: 'preload',
  ATTRIBUTE_USERAGENT: 'useragent',
  ATTRIBUTE_BLINKFEATURES: 'blinkfeatures',

  // Internal attribute.
  ATTRIBUTE_INTERNALINSTANCEID: 'internalinstanceid',

  // Error messages.
  ERROR_MSG_ALREADY_NAVIGATED: 'The object has already navigated, so its partition cannot be changed.',
  ERROR_MSG_CANNOT_INJECT_SCRIPT: '<webview>: ' + 'Script cannot be injected into content until the page has loaded.',
  ERROR_MSG_INVALID_PARTITION_ATTRIBUTE: 'Invalid partition attribute.',
  ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE: 'Only "file:" protocol is supported in "preload" attribute.'
}
'use strict'

const deprecate = require('electron').deprecate
const webFrame = require('electron').webFrame
const remote = require('electron').remote
const ipcRenderer = require('electron').ipcRenderer

const v8Util = process.atomBinding('v8_util')
const guestViewInternal = require('./guest-view-internal')
const webViewConstants = require('./web-view-constants')

var hasProp = {}.hasOwnProperty

// ID generator.
var nextId = 0

var getNextId = function () {
  return ++nextId
}

// Represents the internal state of the WebView node.
var WebViewImpl = (function () {
  function WebViewImpl (webviewNode) {
    var shadowRoot
    this.webviewNode = webviewNode
    v8Util.setHiddenValue(this.webviewNode, 'internal', this)
    this.attached = false
    this.elementAttached = false
    this.beforeFirstNavigation = true

    // on* Event handlers.
    this.on = {}
    this.browserPluginNode = this.createBrowserPluginNode()
    shadowRoot = this.webviewNode.createShadowRoot()
    shadowRoot.innerHTML = '<style>:host { display: flex; }</style>'
    this.setupWebViewAttributes()
    this.setupFocusPropagation()
    this.viewInstanceId = getNextId()
    shadowRoot.appendChild(this.browserPluginNode)

    // Subscribe to host's zoom level changes.
    this.onZoomLevelChanged = (zoomLevel) => {
      this.webviewNode.setZoomLevel(zoomLevel)
    }
    webFrame.on('zoom-level-changed', this.onZoomLevelChanged)
  }

  WebViewImpl.prototype.createBrowserPluginNode = function () {
    // We create BrowserPlugin as a custom element in order to observe changes
    // to attributes synchronously.
    var browserPluginNode
    browserPluginNode = new WebViewImpl.BrowserPlugin()
    v8Util.setHiddenValue(browserPluginNode, 'internal', this)
    return browserPluginNode
  }

  // Resets some state upon reattaching <webview> element to the DOM.
  WebViewImpl.prototype.reset = function () {
    // Unlisten the zoom-level-changed event.
    webFrame.removeListener('zoom-level-changed', this.onZoomLevelChanged)

    // If guestInstanceId is defined then the <webview> has navigated and has
    // already picked up a partition ID. Thus, we need to reset the initialization
    // state. However, it may be the case that beforeFirstNavigation is false BUT
    // guestInstanceId has yet to be initialized. This means that we have not
    // heard back from createGuest yet. We will not reset the flag in this case so
    // that we don't end up allocating a second guest.
    if (this.guestInstanceId) {
      guestViewInternal.destroyGuest(this.guestInstanceId)
      this.webContents = null
      this.guestInstanceId = void 0
      this.beforeFirstNavigation = true
      this.attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId = true
    }
    this.internalInstanceId = 0
  }

  // Sets the <webview>.request property.
  WebViewImpl.prototype.setRequestPropertyOnWebViewNode = function (request) {
    return Object.defineProperty(this.webviewNode, 'request', {
      value: request,
      enumerable: true
    })
  }

  WebViewImpl.prototype.setupFocusPropagation = function () {
    if (!this.webviewNode.hasAttribute('tabIndex')) {
      // <webview> needs a tabIndex in order to be focusable.
      // TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute
      // to allow <webview> to be focusable.
      // See http://crbug.com/231664.
      this.webviewNode.setAttribute('tabIndex', -1)
    }

    // Focus the BrowserPlugin when the <webview> takes focus.
    this.webviewNode.addEventListener('focus', () => {
      this.browserPluginNode.focus()
    })

    // Blur the BrowserPlugin when the <webview> loses focus.
    this.webviewNode.addEventListener('blur', () => {
      this.browserPluginNode.blur()
    })
  }

  // This observer monitors mutations to attributes of the <webview> and
  // updates the BrowserPlugin properties accordingly. In turn, updating
  // a BrowserPlugin property will update the corresponding BrowserPlugin
  // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more
  // details.
  WebViewImpl.prototype.handleWebviewAttributeMutation = function (attributeName, oldValue, newValue) {
    if (!this.attributes[attributeName] || this.attributes[attributeName].ignoreMutation) {
      return
    }

    // Let the changed attribute handle its own mutation
    return this.attributes[attributeName].handleMutation(oldValue, newValue)
  }

  WebViewImpl.prototype.handleBrowserPluginAttributeMutation = function (attributeName, oldValue, newValue) {
    if (attributeName === webViewConstants.ATTRIBUTE_INTERNALINSTANCEID && !oldValue && !!newValue) {
      this.browserPluginNode.removeAttribute(webViewConstants.ATTRIBUTE_INTERNALINSTANCEID)
      this.internalInstanceId = parseInt(newValue)

      // Track when the element resizes using the element resize callback.
      webFrame.registerElementResizeCallback(this.internalInstanceId, this.onElementResize.bind(this))
      if (!this.guestInstanceId) {
        return
      }
      return guestViewInternal.attachGuest(this.internalInstanceId, this.guestInstanceId, this.buildParams())
    }
  }

  WebViewImpl.prototype.onSizeChanged = function (webViewEvent) {
    var maxHeight, maxWidth, minHeight, minWidth, newHeight, newWidth, node, width
    newWidth = webViewEvent.newWidth
    newHeight = webViewEvent.newHeight
    node = this.webviewNode
    width = node.offsetWidth

    // Check the current bounds to make sure we do not resize <webview>
    // outside of current constraints.
    maxWidth = this.attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() | width
    maxHeight = this.attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() | width
    minWidth = this.attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() | width
    minHeight = this.attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() | width
    minWidth = Math.min(minWidth, maxWidth)
    minHeight = Math.min(minHeight, maxHeight)
    if (!this.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() || (newWidth >= minWidth && newWidth <= maxWidth && newHeight >= minHeight && newHeight <= maxHeight)) {
      node.style.width = newWidth + 'px'
      node.style.height = newHeight + 'px'

      // Only fire the DOM event if the size of the <webview> has actually
      // changed.
      return this.dispatchEvent(webViewEvent)
    }
  }

  WebViewImpl.prototype.onElementResize = function (newSize) {
    // Dispatch the 'resize' event.
    var resizeEvent
    resizeEvent = new Event('resize', {
      bubbles: true
    })
    resizeEvent.newWidth = newSize.width
    resizeEvent.newHeight = newSize.height
    this.dispatchEvent(resizeEvent)
    if (this.guestInstanceId) {
      return guestViewInternal.setSize(this.guestInstanceId, {
        normal: newSize
      })
    }
  }

  WebViewImpl.prototype.createGuest = function () {
    return guestViewInternal.createGuest(this.buildParams(), (event, guestInstanceId) => {
      this.attachWindow(guestInstanceId)
    })
  }

  WebViewImpl.prototype.dispatchEvent = function (webViewEvent) {
    return this.webviewNode.dispatchEvent(webViewEvent)
  }

  // Adds an 'on<event>' property on the webview, which can be used to set/unset
  // an event handler.
  WebViewImpl.prototype.setupEventProperty = function (eventName) {
    var propertyName
    propertyName = 'on' + eventName.toLowerCase()
    return Object.defineProperty(this.webviewNode, propertyName, {
      get: () => {
        return this.on[propertyName]
      },
      set: (value) => {
        if (this.on[propertyName]) {
          this.webviewNode.removeEventListener(eventName, this.on[propertyName])
        }
        this.on[propertyName] = value
        if (value) {
          return this.webviewNode.addEventListener(eventName, value)
        }
      },
      enumerable: true
    })
  }

  // Updates state upon loadcommit.
  WebViewImpl.prototype.onLoadCommit = function (webViewEvent) {
    var newValue, oldValue
    oldValue = this.webviewNode.getAttribute(webViewConstants.ATTRIBUTE_SRC)
    newValue = webViewEvent.url
    if (webViewEvent.isMainFrame && (oldValue !== newValue)) {
      // Touching the src attribute triggers a navigation. To avoid
      // triggering a page reload on every guest-initiated navigation,
      // we do not handle this mutation.
      return this.attributes[webViewConstants.ATTRIBUTE_SRC].setValueIgnoreMutation(newValue)
    }
  }

  WebViewImpl.prototype.onAttach = function (storagePartitionId) {
    return this.attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue(storagePartitionId)
  }

  WebViewImpl.prototype.buildParams = function () {
    var attribute, attributeName, css, elementRect, params, ref1
    params = {
      instanceId: this.viewInstanceId,
      userAgentOverride: this.userAgentOverride
    }
    ref1 = this.attributes
    for (attributeName in ref1) {
      if (!hasProp.call(ref1, attributeName)) continue
      attribute = ref1[attributeName]
      params[attributeName] = attribute.getValue()
    }

    // When the WebView is not participating in layout (display:none)
    // then getBoundingClientRect() would report a width and height of 0.
    // However, in the case where the WebView has a fixed size we can
    // use that value to initially size the guest so as to avoid a relayout of
    // the on display:block.
    css = window.getComputedStyle(this.webviewNode, null)
    elementRect = this.webviewNode.getBoundingClientRect()
    params.elementWidth = parseInt(elementRect.width) || parseInt(css.getPropertyValue('width'))
    params.elementHeight = parseInt(elementRect.height) || parseInt(css.getPropertyValue('height'))
    return params
  }

  WebViewImpl.prototype.attachWindow = function (guestInstanceId) {
    this.guestInstanceId = guestInstanceId
    this.webContents = remote.getGuestWebContents(this.guestInstanceId)
    if (!this.internalInstanceId) {
      return true
    }
    return guestViewInternal.attachGuest(this.internalInstanceId, this.guestInstanceId, this.buildParams())
  }

  return WebViewImpl
})()

// Registers browser plugin <object> custom element.
var registerBrowserPluginElement = function () {
  var proto
  proto = Object.create(HTMLObjectElement.prototype)
  proto.createdCallback = function () {
    this.setAttribute('type', 'application/browser-plugin')
    this.setAttribute('id', 'browser-plugin-' + getNextId())

    // The <object> node fills in the <webview> container.
    this.style.flex = '1 1 auto'
  }
  proto.attributeChangedCallback = function (name, oldValue, newValue) {
    var internal
    internal = v8Util.getHiddenValue(this, 'internal')
    if (!internal) {
      return
    }
    return internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue)
  }
  proto.attachedCallback = function () {
    // Load the plugin immediately.
    return this.nonExistentAttribute
  }
  WebViewImpl.BrowserPlugin = webFrame.registerEmbedderCustomElement('browserplugin', {
    'extends': 'object',
    prototype: proto
  })
  delete proto.createdCallback
  delete proto.attachedCallback
  delete proto.detachedCallback
  return delete proto.attributeChangedCallback
}

// Registers <webview> custom element.
var registerWebViewElement = function () {
  var createBlockHandler, createNonBlockHandler, i, j, len, len1, m, methods, nonblockMethods, proto
  proto = Object.create(HTMLObjectElement.prototype)
  proto.createdCallback = function () {
    return new WebViewImpl(this)
  }
  proto.attributeChangedCallback = function (name, oldValue, newValue) {
    var internal
    internal = v8Util.getHiddenValue(this, 'internal')
    if (!internal) {
      return
    }
    return internal.handleWebviewAttributeMutation(name, oldValue, newValue)
  }
  proto.detachedCallback = function () {
    var internal
    internal = v8Util.getHiddenValue(this, 'internal')
    if (!internal) {
      return
    }
    guestViewInternal.deregisterEvents(internal.viewInstanceId)
    internal.elementAttached = false
    return internal.reset()
  }
  proto.attachedCallback = function () {
    var internal
    internal = v8Util.getHiddenValue(this, 'internal')
    if (!internal) {
      return
    }
    if (!internal.elementAttached) {
      guestViewInternal.registerEvents(internal, internal.viewInstanceId)
      internal.elementAttached = true
      return internal.attributes[webViewConstants.ATTRIBUTE_SRC].parse()
    }
  }

  // Public-facing API methods.
  methods = [
    'getURL',
    'loadURL',
    'getTitle',
    'isLoading',
    'isWaitingForResponse',
    'stop',
    'reload',
    'reloadIgnoringCache',
    'canGoBack',
    'canGoForward',
    'canGoToOffset',
    'clearHistory',
    'goBack',
    'goForward',
    'goToIndex',
    'goToOffset',
    'isCrashed',
    'setUserAgent',
    'getUserAgent',
    'openDevTools',
    'closeDevTools',
    'isDevToolsOpened',
    'isDevToolsFocused',
    'inspectElement',
    'setAudioMuted',
    'isAudioMuted',
    'undo',
    'redo',
    'cut',
    'copy',
    'paste',
    'pasteAndMatchStyle',
    'delete',
    'selectAll',
    'unselect',
    'replace',
    'replaceMisspelling',
    'findInPage',
    'stopFindInPage',
    'getId',
    'downloadURL',
    'inspectServiceWorker',
    'print',
    'printToPDF'
  ]
  nonblockMethods = [
    'insertCSS',
    'insertText',
    'send',
    'sendInputEvent',
    'setZoomFactor',
    'setZoomLevel',
    'setZoomLevelLimits'
  ]

  // Forward proto.foo* method calls to WebViewImpl.foo*.
  createBlockHandler = function (m) {
    return function (...args) {
      const internal = v8Util.getHiddenValue(this, 'internal')
      if (internal.webContents) {
        return internal.webContents[m].apply(internal.webContents, args)
      } else {
        throw new Error(`Cannot call ${m} because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emitted before this method can be called.`)
      }
    }
  }
  for (i = 0, len = methods.length; i < len; i++) {
    m = methods[i]
    proto[m] = createBlockHandler(m)
  }
  createNonBlockHandler = function (m) {
    return function (...args) {
      const internal = v8Util.getHiddenValue(this, 'internal')
      return ipcRenderer.send.apply(ipcRenderer, ['ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', null, internal.guestInstanceId, m].concat(args))
    }
  }
  for (j = 0, len1 = nonblockMethods.length; j < len1; j++) {
    m = nonblockMethods[j]
    proto[m] = createNonBlockHandler(m)
  }

  proto.executeJavaScript = function (code, hasUserGesture, callback) {
    var internal = v8Util.getHiddenValue(this, 'internal')
    if (typeof hasUserGesture === 'function') {
      callback = hasUserGesture
      hasUserGesture = false
    }
    let requestId = getNextId()
    ipcRenderer.send('ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', requestId, internal.guestInstanceId, 'executeJavaScript', code, hasUserGesture)
    ipcRenderer.once(`ELECTRON_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, function (event, result) {
      if (callback) callback(result)
    })
  }

  // WebContents associated with this webview.
  proto.getWebContents = function () {
    var internal = v8Util.getHiddenValue(this, 'internal')
    return internal.webContents
  }

  // Deprecated.
  deprecate.rename(proto, 'getUrl', 'getURL')
  window.WebView = webFrame.registerEmbedderCustomElement('webview', {
    prototype: proto
  })

  // Delete the callbacks so developers cannot call them and produce unexpected
  // behavior.
  delete proto.createdCallback
  delete proto.attachedCallback
  delete proto.detachedCallback
  return delete proto.attributeChangedCallback
}

var useCapture = true

var listener = function (event) {
  if (document.readyState === 'loading') {
    return
  }
  registerBrowserPluginElement()
  registerWebViewElement()
  return window.removeEventListener(event.type, listener, useCapture)
}

window.addEventListener('readystatechange', listener, true)

module.exports = WebViewImpl