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
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());
mate::ObjectTemplateBuilder(isolate, prototype)
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("quit", base::Bind(&Browser::Quit, browser))
.SetMethod("exit", base::Bind(&Browser::Exit, browser))
.SetMethod("focus", base::Bind(&Browser::Focus, browser))
@ -638,6 +639,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
auto command_line = base::CommandLine::ForCurrentProcess();
mate::Dictionary dict(isolate, exports);
dict.Set("App", atom::api::App::GetConstructor(isolate)->GetFunction());
dict.Set("app", atom::api::App::Create(isolate));
dict.SetMethod("appendSwitch", &AppendSwitch);
dict.SetMethod("appendArgument",
@ -656,6 +658,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
base::Bind(&Browser::DockGetBadgeText, browser));
dict.SetMethod("dockHide", base::Bind(&Browser::DockHide, browser));
dict.SetMethod("dockShow", base::Bind(&Browser::DockShow, browser));
dict.SetMethod("dockIsVisible", base::Bind(&Browser::DockIsVisible, browser));
dict.SetMethod("dockSetMenu", &DockSetMenu);
dict.SetMethod("dockSetIcon", base::Bind(&Browser::DockSetIcon, browser));
#endif

View file

@ -40,7 +40,7 @@ class App : public AtomBrowserClient::Delegate,
static mate::Handle<App> Create(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.
void OnCreateWindow(const GURL& target_url,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -17,7 +17,7 @@ namespace api {
class MenuMac : public Menu {
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;

View file

@ -18,7 +18,8 @@ namespace atom {
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) {
@ -94,8 +95,8 @@ void Menu::SendActionToFirstResponder(const std::string& action) {
}
// static
mate::WrappableBase* Menu::Create(v8::Isolate* isolate) {
return new MenuMac(isolate);
mate::WrappableBase* Menu::New(mate::Arguments* args) {
return new MenuMac(args->isolate(), args->GetThis());
}
} // namespace api

View file

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

View file

@ -14,7 +14,7 @@ namespace api {
class MenuViews : public Menu {
public:
explicit MenuViews(v8::Isolate* isolate);
MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
protected:
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
void PowerMonitor::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype);
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "PowerMonitor"));
}
} // namespace api
@ -63,16 +63,19 @@ void PowerMonitor::BuildPrototype(
namespace {
using atom::api::PowerMonitor;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
#if defined(OS_MACOSX)
base::PowerMonitorDeviceSource::AllocateSystemIOPorts();
#endif
using atom::api::PowerMonitor;
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("powerMonitor", PowerMonitor::Create(isolate));
dict.Set("PowerMonitor",
PowerMonitor::GetConstructor(isolate)->GetFunction());
}
} // namespace

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -20,7 +20,7 @@ class RenderProcessPreferences
ForAllWebContents(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);
void RemoveEntry(int id);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -21,7 +21,7 @@ class Event : public Wrappable<Event>,
static Handle<Event> Create(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.
void SetSenderAndMessage(content::WebContents* sender, IPC::Message* message);

View file

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

View file

@ -29,7 +29,7 @@ class IDUserData : public base::SupportsUserData::Data {
} // namespace
TrackableObjectBase::TrackableObjectBase()
: weak_map_id_(0), wrapped_(nullptr), weak_factory_(this) {
: weak_map_id_(0), weak_factory_(this) {
cleanup_ = RegisterDestructionCallback(GetDestroyClosure());
}
@ -46,14 +46,7 @@ void TrackableObjectBase::Destroy() {
}
void TrackableObjectBase::AttachAsUserData(base::SupportsUserData* wrapped) {
if (weak_map_id_ != 0) {
wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_));
wrapped_ = nullptr;
} else {
// If the TrackableObjectBase is not ready yet then delay SetUserData until
// AfterInit is called.
wrapped_ = wrapped;
}
wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_));
}
// static

View file

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

View file

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

View file

