Merge pull request #3328 from atom/wrapper-cleanup

Clean up native resources on exit
This commit is contained in:
Cheng Zhao 2015-11-04 19:24:32 +08:00
commit 9f536f4783
19 changed files with 112 additions and 51 deletions

View file

@ -6,6 +6,7 @@
#include <map> #include <map>
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h"
@ -159,14 +160,6 @@ mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder(
.SetMethod("setSavePath", &DownloadItem::SetSavePath); .SetMethod("setSavePath", &DownloadItem::SetSavePath);
} }
void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) {
g_wrap_download_item = callback;
}
void ClearWrapDownloadItem() {
g_wrap_download_item.Reset();
}
// static // static
mate::Handle<DownloadItem> DownloadItem::Create( mate::Handle<DownloadItem> DownloadItem::Create(
v8::Isolate* isolate, content::DownloadItem* item) { v8::Isolate* isolate, content::DownloadItem* item) {
@ -182,6 +175,18 @@ void* DownloadItem::UserDataKey() {
return &kDownloadItemSavePathKey; return &kDownloadItemSavePathKey;
} }
void ClearWrapDownloadItem() {
g_wrap_download_item.Reset();
}
void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) {
g_wrap_download_item = callback;
// Cleanup the wrapper on exit.
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
base::Bind(ClearWrapDownloadItem));
}
} // namespace api } // namespace api
} // namespace atom } // namespace atom
@ -193,7 +198,6 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.SetMethod("_setWrapDownloadItem", &atom::api::SetWrapDownloadItem); dict.SetMethod("_setWrapDownloadItem", &atom::api::SetWrapDownloadItem);
dict.SetMethod("_clearWrapDownloadItem", &atom::api::ClearWrapDownloadItem);
} }
} // namespace } // namespace

View file

@ -23,6 +23,9 @@ GlobalShortcut::GlobalShortcut() {
} }
GlobalShortcut::~GlobalShortcut() { GlobalShortcut::~GlobalShortcut() {
}
void GlobalShortcut::Destroy() {
UnregisterAll(); UnregisterAll();
} }

View file

@ -8,9 +8,9 @@
#include <map> #include <map>
#include <string> #include <string>
#include "atom/browser/api/trackable_object.h"
#include "base/callback.h" #include "base/callback.h"
#include "chrome/browser/extensions/global_shortcut_listener.h" #include "chrome/browser/extensions/global_shortcut_listener.h"
#include "native_mate/wrappable.h"
#include "native_mate/handle.h" #include "native_mate/handle.h"
#include "ui/base/accelerators/accelerator.h" #include "ui/base/accelerators/accelerator.h"
@ -19,13 +19,16 @@ namespace atom {
namespace api { namespace api {
class GlobalShortcut : public extensions::GlobalShortcutListener::Observer, class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
public mate::Wrappable { public mate::TrackableObject<GlobalShortcut> {
public: public:
static mate::Handle<GlobalShortcut> Create(v8::Isolate* isolate); static mate::Handle<GlobalShortcut> Create(v8::Isolate* isolate);
protected: protected:
GlobalShortcut(); GlobalShortcut();
virtual ~GlobalShortcut(); ~GlobalShortcut() override;
// mate::TrackableObject:
void Destroy() override;
// mate::Wrappable implementations: // mate::Wrappable implementations:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder( mate::ObjectTemplateBuilder GetObjectTemplateBuilder(

View file

@ -27,6 +27,14 @@ Menu::Menu()
Menu::~Menu() { Menu::~Menu() {
} }
void Menu::Destroy() {
model_.reset();
}
bool Menu::IsDestroyed() const {
return !model_;
}
void Menu::AfterInit(v8::Isolate* isolate) { void Menu::AfterInit(v8::Isolate* isolate) {
mate::Dictionary wrappable(isolate, GetWrapper(isolate)); mate::Dictionary wrappable(isolate, GetWrapper(isolate));
mate::Dictionary delegate; mate::Dictionary delegate;

View file

@ -8,16 +8,16 @@
#include <string> #include <string>
#include "atom/browser/api/atom_api_window.h" #include "atom/browser/api/atom_api_window.h"
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/ui/atom_menu_model.h" #include "atom/browser/ui/atom_menu_model.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "native_mate/wrappable.h"
namespace atom { namespace atom {
namespace api { namespace api {
class Menu : public mate::Wrappable, class Menu : public mate::TrackableObject<Menu>,
public AtomMenuModel::Delegate { public AtomMenuModel::Delegate {
public: public:
static mate::Wrappable* Create(); static mate::Wrappable* Create();
@ -37,9 +37,13 @@ class Menu : public mate::Wrappable,
protected: protected:
Menu(); Menu();
virtual ~Menu(); ~Menu() override;
// mate::TrackableObject:
void Destroy() override;
// mate::Wrappable: // mate::Wrappable:
bool IsDestroyed() const override;
void AfterInit(v8::Isolate* isolate) override; void AfterInit(v8::Isolate* isolate) override;
// ui::SimpleMenuModel::Delegate: // ui::SimpleMenuModel::Delegate:

View file

@ -19,6 +19,7 @@ class MenuMac : public Menu {
protected: protected:
MenuMac(); MenuMac();
void Destroy() override;
void Popup(Window* window) override; void Popup(Window* window) override;
void PopupAt(Window* window, int x, int y) override; void PopupAt(Window* window, int x, int y) override;

View file

@ -18,6 +18,11 @@ namespace api {
MenuMac::MenuMac() { MenuMac::MenuMac() {
} }
void MenuMac::Destroy() {
menu_controller_.reset();
Menu::Destroy();
}
void MenuMac::Popup(Window* window) { void MenuMac::Popup(Window* window) {
NativeWindow* native_window = window->window(); NativeWindow* native_window = window->window();
if (!native_window) if (!native_window)

View file

@ -19,6 +19,9 @@ PowerMonitor::PowerMonitor() {
} }
PowerMonitor::~PowerMonitor() { PowerMonitor::~PowerMonitor() {
}
void PowerMonitor::Destroy() {
base::PowerMonitor::Get()->RemoveObserver(this); base::PowerMonitor::Get()->RemoveObserver(this);
} }

View file

@ -5,7 +5,7 @@
#ifndef ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_ #ifndef ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_
#define ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_ #define ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_
#include "atom/browser/api/event_emitter.h" #include "atom/browser/api/trackable_object.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/power_monitor/power_observer.h" #include "base/power_monitor/power_observer.h"
#include "native_mate/handle.h" #include "native_mate/handle.h"
@ -14,14 +14,17 @@ namespace atom {
namespace api { namespace api {
class PowerMonitor : public mate::EventEmitter, class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
public base::PowerObserver { public base::PowerObserver {
public: public:
static v8::Local<v8::Value> Create(v8::Isolate* isolate); static v8::Local<v8::Value> Create(v8::Isolate* isolate);
protected: protected:
PowerMonitor(); PowerMonitor();
virtual ~PowerMonitor(); ~PowerMonitor() override;
// mate::TrackableObject:
void Destroy() override;
// base::PowerObserver implementations: // base::PowerObserver implementations:
void OnPowerStateChange(bool on_battery_power) override; void OnPowerStateChange(bool on_battery_power) override;

View file

@ -45,6 +45,11 @@ PowerSaveBlocker::PowerSaveBlocker()
PowerSaveBlocker::~PowerSaveBlocker() { PowerSaveBlocker::~PowerSaveBlocker() {
} }
void PowerSaveBlocker::Destroy() {
power_save_blocker_types_.clear();
power_save_blocker_.reset();
}
void PowerSaveBlocker::UpdatePowerSaveBlocker() { void PowerSaveBlocker::UpdatePowerSaveBlocker() {
if (power_save_blocker_types_.empty()) { if (power_save_blocker_types_.empty()) {
power_save_blocker_.reset(); power_save_blocker_.reset();

View file

@ -7,10 +7,10 @@
#include <map> #include <map>
#include "atom/browser/api/trackable_object.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "content/public/browser/power_save_blocker.h" #include "content/public/browser/power_save_blocker.h"
#include "native_mate/handle.h" #include "native_mate/handle.h"
#include "native_mate/wrappable.h"
namespace mate { namespace mate {
class Dictionary; class Dictionary;
@ -20,13 +20,16 @@ namespace atom {
namespace api { namespace api {
class PowerSaveBlocker : public mate::Wrappable { class PowerSaveBlocker : public mate::TrackableObject<PowerSaveBlocker> {
public: public:
static mate::Handle<PowerSaveBlocker> Create(v8::Isolate* isolate); static mate::Handle<PowerSaveBlocker> Create(v8::Isolate* isolate);
protected: protected:
PowerSaveBlocker(); PowerSaveBlocker();
virtual ~PowerSaveBlocker(); ~PowerSaveBlocker() override;
// mate::TrackableObject:
void Destroy() override;
// mate::Wrappable implementations: // mate::Wrappable implementations:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder( mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
@ -48,7 +51,6 @@ class PowerSaveBlocker : public mate::Wrappable {
std::map<int, content::PowerSaveBlocker::PowerSaveBlockerType>; std::map<int, content::PowerSaveBlocker::PowerSaveBlockerType>;
PowerSaveBlockerTypeMap power_save_blocker_types_; PowerSaveBlockerTypeMap power_save_blocker_types_;
DISALLOW_COPY_AND_ASSIGN(PowerSaveBlocker); DISALLOW_COPY_AND_ASSIGN(PowerSaveBlocker);
}; };

View file

@ -9,9 +9,10 @@
#include "atom/browser/api/atom_api_cookies.h" #include "atom/browser/api/atom_api_cookies.h"
#include "atom/browser/api/atom_api_download_item.h" #include "atom/browser/api/atom_api_download_item.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/api/save_page_handler.h" #include "atom/browser/api/save_page_handler.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h"
@ -395,14 +396,18 @@ mate::Handle<Session> Session::FromPartition(
static_cast<AtomBrowserContext*>(browser_context.get())); static_cast<AtomBrowserContext*>(browser_context.get()));
} }
void SetWrapSession(const WrapSessionCallback& callback) {
g_wrap_session = callback;
}
void ClearWrapSession() { void ClearWrapSession() {
g_wrap_session.Reset(); g_wrap_session.Reset();
} }
void SetWrapSession(const WrapSessionCallback& callback) {
g_wrap_session = callback;
// Cleanup the wrapper on exit.
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
base::Bind(ClearWrapSession));
}
} // namespace api } // namespace api
} // namespace atom } // namespace atom
@ -415,7 +420,6 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.SetMethod("fromPartition", &atom::api::Session::FromPartition); dict.SetMethod("fromPartition", &atom::api::Session::FromPartition);
dict.SetMethod("_setWrapSession", &atom::api::SetWrapSession); dict.SetMethod("_setWrapSession", &atom::api::SetWrapSession);
dict.SetMethod("_clearWrapSession", &atom::api::ClearWrapSession);
} }
} // namespace } // namespace

View file

@ -8,7 +8,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "atom/browser/api/event_emitter.h" #include "atom/browser/api/trackable_object.h"
#include "atom/browser/ui/tray_icon_observer.h" #include "atom/browser/ui/tray_icon_observer.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
@ -29,7 +29,7 @@ namespace api {
class Menu; class Menu;
class Tray : public mate::EventEmitter, class Tray : public mate::TrackableObject<Tray>,
public TrayIconObserver { public TrayIconObserver {
public: public:
static mate::Wrappable* New(v8::Isolate* isolate, const gfx::Image& image); static mate::Wrappable* New(v8::Isolate* isolate, const gfx::Image& image);
@ -39,7 +39,7 @@ class Tray : public mate::EventEmitter,
protected: protected:
explicit Tray(const gfx::Image& image); explicit Tray(const gfx::Image& image);
virtual ~Tray(); ~Tray() override;
// TrayIconObserver: // TrayIconObserver:
void OnClicked(const gfx::Rect& bounds, int modifiers) override; void OnClicked(const gfx::Rect& bounds, int modifiers) override;
@ -53,7 +53,9 @@ class Tray : public mate::EventEmitter,
// mate::Wrappable: // mate::Wrappable:
bool IsDestroyed() const override; bool IsDestroyed() const override;
void Destroy(); // mate::TrackableObject:
void Destroy() override;
void SetImage(mate::Arguments* args, const gfx::Image& image); void SetImage(mate::Arguments* args, const gfx::Image& image);
void SetPressedImage(mate::Arguments* args, const gfx::Image& image); void SetPressedImage(mate::Arguments* args, const gfx::Image& image);
void SetToolTip(mate::Arguments* args, const std::string& tool_tip); void SetToolTip(mate::Arguments* args, const std::string& tool_tip);

View file

@ -1124,14 +1124,18 @@ mate::Handle<WebContents> WebContents::Create(
return handle; return handle;
} }
void SetWrapWebContents(const WrapWebContentsCallback& callback) {
g_wrap_web_contents = callback;
}
void ClearWrapWebContents() { void ClearWrapWebContents() {
g_wrap_web_contents.Reset(); g_wrap_web_contents.Reset();
} }
void SetWrapWebContents(const WrapWebContentsCallback& callback) {
g_wrap_web_contents = callback;
// Cleanup the wrapper on exit.
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
base::Bind(ClearWrapWebContents));
}
} // namespace api } // namespace api
} // namespace atom } // namespace atom
@ -1145,7 +1149,6 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.SetMethod("create", &atom::api::WebContents::Create); dict.SetMethod("create", &atom::api::WebContents::Create);
dict.SetMethod("_setWrapWebContents", &atom::api::SetWrapWebContents); dict.SetMethod("_setWrapWebContents", &atom::api::SetWrapWebContents);
dict.SetMethod("_clearWrapWebContents", &atom::api::ClearWrapWebContents);
} }
} // namespace } // namespace

View file

@ -11,14 +11,14 @@ wrapSession = (session) ->
# session is an Event Emitter. # session is an Event Emitter.
session.__proto__ = EventEmitter.prototype session.__proto__ = EventEmitter.prototype
wrapDownloadItem = (download_item) -> wrapDownloadItem = (downloadItem) ->
# download_item is an Event Emitter. # downloadItem is an Event Emitter.
download_item.__proto__ = EventEmitter.prototype downloadItem.__proto__ = EventEmitter.prototype
# Be compatible with old APIs. # Be compatible with old APIs.
download_item.url = download_item.getUrl() downloadItem.url = downloadItem.getUrl()
download_item.filename = download_item.getFilename() downloadItem.filename = downloadItem.getFilename()
download_item.mimeType = download_item.getMimeType() downloadItem.mimeType = downloadItem.getMimeType()
download_item.hasUserGesture = download_item.hasUserGesture() downloadItem.hasUserGesture = downloadItem.hasUserGesture()
app.setApplicationMenu = (menu) -> app.setApplicationMenu = (menu) ->
require('menu').setApplicationMenu menu require('menu').setApplicationMenu menu
@ -57,12 +57,9 @@ app.setDataPath = (path) -> @setPath 'userData', path
app.resolveProxy = -> @defaultSession.resolveProxy.apply @defaultSession, arguments app.resolveProxy = -> @defaultSession.resolveProxy.apply @defaultSession, arguments
app.on 'activate', (event, hasVisibleWindows) -> @emit 'activate-with-no-open-windows' if not hasVisibleWindows app.on 'activate', (event, hasVisibleWindows) -> @emit 'activate-with-no-open-windows' if not hasVisibleWindows
# Session wrapper. # Wrappers for native classes.
sessionBindings._setWrapSession wrapSession sessionBindings._setWrapSession wrapSession
process.once 'exit', sessionBindings._clearWrapSession
downloadItemBindings._setWrapDownloadItem wrapDownloadItem downloadItemBindings._setWrapDownloadItem wrapDownloadItem
process.once 'exit', downloadItemBindings._clearWrapDownloadItem
# Only one App object pemitted. # Only one App object pemitted.
module.exports = app module.exports = app

View file

@ -112,7 +112,6 @@ wrapWebContents = (webContents) ->
@_printToPDF printingSetting, callback @_printToPDF printingSetting, callback
binding._setWrapWebContents wrapWebContents binding._setWrapWebContents wrapWebContents
process.once 'exit', binding._clearWrapWebContents
module.exports.create = (options={}) -> module.exports.create = (options={}) ->
binding.create(options) binding.create(options)

View file

@ -128,11 +128,23 @@ void AtomBrowserMainParts::PostMainMessageLoopStart() {
void AtomBrowserMainParts::PostMainMessageLoopRun() { void AtomBrowserMainParts::PostMainMessageLoopRun() {
brightray::BrowserMainParts::PostMainMessageLoopRun(); brightray::BrowserMainParts::PostMainMessageLoopRun();
#if defined(OS_MACOSX)
FreeAppDelegate();
#endif
// Make sure destruction callbacks are called before message loop is // Make sure destruction callbacks are called before message loop is
// destroyed, otherwise some objects that need to be deleted on IO thread // destroyed, otherwise some objects that need to be deleted on IO thread
// won't be freed. // won't be freed.
for (const auto& callback : destruction_callbacks_) for (const auto& callback : destruction_callbacks_)
callback.Run(); callback.Run();
// Destroy JavaScript environment immediately after running destruction
// callbacks.
gc_timer_.Stop();
node_debugger_.reset();
atom_bindings_.reset();
node_bindings_.reset();
js_env_.reset();
} }
} // namespace atom } // namespace atom

View file

@ -46,7 +46,6 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
void PostMainMessageLoopRun() override; void PostMainMessageLoopRun() override;
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
void PreMainMessageLoopStart() override; void PreMainMessageLoopStart() override;
void PostDestroyThreads() override;
#endif #endif
private: private:
@ -56,6 +55,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
void HandleShutdownSignals(); void HandleShutdownSignals();
#endif #endif
#if defined(OS_MACOSX)
void FreeAppDelegate();
#endif
// A fake BrowserProcess object that used to feed the source code from chrome. // A fake BrowserProcess object that used to feed the source code from chrome.
scoped_ptr<BrowserProcess> fake_browser_process_; scoped_ptr<BrowserProcess> fake_browser_process_;

View file

@ -34,7 +34,7 @@ void AtomBrowserMainParts::PreMainMessageLoopStart() {
setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
} }
void AtomBrowserMainParts::PostDestroyThreads() { void AtomBrowserMainParts::FreeAppDelegate() {
[[NSApp delegate] release]; [[NSApp delegate] release];
[NSApp setDelegate:nil]; [NSApp setDelegate:nil];
} }