Add 'will-prevent-unload' event.
This commit is contained in:
parent
0c3f80c334
commit
4044548f3e
9 changed files with 88 additions and 17 deletions
|
@ -13,6 +13,7 @@
|
||||||
#include "atom/browser/atom_browser_client.h"
|
#include "atom/browser/atom_browser_client.h"
|
||||||
#include "atom/browser/atom_browser_context.h"
|
#include "atom/browser/atom_browser_context.h"
|
||||||
#include "atom/browser/atom_browser_main_parts.h"
|
#include "atom/browser/atom_browser_main_parts.h"
|
||||||
|
#include "atom/browser/atom_javascript_dialog_manager.h"
|
||||||
#include "atom/browser/child_web_contents_tracker.h"
|
#include "atom/browser/child_web_contents_tracker.h"
|
||||||
#include "atom/browser/lib/bluetooth_chooser.h"
|
#include "atom/browser/lib/bluetooth_chooser.h"
|
||||||
#include "atom/browser/native_window.h"
|
#include "atom/browser/native_window.h"
|
||||||
|
@ -683,6 +684,15 @@ std::unique_ptr<content::BluetoothChooser> WebContents::RunBluetoothChooser(
|
||||||
return std::move(bluetooth_chooser);
|
return std::move(bluetooth_chooser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
content::JavaScriptDialogManager*
|
||||||
|
WebContents::GetJavaScriptDialogManager(
|
||||||
|
content::WebContents* source) {
|
||||||
|
if (!dialog_manager_)
|
||||||
|
dialog_manager_.reset(new AtomJavaScriptDialogManager(this));
|
||||||
|
|
||||||
|
return dialog_manager_.get();
|
||||||
|
}
|
||||||
|
|
||||||
void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
|
void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
|
||||||
// Do nothing, we override this method just to avoid compilation error since
|
// Do nothing, we override this method just to avoid compilation error since
|
||||||
// there are two virtual functions named BeforeUnloadFired.
|
// there are two virtual functions named BeforeUnloadFired.
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace atom {
|
||||||
|
|
||||||
struct SetSizeParams;
|
struct SetSizeParams;
|
||||||
class AtomBrowserContext;
|
class AtomBrowserContext;
|
||||||
|
class AtomJavaScriptDialogManager;
|
||||||
class WebContentsZoomController;
|
class WebContentsZoomController;
|
||||||
class WebViewGuestDelegate;
|
class WebViewGuestDelegate;
|
||||||
|
|
||||||
|
@ -296,6 +297,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
std::unique_ptr<content::BluetoothChooser> RunBluetoothChooser(
|
std::unique_ptr<content::BluetoothChooser> RunBluetoothChooser(
|
||||||
content::RenderFrameHost* frame,
|
content::RenderFrameHost* frame,
|
||||||
const content::BluetoothChooser::EventHandler& handler) override;
|
const content::BluetoothChooser::EventHandler& handler) override;
|
||||||
|
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
|
||||||
|
content::WebContents* source) override;
|
||||||
|
|
||||||
// content::WebContentsObserver:
|
// content::WebContentsObserver:
|
||||||
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
|
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
|
||||||
|
@ -388,6 +391,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
v8::Global<v8::Value> devtools_web_contents_;
|
v8::Global<v8::Value> devtools_web_contents_;
|
||||||
v8::Global<v8::Value> debugger_;
|
v8::Global<v8::Value> debugger_;
|
||||||
|
|
||||||
|
std::unique_ptr<AtomJavaScriptDialogManager> dialog_manager_;
|
||||||
std::unique_ptr<WebViewGuestDelegate> guest_delegate_;
|
std::unique_ptr<WebViewGuestDelegate> guest_delegate_;
|
||||||
|
|
||||||
// The host webcontents that may contain this webcontents.
|
// The host webcontents that may contain this webcontents.
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "atom/browser/api/atom_api_web_contents.h"
|
||||||
#include "atom/browser/native_window.h"
|
#include "atom/browser/native_window.h"
|
||||||
#include "atom/browser/ui/message_box.h"
|
#include "atom/browser/ui/message_box.h"
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
|
@ -17,6 +18,10 @@ using content::JavaScriptDialogType;
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
AtomJavaScriptDialogManager::AtomJavaScriptDialogManager(
|
||||||
|
api::WebContents* api_web_contents)
|
||||||
|
: api_web_contents_(api_web_contents) {}
|
||||||
|
|
||||||
void AtomJavaScriptDialogManager::RunJavaScriptDialog(
|
void AtomJavaScriptDialogManager::RunJavaScriptDialog(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
const GURL& origin_url,
|
const GURL& origin_url,
|
||||||
|
@ -25,7 +30,6 @@ void AtomJavaScriptDialogManager::RunJavaScriptDialog(
|
||||||
const base::string16& default_prompt_text,
|
const base::string16& default_prompt_text,
|
||||||
const DialogClosedCallback& callback,
|
const DialogClosedCallback& callback,
|
||||||
bool* did_suppress_message) {
|
bool* did_suppress_message) {
|
||||||
|
|
||||||
if (dialog_type != JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_ALERT &&
|
if (dialog_type != JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_ALERT &&
|
||||||
dialog_type != JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_CONFIRM) {
|
dialog_type != JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_CONFIRM) {
|
||||||
callback.Run(false, base::string16());
|
callback.Run(false, base::string16());
|
||||||
|
@ -49,8 +53,9 @@ void AtomJavaScriptDialogManager::RunBeforeUnloadDialog(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
bool is_reload,
|
bool is_reload,
|
||||||
const DialogClosedCallback& callback) {
|
const DialogClosedCallback& callback) {
|
||||||
// FIXME(zcbenz): the |message_text| is removed, figure out what should we do.
|
bool default_prevented = api_web_contents_->Emit("will-prevent-unload");
|
||||||
callback.Run(false, base::ASCIIToUTF16("This should not be displayed"));
|
callback.Run(default_prevented, base::string16());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtomJavaScriptDialogManager::CancelDialogs(
|
void AtomJavaScriptDialogManager::CancelDialogs(
|
||||||
|
|
|
@ -11,8 +11,14 @@
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
namespace api {
|
||||||
|
class WebContents;
|
||||||
|
}
|
||||||
|
|
||||||
class AtomJavaScriptDialogManager : public content::JavaScriptDialogManager {
|
class AtomJavaScriptDialogManager : public content::JavaScriptDialogManager {
|
||||||
public:
|
public:
|
||||||
|
explicit AtomJavaScriptDialogManager(api::WebContents* api_web_contents);
|
||||||
|
|
||||||
// content::JavaScriptDialogManager implementations.
|
// content::JavaScriptDialogManager implementations.
|
||||||
void RunJavaScriptDialog(
|
void RunJavaScriptDialog(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
|
@ -33,6 +39,7 @@ class AtomJavaScriptDialogManager : public content::JavaScriptDialogManager {
|
||||||
static void OnMessageBoxCallback(const DialogClosedCallback& callback,
|
static void OnMessageBoxCallback(const DialogClosedCallback& callback,
|
||||||
int code,
|
int code,
|
||||||
bool checkbox_checked);
|
bool checkbox_checked);
|
||||||
|
api::WebContents* api_web_contents_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "atom/browser/atom_browser_context.h"
|
#include "atom/browser/atom_browser_context.h"
|
||||||
#include "atom/browser/atom_javascript_dialog_manager.h"
|
|
||||||
#include "atom/browser/native_window.h"
|
#include "atom/browser/native_window.h"
|
||||||
#include "atom/browser/ui/file_dialog.h"
|
#include "atom/browser/ui/file_dialog.h"
|
||||||
#include "atom/browser/web_dialog_helper.h"
|
#include "atom/browser/web_dialog_helper.h"
|
||||||
|
@ -230,15 +229,6 @@ bool CommonWebContentsDelegate::CanOverscrollContent() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
content::JavaScriptDialogManager*
|
|
||||||
CommonWebContentsDelegate::GetJavaScriptDialogManager(
|
|
||||||
content::WebContents* source) {
|
|
||||||
if (!dialog_manager_)
|
|
||||||
dialog_manager_.reset(new AtomJavaScriptDialogManager);
|
|
||||||
|
|
||||||
return dialog_manager_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
content::ColorChooser* CommonWebContentsDelegate::OpenColorChooser(
|
content::ColorChooser* CommonWebContentsDelegate::OpenColorChooser(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
SkColor color,
|
SkColor color,
|
||||||
|
|
|
@ -20,7 +20,6 @@ using brightray::DevToolsFileSystemIndexer;
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
class AtomBrowserContext;
|
class AtomBrowserContext;
|
||||||
class AtomJavaScriptDialogManager;
|
|
||||||
class NativeWindow;
|
class NativeWindow;
|
||||||
class WebDialogHelper;
|
class WebDialogHelper;
|
||||||
|
|
||||||
|
@ -62,8 +61,6 @@ class CommonWebContentsDelegate
|
||||||
content::WebContents* source,
|
content::WebContents* source,
|
||||||
const content::OpenURLParams& params) override;
|
const content::OpenURLParams& params) override;
|
||||||
bool CanOverscrollContent() const override;
|
bool CanOverscrollContent() const override;
|
||||||
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
|
|
||||||
content::WebContents* source) override;
|
|
||||||
content::ColorChooser* OpenColorChooser(
|
content::ColorChooser* OpenColorChooser(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
SkColor color,
|
SkColor color,
|
||||||
|
@ -147,7 +144,6 @@ class CommonWebContentsDelegate
|
||||||
bool native_fullscreen_;
|
bool native_fullscreen_;
|
||||||
|
|
||||||
std::unique_ptr<WebDialogHelper> web_dialog_helper_;
|
std::unique_ptr<WebDialogHelper> web_dialog_helper_;
|
||||||
std::unique_ptr<AtomJavaScriptDialogManager> dialog_manager_;
|
|
||||||
scoped_refptr<DevToolsFileSystemIndexer> devtools_file_system_indexer_;
|
scoped_refptr<DevToolsFileSystemIndexer> devtools_file_system_indexer_;
|
||||||
|
|
||||||
// Make sure BrowserContext is alwasys destroyed after WebContents.
|
// Make sure BrowserContext is alwasys destroyed after WebContents.
|
||||||
|
|
|
@ -218,6 +218,36 @@ When in-page navigation happens, the page URL changes but does not cause
|
||||||
navigation outside of the page. Examples of this occurring are when anchor links
|
navigation outside of the page. Examples of this occurring are when anchor links
|
||||||
are clicked or when the DOM `hashchange` event is triggered.
|
are clicked or when the DOM `hashchange` event is triggered.
|
||||||
|
|
||||||
|
#### Event: 'will-prevent-unload'
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
* `event` Event
|
||||||
|
|
||||||
|
Emitted when a `beforeunload` event handler is attempting to cancel a page unload.
|
||||||
|
|
||||||
|
Calling `event.preventDefault()` will ignore the `beforeunload` event handler
|
||||||
|
and allow the page to be unloaded.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const {BrowserWindow} = require('electron')
|
||||||
|
let win = new BrowserWindow({width: 800, height: 600})
|
||||||
|
win.webContents.on('will-prevent-unload', (event) => {
|
||||||
|
let choice = dialog.showMessageBox(mainWindow, {
|
||||||
|
type: 'question',
|
||||||
|
buttons: ['Leave', 'Stay'],
|
||||||
|
title: 'Do you want to leave this site?',
|
||||||
|
message: 'Changes you made may not be saved.',
|
||||||
|
defaultId: 0,
|
||||||
|
cancelId: 1
|
||||||
|
})
|
||||||
|
let leave = (choice === 0)
|
||||||
|
if (leave) {
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
#### Event: 'crashed'
|
#### Event: 'crashed'
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
|
@ -543,6 +543,31 @@ describe('webContents module', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('will-prevent-unload event', function () {
|
||||||
|
it('does not emit if beforeunload returns undefined', function (done) {
|
||||||
|
w.once('closed', function () {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.webContents.on('will-prevent-unload', function (e) {
|
||||||
|
assert.fail('should not have fired')
|
||||||
|
})
|
||||||
|
w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-undefined.html'))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits if beforeunload returns false', (done) => {
|
||||||
|
w.webContents.on('will-prevent-unload', () => {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html'))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('supports calling preventDefault on will-prevent-unload events', function (done) {
|
||||||
|
ipcRenderer.send('prevent-next-will-prevent-unload', w.webContents.id)
|
||||||
|
w.once('closed', () => done())
|
||||||
|
w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html'))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('destroy()', () => {
|
describe('destroy()', () => {
|
||||||
let server
|
let server
|
||||||
|
|
||||||
|
|
|
@ -266,6 +266,10 @@ ipcMain.on('prevent-next-will-attach-webview', (event) => {
|
||||||
event.sender.once('will-attach-webview', event => event.preventDefault())
|
event.sender.once('will-attach-webview', event => event.preventDefault())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.on('prevent-next-will-prevent-unload', (event, id) => {
|
||||||
|
webContents.fromId(id).once('will-prevent-unload', event => event.preventDefault())
|
||||||
|
})
|
||||||
|
|
||||||
ipcMain.on('disable-node-on-next-will-attach-webview', (event, id) => {
|
ipcMain.on('disable-node-on-next-will-attach-webview', (event, id) => {
|
||||||
event.sender.once('will-attach-webview', (event, webPreferences, params) => {
|
event.sender.once('will-attach-webview', (event, webPreferences, params) => {
|
||||||
params.src = `file://${path.join(__dirname, '..', 'fixtures', 'pages', 'c.html')}`
|
params.src = `file://${path.join(__dirname, '..', 'fixtures', 'pages', 'c.html')}`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue