Move closing logic to api::BrowserWindow
Closing a BrowserWindow is essentially closing a WebContents, the logic should not be in NativeWindow.
This commit is contained in:
parent
66fab65a1a
commit
aa3eafcea1
8 changed files with 103 additions and 143 deletions
|
@ -9,7 +9,9 @@
|
|||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
|
@ -174,7 +176,7 @@ void BrowserWindow::Init(v8::Isolate* isolate,
|
|||
|
||||
BrowserWindow::~BrowserWindow() {
|
||||
if (!window_->IsClosed())
|
||||
window_->CloseContents(nullptr);
|
||||
window_->CloseImmediately();
|
||||
|
||||
api_web_contents_->RemoveObserver(this);
|
||||
|
||||
|
@ -214,6 +216,23 @@ void BrowserWindow::DidFirstVisuallyNonEmptyPaint() {
|
|||
}, GetWeakPtr()));
|
||||
}
|
||||
|
||||
void BrowserWindow::BeforeUnloadDialogCancelled() {
|
||||
WindowList::WindowCloseCancelled(window_.get());
|
||||
// Cancel unresponsive event when window close is cancelled.
|
||||
window_unresposive_closure_.Cancel();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnRendererUnresponsive(content::RenderWidgetHost*) {
|
||||
// Schedule the unresponsive shortly later, since we may receive the
|
||||
// responsive event soon. This could happen after the whole application had
|
||||
// blocked for a while.
|
||||
// Also notice that when closing this event would be ignored because we have
|
||||
// explicitly started a close timeout counter. This is on purpose because we
|
||||
// don't want the unresponsive event to be sent too early when user is closing
|
||||
// the window.
|
||||
ScheduleUnresponsiveEvent(50);
|
||||
}
|
||||
|
||||
bool BrowserWindow::OnMessageReceived(const IPC::Message& message,
|
||||
content::RenderFrameHost* rfh) {
|
||||
bool handled = true;
|
||||
|
@ -225,14 +244,11 @@ bool BrowserWindow::OnMessageReceived(const IPC::Message& message,
|
|||
return handled;
|
||||
}
|
||||
|
||||
void BrowserWindow::OnRendererResponsive() {
|
||||
}
|
||||
void BrowserWindow::OnCloseContents() {
|
||||
if (!web_contents())
|
||||
return;
|
||||
Observe(nullptr);
|
||||
|
||||
void BrowserWindow::WillCloseWindow(bool* prevent_default) {
|
||||
*prevent_default = Emit("close");
|
||||
}
|
||||
|
||||
void BrowserWindow::WillDestroyNativeObject() {
|
||||
// Close all child windows before closing current window.
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
|
@ -241,6 +257,25 @@ void BrowserWindow::WillDestroyNativeObject() {
|
|||
if (mate::ConvertFromV8(isolate(), value, &child) && !child.IsEmpty())
|
||||
child->window_->CloseImmediately();
|
||||
}
|
||||
|
||||
// When the web contents is gone, close the window immediately, but the
|
||||
// memory will not be freed until you call delete.
|
||||
// In this way, it would be safe to manage windows via smart pointers. If you
|
||||
// want to free memory when the window is closed, you can do deleting by
|
||||
// overriding the OnWindowClosed method in the observer.
|
||||
window_->CloseImmediately();
|
||||
|
||||
// Do not sent "unresponsive" event after window is closed.
|
||||
window_unresposive_closure_.Cancel();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnRendererResponsive() {
|
||||
window_unresposive_closure_.Cancel();
|
||||
Emit("responsive");
|
||||
}
|
||||
|
||||
void BrowserWindow::WillCloseWindow(bool* prevent_default) {
|
||||
*prevent_default = Emit("close");
|
||||
}
|
||||
|
||||
void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
|
||||
|
@ -248,7 +283,22 @@ void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
|
|||
// not close the window immediately, instead we try to close the web page
|
||||
// first, and when the web page is closed the window will also be closed.
|
||||
*prevent_default = true;
|
||||
window_->RequestToClosePage();
|
||||
|
||||
// Assume the window is not responding if it doesn't cancel the close and is
|
||||
// not closed in 5s, in this way we can quickly show the unresponsive
|
||||
// dialog when the window is busy executing some script withouth waiting for
|
||||
// the unresponsive timeout.
|
||||
if (window_unresposive_closure_.IsCancelled())
|
||||
ScheduleUnresponsiveEvent(5000);
|
||||
|
||||
if (!web_contents())
|
||||
// Already closed by renderer
|
||||
return;
|
||||
|
||||
if (web_contents()->NeedToFireBeforeUnload())
|
||||
web_contents()->DispatchBeforeUnload();
|
||||
else
|
||||
web_contents()->Close();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowClosed() {
|
||||
|
@ -360,14 +410,6 @@ void BrowserWindow::OnWindowLeaveHtmlFullScreen() {
|
|||
Emit("leave-html-full-screen");
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowUnresponsive() {
|
||||
Emit("unresponsive");
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowResponsive() {
|
||||
Emit("responsive");
|
||||
}
|
||||
|
||||
void BrowserWindow::OnExecuteWindowsCommand(const std::string& command_name) {
|
||||
Emit("app-command", command_name);
|
||||
}
|
||||
|
@ -1071,6 +1113,26 @@ void BrowserWindow::UpdateDraggableRegions(
|
|||
window_->UpdateDraggableRegions(regions);
|
||||
}
|
||||
|
||||
void BrowserWindow::ScheduleUnresponsiveEvent(int ms) {
|
||||
if (!window_unresposive_closure_.IsCancelled())
|
||||
return;
|
||||
|
||||
window_unresposive_closure_.Reset(
|
||||
base::Bind(&BrowserWindow::NotifyWindowUnresponsive, GetWeakPtr()));
|
||||
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
||||
FROM_HERE,
|
||||
window_unresposive_closure_.callback(),
|
||||
base::TimeDelta::FromMilliseconds(ms));
|
||||
}
|
||||
|
||||
void BrowserWindow::NotifyWindowUnresponsive() {
|
||||
window_unresposive_closure_.Cancel();
|
||||
if (!window_->IsClosed() && window_->IsEnabled() &&
|
||||
!IsUnresponsiveEventSuppressed()) {
|
||||
Emit("unresponsive");
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserWindow::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "atom/browser/native_window_observer.h"
|
||||
#include "atom/common/api/atom_api_native_image.h"
|
||||
#include "atom/common/key_weak_map.h"
|
||||
#include "base/cancelable_callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "native_mate/persistent_dictionary.h"
|
||||
|
||||
|
@ -62,15 +63,17 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
|
|||
// content::WebContentsObserver:
|
||||
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
|
||||
void DidFirstVisuallyNonEmptyPaint() override;
|
||||
void BeforeUnloadDialogCancelled() override;
|
||||
void OnRendererUnresponsive(content::RenderWidgetHost*) override;
|
||||
bool OnMessageReceived(const IPC::Message& message,
|
||||
content::RenderFrameHost* rfh) override;
|
||||
|
||||
// ExtendedWebContentsObserver:
|
||||
void OnCloseContents() override;
|
||||
void OnRendererResponsive() override;
|
||||
|
||||
// NativeWindowObserver:
|
||||
void WillCloseWindow(bool* prevent_default) override;
|
||||
void WillDestroyNativeObject() override;
|
||||
void OnCloseButtonClicked(bool* prevent_default) override;
|
||||
void OnWindowClosed() override;
|
||||
void OnWindowEndSession() override;
|
||||
|
@ -95,8 +98,6 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
|
|||
void OnWindowLeaveFullScreen() override;
|
||||
void OnWindowEnterHtmlFullScreen() override;
|
||||
void OnWindowLeaveHtmlFullScreen() override;
|
||||
void OnWindowUnresponsive() override;
|
||||
void OnWindowResponsive() override;
|
||||
void OnExecuteWindowsCommand(const std::string& command_name) override;
|
||||
void OnTouchBarItemResult(const std::string& item_id,
|
||||
const base::DictionaryValue& details) override;
|
||||
|
@ -253,11 +254,21 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
|
|||
content::RenderFrameHost* rfh,
|
||||
const std::vector<DraggableRegion>& regions);
|
||||
|
||||
// Schedule a notification unresponsive event.
|
||||
void ScheduleUnresponsiveEvent(int ms);
|
||||
|
||||
// Dispatch unresponsive event to observers.
|
||||
void NotifyWindowUnresponsive();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
typedef std::map<UINT, MessageCallback> MessageCallbackMap;
|
||||
MessageCallbackMap messages_callback_map_;
|
||||
#endif
|
||||
|
||||
// Closure that would be called when window is unresponsive when closing,
|
||||
// it should be cancelled when we can prove that the window is responsive.
|
||||
base::CancelableClosure window_unresposive_closure_;
|
||||
|
||||
v8::Global<v8::Value> browser_view_;
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
v8::Global<v8::Value> menu_;
|
||||
|
|
|
@ -446,6 +446,8 @@ void WebContents::InitWithSessionAndOptions(v8::Isolate* isolate,
|
|||
WebContents::~WebContents() {
|
||||
// The destroy() is called.
|
||||
if (managed_web_contents()) {
|
||||
managed_web_contents()->GetView()->SetDelegate(nullptr);
|
||||
|
||||
// For webview we need to tell content module to do some cleanup work before
|
||||
// destroying it.
|
||||
if (type_ == WEB_VIEW)
|
||||
|
@ -457,7 +459,8 @@ WebContents::~WebContents() {
|
|||
DestroyWebContents(false /* async */);
|
||||
} else {
|
||||
if (type_ == BROWSER_WINDOW && owner_window()) {
|
||||
owner_window()->CloseContents(nullptr);
|
||||
for (ExtendedWebContentsObserver& observer : observers_)
|
||||
observer.OnCloseContents();
|
||||
} else {
|
||||
DestroyWebContents(true /* async */);
|
||||
}
|
||||
|
@ -565,9 +568,10 @@ void WebContents::MoveContents(content::WebContents* source,
|
|||
|
||||
void WebContents::CloseContents(content::WebContents* source) {
|
||||
Emit("close");
|
||||
|
||||
if ((type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) && owner_window())
|
||||
owner_window()->CloseContents(source);
|
||||
if (managed_web_contents())
|
||||
managed_web_contents()->GetView()->SetDelegate(nullptr);
|
||||
for (ExtendedWebContentsObserver& observer : observers_)
|
||||
observer.OnCloseContents();
|
||||
}
|
||||
|
||||
void WebContents::ActivateContents(content::WebContents* source) {
|
||||
|
@ -640,8 +644,6 @@ void WebContents::RendererUnresponsive(
|
|||
|
||||
void WebContents::RendererResponsive(content::WebContents* source) {
|
||||
Emit("responsive");
|
||||
if ((type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) && owner_window())
|
||||
owner_window()->RendererResponsive(source);
|
||||
for (ExtendedWebContentsObserver& observer : observers_)
|
||||
observer.OnRendererResponsive();
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace api {
|
|||
// dispatch those events.
|
||||
class ExtendedWebContentsObserver {
|
||||
public:
|
||||
virtual void OnCloseContents() {}
|
||||
virtual void OnRendererResponsive() {}
|
||||
};
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/draggable_region.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
|
@ -426,52 +425,6 @@ void NativeWindow::PreviewFile(const std::string& path,
|
|||
void NativeWindow::CloseFilePreview() {
|
||||
}
|
||||
|
||||
void NativeWindow::RequestToClosePage() {
|
||||
// Assume the window is not responding if it doesn't cancel the close and is
|
||||
// not closed in 5s, in this way we can quickly show the unresponsive
|
||||
// dialog when the window is busy executing some script withouth waiting for
|
||||
// the unresponsive timeout.
|
||||
if (window_unresposive_closure_.IsCancelled())
|
||||
ScheduleUnresponsiveEvent(5000);
|
||||
|
||||
if (!web_contents())
|
||||
// Already closed by renderer
|
||||
return;
|
||||
|
||||
if (web_contents()->NeedToFireBeforeUnload())
|
||||
web_contents()->DispatchBeforeUnload();
|
||||
else
|
||||
web_contents()->Close();
|
||||
}
|
||||
|
||||
void NativeWindow::CloseContents(content::WebContents* source) {
|
||||
if (!inspectable_web_contents_)
|
||||
return;
|
||||
|
||||
inspectable_web_contents_->GetView()->SetDelegate(nullptr);
|
||||
inspectable_web_contents_ = nullptr;
|
||||
Observe(nullptr);
|
||||
|
||||
for (NativeWindowObserver& observer : observers_)
|
||||
observer.WillDestroyNativeObject();
|
||||
|
||||
// When the web contents is gone, close the window immediately, but the
|
||||
// memory will not be freed until you call delete.
|
||||
// In this way, it would be safe to manage windows via smart pointers. If you
|
||||
// want to free memory when the window is closed, you can do deleting by
|
||||
// overriding the OnWindowClosed method in the observer.
|
||||
CloseImmediately();
|
||||
|
||||
// Do not sent "unresponsive" event after window is closed.
|
||||
window_unresposive_closure_.Cancel();
|
||||
}
|
||||
|
||||
void NativeWindow::RendererResponsive(content::WebContents* source) {
|
||||
window_unresposive_closure_.Cancel();
|
||||
for (NativeWindowObserver& observer : observers_)
|
||||
observer.OnWindowResponsive();
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowCloseButtonClicked() {
|
||||
// First ask the observers whether we want to close.
|
||||
bool prevent_default = false;
|
||||
|
@ -652,44 +605,4 @@ std::unique_ptr<SkRegion> NativeWindow::DraggableRegionsToSkRegion(
|
|||
return sk_region;
|
||||
}
|
||||
|
||||
void NativeWindow::BeforeUnloadDialogCancelled() {
|
||||
WindowList::WindowCloseCancelled(this);
|
||||
|
||||
// Cancel unresponsive event when window close is cancelled.
|
||||
window_unresposive_closure_.Cancel();
|
||||
}
|
||||
|
||||
void NativeWindow::OnRendererUnresponsive(content::RenderWidgetHost*) {
|
||||
// Schedule the unresponsive shortly later, since we may receive the
|
||||
// responsive event soon. This could happen after the whole application had
|
||||
// blocked for a while.
|
||||
// Also notice that when closing this event would be ignored because we have
|
||||
// explicitly started a close timeout counter. This is on purpose because we
|
||||
// don't want the unresponsive event to be sent too early when user is closing
|
||||
// the window.
|
||||
ScheduleUnresponsiveEvent(50);
|
||||
}
|
||||
|
||||
void NativeWindow::ScheduleUnresponsiveEvent(int ms) {
|
||||
if (!window_unresposive_closure_.IsCancelled())
|
||||
return;
|
||||
|
||||
window_unresposive_closure_.Reset(
|
||||
base::Bind(&NativeWindow::NotifyWindowUnresponsive,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
||||
FROM_HERE,
|
||||
window_unresposive_closure_.callback(),
|
||||
base::TimeDelta::FromMilliseconds(ms));
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowUnresponsive() {
|
||||
window_unresposive_closure_.Cancel();
|
||||
|
||||
if (!is_closed_ && !IsUnresponsiveEventSuppressed() && IsEnabled()) {
|
||||
for (NativeWindowObserver& observer : observers_)
|
||||
observer.OnWindowUnresponsive();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "atom/browser/native_window_observer.h"
|
||||
#include "atom/browser/ui/accelerator_util.h"
|
||||
#include "atom/browser/ui/atom_menu_model.h"
|
||||
#include "base/cancelable_callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/supports_user_data.h"
|
||||
|
@ -230,12 +229,7 @@ class NativeWindow : public base::SupportsUserData,
|
|||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
// Requests the WebContents to close, can be cancelled by the page.
|
||||
virtual void RequestToClosePage();
|
||||
|
||||
// Methods called by the WebContents.
|
||||
virtual void CloseContents(content::WebContents* source);
|
||||
virtual void RendererResponsive(content::WebContents* source);
|
||||
virtual void HandleKeyboardEvent(
|
||||
content::WebContents*,
|
||||
const content::NativeWebKeyboardEvent& event) {}
|
||||
|
@ -315,17 +309,7 @@ class NativeWindow : public base::SupportsUserData,
|
|||
std::unique_ptr<SkRegion> DraggableRegionsToSkRegion(
|
||||
const std::vector<DraggableRegion>& regions);
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void BeforeUnloadDialogCancelled() override;
|
||||
void OnRendererUnresponsive(content::RenderWidgetHost*) override;
|
||||
|
||||
private:
|
||||
// Schedule a notification unresponsive event.
|
||||
void ScheduleUnresponsiveEvent(int ms);
|
||||
|
||||
// Dispatch unresponsive event to observers.
|
||||
void NotifyWindowUnresponsive();
|
||||
|
||||
// Whether window has standard frame.
|
||||
bool has_frame_;
|
||||
|
||||
|
@ -341,10 +325,6 @@ class NativeWindow : public base::SupportsUserData,
|
|||
// The windows has been closed.
|
||||
bool is_closed_;
|
||||
|
||||
// Closure that would be called when window is unresponsive when closing,
|
||||
// it should be cancelled when we can prove that the window is responsive.
|
||||
base::CancelableClosure window_unresposive_closure_;
|
||||
|
||||
// Used to display sheets at the appropriate horizontal and vertical offsets
|
||||
// on macOS.
|
||||
double sheet_offset_x_;
|
||||
|
|
|
@ -34,9 +34,6 @@ class NativeWindowObserver {
|
|||
// Called when the window is gonna closed.
|
||||
virtual void WillCloseWindow(bool* prevent_default) {}
|
||||
|
||||
// Called before the native window object is going to be destroyed.
|
||||
virtual void WillDestroyNativeObject() {}
|
||||
|
||||
// Called when closed button is clicked.
|
||||
virtual void OnCloseButtonClicked(bool* prevent_default) {}
|
||||
|
||||
|
@ -85,12 +82,6 @@ class NativeWindowObserver {
|
|||
virtual void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {}
|
||||
#endif
|
||||
|
||||
// Called when renderer is hung.
|
||||
virtual void OnWindowUnresponsive() {}
|
||||
|
||||
// Called when renderer recovers.
|
||||
virtual void OnWindowResponsive() {}
|
||||
|
||||
// Called on Windows when App Commands arrive (WM_APPCOMMAND)
|
||||
virtual void OnExecuteWindowsCommand(const std::string& command_name) {}
|
||||
};
|
||||
|
|
|
@ -93,7 +93,7 @@ void WindowList::CloseAllWindows() {
|
|||
void WindowList::DestroyAllWindows() {
|
||||
WindowVector windows = GetInstance()->windows_;
|
||||
for (const auto& window : windows)
|
||||
window->CloseContents(nullptr); // e.g. Destroy()
|
||||
window->CloseImmediately(); // e.g. Destroy()
|
||||
}
|
||||
|
||||
WindowList::WindowList() {
|
||||
|
|
Loading…
Add table
Reference in a new issue