Merge pull request #790 from atom/error-box
Fix crash when showing error dialog before GUI environment is initialized
This commit is contained in:
commit
6d2cc8aedf
7 changed files with 69 additions and 15 deletions
|
@ -103,6 +103,7 @@ void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
|
||||||
v8::Handle<v8::Context> context, void* priv) {
|
v8::Handle<v8::Context> context, void* priv) {
|
||||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||||
dict.SetMethod("showMessageBox", &ShowMessageBox);
|
dict.SetMethod("showMessageBox", &ShowMessageBox);
|
||||||
|
dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
|
||||||
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
|
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
|
||||||
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
|
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
binding = process.atomBinding 'dialog'
|
binding = process.atomBinding 'dialog'
|
||||||
v8Util = process.atomBinding 'v8_util'
|
v8Util = process.atomBinding 'v8_util'
|
||||||
|
app = require 'app'
|
||||||
BrowserWindow = require 'browser-window'
|
BrowserWindow = require 'browser-window'
|
||||||
|
|
||||||
fileDialogProperties =
|
fileDialogProperties =
|
||||||
|
@ -22,8 +23,12 @@ parseArgs = (window, options, callback) ->
|
||||||
options = null
|
options = null
|
||||||
[window, options, callback]
|
[window, options, callback]
|
||||||
|
|
||||||
|
checkAppInitialized = ->
|
||||||
|
throw new Error('dialog module can only be used after app is ready') unless app.isReady()
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
showOpenDialog: (args...) ->
|
showOpenDialog: (args...) ->
|
||||||
|
checkAppInitialized()
|
||||||
[window, options, callback] = parseArgs args...
|
[window, options, callback] = parseArgs args...
|
||||||
|
|
||||||
options ?= title: 'Open', properties: ['openFile']
|
options ?= title: 'Open', properties: ['openFile']
|
||||||
|
@ -52,6 +57,7 @@ module.exports =
|
||||||
wrappedCallback
|
wrappedCallback
|
||||||
|
|
||||||
showSaveDialog: (args...) ->
|
showSaveDialog: (args...) ->
|
||||||
|
checkAppInitialized()
|
||||||
[window, options, callback] = parseArgs args...
|
[window, options, callback] = parseArgs args...
|
||||||
|
|
||||||
options ?= title: 'Save'
|
options ?= title: 'Save'
|
||||||
|
@ -72,6 +78,7 @@ module.exports =
|
||||||
wrappedCallback
|
wrappedCallback
|
||||||
|
|
||||||
showMessageBox: (args...) ->
|
showMessageBox: (args...) ->
|
||||||
|
checkAppInitialized()
|
||||||
[window, options, callback] = parseArgs args...
|
[window, options, callback] = parseArgs args...
|
||||||
|
|
||||||
options ?= type: 'none'
|
options ?= type: 'none'
|
||||||
|
@ -93,5 +100,8 @@ module.exports =
|
||||||
window,
|
window,
|
||||||
callback
|
callback
|
||||||
|
|
||||||
|
showErrorBox: (args...) ->
|
||||||
|
binding.showErrorBox args...
|
||||||
|
|
||||||
# Mark standard asynchronous functions.
|
# Mark standard asynchronous functions.
|
||||||
v8Util.setHiddenValue f, 'asynchronous', true for k, f of module.exports
|
v8Util.setHiddenValue f, 'asynchronous', true for k, f of module.exports
|
||||||
|
|
|
@ -48,14 +48,7 @@ if (option.file && !option.webdriver) {
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (e.code == 'MODULE_NOT_FOUND') {
|
if (e.code == 'MODULE_NOT_FOUND') {
|
||||||
app.focus();
|
app.focus();
|
||||||
console.error(e.stack);
|
dialog.showErrorBox('Error opening app', 'The app provided is not a valid atom-shell app, please read the docs on how to write one:\nhttps://github.com/atom/atom-shell/tree/master/docs');
|
||||||
dialog.showMessageBox({
|
|
||||||
type: 'warning',
|
|
||||||
buttons: ['OK'],
|
|
||||||
title: 'Error opening app',
|
|
||||||
message: 'The app provided is not a valid atom-shell app, please read the docs on how to write one:',
|
|
||||||
detail: 'https://github.com/atom/atom-shell/tree/master/docs'
|
|
||||||
});
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
console.error('App throwed an error when running', e);
|
console.error('App throwed an error when running', e);
|
||||||
|
|
|
@ -45,13 +45,9 @@ process.once 'BIND_DONE', ->
|
||||||
# Don't quit on fatal error.
|
# Don't quit on fatal error.
|
||||||
process.on 'uncaughtException', (error) ->
|
process.on 'uncaughtException', (error) ->
|
||||||
# Show error in GUI.
|
# Show error in GUI.
|
||||||
message = error.stack ? "#{error.name}: #{error.message}"
|
stack = error.stack ? "#{error.name}: #{error.message}"
|
||||||
require('dialog').showMessageBox
|
message = "Uncaught Exception:\n#{stack}"
|
||||||
type: 'warning'
|
require('dialog').showErrorBox 'A JavaScript error occured in the browser process', message
|
||||||
title: 'A javascript error occured in the browser'
|
|
||||||
message: 'uncaughtException'
|
|
||||||
detail: message
|
|
||||||
buttons: ['OK']
|
|
||||||
|
|
||||||
# Emit 'exit' event on quit.
|
# Emit 'exit' event on quit.
|
||||||
require('app').on 'quit', ->
|
require('app').on 'quit', ->
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/callback_forward.h"
|
#include "base/callback_forward.h"
|
||||||
|
#include "base/strings/string16.h"
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
@ -37,6 +38,10 @@ void ShowMessageBox(NativeWindow* parent_window,
|
||||||
const std::string& detail,
|
const std::string& detail,
|
||||||
const MessageBoxCallback& callback);
|
const MessageBoxCallback& callback);
|
||||||
|
|
||||||
|
// Like ShowMessageBox with simplest settings, but safe to call at very early
|
||||||
|
// stage of application.
|
||||||
|
void ShowErrorBox(const base::string16& title, const base::string16& content);
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
||||||
#endif // ATOM_BROWSER_UI_MESSAGE_BOX_H_
|
#endif // ATOM_BROWSER_UI_MESSAGE_BOX_H_
|
||||||
|
|
|
@ -141,4 +141,13 @@ void ShowMessageBox(NativeWindow* parent_window,
|
||||||
contextInfo:nil];
|
contextInfo:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShowErrorBox(const base::string16& title, const base::string16& content) {
|
||||||
|
NSAlert* alert = [[NSAlert alloc] init];
|
||||||
|
[alert setMessageText:base::SysUTF16ToNSString(title)];
|
||||||
|
[alert setInformativeText:base::SysUTF16ToNSString(content)];
|
||||||
|
[alert setAlertStyle:NSWarningAlertStyle];
|
||||||
|
[alert runModal];
|
||||||
|
[alert release];
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
|
|
||||||
#include "atom/browser/ui/message_box.h"
|
#include "atom/browser/ui/message_box.h"
|
||||||
|
|
||||||
|
#if defined(USE_X11)
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "atom/browser/native_window.h"
|
#include "atom/browser/native_window.h"
|
||||||
#include "base/callback.h"
|
#include "base/callback.h"
|
||||||
#include "base/message_loop/message_loop.h"
|
#include "base/message_loop/message_loop.h"
|
||||||
|
@ -23,9 +27,20 @@
|
||||||
#include "ui/wm/core/shadow_types.h"
|
#include "ui/wm/core/shadow_types.h"
|
||||||
|
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
|
#include "atom/browser/browser.h"
|
||||||
#include "ui/views/window/native_frame_view.h"
|
#include "ui/views/window/native_frame_view.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
#include "ui/base/win/message_box_win.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ANSI_FOREGROUND_RED "\x1b[31m"
|
||||||
|
#define ANSI_FOREGROUND_BLACK "\x1b[30m"
|
||||||
|
#define ANSI_TEXT_BOLD "\x1b[1m"
|
||||||
|
#define ANSI_BACKGROUND_GRAY "\x1b[47m"
|
||||||
|
#define ANSI_RESET "\x1b[0m"
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -350,4 +365,29 @@ void ShowMessageBox(NativeWindow* parent_window,
|
||||||
dialog->Show();
|
dialog->Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShowErrorBox(const base::string16& title, const base::string16& content) {
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
ui::MessageBox(NULL, content, title, MB_OK | MB_ICONERROR | MB_TASKMODAL);
|
||||||
|
#elif defined(USE_X11)
|
||||||
|
if (Browser::Get()->is_ready()) {
|
||||||
|
GtkWidget* dialog = gtk_message_dialog_new(
|
||||||
|
NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
|
||||||
|
"%s", base::UTF16ToUTF8(title).c_str());
|
||||||
|
gtk_message_dialog_format_secondary_text(
|
||||||
|
GTK_MESSAGE_DIALOG(dialog),
|
||||||
|
"%s", base::UTF16ToUTF8(content).c_str());
|
||||||
|
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,
|
||||||
|
ANSI_TEXT_BOLD ANSI_BACKGROUND_GRAY
|
||||||
|
ANSI_FOREGROUND_RED "%s\n"
|
||||||
|
ANSI_FOREGROUND_BLACK "%s"
|
||||||
|
ANSI_RESET "\n",
|
||||||
|
base::UTF16ToUTF8(title).c_str(),
|
||||||
|
base::UTF16ToUTF8(content).c_str());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
Loading…
Reference in a new issue