crash-reporter.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. 'use strict'
  2. const {spawn} = require('child_process')
  3. const os = require('os')
  4. const path = require('path')
  5. const electron = require('electron')
  6. const {app, deprecate} = process.type === 'browser' ? electron : electron.remote
  7. const binding = process.atomBinding('crash_reporter')
  8. class CrashReporter {
  9. start (options) {
  10. if (options == null) options = {}
  11. this.productName = options.productName != null ? options.productName : app.getName()
  12. let {
  13. companyName,
  14. extra,
  15. ignoreSystemCrashHandler,
  16. submitURL,
  17. uploadToServer
  18. } = options
  19. if (uploadToServer == null) {
  20. if (options.autoSubmit) {
  21. deprecate.warn('autoSubmit', 'uploadToServer')
  22. uploadToServer = options.autoSubmit
  23. } else {
  24. uploadToServer = true
  25. }
  26. }
  27. if (ignoreSystemCrashHandler == null) ignoreSystemCrashHandler = false
  28. if (extra == null) extra = {}
  29. if (extra._productName == null) extra._productName = this.getProductName()
  30. if (extra._companyName == null) extra._companyName = companyName
  31. if (extra._version == null) extra._version = app.getVersion()
  32. if (companyName == null) {
  33. throw new Error('companyName is a required option to crashReporter.start')
  34. }
  35. if (submitURL == null) {
  36. throw new Error('submitURL is a required option to crashReporter.start')
  37. }
  38. if (process.platform === 'win32') {
  39. const env = {
  40. ELECTRON_INTERNAL_CRASH_SERVICE: 1
  41. }
  42. const args = [
  43. '--reporter-url=' + submitURL,
  44. '--application-name=' + this.getProductName(),
  45. '--crashes-directory=' + this.getCrashesDirectory(),
  46. '--v=1'
  47. ]
  48. this._crashServiceProcess = spawn(process.execPath, args, {
  49. env: env,
  50. detached: true
  51. })
  52. }
  53. binding.start(this.getProductName(), companyName, submitURL, this.getCrashesDirectory(), uploadToServer, ignoreSystemCrashHandler, extra)
  54. }
  55. getLastCrashReport () {
  56. const reports = this.getUploadedReports()
  57. .sort((a, b) => {
  58. const ats = (a && a.date) ? new Date(a.date).getTime() : 0
  59. const bts = (b && b.date) ? new Date(b.date).getTime() : 0
  60. return bts - ats
  61. })
  62. return (reports.length > 0) ? reports[0] : null
  63. }
  64. getUploadedReports () {
  65. return binding.getUploadedReports(this.getCrashesDirectory())
  66. }
  67. getCrashesDirectory () {
  68. const crashesDir = `${this.getProductName()} Crashes`
  69. return path.join(this.getTempDirectory(), crashesDir)
  70. }
  71. getProductName () {
  72. if (this.productName == null) {
  73. this.productName = app.getName()
  74. }
  75. return this.productName
  76. }
  77. getTempDirectory () {
  78. if (this.tempDirectory == null) {
  79. try {
  80. this.tempDirectory = app.getPath('temp')
  81. } catch (error) {
  82. this.tempDirectory = os.tmpdir()
  83. }
  84. }
  85. return this.tempDirectory
  86. }
  87. getUploadToServer () {
  88. if (process.type === 'browser') {
  89. return binding.getUploadToServer()
  90. } else {
  91. throw new Error('getUploadToServer can only be called from the main process')
  92. }
  93. }
  94. setUploadToServer (uploadToServer) {
  95. if (process.type === 'browser') {
  96. return binding.setUploadToServer(uploadToServer)
  97. } else {
  98. throw new Error('setUploadToServer can only be called from the main process')
  99. }
  100. }
  101. addExtraParameter (key, value) {
  102. binding.addExtraParameter(key, value)
  103. }
  104. removeExtraParameter (key) {
  105. binding.removeExtraParameter(key)
  106. }
  107. getParameters (key, value) {
  108. return binding.getParameters()
  109. }
  110. }
  111. module.exports = new CrashReporter()