Merge pull request #790 from atom/error-box

Fix crash when showing error dialog before GUI environment is initialized
This commit is contained in:
Cheng Zhao 2014-11-05 20:25:04 +08:00
commit 6d2cc8aedf
7 changed files with 69 additions and 15 deletions

View file

@ -103,6 +103,7 @@ void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context, void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("showMessageBox", &ShowMessageBox);
dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
}

View file

@ -1,5 +1,6 @@
binding = process.atomBinding 'dialog'
v8Util = process.atomBinding 'v8_util'
app = require 'app'
BrowserWindow = require 'browser-window'
fileDialogProperties =
@ -22,8 +23,12 @@ parseArgs = (window, options, callback) ->
options = null
[window, options, callback]
checkAppInitialized = ->
throw new Error('dialog module can only be used after app is ready') unless app.isReady()
module.exports =
showOpenDialog: (args...) ->
checkAppInitialized()
[window, options, callback] = parseArgs args...
options ?= title: 'Open', properties: ['openFile']
@ -52,6 +57,7 @@ module.exports =
wrappedCallback
showSaveDialog: (args...) ->
checkAppInitialized()
[window, options, callback] = parseArgs args...
options ?= title: 'Save'
@ -72,6 +78,7 @@ module.exports =
wrappedCallback
showMessageBox: (args...) ->
checkAppInitialized()
[window, options, callback] = parseArgs args...
options ?= type: 'none'
@ -93,5 +100,8 @@ module.exports =
window,
callback
showErrorBox: (args...) ->
binding.showErrorBox args...
# Mark standard asynchronous functions.
v8Util.setHiddenValue f, 'asynchronous', true for k, f of module.exports

View file

@ -48,14 +48,7 @@ if (option.file && !option.webdriver) {
} catch(e) {
if (e.code == 'MODULE_NOT_FOUND') {
app.focus();
console.error(e.stack);
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'
});
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');
process.exit(1);
} else {
console.error('App throwed an error when running', e);

View file

@ -45,13 +45,9 @@ process.once 'BIND_DONE', ->
# Don't quit on fatal error.
process.on 'uncaughtException', (error) ->
# Show error in GUI.
message = error.stack ? "#{error.name}: #{error.message}"
require('dialog').showMessageBox
type: 'warning'
title: 'A javascript error occured in the browser'
message: 'uncaughtException'
detail: message
buttons: ['OK']
stack = error.stack ? "#{error.name}: #{error.message}"
message = "Uncaught Exception:\n#{stack}"
require('dialog').showErrorBox 'A JavaScript error occured in the browser process', message
# Emit 'exit' event on quit.
require('app').on 'quit', ->

View file

@ -9,6 +9,7 @@
#include <vector>
#include "base/callback_forward.h"
#include "base/strings/string16.h"
namespace atom {
@ -37,6 +38,10 @@ void ShowMessageBox(NativeWindow* parent_window,
const std::string& detail,
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
#endif // ATOM_BROWSER_UI_MESSAGE_BOX_H_

View file

@ -141,4 +141,13 @@ void ShowMessageBox(NativeWindow* parent_window,
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

View file

@ -4,6 +4,10 @@
#include "atom/browser/ui/message_box.h"
#if defined(USE_X11)
#include <gtk/gtk.h>
#endif
#include "atom/browser/native_window.h"
#include "base/callback.h"
#include "base/message_loop/message_loop.h"
@ -23,9 +27,20 @@
#include "ui/wm/core/shadow_types.h"
#if defined(USE_X11)
#include "atom/browser/browser.h"
#include "ui/views/window/native_frame_view.h"
#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 {
@ -350,4 +365,29 @@ void ShowMessageBox(NativeWindow* parent_window,
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