Merge remote-tracking branch 'upstream/master' into speedup-gpu

This commit is contained in:
gellert 2016-08-02 14:59:03 +02:00
commit 8eed91d87a
79 changed files with 674 additions and 436 deletions

View file

@ -531,9 +531,10 @@ mate::Handle<App> App::Create(v8::Isolate* isolate) {
// static // static
void App::BuildPrototype( void App::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "App"));
auto browser = base::Unretained(Browser::Get()); auto browser = base::Unretained(Browser::Get());
mate::ObjectTemplateBuilder(isolate, prototype) mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("quit", base::Bind(&Browser::Quit, browser)) .SetMethod("quit", base::Bind(&Browser::Quit, browser))
.SetMethod("exit", base::Bind(&Browser::Exit, browser)) .SetMethod("exit", base::Bind(&Browser::Exit, browser))
.SetMethod("focus", base::Bind(&Browser::Focus, browser)) .SetMethod("focus", base::Bind(&Browser::Focus, browser))
@ -638,6 +639,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
auto command_line = base::CommandLine::ForCurrentProcess(); auto command_line = base::CommandLine::ForCurrentProcess();
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.Set("App", atom::api::App::GetConstructor(isolate)->GetFunction());
dict.Set("app", atom::api::App::Create(isolate)); dict.Set("app", atom::api::App::Create(isolate));
dict.SetMethod("appendSwitch", &AppendSwitch); dict.SetMethod("appendSwitch", &AppendSwitch);
dict.SetMethod("appendArgument", dict.SetMethod("appendArgument",
@ -656,6 +658,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
base::Bind(&Browser::DockGetBadgeText, browser)); base::Bind(&Browser::DockGetBadgeText, browser));
dict.SetMethod("dockHide", base::Bind(&Browser::DockHide, browser)); dict.SetMethod("dockHide", base::Bind(&Browser::DockHide, browser));
dict.SetMethod("dockShow", base::Bind(&Browser::DockShow, browser)); dict.SetMethod("dockShow", base::Bind(&Browser::DockShow, browser));
dict.SetMethod("dockIsVisible", base::Bind(&Browser::DockIsVisible, browser));
dict.SetMethod("dockSetMenu", &DockSetMenu); dict.SetMethod("dockSetMenu", &DockSetMenu);
dict.SetMethod("dockSetIcon", base::Bind(&Browser::DockSetIcon, browser)); dict.SetMethod("dockSetIcon", base::Bind(&Browser::DockSetIcon, browser));
#endif #endif

View file

@ -40,7 +40,7 @@ class App : public AtomBrowserClient::Delegate,
static mate::Handle<App> Create(v8::Isolate* isolate); static mate::Handle<App> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
// Called when window with disposition needs to be created. // Called when window with disposition needs to be created.
void OnCreateWindow(const GURL& target_url, void OnCreateWindow(const GURL& target_url,

View file

@ -106,8 +106,9 @@ mate::Handle<AutoUpdater> AutoUpdater::Create(v8::Isolate* isolate) {
// static // static
void AutoUpdater::BuildPrototype( void AutoUpdater::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "AutoUpdater"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates) .SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
.SetMethod("getFeedURL", &auto_updater::AutoUpdater::GetFeedURL) .SetMethod("getFeedURL", &auto_updater::AutoUpdater::GetFeedURL)
.SetMethod("setFeedURL", &AutoUpdater::SetFeedURL) .SetMethod("setFeedURL", &AutoUpdater::SetFeedURL)
@ -121,11 +122,14 @@ void AutoUpdater::BuildPrototype(
namespace { namespace {
using atom::api::AutoUpdater;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); 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 } // namespace

View file

@ -24,7 +24,7 @@ class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
static mate::Handle<AutoUpdater> Create(v8::Isolate* isolate); static mate::Handle<AutoUpdater> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
protected: protected:
explicit AutoUpdater(v8::Isolate* isolate); explicit AutoUpdater(v8::Isolate* isolate);

View file

@ -248,8 +248,9 @@ mate::Handle<Cookies> Cookies::Create(
// static // static
void Cookies::BuildPrototype(v8::Isolate* isolate, void Cookies::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "Cookies"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("get", &Cookies::Get) .SetMethod("get", &Cookies::Get)
.SetMethod("remove", &Cookies::Remove) .SetMethod("remove", &Cookies::Remove)
.SetMethod("set", &Cookies::Set); .SetMethod("set", &Cookies::Set);

View file

@ -41,7 +41,7 @@ class Cookies : public mate::TrackableObject<Cookies> {
// mate::TrackableObject: // mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
protected: protected:
Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context); Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context);

View file

@ -23,14 +23,6 @@ namespace atom {
namespace api { namespace api {
namespace {
// The wrapDebugger funtion which is implemented in JavaScript.
using WrapDebuggerCallback = base::Callback<void(v8::Local<v8::Value>)>;
WrapDebuggerCallback g_wrap_debugger;
} // namespace
Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents) Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents)
: web_contents_(web_contents), : web_contents_(web_contents),
previous_request_id_(0) { previous_request_id_(0) {
@ -151,37 +143,33 @@ void Debugger::SendCommand(mate::Arguments* args) {
mate::Handle<Debugger> Debugger::Create( mate::Handle<Debugger> Debugger::Create(
v8::Isolate* isolate, v8::Isolate* isolate,
content::WebContents* web_contents) { content::WebContents* web_contents) {
auto handle = mate::CreateHandle( return mate::CreateHandle(isolate, new Debugger(isolate, web_contents));
isolate, new Debugger(isolate, web_contents));
g_wrap_debugger.Run(handle.ToV8());
return handle;
} }
// static // static
void Debugger::BuildPrototype(v8::Isolate* isolate, void Debugger::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "Debugger"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("attach", &Debugger::Attach) .SetMethod("attach", &Debugger::Attach)
.SetMethod("isAttached", &Debugger::IsAttached) .SetMethod("isAttached", &Debugger::IsAttached)
.SetMethod("detach", &Debugger::Detach) .SetMethod("detach", &Debugger::Detach)
.SetMethod("sendCommand", &Debugger::SendCommand); .SetMethod("sendCommand", &Debugger::SendCommand);
} }
void SetWrapDebugger(const WrapDebuggerCallback& callback) {
g_wrap_debugger = callback;
}
} // namespace api } // namespace api
} // namespace atom } // namespace atom
namespace { namespace {
using atom::api::Debugger;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); mate::Dictionary(isolate, exports)
dict.SetMethod("_setWrapDebugger", &atom::api::SetWrapDebugger); .Set("Debugger", Debugger::GetConstructor(isolate)->GetFunction());
} }
} // namespace } // namespace

View file

@ -39,7 +39,7 @@ class Debugger: public mate::TrackableObject<Debugger>,
// mate::TrackableObject: // mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
protected: protected:
Debugger(v8::Isolate* isolate, content::WebContents* web_contents); Debugger(v8::Isolate* isolate, content::WebContents* web_contents);

View file

@ -99,8 +99,9 @@ mate::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
// static // static
void DesktopCapturer::BuildPrototype( void DesktopCapturer::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "DesktopCapturer"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("startHandling", &DesktopCapturer::StartHandling); .SetMethod("startHandling", &DesktopCapturer::StartHandling);
} }

View file

@ -20,7 +20,7 @@ class DesktopCapturer: public mate::EventEmitter<DesktopCapturer>,
static mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate); static mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
void StartHandling(bool capture_window, void StartHandling(bool capture_window,
bool capture_screen, bool capture_screen,

View file

@ -11,7 +11,6 @@
#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"
#include "atom/common/node_includes.h" #include "atom/common/node_includes.h"
#include "base/memory/linked_ptr.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "native_mate/dictionary.h" #include "native_mate/dictionary.h"
@ -52,11 +51,7 @@ namespace api {
namespace { namespace {
// The wrapDownloadItem funtion which is implemented in JavaScript std::map<uint32_t, v8::Global<v8::Object>> g_download_item_objects;
using WrapDownloadItemCallback = base::Callback<void(v8::Local<v8::Value>)>;
WrapDownloadItemCallback g_wrap_download_item;
std::map<uint32_t, linked_ptr<v8::Global<v8::Value>>> g_download_item_objects;
} // namespace } // namespace
@ -76,9 +71,7 @@ DownloadItem::~DownloadItem() {
} }
// Remove from the global map. // Remove from the global map.
auto iter = g_download_item_objects.find(weak_map_id()); g_download_item_objects.erase(weak_map_id());
if (iter != g_download_item_objects.end())
g_download_item_objects.erase(iter);
} }
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) { void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
@ -170,8 +163,9 @@ base::FilePath DownloadItem::GetSavePath() const {
// static // static
void DownloadItem::BuildPrototype(v8::Isolate* isolate, void DownloadItem::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "DownloadItem"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable() .MakeDestroyable()
.SetMethod("pause", &DownloadItem::Pause) .SetMethod("pause", &DownloadItem::Pause)
.SetMethod("isPaused", &DownloadItem::IsPaused) .SetMethod("isPaused", &DownloadItem::IsPaused)
@ -199,18 +193,13 @@ mate::Handle<DownloadItem> DownloadItem::Create(
return mate::CreateHandle(isolate, static_cast<DownloadItem*>(existing)); return mate::CreateHandle(isolate, static_cast<DownloadItem*>(existing));
auto handle = mate::CreateHandle(isolate, new DownloadItem(isolate, item)); 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. // Reference this object in case it got garbage collected.
g_download_item_objects[handle->weak_map_id()] = make_linked_ptr( g_download_item_objects[handle->weak_map_id()] =
new v8::Global<v8::Value>(isolate, handle.ToV8())); v8::Global<v8::Object>(isolate, handle.ToV8());
return handle; return handle;
} }
void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) {
g_wrap_download_item = callback;
}
} // namespace api } // namespace api
} // namespace atom } // namespace atom
@ -220,8 +209,9 @@ namespace {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); mate::Dictionary(isolate, exports)
dict.SetMethod("_setWrapDownloadItem", &atom::api::SetWrapDownloadItem); .Set("DownloadItem",
atom::api::DownloadItem::GetConstructor(isolate)->GetFunction());
} }
} // namespace } // namespace