@ -208,6 +208,12 @@ void Browser::DockHide() {
TransformProcessType(&psn, kProcessTransformToUIElementApplication);
}
bool Browser::DockIsVisible() {
// Because DockShow has a slight delay this may not be true immediately
// after that call.
return ([[NSRunningApplication currentApplication] activationPolicy] == NSApplicationActivationPolicyRegular);
}
void Browser::DockShow() {
BOOL active = [[NSRunningApplication currentApplication] isActive];
ProcessSerialNumber psn = { 0, kCurrentProcess };

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

@ -725,6 +725,12 @@ Hides the dock icon.
Shows the dock icon.
### `app.dock.isVisible()` _macOS_
Returns whether the dock icon is visible.
The `app.dock.show()` call is asynchronous so this method might not
return true immediately after that call.
### `app.dock.setMenu(menu)` _macOS_
* `menu` [Menu](menu.md)

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.
On Windows, you can also load `ICO` icons from file paths. For best visual
quality it is recommended to include at least the following sizes in the icon:
quality it is recommended to include at least the following sizes in the:
* 16x16
* 32x32
* 40x40
* 48x48
* 64x64
* Small icon
* 16x16 (100% DPI scale)
* 20x20 (125% DPI scale)
* 24x24 (150% DPI scale)
* 32x32 (200% DPI scale)
* Large icon
* 32x32 (100% DPI scale)
* 40x40 (125% DPI scale)
* 48x48 (150% DPI scale)
* 64x64 (200% DPI scale)
* 256x256
Check the *Size requirements* section in [this article][icons].
[icons]:https://msdn.microsoft.com/en-us/library/windows/desktop/dn742485(v=vs.85).aspx
## High Resolution Image
On platforms that have high-DPI support such as Apple Retina displays, you can

View file

@ -651,6 +651,42 @@ Mute the audio on the current web page.
Returns whether this page has been muted.
#### `contents.setZoomFactor(factor)`
* `factor` Number - Zoom factor.
Changes the zoom factor to the specified factor. Zoom factor is
zoom percent divided by 100, so 300% = 3.0.
#### `contents.getZoomFactor(callback)`
* `callback` Function
Sends a request to get current zoom factor, the `callback` will be called with
`callback(zoomFactor)`.
#### `contents.setZoomLevel(level)`
* `level` Number - Zoom level
Changes the zoom level to the specified level. The original size is 0 and each
increment above or below represents zooming 20% larger or smaller to default
limits of 300% and 50% of original size, respectively.
#### `contents.getZoomLevel(callback)`
* `callback` Function
Sends a request to get current zoom level, the `callback` will be called with
`callback(zoomLevel)`.
#### `contents.setZoomLevelLimits(minimumLevel, maximumLevel)`
* `minimumLevel` Number
* `maximumLevel` Number
Sets the maximum and minimum zoom level.`
#### `contents.undo()`
Executes the editing command `undo` in web page.

View file

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

View file

@ -1,6 +1,6 @@
const EventEmitter = require('events').EventEmitter
const autoUpdater = process.atomBinding('auto_updater').autoUpdater
const {autoUpdater, AutoUpdater} = process.atomBinding('auto_updater')
Object.setPrototypeOf(autoUpdater, EventEmitter.prototype)
Object.setPrototypeOf(AutoUpdater.prototype, EventEmitter.prototype)
module.exports = autoUpdater

View file

@ -1,6 +1,6 @@
const {EventEmitter} = require('events')
const {powerMonitor} = process.atomBinding('power_monitor')
const {powerMonitor, PowerMonitor} = process.atomBinding('power_monitor')
Object.setPrototypeOf(powerMonitor, EventEmitter.prototype)
Object.setPrototypeOf(PowerMonitor.prototype, EventEmitter.prototype)
module.exports = powerMonitor

View file

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

View file

@ -1,6 +1,6 @@
const {EventEmitter} = require('events')
const {screen} = process.atomBinding('screen')
const {screen, Screen} = process.atomBinding('screen')
Object.setPrototypeOf(screen, EventEmitter.prototype)
Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype)
module.exports = screen

View file

@ -1,8 +1,8 @@
const {EventEmitter} = require('events')
const {app} = require('electron')
const {fromPartition, _setWrapSession} = process.atomBinding('session')
const {fromPartition, Session} = process.atomBinding('session')
// Returns the default session.
// Public API.
Object.defineProperties(exports, {
defaultSession: {
enumerable: true,
@ -14,9 +14,8 @@ Object.defineProperties(exports, {
}
})
// Wraps native Session class.
_setWrapSession(function (session) {
// Session is an EventEmitter.
Object.setPrototypeOf(session, EventEmitter.prototype)
app.emit('session-created', session)
})
Object.setPrototypeOf(Session.prototype, EventEmitter.prototype)
Session.prototype._init = function () {
app.emit('session-created', this)
}

View file

@ -1,6 +1,6 @@
const {EventEmitter} = require('events')
const {systemPreferences} = process.atomBinding('system_preferences')
const {systemPreferences, SystemPreferences} = process.atomBinding('system_preferences')
Object.setPrototypeOf(systemPreferences, EventEmitter.prototype)
Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype)
module.exports = systemPreferences

View file

@ -7,9 +7,6 @@ const {app, ipcMain, session, Menu, NavigationController} = require('electron')
// before the webContents module.
session
const binding = process.atomBinding('web_contents')
const debuggerBinding = process.atomBinding('debugger')
let nextId = 0
const getNextId = function () {
return ++nextId
@ -81,6 +78,24 @@ const defaultPrintingSetting = {
shouldPrintSelectionOnly: false
}
// JavaScript implementations of WebContents.
const binding = process.atomBinding('web_contents')
const {WebContents} = binding
Object.setPrototypeOf(NavigationController.prototype, EventEmitter.prototype)
Object.setPrototypeOf(WebContents.prototype, NavigationController.prototype)
// WebContents::send(channel, args..)
// WebContents::sendToAll(channel, args..)
WebContents.prototype.send = function (channel, ...args) {
if (channel == null) throw new Error('Missing required channel argument')
return this._send(false, channel, args)
}
WebContents.prototype.sendToAll = function (channel, ...args) {
if (channel == null) throw new Error('Missing required channel argument')
return this._send(true, channel, args)
}
// Following methods are mapped to webFrame.
const webFrameMethods = [
'insertText',
@ -88,74 +103,112 @@ const webFrameMethods = [
'setZoomLevel',
'setZoomLevelLimits'
]
const webFrameMethodsWithResult = [
'getZoomFactor',
'getZoomLevel'
]
const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) {
if (callback) callback(result)
})
}
const syncWebFrameMethods = function (requestId, method, callback, ...args) {
this.send('ELECTRON_INTERNAL_RENDERER_SYNC_WEB_FRAME_METHOD', requestId, method, args)
ipcMain.once(`ELECTRON_INTERNAL_BROWSER_SYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) {
if (callback) callback(result)
})
}
for (const method of webFrameMethods) {
WebContents.prototype[method] = function (...args) {
this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args)
}
}
for (const method of webFrameMethodsWithResult) {
WebContents.prototype[method] = function (...args) {
const callback = args[args.length - 1]
const actualArgs = args.slice(0, args.length - 2)
syncWebFrameMethods.call(this, getNextId(), method, callback, ...actualArgs)
}
}
// Make sure WebContents::executeJavaScript would run the code only when the
// WebContents has been loaded.
WebContents.prototype.executeJavaScript = function (code, hasUserGesture, callback) {
const requestId = getNextId()
if (typeof hasUserGesture === 'function') {
callback = hasUserGesture
hasUserGesture = false
}
if (this.getURL() && !this.isLoadingMainFrame()) {
asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture)
} else {
this.once('did-finish-load', () => {
asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture)
})
}
}
// Translate the options of printToPDF.
WebContents.prototype.printToPDF = function (options, callback) {
const printingSetting = Object.assign({}, defaultPrintingSetting)
if (options.landscape) {
printingSetting.landscape = options.landscape
}
if (options.marginsType) {
printingSetting.marginsType = options.marginsType
}
if (options.printSelectionOnly) {
printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly
}
if (options.printBackground) {
printingSetting.shouldPrintBackgrounds = options.printBackground
}
if (options.pageSize) {
const pageSize = options.pageSize
if (typeof pageSize === 'object') {
if (!pageSize.height || !pageSize.width) {
return callback(new Error('Must define height and width for pageSize'))
}
// Dimensions in Microns
// 1 meter = 10^6 microns
printingSetting.mediaSize = {
name: 'CUSTOM',
custom_display_name: 'Custom',
height_microns: pageSize.height,
width_microns: pageSize.width
}
} else if (PDFPageSizes[pageSize]) {
printingSetting.mediaSize = PDFPageSizes[pageSize]
} else {
return callback(new Error(`Does not support pageSize with ${pageSize}`))
}
} else {
printingSetting.mediaSize = PDFPageSizes['A4']
}
this._printToPDF(printingSetting, callback)
}
// Add JavaScript wrappers for WebContents class.
const wrapWebContents = function (webContents) {
// webContents is an EventEmitter.
Object.setPrototypeOf(webContents, EventEmitter.prototype)
WebContents.prototype._init = function () {
// The navigation controller.
NavigationController.call(this, this)
// Every remote callback from renderer process would add a listenter to the
// render-view-deleted event, so ignore the listenters warning.
webContents.setMaxListeners(0)
// WebContents::send(channel, args..)
// WebContents::sendToAll(channel, args..)
const sendWrapper = (allFrames, channel, ...args) => {
if (channel == null) {
throw new Error('Missing required channel argument')
}
return webContents._send(allFrames, channel, args)
}
webContents.send = sendWrapper.bind(null, false)
webContents.sendToAll = sendWrapper.bind(null, true)
// The navigation controller.
const controller = new NavigationController(webContents)
for (const name in NavigationController.prototype) {
const method = NavigationController.prototype[name]
if (method instanceof Function) {
webContents[name] = function () {
return method.apply(controller, arguments)
}
}
}
// Mapping webFrame methods.
for (const method of webFrameMethods) {
webContents[method] = function (...args) {
this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args)
}
}
const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) {
if (callback) callback(result)
})
}
// Make sure webContents.executeJavaScript would run the code only when the
// webContents has been loaded.
webContents.executeJavaScript = function (code, hasUserGesture, callback) {
const requestId = getNextId()
if (typeof hasUserGesture === 'function') {
callback = hasUserGesture
hasUserGesture = false
}
if (this.getURL() && !this.isLoadingMainFrame()) {
asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture)
} else {
this.once('did-finish-load', () => {
asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture)
})
}
}
this.setMaxListeners(0)
// Dispatch IPC messages to the ipc module.
webContents.on('ipc-message', function (event, [channel, ...args]) {
this.on('ipc-message', function (event, [channel, ...args]) {
ipcMain.emit(channel, event, ...args)
})
webContents.on('ipc-message-sync', function (event, [channel, ...args]) {
this.on('ipc-message-sync', function (event, [channel, ...args]) {
Object.defineProperty(event, 'returnValue', {
set: function (value) {
return event.sendReply(JSON.stringify(value))
@ -166,77 +219,32 @@ const wrapWebContents = function (webContents) {
})
// Handle context menu action request from pepper plugin.
webContents.on('pepper-context-menu', function (event, params) {
this.on('pepper-context-menu', function (event, params) {
const menu = Menu.buildFromTemplate(params.menu)
menu.popup(params.x, params.y)
})
// The devtools requests the webContents to reload.
webContents.on('devtools-reload-page', function () {
webContents.reload()
this.on('devtools-reload-page', function () {
this.reload()
})
// Delays the page-title-updated event to next tick.
webContents.on('-page-title-updated', function (...args) {
this.on('-page-title-updated', function (...args) {
setImmediate(() => {
this.emit.apply(this, ['page-title-updated'].concat(args))
})
})
webContents.printToPDF = function (options, callback) {
const printingSetting = Object.assign({}, defaultPrintingSetting)
if (options.landscape) {
printingSetting.landscape = options.landscape
}
if (options.marginsType) {
printingSetting.marginsType = options.marginsType
}
if (options.printSelectionOnly) {
printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly
}
if (options.printBackground) {
printingSetting.shouldPrintBackgrounds = options.printBackground
}
if (options.pageSize) {
const pageSize = options.pageSize
if (typeof pageSize === 'object') {
if (!pageSize.height || !pageSize.width) {
return callback(new Error('Must define height and width for pageSize'))
}
// Dimensions in Microns
// 1 meter = 10^6 microns
printingSetting.mediaSize = {
name: 'CUSTOM',
custom_display_name: 'Custom',
height_microns: pageSize.height,
width_microns: pageSize.width
}
} else if (PDFPageSizes[pageSize]) {
printingSetting.mediaSize = PDFPageSizes[pageSize]
} else {
return callback(new Error(`Does not support pageSize with ${pageSize}`))
}
} else {
printingSetting.mediaSize = PDFPageSizes['A4']
}
this._printToPDF(printingSetting, callback)
}
app.emit('web-contents-created', {}, webContents)
app.emit('web-contents-created', {}, this)
}
binding._setWrapWebContents(wrapWebContents)
// JavaScript wrapper of Debugger.
const {Debugger} = process.atomBinding('debugger')
// Add JavaScript wrappers for Debugger class.
const wrapDebugger = function (webContentsDebugger) {
// debugger is an EventEmitter.
Object.setPrototypeOf(webContentsDebugger, EventEmitter.prototype)
}
debuggerBinding._setWrapDebugger(wrapDebugger)
Object.setPrototypeOf(Debugger.prototype, EventEmitter.prototype)
// Public APIs.
module.exports = {
create (options = {}) {
return binding.create(options)

View file

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

View file

@ -1,11 +1,10 @@
'use strict'
const EventEmitter = require('events').EventEmitter
const {EventEmitter} = require('events')
const {webFrame, WebFrame} = process.atomBinding('web_frame')
const webFrame = process.atomBinding('web_frame').webFrame
// webFrame is an EventEmitter.
Object.setPrototypeOf(webFrame, EventEmitter.prototype)
// WebFrame is an EventEmitter.
Object.setPrototypeOf(WebFrame.prototype, EventEmitter.prototype)
// Lots of webview would subscribe to webFrame's events.
webFrame.setMaxListeners(0)

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

View file

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

View file

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

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

2
vendor/native_mate vendored

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