crash-reporter.js 3.4 KB

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