diff --git a/atom/browser/api/atom_api_dialog.cc b/atom/browser/api/atom_api_dialog.cc index 3c4d02821d0..975c30963fa 100644 --- a/atom/browser/api/atom_api_dialog.cc +++ b/atom/browser/api/atom_api_dialog.cc @@ -103,6 +103,7 @@ void Initialize(v8::Handle exports, v8::Handle unused, v8::Handle 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); } diff --git a/atom/browser/api/lib/dialog.coffee b/atom/browser/api/lib/dialog.coffee index 640db088cbb..49b1c0ef003 100644 --- a/atom/browser/api/lib/dialog.coffee +++ b/atom/browser/api/lib/dialog.coffee @@ -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 diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index ae4a844cca3..8f6e3874031 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -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); diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index ff8137f8efe..ae2419b2199 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -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', -> diff --git a/atom/browser/ui/message_box.h b/atom/browser/ui/message_box.h index c3d2c5d15d9..bdaa31ec6dc 100644 --- a/atom/browser/ui/message_box.h +++ b/atom/browser/ui/message_box.h @@ -9,6 +9,7 @@ #include #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_ diff --git a/atom/browser/ui/message_box_mac.mm b/atom/browser/ui/message_box_mac.mm index 2ff0ee93e92..370b5911d0c 100644 --- a/atom/browser/ui/message_box_mac.mm +++ b/atom/browser/ui/message_box_mac.mm @@ -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 diff --git a/atom/browser/ui/message_box_views.cc b/atom/browser/ui/message_box_views.cc index 9bfac985611..959545c252d 100644 --- a/atom/browser/ui/message_box_views.cc +++ b/atom/browser/ui/message_box_views.cc @@ -4,6 +4,10 @@ #include "atom/browser/ui/message_box.h" +#if defined(USE_X11) +#include +#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