Merge remote-tracking branch 'origin/master' into chrome58
This commit is contained in:
commit
fb85b26767
49 changed files with 721 additions and 208 deletions
|
@ -72,10 +72,11 @@ locations:
|
|||
forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
||||
- [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
||||
- [`electron-tr`](https://electron-tr.slack.com) *(Turkish)*
|
||||
- [`electron-tr`](http://electron-tr.herokuapp.com) *(Turkish)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
|
|
|
@ -34,12 +34,12 @@
|
|||
#include "chrome/browser/icon_manager.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
#include "content/public/browser/browser_accessibility_state.h"
|
||||
#include "content/public/browser/browser_child_process_host.h"
|
||||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
#include "content/public/browser/gpu_data_manager.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "media/audio/audio_manager.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
@ -337,6 +337,17 @@ namespace api {
|
|||
|
||||
namespace {
|
||||
|
||||
class AppIdProcessIterator : public base::ProcessIterator {
|
||||
public:
|
||||
AppIdProcessIterator() : base::ProcessIterator(nullptr) {}
|
||||
|
||||
protected:
|
||||
bool IncludeEntry() override {
|
||||
return (entry().parent_pid() == base::GetCurrentProcId() ||
|
||||
entry().pid() == base::GetCurrentProcId());
|
||||
}
|
||||
};
|
||||
|
||||
IconLoader::IconSize GetIconSizeByString(const std::string& size) {
|
||||
if (size == "small") {
|
||||
return IconLoader::IconSize::SMALL;
|
||||
|
@ -912,6 +923,47 @@ void App::GetFileIcon(const base::FilePath& path,
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<mate::Dictionary> App::GetAppMemoryInfo(v8::Isolate* isolate) {
|
||||
AppIdProcessIterator process_iterator;
|
||||
auto process_entry = process_iterator.NextProcessEntry();
|
||||
std::vector<mate::Dictionary> result;
|
||||
|
||||
while (process_entry != nullptr) {
|
||||
int64_t pid = process_entry->pid();
|
||||
auto process = base::Process::OpenWithExtraPrivileges(pid);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
std::unique_ptr<base::ProcessMetrics> metrics(
|
||||
base::ProcessMetrics::CreateProcessMetrics(
|
||||
process.Handle(), content::BrowserChildProcessHost::GetPortProvider()));
|
||||
#else
|
||||
std::unique_ptr<base::ProcessMetrics> metrics(
|
||||
base::ProcessMetrics::CreateProcessMetrics(process.Handle()));
|
||||
#endif
|
||||
|
||||
mate::Dictionary pid_dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
mate::Dictionary memory_dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
|
||||
memory_dict.Set("workingSetSize",
|
||||
static_cast<double>(metrics->GetWorkingSetSize() >> 10));
|
||||
memory_dict.Set("peakWorkingSetSize",
|
||||
static_cast<double>(metrics->GetPeakWorkingSetSize() >> 10));
|
||||
|
||||
size_t private_bytes, shared_bytes;
|
||||
if (metrics->GetMemoryBytes(&private_bytes, &shared_bytes)) {
|
||||
memory_dict.Set("privateBytes", static_cast<double>(private_bytes >> 10));
|
||||
memory_dict.Set("sharedBytes", static_cast<double>(shared_bytes >> 10));
|
||||
}
|
||||
|
||||
pid_dict.Set("memory", memory_dict);
|
||||
pid_dict.Set("pid", pid);
|
||||
result.push_back(pid_dict);
|
||||
process_entry = process_iterator.NextProcessEntry();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<App> App::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new App(isolate));
|
||||
|
@ -983,7 +1035,8 @@ void App::BuildPrototype(
|
|||
&App::IsAccessibilitySupportEnabled)
|
||||
.SetMethod("disableHardwareAcceleration",
|
||||
&App::DisableHardwareAcceleration)
|
||||
.SetMethod("getFileIcon", &App::GetFileIcon);
|
||||
.SetMethod("getFileIcon", &App::GetFileIcon)
|
||||
.SetMethod("getAppMemoryInfo", &App::GetAppMemoryInfo);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/browser_observer.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "base/process/process_iterator.h"
|
||||
#include "base/task/cancelable_task_tracker.h"
|
||||
#include "chrome/browser/icon_manager.h"
|
||||
#include "chrome/browser/process_singleton.h"
|
||||
#include "content/public/browser/gpu_data_manager_observer.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
|
||||
|
@ -141,6 +143,8 @@ class App : public AtomBrowserClient::Delegate,
|
|||
void GetFileIcon(const base::FilePath& path,
|
||||
mate::Arguments* args);
|
||||
|
||||
std::vector<mate::Dictionary> GetAppMemoryInfo(v8::Isolate* isolate);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Get the current Jump List settings.
|
||||
v8::Local<v8::Value> GetJumpListSettings();
|
||||
|
|
|
@ -129,7 +129,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
|||
dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
|
||||
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
|
||||
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
|
||||
#if defined(OS_MACOSX)
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
dict.SetMethod("showCertificateTrustDialog",
|
||||
&certificate_trust::ShowCertificateTrust);
|
||||
#endif
|
||||
|
|
|
@ -873,6 +873,15 @@ void WebContents::Observe(int type,
|
|||
}
|
||||
}
|
||||
|
||||
void WebContents::BeforeUnloadDialogCancelled() {
|
||||
if (deferred_load_url_.id) {
|
||||
auto& controller = web_contents()->GetController();
|
||||
if (!controller.GetPendingEntry()) {
|
||||
deferred_load_url_.id = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::DevToolsReloadPage() {
|
||||
Emit("devtools-reload-page");
|
||||
}
|
||||
|
|
|
@ -340,6 +340,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
void Observe(int type,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) override;
|
||||
void BeforeUnloadDialogCancelled() override;
|
||||
|
||||
// brightray::InspectableWebContentsDelegate:
|
||||
void DevToolsReloadPage() override;
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
<key>CFBundleIconFile</key>
|
||||
<string>electron.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.6.8</string>
|
||||
<string>1.6.9</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.6.8</string>
|
||||
<string>1.6.9</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
|
|
@ -56,8 +56,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,6,8,0
|
||||
PRODUCTVERSION 1,6,8,0
|
||||
FILEVERSION 1,6,9,0
|
||||
PRODUCTVERSION 1,6,9,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -74,12 +74,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "1.6.8"
|
||||
VALUE "FileVersion", "1.6.9"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "1.6.8"
|
||||
VALUE "ProductVersion", "1.6.9"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
|
98
atom/browser/ui/certificate_trust_win.cc
Normal file
98
atom/browser/ui/certificate_trust_win.cc
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/ui/certificate_trust.h"
|
||||
|
||||
#include <wincrypt.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "net/cert/cert_database.h"
|
||||
|
||||
namespace certificate_trust {
|
||||
|
||||
// Add the provided certificate to the Trusted Root Certificate Authorities
|
||||
// store for the current user.
|
||||
//
|
||||
// This requires prompting the user to confirm they trust the certificate.
|
||||
BOOL AddToTrustedRootStore(const PCCERT_CONTEXT cert_context,
|
||||
const scoped_refptr<net::X509Certificate>& cert) {
|
||||
auto root_cert_store = CertOpenStore(
|
||||
CERT_STORE_PROV_SYSTEM,
|
||||
0,
|
||||
NULL,
|
||||
CERT_SYSTEM_STORE_CURRENT_USER,
|
||||
L"Root");
|
||||
|
||||
if (root_cert_store == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result = CertAddCertificateContextToStore(
|
||||
root_cert_store,
|
||||
cert_context,
|
||||
CERT_STORE_ADD_REPLACE_EXISTING,
|
||||
NULL);
|
||||
|
||||
if (result) {
|
||||
// force Chromium to reload it's database for this certificate
|
||||
auto cert_db = net::CertDatabase::GetInstance();
|
||||
cert_db->NotifyObserversCertDBChanged(cert.get());
|
||||
}
|
||||
|
||||
CertCloseStore(root_cert_store, CERT_CLOSE_STORE_FORCE_FLAG);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CERT_CHAIN_PARA GetCertificateChainParameters() {
|
||||
CERT_ENHKEY_USAGE enhkey_usage;
|
||||
enhkey_usage.cUsageIdentifier = 0;
|
||||
enhkey_usage.rgpszUsageIdentifier = NULL;
|
||||
|
||||
CERT_USAGE_MATCH cert_usage;
|
||||
// ensure the rules are applied to the entire chain
|
||||
cert_usage.dwType = USAGE_MATCH_TYPE_AND;
|
||||
cert_usage.Usage = enhkey_usage;
|
||||
|
||||
CERT_CHAIN_PARA params = { sizeof(CERT_CHAIN_PARA) };
|
||||
params.RequestedUsage = cert_usage;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
void ShowCertificateTrust(atom::NativeWindow* parent_window,
|
||||
const scoped_refptr<net::X509Certificate>& cert,
|
||||
const std::string& message,
|
||||
const ShowTrustCallback& callback) {
|
||||
PCCERT_CHAIN_CONTEXT chain_context;
|
||||
|
||||
auto cert_context = cert->CreateOSCertChainForCert();
|
||||
|
||||
auto params = GetCertificateChainParameters();
|
||||
|
||||
if (CertGetCertificateChain(NULL,
|
||||
cert_context,
|
||||
NULL,
|
||||
NULL,
|
||||
¶ms,
|
||||
NULL,
|
||||
NULL,
|
||||
&chain_context)) {
|
||||
auto error_status = chain_context->TrustStatus.dwErrorStatus;
|
||||
if (error_status == CERT_TRUST_IS_SELF_SIGNED ||
|
||||
error_status == CERT_TRUST_IS_UNTRUSTED_ROOT) {
|
||||
// these are the only scenarios we're interested in supporting
|
||||
AddToTrustedRootStore(cert_context, cert);
|
||||
}
|
||||
|
||||
CertFreeCertificateChain(chain_context);
|
||||
}
|
||||
|
||||
CertFreeCertificateContext(cert_context);
|
||||
|
||||
callback.Run();
|
||||
}
|
||||
|
||||
} // namespace certificate_trust
|
|
@ -224,6 +224,7 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
NSString* item_id = [NSString stringWithFormat:@"%ld", ((NSSegmentedControl*)sender).tag];
|
||||
base::DictionaryValue details;
|
||||
details.SetInteger("selectedIndex", ((NSSegmentedControl*)sender).selectedSegment);
|
||||
details.SetBoolean("isSelected", [((NSSegmentedControl*)sender) isSelectedForSegment:((NSSegmentedControl*)sender).selectedSegment]);
|
||||
window_->NotifyTouchBarItemInteraction([item_id UTF8String],
|
||||
details);
|
||||
}
|
||||
|
@ -520,6 +521,15 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
else
|
||||
control.segmentStyle = NSSegmentStyleAutomatic;
|
||||
|
||||
std::string segmentMode;
|
||||
settings.Get("mode", &segmentMode);
|
||||
if (segmentMode == "multiple")
|
||||
control.trackingMode = NSSegmentSwitchTrackingSelectAny;
|
||||
else if (segmentMode == "buttons")
|
||||
control.trackingMode = NSSegmentSwitchTrackingMomentary;
|
||||
else
|
||||
control.trackingMode = NSSegmentSwitchTrackingSelectOne;
|
||||
|
||||
std::vector<mate::Dictionary> segments;
|
||||
settings.Get("segments", &segments);
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/process/process_metrics.h"
|
||||
#include "base/sys_info.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace atom {
|
||||
|
@ -23,51 +23,6 @@ namespace {
|
|||
// Dummy class type that used for crashing the program.
|
||||
struct DummyClass { bool crash; };
|
||||
|
||||
void Hang() {
|
||||
for (;;)
|
||||
base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> GetProcessMemoryInfo(v8::Isolate* isolate) {
|
||||
std::unique_ptr<base::ProcessMetrics> metrics(
|
||||
base::ProcessMetrics::CreateCurrentProcessMetrics());
|
||||
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("workingSetSize",
|
||||
static_cast<double>(metrics->GetWorkingSetSize() >> 10));
|
||||
dict.Set("peakWorkingSetSize",
|
||||
static_cast<double>(metrics->GetPeakWorkingSetSize() >> 10));
|
||||
|
||||
size_t private_bytes, shared_bytes;
|
||||
if (metrics->GetMemoryBytes(&private_bytes, &shared_bytes)) {
|
||||
dict.Set("privateBytes", static_cast<double>(private_bytes >> 10));
|
||||
dict.Set("sharedBytes", static_cast<double>(shared_bytes >> 10));
|
||||
}
|
||||
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> GetSystemMemoryInfo(v8::Isolate* isolate,
|
||||
mate::Arguments* args) {
|
||||
base::SystemMemoryInfoKB mem_info;
|
||||
if (!base::GetSystemMemoryInfo(&mem_info)) {
|
||||
args->ThrowError("Unable to retrieve system memory information");
|
||||
return v8::Undefined(isolate);
|
||||
}
|
||||
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("total", mem_info.total);
|
||||
dict.Set("free", mem_info.free);
|
||||
|
||||
// NB: These return bogus values on macOS
|
||||
#if !defined(OS_MACOSX)
|
||||
dict.Set("swapTotal", mem_info.swap_total);
|
||||
dict.Set("swapFree", mem_info.swap_free);
|
||||
#endif
|
||||
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
||||
// Called when there is a fatal error in V8, we just crash the process here so
|
||||
// we can get the stack trace.
|
||||
void FatalErrorCallback(const char* location, const char* message) {
|
||||
|
@ -81,6 +36,7 @@ void FatalErrorCallback(const char* location, const char* message) {
|
|||
AtomBindings::AtomBindings(uv_loop_t* loop) {
|
||||
uv_async_init(loop, &call_next_tick_async_, OnCallNextTick);
|
||||
call_next_tick_async_.data = this;
|
||||
metrics_ = base::ProcessMetrics::CreateCurrentProcessMetrics();
|
||||
}
|
||||
|
||||
AtomBindings::~AtomBindings() {
|
||||
|
@ -97,6 +53,9 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
|
|||
dict.SetMethod("log", &Log);
|
||||
dict.SetMethod("getProcessMemoryInfo", &GetProcessMemoryInfo);
|
||||
dict.SetMethod("getSystemMemoryInfo", &GetSystemMemoryInfo);
|
||||
dict.SetMethod("getCPUUsage",
|
||||
base::Bind(&AtomBindings::GetCPUUsage, base::Unretained(this)));
|
||||
dict.SetMethod("getIOCounters", &GetIOCounters);
|
||||
#if defined(OS_POSIX)
|
||||
dict.SetMethod("setFdLimit", &base::SetFdLimit);
|
||||
#endif
|
||||
|
@ -168,4 +127,81 @@ void AtomBindings::Crash() {
|
|||
static_cast<DummyClass*>(nullptr)->crash = true;
|
||||
}
|
||||
|
||||
// static
|
||||
void AtomBindings::Hang() {
|
||||
for (;;)
|
||||
base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> AtomBindings::GetProcessMemoryInfo(v8::Isolate* isolate) {
|
||||
std::unique_ptr<base::ProcessMetrics> metrics(
|
||||
base::ProcessMetrics::CreateCurrentProcessMetrics());
|
||||
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("workingSetSize",
|
||||
static_cast<double>(metrics->GetWorkingSetSize() >> 10));
|
||||
dict.Set("peakWorkingSetSize",
|
||||
static_cast<double>(metrics->GetPeakWorkingSetSize() >> 10));
|
||||
|
||||
size_t private_bytes, shared_bytes;
|
||||
if (metrics->GetMemoryBytes(&private_bytes, &shared_bytes)) {
|
||||
dict.Set("privateBytes", static_cast<double>(private_bytes >> 10));
|
||||
dict.Set("sharedBytes", static_cast<double>(shared_bytes >> 10));
|
||||
}
|
||||
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> AtomBindings::GetSystemMemoryInfo(v8::Isolate* isolate,
|
||||
mate::Arguments* args) {
|
||||
base::SystemMemoryInfoKB mem_info;
|
||||
if (!base::GetSystemMemoryInfo(&mem_info)) {
|
||||
args->ThrowError("Unable to retrieve system memory information");
|
||||
return v8::Undefined(isolate);
|
||||
}
|
||||
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("total", mem_info.total);
|
||||
dict.Set("free", mem_info.free);
|
||||
|
||||
// NB: These return bogus values on macOS
|
||||
#if !defined(OS_MACOSX)
|
||||
dict.Set("swapTotal", mem_info.swap_total);
|
||||
dict.Set("swapFree", mem_info.swap_free);
|
||||
#endif
|
||||
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> AtomBindings::GetCPUUsage(v8::Isolate* isolate) {
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
int processor_count = base::SysInfo::NumberOfProcessors();
|
||||
dict.Set("percentCPUUsage",
|
||||
metrics_->GetPlatformIndependentCPUUsage() / processor_count);
|
||||
dict.Set("idleWakeupsPerSecond", metrics_->GetIdleWakeupsPerSecond());
|
||||
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> AtomBindings::GetIOCounters(v8::Isolate* isolate) {
|
||||
std::unique_ptr<base::ProcessMetrics> metrics(
|
||||
base::ProcessMetrics::CreateCurrentProcessMetrics());
|
||||
base::IoCounters io_counters;
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
|
||||
if (metrics->GetIOCounters(&io_counters)) {
|
||||
dict.Set("readOperationCount", io_counters.ReadOperationCount);
|
||||
dict.Set("writeOperationCount", io_counters.WriteOperationCount);
|
||||
dict.Set("otherOperationCount", io_counters.OtherOperationCount);
|
||||
dict.Set("readTransferCount", io_counters.ReadTransferCount);
|
||||
dict.Set("writeTransferCount", io_counters.WriteTransferCount);
|
||||
dict.Set("otherTransferCount", io_counters.OtherTransferCount);
|
||||
}
|
||||
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
#include <list>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/process/process_metrics.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "native_mate/arguments.h"
|
||||
#include "v8/include/v8.h"
|
||||
#include "vendor/node/deps/uv/include/uv.h"
|
||||
|
||||
|
@ -32,6 +34,12 @@ class AtomBindings {
|
|||
|
||||
static void Log(const base::string16& message);
|
||||
static void Crash();
|
||||
static void Hang();
|
||||
static v8::Local<v8::Value> GetProcessMemoryInfo(v8::Isolate* isolate);
|
||||
static v8::Local<v8::Value> GetSystemMemoryInfo(v8::Isolate* isolate,
|
||||
mate::Arguments* args);
|
||||
v8::Local<v8::Value> GetCPUUsage(v8::Isolate* isolate);
|
||||
static v8::Local<v8::Value> GetIOCounters(v8::Isolate* isolate);
|
||||
|
||||
private:
|
||||
void ActivateUVLoop(v8::Isolate* isolate);
|
||||
|
@ -40,6 +48,7 @@ class AtomBindings {
|
|||
|
||||
uv_async_t call_next_tick_async_;
|
||||
std::list<node::Environment*> pending_next_ticks_;
|
||||
std::unique_ptr<base::ProcessMetrics> metrics_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBindings);
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#define ATOM_MAJOR_VERSION 1
|
||||
#define ATOM_MINOR_VERSION 6
|
||||
#define ATOM_PATCH_VERSION 8
|
||||
#define ATOM_PATCH_VERSION 9
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
|
|
@ -86,6 +86,9 @@ void InitializeBindings(v8::Local<v8::Object> binding,
|
|||
mate::Dictionary b(isolate, binding);
|
||||
b.SetMethod("get", GetBinding);
|
||||
b.SetMethod("crash", AtomBindings::Crash);
|
||||
b.SetMethod("hang", AtomBindings::Hang);
|
||||
b.SetMethod("getProcessMemoryInfo", &AtomBindings::GetProcessMemoryInfo);
|
||||
b.SetMethod("getSystemMemoryInfo", &AtomBindings::GetSystemMemoryInfo);
|
||||
}
|
||||
|
||||
class AtomSandboxedRenderViewObserver : public AtomRenderViewObserver {
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
|
||||
:memo: Traducciones disponibles: [Koreano](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Chino Simplificado](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Portugués Brasileño](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Chino Tradicional](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md)
|
||||
|
||||
Electron es un framework que permite escribir aplicaciones de escritorio multiplataforma
|
||||
usando JavaScript, HTML y CSS. Está basado en [Node.js](https://nodejs.org/) con
|
||||
Electron es un framework que permite escribir aplicaciones de escritorio multiplataforma
|
||||
usando JavaScript, HTML y CSS. Está basado en [Node.js](https://nodejs.org/) con
|
||||
[Chromium](http://www.chromium.org). Es usado por [Atom
|
||||
editor](https://github.com/atom/atom) y muchas otras [aplicaciones](https://electron.atom.io/apps).
|
||||
|
||||
Sigue a [@ElectronJS](https://twitter.com/electronjs) en Twitter para estar informado de anuncios
|
||||
Sigue a [@ElectronJS](https://twitter.com/electronjs) en Twitter para estar informado de anuncios
|
||||
importantes.
|
||||
|
||||
Este proyecto se adhiere al [Código de Conducta convenido para Colaboradores](CODE_OF_CONDUCT.md).
|
||||
|
@ -41,7 +41,7 @@ los prebuilt binaries, debug symbols, y más.
|
|||
|
||||
## Documentación
|
||||
|
||||
Las guías y API de referencia están disponibles en el directorio
|
||||
Las guías y API de referencia están disponibles en el directorio
|
||||
[docs](https://github.com/electron/electron/tree/master/docs). Ahí también
|
||||
puedes encontrar documentos que describen cómo construir y contribuir en Electron.
|
||||
|
||||
|
@ -67,14 +67,14 @@ para ver una aplicación mínima en acción.
|
|||
## Comunidad
|
||||
|
||||
Puedes preguntar y interactuar con la comunidad en los siguientes lugares:
|
||||
- [`electron`](http://discuss.atom.io/c/electron) Categoría en los Foros de
|
||||
- [`electron`](http://discuss.atom.io/c/electron) Categoría en los Foros de
|
||||
Atom.
|
||||
- `#atom-shell` canal de IRC en Freenode
|
||||
- [`Atom`](http://atom-slack.herokuapp.com/) canales en Slack
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Portugués Brasileño)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Koreano)*
|
||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japonés)*
|
||||
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turco)*
|
||||
- [`electron-tr`](http://electron-tr.herokuapp.com) *(Turco)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonés*
|
||||
|
||||
Mira [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
|
|
|
@ -73,7 +73,7 @@ npm install electron --save-dev
|
|||
- [`electron-br`](https://electron-br.slack.com) *(브라질)* 커뮤니티
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(한국)* 커뮤니티
|
||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(일본)* 커뮤니티
|
||||
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(터키)* 커뮤니티
|
||||
- [`electron-tr`](http://electron-tr.herokuapp.com) *(터키)* 커뮤니티
|
||||
- [`electron-id`](https://electron-id.slack.com) *(인도네시아)* 커뮤니티
|
||||
|
||||
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에
|
||||
|
|
|
@ -61,7 +61,7 @@ Você pode fazer perguntas e interagir com a comunidade nos seguintes locais:
|
|||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(Japanese)*
|
||||
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turkish)*
|
||||
- [`electron-tr`](http://electron-tr.herokuapp.com) *(Turkish)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
|
||||
Confira [awesome-electron](https://github.com/sindresorhus/awesome-electron) para uma lista mantida pela comunidade de exemplos de aplicativos úteis, ferramentas e recursos.
|
||||
|
|
|
@ -72,7 +72,7 @@ Asağıdaki sayfalardan sorular sorabilir ve topluluk ile etkileşime geçebilir
|
|||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
||||
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turkish)*
|
||||
- [`electron-tr`](http://electron-tr.herokuapp.com) *(Turkish)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
|
||||
Topluluk tarafından sağlanan örnek uygulamaları, aracları ve kaynaklara ulaşmak için
|
||||
|
|
|
@ -73,7 +73,7 @@ ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ npm install electron -g
|
|||
- [`electron-br`](https://electron-br.slack.com) *(葡萄牙语-巴西)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(韩语)*
|
||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(日语)*
|
||||
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(土耳其)*
|
||||
- [`electron-tr`](http://electron-tr.herokuapp.com) *(土耳其)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(印度尼西亚)*
|
||||
|
||||
查看 [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
|
|
|
@ -66,12 +66,12 @@ Clone 並使用 [`electron/electron-quick-start`](https://github.com/electron/el
|
|||
- [`electron-br`](https://electron-br.slack.com) *(葡萄牙語-巴西)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(韓語)*
|
||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(日語)*
|
||||
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(土耳其)*
|
||||
- [`electron-tr`](http://electron-tr.herokuapp.com) *(土耳其)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(印度尼西亞)*
|
||||
|
||||
在 [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
查看由社群維護的清單,包括實用的應用程式、工具以及資源。
|
||||
|
||||
## 憑證
|
||||
## 授權條款
|
||||
|
||||
MIT © 2016 Github
|
||||
|
|
|
@ -40,6 +40,7 @@ an issue:
|
|||
* [Desktop Environment Integration](tutorial/desktop-environment-integration.md)
|
||||
* [Online/Offline Event Detection](tutorial/online-offline-events.md)
|
||||
* [REPL](tutorial/repl.md)
|
||||
* [Native Notifications](tutorial/notifications.md)
|
||||
|
||||
## API References
|
||||
|
||||
|
|
|
@ -760,6 +760,10 @@ Disables hardware acceleration for current app.
|
|||
|
||||
This method can only be called before app is ready.
|
||||
|
||||
### `app.getAppMemoryInfo()`
|
||||
|
||||
Returns [ProcessMemoryInfo[]](structures/process-memory-info.md): Array of `ProcessMemoryInfo` objects that correspond to memory usage statistics of all the processes associated with the app.
|
||||
|
||||
### `app.setBadgeCount(count)` _Linux_ _macOS_
|
||||
|
||||
* `count` Integer
|
||||
|
|
|
@ -176,7 +176,7 @@ it is usually used to report errors in early stage of startup. If called
|
|||
before the app `ready`event on Linux, the message will be emitted to stderr,
|
||||
and no GUI dialog will appear.
|
||||
|
||||
### `dialog.showCertificateTrustDialog([browserWindow, ]options, callback)` _macOS_
|
||||
### `dialog.showCertificateTrustDialog([browserWindow, ]options, callback)` _macOS_ _Windows_
|
||||
|
||||
* `browserWindow` BrowserWindow (optional)
|
||||
* `options` Object
|
||||
|
@ -184,11 +184,17 @@ and no GUI dialog will appear.
|
|||
* `message` String - The message to display to the user.
|
||||
* `callback` Function
|
||||
|
||||
Displays a modal dialog that shows a message and certificate information, and
|
||||
gives the user the option of trusting/importing the certificate.
|
||||
On macOS, this displays a modal dialog that shows a message and certificate
|
||||
information, and gives the user the option of trusting/importing the
|
||||
certificate. If you provide a `browserWindow` argument the dialog will be
|
||||
attached to the parent window, making it modal.
|
||||
|
||||
The `browserWindow` argument allows the dialog to attach itself to a parent
|
||||
window, making it modal.
|
||||
On Windows the options are more limited, due to the Win32 APIs used:
|
||||
|
||||
- The `message` argument is not used, as the OS provides its own confirmation
|
||||
dialog.
|
||||
- The `browserWindow` argument is ignored since it is not possible to make
|
||||
this confirmation dialog modal.
|
||||
|
||||
## Sheets
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ It is also possible to send messages from the main process to the renderer
|
|||
process, see [webContents.send][web-contents-send] for more information.
|
||||
|
||||
* When sending a message, the event name is the `channel`.
|
||||
* To reply a synchronous message, you need to set `event.returnValue`.
|
||||
* To send an asynchronous back to the sender, you can use
|
||||
* To reply to a synchronous message, you need to set `event.returnValue`.
|
||||
* To send an asynchronous message back to the sender, you can use
|
||||
`event.sender.send(...)`.
|
||||
|
||||
An example of sending and handling messages between the render and main
|
||||
|
|
|
@ -8,132 +8,135 @@ values are listed below:
|
|||
| Language Code | Language Name |
|
||||
|---------------|---------------|
|
||||
| af | Afrikaans |
|
||||
| an | Aragonese |
|
||||
| ar-AE | Arabic (U.A.E.) |
|
||||
| ar-IQ | Arabic (Iraq) |
|
||||
| ar | Arabic (Standard) |
|
||||
| ar-BH | Arabic (Bahrain) |
|
||||
| ar-DZ | Arabic (Algeria) |
|
||||
| ar-EG | Arabic (Egypt) |
|
||||
| ar-JO | Arabic (Jordan) |
|
||||
| ar-KW | Arabic (Kuwait) |
|
||||
| ar-LB | Arabic (Lebanon) |
|
||||
| ar-LY | Arabic (Libya) |
|
||||
| ar-MA | Arabic (Morocco) |
|
||||
| ar-OM | Arabic (Oman) |
|
||||
| ar-QA | Arabic (Qatar) |
|
||||
| ar-SA | Arabic (Saudi Arabia) |
|
||||
| ar-SY | Arabic (Syria) |
|
||||
| ar-TN | Arabic (Tunisia) |
|
||||
| ar-YE | Arabic (Yemen) |
|
||||
| as | Assamese |
|
||||
| ast | Asturian |
|
||||
| am | Amharic |
|
||||
| ar | Arabic |
|
||||
| az | Azerbaijani |
|
||||
| be | Belarusian |
|
||||
| bg | Bulgarian |
|
||||
| bg | Bulgarian |
|
||||
| bh | Bihari |
|
||||
| bn | Bengali |
|
||||
| br | Breton |
|
||||
| bs | Bosnian |
|
||||
| ca | Catalan |
|
||||
| ce | Chechen |
|
||||
| ch | Chamorro |
|
||||
| co | Corsican |
|
||||
| cr | Cree |
|
||||
| cs | Czech |
|
||||
| cv | Chuvash |
|
||||
| cy | Welsh |
|
||||
| da | Danish |
|
||||
| de | German (Standard) |
|
||||
| de | German |
|
||||
| de-AT | German (Austria) |
|
||||
| de-CH | German (Switzerland) |
|
||||
| de-DE | German (Germany) |
|
||||
| de-LI | German (Liechtenstein) |
|
||||
| de-LU | German (Luxembourg) |
|
||||
| el | Greek |
|
||||
| en-AU | English (Australia) |
|
||||
| en-BZ | English (Belize) |
|
||||
| en | English |
|
||||
| en-AU | English (Australia) |
|
||||
| en-CA | English (Canada) |
|
||||
| en-GB | English (United Kingdom) |
|
||||
| en-IE | English (Ireland) |
|
||||
| en-JM | English (Jamaica) |
|
||||
| en-GB | English (UK) |
|
||||
| en-NZ | English (New Zealand) |
|
||||
| en-PH | English (Philippines) |
|
||||
| en-TT | English (Trinidad & Tobago) |
|
||||
| en-US | English (United States) |
|
||||
| en-US | English (US) |
|
||||
| en-ZA | English (South Africa) |
|
||||
| en-ZW | English (Zimbabwe) |
|
||||
| eo | Esperanto |
|
||||
| es | Spanish |
|
||||
| es-419 | Spanish (Latin America) |
|
||||
| et | Estonian |
|
||||
| eu | Basque |
|
||||
| fa | Persian |
|
||||
| fa | Farsi |
|
||||
| fa-IR | Persian/Iran |
|
||||
| fi | Finnish |
|
||||
| fj | Fijian |
|
||||
| fo | Faeroese |
|
||||
| fil | Filipino |
|
||||
| fo | Faroese |
|
||||
| fr | French |
|
||||
| fr-CA | French (Canada) |
|
||||
| fr-CH | French (Switzerland) |
|
||||
| fr-FR | French (France) |
|
||||
| fr-LU | French (Luxembourg) |
|
||||
| fr-MC | French (Monaco) |
|
||||
| fr | French (Standard) |
|
||||
| fr-BE | French (Belgium) |
|
||||
| fr-CA | French (Canada) |
|
||||
| fur | Friulian |
|
||||
| fy | Frisian |
|
||||
| ga | Irish |
|
||||
| gd-IE | Gaelic (Irish) |
|
||||
| gd | Gaelic (Scots) |
|
||||
| gl | Galacian |
|
||||
| gu | Gujurati |
|
||||
| gd | Scots Gaelic |
|
||||
| gl | Galician |
|
||||
| gn | Guarani |
|
||||
| gu | Gujarati |
|
||||
| ha | Hausa |
|
||||
| haw | Hawaiian |
|
||||
| he | Hebrew |
|
||||
| hi | Hindi |
|
||||
| hr | Croatian |
|
||||
| ht | Haitian |
|
||||
| hu | Hungarian |
|
||||
| hy | Armenian |
|
||||
| ia | Interlingua |
|
||||
| id | Indonesian |
|
||||
| is | Icelandic |
|
||||
| it | Italian |
|
||||
| it-CH | Italian (Switzerland) |
|
||||
| it | Italian (Standard) |
|
||||
| iu | Inuktitut |
|
||||
| it-IT | Italian (Italy) |
|
||||
| ja | Japanese |
|
||||
| jw | Javanese |
|
||||
| ka | Georgian |
|
||||
| kk | Kazakh |
|
||||
| km | Khmer |
|
||||
| km | Cambodian |
|
||||
| kn | Kannada |
|
||||
| ko | Korean |
|
||||
| ko-KP | Korean (North Korea) |
|
||||
| ko-KR | Korean (South Korea) |
|
||||
| ks | Kashmiri |
|
||||
| ky | Kirghiz |
|
||||
| ku | Kurdish |
|
||||
| ky | Kyrgyz |
|
||||
| la | Latin |
|
||||
| lb | Luxembourgish |
|
||||
| ln | Lingala |
|
||||
| lo | Laothian |
|
||||
| lt | Lithuanian |
|
||||
| lv | Latvian |
|
||||
| mi | Maori |
|
||||
| mk | FYRO Macedonian |
|
||||
| mk | Macedonian |
|
||||
| ml | Malayalam |
|
||||
| mn | Mongolian |
|
||||
| mo | Moldavian |
|
||||
| mr | Marathi |
|
||||
| ms | Malay |
|
||||
| mt | Maltese |
|
||||
| my | Burmese |
|
||||
| nb | Norwegian (Bokmal) |
|
||||
| ne | Nepali |
|
||||
| ng | Ndonga |
|
||||
| nl | Dutch (Standard) |
|
||||
| nl-BE | Dutch (Belgian) |
|
||||
| nl | Dutch |
|
||||
| nn | Norwegian (Nynorsk) |
|
||||
| no | Norwegian |
|
||||
| nv | Navajo |
|
||||
| oc | Occitan |
|
||||
| om | Oromo |
|
||||
| or | Oriya |
|
||||
| pa | Punjabi |
|
||||
| pl | Polish |
|
||||
| ps | Pashto |
|
||||
| pt | Portuguese |
|
||||
| pt-BR | Portuguese (Brazil) |
|
||||
| pt-PT | Portuguese (Portugal) |
|
||||
| qu | Quechua |
|
||||
| rm | Romansh |
|
||||
| ro | Romanian |
|
||||
| ru | Russian |
|
||||
| sd | Sindhi |
|
||||
| sh | Serbo-Croatian |
|
||||
| si | Sinhalese |
|
||||
| sk | Slovak |
|
||||
| sl | Slovenian |
|
||||
| sn | Shona |
|
||||
| so | Somali |
|
||||
| sq | Albanian |
|
||||
| tlh | Klingon |
|
||||
| zh-TW | Chinese (Taiwan) |
|
||||
| sr | Serbian |
|
||||
| st | Sesotho |
|
||||
| su | Sundanese |
|
||||
| sv | Swedish |
|
||||
| sw | Swahili |
|
||||
| ta | Tamil |
|
||||
| te | Telugu |
|
||||
| tg | Tajik |
|
||||
| th | Thai |
|
||||
| ti | Tigrinya |
|
||||
| tk | Turkmen |
|
||||
| to | Tonga |
|
||||
| tr | Turkish |
|
||||
| tt | Tatar |
|
||||
| tw | Twi |
|
||||
| ug | Uighur |
|
||||
| uk | Ukrainian |
|
||||
| ur | Urdu |
|
||||
| uz | Uzbek |
|
||||
| vi | Vietnamese |
|
||||
| xh | Xhosa |
|
||||
| yi | Yiddish |
|
||||
| yo | Yoruba |
|
||||
| zh | Chinese |
|
||||
| zh-CN | Chinese (PRC) |
|
||||
| zh-HK | Chinese (Hong Kong) |
|
||||
| zh-SG | Chinese (Singapore) |
|
||||
| zh-CN | Chinese (Simplified) |
|
||||
| zh-TW | Chinese (Traditional) |
|
||||
| zu | Zulu |
|
||||
|
|
|
@ -116,3 +116,15 @@ Returns `Object`:
|
|||
|
||||
Returns an object giving memory usage statistics about the entire system. Note
|
||||
that all statistics are reported in Kilobytes.
|
||||
|
||||
### `process.getCPUUsage()`
|
||||
|
||||
Returns:
|
||||
|
||||
* `CPUUsage` [CPUUsage](structures/cpu-usage.md)
|
||||
|
||||
### `process.getIOCounters()` _Windows_ _Linux_
|
||||
|
||||
Returns:
|
||||
|
||||
* `IOCounters` [IOCounters](structures/io-counters.md)
|
6
docs/api/structures/cpu-usage.md
Normal file
6
docs/api/structures/cpu-usage.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# CPUUsage Object
|
||||
|
||||
* `percentCPUUsage` Number - Percentage of CPU used since the last call to getCPUUsage.
|
||||
First call returns 0.
|
||||
* `idleWakeupsPerSecond` Number - The number of average idle cpu wakeups per second
|
||||
since the last call to getCPUUsage. First call returns 0.
|
8
docs/api/structures/io-counters.md
Normal file
8
docs/api/structures/io-counters.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# IOCounters Object
|
||||
|
||||
* `readOperationCount` Number - The number of I/O read operations.
|
||||
* `writeOperationCount` Number - The number of I/O write operations.
|
||||
* `otherOperationCount` Number - Then number of I/O other operations.
|
||||
* `readTransferCount` Number - The number of I/O read transfers.
|
||||
* `writeTransferCount` Number - The number of I/O write transfers.
|
||||
* `otherTransferCount` Number - Then number of I/O other transfers.
|
12
docs/api/structures/memory-info.md
Normal file
12
docs/api/structures/memory-info.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
# MemoryInfo Object
|
||||
|
||||
* `workingSetSize` Integer - Process id of the process.
|
||||
* `workingSetSize` Integer - The amount of memory currently pinned to actual physical RAM.
|
||||
* `peakWorkingSetSize` Integer - The maximum amount of memory that has ever been pinned
|
||||
to actual physical RAM.
|
||||
* `privateBytes` Integer - The amount of memory not shared by other processes, such as
|
||||
JS heap or HTML content.
|
||||
* `sharedBytes` Integer - The amount of memory shared between processes, typically
|
||||
memory consumed by the Electron code itself
|
||||
|
||||
Note that all statistics are reported in Kilobytes.
|
4
docs/api/structures/process-memory-info.md
Normal file
4
docs/api/structures/process-memory-info.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# ProcessMemoryInfo Object
|
||||
|
||||
* `pid` Integer - Process id of the process.
|
||||
* `memory` [MemoryInfo](memory-info.md) - Memory information of the process.
|
|
@ -21,10 +21,15 @@ Process: [Main](../tutorial/quick-start.md#main-process)
|
|||
* `small-square` - The control is displayed using the small square style.
|
||||
* `separated` - The segments in the control are displayed very close to each
|
||||
other but not touching.
|
||||
* `segments` [SegmentedControlSegment[]](structures/segmented-control-segment.md) - An array of segments to place in this control
|
||||
* `selectedIndex` Integer (Optional) - The index of the currently selected segment, will update automatically with user interaction
|
||||
* `mode` String - (Optional) The selection mode of the control:
|
||||
* `single` - Default. One item selected at a time, selecting one deselects the previously selected item.
|
||||
* `multiple` - Multiple items can be selected at a time.
|
||||
* `buttons` - Make the segments act as buttons, each segment can be pressed and released but never marked as active.
|
||||
* `segments` [SegmentedControlSegment[]](structures/segmented-control-segment.md) - An array of segments to place in this control.
|
||||
* `selectedIndex` Integer (Optional) - The index of the currently selected segment, will update automatically with user interaction. When the mode is multiple it will be the last selected item.
|
||||
* `change` Function - Called when the user selects a new segment
|
||||
* `selectedIndex` Integer - The index of the segment the user selected
|
||||
* `selectedIndex` Integer - The index of the segment the user selected.
|
||||
* `isSelected` Boolean - Whether as a result of user selection the segment is selected or not.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ available in "core".
|
|||
### V8
|
||||
|
||||
V8 is Google's open source JavaScript engine. It is written in C++ and is
|
||||
used in Google Chrome, the open source browser from Google. V8 can run
|
||||
used in Google Chrome. V8 can run
|
||||
standalone, or can be embedded into any C++ application.
|
||||
|
||||
### webview
|
||||
|
|
|
@ -8,55 +8,9 @@ applications can put a custom menu in the dock menu.
|
|||
This guide explains how to integrate your application into those desktop
|
||||
environments with Electron APIs.
|
||||
|
||||
## Notifications (Windows, Linux, macOS)
|
||||
## Notifications
|
||||
|
||||
All three operating systems provide means for applications to send notifications
|
||||
to the user. Electron conveniently allows developers to send notifications with
|
||||
the [HTML5 Notification API](https://notifications.spec.whatwg.org/), using
|
||||
the currently running operating system's native notification APIs to display it.
|
||||
|
||||
**Note:** Since this is an HTML5 API it is only available in the renderer process.
|
||||
|
||||
```javascript
|
||||
let myNotification = new Notification('Title', {
|
||||
body: 'Lorem Ipsum Dolor Sit Amet'
|
||||
})
|
||||
|
||||
myNotification.onclick = () => {
|
||||
console.log('Notification clicked')
|
||||
}
|
||||
```
|
||||
|
||||
While code and user experience across operating systems are similar, there
|
||||
are fine differences.
|
||||
|
||||
### Windows
|
||||
|
||||
* On Windows 10, notifications "just work".
|
||||
* On Windows 8.1 and Windows 8, a shortcut to your app, with a [Application User
|
||||
Model ID][app-user-model-id], must be installed to the Start screen. Note,
|
||||
however, that it does not need to be pinned to the Start screen.
|
||||
* On Windows 7, notifications work via a custom implemetation which visually
|
||||
resembles the native one on newer systems.
|
||||
|
||||
Furthermore, the maximum length for the notification body is 250 characters,
|
||||
with the Windows team recommending that notifications should be kept to 200
|
||||
characters.
|
||||
|
||||
### Linux
|
||||
|
||||
Notifications are sent using `libnotify`, it can show notifications on any
|
||||
desktop environment that follows [Desktop Notifications
|
||||
Specification][notification-spec], including Cinnamon, Enlightenment, Unity,
|
||||
GNOME, KDE.
|
||||
|
||||
### macOS
|
||||
|
||||
Notifications are straight-forward on macOS, you should however be aware of
|
||||
[Apple's Human Interface guidelines regarding notifications](https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/NotificationCenter.html).
|
||||
|
||||
Note that notifications are limited to 256 bytes in size - and will be truncated
|
||||
if you exceed that limit.
|
||||
See [Notifications](notifications.md)
|
||||
|
||||
## Recent documents (Windows & macOS)
|
||||
|
||||
|
|
85
docs/tutorial/notifications.md
Normal file
85
docs/tutorial/notifications.md
Normal file
|
@ -0,0 +1,85 @@
|
|||
# Notifications (Windows, Linux, macOS)
|
||||
|
||||
All three operating systems provide means for applications to send notifications
|
||||
to the user. Electron conveniently allows developers to send notifications with
|
||||
the [HTML5 Notification API](https://notifications.spec.whatwg.org/), using
|
||||
the currently running operating system's native notification APIs to display it.
|
||||
|
||||
**Note:** Since this is an HTML5 API it is only available in the renderer process.
|
||||
|
||||
```javascript
|
||||
let myNotification = new Notification('Title', {
|
||||
body: 'Lorem Ipsum Dolor Sit Amet'
|
||||
})
|
||||
|
||||
myNotification.onclick = () => {
|
||||
console.log('Notification clicked')
|
||||
}
|
||||
```
|
||||
|
||||
While code and user experience across operating systems are similar, there
|
||||
are subtle differences.
|
||||
|
||||
## Windows
|
||||
|
||||
* On Windows 10, notifications "just work".
|
||||
* On Windows 8.1 and Windows 8, a shortcut to your app, with an [Application User
|
||||
Model ID][app-user-model-id], must be installed to the Start screen. Note,
|
||||
however, that it does not need to be pinned to the Start screen.
|
||||
* On Windows 7, notifications work via a custom implementation which visually
|
||||
resembles the native one on newer systems.
|
||||
|
||||
Furthermore, in Windows 8, the maximum length for the notification body is 250
|
||||
characters, with the Windows team recommending that notifications should be kept
|
||||
to 200 characters. That said, that limitation has been removed in Windows 10, with
|
||||
the Windows team asking developers to be reasonable. Attempting to send gigantic
|
||||
amounts of text to the API (thousands of characters) might result in instability.
|
||||
|
||||
### Advanced Notifications
|
||||
|
||||
Later versions of Windows allow for advanced notifications, with custom templates,
|
||||
images, and other flexible elements. To send those notifications (from either the
|
||||
main process or the renderer process), use the userland module
|
||||
[electron-windows-notifications](https://github.com/felixrieseberg/electron-windows-notifications),
|
||||
which uses native Node addons to send `ToastNotification` and `TileNotification` objects.
|
||||
|
||||
While notifications including buttons work with just `electron-windows-notifications`,
|
||||
handling replies requires the use of [`electron-windows-interactive-notifications`](https://github.com/felixrieseberg/electron-windows-interactive-notifications), which
|
||||
helps with registering the required COM components and calling your Electron app with
|
||||
the entered user data.
|
||||
|
||||
### Quiet Hours / Presentation Mode
|
||||
|
||||
To detect whether or not you're allowed to send a notification, use the userland module
|
||||
[electron-notification-state](https://github.com/felixrieseberg/electron-notification-state).
|
||||
|
||||
This allows you to determine ahead of time whether or not Windows will silently throw
|
||||
the notification away.
|
||||
|
||||
## macOS
|
||||
|
||||
Notifications are straight-forward on macOS, but you should be aware of
|
||||
[Apple's Human Interface guidelines regarding notifications](https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/NotificationCenter.html).
|
||||
|
||||
Note that notifications are limited to 256 bytes in size and will be truncated
|
||||
if you exceed that limit.
|
||||
|
||||
### Advanced Notifications
|
||||
|
||||
Later versions of macOS allow for notifications with an input field, allowing the user
|
||||
to quickly reply to a notification. In order to send notifications with an input field,
|
||||
use the userland module [node-mac-notifier](https://github.com/CharlieHess/node-mac-notifier).
|
||||
|
||||
### Do not disturb / Session State
|
||||
|
||||
To detect whether or not you're allowed to send a notification, use the userland module
|
||||
[electron-notification-state](https://github.com/felixrieseberg/electron-notification-state).
|
||||
|
||||
This will allow you to detect ahead of time whether or not the notification will be displayed.
|
||||
|
||||
## Linux
|
||||
|
||||
Notifications are sent using `libnotify` which can show notifications on any
|
||||
desktop environment that follows [Desktop Notifications
|
||||
Specification][notification-spec], including Cinnamon, Enlightenment, Unity,
|
||||
GNOME, KDE.
|
|
@ -192,10 +192,10 @@ $ .\node_modules\.bin\electron .
|
|||
If you downloaded Electron manually, you can also use the included
|
||||
binary to execute your app directly.
|
||||
|
||||
#### Windows
|
||||
#### macOS
|
||||
|
||||
```bash
|
||||
$ .\electron\electron.exe your-app\
|
||||
$ ./Electron.app/Contents/MacOS/Electron your-app/
|
||||
```
|
||||
|
||||
#### Linux
|
||||
|
@ -204,10 +204,10 @@ $ .\electron\electron.exe your-app\
|
|||
$ ./electron/electron your-app/
|
||||
```
|
||||
|
||||
#### macOS
|
||||
#### Windows
|
||||
|
||||
```bash
|
||||
$ ./Electron.app/Contents/MacOS/Electron your-app/
|
||||
$ .\electron\electron.exe your-app\
|
||||
```
|
||||
|
||||
`Electron.app` here is part of the Electron's release package, you can download
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '1.6.8',
|
||||
'version%': '1.6.9',
|
||||
'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c',
|
||||
},
|
||||
'includes': [
|
||||
|
|
|
@ -291,6 +291,7 @@
|
|||
'atom/browser/ui/atom_menu_model.h',
|
||||
'atom/browser/ui/certificate_trust.h',
|
||||
'atom/browser/ui/certificate_trust_mac.mm',
|
||||
'atom/browser/ui/certificate_trust_win.cc',
|
||||
'atom/browser/ui/cocoa/atom_menu_controller.h',
|
||||
'atom/browser/ui/cocoa/atom_menu_controller.mm',
|
||||
'atom/browser/ui/cocoa/atom_touch_bar.h',
|
||||
|
|
|
@ -264,16 +264,17 @@ TouchBar.TouchBarSegmentedControl = class TouchBarSegmentedControl extends Touch
|
|||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
const {segmentStyle, segments, selectedIndex, change} = config
|
||||
const {segmentStyle, segments, selectedIndex, change, mode} = config
|
||||
this.type = 'segmented_control'
|
||||
this._addLiveProperty('segmentStyle', segmentStyle)
|
||||
this._addLiveProperty('segments', segments || [])
|
||||
this._addLiveProperty('selectedIndex', selectedIndex)
|
||||
this._addLiveProperty('mode', mode)
|
||||
|
||||
if (typeof change === 'function') {
|
||||
this.onInteraction = (details) => {
|
||||
this._selectedIndex = details.selectedIndex
|
||||
change(details.selectedIndex)
|
||||
change(details.selectedIndex, details.isSelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ const preloadSrc = fs.readFileSync(preloadPath).toString()
|
|||
// access to things like `process.atomBinding`).
|
||||
const preloadProcess = new events.EventEmitter()
|
||||
preloadProcess.crash = () => binding.crash()
|
||||
preloadProcess.hang = () => binding.hang()
|
||||
preloadProcess.getProcessMemoryInfo = () => binding.getProcessMemoryInfo()
|
||||
preloadProcess.getSystemMemoryInfo = () => binding.getSystemMemoryInfo()
|
||||
process.platform = preloadProcess.platform = electron.remote.process.platform
|
||||
process.execPath = preloadProcess.execPath = electron.remote.process.execPath
|
||||
process.on('exit', () => preloadProcess.emit('exit'))
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"name": "electron",
|
||||
"version": "1.6.8",
|
||||
"version": "1.6.9",
|
||||
"devDependencies": {
|
||||
"asar": "^0.11.0",
|
||||
"browserify": "^13.1.0",
|
||||
"electabul": "~0.0.4",
|
||||
"electron-docs-linter": "^2.1.0",
|
||||
"electron-typescript-definitions": "^1.2.0",
|
||||
"request": "*",
|
||||
"standard": "^8.4.0",
|
||||
"standard-markdown": "^2.1.1"
|
||||
|
|
|
@ -81,6 +81,7 @@ def main():
|
|||
sys.stderr.write('\nRunning `npm run lint`\n')
|
||||
sys.stderr.flush()
|
||||
execute([npm, 'run', 'lint'])
|
||||
|
||||
if is_release:
|
||||
run_script('build.py', ['-c', 'R'])
|
||||
run_script('create-dist.py')
|
||||
|
|
|
@ -91,6 +91,7 @@ def main():
|
|||
|
||||
if PLATFORM != 'win32' and not args.no_api_docs:
|
||||
create_api_json_schema()
|
||||
create_typescript_definitions()
|
||||
|
||||
if PLATFORM == 'linux':
|
||||
strip_binaries()
|
||||
|
@ -143,6 +144,15 @@ def create_api_json_schema():
|
|||
'--version={}'.format(ELECTRON_VERSION.replace('v', ''))],
|
||||
env=env)
|
||||
|
||||
def create_typescript_definitions():
|
||||
node_bin_dir = os.path.join(SOURCE_ROOT, 'node_modules', '.bin')
|
||||
env = os.environ.copy()
|
||||
env['PATH'] = os.path.pathsep.join([node_bin_dir, env['PATH']])
|
||||
infile = os.path.relpath(os.path.join(DIST_DIR, 'electron-api.json'))
|
||||
outfile = os.path.relpath(os.path.join(DIST_DIR, 'electron.d.ts'))
|
||||
execute(['electron-typescript-definitions', '--in={0}'.format(infile),
|
||||
'--out={0}'.format(outfile)], env=env)
|
||||
|
||||
def strip_binaries():
|
||||
for binary in TARGET_BINARIES[PLATFORM]:
|
||||
if binary.endswith('.so') or '.' not in binary:
|
||||
|
|
|
@ -81,6 +81,7 @@ def main():
|
|||
if PLATFORM == 'darwin':
|
||||
upload_electron(github, release, os.path.join(DIST_DIR,
|
||||
'electron-api.json'))
|
||||
upload_electron(github, release, os.path.join(DIST_DIR, 'electron.d.ts'))
|
||||
upload_electron(github, release, os.path.join(DIST_DIR, DSYM_NAME))
|
||||
elif PLATFORM == 'win32':
|
||||
upload_electron(github, release, os.path.join(DIST_DIR, PDB_NAME))
|
||||
|
|
|
@ -533,4 +533,17 @@ describe('app module', function () {
|
|||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getAppMemoryInfo() API', function () {
|
||||
it('returns the process memory of all running electron processes', function () {
|
||||
const appMemoryInfo = app.getAppMemoryInfo()
|
||||
assert.ok(appMemoryInfo.length > 0, 'App memory info object is not > 0')
|
||||
for (const {memory, pid} of appMemoryInfo) {
|
||||
assert.ok(memory.workingSetSize > 0, 'working set size is not > 0')
|
||||
assert.ok(memory.privateBytes > 0, 'private bytes is not > 0')
|
||||
assert.ok(memory.sharedBytes > 0, 'shared bytes is not > 0')
|
||||
assert.ok(pid > 0, 'pid is not > 0')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1150,6 +1150,29 @@ describe('BrowserWindow module', function () {
|
|||
})
|
||||
w.loadURL('file://' + path.join(fixtures, 'pages', 'window-open.html'))
|
||||
})
|
||||
|
||||
it('releases memory after popup is closed', (done) => {
|
||||
w.destroy()
|
||||
w = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
preload: preload,
|
||||
sandbox: true
|
||||
}
|
||||
})
|
||||
w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?allocate-memory'))
|
||||
w.webContents.openDevTools({mode: 'detach'})
|
||||
ipcMain.once('answer', function (event, {bytesBeforeOpen, bytesAfterOpen, bytesAfterClose}) {
|
||||
const memoryIncreaseByOpen = bytesAfterOpen - bytesBeforeOpen
|
||||
const memoryDecreaseByClose = bytesAfterOpen - bytesAfterClose
|
||||
// decreased memory should be less than increased due to factors we
|
||||
// can't control, but given the amount of memory allocated in the
|
||||
// fixture, we can reasonably expect decrease to be at least 70% of
|
||||
// increase
|
||||
assert(memoryDecreaseByClose > memoryIncreaseByOpen * 0.7)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1174,6 +1197,60 @@ describe('BrowserWindow module', function () {
|
|||
})
|
||||
w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-empty-string.html'))
|
||||
})
|
||||
|
||||
it('emits for each close attempt', function (done) {
|
||||
var beforeUnloadCount = 0
|
||||
w.on('onbeforeunload', function () {
|
||||
beforeUnloadCount++
|
||||
if (beforeUnloadCount < 3) {
|
||||
w.close()
|
||||
} else if (beforeUnloadCount === 3) {
|
||||
done()
|
||||
}
|
||||
})
|
||||
w.webContents.once('did-finish-load', function () {
|
||||
w.close()
|
||||
})
|
||||
w.loadURL('file://' + path.join(fixtures, 'api', 'beforeunload-false-prevent3.html'))
|
||||
})
|
||||
|
||||
it('emits for each reload attempt', function (done) {
|
||||
var beforeUnloadCount = 0
|
||||
w.on('onbeforeunload', function () {
|
||||
beforeUnloadCount++
|
||||
if (beforeUnloadCount < 3) {
|
||||
w.reload()
|
||||
} else if (beforeUnloadCount === 3) {
|
||||
done()
|
||||
}
|
||||
})
|
||||
w.webContents.once('did-finish-load', function () {
|
||||
w.webContents.once('did-finish-load', function () {
|
||||
assert.fail('Reload was not prevented')
|
||||
})
|
||||
w.reload()
|
||||
})
|
||||
w.loadURL('file://' + path.join(fixtures, 'api', 'beforeunload-false-prevent3.html'))
|
||||
})
|
||||
|
||||
it('emits for each navigation attempt', function (done) {
|
||||
var beforeUnloadCount = 0
|
||||
w.on('onbeforeunload', function () {
|
||||
beforeUnloadCount++
|
||||
if (beforeUnloadCount < 3) {
|
||||
w.loadURL('about:blank')
|
||||
} else if (beforeUnloadCount === 3) {
|
||||
done()
|
||||
}
|
||||
})
|
||||
w.webContents.once('did-finish-load', function () {
|
||||
w.webContents.once('did-finish-load', function () {
|
||||
assert.fail('Navigation was not prevented')
|
||||
})
|
||||
w.loadURL('about:blank')
|
||||
})
|
||||
w.loadURL('file://' + path.join(fixtures, 'api', 'beforeunload-false-prevent3.html'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('new-window event', function () {
|
||||
|
|
26
spec/api-process-spec.js
Normal file
26
spec/api-process-spec.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
const assert = require('assert')
|
||||
|
||||
describe('process module', function () {
|
||||
describe('process.getCPUUsage()', function () {
|
||||
it('returns a cpu usage object', function () {
|
||||
const cpuUsage = process.getCPUUsage()
|
||||
assert.equal(typeof cpuUsage.percentCPUUsage, 'number')
|
||||
assert.equal(typeof cpuUsage.idleWakeupsPerSecond, 'number')
|
||||
})
|
||||
})
|
||||
|
||||
describe('process.getIOCounters()', function () {
|
||||
it('returns an io counters object', function () {
|
||||
if (process.platform === 'darwin') {
|
||||
return
|
||||
}
|
||||
const ioCounters = process.getIOCounters()
|
||||
assert.equal(typeof ioCounters.readOperationCount, 'number')
|
||||
assert.equal(typeof ioCounters.writeOperationCount, 'number')
|
||||
assert.equal(typeof ioCounters.otherOperationCount, 'number')
|
||||
assert.equal(typeof ioCounters.readTransferCount, 'number')
|
||||
assert.equal(typeof ioCounters.writeTransferCount, 'number')
|
||||
assert.equal(typeof ioCounters.otherTransferCount, 'number')
|
||||
})
|
||||
})
|
||||
})
|
11
spec/fixtures/api/allocate-memory.html
vendored
Normal file
11
spec/fixtures/api/allocate-memory.html
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.bigBuffer = new Uint8Array(1024 * 1024 * 64)
|
||||
window.bigBuffer.fill(5, 50, 1024 * 1024)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
17
spec/fixtures/api/beforeunload-false-prevent3.html
vendored
Normal file
17
spec/fixtures/api/beforeunload-false-prevent3.html
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
<html>
|
||||
<body>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
// Only prevent unload on the first three window closes
|
||||
var unloadPreventedCount = 0;
|
||||
window.onbeforeunload = function() {
|
||||
setTimeout(function() {
|
||||
require('electron').remote.getCurrentWindow().emit('onbeforeunload');
|
||||
}, 0);
|
||||
if (unloadPreventedCount < 3) {
|
||||
unloadPreventedCount++;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
27
spec/fixtures/api/sandbox.html
vendored
27
spec/fixtures/api/sandbox.html
vendored
|
@ -1,5 +1,18 @@
|
|||
<html>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
function timeout(ms) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms)
|
||||
})
|
||||
}
|
||||
async function invokeGc () {
|
||||
// it seems calling window.gc once does not guarantee garbage will be
|
||||
// collected, so we repeat 10 times with interval of 100 ms
|
||||
for (let i = 0; i < 10; i++) {
|
||||
window.gc()
|
||||
await timeout(100)
|
||||
}
|
||||
}
|
||||
if (window.opener) {
|
||||
window.callback = () => {
|
||||
opener.require('electron').ipcRenderer.send('answer', document.body.innerHTML)
|
||||
|
@ -7,6 +20,20 @@
|
|||
} else {
|
||||
const {ipcRenderer} = require('electron')
|
||||
const tests = {
|
||||
'allocate-memory': async () => {
|
||||
await invokeGc()
|
||||
const {privateBytes: bytesBeforeOpen} = process.getProcessMemoryInfo()
|
||||
let w = open('./allocate-memory.html')
|
||||
await invokeGc()
|
||||
const {privateBytes: bytesAfterOpen} = process.getProcessMemoryInfo()
|
||||
w.close()
|
||||
w = null
|
||||
await invokeGc()
|
||||
const {privateBytes: bytesAfterClose} = process.getProcessMemoryInfo()
|
||||
ipcRenderer.send('answer', {
|
||||
bytesBeforeOpen, bytesAfterOpen, bytesAfterClose
|
||||
})
|
||||
},
|
||||
'window-events': () => {
|
||||
document.title = 'changed'
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue