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
|
forums
|
||||||
- `#atom-shell` channel on Freenode
|
- `#atom-shell` channel on Freenode
|
||||||
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
- [`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-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
- [`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)*
|
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||||
|
|
||||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||||
|
|
|
@ -34,12 +34,12 @@
|
||||||
#include "chrome/browser/icon_manager.h"
|
#include "chrome/browser/icon_manager.h"
|
||||||
#include "chrome/common/chrome_paths.h"
|
#include "chrome/common/chrome_paths.h"
|
||||||
#include "content/public/browser/browser_accessibility_state.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/client_certificate_delegate.h"
|
||||||
#include "content/public/browser/gpu_data_manager.h"
|
#include "content/public/browser/gpu_data_manager.h"
|
||||||
#include "content/public/browser/render_frame_host.h"
|
#include "content/public/browser/render_frame_host.h"
|
||||||
#include "content/public/common/content_switches.h"
|
#include "content/public/common/content_switches.h"
|
||||||
#include "media/audio/audio_manager.h"
|
#include "media/audio/audio_manager.h"
|
||||||
#include "native_mate/dictionary.h"
|
|
||||||
#include "native_mate/object_template_builder.h"
|
#include "native_mate/object_template_builder.h"
|
||||||
#include "net/ssl/ssl_cert_request_info.h"
|
#include "net/ssl/ssl_cert_request_info.h"
|
||||||
#include "ui/base/l10n/l10n_util.h"
|
#include "ui/base/l10n/l10n_util.h"
|
||||||
|
@ -337,6 +337,17 @@ namespace api {
|
||||||
|
|
||||||
namespace {
|
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) {
|
IconLoader::IconSize GetIconSizeByString(const std::string& size) {
|
||||||
if (size == "small") {
|
if (size == "small") {
|
||||||
return IconLoader::IconSize::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
|
// static
|
||||||
mate::Handle<App> App::Create(v8::Isolate* isolate) {
|
mate::Handle<App> App::Create(v8::Isolate* isolate) {
|
||||||
return mate::CreateHandle(isolate, new App(isolate));
|
return mate::CreateHandle(isolate, new App(isolate));
|
||||||
|
@ -983,7 +1035,8 @@ void App::BuildPrototype(
|
||||||
&App::IsAccessibilitySupportEnabled)
|
&App::IsAccessibilitySupportEnabled)
|
||||||
.SetMethod("disableHardwareAcceleration",
|
.SetMethod("disableHardwareAcceleration",
|
||||||
&App::DisableHardwareAcceleration)
|
&App::DisableHardwareAcceleration)
|
||||||
.SetMethod("getFileIcon", &App::GetFileIcon);
|
.SetMethod("getFileIcon", &App::GetFileIcon)
|
||||||
|
.SetMethod("getAppMemoryInfo", &App::GetAppMemoryInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
|
|
|
@ -13,10 +13,12 @@
|
||||||
#include "atom/browser/browser.h"
|
#include "atom/browser/browser.h"
|
||||||
#include "atom/browser/browser_observer.h"
|
#include "atom/browser/browser_observer.h"
|
||||||
#include "atom/common/native_mate_converters/callback.h"
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
|
#include "base/process/process_iterator.h"
|
||||||
#include "base/task/cancelable_task_tracker.h"
|
#include "base/task/cancelable_task_tracker.h"
|
||||||
#include "chrome/browser/icon_manager.h"
|
#include "chrome/browser/icon_manager.h"
|
||||||
#include "chrome/browser/process_singleton.h"
|
#include "chrome/browser/process_singleton.h"
|
||||||
#include "content/public/browser/gpu_data_manager_observer.h"
|
#include "content/public/browser/gpu_data_manager_observer.h"
|
||||||
|
#include "native_mate/dictionary.h"
|
||||||
#include "native_mate/handle.h"
|
#include "native_mate/handle.h"
|
||||||
#include "net/base/completion_callback.h"
|
#include "net/base/completion_callback.h"
|
||||||
|
|
||||||
|
@ -141,6 +143,8 @@ class App : public AtomBrowserClient::Delegate,
|
||||||
void GetFileIcon(const base::FilePath& path,
|
void GetFileIcon(const base::FilePath& path,
|
||||||
mate::Arguments* args);
|
mate::Arguments* args);
|
||||||
|
|
||||||
|
std::vector<mate::Dictionary> GetAppMemoryInfo(v8::Isolate* isolate);
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
// Get the current Jump List settings.
|
// Get the current Jump List settings.
|
||||||
v8::Local<v8::Value> GetJumpListSettings();
|
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("showErrorBox", &atom::ShowErrorBox);
|
||||||
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
|
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
|
||||||
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
|
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||||
dict.SetMethod("showCertificateTrustDialog",
|
dict.SetMethod("showCertificateTrustDialog",
|
||||||
&certificate_trust::ShowCertificateTrust);
|
&certificate_trust::ShowCertificateTrust);
|
||||||
#endif
|
#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() {
|
void WebContents::DevToolsReloadPage() {
|
||||||
Emit("devtools-reload-page");
|
Emit("devtools-reload-page");
|
||||||
}
|
}
|
||||||
|
|
|
@ -340,6 +340,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
void Observe(int type,
|
void Observe(int type,
|
||||||
const content::NotificationSource& source,
|
const content::NotificationSource& source,
|
||||||
const content::NotificationDetails& details) override;
|
const content::NotificationDetails& details) override;
|
||||||
|
void BeforeUnloadDialogCancelled() override;
|
||||||
|
|
||||||
// brightray::InspectableWebContentsDelegate:
|
// brightray::InspectableWebContentsDelegate:
|
||||||
void DevToolsReloadPage() override;
|
void DevToolsReloadPage() override;
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>electron.icns</string>
|
<string>electron.icns</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.6.8</string>
|
<string>1.6.9</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.6.8</string>
|
<string>1.6.9</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.developer-tools</string>
|
<string>public.app-category.developer-tools</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
|
|
@ -56,8 +56,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,6,8,0
|
FILEVERSION 1,6,9,0
|
||||||
PRODUCTVERSION 1,6,8,0
|
PRODUCTVERSION 1,6,9,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -74,12 +74,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "GitHub, Inc."
|
VALUE "CompanyName", "GitHub, Inc."
|
||||||
VALUE "FileDescription", "Electron"
|
VALUE "FileDescription", "Electron"
|
||||||
VALUE "FileVersion", "1.6.8"
|
VALUE "FileVersion", "1.6.9"
|
||||||
VALUE "InternalName", "electron.exe"
|
VALUE "InternalName", "electron.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||||
VALUE "OriginalFilename", "electron.exe"
|
VALUE "OriginalFilename", "electron.exe"
|
||||||
VALUE "ProductName", "Electron"
|
VALUE "ProductName", "Electron"
|
||||||
VALUE "ProductVersion", "1.6.8"
|
VALUE "ProductVersion", "1.6.9"
|
||||||
VALUE "SquirrelAwareVersion", "1"
|
VALUE "SquirrelAwareVersion", "1"
|
||||||
END
|
END
|
||||||
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];
|
NSString* item_id = [NSString stringWithFormat:@"%ld", ((NSSegmentedControl*)sender).tag];
|
||||||
base::DictionaryValue details;
|
base::DictionaryValue details;
|
||||||
details.SetInteger("selectedIndex", ((NSSegmentedControl*)sender).selectedSegment);
|
details.SetInteger("selectedIndex", ((NSSegmentedControl*)sender).selectedSegment);
|
||||||
|
details.SetBoolean("isSelected", [((NSSegmentedControl*)sender) isSelectedForSegment:((NSSegmentedControl*)sender).selectedSegment]);
|
||||||
window_->NotifyTouchBarItemInteraction([item_id UTF8String],
|
window_->NotifyTouchBarItemInteraction([item_id UTF8String],
|
||||||
details);
|
details);
|
||||||
}
|
}
|
||||||
|
@ -520,6 +521,15 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
||||||
else
|
else
|
||||||
control.segmentStyle = NSSegmentStyleAutomatic;
|
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;
|
std::vector<mate::Dictionary> segments;
|
||||||
settings.Get("segments", &segments);
|
settings.Get("segments", &segments);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||||
#include "atom/common/node_includes.h"
|
#include "atom/common/node_includes.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/process/process_metrics.h"
|
#include "base/sys_info.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
@ -23,51 +23,6 @@ namespace {
|
||||||
// Dummy class type that used for crashing the program.
|
// Dummy class type that used for crashing the program.
|
||||||
struct DummyClass { bool crash; };
|
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
|
// Called when there is a fatal error in V8, we just crash the process here so
|
||||||
// we can get the stack trace.
|
// we can get the stack trace.
|
||||||
void FatalErrorCallback(const char* location, const char* message) {
|
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) {
|
AtomBindings::AtomBindings(uv_loop_t* loop) {
|
||||||
uv_async_init(loop, &call_next_tick_async_, OnCallNextTick);
|
uv_async_init(loop, &call_next_tick_async_, OnCallNextTick);
|
||||||
call_next_tick_async_.data = this;
|
call_next_tick_async_.data = this;
|
||||||
|
metrics_ = base::ProcessMetrics::CreateCurrentProcessMetrics();
|
||||||
}
|
}
|
||||||
|
|
||||||
AtomBindings::~AtomBindings() {
|
AtomBindings::~AtomBindings() {
|
||||||
|
@ -97,6 +53,9 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
|
||||||
dict.SetMethod("log", &Log);
|
dict.SetMethod("log", &Log);
|
||||||
dict.SetMethod("getProcessMemoryInfo", &GetProcessMemoryInfo);
|
dict.SetMethod("getProcessMemoryInfo", &GetProcessMemoryInfo);
|
||||||
dict.SetMethod("getSystemMemoryInfo", &GetSystemMemoryInfo);
|
dict.SetMethod("getSystemMemoryInfo", &GetSystemMemoryInfo);
|
||||||
|
dict.SetMethod("getCPUUsage",
|
||||||
|
base::Bind(&AtomBindings::GetCPUUsage, base::Unretained(this)));
|
||||||
|
dict.SetMethod("getIOCounters", &GetIOCounters);
|
||||||
#if defined(OS_POSIX)
|
#if defined(OS_POSIX)
|
||||||
dict.SetMethod("setFdLimit", &base::SetFdLimit);
|
dict.SetMethod("setFdLimit", &base::SetFdLimit);
|
||||||
#endif
|
#endif
|
||||||
|
@ -168,4 +127,81 @@ void AtomBindings::Crash() {
|
||||||
static_cast<DummyClass*>(nullptr)->crash = true;
|
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
|
} // namespace atom
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
|
#include "base/process/process_metrics.h"
|
||||||
#include "base/strings/string16.h"
|
#include "base/strings/string16.h"
|
||||||
|
#include "native_mate/arguments.h"
|
||||||
#include "v8/include/v8.h"
|
#include "v8/include/v8.h"
|
||||||
#include "vendor/node/deps/uv/include/uv.h"
|
#include "vendor/node/deps/uv/include/uv.h"
|
||||||
|
|
||||||
|
@ -32,6 +34,12 @@ class AtomBindings {
|
||||||
|
|
||||||
static void Log(const base::string16& message);
|
static void Log(const base::string16& message);
|
||||||
static void Crash();
|
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:
|
private:
|
||||||
void ActivateUVLoop(v8::Isolate* isolate);
|
void ActivateUVLoop(v8::Isolate* isolate);
|
||||||
|
@ -40,6 +48,7 @@ class AtomBindings {
|
||||||
|
|
||||||
uv_async_t call_next_tick_async_;
|
uv_async_t call_next_tick_async_;
|
||||||
std::list<node::Environment*> pending_next_ticks_;
|
std::list<node::Environment*> pending_next_ticks_;
|
||||||
|
std::unique_ptr<base::ProcessMetrics> metrics_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(AtomBindings);
|
DISALLOW_COPY_AND_ASSIGN(AtomBindings);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#define ATOM_MAJOR_VERSION 1
|
#define ATOM_MAJOR_VERSION 1
|
||||||
#define ATOM_MINOR_VERSION 6
|
#define ATOM_MINOR_VERSION 6
|
||||||
#define ATOM_PATCH_VERSION 8
|
#define ATOM_PATCH_VERSION 9
|
||||||
|
|
||||||
#define ATOM_VERSION_IS_RELEASE 1
|
#define ATOM_VERSION_IS_RELEASE 1
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,9 @@ void InitializeBindings(v8::Local<v8::Object> binding,
|
||||||
mate::Dictionary b(isolate, binding);
|
mate::Dictionary b(isolate, binding);
|
||||||
b.SetMethod("get", GetBinding);
|
b.SetMethod("get", GetBinding);
|
||||||
b.SetMethod("crash", AtomBindings::Crash);
|
b.SetMethod("crash", AtomBindings::Crash);
|
||||||
|
b.SetMethod("hang", AtomBindings::Hang);
|
||||||
|
b.SetMethod("getProcessMemoryInfo", &AtomBindings::GetProcessMemoryInfo);
|
||||||
|
b.SetMethod("getSystemMemoryInfo", &AtomBindings::GetSystemMemoryInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
class AtomSandboxedRenderViewObserver : public AtomRenderViewObserver {
|
class AtomSandboxedRenderViewObserver : public AtomRenderViewObserver {
|
||||||
|
|
|
@ -74,7 +74,7 @@ Atom.
|
||||||
- [`electron-br`](https://electron-br.slack.com) *(Portugués Brasileño)*
|
- [`electron-br`](https://electron-br.slack.com) *(Portugués Brasileño)*
|
||||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Koreano)*
|
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Koreano)*
|
||||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japonés)*
|
- [`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*
|
- [`electron-id`](https://electron-id.slack.com) *(Indonés*
|
||||||
|
|
||||||
Mira [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
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-br`](https://electron-br.slack.com) *(브라질)* 커뮤니티
|
||||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(한국)* 커뮤니티
|
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(한국)* 커뮤니티
|
||||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(일본)* 커뮤니티
|
- [`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) *(인도네시아)* 커뮤니티
|
- [`electron-id`](https://electron-id.slack.com) *(인도네시아)* 커뮤니티
|
||||||
|
|
||||||
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에
|
[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-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(Japanese)*
|
- [`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)*
|
- [`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.
|
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-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
- [`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)*
|
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||||
|
|
||||||
Topluluk tarafından sağlanan örnek uygulamaları, aracları ve kaynaklara ulaşmak için
|
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-br`](https://electron-br.slack.com) *(葡萄牙语-巴西)*
|
||||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(韩语)*
|
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(韩语)*
|
||||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(日语)*
|
- [`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) *(印度尼西亚)*
|
- [`electron-id`](https://electron-id.slack.com) *(印度尼西亚)*
|
||||||
|
|
||||||
查看 [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
查看 [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-br`](https://electron-br.slack.com) *(葡萄牙語-巴西)*
|
||||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(韓語)*
|
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(韓語)*
|
||||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(日語)*
|
- [`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) *(印度尼西亞)*
|
- [`electron-id`](https://electron-id.slack.com) *(印度尼西亞)*
|
||||||
|
|
||||||
在 [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
在 [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||||
查看由社群維護的清單,包括實用的應用程式、工具以及資源。
|
查看由社群維護的清單,包括實用的應用程式、工具以及資源。
|
||||||
|
|
||||||
## 憑證
|
## 授權條款
|
||||||
|
|
||||||
MIT © 2016 Github
|
MIT © 2016 Github
|
||||||
|
|
|
@ -40,6 +40,7 @@ an issue:
|
||||||
* [Desktop Environment Integration](tutorial/desktop-environment-integration.md)
|
* [Desktop Environment Integration](tutorial/desktop-environment-integration.md)
|
||||||
* [Online/Offline Event Detection](tutorial/online-offline-events.md)
|
* [Online/Offline Event Detection](tutorial/online-offline-events.md)
|
||||||
* [REPL](tutorial/repl.md)
|
* [REPL](tutorial/repl.md)
|
||||||
|
* [Native Notifications](tutorial/notifications.md)
|
||||||
|
|
||||||
## API References
|
## API References
|
||||||
|
|
||||||
|
|
|
@ -760,6 +760,10 @@ Disables hardware acceleration for current app.
|
||||||
|
|
||||||
This method can only be called before app is ready.
|
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_
|
### `app.setBadgeCount(count)` _Linux_ _macOS_
|
||||||
|
|
||||||
* `count` Integer
|
* `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,
|
before the app `ready`event on Linux, the message will be emitted to stderr,
|
||||||
and no GUI dialog will appear.
|
and no GUI dialog will appear.
|
||||||
|
|
||||||
### `dialog.showCertificateTrustDialog([browserWindow, ]options, callback)` _macOS_
|
### `dialog.showCertificateTrustDialog([browserWindow, ]options, callback)` _macOS_ _Windows_
|
||||||
|
|
||||||
* `browserWindow` BrowserWindow (optional)
|
* `browserWindow` BrowserWindow (optional)
|
||||||
* `options` Object
|
* `options` Object
|
||||||
|
@ -184,11 +184,17 @@ and no GUI dialog will appear.
|
||||||
* `message` String - The message to display to the user.
|
* `message` String - The message to display to the user.
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
|
|
||||||
Displays a modal dialog that shows a message and certificate information, and
|
On macOS, this displays a modal dialog that shows a message and certificate
|
||||||
gives the user the option of trusting/importing the 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
|
On Windows the options are more limited, due to the Win32 APIs used:
|
||||||
window, making it modal.
|
|
||||||
|
- 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
|
## 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.
|
process, see [webContents.send][web-contents-send] for more information.
|
||||||
|
|
||||||
* When sending a message, the event name is the `channel`.
|
* When sending a message, the event name is the `channel`.
|
||||||
* To reply a synchronous message, you need to set `event.returnValue`.
|
* To reply to a synchronous message, you need to set `event.returnValue`.
|
||||||
* To send an asynchronous back to the sender, you can use
|
* To send an asynchronous message back to the sender, you can use
|
||||||
`event.sender.send(...)`.
|
`event.sender.send(...)`.
|
||||||
|
|
||||||
An example of sending and handling messages between the render and main
|
An example of sending and handling messages between the render and main
|
||||||
|
|
|
@ -8,132 +8,135 @@ values are listed below:
|
||||||
| Language Code | Language Name |
|
| Language Code | Language Name |
|
||||||
|---------------|---------------|
|
|---------------|---------------|
|
||||||
| af | Afrikaans |
|
| af | Afrikaans |
|
||||||
| an | Aragonese |
|
| am | Amharic |
|
||||||
| ar-AE | Arabic (U.A.E.) |
|
| ar | Arabic |
|
||||||
| 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 |
|
|
||||||
| az | Azerbaijani |
|
| az | Azerbaijani |
|
||||||
| be | Belarusian |
|
| be | Belarusian |
|
||||||
| bg | Bulgarian |
|
| bg | Bulgarian |
|
||||||
| bg | Bulgarian |
|
| bh | Bihari |
|
||||||
| bn | Bengali |
|
| bn | Bengali |
|
||||||
| br | Breton |
|
| br | Breton |
|
||||||
| bs | Bosnian |
|
| bs | Bosnian |
|
||||||
| ca | Catalan |
|
| ca | Catalan |
|
||||||
| ce | Chechen |
|
|
||||||
| ch | Chamorro |
|
|
||||||
| co | Corsican |
|
| co | Corsican |
|
||||||
| cr | Cree |
|
|
||||||
| cs | Czech |
|
| cs | Czech |
|
||||||
| cv | Chuvash |
|
| cy | Welsh |
|
||||||
| da | Danish |
|
| da | Danish |
|
||||||
| de | German (Standard) |
|
| de | German |
|
||||||
| de-AT | German (Austria) |
|
| de-AT | German (Austria) |
|
||||||
| de-CH | German (Switzerland) |
|
| de-CH | German (Switzerland) |
|
||||||
| de-DE | German (Germany) |
|
| de-DE | German (Germany) |
|
||||||
| de-LI | German (Liechtenstein) |
|
|
||||||
| de-LU | German (Luxembourg) |
|
|
||||||
| el | Greek |
|
| el | Greek |
|
||||||
| en-AU | English (Australia) |
|
|
||||||
| en-BZ | English (Belize) |
|
|
||||||
| en | English |
|
| en | English |
|
||||||
|
| en-AU | English (Australia) |
|
||||||
| en-CA | English (Canada) |
|
| en-CA | English (Canada) |
|
||||||
| en-GB | English (United Kingdom) |
|
| en-GB | English (UK) |
|
||||||
| en-IE | English (Ireland) |
|
|
||||||
| en-JM | English (Jamaica) |
|
|
||||||
| en-NZ | English (New Zealand) |
|
| en-NZ | English (New Zealand) |
|
||||||
| en-PH | English (Philippines) |
|
| en-US | English (US) |
|
||||||
| en-TT | English (Trinidad & Tobago) |
|
|
||||||
| en-US | English (United States) |
|
|
||||||
| en-ZA | English (South Africa) |
|
| en-ZA | English (South Africa) |
|
||||||
| en-ZW | English (Zimbabwe) |
|
|
||||||
| eo | Esperanto |
|
| eo | Esperanto |
|
||||||
|
| es | Spanish |
|
||||||
|
| es-419 | Spanish (Latin America) |
|
||||||
| et | Estonian |
|
| et | Estonian |
|
||||||
| eu | Basque |
|
| eu | Basque |
|
||||||
| fa | Persian |
|
| fa | Persian |
|
||||||
| fa | Farsi |
|
|
||||||
| fa-IR | Persian/Iran |
|
|
||||||
| fi | Finnish |
|
| fi | Finnish |
|
||||||
| fj | Fijian |
|
| fil | Filipino |
|
||||||
| fo | Faeroese |
|
| fo | Faroese |
|
||||||
|
| fr | French |
|
||||||
|
| fr-CA | French (Canada) |
|
||||||
| fr-CH | French (Switzerland) |
|
| fr-CH | French (Switzerland) |
|
||||||
| fr-FR | French (France) |
|
| 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 |
|
| fy | Frisian |
|
||||||
| ga | Irish |
|
| ga | Irish |
|
||||||
| gd-IE | Gaelic (Irish) |
|
| gd | Scots Gaelic |
|
||||||
| gd | Gaelic (Scots) |
|
| gl | Galician |
|
||||||
| gl | Galacian |
|
| gn | Guarani |
|
||||||
| gu | Gujurati |
|
| gu | Gujarati |
|
||||||
|
| ha | Hausa |
|
||||||
|
| haw | Hawaiian |
|
||||||
| he | Hebrew |
|
| he | Hebrew |
|
||||||
| hi | Hindi |
|
| hi | Hindi |
|
||||||
| hr | Croatian |
|
| hr | Croatian |
|
||||||
| ht | Haitian |
|
|
||||||
| hu | Hungarian |
|
| hu | Hungarian |
|
||||||
| hy | Armenian |
|
| hy | Armenian |
|
||||||
|
| ia | Interlingua |
|
||||||
| id | Indonesian |
|
| id | Indonesian |
|
||||||
| is | Icelandic |
|
| is | Icelandic |
|
||||||
|
| it | Italian |
|
||||||
| it-CH | Italian (Switzerland) |
|
| it-CH | Italian (Switzerland) |
|
||||||
| it | Italian (Standard) |
|
| it-IT | Italian (Italy) |
|
||||||
| iu | Inuktitut |
|
|
||||||
| ja | Japanese |
|
| ja | Japanese |
|
||||||
|
| jw | Javanese |
|
||||||
| ka | Georgian |
|
| ka | Georgian |
|
||||||
| kk | Kazakh |
|
| kk | Kazakh |
|
||||||
| km | Khmer |
|
| km | Cambodian |
|
||||||
| kn | Kannada |
|
| kn | Kannada |
|
||||||
| ko | Korean |
|
| ko | Korean |
|
||||||
| ko-KP | Korean (North Korea) |
|
| ku | Kurdish |
|
||||||
| ko-KR | Korean (South Korea) |
|
| ky | Kyrgyz |
|
||||||
| ks | Kashmiri |
|
|
||||||
| ky | Kirghiz |
|
|
||||||
| la | Latin |
|
| la | Latin |
|
||||||
| lb | Luxembourgish |
|
| ln | Lingala |
|
||||||
|
| lo | Laothian |
|
||||||
| lt | Lithuanian |
|
| lt | Lithuanian |
|
||||||
| lv | Latvian |
|
| lv | Latvian |
|
||||||
| mi | Maori |
|
| mk | Macedonian |
|
||||||
| mk | FYRO Macedonian |
|
|
||||||
| ml | Malayalam |
|
| ml | Malayalam |
|
||||||
|
| mn | Mongolian |
|
||||||
| mo | Moldavian |
|
| mo | Moldavian |
|
||||||
| mr | Marathi |
|
| mr | Marathi |
|
||||||
| ms | Malay |
|
| ms | Malay |
|
||||||
| mt | Maltese |
|
| mt | Maltese |
|
||||||
| my | Burmese |
|
|
||||||
| nb | Norwegian (Bokmal) |
|
| nb | Norwegian (Bokmal) |
|
||||||
| ne | Nepali |
|
| ne | Nepali |
|
||||||
| ng | Ndonga |
|
| nl | Dutch |
|
||||||
| nl | Dutch (Standard) |
|
|
||||||
| nl-BE | Dutch (Belgian) |
|
|
||||||
| nn | Norwegian (Nynorsk) |
|
| nn | Norwegian (Nynorsk) |
|
||||||
| no | Norwegian |
|
| no | Norwegian |
|
||||||
| nv | Navajo |
|
|
||||||
| oc | Occitan |
|
| oc | Occitan |
|
||||||
| om | Oromo |
|
| om | Oromo |
|
||||||
| or | Oriya |
|
| 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 |
|
| sq | Albanian |
|
||||||
| tlh | Klingon |
|
| sr | Serbian |
|
||||||
| zh-TW | Chinese (Taiwan) |
|
| 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 | Chinese |
|
||||||
| zh-CN | Chinese (PRC) |
|
| zh-CN | Chinese (Simplified) |
|
||||||
| zh-HK | Chinese (Hong Kong) |
|
| zh-TW | Chinese (Traditional) |
|
||||||
| zh-SG | Chinese (Singapore) |
|
| zu | Zulu |
|
||||||
|
|
|
@ -116,3 +116,15 @@ Returns `Object`:
|
||||||
|
|
||||||
Returns an object giving memory usage statistics about the entire system. Note
|
Returns an object giving memory usage statistics about the entire system. Note
|
||||||
that all statistics are reported in Kilobytes.
|
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.
|
* `small-square` - The control is displayed using the small square style.
|
||||||
* `separated` - The segments in the control are displayed very close to each
|
* `separated` - The segments in the control are displayed very close to each
|
||||||
other but not touching.
|
other but not touching.
|
||||||
* `segments` [SegmentedControlSegment[]](structures/segmented-control-segment.md) - An array of segments to place in this control
|
* `mode` String - (Optional) The selection mode of the control:
|
||||||
* `selectedIndex` Integer (Optional) - The index of the currently selected segment, will update automatically with user interaction
|
* `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
|
* `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
|
### Instance Properties
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ available in "core".
|
||||||
### V8
|
### V8
|
||||||
|
|
||||||
V8 is Google's open source JavaScript engine. It is written in C++ and is
|
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.
|
standalone, or can be embedded into any C++ application.
|
||||||
|
|
||||||
### webview
|
### 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
|
This guide explains how to integrate your application into those desktop
|
||||||
environments with Electron APIs.
|
environments with Electron APIs.
|
||||||
|
|
||||||
## Notifications (Windows, Linux, macOS)
|
## Notifications
|
||||||
|
|
||||||
All three operating systems provide means for applications to send notifications
|
See [Notifications](notifications.md)
|
||||||
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.
|
|
||||||
|
|
||||||
## Recent documents (Windows & macOS)
|
## 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
|
If you downloaded Electron manually, you can also use the included
|
||||||
binary to execute your app directly.
|
binary to execute your app directly.
|
||||||
|
|
||||||
#### Windows
|
#### macOS
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ .\electron\electron.exe your-app\
|
$ ./Electron.app/Contents/MacOS/Electron your-app/
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Linux
|
#### Linux
|
||||||
|
@ -204,10 +204,10 @@ $ .\electron\electron.exe your-app\
|
||||||
$ ./electron/electron your-app/
|
$ ./electron/electron your-app/
|
||||||
```
|
```
|
||||||
|
|
||||||
#### macOS
|
#### Windows
|
||||||
|
|
||||||
```bash
|
```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
|
`Electron.app` here is part of the Electron's release package, you can download
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
'product_name%': 'Electron',
|
'product_name%': 'Electron',
|
||||||
'company_name%': 'GitHub, Inc',
|
'company_name%': 'GitHub, Inc',
|
||||||
'company_abbr%': 'github',
|
'company_abbr%': 'github',
|
||||||
'version%': '1.6.8',
|
'version%': '1.6.9',
|
||||||
'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c',
|
'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c',
|
||||||
},
|
},
|
||||||
'includes': [
|
'includes': [
|
||||||
|
|
|
@ -291,6 +291,7 @@
|
||||||
'atom/browser/ui/atom_menu_model.h',
|
'atom/browser/ui/atom_menu_model.h',
|
||||||
'atom/browser/ui/certificate_trust.h',
|
'atom/browser/ui/certificate_trust.h',
|
||||||
'atom/browser/ui/certificate_trust_mac.mm',
|
'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.h',
|
||||||
'atom/browser/ui/cocoa/atom_menu_controller.mm',
|
'atom/browser/ui/cocoa/atom_menu_controller.mm',
|
||||||
'atom/browser/ui/cocoa/atom_touch_bar.h',
|
'atom/browser/ui/cocoa/atom_touch_bar.h',
|
||||||
|
|
|
@ -264,16 +264,17 @@ TouchBar.TouchBarSegmentedControl = class TouchBarSegmentedControl extends Touch
|
||||||
constructor (config) {
|
constructor (config) {
|
||||||
super()
|
super()
|
||||||
if (config == null) config = {}
|
if (config == null) config = {}
|
||||||
const {segmentStyle, segments, selectedIndex, change} = config
|
const {segmentStyle, segments, selectedIndex, change, mode} = config
|
||||||
this.type = 'segmented_control'
|
this.type = 'segmented_control'
|
||||||
this._addLiveProperty('segmentStyle', segmentStyle)
|
this._addLiveProperty('segmentStyle', segmentStyle)
|
||||||
this._addLiveProperty('segments', segments || [])
|
this._addLiveProperty('segments', segments || [])
|
||||||
this._addLiveProperty('selectedIndex', selectedIndex)
|
this._addLiveProperty('selectedIndex', selectedIndex)
|
||||||
|
this._addLiveProperty('mode', mode)
|
||||||
|
|
||||||
if (typeof change === 'function') {
|
if (typeof change === 'function') {
|
||||||
this.onInteraction = (details) => {
|
this.onInteraction = (details) => {
|
||||||
this._selectedIndex = details.selectedIndex
|
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`).
|
// access to things like `process.atomBinding`).
|
||||||
const preloadProcess = new events.EventEmitter()
|
const preloadProcess = new events.EventEmitter()
|
||||||
preloadProcess.crash = () => binding.crash()
|
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.platform = preloadProcess.platform = electron.remote.process.platform
|
||||||
process.execPath = preloadProcess.execPath = electron.remote.process.execPath
|
process.execPath = preloadProcess.execPath = electron.remote.process.execPath
|
||||||
process.on('exit', () => preloadProcess.emit('exit'))
|
process.on('exit', () => preloadProcess.emit('exit'))
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "electron",
|
"name": "electron",
|
||||||
"version": "1.6.8",
|
"version": "1.6.9",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"asar": "^0.11.0",
|
"asar": "^0.11.0",
|
||||||
"browserify": "^13.1.0",
|
"browserify": "^13.1.0",
|
||||||
"electabul": "~0.0.4",
|
"electabul": "~0.0.4",
|
||||||
"electron-docs-linter": "^2.1.0",
|
"electron-docs-linter": "^2.1.0",
|
||||||
|
"electron-typescript-definitions": "^1.2.0",
|
||||||
"request": "*",
|
"request": "*",
|
||||||
"standard": "^8.4.0",
|
"standard": "^8.4.0",
|
||||||
"standard-markdown": "^2.1.1"
|
"standard-markdown": "^2.1.1"
|
||||||
|
|
|
@ -81,6 +81,7 @@ def main():
|
||||||
sys.stderr.write('\nRunning `npm run lint`\n')
|
sys.stderr.write('\nRunning `npm run lint`\n')
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
execute([npm, 'run', 'lint'])
|
execute([npm, 'run', 'lint'])
|
||||||
|
|
||||||
if is_release:
|
if is_release:
|
||||||
run_script('build.py', ['-c', 'R'])
|
run_script('build.py', ['-c', 'R'])
|
||||||
run_script('create-dist.py')
|
run_script('create-dist.py')
|
||||||
|
|
|
@ -91,6 +91,7 @@ def main():
|
||||||
|
|
||||||
if PLATFORM != 'win32' and not args.no_api_docs:
|
if PLATFORM != 'win32' and not args.no_api_docs:
|
||||||
create_api_json_schema()
|
create_api_json_schema()
|
||||||
|
create_typescript_definitions()
|
||||||
|
|
||||||
if PLATFORM == 'linux':
|
if PLATFORM == 'linux':
|
||||||
strip_binaries()
|
strip_binaries()
|
||||||
|
@ -143,6 +144,15 @@ def create_api_json_schema():
|
||||||
'--version={}'.format(ELECTRON_VERSION.replace('v', ''))],
|
'--version={}'.format(ELECTRON_VERSION.replace('v', ''))],
|
||||||
env=env)
|
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():
|
def strip_binaries():
|
||||||
for binary in TARGET_BINARIES[PLATFORM]:
|
for binary in TARGET_BINARIES[PLATFORM]:
|
||||||
if binary.endswith('.so') or '.' not in binary:
|
if binary.endswith('.so') or '.' not in binary:
|
||||||
|
|
|
@ -81,6 +81,7 @@ def main():
|
||||||
if PLATFORM == 'darwin':
|
if PLATFORM == 'darwin':
|
||||||
upload_electron(github, release, os.path.join(DIST_DIR,
|
upload_electron(github, release, os.path.join(DIST_DIR,
|
||||||
'electron-api.json'))
|
'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))
|
upload_electron(github, release, os.path.join(DIST_DIR, DSYM_NAME))
|
||||||
elif PLATFORM == 'win32':
|
elif PLATFORM == 'win32':
|
||||||
upload_electron(github, release, os.path.join(DIST_DIR, PDB_NAME))
|
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'))
|
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'))
|
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 () {
|
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>
|
<html>
|
||||||
<script type="text/javascript" charset="utf-8">
|
<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) {
|
if (window.opener) {
|
||||||
window.callback = () => {
|
window.callback = () => {
|
||||||
opener.require('electron').ipcRenderer.send('answer', document.body.innerHTML)
|
opener.require('electron').ipcRenderer.send('answer', document.body.innerHTML)
|
||||||
|
@ -7,6 +20,20 @@
|
||||||
} else {
|
} else {
|
||||||
const {ipcRenderer} = require('electron')
|
const {ipcRenderer} = require('electron')
|
||||||
const tests = {
|
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': () => {
|
'window-events': () => {
|
||||||
document.title = 'changed'
|
document.title = 'changed'
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue