diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 8a66c041f4..5228c640f0 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -531,9 +531,10 @@ mate::Handle App::Create(v8::Isolate* isolate) { // static void App::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "App")); auto browser = base::Unretained(Browser::Get()); - mate::ObjectTemplateBuilder(isolate, prototype) + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("quit", base::Bind(&Browser::Quit, browser)) .SetMethod("exit", base::Bind(&Browser::Exit, browser)) .SetMethod("focus", base::Bind(&Browser::Focus, browser)) @@ -638,6 +639,7 @@ void Initialize(v8::Local exports, v8::Local unused, auto command_line = base::CommandLine::ForCurrentProcess(); mate::Dictionary dict(isolate, exports); + dict.Set("App", atom::api::App::GetConstructor(isolate)->GetFunction()); dict.Set("app", atom::api::App::Create(isolate)); dict.SetMethod("appendSwitch", &AppendSwitch); dict.SetMethod("appendArgument", @@ -656,6 +658,7 @@ void Initialize(v8::Local exports, v8::Local unused, base::Bind(&Browser::DockGetBadgeText, browser)); dict.SetMethod("dockHide", base::Bind(&Browser::DockHide, browser)); dict.SetMethod("dockShow", base::Bind(&Browser::DockShow, browser)); + dict.SetMethod("dockIsVisible", base::Bind(&Browser::DockIsVisible, browser)); dict.SetMethod("dockSetMenu", &DockSetMenu); dict.SetMethod("dockSetIcon", base::Bind(&Browser::DockSetIcon, browser)); #endif diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 13cedaa7d8..990199cd6f 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -40,7 +40,7 @@ class App : public AtomBrowserClient::Delegate, static mate::Handle Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); // Called when window with disposition needs to be created. void OnCreateWindow(const GURL& target_url, diff --git a/atom/browser/api/atom_api_auto_updater.cc b/atom/browser/api/atom_api_auto_updater.cc index f8d9a2f9ac..83e5505a19 100644 --- a/atom/browser/api/atom_api_auto_updater.cc +++ b/atom/browser/api/atom_api_auto_updater.cc @@ -106,8 +106,9 @@ mate::Handle AutoUpdater::Create(v8::Isolate* isolate) { // static void AutoUpdater::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "AutoUpdater")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates) .SetMethod("getFeedURL", &auto_updater::AutoUpdater::GetFeedURL) .SetMethod("setFeedURL", &AutoUpdater::SetFeedURL) @@ -121,11 +122,14 @@ void AutoUpdater::BuildPrototype( namespace { +using atom::api::AutoUpdater; + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { v8::Isolate* isolate = context->GetIsolate(); mate::Dictionary dict(isolate, exports); - dict.Set("autoUpdater", atom::api::AutoUpdater::Create(isolate)); + dict.Set("autoUpdater", AutoUpdater::Create(isolate)); + dict.Set("AutoUpdater", AutoUpdater::GetConstructor(isolate)->GetFunction()); } } // namespace diff --git a/atom/browser/api/atom_api_auto_updater.h b/atom/browser/api/atom_api_auto_updater.h index 4c73f7ce8e..83a66146a3 100644 --- a/atom/browser/api/atom_api_auto_updater.h +++ b/atom/browser/api/atom_api_auto_updater.h @@ -24,7 +24,7 @@ class AutoUpdater : public mate::EventEmitter, static mate::Handle Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); protected: explicit AutoUpdater(v8::Isolate* isolate); diff --git a/atom/browser/api/atom_api_cookies.cc b/atom/browser/api/atom_api_cookies.cc index 4ee2190219..86cc59847b 100644 --- a/atom/browser/api/atom_api_cookies.cc +++ b/atom/browser/api/atom_api_cookies.cc @@ -248,8 +248,9 @@ mate::Handle Cookies::Create( // static void Cookies::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "Cookies")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("get", &Cookies::Get) .SetMethod("remove", &Cookies::Remove) .SetMethod("set", &Cookies::Set); diff --git a/atom/browser/api/atom_api_cookies.h b/atom/browser/api/atom_api_cookies.h index ce20c77597..5f60cb7ab4 100644 --- a/atom/browser/api/atom_api_cookies.h +++ b/atom/browser/api/atom_api_cookies.h @@ -41,7 +41,7 @@ class Cookies : public mate::TrackableObject { // mate::TrackableObject: static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); protected: Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context); diff --git a/atom/browser/api/atom_api_debugger.cc b/atom/browser/api/atom_api_debugger.cc index 48b7a6f70c..88d2a7adf4 100644 --- a/atom/browser/api/atom_api_debugger.cc +++ b/atom/browser/api/atom_api_debugger.cc @@ -23,14 +23,6 @@ namespace atom { namespace api { -namespace { - -// The wrapDebugger funtion which is implemented in JavaScript. -using WrapDebuggerCallback = base::Callback)>; -WrapDebuggerCallback g_wrap_debugger; - -} // namespace - Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents) : web_contents_(web_contents), previous_request_id_(0) { @@ -151,37 +143,33 @@ void Debugger::SendCommand(mate::Arguments* args) { mate::Handle Debugger::Create( v8::Isolate* isolate, content::WebContents* web_contents) { - auto handle = mate::CreateHandle( - isolate, new Debugger(isolate, web_contents)); - g_wrap_debugger.Run(handle.ToV8()); - return handle; + return mate::CreateHandle(isolate, new Debugger(isolate, web_contents)); } // static void Debugger::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "Debugger")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("attach", &Debugger::Attach) .SetMethod("isAttached", &Debugger::IsAttached) .SetMethod("detach", &Debugger::Detach) .SetMethod("sendCommand", &Debugger::SendCommand); } -void SetWrapDebugger(const WrapDebuggerCallback& callback) { - g_wrap_debugger = callback; -} - } // namespace api } // namespace atom namespace { +using atom::api::Debugger; + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { v8::Isolate* isolate = context->GetIsolate(); - mate::Dictionary dict(isolate, exports); - dict.SetMethod("_setWrapDebugger", &atom::api::SetWrapDebugger); + mate::Dictionary(isolate, exports) + .Set("Debugger", Debugger::GetConstructor(isolate)->GetFunction()); } } // namespace diff --git a/atom/browser/api/atom_api_debugger.h b/atom/browser/api/atom_api_debugger.h index 1e97fa89ab..2f7106efd7 100644 --- a/atom/browser/api/atom_api_debugger.h +++ b/atom/browser/api/atom_api_debugger.h @@ -39,7 +39,7 @@ class Debugger: public mate::TrackableObject, // mate::TrackableObject: static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); protected: Debugger(v8::Isolate* isolate, content::WebContents* web_contents); diff --git a/atom/browser/api/atom_api_desktop_capturer.cc b/atom/browser/api/atom_api_desktop_capturer.cc index 3cb29a9124..1ff5aadc0f 100644 --- a/atom/browser/api/atom_api_desktop_capturer.cc +++ b/atom/browser/api/atom_api_desktop_capturer.cc @@ -99,8 +99,9 @@ mate::Handle DesktopCapturer::Create(v8::Isolate* isolate) { // static void DesktopCapturer::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "DesktopCapturer")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("startHandling", &DesktopCapturer::StartHandling); } diff --git a/atom/browser/api/atom_api_desktop_capturer.h b/atom/browser/api/atom_api_desktop_capturer.h index 4d1755e068..571f08bcfc 100644 --- a/atom/browser/api/atom_api_desktop_capturer.h +++ b/atom/browser/api/atom_api_desktop_capturer.h @@ -20,7 +20,7 @@ class DesktopCapturer: public mate::EventEmitter, static mate::Handle Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); void StartHandling(bool capture_window, bool capture_screen, diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index 81107abcea..05261a64f0 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -11,7 +11,6 @@ #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/node_includes.h" -#include "base/memory/linked_ptr.h" #include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" #include "native_mate/dictionary.h" @@ -52,11 +51,7 @@ namespace api { namespace { -// The wrapDownloadItem funtion which is implemented in JavaScript -using WrapDownloadItemCallback = base::Callback)>; -WrapDownloadItemCallback g_wrap_download_item; - -std::map>> g_download_item_objects; +std::map> g_download_item_objects; } // namespace @@ -76,9 +71,7 @@ DownloadItem::~DownloadItem() { } // Remove from the global map. - auto iter = g_download_item_objects.find(weak_map_id()); - if (iter != g_download_item_objects.end()) - g_download_item_objects.erase(iter); + g_download_item_objects.erase(weak_map_id()); } void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) { @@ -170,8 +163,9 @@ base::FilePath DownloadItem::GetSavePath() const { // static void DownloadItem::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "DownloadItem")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .MakeDestroyable() .SetMethod("pause", &DownloadItem::Pause) .SetMethod("isPaused", &DownloadItem::IsPaused) @@ -199,18 +193,13 @@ mate::Handle DownloadItem::Create( return mate::CreateHandle(isolate, static_cast(existing)); auto handle = mate::CreateHandle(isolate, new DownloadItem(isolate, item)); - g_wrap_download_item.Run(handle.ToV8()); // Reference this object in case it got garbage collected. - g_download_item_objects[handle->weak_map_id()] = make_linked_ptr( - new v8::Global(isolate, handle.ToV8())); + g_download_item_objects[handle->weak_map_id()] = + v8::Global(isolate, handle.ToV8()); return handle; } -void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) { - g_wrap_download_item = callback; -} - } // namespace api } // namespace atom @@ -220,8 +209,9 @@ namespace { void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { v8::Isolate* isolate = context->GetIsolate(); - mate::Dictionary dict(isolate, exports); - dict.SetMethod("_setWrapDownloadItem", &atom::api::SetWrapDownloadItem); + mate::Dictionary(isolate, exports) + .Set("DownloadItem", + atom::api::DownloadItem::GetConstructor(isolate)->GetFunction()); } } // namespace diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h index fa330b90a0..332c8cebb8 100644 --- a/atom/browser/api/atom_api_download_item.h +++ b/atom/browser/api/atom_api_download_item.h @@ -24,7 +24,7 @@ class DownloadItem : public mate::TrackableObject, content::DownloadItem* item); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); void Pause(); bool IsPaused() const; diff --git a/atom/browser/api/atom_api_global_shortcut.cc b/atom/browser/api/atom_api_global_shortcut.cc index 2b1e5d6591..039d708a7c 100644 --- a/atom/browser/api/atom_api_global_shortcut.cc +++ b/atom/browser/api/atom_api_global_shortcut.cc @@ -74,8 +74,9 @@ mate::Handle GlobalShortcut::Create(v8::Isolate* isolate) { // static void GlobalShortcut::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "GlobalShortcut")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("register", &GlobalShortcut::Register) .SetMethod("isRegistered", &GlobalShortcut::IsRegistered) .SetMethod("unregister", &GlobalShortcut::Unregister) diff --git a/atom/browser/api/atom_api_global_shortcut.h b/atom/browser/api/atom_api_global_shortcut.h index 41eb42f855..b023aec4a8 100644 --- a/atom/browser/api/atom_api_global_shortcut.h +++ b/atom/browser/api/atom_api_global_shortcut.h @@ -24,7 +24,7 @@ class GlobalShortcut : public extensions::GlobalShortcutListener::Observer, static mate::Handle Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); protected: explicit GlobalShortcut(v8::Isolate* isolate); diff --git a/atom/browser/api/atom_api_menu.cc b/atom/browser/api/atom_api_menu.cc index 54a3d4e813..627ce601f5 100644 --- a/atom/browser/api/atom_api_menu.cc +++ b/atom/browser/api/atom_api_menu.cc @@ -19,9 +19,10 @@ namespace atom { namespace api { -Menu::Menu(v8::Isolate* isolate) +Menu::Menu(v8::Isolate* isolate, v8::Local wrapper) : model_(new AtomMenuModel(this)), parent_(nullptr) { + InitWith(isolate, wrapper); } Menu::~Menu() { @@ -154,8 +155,9 @@ bool Menu::IsVisibleAt(int index) const { // static void Menu::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "Menu")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .MakeDestroyable() .SetMethod("insertItem", &Menu::InsertItemAt) .SetMethod("insertCheckItem", &Menu::InsertCheckItemAt) @@ -184,14 +186,15 @@ void Menu::BuildPrototype(v8::Isolate* isolate, namespace { +using atom::api::Menu; + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { - using atom::api::Menu; v8::Isolate* isolate = context->GetIsolate(); - v8::Local constructor = mate::CreateConstructor( - isolate, "Menu", base::Bind(&Menu::Create)); + Menu::SetConstructor(isolate, base::Bind(&Menu::New)); + mate::Dictionary dict(isolate, exports); - dict.Set("Menu", static_cast>(constructor)); + dict.Set("Menu", Menu::GetConstructor(isolate)->GetFunction()); #if defined(OS_MACOSX) dict.SetMethod("setApplicationMenu", &Menu::SetApplicationMenu); dict.SetMethod("sendActionToFirstResponder", diff --git a/atom/browser/api/atom_api_menu.h b/atom/browser/api/atom_api_menu.h index e04d189efc..97b6360049 100644 --- a/atom/browser/api/atom_api_menu.h +++ b/atom/browser/api/atom_api_menu.h @@ -20,10 +20,10 @@ namespace api { class Menu : public mate::TrackableObject, public AtomMenuModel::Delegate { public: - static mate::WrappableBase* Create(v8::Isolate* isolate); + static mate::WrappableBase* New(mate::Arguments* args); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); #if defined(OS_MACOSX) // Set the global menubar. @@ -36,7 +36,7 @@ class Menu : public mate::TrackableObject, AtomMenuModel* model() const { return model_.get(); } protected: - explicit Menu(v8::Isolate* isolate); + Menu(v8::Isolate* isolate, v8::Local wrapper); ~Menu() override; // mate::Wrappable: diff --git a/atom/browser/api/atom_api_menu_mac.h b/atom/browser/api/atom_api_menu_mac.h index 062fd9be41..d318b7bdc0 100644 --- a/atom/browser/api/atom_api_menu_mac.h +++ b/atom/browser/api/atom_api_menu_mac.h @@ -17,7 +17,7 @@ namespace api { class MenuMac : public Menu { protected: - explicit MenuMac(v8::Isolate* isolate); + MenuMac(v8::Isolate* isolate, v8::Local wrapper); void PopupAt(Window* window, int x, int y, int positioning_item) override; diff --git a/atom/browser/api/atom_api_menu_mac.mm b/atom/browser/api/atom_api_menu_mac.mm index 6a7d43b4da..9e901d1098 100644 --- a/atom/browser/api/atom_api_menu_mac.mm +++ b/atom/browser/api/atom_api_menu_mac.mm @@ -18,7 +18,8 @@ namespace atom { namespace api { -MenuMac::MenuMac(v8::Isolate* isolate) : Menu(isolate) { +MenuMac::MenuMac(v8::Isolate* isolate, v8::Local wrapper) + : Menu(isolate, wrapper) { } void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) { @@ -94,8 +95,8 @@ void Menu::SendActionToFirstResponder(const std::string& action) { } // static -mate::WrappableBase* Menu::Create(v8::Isolate* isolate) { - return new MenuMac(isolate); +mate::WrappableBase* Menu::New(mate::Arguments* args) { + return new MenuMac(args->isolate(), args->GetThis()); } } // namespace api diff --git a/atom/browser/api/atom_api_menu_views.cc b/atom/browser/api/atom_api_menu_views.cc index a6fd8024ab..8a72247c9d 100644 --- a/atom/browser/api/atom_api_menu_views.cc +++ b/atom/browser/api/atom_api_menu_views.cc @@ -14,7 +14,8 @@ namespace atom { namespace api { -MenuViews::MenuViews(v8::Isolate* isolate) : Menu(isolate) { +MenuViews::MenuViews(v8::Isolate* isolate, v8::Local wrapper) + : Menu(isolate, wrapper) { } void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item) { @@ -53,8 +54,8 @@ void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item) { } // static -mate::WrappableBase* Menu::Create(v8::Isolate* isolate) { - return new MenuViews(isolate); +mate::WrappableBase* Menu::New(mate::Arguments* args) { + return new MenuViews(args->isolate(), args->GetThis()); } } // namespace api diff --git a/atom/browser/api/atom_api_menu_views.h b/atom/browser/api/atom_api_menu_views.h index 9b4ddf77f2..1e7abd1372 100644 --- a/atom/browser/api/atom_api_menu_views.h +++ b/atom/browser/api/atom_api_menu_views.h @@ -14,7 +14,7 @@ namespace api { class MenuViews : public Menu { public: - explicit MenuViews(v8::Isolate* isolate); + MenuViews(v8::Isolate* isolate, v8::Local wrapper); protected: void PopupAt(Window* window, int x, int y, int positioning_item) override; diff --git a/atom/browser/api/atom_api_power_monitor.cc b/atom/browser/api/atom_api_power_monitor.cc index 32c50c696c..02b61e8f4b 100644 --- a/atom/browser/api/atom_api_power_monitor.cc +++ b/atom/browser/api/atom_api_power_monitor.cc @@ -52,8 +52,8 @@ v8::Local PowerMonitor::Create(v8::Isolate* isolate) { // static void PowerMonitor::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype); + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "PowerMonitor")); } } // namespace api @@ -63,16 +63,19 @@ void PowerMonitor::BuildPrototype( namespace { +using atom::api::PowerMonitor; + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { #if defined(OS_MACOSX) base::PowerMonitorDeviceSource::AllocateSystemIOPorts(); #endif - using atom::api::PowerMonitor; v8::Isolate* isolate = context->GetIsolate(); mate::Dictionary dict(isolate, exports); dict.Set("powerMonitor", PowerMonitor::Create(isolate)); + dict.Set("PowerMonitor", + PowerMonitor::GetConstructor(isolate)->GetFunction()); } } // namespace diff --git a/atom/browser/api/atom_api_power_monitor.h b/atom/browser/api/atom_api_power_monitor.h index 50d4bb466c..94717e4c90 100644 --- a/atom/browser/api/atom_api_power_monitor.h +++ b/atom/browser/api/atom_api_power_monitor.h @@ -20,7 +20,7 @@ class PowerMonitor : public mate::TrackableObject, static v8::Local Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); protected: explicit PowerMonitor(v8::Isolate* isolate); diff --git a/atom/browser/api/atom_api_power_save_blocker.cc b/atom/browser/api/atom_api_power_save_blocker.cc index 67c9b6dd83..0f017be5fb 100644 --- a/atom/browser/api/atom_api_power_save_blocker.cc +++ b/atom/browser/api/atom_api_power_save_blocker.cc @@ -105,8 +105,9 @@ mate::Handle PowerSaveBlocker::Create(v8::Isolate* isolate) { // static void PowerSaveBlocker::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "PowerSaveBlocker")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("start", &PowerSaveBlocker::Start) .SetMethod("stop", &PowerSaveBlocker::Stop) .SetMethod("isStarted", &PowerSaveBlocker::IsStarted); diff --git a/atom/browser/api/atom_api_power_save_blocker.h b/atom/browser/api/atom_api_power_save_blocker.h index ee1e0e3213..0687106ab8 100644 --- a/atom/browser/api/atom_api_power_save_blocker.h +++ b/atom/browser/api/atom_api_power_save_blocker.h @@ -25,7 +25,7 @@ class PowerSaveBlocker : public mate::TrackableObject { static mate::Handle Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); protected: explicit PowerSaveBlocker(v8::Isolate* isolate); diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 4019a96f2a..eaed0c6dca 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -160,8 +160,9 @@ mate::Handle Protocol::Create( // static void Protocol::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "Protocol")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("registerServiceWorkerSchemes", &Protocol::RegisterServiceWorkerSchemes) .SetMethod("registerStringProtocol", diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index b5d47def68..969fe7f665 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -39,7 +39,7 @@ class Protocol : public mate::TrackableObject { v8::Isolate* isolate, AtomBrowserContext* browser_context); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); protected: Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context); diff --git a/atom/browser/api/atom_api_render_process_preferences.cc b/atom/browser/api/atom_api_render_process_preferences.cc index 3d9495d932..d5017122dd 100644 --- a/atom/browser/api/atom_api_render_process_preferences.cc +++ b/atom/browser/api/atom_api_render_process_preferences.cc @@ -53,8 +53,10 @@ void RenderProcessPreferences::RemoveEntry(int id) { // static void RenderProcessPreferences::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName( + mate::StringToV8(isolate, "RenderProcessPreferences")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("addEntry", &RenderProcessPreferences::AddEntry) .SetMethod("removeEntry", &RenderProcessPreferences::RemoveEntry); } diff --git a/atom/browser/api/atom_api_render_process_preferences.h b/atom/browser/api/atom_api_render_process_preferences.h index 3fa197ed04..19cc0d8821 100644 --- a/atom/browser/api/atom_api_render_process_preferences.h +++ b/atom/browser/api/atom_api_render_process_preferences.h @@ -20,7 +20,7 @@ class RenderProcessPreferences ForAllWebContents(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); int AddEntry(const base::DictionaryValue& entry); void RemoveEntry(int id); diff --git a/atom/browser/api/atom_api_screen.cc b/atom/browser/api/atom_api_screen.cc index 68f4baeaf2..dfdd3450eb 100644 --- a/atom/browser/api/atom_api_screen.cc +++ b/atom/browser/api/atom_api_screen.cc @@ -113,8 +113,9 @@ v8::Local Screen::Create(v8::Isolate* isolate) { // static void Screen::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "Screen")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint) .SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay) .SetMethod("getAllDisplays", &Screen::GetAllDisplays) @@ -128,10 +129,14 @@ void Screen::BuildPrototype( namespace { +using atom::api::Screen; + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { - mate::Dictionary dict(context->GetIsolate(), exports); - dict.Set("screen", atom::api::Screen::Create(context->GetIsolate())); + v8::Isolate* isolate = context->GetIsolate(); + mate::Dictionary dict(isolate, exports); + dict.Set("screen", Screen::Create(isolate)); + dict.Set("Screen", Screen::GetConstructor(isolate)->GetFunction()); } } // namespace diff --git a/atom/browser/api/atom_api_screen.h b/atom/browser/api/atom_api_screen.h index feff6ddfff..2bbaa13f6d 100644 --- a/atom/browser/api/atom_api_screen.h +++ b/atom/browser/api/atom_api_screen.h @@ -28,7 +28,7 @@ class Screen : public mate::EventEmitter, static v8::Local Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); protected: Screen(v8::Isolate* isolate, display::Screen* screen); diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 02fafddf94..58de02f2ff 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -4,6 +4,7 @@ #include "atom/browser/api/atom_api_session.h" +#include #include #include @@ -169,9 +170,8 @@ namespace { const char kPersistPrefix[] = "persist:"; -// The wrapSession funtion which is implemented in JavaScript -using WrapSessionCallback = base::Callback)>; -WrapSessionCallback g_wrap_session; +// Referenced session objects. +std::map> g_sessions; class ResolveProxyHelper { public: @@ -346,6 +346,7 @@ Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context) Session::~Session() { content::BrowserContext::GetDownloadManager(browser_context())-> RemoveObserver(this); + g_sessions.erase(weak_map_id()); } void Session::OnDownloadCreated(content::DownloadManager* manager, @@ -536,7 +537,12 @@ mate::Handle Session::CreateFrom( auto handle = mate::CreateHandle( isolate, new Session(isolate, browser_context)); - g_wrap_session.Run(handle.ToV8()); + + // The Sessions should never be garbage collected, since the common pattern is + // to use partition strings, instead of using the Session object directly. + g_sessions[handle->weak_map_id()] = + v8::Global(isolate, handle.ToV8()); + return handle; } @@ -559,8 +565,9 @@ mate::Handle Session::FromPartition( // static void Session::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "Session")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .MakeDestroyable() .SetMethod("resolveProxy", &Session::ResolveProxy) .SetMethod("getCacheSize", &Session::DoCacheAction) @@ -584,16 +591,14 @@ void Session::BuildPrototype(v8::Isolate* isolate, .SetProperty("webRequest", &Session::WebRequest); } -void SetWrapSession(const WrapSessionCallback& callback) { - g_wrap_session = callback; -} - } // namespace api } // namespace atom namespace { +using atom::api::Session; + v8::Local FromPartition( const std::string& partition, mate::Arguments* args) { if (!atom::Browser::Get()->is_ready()) { @@ -602,16 +607,15 @@ v8::Local FromPartition( } base::DictionaryValue options; args->GetNext(&options); - return atom::api::Session::FromPartition( - args->isolate(), partition, options).ToV8(); + return Session::FromPartition(args->isolate(), partition, options).ToV8(); } void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { v8::Isolate* isolate = context->GetIsolate(); mate::Dictionary dict(isolate, exports); + dict.Set("Session", Session::GetConstructor(isolate)->GetFunction()); dict.SetMethod("fromPartition", &FromPartition); - dict.SetMethod("_setWrapSession", &atom::api::SetWrapSession); } } // namespace diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index c3bb82eeba..18189cf7e5 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -57,7 +57,7 @@ class Session: public mate::TrackableObject, // mate::TrackableObject: static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); // Methods. void ResolveProxy(const GURL& url, ResolveProxyCallback callback); diff --git a/atom/browser/api/atom_api_system_preferences.cc b/atom/browser/api/atom_api_system_preferences.cc index c3421365f0..618a9dff5b 100644 --- a/atom/browser/api/atom_api_system_preferences.cc +++ b/atom/browser/api/atom_api_system_preferences.cc @@ -44,8 +44,9 @@ mate::Handle SystemPreferences::Create( // static void SystemPreferences::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "SystemPreferences")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) #if defined(OS_WIN) .SetMethod("isAeroGlassEnabled", &SystemPreferences::IsAeroGlassEnabled) #elif defined(OS_MACOSX) @@ -68,11 +69,15 @@ void SystemPreferences::BuildPrototype( namespace { +using atom::api::SystemPreferences; + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { v8::Isolate* isolate = context->GetIsolate(); mate::Dictionary dict(isolate, exports); - dict.Set("systemPreferences", atom::api::SystemPreferences::Create(isolate)); + dict.Set("systemPreferences", SystemPreferences::Create(isolate)); + dict.Set("SystemPreferences", + SystemPreferences::GetConstructor(isolate)->GetFunction()); } } // namespace diff --git a/atom/browser/api/atom_api_system_preferences.h b/atom/browser/api/atom_api_system_preferences.h index 9a5cf99035..0d1f954b7a 100644 --- a/atom/browser/api/atom_api_system_preferences.h +++ b/atom/browser/api/atom_api_system_preferences.h @@ -24,7 +24,7 @@ class SystemPreferences : public mate::EventEmitter { static mate::Handle Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); #if defined(OS_WIN) bool IsAeroGlassEnabled(); diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index 213ddbfd89..3f0386ab70 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -60,10 +60,13 @@ namespace atom { namespace api { -Tray::Tray(v8::Isolate* isolate, mate::Handle image) +Tray::Tray(v8::Isolate* isolate, v8::Local wrapper, + mate::Handle image) : tray_icon_(TrayIcon::Create()) { SetImage(isolate, image); tray_icon_->AddObserver(this); + + InitWith(isolate, wrapper); } Tray::~Tray() { @@ -72,14 +75,13 @@ Tray::~Tray() { } // static -mate::WrappableBase* Tray::New(v8::Isolate* isolate, - mate::Handle image) { +mate::WrappableBase* Tray::New(mate::Handle image, + mate::Arguments* args) { if (!Browser::Get()->is_ready()) { - isolate->ThrowException(v8::Exception::Error(mate::StringToV8( - isolate, "Cannot create Tray before app is ready"))); + args->ThrowError("Cannot create Tray before app is ready"); return nullptr; } - return new Tray(isolate, image); + return new Tray(args->isolate(), args->GetThis(), image); } void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) { @@ -199,8 +201,9 @@ gfx::Rect Tray::GetBounds() { // static void Tray::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "Tray")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .MakeDestroyable() .SetMethod("setImage", &Tray::SetImage) .SetMethod("setPressedImage", &Tray::SetPressedImage) @@ -220,14 +223,15 @@ void Tray::BuildPrototype(v8::Isolate* isolate, namespace { +using atom::api::Tray; + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { - using atom::api::Tray; v8::Isolate* isolate = context->GetIsolate(); - v8::Local constructor = mate::CreateConstructor( - isolate, "Tray", base::Bind(&Tray::New)); + Tray::SetConstructor(isolate, base::Bind(&Tray::New)); + mate::Dictionary dict(isolate, exports); - dict.Set("Tray", static_cast>(constructor)); + dict.Set("Tray", Tray::GetConstructor(isolate)->GetFunction()); } } // namespace diff --git a/atom/browser/api/atom_api_tray.h b/atom/browser/api/atom_api_tray.h index 1e1bc13075..61ee72bedf 100644 --- a/atom/browser/api/atom_api_tray.h +++ b/atom/browser/api/atom_api_tray.h @@ -35,14 +35,15 @@ class NativeImage; class Tray : public mate::TrackableObject, public TrayIconObserver { public: - static mate::WrappableBase* New( - v8::Isolate* isolate, mate::Handle image); + static mate::WrappableBase* New(mate::Handle image, + mate::Arguments* args); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); protected: - Tray(v8::Isolate* isolate, mate::Handle image); + Tray(v8::Isolate* isolate, v8::Local wrapper, + mate::Handle image); ~Tray() override; // TrayIconObserver: diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index d590bebb57..79851030fa 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -228,10 +228,6 @@ namespace api { namespace { -// The wrapWebContents function which is implemented in JavaScript -using WrapWebContentsCallback = base::Callback)>; -WrapWebContentsCallback g_wrap_web_contents; - content::ServiceWorkerContext* GetServiceWorkerContext( const content::WebContents* web_contents) { auto context = web_contents->GetBrowserContext(); @@ -1458,8 +1454,9 @@ int WebContents::GetFrameRate() const { // static void WebContents::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "WebContents")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .MakeDestroyable() .SetMethod("getId", &WebContents::GetID) .SetMethod("equal", &WebContents::Equal) @@ -1569,41 +1566,32 @@ mate::Handle WebContents::CreateFrom( return mate::CreateHandle(isolate, static_cast(existing)); // Otherwise create a new WebContents wrapper object. - auto handle = mate::CreateHandle( - isolate, new WebContents(isolate, web_contents)); - g_wrap_web_contents.Run(handle.ToV8()); - return handle; + return mate::CreateHandle(isolate, new WebContents(isolate, web_contents)); } // static mate::Handle WebContents::Create( v8::Isolate* isolate, const mate::Dictionary& options) { - auto handle = mate::CreateHandle(isolate, new WebContents(isolate, options)); - g_wrap_web_contents.Run(handle.ToV8()); - return handle; -} - -void SetWrapWebContents(const WrapWebContentsCallback& callback) { - g_wrap_web_contents = callback; + return mate::CreateHandle(isolate, new WebContents(isolate, options)); } } // namespace api } // namespace atom - namespace { +using atom::api::WebContents; + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { v8::Isolate* isolate = context->GetIsolate(); mate::Dictionary dict(isolate, exports); - dict.SetMethod("create", &atom::api::WebContents::Create); - dict.SetMethod("_setWrapWebContents", &atom::api::SetWrapWebContents); - dict.SetMethod("fromId", - &mate::TrackableObject::FromWeakMapID); + dict.Set("WebContents", WebContents::GetConstructor(isolate)->GetFunction()); + dict.SetMethod("create", &WebContents::Create); + dict.SetMethod("fromId", &mate::TrackableObject::FromWeakMapID); dict.SetMethod("getAllWebContents", - &mate::TrackableObject::GetAll); + &mate::TrackableObject::GetAll); } } // namespace diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 641442e1fc..ba571cf02a 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -66,7 +66,7 @@ class WebContents : public mate::TrackableObject, v8::Isolate* isolate, const mate::Dictionary& options); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); int GetID() const; Type GetType() const; diff --git a/atom/browser/api/atom_api_web_request.cc b/atom/browser/api/atom_api_web_request.cc index 867901df06..2a39347d02 100644 --- a/atom/browser/api/atom_api_web_request.cc +++ b/atom/browser/api/atom_api_web_request.cc @@ -88,8 +88,9 @@ mate::Handle WebRequest::Create( // static void WebRequest::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "WebRequest")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("onBeforeRequest", &WebRequest::SetResponseListener< AtomNetworkDelegate::kOnBeforeRequest>) diff --git a/atom/browser/api/atom_api_web_request.h b/atom/browser/api/atom_api_web_request.h index edcdcc5339..b05a4e11b9 100644 --- a/atom/browser/api/atom_api_web_request.h +++ b/atom/browser/api/atom_api_web_request.h @@ -22,7 +22,7 @@ class WebRequest : public mate::TrackableObject { AtomBrowserContext* browser_context); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); protected: WebRequest(v8::Isolate* isolate, AtomBrowserContext* browser_context); diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 5f8b71b8f6..550372c577 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -69,7 +69,8 @@ v8::Local ToBuffer(v8::Isolate* isolate, void* val, int size) { } // namespace -Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) { +Window::Window(v8::Isolate* isolate, v8::Local wrapper, + const mate::Dictionary& options) { // Use options.webPreferences to create WebContents. mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate); options.Get(options::kWebPreferences, &web_preferences); @@ -113,7 +114,14 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) { window_->InitFromOptions(options); window_->AddObserver(this); + + InitWith(isolate, wrapper); AttachAsUserData(window_.get()); + + // We can only append this window to parent window's child windows after this + // window's JS wrapper gets initialized. + if (!parent.IsEmpty()) + parent->child_windows_.Set(isolate, ID(), wrapper); } Window::~Window() { @@ -125,17 +133,6 @@ Window::~Window() { base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release()); } -void Window::AfterInit(v8::Isolate* isolate) { - mate::TrackableObject::AfterInit(isolate); - - // We can only append this window to parent window's child windows after this - // window's JS wrapper gets initialized. - mate::Handle parent; - if (!parent_window_.IsEmpty() && - mate::ConvertFromV8(isolate, GetParentWindow(), &parent)) - parent->child_windows_.Set(isolate, ID(), GetWrapper()); -} - void Window::WillCloseWindow(bool* prevent_default) { *prevent_default = Emit("close"); } @@ -268,10 +265,9 @@ void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) { #endif // static -mate::WrappableBase* Window::New(v8::Isolate* isolate, mate::Arguments* args) { +mate::WrappableBase* Window::New(mate::Arguments* args) { if (!Browser::Get()->is_ready()) { - isolate->ThrowException(v8::Exception::Error(mate::StringToV8( - isolate, "Cannot create BrowserWindow before app is ready"))); + args->ThrowError("Cannot create BrowserWindow before app is ready"); return nullptr; } @@ -282,10 +278,10 @@ mate::WrappableBase* Window::New(v8::Isolate* isolate, mate::Arguments* args) { mate::Dictionary options; if (!(args->Length() == 1 && args->GetNext(&options))) { - options = mate::Dictionary::CreateEmpty(isolate); + options = mate::Dictionary::CreateEmpty(args->isolate()); } - return new Window(isolate, options); + return new Window(args->isolate(), args->GetThis(), options); } void Window::Close() { @@ -756,8 +752,9 @@ void Window::RemoveFromParentChildWindows() { // static void Window::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "BrowserWindow")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .MakeDestroyable() .SetMethod("close", &Window::Close) .SetMethod("focus", &Window::Focus) @@ -879,9 +876,10 @@ using atom::api::Window; void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { v8::Isolate* isolate = context->GetIsolate(); - v8::Local constructor = mate::CreateConstructor( - isolate, "BrowserWindow", base::Bind(&Window::New)); - mate::Dictionary browser_window(isolate, constructor); + Window::SetConstructor(isolate, base::Bind(&Window::New)); + + mate::Dictionary browser_window( + isolate, Window::GetConstructor(isolate)->GetFunction()); browser_window.SetMethod("fromId", &mate::TrackableObject::FromWeakMapID); browser_window.SetMethod("getAllWindows", diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 7736f835f7..5da7bd8d4b 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -40,10 +40,10 @@ class WebContents; class Window : public mate::TrackableObject, public NativeWindowObserver { public: - static mate::WrappableBase* New(v8::Isolate* isolate, mate::Arguments* args); + static mate::WrappableBase* New(mate::Arguments* args); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); // Returns the BrowserWindow object from |native_window|. static v8::Local From(v8::Isolate* isolate, @@ -52,12 +52,10 @@ class Window : public mate::TrackableObject, NativeWindow* window() const { return window_.get(); } protected: - Window(v8::Isolate* isolate, const mate::Dictionary& options); + Window(v8::Isolate* isolate, v8::Local wrapper, + const mate::Dictionary& options); ~Window() override; - // TrackableObject: - void AfterInit(v8::Isolate* isolate) override; - // NativeWindowObserver: void WillCloseWindow(bool* prevent_default) override; void WillDestoryNativeObject() override; diff --git a/atom/browser/api/event.cc b/atom/browser/api/event.cc index 8c60eda247..8810fed4b9 100644 --- a/atom/browser/api/event.cc +++ b/atom/browser/api/event.cc @@ -58,8 +58,9 @@ Handle Event::Create(v8::Isolate* isolate) { // static void Event::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "Event")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("preventDefault", &Event::PreventDefault) .SetMethod("sendReply", &Event::SendReply); } diff --git a/atom/browser/api/event.h b/atom/browser/api/event.h index 81db638a0d..f08802b4ed 100644 --- a/atom/browser/api/event.h +++ b/atom/browser/api/event.h @@ -21,7 +21,7 @@ class Event : public Wrappable, static Handle Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); // Pass the sender and message to be replied. void SetSenderAndMessage(content::WebContents* sender, IPC::Message* message); diff --git a/atom/browser/api/event_emitter.cc b/atom/browser/api/event_emitter.cc index e98008b85d..3dbcd0601e 100644 --- a/atom/browser/api/event_emitter.cc +++ b/atom/browser/api/event_emitter.cc @@ -10,6 +10,8 @@ #include "native_mate/object_template_builder.h" #include "ui/events/event_constants.h" +#include "atom/common/node_includes.h" + namespace mate { namespace { diff --git a/atom/browser/api/trackable_object.cc b/atom/browser/api/trackable_object.cc index 5148df627c..502757aa23 100644 --- a/atom/browser/api/trackable_object.cc +++ b/atom/browser/api/trackable_object.cc @@ -29,7 +29,7 @@ class IDUserData : public base::SupportsUserData::Data { } // namespace TrackableObjectBase::TrackableObjectBase() - : weak_map_id_(0), wrapped_(nullptr), weak_factory_(this) { + : weak_map_id_(0), weak_factory_(this) { cleanup_ = RegisterDestructionCallback(GetDestroyClosure()); } @@ -46,14 +46,7 @@ void TrackableObjectBase::Destroy() { } void TrackableObjectBase::AttachAsUserData(base::SupportsUserData* wrapped) { - if (weak_map_id_ != 0) { - wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_)); - wrapped_ = nullptr; - } else { - // If the TrackableObjectBase is not ready yet then delay SetUserData until - // AfterInit is called. - wrapped_ = wrapped; - } + wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_)); } // static diff --git a/atom/browser/api/trackable_object.h b/atom/browser/api/trackable_object.h index 2cb9428a00..3f04783bcd 100644 --- a/atom/browser/api/trackable_object.h +++ b/atom/browser/api/trackable_object.h @@ -44,7 +44,6 @@ class TrackableObjectBase { static base::Closure RegisterDestructionCallback(const base::Closure& c); int32_t weak_map_id_; - base::SupportsUserData* wrapped_; private: void Destroy(); @@ -110,14 +109,13 @@ class TrackableObject : public TrackableObjectBase, RemoveFromWeakMap(); } - void AfterInit(v8::Isolate* isolate) override { + void InitWith(v8::Isolate* isolate, v8::Local wrapper) override { + WrappableBase::InitWith(isolate, wrapper); if (!weak_map_) { weak_map_ = new atom::KeyWeakMap; } weak_map_id_ = ++next_id_; - weak_map_->Set(isolate, weak_map_id_, Wrappable::GetWrapper()); - if (wrapped_) - AttachAsUserData(wrapped_); + weak_map_->Set(isolate, weak_map_id_, wrapper); } private: diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 771a29a87a..96fad18fc7 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -136,6 +136,7 @@ class Browser : public WindowListObserver { // Hide/Show dock. void DockHide(); void DockShow(); + bool DockIsVisible(); // Set docks' menu. void DockSetMenu(AtomMenuModel* model); diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index d4b615e73e..2cfb4ca2cd 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -208,6 +208,12 @@ void Browser::DockHide() { TransformProcessType(&psn, kProcessTransformToUIElementApplication); } +bool Browser::DockIsVisible() { + // Because DockShow has a slight delay this may not be true immediately + // after that call. + return ([[NSRunningApplication currentApplication] activationPolicy] == NSApplicationActivationPolicyRegular); +} + void Browser::DockShow() { BOOL active = [[NSRunningApplication currentApplication] isActive]; ProcessSerialNumber psn = { 0, kCurrentProcess }; diff --git a/atom/common/api/atom_api_asar.cc b/atom/common/api/atom_api_asar.cc index 97c2e47fde..012d8f3c16 100644 --- a/atom/common/api/atom_api_asar.cc +++ b/atom/common/api/atom_api_asar.cc @@ -29,8 +29,9 @@ class Archive : public mate::Wrappable { } static void BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "Archive")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetProperty("path", &Archive::GetPath) .SetMethod("getFileInfo", &Archive::GetFileInfo) .SetMethod("stat", &Archive::Stat) diff --git a/atom/common/api/atom_api_key_weak_map.h b/atom/common/api/atom_api_key_weak_map.h index b13338badd..743b719e40 100644 --- a/atom/common/api/atom_api_key_weak_map.h +++ b/atom/common/api/atom_api_key_weak_map.h @@ -8,6 +8,7 @@ #include "atom/common/key_weak_map.h" #include "native_mate/object_template_builder.h" #include "native_mate/handle.h" +#include "native_mate/wrappable.h" namespace atom { @@ -21,8 +22,9 @@ class KeyWeakMap : public mate::Wrappable> { } static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "KeyWeakMap")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("set", &KeyWeakMap::Set) .SetMethod("get", &KeyWeakMap::Get) .SetMethod("has", &KeyWeakMap::Has) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 187ec7f48e..bd97ea3385 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -355,8 +355,9 @@ mate::Handle NativeImage::CreateFromDataURL( // static void NativeImage::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "NativeImage")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("toPNG", &NativeImage::ToPNG) .SetMethod("toJPEG", &NativeImage::ToJPEG) .SetMethod("toBitmap", &NativeImage::ToBitmap) diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 6702b33574..d6fddd1076 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -52,7 +52,7 @@ class NativeImage : public mate::Wrappable { v8::Isolate* isolate, const GURL& url); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); #if defined(OS_WIN) HICON GetHICON(int size); diff --git a/atom/common/key_weak_map.h b/atom/common/key_weak_map.h index 009ba099c9..8e879d656e 100644 --- a/atom/common/key_weak_map.h +++ b/atom/common/key_weak_map.h @@ -9,7 +9,7 @@ #include #include -#include "base/memory/linked_ptr.h" +#include "base/macros.h" #include "v8/include/v8.h" namespace atom { @@ -26,16 +26,16 @@ class KeyWeakMap { KeyWeakMap() {} virtual ~KeyWeakMap() { - for (const auto& p : map_) - p.second.second->ClearWeak(); + for (auto& p : map_) + p.second.second.ClearWeak(); } // Sets the object to WeakMap with the given |key|. void Set(v8::Isolate* isolate, const K& key, v8::Local object) { - auto value = make_linked_ptr(new v8::Global(isolate, object)); KeyObject key_object = {key, this}; - auto& p = map_[key] = std::make_pair(key_object, value); - value->SetWeak(&(p.first), OnObjectGC, v8::WeakCallbackType::kParameter); + auto& p = map_[key] = + std::make_pair(key_object, v8::Global(isolate, object)); + p.second.SetWeak(&(p.first), OnObjectGC, v8::WeakCallbackType::kParameter); } // Gets the object from WeakMap by its |key|. @@ -44,7 +44,7 @@ class KeyWeakMap { if (iter == map_.end()) return v8::MaybeLocal(); else - return v8::Local::New(isolate, *(iter->second.second)); + return v8::Local::New(isolate, iter->second.second); } // Whethere there is an object with |key| in this WeakMap. @@ -56,10 +56,8 @@ class KeyWeakMap { std::vector> Values(v8::Isolate* isolate) const { std::vector> keys; keys.reserve(map_.size()); - for (const auto& iter : map_) { - const auto& value = *(iter.second.second); - keys.emplace_back(v8::Local::New(isolate, value)); - } + for (const auto& it : map_) + keys.emplace_back(v8::Local::New(isolate, it.second.second)); return keys; } @@ -69,7 +67,7 @@ class KeyWeakMap { if (iter == map_.end()) return; - iter->second.second->ClearWeak(); + iter->second.second.ClearWeak(); map_.erase(iter); } @@ -82,7 +80,7 @@ class KeyWeakMap { // Map of stored objects. std::unordered_map< - K, std::pair>>> map_; + K, std::pair>> map_; DISALLOW_COPY_AND_ASSIGN(KeyWeakMap); }; diff --git a/atom/renderer/api/atom_api_web_frame.cc b/atom/renderer/api/atom_api_web_frame.cc index dce72b5809..9c83fc8e2f 100644 --- a/atom/renderer/api/atom_api_web_frame.cc +++ b/atom/renderer/api/atom_api_web_frame.cc @@ -187,8 +187,9 @@ void WebFrame::ClearCache(v8::Isolate* isolate) { // static void WebFrame::BuildPrototype( - v8::Isolate* isolate, v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) + v8::Isolate* isolate, v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "WebFrame")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("setName", &WebFrame::SetName) .SetMethod("setZoomLevel", &WebFrame::SetZoomLevel) .SetMethod("getZoomLevel", &WebFrame::GetZoomLevel) @@ -219,11 +220,14 @@ void WebFrame::BuildPrototype( namespace { +using atom::api::WebFrame; + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { v8::Isolate* isolate = context->GetIsolate(); mate::Dictionary dict(isolate, exports); - dict.Set("webFrame", atom::api::WebFrame::Create(isolate)); + dict.Set("webFrame", WebFrame::Create(isolate)); + dict.Set("WebFrame", WebFrame::GetConstructor(isolate)->GetFunction()); } } // namespace diff --git a/atom/renderer/api/atom_api_web_frame.h b/atom/renderer/api/atom_api_web_frame.h index 852191fc76..7b2401dd40 100644 --- a/atom/renderer/api/atom_api_web_frame.h +++ b/atom/renderer/api/atom_api_web_frame.h @@ -32,7 +32,7 @@ class WebFrame : public mate::Wrappable { static mate::Handle Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + v8::Local prototype); private: explicit WebFrame(v8::Isolate* isolate); diff --git a/docs-translations/jp/README.md b/docs-translations/jp/README.md index 36d99f5188..3ddc0881f5 100644 --- a/docs-translations/jp/README.md +++ b/docs-translations/jp/README.md @@ -63,9 +63,9 @@ _リンクになっていないリストは未翻訳のものです。_ * [powerSaveBlocker](api/power-save-blocker.md) * [protocol](api/protocol.md) * [session](api/session.md) -* systemPreferences (api/system-preferences.md) -* webContents (api/web-contents.md) +* [systemPreferences](api/system-preferences.md) * [Tray](api/tray.md) +* webContents (api/web-contents.md) ### Renderer Processのモジュール (Web Page): diff --git a/docs-translations/jp/api/system-preferences.md b/docs-translations/jp/api/system-preferences.md new file mode 100644 index 0000000000..aa78d2e880 --- /dev/null +++ b/docs-translations/jp/api/system-preferences.md @@ -0,0 +1,93 @@ +# systemPreferences + +> システムの環境設定を取得します。 + +```javascript +const {systemPreferences} = require('electron') +console.log(systemPreferences.isDarkMode()) +``` + +## メソッド + +### `systemPreferences.isDarkMode()` _macOS_ + +macOS がダークモードならば `true` を返し、通常モードなら `false` を返します。 + +### `systemPreferences.subscribeNotification(event, callback)` _macOS_ + +* `event` String +* `callback` Function + +macOS のネイティブな通知を購読します。 `callback` は `callback(event, userInfo)` として `event` の発生に対応して呼ばれます。`userInfo` は通知によって送られてくるユーザー情報のオブジェクトです。 + +この関数が返す `id` は `event`の購読をやめる際に使用します。 + +内部ではこの API は `NSDistributedNotificationCenter` を購読するので、`event` の例は以下のようなものがあります。 + +* `AppleInterfaceThemeChangedNotification` +* `AppleAquaColorVariantChanged` +* `AppleColorPreferencesChangedNotification` +* `AppleShowScrollBarsSettingChanged` + +### `systemPreferences.unsubscribeNotification(id)` _macOS_ + +* `id` Integer + +`id` の購読をやめます。 + +### `systemPreferences.subscribeLocalNotification(event, callback)` _macOS_ + +`subscribeNotification` と同じですが、 `NSNotificationCenter` を購読します。下記のような `event` を捕まえるために必要です。 + +* `NSUserDefaultsDidChangeNotification` + +### `systemPreferences.unsubscribeLocalNotification(id)` _macOS_ + +`unsubscribeNotification` と同じですが、`NSNotificationCenter` による購読をやめます。 + +### `systemPreferences.getUserDefault(key, type)` _macOS_ + +* `key` String +* `type` String - 右記の値を入れられます `string`, `boolean`, `integer`, `float`, `double`, + `url`, `array`, `dictionary` + +システム環境設定の `key` の値を取得します。 + +この API は macOS の `NSUserDefaults` から情報を取得します。よく使われる `key` 及び `type` には下記のものがあります。 + +* `AppleInterfaceStyle: string` +* `AppleAquaColorVariant: integer` +* `AppleHighlightColor: string` +* `AppleShowScrollBars: string` +* `NSNavRecentPlaces: array` +* `NSPreferredWebServices: dictionary` +* `NSUserDictionaryReplacementItems: array` + +### `systemPreferences.isAeroGlassEnabled()` _Windows_ +[DWM composition][dwm-composition] (Aero Glass) が有効だと `true` を返し、そうでないと `false` を返します。 + +使用例として、例えば透過ウィンドウを作成するかしないか決めるときに使います(DWM composition が無効だと透過ウィンドウは正常に動作しません) + +```javascript +const {BrowserWindow, systemPreferences} = require('electron') +let browserOptions = {width: 1000, height: 800} + +// プラットフォームがサポートしている場合に限り透過ウィンドウを作成します。 +if (process.platform !== 'win32' || systemPreferences.isAeroGlassEnabled()) { + browserOptions.transparent = true + browserOptions.frame = false +} + +// ウィンドウを作成 +let win = new BrowserWindow(browserOptions) + +// 分岐 +if (browserOptions.transparent) { + win.loadURL(`file://${__dirname}/index.html`) +} else { + // 透過がサポートされてないなら、通常のスタイルの html を表示する + win.loadURL(`file://${__dirname}/fallback.html`) +} +``` + +[dwm-composition]:https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx diff --git a/docs/README.md b/docs/README.md index aec23bf47e..5a39d8edcd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -93,6 +93,6 @@ an issue: * [Build Instructions (macOS)](development/build-instructions-osx.md) * [Build Instructions (Windows)](development/build-instructions-windows.md) * [Build Instructions (Linux)](development/build-instructions-linux.md) -* [Debug Instructions (macOS)](development/debug-instructions-windows.md) -* [Debug Instructions (Windows)](development/debug-instructions-macos.md) +* [Debug Instructions (macOS)](development/debug-instructions-macos.md) +* [Debug Instructions (Windows)](development/debug-instructions-windows.md) * [Setting Up Symbol Server in debugger](development/setting-up-symbol-server.md) diff --git a/docs/api/app.md b/docs/api/app.md index 1220f36c9f..ca1a36c9f9 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -725,6 +725,12 @@ Hides the dock icon. Shows the dock icon. +### `app.dock.isVisible()` _macOS_ + +Returns whether the dock icon is visible. +The `app.dock.show()` call is asynchronous so this method might not +return true immediately after that call. + ### `app.dock.setMenu(menu)` _macOS_ * `menu` [Menu](menu.md) diff --git a/docs/api/native-image.md b/docs/api/native-image.md index eed0b5cbaa..d0c9a3b62f 100644 --- a/docs/api/native-image.md +++ b/docs/api/native-image.md @@ -31,15 +31,24 @@ Currently `PNG` and `JPEG` image formats are supported. `PNG` is recommended because of its support for transparency and lossless compression. On Windows, you can also load `ICO` icons from file paths. For best visual -quality it is recommended to include at least the following sizes in the icon: +quality it is recommended to include at least the following sizes in the: -* 16x16 -* 32x32 -* 40x40 -* 48x48 -* 64x64 +* Small icon + * 16x16 (100% DPI scale) + * 20x20 (125% DPI scale) + * 24x24 (150% DPI scale) + * 32x32 (200% DPI scale) +* Large icon + * 32x32 (100% DPI scale) + * 40x40 (125% DPI scale) + * 48x48 (150% DPI scale) + * 64x64 (200% DPI scale) * 256x256 +Check the *Size requirements* section in [this article][icons]. + +[icons]:https://msdn.microsoft.com/en-us/library/windows/desktop/dn742485(v=vs.85).aspx + ## High Resolution Image On platforms that have high-DPI support such as Apple Retina displays, you can diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 8810e634bb..b626d3ea13 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -651,6 +651,42 @@ Mute the audio on the current web page. Returns whether this page has been muted. +#### `contents.setZoomFactor(factor)` + +* `factor` Number - Zoom factor. + +Changes the zoom factor to the specified factor. Zoom factor is +zoom percent divided by 100, so 300% = 3.0. + +#### `contents.getZoomFactor(callback)` + +* `callback` Function + +Sends a request to get current zoom factor, the `callback` will be called with +`callback(zoomFactor)`. + +#### `contents.setZoomLevel(level)` + +* `level` Number - Zoom level + +Changes the zoom level to the specified level. The original size is 0 and each +increment above or below represents zooming 20% larger or smaller to default +limits of 300% and 50% of original size, respectively. + +#### `contents.getZoomLevel(callback)` + +* `callback` Function + +Sends a request to get current zoom level, the `callback` will be called with +`callback(zoomLevel)`. + +#### `contents.setZoomLevelLimits(minimumLevel, maximumLevel)` + +* `minimumLevel` Number +* `maximumLevel` Number + +Sets the maximum and minimum zoom level.` + #### `contents.undo()` Executes the editing command `undo` in web page. diff --git a/lib/browser/api/app.js b/lib/browser/api/app.js index 0ea788b94a..c6ad57321b 100644 --- a/lib/browser/api/app.js +++ b/lib/browser/api/app.js @@ -1,7 +1,7 @@ 'use strict' const bindings = process.atomBinding('app') -const {app} = bindings +const {app, App} = bindings // Only one app object permitted. module.exports = app @@ -10,7 +10,7 @@ const electron = require('electron') const {deprecate, Menu} = electron const {EventEmitter} = require('events') -Object.setPrototypeOf(app, EventEmitter.prototype) +Object.setPrototypeOf(App.prototype, EventEmitter.prototype) let appPath = null @@ -40,6 +40,7 @@ if (process.platform === 'darwin') { getBadge: bindings.dockGetBadgeText, hide: bindings.dockHide, show: bindings.dockShow, + isVisible: bindings.dockIsVisible, setMenu: bindings.dockSetMenu, setIcon: bindings.dockSetIcon } @@ -75,7 +76,5 @@ for (let name of events) { } // Wrappers for native classes. -process.atomBinding('download_item')._setWrapDownloadItem((downloadItem) => { - // downloadItem is an EventEmitter. - Object.setPrototypeOf(downloadItem, EventEmitter.prototype) -}) +const {DownloadItem} = process.atomBinding('download_item') +Object.setPrototypeOf(DownloadItem.prototype, EventEmitter.prototype) diff --git a/lib/browser/api/auto-updater/auto-updater-native.js b/lib/browser/api/auto-updater/auto-updater-native.js index 1fff05dbd6..80e2eb1b84 100644 --- a/lib/browser/api/auto-updater/auto-updater-native.js +++ b/lib/browser/api/auto-updater/auto-updater-native.js @@ -1,6 +1,6 @@ const EventEmitter = require('events').EventEmitter -const autoUpdater = process.atomBinding('auto_updater').autoUpdater +const {autoUpdater, AutoUpdater} = process.atomBinding('auto_updater') -Object.setPrototypeOf(autoUpdater, EventEmitter.prototype) +Object.setPrototypeOf(AutoUpdater.prototype, EventEmitter.prototype) module.exports = autoUpdater diff --git a/lib/browser/api/power-monitor.js b/lib/browser/api/power-monitor.js index 87c0069da3..aee9b450c8 100644 --- a/lib/browser/api/power-monitor.js +++ b/lib/browser/api/power-monitor.js @@ -1,6 +1,6 @@ const {EventEmitter} = require('events') -const {powerMonitor} = process.atomBinding('power_monitor') +const {powerMonitor, PowerMonitor} = process.atomBinding('power_monitor') -Object.setPrototypeOf(powerMonitor, EventEmitter.prototype) +Object.setPrototypeOf(PowerMonitor.prototype, EventEmitter.prototype) module.exports = powerMonitor diff --git a/lib/browser/api/protocol.js b/lib/browser/api/protocol.js index 9d8394f767..ab7f89bef5 100644 --- a/lib/browser/api/protocol.js +++ b/lib/browser/api/protocol.js @@ -9,7 +9,7 @@ Object.setPrototypeOf(module.exports, new Proxy({}, { if (!app.isReady()) return const protocol = session.defaultSession.protocol - if (!protocol.hasOwnProperty(property)) return + if (!Object.getPrototypeOf(protocol).hasOwnProperty(property)) return // Returning a native function directly would throw error. return (...args) => protocol[property](...args) @@ -18,7 +18,7 @@ Object.setPrototypeOf(module.exports, new Proxy({}, { ownKeys () { if (!app.isReady()) return [] - return Object.getOwnPropertyNames(session.defaultSession.protocol) + return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession.protocol)) }, getOwnPropertyDescriptor (target) { diff --git a/lib/browser/api/screen.js b/lib/browser/api/screen.js index 25e3c37d3d..83381ab5d7 100644 --- a/lib/browser/api/screen.js +++ b/lib/browser/api/screen.js @@ -1,6 +1,6 @@ const {EventEmitter} = require('events') -const {screen} = process.atomBinding('screen') +const {screen, Screen} = process.atomBinding('screen') -Object.setPrototypeOf(screen, EventEmitter.prototype) +Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype) module.exports = screen diff --git a/lib/browser/api/session.js b/lib/browser/api/session.js index 86a7902ef5..af553e442e 100644 --- a/lib/browser/api/session.js +++ b/lib/browser/api/session.js @@ -1,8 +1,8 @@ const {EventEmitter} = require('events') const {app} = require('electron') -const {fromPartition, _setWrapSession} = process.atomBinding('session') +const {fromPartition, Session} = process.atomBinding('session') -// Returns the default session. +// Public API. Object.defineProperties(exports, { defaultSession: { enumerable: true, @@ -14,9 +14,8 @@ Object.defineProperties(exports, { } }) -// Wraps native Session class. -_setWrapSession(function (session) { - // Session is an EventEmitter. - Object.setPrototypeOf(session, EventEmitter.prototype) - app.emit('session-created', session) -}) +Object.setPrototypeOf(Session.prototype, EventEmitter.prototype) + +Session.prototype._init = function () { + app.emit('session-created', this) +} diff --git a/lib/browser/api/system-preferences.js b/lib/browser/api/system-preferences.js index 6ba1750507..7d9d475bc2 100644 --- a/lib/browser/api/system-preferences.js +++ b/lib/browser/api/system-preferences.js @@ -1,6 +1,6 @@ const {EventEmitter} = require('events') -const {systemPreferences} = process.atomBinding('system_preferences') +const {systemPreferences, SystemPreferences} = process.atomBinding('system_preferences') -Object.setPrototypeOf(systemPreferences, EventEmitter.prototype) +Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype) module.exports = systemPreferences diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index 5515984571..eba951b6d7 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -7,9 +7,6 @@ const {app, ipcMain, session, Menu, NavigationController} = require('electron') // before the webContents module. session -const binding = process.atomBinding('web_contents') -const debuggerBinding = process.atomBinding('debugger') - let nextId = 0 const getNextId = function () { return ++nextId @@ -81,6 +78,24 @@ const defaultPrintingSetting = { shouldPrintSelectionOnly: false } +// JavaScript implementations of WebContents. +const binding = process.atomBinding('web_contents') +const {WebContents} = binding + +Object.setPrototypeOf(NavigationController.prototype, EventEmitter.prototype) +Object.setPrototypeOf(WebContents.prototype, NavigationController.prototype) + +// WebContents::send(channel, args..) +// WebContents::sendToAll(channel, args..) +WebContents.prototype.send = function (channel, ...args) { + if (channel == null) throw new Error('Missing required channel argument') + return this._send(false, channel, args) +} +WebContents.prototype.sendToAll = function (channel, ...args) { + if (channel == null) throw new Error('Missing required channel argument') + return this._send(true, channel, args) +} + // Following methods are mapped to webFrame. const webFrameMethods = [ 'insertText', @@ -88,74 +103,112 @@ const webFrameMethods = [ 'setZoomLevel', 'setZoomLevelLimits' ] +const webFrameMethodsWithResult = [ + 'getZoomFactor', + 'getZoomLevel' +] + +const asyncWebFrameMethods = function (requestId, method, callback, ...args) { + this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args) + ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) { + if (callback) callback(result) + }) +} + +const syncWebFrameMethods = function (requestId, method, callback, ...args) { + this.send('ELECTRON_INTERNAL_RENDERER_SYNC_WEB_FRAME_METHOD', requestId, method, args) + ipcMain.once(`ELECTRON_INTERNAL_BROWSER_SYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) { + if (callback) callback(result) + }) +} + +for (const method of webFrameMethods) { + WebContents.prototype[method] = function (...args) { + this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args) + } +} + +for (const method of webFrameMethodsWithResult) { + WebContents.prototype[method] = function (...args) { + const callback = args[args.length - 1] + const actualArgs = args.slice(0, args.length - 2) + syncWebFrameMethods.call(this, getNextId(), method, callback, ...actualArgs) + } +} + +// Make sure WebContents::executeJavaScript would run the code only when the +// WebContents has been loaded. +WebContents.prototype.executeJavaScript = function (code, hasUserGesture, callback) { + const requestId = getNextId() + if (typeof hasUserGesture === 'function') { + callback = hasUserGesture + hasUserGesture = false + } + if (this.getURL() && !this.isLoadingMainFrame()) { + asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture) + } else { + this.once('did-finish-load', () => { + asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture) + }) + } +} + +// Translate the options of printToPDF. +WebContents.prototype.printToPDF = function (options, callback) { + const printingSetting = Object.assign({}, defaultPrintingSetting) + if (options.landscape) { + printingSetting.landscape = options.landscape + } + if (options.marginsType) { + printingSetting.marginsType = options.marginsType + } + if (options.printSelectionOnly) { + printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly + } + if (options.printBackground) { + printingSetting.shouldPrintBackgrounds = options.printBackground + } + + if (options.pageSize) { + const pageSize = options.pageSize + if (typeof pageSize === 'object') { + if (!pageSize.height || !pageSize.width) { + return callback(new Error('Must define height and width for pageSize')) + } + // Dimensions in Microns + // 1 meter = 10^6 microns + printingSetting.mediaSize = { + name: 'CUSTOM', + custom_display_name: 'Custom', + height_microns: pageSize.height, + width_microns: pageSize.width + } + } else if (PDFPageSizes[pageSize]) { + printingSetting.mediaSize = PDFPageSizes[pageSize] + } else { + return callback(new Error(`Does not support pageSize with ${pageSize}`)) + } + } else { + printingSetting.mediaSize = PDFPageSizes['A4'] + } + + this._printToPDF(printingSetting, callback) +} // Add JavaScript wrappers for WebContents class. -const wrapWebContents = function (webContents) { - // webContents is an EventEmitter. - Object.setPrototypeOf(webContents, EventEmitter.prototype) +WebContents.prototype._init = function () { + // The navigation controller. + NavigationController.call(this, this) // Every remote callback from renderer process would add a listenter to the // render-view-deleted event, so ignore the listenters warning. - webContents.setMaxListeners(0) - - // WebContents::send(channel, args..) - // WebContents::sendToAll(channel, args..) - const sendWrapper = (allFrames, channel, ...args) => { - if (channel == null) { - throw new Error('Missing required channel argument') - } - return webContents._send(allFrames, channel, args) - } - webContents.send = sendWrapper.bind(null, false) - webContents.sendToAll = sendWrapper.bind(null, true) - - // The navigation controller. - const controller = new NavigationController(webContents) - for (const name in NavigationController.prototype) { - const method = NavigationController.prototype[name] - if (method instanceof Function) { - webContents[name] = function () { - return method.apply(controller, arguments) - } - } - } - - // Mapping webFrame methods. - for (const method of webFrameMethods) { - webContents[method] = function (...args) { - this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args) - } - } - - const asyncWebFrameMethods = function (requestId, method, callback, ...args) { - this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args) - ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) { - if (callback) callback(result) - }) - } - - // Make sure webContents.executeJavaScript would run the code only when the - // webContents has been loaded. - webContents.executeJavaScript = function (code, hasUserGesture, callback) { - const requestId = getNextId() - if (typeof hasUserGesture === 'function') { - callback = hasUserGesture - hasUserGesture = false - } - if (this.getURL() && !this.isLoadingMainFrame()) { - asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture) - } else { - this.once('did-finish-load', () => { - asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture) - }) - } - } + this.setMaxListeners(0) // Dispatch IPC messages to the ipc module. - webContents.on('ipc-message', function (event, [channel, ...args]) { + this.on('ipc-message', function (event, [channel, ...args]) { ipcMain.emit(channel, event, ...args) }) - webContents.on('ipc-message-sync', function (event, [channel, ...args]) { + this.on('ipc-message-sync', function (event, [channel, ...args]) { Object.defineProperty(event, 'returnValue', { set: function (value) { return event.sendReply(JSON.stringify(value)) @@ -166,77 +219,32 @@ const wrapWebContents = function (webContents) { }) // Handle context menu action request from pepper plugin. - webContents.on('pepper-context-menu', function (event, params) { + this.on('pepper-context-menu', function (event, params) { const menu = Menu.buildFromTemplate(params.menu) menu.popup(params.x, params.y) }) // The devtools requests the webContents to reload. - webContents.on('devtools-reload-page', function () { - webContents.reload() + this.on('devtools-reload-page', function () { + this.reload() }) // Delays the page-title-updated event to next tick. - webContents.on('-page-title-updated', function (...args) { + this.on('-page-title-updated', function (...args) { setImmediate(() => { this.emit.apply(this, ['page-title-updated'].concat(args)) }) }) - webContents.printToPDF = function (options, callback) { - const printingSetting = Object.assign({}, defaultPrintingSetting) - if (options.landscape) { - printingSetting.landscape = options.landscape - } - if (options.marginsType) { - printingSetting.marginsType = options.marginsType - } - if (options.printSelectionOnly) { - printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly - } - if (options.printBackground) { - printingSetting.shouldPrintBackgrounds = options.printBackground - } - - if (options.pageSize) { - const pageSize = options.pageSize - if (typeof pageSize === 'object') { - if (!pageSize.height || !pageSize.width) { - return callback(new Error('Must define height and width for pageSize')) - } - // Dimensions in Microns - // 1 meter = 10^6 microns - printingSetting.mediaSize = { - name: 'CUSTOM', - custom_display_name: 'Custom', - height_microns: pageSize.height, - width_microns: pageSize.width - } - } else if (PDFPageSizes[pageSize]) { - printingSetting.mediaSize = PDFPageSizes[pageSize] - } else { - return callback(new Error(`Does not support pageSize with ${pageSize}`)) - } - } else { - printingSetting.mediaSize = PDFPageSizes['A4'] - } - - this._printToPDF(printingSetting, callback) - } - - app.emit('web-contents-created', {}, webContents) + app.emit('web-contents-created', {}, this) } -binding._setWrapWebContents(wrapWebContents) +// JavaScript wrapper of Debugger. +const {Debugger} = process.atomBinding('debugger') -// Add JavaScript wrappers for Debugger class. -const wrapDebugger = function (webContentsDebugger) { - // debugger is an EventEmitter. - Object.setPrototypeOf(webContentsDebugger, EventEmitter.prototype) -} - -debuggerBinding._setWrapDebugger(wrapDebugger) +Object.setPrototypeOf(Debugger.prototype, EventEmitter.prototype) +// Public APIs. module.exports = { create (options = {}) { return binding.create(options) diff --git a/lib/browser/init.js b/lib/browser/init.js index 88377a6978..f7619fd17b 100644 --- a/lib/browser/init.js +++ b/lib/browser/init.js @@ -65,7 +65,7 @@ process.on('uncaughtException', function (error) { }) // Emit 'exit' event on quit. -var app = require('electron').app +const {app} = require('electron') app.on('quit', function (event, exitCode) { process.emit('exit', exitCode) @@ -86,15 +86,12 @@ if (process.platform === 'win32') { // form `com.squirrel.PACKAGE-NAME.OUREXE`. We need to call // app.setAppUserModelId with a matching identifier so that renderer processes // will inherit this value. - var updateDotExe = path.join( - path.dirname(process.execPath), - '..', - 'update.exe') + const updateDotExe = path.join(path.dirname(process.execPath), '..', 'update.exe') - if (fs.statSyncNoException(updateDotExe)) { - var packageDir = path.dirname(path.resolve(updateDotExe)) - var packageName = path.basename(packageDir).replace(/\s/g, '') - var exeName = path.basename(process.execPath).replace(/\.exe$/i, '').replace(/\s/g, '') + if (fs.existsSync(updateDotExe)) { + const packageDir = path.dirname(path.resolve(updateDotExe)) + const packageName = path.basename(packageDir).replace(/\s/g, '') + const exeName = path.basename(process.execPath).replace(/\.exe$/i, '').replace(/\s/g, '') app.setAppUserModelId(`com.squirrel.${packageName}.${exeName}`) } @@ -108,15 +105,13 @@ require('./rpc-server') // Load the guest view manager. require('./guest-view-manager') - require('./guest-window-manager') // Now we try to load app's package.json. -var packageJson = null -var searchPaths = ['app', 'app.asar', 'default_app.asar'] -var i, len, packagePath -for (i = 0, len = searchPaths.length; i < len; i++) { - packagePath = searchPaths[i] +let packagePath = null +let packageJson = null +const searchPaths = ['app', 'app.asar', 'default_app.asar'] +for (packagePath of searchPaths) { try { packagePath = path.join(process.resourcesPath, packagePath) packageJson = require(path.join(packagePath, 'package.json')) @@ -157,14 +152,9 @@ if (packageJson.v8Flags != null) { v8.setFlagsFromString(packageJson.v8Flags) } -// Chrome 42 disables NPAPI plugins by default, reenable them here -app.commandLine.appendSwitch('enable-npapi') - // Set the user path according to application's name. app.setPath('userData', path.join(app.getPath('appData'), app.getName())) - app.setPath('userCache', path.join(app.getPath('cache'), app.getName())) - app.setAppPath(packagePath) // Load the chrome extension support. @@ -177,7 +167,7 @@ require('./desktop-capturer') require('./api/protocol') // Set main startup script of the app. -var mainStartupScript = packageJson.main || 'index.js' +const mainStartupScript = packageJson.main || 'index.js' // Finally load app's main.js and transfer control to C++. Module._load(path.join(packagePath, mainStartupScript), Module, true) diff --git a/lib/renderer/api/web-frame.js b/lib/renderer/api/web-frame.js index 81855c391f..f9d2b3b191 100644 --- a/lib/renderer/api/web-frame.js +++ b/lib/renderer/api/web-frame.js @@ -1,11 +1,10 @@ 'use strict' -const EventEmitter = require('events').EventEmitter +const {EventEmitter} = require('events') +const {webFrame, WebFrame} = process.atomBinding('web_frame') -const webFrame = process.atomBinding('web_frame').webFrame - -// webFrame is an EventEmitter. -Object.setPrototypeOf(webFrame, EventEmitter.prototype) +// WebFrame is an EventEmitter. +Object.setPrototypeOf(WebFrame.prototype, EventEmitter.prototype) // Lots of webview would subscribe to webFrame's events. webFrame.setMaxListeners(0) diff --git a/lib/renderer/init.js b/lib/renderer/init.js index f0875cae12..710c4c7c2d 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -32,6 +32,11 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', (event, m electron.webFrame[method].apply(electron.webFrame, args) }) +electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_SYNC_WEB_FRAME_METHOD', (event, requestId, method, args) => { + const result = electron.webFrame[method].apply(electron.webFrame, args) + event.sender.send(`ELECTRON_INTERNAL_BROWSER_SYNC_WEB_FRAME_RESPONSE_${requestId}`, result) +}) + electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (event, requestId, method, args) => { const responseCallback = function (result) { event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, result) diff --git a/script/lib/config.py b/script/lib/config.py index 1b6fb12f66..780f4276b6 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '141739f27054dbe032226a6547ff27a9f5f5626c' +LIBCHROMIUMCONTENT_COMMIT = '658edcb9509cfa03eea321977d060769467891e0' PLATFORM = { 'cygwin': 'win32', diff --git a/script/lib/util.py b/script/lib/util.py index 4db4e5fa67..cff7e94a04 100644 --- a/script/lib/util.py +++ b/script/lib/util.py @@ -18,6 +18,9 @@ import zipfile from config import is_verbose_mode from env_util import get_vs_env +BOTO_DIR = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'vendor', + 'boto')) + def get_host_arch(): """Returns the host architecture with a predictable string.""" @@ -202,28 +205,33 @@ def parse_version(version): return vs + ['0'] * (4 - len(vs)) -def s3put(bucket, access_key, secret_key, prefix, key_prefix, files): - env = os.environ.copy() - BOTO_DIR = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'vendor', - 'boto')) - env['PYTHONPATH'] = os.path.pathsep.join([ - env.get('PYTHONPATH', ''), +def boto_path_dirs(): + return [ os.path.join(BOTO_DIR, 'build', 'lib'), - os.path.join(BOTO_DIR, 'build', 'lib.linux-x86_64-2.7')]) + os.path.join(BOTO_DIR, 'build', 'lib.linux-x86_64-2.7') + ] - boto = os.path.join(BOTO_DIR, 'bin', 's3put') + +def run_boto_script(access_key, secret_key, script_name, *args): + env = os.environ.copy() + env['AWS_ACCESS_KEY_ID'] = access_key + env['AWS_SECRET_ACCESS_KEY'] = secret_key + env['PYTHONPATH'] = os.path.pathsep.join( + [env.get('PYTHONPATH', '')] + boto_path_dirs()) + + boto = os.path.join(BOTO_DIR, 'bin', script_name) + execute([sys.executable, boto] + list(args), env) + + +def s3put(bucket, access_key, secret_key, prefix, key_prefix, files): args = [ - sys.executable, - boto, '--bucket', bucket, - '--access_key', access_key, - '--secret_key', secret_key, '--prefix', prefix, '--key_prefix', key_prefix, '--grant', 'public-read' ] + files - execute(args, env) + run_boto_script(access_key, secret_key, 's3put', *args) def import_vs_env(target_arch): diff --git a/script/merge-electron-checksums.py b/script/merge-electron-checksums.py new file mode 100755 index 0000000000..bab9d97a0c --- /dev/null +++ b/script/merge-electron-checksums.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +# Download individual checksum files for Electron zip files from S3, +# concatenate them, and upload to GitHub. + +from __future__ import print_function + +import argparse +import sys + +from lib.config import s3_config +from lib.util import boto_path_dirs + +sys.path.extend(boto_path_dirs()) +from boto.s3.connection import S3Connection + + +def main(): + args = parse_args() + + bucket_name, access_key, secret_key = s3_config() + s3 = S3Connection(access_key, secret_key) + bucket = s3.get_bucket(bucket_name) + if bucket is None: + print('S3 bucket "{}" does not exist!'.format(bucket_name), file=sys.stderr) + return 1 + + prefix = 'atom-shell/tmp/{0}/'.format(args.version) + shasums = [s3_object.get_contents_as_string().strip() + for s3_object in bucket.list(prefix, delimiter='/') + if s3_object.key.endswith('.sha256sum')] + print('\n'.join(shasums)) + return 0 + + +def parse_args(): + parser = argparse.ArgumentParser(description='Upload SHASUMS files to GitHub') + parser.add_argument('-v', '--version', help='Specify the version', + required=True) + return parser.parse_args() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/script/upload-checksums.py b/script/upload-node-checksums.py similarity index 100% rename from script/upload-checksums.py rename to script/upload-node-checksums.py diff --git a/script/upload.py b/script/upload.py index 1abd67aaf0..ee97220a82 100755 --- a/script/upload.py +++ b/script/upload.py @@ -2,15 +2,17 @@ import argparse import errno +import hashlib import os import subprocess import sys import tempfile +from io import StringIO from lib.config import PLATFORM, get_target_arch, get_chromedriver_version, \ - get_platform_key, get_env_var + get_platform_key, get_env_var, s3_config from lib.util import electron_gyp, execute, get_electron_version, \ - parse_version, scoped_cwd + parse_version, scoped_cwd, s3put from lib.github import GitHub @@ -46,8 +48,7 @@ def main(): if not args.publish_release: if not dist_newer_than_head(): - create_dist = os.path.join(SOURCE_ROOT, 'script', 'create-dist.py') - execute([sys.executable, create_dist]) + run_python_script('create-dist.py') build_version = get_electron_build_version() if not ELECTRON_VERSION.startswith(build_version): @@ -69,14 +70,14 @@ def main(): tag_exists) if args.publish_release: - # Upload the SHASUMS.txt. - execute([sys.executable, - os.path.join(SOURCE_ROOT, 'script', 'upload-checksums.py'), - '-v', ELECTRON_VERSION]) + # Upload the Node SHASUMS*.txt. + run_python_script('upload-node-checksums.py', '-v', ELECTRON_VERSION) # Upload the index.json. - execute([sys.executable, - os.path.join(SOURCE_ROOT, 'script', 'upload-index-json.py')]) + run_python_script('upload-index-json.py') + + # Create and upload the Electron SHASUMS*.txt + release_electron_checksums(github, release) # Press the publish button. publish_release(github, release['id']) @@ -108,13 +109,10 @@ def main(): if PLATFORM == 'win32' and not tag_exists: # Upload PDBs to Windows symbol server. - execute([sys.executable, - os.path.join(SOURCE_ROOT, 'script', 'upload-windows-pdb.py')]) + run_python_script('upload-windows-pdb.py') # Upload node headers. - execute([sys.executable, - os.path.join(SOURCE_ROOT, 'script', 'upload-node-headers.py'), - '-v', args.version]) + run_python_script('upload-node-headers.py', '-v', args.version) def parse_args(): @@ -127,6 +125,11 @@ def parse_args(): return parser.parse_args() +def run_python_script(script, *args): + script_path = os.path.join(SOURCE_ROOT, 'script', script) + return execute([sys.executable, script_path] + list(args)) + + def get_electron_build_version(): if get_target_arch() == 'arm' or os.environ.has_key('CI'): # In CI we just build as told. @@ -202,23 +205,51 @@ def create_release_draft(github, tag): return r +def release_electron_checksums(github, release): + checksums = run_python_script('merge-electron-checksums.py', + '-v', ELECTRON_VERSION) + upload_io_to_github(github, release, 'SHASUMS256.txt', + StringIO(checksums.decode('utf-8')), 'text/plain') + + def upload_electron(github, release, file_path): # Delete the original file before uploading in CI. + filename = os.path.basename(file_path) if os.environ.has_key('CI'): try: for asset in release['assets']: - if asset['name'] == os.path.basename(file_path): + if asset['name'] == filename: github.repos(ELECTRON_REPO).releases.assets(asset['id']).delete() - break except Exception: pass # Upload the file. - params = {'name': os.path.basename(file_path)} - headers = {'Content-Type': 'application/zip'} with open(file_path, 'rb') as f: - github.repos(ELECTRON_REPO).releases(release['id']).assets.post( - params=params, headers=headers, data=f, verify=False) + upload_io_to_github(github, release, filename, f, 'application/zip') + + # Upload the checksum file. + upload_sha256_checksum(release['tag_name'], file_path) + + +def upload_io_to_github(github, release, name, io, content_type): + params = {'name': name} + headers = {'Content-Type': content_type} + github.repos(ELECTRON_REPO).releases(release['id']).assets.post( + params=params, headers=headers, data=io, verify=False) + + +def upload_sha256_checksum(version, file_path): + bucket, access_key, secret_key = s3_config() + checksum_path = '{}.sha256sum'.format(file_path) + sha256 = hashlib.sha256() + with open(file_path, 'rb') as f: + sha256.update(f.read()) + + filename = os.path.basename(file_path) + with open(checksum_path, 'w') as checksum: + checksum.write('{} {}'.format(sha256.hexdigest(), filename)) + s3put(bucket, access_key, secret_key, os.path.dirname(checksum_path), + 'atom-shell/tmp/{0}'.format(version), [checksum_path]) def publish_release(github, release_id): diff --git a/vendor/native_mate b/vendor/native_mate index d9bfe6a49d..fa483e1fe0 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit d9bfe6a49d8585916bd8dc77165154afeee4e5b6 +Subproject commit fa483e1fe012f873ad9812a67a66e2b7dbb570c6