Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send the "unresponsive" event if window does not close or cancel the close in 500ms when closing it. #130

Merged
merged 3 commits into from Nov 29, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions browser/api/atom_api_dialog.cc
Expand Up @@ -59,9 +59,8 @@ v8::Handle<v8::Value> ShowMessageBox(const v8::Arguments &args) {
return node::ThrowTypeError("Bad argument");

NativeWindow* native_window = FromV8Value(args[5]);
v8::Persistent<v8::Function> callback = FromV8Value(args[6]);

if (callback.IsEmpty()) {
if (!args[6]->IsFunction()) {
int chosen = atom::ShowMessageBox(
native_window,
(MessageBoxType)type,
Expand All @@ -71,6 +70,7 @@ v8::Handle<v8::Value> ShowMessageBox(const v8::Arguments &args) {
detail);
return scope.Close(v8::Integer::New(chosen));
} else {
v8::Persistent<v8::Function> callback = FromV8Value(args[6]);
atom::ShowMessageBox(
native_window,
(MessageBoxType)type,
Expand All @@ -93,9 +93,8 @@ v8::Handle<v8::Value> ShowOpenDialog(const v8::Arguments &args) {
return node::ThrowTypeError("Bad argument");

NativeWindow* native_window = FromV8Value(args[3]);
v8::Persistent<v8::Function> callback = FromV8Value(args[4]);

if (callback.IsEmpty()) {
if (!args[4]->IsFunction()) {
std::vector<base::FilePath> paths;
if (!file_dialog::ShowOpenDialog(native_window,
title,
Expand All @@ -110,6 +109,7 @@ v8::Handle<v8::Value> ShowOpenDialog(const v8::Arguments &args) {

return scope.Close(result);
} else {
v8::Persistent<v8::Function> callback = FromV8Value(args[4]);
file_dialog::ShowOpenDialog(
native_window,
title,
Expand All @@ -130,9 +130,8 @@ v8::Handle<v8::Value> ShowSaveDialog(const v8::Arguments &args) {
return node::ThrowTypeError("Bad argument");

NativeWindow* native_window = FromV8Value(args[2]);
v8::Persistent<v8::Function> callback = FromV8Value(args[3]);

if (callback.IsEmpty()) {
if (!args[3]->IsFunction()) {
base::FilePath path;
if (!file_dialog::ShowSaveDialog(native_window,
title,
Expand All @@ -142,6 +141,7 @@ v8::Handle<v8::Value> ShowSaveDialog(const v8::Arguments &args) {

return scope.Close(ToV8Value(path));
} else {
v8::Persistent<v8::Function> callback = FromV8Value(args[3]);
file_dialog::ShowSaveDialog(
native_window,
title,
Expand Down
19 changes: 16 additions & 3 deletions browser/native_window.cc
Expand Up @@ -45,6 +45,7 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
has_frame_(true),
is_closed_(false),
not_responding_(false),
weak_factory_(this),
inspectable_web_contents_(
brightray::InspectableWebContents::Create(web_contents)) {
options->GetBoolean(switches::kFrame, &has_frame_);
Expand Down Expand Up @@ -205,7 +206,7 @@ void NativeWindow::CapturePage(const gfx::Rect& rect,
rect,
gfx::Size(),
base::Bind(&NativeWindow::OnCapturePageDone,
base::Unretained(this),
weak_factory_.GetWeakPtr(),
callback));
}

Expand All @@ -221,6 +222,12 @@ void NativeWindow::CloseWebContents() {

content::WebContents* web_contents(GetWebContents());

// Assume the window is not responding if it doesn't cancel the close and is
// not closed in 500ms, in this way we can quickly show the unresponsive
// dialog when the window is busy executing some script withouth waiting for
// the unresponsive timeout.
RendererUnresponsive(web_contents);

if (web_contents->NeedToFireBeforeUnload())
web_contents->GetRenderViewHost()->FirePageBeforeUnload(false);
else
Expand Down Expand Up @@ -277,6 +284,9 @@ void NativeWindow::BeforeUnloadFired(content::WebContents* tab,

if (!proceed)
WindowList::WindowCloseCancelled(this);

// When the "beforeunload" callback is fired the window is certainly live.
not_responding_ = false;
}

void NativeWindow::RequestToLockMouse(content::WebContents* web_contents,
Expand Down Expand Up @@ -319,6 +329,9 @@ void NativeWindow::CloseContents(content::WebContents* source) {
CloseImmediately();

NotifyWindowClosed();

// Do not sent "unresponsive" event after window is closed.
not_responding_ = false;
}

bool NativeWindow::IsPopupOrPanel(const content::WebContents* source) const {
Expand All @@ -331,8 +344,8 @@ void NativeWindow::RendererUnresponsive(content::WebContents* source) {
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&NativeWindow::RendererUnresponsiveDelayed,
base::Unretained(this)),
base::TimeDelta::FromSeconds(1));
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(500));
}

void NativeWindow::RendererResponsive(content::WebContents* source) {
Expand Down
3 changes: 3 additions & 0 deletions browser/native_window.h
Expand Up @@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "browser/native_window_observer.h"
#include "content/public/browser/notification_registrar.h"
Expand Down Expand Up @@ -216,6 +217,8 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
// The window is not responding.
bool not_responding_;

base::WeakPtrFactory<NativeWindow> weak_factory_;

scoped_ptr<AtomJavaScriptDialogManager> dialog_manager_;
scoped_ptr<brightray::InspectableWebContents> inspectable_web_contents_;

Expand Down
10 changes: 10 additions & 0 deletions spec/main.js
@@ -1,5 +1,6 @@
var app = require('app');
var ipc = require('ipc');
var dialog = require('dialog');
var BrowserWindow = require('browser-window');
var Menu = require('menu');

Expand Down Expand Up @@ -103,4 +104,13 @@ app.on('finish-launching', function() {
height: 600
});
window.loadUrl('file://' + __dirname + '/index.html');
window.on('unresponsive', function() {
var chosen = dialog.showMessageBox(window, {
type: 'warning',
buttons: ['Close', 'Keep Waiting'],
message: 'Window is not responsing',
detail: 'The window is not responding. Would you like to force close it or just keep waiting?'
});
if (chosen == 0) window.destroy();
});
});