View file

@ -24,7 +24,7 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
content::DownloadItem* item); content::DownloadItem* item);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
void Pause(); void Pause();
bool IsPaused() const; bool IsPaused() const;

View file

@ -74,8 +74,9 @@ mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
// static // static
void GlobalShortcut::BuildPrototype( void GlobalShortcut::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "GlobalShortcut"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("register", &GlobalShortcut::Register) .SetMethod("register", &GlobalShortcut::Register)
.SetMethod("isRegistered", &GlobalShortcut::IsRegistered) .SetMethod("isRegistered", &GlobalShortcut::IsRegistered)
.SetMethod("unregister", &GlobalShortcut::Unregister) .SetMethod("unregister", &GlobalShortcut::Unregister)

View file

@ -24,7 +24,7 @@ class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
static mate::Handle<GlobalShortcut> Create(v8::Isolate* isolate); static mate::Handle<GlobalShortcut> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
protected: protected:
explicit GlobalShortcut(v8::Isolate* isolate); explicit GlobalShortcut(v8::Isolate* isolate);

View file

@ -19,9 +19,10 @@ namespace atom {
namespace api { namespace api {
Menu::Menu(v8::Isolate* isolate) Menu::Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
: model_(new AtomMenuModel(this)), : model_(new AtomMenuModel(this)),
parent_(nullptr) { parent_(nullptr) {
InitWith(isolate, wrapper);
} }
Menu::~Menu() { Menu::~Menu() {
@ -154,8 +155,9 @@ bool Menu::IsVisibleAt(int index) const {
// static // static
void Menu::BuildPrototype(v8::Isolate* isolate, void Menu::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "Menu"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable() .MakeDestroyable()
.SetMethod("insertItem", &Menu::InsertItemAt) .SetMethod("insertItem", &Menu::InsertItemAt)
.SetMethod("insertCheckItem", &Menu::InsertCheckItemAt) .SetMethod("insertCheckItem", &Menu::InsertCheckItemAt)
@ -184,14 +186,15 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
namespace { namespace {
using atom::api::Menu;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
using atom::api::Menu;
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
v8::Local<v8::Function> constructor = mate::CreateConstructor<Menu>( Menu::SetConstructor(isolate, base::Bind(&Menu::New));
isolate, "Menu", base::Bind(&Menu::Create));
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.Set("Menu", static_cast<v8::Local<v8::Value>>(constructor)); dict.Set("Menu", Menu::GetConstructor(isolate)->GetFunction());
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
dict.SetMethod("setApplicationMenu", &Menu::SetApplicationMenu); dict.SetMethod("setApplicationMenu", &Menu::SetApplicationMenu);
dict.SetMethod("sendActionToFirstResponder", dict.SetMethod("sendActionToFirstResponder",

View file

@ -20,10 +20,10 @@ namespace api {
class Menu : public mate::TrackableObject<Menu>, class Menu : public mate::TrackableObject<Menu>,
public AtomMenuModel::Delegate { public AtomMenuModel::Delegate {
public: public:
static mate::WrappableBase* Create(v8::Isolate* isolate); static mate::WrappableBase* New(mate::Arguments* args);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
// Set the global menubar. // Set the global menubar.
@ -36,7 +36,7 @@ class Menu : public mate::TrackableObject<Menu>,
AtomMenuModel* model() const { return model_.get(); } AtomMenuModel* model() const { return model_.get(); }
protected: protected:
explicit Menu(v8::Isolate* isolate); Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
~Menu() override; ~Menu() override;
// mate::Wrappable: // mate::Wrappable:

View file

@ -17,7 +17,7 @@ namespace api {
class MenuMac : public Menu { class MenuMac : public Menu {
protected: protected:
explicit MenuMac(v8::Isolate* isolate); MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
void PopupAt(Window* window, int x, int y, int positioning_item) override; void PopupAt(Window* window, int x, int y, int positioning_item) override;

View file

@ -18,7 +18,8 @@ namespace atom {
namespace api { namespace api {
MenuMac::MenuMac(v8::Isolate* isolate) : Menu(isolate) { MenuMac::MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
: Menu(isolate, wrapper) {
} }
void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) { void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) {
@ -94,8 +95,8 @@ void Menu::SendActionToFirstResponder(const std::string& action) {
} }
// static // static
mate::WrappableBase* Menu::Create(v8::Isolate* isolate) { mate::WrappableBase* Menu::New(mate::Arguments* args) {
return new MenuMac(isolate); return new MenuMac(args->isolate(), args->GetThis());
} }
} // namespace api } // namespace api

View file

@ -14,7 +14,8 @@ namespace atom {
namespace api { namespace api {
MenuViews::MenuViews(v8::Isolate* isolate) : Menu(isolate) { MenuViews::MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
: Menu(isolate, wrapper) {
} }
void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item) { 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 // static
mate::WrappableBase* Menu::Create(v8::Isolate* isolate) { mate::WrappableBase* Menu::New(mate::Arguments* args) {
return new MenuViews(isolate); return new MenuViews(args->isolate(), args->GetThis());
} }
} // namespace api } // namespace api

View file

@ -14,7 +14,7 @@ namespace api {
class MenuViews : public Menu { class MenuViews : public Menu {
public: public:
explicit MenuViews(v8::Isolate* isolate); MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
protected: protected:
void PopupAt(Window* window, int x, int y, int positioning_item) override; void PopupAt(Window* window, int x, int y, int positioning_item) override;

View file

@ -52,8 +52,8 @@ v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
// static // static
void PowerMonitor::BuildPrototype( void PowerMonitor::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype); prototype->SetClassName(mate::StringToV8(isolate, "PowerMonitor"));
} }
} // namespace api } // namespace api
@ -63,16 +63,19 @@ void PowerMonitor::BuildPrototype(
namespace { namespace {
using atom::api::PowerMonitor;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
base::PowerMonitorDeviceSource::AllocateSystemIOPorts(); base::PowerMonitorDeviceSource::AllocateSystemIOPorts();
#endif #endif
using atom::api::PowerMonitor;
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.Set("powerMonitor", PowerMonitor::Create(isolate)); dict.Set("powerMonitor", PowerMonitor::Create(isolate));
dict.Set("PowerMonitor",
PowerMonitor::GetConstructor(isolate)->GetFunction());
} }
} // namespace } // namespace

View file

@ -20,7 +20,7 @@ class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
static v8::Local<v8::Value> Create(v8::Isolate* isolate); static v8::Local<v8::Value> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
protected: protected:
explicit PowerMonitor(v8::Isolate* isolate); explicit PowerMonitor(v8::Isolate* isolate);

View file

@ -105,8 +105,9 @@ mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
// static // static
void PowerSaveBlocker::BuildPrototype( void PowerSaveBlocker::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "PowerSaveBlocker"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("start", &PowerSaveBlocker::Start) .SetMethod("start", &PowerSaveBlocker::Start)
.SetMethod("stop", &PowerSaveBlocker::Stop) .SetMethod("stop", &PowerSaveBlocker::Stop)
.SetMethod("isStarted", &PowerSaveBlocker::IsStarted); .SetMethod("isStarted", &PowerSaveBlocker::IsStarted);

View file

@ -25,7 +25,7 @@ class PowerSaveBlocker : public mate::TrackableObject<PowerSaveBlocker> {
static mate::Handle<PowerSaveBlocker> Create(v8::Isolate* isolate); static mate::Handle<PowerSaveBlocker> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
protected: protected:
explicit PowerSaveBlocker(v8::Isolate* isolate); explicit PowerSaveBlocker(v8::Isolate* isolate);

View file

@ -160,8 +160,9 @@ mate::Handle<Protocol> Protocol::Create(
// static // static
void Protocol::BuildPrototype( void Protocol::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "Protocol"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("registerServiceWorkerSchemes", .SetMethod("registerServiceWorkerSchemes",
&Protocol::RegisterServiceWorkerSchemes) &Protocol::RegisterServiceWorkerSchemes)
.SetMethod("registerStringProtocol", .SetMethod("registerStringProtocol",

View file

@ -39,7 +39,7 @@ class Protocol : public mate::TrackableObject<Protocol> {
v8::Isolate* isolate, AtomBrowserContext* browser_context); v8::Isolate* isolate, AtomBrowserContext* browser_context);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
protected: protected:
Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context); Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context);

View file

@ -53,8 +53,10 @@ void RenderProcessPreferences::RemoveEntry(int id) {
// static // static
void RenderProcessPreferences::BuildPrototype( void RenderProcessPreferences::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(
mate::StringToV8(isolate, "RenderProcessPreferences"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("addEntry", &RenderProcessPreferences::AddEntry) .SetMethod("addEntry", &RenderProcessPreferences::AddEntry)
.SetMethod("removeEntry", &RenderProcessPreferences::RemoveEntry); .SetMethod("removeEntry", &RenderProcessPreferences::RemoveEntry);
} }

View file

@ -20,7 +20,7 @@ class RenderProcessPreferences
ForAllWebContents(v8::Isolate* isolate); ForAllWebContents(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
int AddEntry(const base::DictionaryValue& entry); int AddEntry(const base::DictionaryValue& entry);
void RemoveEntry(int id); void RemoveEntry(int id);

View file

@ -113,8 +113,9 @@ v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
// static // static
void Screen::BuildPrototype( void Screen::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "Screen"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint) .SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint)
.SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay) .SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay)
.SetMethod("getAllDisplays", &Screen::GetAllDisplays) .SetMethod("getAllDisplays", &Screen::GetAllDisplays)
@ -128,10 +129,14 @@ void Screen::BuildPrototype(
namespace { namespace {
using atom::api::Screen;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports); v8::Isolate* isolate = context->GetIsolate();
dict.Set("screen", atom::api::Screen::Create(context->GetIsolate())); mate::Dictionary dict(isolate, exports);
dict.Set("screen", Screen::Create(isolate));
dict.Set("Screen", Screen::GetConstructor(isolate)->GetFunction());
} }
} // namespace } // namespace

View file

@ -28,7 +28,7 @@ class Screen : public mate::EventEmitter<Screen>,
static v8::Local<v8::Value> Create(v8::Isolate* isolate); static v8::Local<v8::Value> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
protected: protected:
Screen(v8::Isolate* isolate, display::Screen* screen); Screen(v8::Isolate* isolate, display::Screen* screen);

View file

@ -4,6 +4,7 @@
#include "atom/browser/api/atom_api_session.h" #include "atom/browser/api/atom_api_session.h"
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
@ -169,9 +170,8 @@ namespace {
const char kPersistPrefix[] = "persist:"; const char kPersistPrefix[] = "persist:";
// The wrapSession funtion which is implemented in JavaScript // Referenced session objects.
using WrapSessionCallback = base::Callback<void(v8::Local<v8::Value>)>; std::map<uint32_t, v8::Global<v8::Object>> g_sessions;
WrapSessionCallback g_wrap_session;
class ResolveProxyHelper { class ResolveProxyHelper {
public: public:
@ -346,6 +346,7 @@ Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
Session::~Session() { Session::~Session() {
content::BrowserContext::GetDownloadManager(browser_context())-> content::BrowserContext::GetDownloadManager(browser_context())->
RemoveObserver(this); RemoveObserver(this);
g_sessions.erase(weak_map_id());
} }
void Session::OnDownloadCreated(content::DownloadManager* manager, void Session::OnDownloadCreated(content::DownloadManager* manager,
@ -536,7 +537,12 @@ mate::Handle<Session> Session::CreateFrom(
auto handle = mate::CreateHandle( auto handle = mate::CreateHandle(
isolate, new Session(isolate, browser_context)); 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<v8::Object>(isolate, handle.ToV8());
return handle; return handle;
} }
@ -559,8 +565,9 @@ mate::Handle<Session> Session::FromPartition(
// static // static
void Session::BuildPrototype(v8::Isolate* isolate, void Session::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "Session"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable() .MakeDestroyable()
.SetMethod("resolveProxy", &Session::ResolveProxy) .SetMethod("resolveProxy", &Session::ResolveProxy)
.SetMethod("getCacheSize", &Session::DoCacheAction<CacheAction::STATS>) .SetMethod("getCacheSize", &Session::DoCacheAction<CacheAction::STATS>)
@ -584,16 +591,14 @@ void Session::BuildPrototype(v8::Isolate* isolate,
.SetProperty("webRequest", &Session::WebRequest); .SetProperty("webRequest", &Session::WebRequest);
} }
void SetWrapSession(const WrapSessionCallback& callback) {
g_wrap_session = callback;
}
} // namespace api } // namespace api
} // namespace atom } // namespace atom
namespace { namespace {
using atom::api::Session;
v8::Local<v8::Value> FromPartition( v8::Local<v8::Value> FromPartition(
const std::string& partition, mate::Arguments* args) { const std::string& partition, mate::Arguments* args) {
if (!atom::Browser::Get()->is_ready()) { if (!atom::Browser::Get()->is_ready()) {
@ -602,16 +607,15 @@ v8::Local<v8::Value> FromPartition(
} }
base::DictionaryValue options; base::DictionaryValue options;
args->GetNext(&options); args->GetNext(&options);
return atom::api::Session::FromPartition( return Session::FromPartition(args->isolate(), partition, options).ToV8();
args->isolate(), partition, options).ToV8();
} }
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.Set("Session", Session::GetConstructor(isolate)->GetFunction());
dict.SetMethod("fromPartition", &FromPartition); dict.SetMethod("fromPartition", &FromPartition);
dict.SetMethod("_setWrapSession", &atom::api::SetWrapSession);
} }
} // namespace } // namespace

View file

@ -57,7 +57,7 @@ class Session: public mate::TrackableObject<Session>,
// mate::TrackableObject: // mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
// Methods. // Methods.
void ResolveProxy(const GURL& url, ResolveProxyCallback callback); void ResolveProxy(const GURL& url, ResolveProxyCallback callback);

View file

@ -44,8 +44,9 @@ mate::Handle<SystemPreferences> SystemPreferences::Create(
// static // static
void SystemPreferences::BuildPrototype( void SystemPreferences::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "SystemPreferences"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
#if defined(OS_WIN) #if defined(OS_WIN)
.SetMethod("isAeroGlassEnabled", &SystemPreferences::IsAeroGlassEnabled) .SetMethod("isAeroGlassEnabled", &SystemPreferences::IsAeroGlassEnabled)
#elif defined(OS_MACOSX) #elif defined(OS_MACOSX)
@ -68,11 +69,15 @@ void SystemPreferences::BuildPrototype(
namespace { namespace {
using atom::api::SystemPreferences;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); 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 } // namespace

View file

@ -24,7 +24,7 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
static mate::Handle<SystemPreferences> Create(v8::Isolate* isolate); static mate::Handle<SystemPreferences> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
#if defined(OS_WIN) #if defined(OS_WIN)
bool IsAeroGlassEnabled(); bool IsAeroGlassEnabled();

View file

@ -60,10 +60,13 @@ namespace atom {
namespace api { namespace api {
Tray::Tray(v8::Isolate* isolate, mate::Handle<NativeImage> image) Tray::Tray(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
mate::Handle<NativeImage> image)
: tray_icon_(TrayIcon::Create()) { : tray_icon_(TrayIcon::Create()) {
SetImage(isolate, image); SetImage(isolate, image);
tray_icon_->AddObserver(this); tray_icon_->AddObserver(this);
InitWith(isolate, wrapper);
} }
Tray::~Tray() { Tray::~Tray() {
@ -72,14 +75,13 @@ Tray::~Tray() {
} }
// static // static
mate::WrappableBase* Tray::New(v8::Isolate* isolate, mate::WrappableBase* Tray::New(mate::Handle<NativeImage> image,
mate::Handle<NativeImage> image) { mate::Arguments* args) {
if (!Browser::Get()->is_ready()) { if (!Browser::Get()->is_ready()) {
isolate->ThrowException(v8::Exception::Error(mate::StringToV8( args->ThrowError("Cannot create Tray before app is ready");
isolate, "Cannot create Tray before app is ready")));
return nullptr; return nullptr;
} }
return new Tray(isolate, image); return new Tray(args->isolate(), args->GetThis(), image);
} }
void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) { void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) {
@ -199,8 +201,9 @@ gfx::Rect Tray::GetBounds() {
// static // static
void Tray::BuildPrototype(v8::Isolate* isolate, void Tray::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "Tray"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable() .MakeDestroyable()
.SetMethod("setImage", &Tray::SetImage) .SetMethod("setImage", &Tray::SetImage)
.SetMethod("setPressedImage", &Tray::SetPressedImage) .SetMethod("setPressedImage", &Tray::SetPressedImage)
@ -220,14 +223,15 @@ void Tray::BuildPrototype(v8::Isolate* isolate,
namespace { namespace {
using atom::api::Tray;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
using atom::api::Tray;
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
v8::Local<v8::Function> constructor = mate::CreateConstructor<Tray>( Tray::SetConstructor(isolate, base::Bind(&Tray::New));
isolate, "Tray", base::Bind(&Tray::New));
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.Set("Tray", static_cast<v8::Local<v8::Value>>(constructor)); dict.Set("Tray", Tray::GetConstructor(isolate)->GetFunction());
} }
} // namespace } // namespace

View file

@ -35,14 +35,15 @@ class NativeImage;
class Tray : public mate::TrackableObject<Tray>, class Tray : public mate::TrackableObject<Tray>,
public TrayIconObserver { public TrayIconObserver {
public: public:
static mate::WrappableBase* New( static mate::WrappableBase* New(mate::Handle<NativeImage> image,
v8::Isolate* isolate, mate::Handle<NativeImage> image); mate::Arguments* args);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
protected: protected:
Tray(v8::Isolate* isolate, mate::Handle<NativeImage> image); Tray(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
mate::Handle<NativeImage> image);
~Tray() override; ~Tray() override;
// TrayIconObserver: // TrayIconObserver:

View file

@ -228,10 +228,6 @@ namespace api {
namespace { namespace {
// The wrapWebContents function which is implemented in JavaScript
using WrapWebContentsCallback = base::Callback<void(v8::Local<v8::Value>)>;
WrapWebContentsCallback g_wrap_web_contents;
content::ServiceWorkerContext* GetServiceWorkerContext( content::ServiceWorkerContext* GetServiceWorkerContext(
const content::WebContents* web_contents) { const content::WebContents* web_contents) {
auto context = web_contents->GetBrowserContext(); auto context = web_contents->GetBrowserContext();
@ -1458,8 +1454,9 @@ int WebContents::GetFrameRate() const {
// static // static
void WebContents::BuildPrototype(v8::Isolate* isolate, void WebContents::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "WebContents"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable() .MakeDestroyable()
.SetMethod("getId", &WebContents::GetID) .SetMethod("getId", &WebContents::GetID)
.SetMethod("equal", &WebContents::Equal) .SetMethod("equal", &WebContents::Equal)
@ -1569,41 +1566,32 @@ mate::Handle<WebContents> WebContents::CreateFrom(
return mate::CreateHandle(isolate, static_cast<WebContents*>(existing)); return mate::CreateHandle(isolate, static_cast<WebContents*>(existing));
// Otherwise create a new WebContents wrapper object. // Otherwise create a new WebContents wrapper object.
auto handle = mate::CreateHandle( return mate::CreateHandle(isolate, new WebContents(isolate, web_contents));
isolate, new WebContents(isolate, web_contents));
g_wrap_web_contents.Run(handle.ToV8());
return handle;
} }
// static // static
mate::Handle<WebContents> WebContents::Create( mate::Handle<WebContents> WebContents::Create(
v8::Isolate* isolate, const mate::Dictionary& options) { v8::Isolate* isolate, const mate::Dictionary& options) {
auto handle = mate::CreateHandle(isolate, new WebContents(isolate, options)); return 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;
} }
} // namespace api } // namespace api
} // namespace atom } // namespace atom
namespace { namespace {
using atom::api::WebContents;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.SetMethod("create", &atom::api::WebContents::Create); dict.Set("WebContents", WebContents::GetConstructor(isolate)->GetFunction());
dict.SetMethod("_setWrapWebContents", &atom::api::SetWrapWebContents); dict.SetMethod("create", &WebContents::Create);
dict.SetMethod("fromId", dict.SetMethod("fromId", &mate::TrackableObject<WebContents>::FromWeakMapID);
&mate::TrackableObject<atom::api::WebContents>::FromWeakMapID);
dict.SetMethod("getAllWebContents", dict.SetMethod("getAllWebContents",
&mate::TrackableObject<atom::api::WebContents>::GetAll); &mate::TrackableObject<WebContents>::GetAll);
} }
} // namespace } // namespace

View file

@ -66,7 +66,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
v8::Isolate* isolate, const mate::Dictionary& options); v8::Isolate* isolate, const mate::Dictionary& options);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
int GetID() const; int GetID() const;
Type GetType() const; Type GetType() const;

View file

@ -88,8 +88,9 @@ mate::Handle<WebRequest> WebRequest::Create(
// static // static
void WebRequest::BuildPrototype(v8::Isolate* isolate, void WebRequest::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "WebRequest"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("onBeforeRequest", .SetMethod("onBeforeRequest",
&WebRequest::SetResponseListener< &WebRequest::SetResponseListener<
AtomNetworkDelegate::kOnBeforeRequest>) AtomNetworkDelegate::kOnBeforeRequest>)

View file

@ -22,7 +22,7 @@ class WebRequest : public mate::TrackableObject<WebRequest> {
AtomBrowserContext* browser_context); AtomBrowserContext* browser_context);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
protected: protected:
WebRequest(v8::Isolate* isolate, AtomBrowserContext* browser_context); WebRequest(v8::Isolate* isolate, AtomBrowserContext* browser_context);

View file

@ -69,7 +69,8 @@ v8::Local<v8::Value> ToBuffer(v8::Isolate* isolate, void* val, int size) {
} // namespace } // namespace
Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) { Window::Window(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
const mate::Dictionary& options) {
// Use options.webPreferences to create WebContents. // Use options.webPreferences to create WebContents.
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate); mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
options.Get(options::kWebPreferences, &web_preferences); options.Get(options::kWebPreferences, &web_preferences);
@ -113,7 +114,14 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
window_->InitFromOptions(options); window_->InitFromOptions(options);
window_->AddObserver(this); window_->AddObserver(this);
InitWith(isolate, wrapper);
AttachAsUserData(window_.get()); 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() { Window::~Window() {
@ -125,17 +133,6 @@ Window::~Window() {
base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release()); base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release());
} }
void Window::AfterInit(v8::Isolate* isolate) {
mate::TrackableObject<Window>::AfterInit(isolate);
// We can only append this window to parent window's child windows after this
// window's JS wrapper gets initialized.
mate::Handle<Window> parent;
if (!parent_window_.IsEmpty() &&
mate::ConvertFromV8(isolate, GetParentWindow(), &parent))
parent->child_windows_.Set(isolate, ID(), GetWrapper());
}
void Window::WillCloseWindow(bool* prevent_default) { void Window::WillCloseWindow(bool* prevent_default) {
*prevent_default = Emit("close"); *prevent_default = Emit("close");
} }
@ -268,10 +265,9 @@ void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {
#endif #endif
// static // static
mate::WrappableBase* Window::New(v8::Isolate* isolate, mate::Arguments* args) { mate::WrappableBase* Window::New(mate::Arguments* args) {
if (!Browser::Get()->is_ready()) { if (!Browser::Get()->is_ready()) {
isolate->ThrowException(v8::Exception::Error(mate::StringToV8( args->ThrowError("Cannot create BrowserWindow before app is ready");
isolate, "Cannot create BrowserWindow before app is ready")));
return nullptr; return nullptr;
} }
@ -282,10 +278,10 @@ mate::WrappableBase* Window::New(v8::Isolate* isolate, mate::Arguments* args) {
mate::Dictionary options; mate::Dictionary options;
if (!(args->Length() == 1 && args->GetNext(&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() { void Window::Close() {
@ -756,8 +752,9 @@ void Window::RemoveFromParentChildWindows() {
// static // static
void Window::BuildPrototype(v8::Isolate* isolate, void Window::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "BrowserWindow"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable() .MakeDestroyable()
.SetMethod("close", &Window::Close) .SetMethod("close", &Window::Close)
.SetMethod("focus", &Window::Focus) .SetMethod("focus", &Window::Focus)
@ -879,9 +876,10 @@ using atom::api::Window;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
v8::Local<v8::Function> constructor = mate::CreateConstructor<Window>( Window::SetConstructor(isolate, base::Bind(&Window::New));
isolate, "BrowserWindow", base::Bind(&Window::New));
mate::Dictionary browser_window(isolate, constructor); mate::Dictionary browser_window(
isolate, Window::GetConstructor(isolate)->GetFunction());
browser_window.SetMethod("fromId", browser_window.SetMethod("fromId",
&mate::TrackableObject<Window>::FromWeakMapID); &mate::TrackableObject<Window>::FromWeakMapID);
browser_window.SetMethod("getAllWindows", browser_window.SetMethod("getAllWindows",

View file

@ -40,10 +40,10 @@ class WebContents;
class Window : public mate::TrackableObject<Window>, class Window : public mate::TrackableObject<Window>,
public NativeWindowObserver { public NativeWindowObserver {
public: public:
static mate::WrappableBase* New(v8::Isolate* isolate, mate::Arguments* args); static mate::WrappableBase* New(mate::Arguments* args);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
// Returns the BrowserWindow object from |native_window|. // Returns the BrowserWindow object from |native_window|.
static v8::Local<v8::Value> From(v8::Isolate* isolate, static v8::Local<v8::Value> From(v8::Isolate* isolate,
@ -52,12 +52,10 @@ class Window : public mate::TrackableObject<Window>,
NativeWindow* window() const { return window_.get(); } NativeWindow* window() const { return window_.get(); }
protected: protected:
Window(v8::Isolate* isolate, const mate::Dictionary& options); Window(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
const mate::Dictionary& options);
~Window() override; ~Window() override;
// TrackableObject:
void AfterInit(v8::Isolate* isolate) override;
// NativeWindowObserver: // NativeWindowObserver:
void WillCloseWindow(bool* prevent_default) override; void WillCloseWindow(bool* prevent_default) override;
void WillDestoryNativeObject() override; void WillDestoryNativeObject() override;

View file

@ -58,8 +58,9 @@ Handle<Event> Event::Create(v8::Isolate* isolate) {
// static // static
void Event::BuildPrototype( void Event::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "Event"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("preventDefault", &Event::PreventDefault) .SetMethod("preventDefault", &Event::PreventDefault)
.SetMethod("sendReply", &Event::SendReply); .SetMethod("sendReply", &Event::SendReply);
} }

View file

@ -21,7 +21,7 @@ class Event : public Wrappable<Event>,
static Handle<Event> Create(v8::Isolate* isolate); static Handle<Event> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
// Pass the sender and message to be replied. // Pass the sender and message to be replied.
void SetSenderAndMessage(content::WebContents* sender, IPC::Message* message); void SetSenderAndMessage(content::WebContents* sender, IPC::Message* message);

View file

@ -10,6 +10,8 @@
#include "native_mate/object_template_builder.h" #include "native_mate/object_template_builder.h"
#include "ui/events/event_constants.h" #include "ui/events/event_constants.h"
#include "atom/common/node_includes.h"
namespace mate { namespace mate {
namespace { namespace {

View file

@ -29,7 +29,7 @@ class IDUserData : public base::SupportsUserData::Data {
} // namespace } // namespace
TrackableObjectBase::TrackableObjectBase() TrackableObjectBase::TrackableObjectBase()
: weak_map_id_(0), wrapped_(nullptr), weak_factory_(this) { : weak_map_id_(0), weak_factory_(this) {
cleanup_ = RegisterDestructionCallback(GetDestroyClosure()); cleanup_ = RegisterDestructionCallback(GetDestroyClosure());
} }
@ -46,14 +46,7 @@ void TrackableObjectBase::Destroy() {
} }
void TrackableObjectBase::AttachAsUserData(base::SupportsUserData* wrapped) { void TrackableObjectBase::AttachAsUserData(base::SupportsUserData* wrapped) {
if (weak_map_id_ != 0) {
wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_)); 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;
}
} }
// static // static

View file

@ -44,7 +44,6 @@ class TrackableObjectBase {
static base::Closure RegisterDestructionCallback(const base::Closure& c); static base::Closure RegisterDestructionCallback(const base::Closure& c);
int32_t weak_map_id_; int32_t weak_map_id_;
base::SupportsUserData* wrapped_;
private: private:
void Destroy(); void Destroy();
@ -110,14 +109,13 @@ class TrackableObject : public TrackableObjectBase,
RemoveFromWeakMap(); RemoveFromWeakMap();
} }
void AfterInit(v8::Isolate* isolate) override { void InitWith(v8::Isolate* isolate, v8::Local<v8::Object> wrapper) override {
WrappableBase::InitWith(isolate, wrapper);
if (!weak_map_) { if (!weak_map_) {
weak_map_ = new atom::KeyWeakMap<int32_t>; weak_map_ = new atom::KeyWeakMap<int32_t>;
} }
weak_map_id_ = ++next_id_; weak_map_id_ = ++next_id_;
weak_map_->Set(isolate, weak_map_id_, Wrappable<T>::GetWrapper()); weak_map_->Set(isolate, weak_map_id_, wrapper);
if (wrapped_)
AttachAsUserData(wrapped_);
} }
private: private:

View file

@ -136,6 +136,7 @@ class Browser : public WindowListObserver {
// Hide/Show dock. // Hide/Show dock.
void DockHide(); void DockHide();
void DockShow(); void DockShow();
bool DockIsVisible();
// Set docks' menu. // Set docks' menu.
void DockSetMenu(AtomMenuModel* model); void DockSetMenu(AtomMenuModel* model);

View file

@ -208,6 +208,12 @@ void Browser::DockHide() {
TransformProcessType(&psn, kProcessTransformToUIElementApplication); 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() { void Browser::DockShow() {
BOOL active = [[NSRunningApplication currentApplication] isActive]; BOOL active = [[NSRunningApplication currentApplication] isActive];
ProcessSerialNumber psn = { 0, kCurrentProcess }; ProcessSerialNumber psn = { 0, kCurrentProcess };

View file

@ -29,8 +29,9 @@ class Archive : public mate::Wrappable<Archive> {
} }
static void BuildPrototype( static void BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "Archive"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetProperty("path", &Archive::GetPath) .SetProperty("path", &Archive::GetPath)
.SetMethod("getFileInfo", &Archive::GetFileInfo) .SetMethod("getFileInfo", &Archive::GetFileInfo)
.SetMethod("stat", &Archive::Stat) .SetMethod("stat", &Archive::Stat)

View file

@ -8,6 +8,7 @@
#include "atom/common/key_weak_map.h" #include "atom/common/key_weak_map.h"
#include "native_mate/object_template_builder.h" #include "native_mate/object_template_builder.h"
#include "native_mate/handle.h" #include "native_mate/handle.h"
#include "native_mate/wrappable.h"
namespace atom { namespace atom {
@ -21,8 +22,9 @@ class KeyWeakMap : public mate::Wrappable<KeyWeakMap<K>> {
} }
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "KeyWeakMap"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("set", &KeyWeakMap<K>::Set) .SetMethod("set", &KeyWeakMap<K>::Set)
.SetMethod("get", &KeyWeakMap<K>::Get) .SetMethod("get", &KeyWeakMap<K>::Get)
.SetMethod("has", &KeyWeakMap<K>::Has) .SetMethod("has", &KeyWeakMap<K>::Has)

View file

@ -355,8 +355,9 @@ mate::Handle<NativeImage> NativeImage::CreateFromDataURL(
// static // static
void NativeImage::BuildPrototype( void NativeImage::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "NativeImage"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("toPNG", &NativeImage::ToPNG) .SetMethod("toPNG", &NativeImage::ToPNG)
.SetMethod("toJPEG", &NativeImage::ToJPEG) .SetMethod("toJPEG", &NativeImage::ToJPEG)
.SetMethod("toBitmap", &NativeImage::ToBitmap) .SetMethod("toBitmap", &NativeImage::ToBitmap)

View file

@ -52,7 +52,7 @@ class NativeImage : public mate::Wrappable<NativeImage> {
v8::Isolate* isolate, const GURL& url); v8::Isolate* isolate, const GURL& url);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
#if defined(OS_WIN) #if defined(OS_WIN)
HICON GetHICON(int size); HICON GetHICON(int size);

View file

@ -9,7 +9,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "base/memory/linked_ptr.h" #include "base/macros.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
namespace atom { namespace atom {
@ -26,16 +26,16 @@ class KeyWeakMap {
KeyWeakMap() {} KeyWeakMap() {}
virtual ~KeyWeakMap() { virtual ~KeyWeakMap() {
for (const auto& p : map_) for (auto& p : map_)
p.second.second->ClearWeak(); p.second.second.ClearWeak();
} }
// Sets the object to WeakMap with the given |key|. // Sets the object to WeakMap with the given |key|.
void Set(v8::Isolate* isolate, const K& key, v8::Local<v8::Object> object) { void Set(v8::Isolate* isolate, const K& key, v8::Local<v8::Object> object) {
auto value = make_linked_ptr(new v8::Global<v8::Object>(isolate, object));
KeyObject key_object = {key, this}; KeyObject key_object = {key, this};
auto& p = map_[key] = std::make_pair(key_object, value); auto& p = map_[key] =
value->SetWeak(&(p.first), OnObjectGC, v8::WeakCallbackType::kParameter); std::make_pair(key_object, v8::Global<v8::Object>(isolate, object));
p.second.SetWeak(&(p.first), OnObjectGC, v8::WeakCallbackType::kParameter);
} }
// Gets the object from WeakMap by its |key|. // Gets the object from WeakMap by its |key|.
@ -44,7 +44,7 @@ class KeyWeakMap {
if (iter == map_.end()) if (iter == map_.end())
return v8::MaybeLocal<v8::Object>(); return v8::MaybeLocal<v8::Object>();
else else
return v8::Local<v8::Object>::New(isolate, *(iter->second.second)); return v8::Local<v8::Object>::New(isolate, iter->second.second);
} }
// Whethere there is an object with |key| in this WeakMap. // Whethere there is an object with |key| in this WeakMap.
@ -56,10 +56,8 @@ class KeyWeakMap {
std::vector<v8::Local<v8::Object>> Values(v8::Isolate* isolate) const { std::vector<v8::Local<v8::Object>> Values(v8::Isolate* isolate) const {
std::vector<v8::Local<v8::Object>> keys; std::vector<v8::Local<v8::Object>> keys;
keys.reserve(map_.size()); keys.reserve(map_.size());
for (const auto& iter : map_) { for (const auto& it : map_)
const auto& value = *(iter.second.second); keys.emplace_back(v8::Local<v8::Object>::New(isolate, it.second.second));
keys.emplace_back(v8::Local<v8::Object>::New(isolate, value));
}
return keys; return keys;
} }
@ -69,7 +67,7 @@ class KeyWeakMap {
if (iter == map_.end()) if (iter == map_.end())
return; return;
iter->second.second->ClearWeak(); iter->second.second.ClearWeak();
map_.erase(iter); map_.erase(iter);
} }
@ -82,7 +80,7 @@ class KeyWeakMap {
// Map of stored objects. // Map of stored objects.
std::unordered_map< std::unordered_map<
K, std::pair<KeyObject, linked_ptr<v8::Global<v8::Object>>>> map_; K, std::pair<KeyObject, v8::Global<v8::Object>>> map_;
DISALLOW_COPY_AND_ASSIGN(KeyWeakMap); DISALLOW_COPY_AND_ASSIGN(KeyWeakMap);
}; };

View file

@ -187,8 +187,9 @@ void WebFrame::ClearCache(v8::Isolate* isolate) {
// static // static
void WebFrame::BuildPrototype( void WebFrame::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype) prototype->SetClassName(mate::StringToV8(isolate, "WebFrame"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("setName", &WebFrame::SetName) .SetMethod("setName", &WebFrame::SetName)
.SetMethod("setZoomLevel", &WebFrame::SetZoomLevel) .SetMethod("setZoomLevel", &WebFrame::SetZoomLevel)
.SetMethod("getZoomLevel", &WebFrame::GetZoomLevel) .SetMethod("getZoomLevel", &WebFrame::GetZoomLevel)
@ -219,11 +220,14 @@ void WebFrame::BuildPrototype(
namespace { namespace {
using atom::api::WebFrame;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); 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 } // namespace

View file

@ -32,7 +32,7 @@ class WebFrame : public mate::Wrappable<WebFrame> {
static mate::Handle<WebFrame> Create(v8::Isolate* isolate); static mate::Handle<WebFrame> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
private: private:
explicit WebFrame(v8::Isolate* isolate); explicit WebFrame(v8::Isolate* isolate);

View file

@ -63,9 +63,9 @@ _リンクになっていないリストは未翻訳のものです。_
* [powerSaveBlocker](api/power-save-blocker.md) * [powerSaveBlocker](api/power-save-blocker.md)
* [protocol](api/protocol.md) * [protocol](api/protocol.md)
* [session](api/session.md) * [session](api/session.md)
* systemPreferences (api/system-preferences.md) * [systemPreferences](api/system-preferences.md)
* webContents (api/web-contents.md)
* [Tray](api/tray.md) * [Tray](api/tray.md)
* webContents (api/web-contents.md)
### Renderer Processのモジュール (Web Page): ### Renderer Processのモジュール (Web Page):

View file

@ -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

View file

@ -93,6 +93,6 @@ an issue:
* [Build Instructions (macOS)](development/build-instructions-osx.md) * [Build Instructions (macOS)](development/build-instructions-osx.md)
* [Build Instructions (Windows)](development/build-instructions-windows.md) * [Build Instructions (Windows)](development/build-instructions-windows.md)
* [Build Instructions (Linux)](development/build-instructions-linux.md) * [Build Instructions (Linux)](development/build-instructions-linux.md)
* [Debug Instructions (macOS)](development/debug-instructions-windows.md) * [Debug Instructions (macOS)](development/debug-instructions-macos.md)
* [Debug Instructions (Windows)](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) * [Setting Up Symbol Server in debugger](development/setting-up-symbol-server.md)

View file

@ -725,6 +725,12 @@ Hides the dock icon.
Shows 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_ ### `app.dock.setMenu(menu)` _macOS_
* `menu` [Menu](menu.md) * `menu` [Menu](menu.md)

View file

@ -31,15 +31,24 @@ Currently `PNG` and `JPEG` image formats are supported. `PNG` is recommended
because of its support for transparency and lossless compression. because of its support for transparency and lossless compression.
On Windows, you can also load `ICO` icons from file paths. For best visual 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 * Small icon
* 32x32 * 16x16 (100% DPI scale)
* 40x40 * 20x20 (125% DPI scale)
* 48x48 * 24x24 (150% DPI scale)
* 64x64 * 32x32 (200% DPI scale)
* Large icon
* 32x32 (100% DPI scale)
* 40x40 (125% DPI scale)
* 48x48 (150% DPI scale)
* 64x64 (200% DPI scale)
* 256x256 * 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 ## High Resolution Image
On platforms that have high-DPI support such as Apple Retina displays, you can On platforms that have high-DPI support such as Apple Retina displays, you can

View file

@ -651,6 +651,42 @@ Mute the audio on the current web page.
Returns whether this page has been muted. 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()` #### `contents.undo()`
Executes the editing command `undo` in web page. Executes the editing command `undo` in web page.

View file

@ -1,7 +1,7 @@
'use strict' 'use strict'
const bindings = process.atomBinding('app') const bindings = process.atomBinding('app')
const {app} = bindings const {app, App} = bindings
// Only one app object permitted. // Only one app object permitted.
module.exports = app module.exports = app
@ -10,7 +10,7 @@ const electron = require('electron')
const {deprecate, Menu} = electron const {deprecate, Menu} = electron
const {EventEmitter} = require('events') const {EventEmitter} = require('events')
Object.setPrototypeOf(app, EventEmitter.prototype) Object.setPrototypeOf(App.prototype, EventEmitter.prototype)
let appPath = null let appPath = null
@ -40,6 +40,7 @@ if (process.platform === 'darwin') {
getBadge: bindings.dockGetBadgeText, getBadge: bindings.dockGetBadgeText,
hide: bindings.dockHide, hide: bindings.dockHide,
show: bindings.dockShow, show: bindings.dockShow,
isVisible: bindings.dockIsVisible,
setMenu: bindings.dockSetMenu, setMenu: bindings.dockSetMenu,
setIcon: bindings.dockSetIcon setIcon: bindings.dockSetIcon
} }
@ -75,7 +76,5 @@ for (let name of events) {
} }
// Wrappers for native classes. // Wrappers for native classes.
process.atomBinding('download_item')._setWrapDownloadItem((downloadItem) => { const {DownloadItem} = process.atomBinding('download_item')
// downloadItem is an EventEmitter. Object.setPrototypeOf(DownloadItem.prototype, EventEmitter.prototype)
Object.setPrototypeOf(downloadItem, EventEmitter.prototype)
})

View file

@ -1,6 +1,6 @@
const EventEmitter = require('events').EventEmitter 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 module.exports = autoUpdater

View file

@ -1,6 +1,6 @@
const {EventEmitter} = require('events') 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 module.exports = powerMonitor

View file

@ -9,7 +9,7 @@ Object.setPrototypeOf(module.exports, new Proxy({}, {
if (!app.isReady()) return if (!app.isReady()) return
const protocol = session.defaultSession.protocol 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. // Returning a native function directly would throw error.
return (...args) => protocol[property](...args) return (...args) => protocol[property](...args)
@ -18,7 +18,7 @@ Object.setPrototypeOf(module.exports, new Proxy({}, {
ownKeys () { ownKeys () {
if (!app.isReady()) return [] if (!app.isReady()) return []
return Object.getOwnPropertyNames(session.defaultSession.protocol) return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession.protocol))
}, },
getOwnPropertyDescriptor (target) { getOwnPropertyDescriptor (target) {

View file

@ -1,6 +1,6 @@
const {EventEmitter} = require('events') 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 module.exports = screen

View file

@ -1,8 +1,8 @@
const {EventEmitter} = require('events') const {EventEmitter} = require('events')
const {app} = require('electron') 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, { Object.defineProperties(exports, {
defaultSession: { defaultSession: {
enumerable: true, enumerable: true,
@ -14,9 +14,8 @@ Object.defineProperties(exports, {
} }
}) })
// Wraps native Session class. Object.setPrototypeOf(Session.prototype, EventEmitter.prototype)
_setWrapSession(function (session) {
// Session is an EventEmitter. Session.prototype._init = function () {
Object.setPrototypeOf(session, EventEmitter.prototype) app.emit('session-created', this)
app.emit('session-created', session) }
})

View file

@ -1,6 +1,6 @@
const {EventEmitter} = require('events') 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 module.exports = systemPreferences

View file

@ -7,9 +7,6 @@ const {app, ipcMain, session, Menu, NavigationController} = require('electron')
// before the webContents module. // before the webContents module.
session session
const binding = process.atomBinding('web_contents')
const debuggerBinding = process.atomBinding('debugger')
let nextId = 0 let nextId = 0
const getNextId = function () { const getNextId = function () {
return ++nextId return ++nextId
@ -81,6 +78,24 @@ const defaultPrintingSetting = {
shouldPrintSelectionOnly: false 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. // Following methods are mapped to webFrame.
const webFrameMethods = [ const webFrameMethods = [
'insertText', 'insertText',
@ -88,55 +103,42 @@ const webFrameMethods = [
'setZoomLevel', 'setZoomLevel',
'setZoomLevelLimits' 'setZoomLevelLimits'
] ]
const webFrameMethodsWithResult = [
'getZoomFactor',
'getZoomLevel'
]
// Add JavaScript wrappers for WebContents class. const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
const wrapWebContents = function (webContents) {
// webContents is an EventEmitter.
Object.setPrototypeOf(webContents, EventEmitter.prototype)
// 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) 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) { ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) {
if (callback) callback(result) if (callback) callback(result)
}) })
} }
// Make sure webContents.executeJavaScript would run the code only when the const syncWebFrameMethods = function (requestId, method, callback, ...args) {
// webContents has been loaded. this.send('ELECTRON_INTERNAL_RENDERER_SYNC_WEB_FRAME_METHOD', requestId, method, args)
webContents.executeJavaScript = function (code, hasUserGesture, callback) { 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() const requestId = getNextId()
if (typeof hasUserGesture === 'function') { if (typeof hasUserGesture === 'function') {
callback = hasUserGesture callback = hasUserGesture
@ -149,41 +151,10 @@ const wrapWebContents = function (webContents) {
asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture) asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture)
}) })
} }
} }
// Dispatch IPC messages to the ipc module. // Translate the options of printToPDF.
webContents.on('ipc-message', function (event, [channel, ...args]) { WebContents.prototype.printToPDF = function (options, callback) {
ipcMain.emit(channel, event, ...args)
})
webContents.on('ipc-message-sync', function (event, [channel, ...args]) {
Object.defineProperty(event, 'returnValue', {
set: function (value) {
return event.sendReply(JSON.stringify(value))
},
get: function () {}
})
ipcMain.emit(channel, event, ...args)
})
// Handle context menu action request from pepper plugin.
webContents.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()
})
// Delays the page-title-updated event to next tick.
webContents.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) const printingSetting = Object.assign({}, defaultPrintingSetting)
if (options.landscape) { if (options.landscape) {
printingSetting.landscape = options.landscape printingSetting.landscape = options.landscape
@ -222,21 +193,58 @@ const wrapWebContents = function (webContents) {
} }
this._printToPDF(printingSetting, callback) this._printToPDF(printingSetting, callback)
}
app.emit('web-contents-created', {}, webContents)
} }
binding._setWrapWebContents(wrapWebContents) // Add JavaScript wrappers for WebContents class.
WebContents.prototype._init = function () {
// The navigation controller.
NavigationController.call(this, this)
// Add JavaScript wrappers for Debugger class. // Every remote callback from renderer process would add a listenter to the
const wrapDebugger = function (webContentsDebugger) { // render-view-deleted event, so ignore the listenters warning.
// debugger is an EventEmitter. this.setMaxListeners(0)
Object.setPrototypeOf(webContentsDebugger, EventEmitter.prototype)
// Dispatch IPC messages to the ipc module.
this.on('ipc-message', function (event, [channel, ...args]) {
ipcMain.emit(channel, event, ...args)
})
this.on('ipc-message-sync', function (event, [channel, ...args]) {
Object.defineProperty(event, 'returnValue', {
set: function (value) {
return event.sendReply(JSON.stringify(value))
},
get: function () {}
})
ipcMain.emit(channel, event, ...args)
})
// Handle context menu action request from pepper plugin.
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.
this.on('devtools-reload-page', function () {
this.reload()
})
// Delays the page-title-updated event to next tick.
this.on('-page-title-updated', function (...args) {
setImmediate(() => {
this.emit.apply(this, ['page-title-updated'].concat(args))
})
})
app.emit('web-contents-created', {}, this)
} }
debuggerBinding._setWrapDebugger(wrapDebugger) // JavaScript wrapper of Debugger.
const {Debugger} = process.atomBinding('debugger')
Object.setPrototypeOf(Debugger.prototype, EventEmitter.prototype)
// Public APIs.
module.exports = { module.exports = {
create (options = {}) { create (options = {}) {
return binding.create(options) return binding.create(options)

View file

@ -65,7 +65,7 @@ process.on('uncaughtException', function (error) {
}) })
// Emit 'exit' event on quit. // Emit 'exit' event on quit.
var app = require('electron').app const {app} = require('electron')
app.on('quit', function (event, exitCode) { app.on('quit', function (event, exitCode) {
process.emit('exit', exitCode) process.emit('exit', exitCode)
@ -86,15 +86,12 @@ if (process.platform === 'win32') {
// form `com.squirrel.PACKAGE-NAME.OUREXE`. We need to call // form `com.squirrel.PACKAGE-NAME.OUREXE`. We need to call
// app.setAppUserModelId with a matching identifier so that renderer processes // app.setAppUserModelId with a matching identifier so that renderer processes
// will inherit this value. // will inherit this value.
var updateDotExe = path.join( const updateDotExe = path.join(path.dirname(process.execPath), '..', 'update.exe')
path.dirname(process.execPath),
'..',
'update.exe')
if (fs.statSyncNoException(updateDotExe)) { if (fs.existsSync(updateDotExe)) {
var packageDir = path.dirname(path.resolve(updateDotExe)) const packageDir = path.dirname(path.resolve(updateDotExe))
var packageName = path.basename(packageDir).replace(/\s/g, '') const packageName = path.basename(packageDir).replace(/\s/g, '')
var exeName = path.basename(process.execPath).replace(/\.exe$/i, '').replace(/\s/g, '') const exeName = path.basename(process.execPath).replace(/\.exe$/i, '').replace(/\s/g, '')
app.setAppUserModelId(`com.squirrel.${packageName}.${exeName}`) app.setAppUserModelId(`com.squirrel.${packageName}.${exeName}`)
} }
@ -108,15 +105,13 @@ require('./rpc-server')
// Load the guest view manager. // Load the guest view manager.
require('./guest-view-manager') require('./guest-view-manager')
require('./guest-window-manager') require('./guest-window-manager')
// Now we try to load app's package.json. // Now we try to load app's package.json.
var packageJson = null let packagePath = null
var searchPaths = ['app', 'app.asar', 'default_app.asar'] let packageJson = null
var i, len, packagePath const searchPaths = ['app', 'app.asar', 'default_app.asar']
for (i = 0, len = searchPaths.length; i < len; i++) { for (packagePath of searchPaths) {
packagePath = searchPaths[i]
try { try {
packagePath = path.join(process.resourcesPath, packagePath) packagePath = path.join(process.resourcesPath, packagePath)
packageJson = require(path.join(packagePath, 'package.json')) packageJson = require(path.join(packagePath, 'package.json'))
@ -157,14 +152,9 @@ if (packageJson.v8Flags != null) {
v8.setFlagsFromString(packageJson.v8Flags) 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. // Set the user path according to application's name.
app.setPath('userData', path.join(app.getPath('appData'), app.getName())) app.setPath('userData', path.join(app.getPath('appData'), app.getName()))
app.setPath('userCache', path.join(app.getPath('cache'), app.getName())) app.setPath('userCache', path.join(app.getPath('cache'), app.getName()))
app.setAppPath(packagePath) app.setAppPath(packagePath)
// Load the chrome extension support. // Load the chrome extension support.
@ -177,7 +167,7 @@ require('./desktop-capturer')
require('./api/protocol') require('./api/protocol')
// Set main startup script of the app. // 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++. // Finally load app's main.js and transfer control to C++.
Module._load(path.join(packagePath, mainStartupScript), Module, true) Module._load(path.join(packagePath, mainStartupScript), Module, true)

View file

@ -1,11 +1,10 @@
'use strict' '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.prototype, EventEmitter.prototype)
// webFrame is an EventEmitter.
Object.setPrototypeOf(webFrame, EventEmitter.prototype)
// Lots of webview would subscribe to webFrame's events. // Lots of webview would subscribe to webFrame's events.
webFrame.setMaxListeners(0) webFrame.setMaxListeners(0)

View file

@ -32,6 +32,11 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', (event, m
electron.webFrame[method].apply(electron.webFrame, args) 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) => { electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (event, requestId, method, args) => {
const responseCallback = function (result) { const responseCallback = function (result) {
event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, result) event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, result)

View file

@ -8,7 +8,7 @@ import sys
BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \
'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent' 'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent'
LIBCHROMIUMCONTENT_COMMIT = '141739f27054dbe032226a6547ff27a9f5f5626c' LIBCHROMIUMCONTENT_COMMIT = '658edcb9509cfa03eea321977d060769467891e0'
PLATFORM = { PLATFORM = {
'cygwin': 'win32', 'cygwin': 'win32',

View file

@ -18,6 +18,9 @@ import zipfile
from config import is_verbose_mode from config import is_verbose_mode
from env_util import get_vs_env from env_util import get_vs_env
BOTO_DIR = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'vendor',
'boto'))
def get_host_arch(): def get_host_arch():
"""Returns the host architecture with a predictable string.""" """Returns the host architecture with a predictable string."""
@ -202,28 +205,33 @@ def parse_version(version):
return vs + ['0'] * (4 - len(vs)) return vs + ['0'] * (4 - len(vs))
def s3put(bucket, access_key, secret_key, prefix, key_prefix, files): def boto_path_dirs():
env = os.environ.copy() return [
BOTO_DIR = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'vendor',
'boto'))
env['PYTHONPATH'] = os.path.pathsep.join([
env.get('PYTHONPATH', ''),
os.path.join(BOTO_DIR, 'build', 'lib'), 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 = [ args = [
sys.executable,
boto,
'--bucket', bucket, '--bucket', bucket,
'--access_key', access_key,
'--secret_key', secret_key,
'--prefix', prefix, '--prefix', prefix,
'--key_prefix', key_prefix, '--key_prefix', key_prefix,
'--grant', 'public-read' '--grant', 'public-read'
] + files ] + files
execute(args, env) run_boto_script(access_key, secret_key, 's3put', *args)
def import_vs_env(target_arch): def import_vs_env(target_arch):

View file

@ -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())

View file

@ -2,15 +2,17 @@
import argparse import argparse
import errno import errno
import hashlib
import os import os
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
from io import StringIO
from lib.config import PLATFORM, get_target_arch, get_chromedriver_version, \ 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, \ from lib.util import electron_gyp, execute, get_electron_version, \
parse_version, scoped_cwd parse_version, scoped_cwd, s3put
from lib.github import GitHub from lib.github import GitHub
@ -46,8 +48,7 @@ def main():
if not args.publish_release: if not args.publish_release:
if not dist_newer_than_head(): if not dist_newer_than_head():
create_dist = os.path.join(SOURCE_ROOT, 'script', 'create-dist.py') run_python_script('create-dist.py')
execute([sys.executable, create_dist])
build_version = get_electron_build_version() build_version = get_electron_build_version()
if not ELECTRON_VERSION.startswith(build_version): if not ELECTRON_VERSION.startswith(build_version):
@ -69,14 +70,14 @@ def main():
tag_exists) tag_exists)
if args.publish_release: if args.publish_release:
# Upload the SHASUMS.txt. # Upload the Node SHASUMS*.txt.
execute([sys.executable, run_python_script('upload-node-checksums.py', '-v', ELECTRON_VERSION)
os.path.join(SOURCE_ROOT, 'script', 'upload-checksums.py'),
'-v', ELECTRON_VERSION])
# Upload the index.json. # Upload the index.json.
execute([sys.executable, run_python_script('upload-index-json.py')
os.path.join(SOURCE_ROOT, 'script', 'upload-index-json.py')])
# Create and upload the Electron SHASUMS*.txt
release_electron_checksums(github, release)
# Press the publish button. # Press the publish button.
publish_release(github, release['id']) publish_release(github, release['id'])
@ -108,13 +109,10 @@ def main():
if PLATFORM == 'win32' and not tag_exists: if PLATFORM == 'win32' and not tag_exists:
# Upload PDBs to Windows symbol server. # Upload PDBs to Windows symbol server.
execute([sys.executable, run_python_script('upload-windows-pdb.py')
os.path.join(SOURCE_ROOT, 'script', 'upload-windows-pdb.py')])
# Upload node headers. # Upload node headers.
execute([sys.executable, run_python_script('upload-node-headers.py', '-v', args.version)
os.path.join(SOURCE_ROOT, 'script', 'upload-node-headers.py'),
'-v', args.version])
def parse_args(): def parse_args():
@ -127,6 +125,11 @@ def parse_args():
return parser.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(): def get_electron_build_version():
if get_target_arch() == 'arm' or os.environ.has_key('CI'): if get_target_arch() == 'arm' or os.environ.has_key('CI'):
# In CI we just build as told. # In CI we just build as told.
@ -202,23 +205,51 @@ def create_release_draft(github, tag):
return r 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): def upload_electron(github, release, file_path):
# Delete the original file before uploading in CI. # Delete the original file before uploading in CI.
filename = os.path.basename(file_path)
if os.environ.has_key('CI'): if os.environ.has_key('CI'):
try: try:
for asset in release['assets']: 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() github.repos(ELECTRON_REPO).releases.assets(asset['id']).delete()
break
except Exception: except Exception:
pass pass
# Upload the file. # Upload the file.
params = {'name': os.path.basename(file_path)}
headers = {'Content-Type': 'application/zip'}
with open(file_path, 'rb') as f: with open(file_path, 'rb') as f:
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( github.repos(ELECTRON_REPO).releases(release['id']).assets.post(
params=params, headers=headers, data=f, verify=False) 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): def publish_release(github, release_id):

2
vendor/native_mate vendored

@ -1 +1 @@
Subproject commit d9bfe6a49d8585916bd8dc77165154afeee4e5b6 Subproject commit fa483e1fe012f873ad9812a67a66e2b7dbb570c6