From a92f639b64cb8d16e91228da54e449a4dc0a316d Mon Sep 17 00:00:00 2001 From: Cory Reed Date: Thu, 23 Mar 2017 11:55:46 -0700 Subject: [PATCH 01/80] :memo: Add note regarding dynamic addition/removal of menu items. Closes #8928. [ci skip] --- docs/api/menu.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/api/menu.md b/docs/api/menu.md index cd6817625a..ad846fb84d 100644 --- a/docs/api/menu.md +++ b/docs/api/menu.md @@ -25,6 +25,10 @@ will be set as each window's top menu. Returns `Menu` - The application menu, if set, or `null`, if not set. +**Note:** The returned `Menu` instance doesn't support dynamic addition or +removal of menu items. [Instance properties](#instance-properties) can still +be dynamically modified. + #### `Menu.sendActionToFirstResponder(action)` _macOS_ * `action` String From 673f4f4d0c9167bc03a54e73bad4b0cab78708eb Mon Sep 17 00:00:00 2001 From: Ryohei Ikegami Date: Mon, 3 Apr 2017 19:46:24 +0900 Subject: [PATCH 02/80] Add test for `require` to search under app dir --- spec/modules-spec.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/spec/modules-spec.js b/spec/modules-spec.js index 5f82717527..26cafc7ccb 100644 --- a/spec/modules-spec.js +++ b/spec/modules-spec.js @@ -2,6 +2,8 @@ const assert = require('assert') const Module = require('module') const path = require('path') const temp = require('temp') +const {remote} = require('electron') +const {BrowserWindow} = remote describe('third-party module', function () { var fixtures = path.join(__dirname, 'fixtures') @@ -129,3 +131,17 @@ describe('Module._nodeModulePaths', function () { }) }) }) + +describe('require', () => { + describe('when loaded URL is not file: protocol', () => { + it('searches for module under app directory', async () => { + const w = new BrowserWindow({ + show: false, + }) + w.loadURL('about:blank') + const result = await w.webContents.executeJavaScript('typeof require("q").when') + assert.equal(result, 'function') + w.destroy() + }) + }) +}) From 50c99e4507d3a9f06c66d52754c977d24eea347c Mon Sep 17 00:00:00 2001 From: Ryohei Ikegami Date: Mon, 3 Apr 2017 20:12:02 +0900 Subject: [PATCH 03/80] Search for module under the app directory --- lib/renderer/init.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/renderer/init.js b/lib/renderer/init.js index 38441c9ec1..c6fd6a2e24 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -116,6 +116,9 @@ if (nodeIntegration === 'true') { } else { global.__filename = __filename global.__dirname = __dirname + + // Search for module under the app directory + module.paths = module.paths.concat(Module._nodeModulePaths(electron.remote.app.getAppPath())) } // Redirect window.onerror to uncaughtException. From d1212d4a43a15dc1d501365cda513e7dcee51353 Mon Sep 17 00:00:00 2001 From: Ryohei Ikegami Date: Mon, 3 Apr 2017 20:23:36 +0900 Subject: [PATCH 04/80] Fix JS style --- spec/modules-spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/modules-spec.js b/spec/modules-spec.js index 26cafc7ccb..c918d377dd 100644 --- a/spec/modules-spec.js +++ b/spec/modules-spec.js @@ -136,7 +136,7 @@ describe('require', () => { describe('when loaded URL is not file: protocol', () => { it('searches for module under app directory', async () => { const w = new BrowserWindow({ - show: false, + show: false }) w.loadURL('about:blank') const result = await w.webContents.executeJavaScript('typeof require("q").when') From 001d03c859be5e68267c6b59d3a73d7f2fe7a9fd Mon Sep 17 00:00:00 2001 From: Ryohei Ikegami Date: Mon, 3 Apr 2017 22:11:29 +0900 Subject: [PATCH 05/80] Do not add search paths in devtools --- lib/renderer/init.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/renderer/init.js b/lib/renderer/init.js index c6fd6a2e24..72f7c9ebab 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -117,8 +117,11 @@ if (nodeIntegration === 'true') { global.__filename = __filename global.__dirname = __dirname - // Search for module under the app directory - module.paths = module.paths.concat(Module._nodeModulePaths(electron.remote.app.getAppPath())) + if (window.location.protocol !== 'chrome-devtools:') { + // Search for module under the app directory + // (remote.app doesn't work in devtools) + module.paths = module.paths.concat(Module._nodeModulePaths(electron.remote.app.getAppPath())) + } } // Redirect window.onerror to uncaughtException. From 9cb6bc098de5a9df75c6afda0be6f5c697a4ed3f Mon Sep 17 00:00:00 2001 From: Ryohei Ikegami Date: Tue, 4 Apr 2017 09:08:27 +0900 Subject: [PATCH 06/80] Use beforeEach/afterEach --- spec/modules-spec.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/spec/modules-spec.js b/spec/modules-spec.js index c918d377dd..02fec41444 100644 --- a/spec/modules-spec.js +++ b/spec/modules-spec.js @@ -134,13 +134,21 @@ describe('Module._nodeModulePaths', function () { describe('require', () => { describe('when loaded URL is not file: protocol', () => { - it('searches for module under app directory', async () => { - const w = new BrowserWindow({ + let w + + beforeEach(() => { + w = new BrowserWindow({ show: false }) + }) + + it('searches for module under app directory', async () => { w.loadURL('about:blank') const result = await w.webContents.executeJavaScript('typeof require("q").when') assert.equal(result, 'function') + }) + + afterEach(() => { w.destroy() }) }) From 4a7eec8f2dd74217aa99d8da4ed0cc61038eee3a Mon Sep 17 00:00:00 2001 From: Ryohei Ikegami Date: Tue, 4 Apr 2017 09:36:01 +0900 Subject: [PATCH 07/80] Pass app path as command line argument --- atom/browser/api/atom_api_app.cc | 10 ++++++++++ atom/browser/api/atom_api_app.h | 6 ++++++ atom/browser/atom_browser_client.cc | 6 ++++++ atom/common/options_switches.cc | 3 +++ atom/common/options_switches.h | 1 + lib/browser/api/app.js | 4 ---- lib/renderer/init.js | 8 +++++--- 7 files changed, 31 insertions(+), 7 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 56a11daf69..a53e957660 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -655,6 +655,14 @@ void App::OnGpuProcessCrashed(base::TerminationStatus status) { status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED); } +std::string App::GetAppPath() { + return app_path_; +} + +void App::SetAppPath(const std::string& app_path) { + app_path_ = app_path; +} + base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) { bool succeed = false; base::FilePath path; @@ -959,6 +967,8 @@ void App::BuildPrototype( .SetMethod("isUnityRunning", base::Bind(&Browser::IsUnityRunning, browser)) #endif + .SetMethod("setAppPath", &App::SetAppPath) + .SetMethod("getAppPath", &App::GetAppPath) .SetMethod("setPath", &App::SetPath) .SetMethod("getPath", &App::GetPath) .SetMethod("setDesktopName", &App::SetDesktopName) diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 8b276f334d..4b09d77031 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -70,6 +70,8 @@ class App : public AtomBrowserClient::Delegate, std::unique_ptr model); #endif + std::string GetAppPath(); + protected: explicit App(v8::Isolate* isolate); ~App() override; @@ -115,6 +117,8 @@ class App : public AtomBrowserClient::Delegate, void OnGpuProcessCrashed(base::TerminationStatus status) override; private: + void SetAppPath(const std::string& app_path); + // Get/Set the pre-defined path in PathService. base::FilePath GetPath(mate::Arguments* args, const std::string& name); void SetPath(mate::Arguments* args, @@ -154,6 +158,8 @@ class App : public AtomBrowserClient::Delegate, // Tracks tasks requesting file icons. base::CancelableTaskTracker cancelable_task_tracker_; + std::string app_path_; + DISALLOW_COPY_AND_ASSIGN(App); }; diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index d0bbf4ad53..9894e5e928 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -234,6 +234,12 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches( } #endif + if (delegate_) { + auto app_path = static_cast(delegate_)->GetAppPath(); + command_line->AppendSwitchASCII(switches::kAppPath, + app_path); + } + content::WebContents* web_contents = GetWebContentsFromProcessID(process_id); if (!web_contents) return; diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 288fcd3a07..2f1c0368f3 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -159,6 +159,9 @@ const char kSecureSchemes[] = "secure-schemes"; // The browser process app model ID const char kAppUserModelId[] = "app-user-model-id"; +// The application path +const char kAppPath[] = "app-path"; + // The command line switch versions of the options. const char kBackgroundColor[] = "background-color"; const char kPreloadScript[] = "preload"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 9e1a71ca5b..69e7af029e 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -81,6 +81,7 @@ extern const char kStandardSchemes[]; extern const char kRegisterServiceWorkerSchemes[]; extern const char kSecureSchemes[]; extern const char kAppUserModelId[]; +extern const char kAppPath[]; extern const char kBackgroundColor[]; extern const char kPreloadScript[]; diff --git a/lib/browser/api/app.js b/lib/browser/api/app.js index c5865f2242..d1ca60280e 100644 --- a/lib/browser/api/app.js +++ b/lib/browser/api/app.js @@ -12,11 +12,7 @@ const {EventEmitter} = require('events') Object.setPrototypeOf(App.prototype, EventEmitter.prototype) -let appPath = null - Object.assign(app, { - getAppPath () { return appPath }, - setAppPath (path) { appPath = path }, setApplicationMenu (menu) { return Menu.setApplicationMenu(menu) }, diff --git a/lib/renderer/init.js b/lib/renderer/init.js index 72f7c9ebab..0306463bc4 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -56,6 +56,7 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (ev let nodeIntegration = 'false' let preloadScript = null let isBackgroundPage = false +let appPath = null for (let arg of process.argv) { if (arg.indexOf('--guest-instance-id=') === 0) { // This is a guest web view. @@ -69,6 +70,8 @@ for (let arg of process.argv) { preloadScript = arg.substr(arg.indexOf('=') + 1) } else if (arg === '--background-page') { isBackgroundPage = true + } else if (arg.indexOf('--app-path=') === 0) { + appPath = arg.substr(arg.indexOf('=') + 1) } } @@ -117,10 +120,9 @@ if (nodeIntegration === 'true') { global.__filename = __filename global.__dirname = __dirname - if (window.location.protocol !== 'chrome-devtools:') { + if (appPath) { // Search for module under the app directory - // (remote.app doesn't work in devtools) - module.paths = module.paths.concat(Module._nodeModulePaths(electron.remote.app.getAppPath())) + module.paths = module.paths.concat(Module._nodeModulePaths(appPath)) } } From 24fedb2e20e9468f9b12a03198fe9c649039a9e5 Mon Sep 17 00:00:00 2001 From: Ryohei Ikegami Date: Tue, 4 Apr 2017 09:40:38 +0900 Subject: [PATCH 08/80] No extra linebreak --- atom/browser/atom_browser_client.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 9894e5e928..3908c9613a 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -236,8 +236,7 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches( if (delegate_) { auto app_path = static_cast(delegate_)->GetAppPath(); - command_line->AppendSwitchASCII(switches::kAppPath, - app_path); + command_line->AppendSwitchASCII(switches::kAppPath, app_path); } content::WebContents* web_contents = GetWebContentsFromProcessID(process_id); From c77e07bc1539e3d395047a03adbfb1ef0e2e249d Mon Sep 17 00:00:00 2001 From: Ryohei Ikegami Date: Wed, 12 Apr 2017 11:55:41 +0900 Subject: [PATCH 09/80] Fix afterEach --- spec/modules-spec.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/spec/modules-spec.js b/spec/modules-spec.js index 02fec41444..7cc5d34fe6 100644 --- a/spec/modules-spec.js +++ b/spec/modules-spec.js @@ -4,6 +4,7 @@ const path = require('path') const temp = require('temp') const {remote} = require('electron') const {BrowserWindow} = remote +const {closeWindow} = require('./window-helpers') describe('third-party module', function () { var fixtures = path.join(__dirname, 'fixtures') @@ -142,14 +143,15 @@ describe('require', () => { }) }) + afterEach(async () => { + await closeWindow(w) + w = null + }) + it('searches for module under app directory', async () => { w.loadURL('about:blank') const result = await w.webContents.executeJavaScript('typeof require("q").when') assert.equal(result, 'function') }) - - afterEach(() => { - w.destroy() - }) }) }) From 9d62b196d3676cfe43963ad7dab0917aa2992ad9 Mon Sep 17 00:00:00 2001 From: Ryohei Ikegami Date: Thu, 13 Apr 2017 10:59:12 +0900 Subject: [PATCH 10/80] Use base::FilePath --- atom/browser/api/atom_api_app.cc | 4 ++-- atom/browser/api/atom_api_app.h | 6 +++--- atom/browser/atom_browser_client.cc | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index a53e957660..d8e79171f8 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -655,11 +655,11 @@ void App::OnGpuProcessCrashed(base::TerminationStatus status) { status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED); } -std::string App::GetAppPath() { +base::FilePath App::GetAppPath() { return app_path_; } -void App::SetAppPath(const std::string& app_path) { +void App::SetAppPath(const base::FilePath& app_path) { app_path_ = app_path; } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 4b09d77031..78871f6920 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -70,7 +70,7 @@ class App : public AtomBrowserClient::Delegate, std::unique_ptr model); #endif - std::string GetAppPath(); + base::FilePath GetAppPath(); protected: explicit App(v8::Isolate* isolate); @@ -117,7 +117,7 @@ class App : public AtomBrowserClient::Delegate, void OnGpuProcessCrashed(base::TerminationStatus status) override; private: - void SetAppPath(const std::string& app_path); + void SetAppPath(const base::FilePath& app_path); // Get/Set the pre-defined path in PathService. base::FilePath GetPath(mate::Arguments* args, const std::string& name); @@ -158,7 +158,7 @@ class App : public AtomBrowserClient::Delegate, // Tracks tasks requesting file icons. base::CancelableTaskTracker cancelable_task_tracker_; - std::string app_path_; + base::FilePath app_path_; DISALLOW_COPY_AND_ASSIGN(App); }; diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 3908c9613a..db33e2e38f 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -236,7 +236,7 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches( if (delegate_) { auto app_path = static_cast(delegate_)->GetAppPath(); - command_line->AppendSwitchASCII(switches::kAppPath, app_path); + command_line->AppendSwitchPath(switches::kAppPath, app_path); } content::WebContents* web_contents = GetWebContentsFromProcessID(process_id); From ed20cc0af826b9b3c317b0a1182f8f7e64e569b8 Mon Sep 17 00:00:00 2001 From: ZhangYu Date: Thu, 13 Apr 2017 10:27:32 +0800 Subject: [PATCH 11/80] Update shell.md --- docs-translations/zh-CN/api/shell.md | 44 +++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/docs-translations/zh-CN/api/shell.md b/docs-translations/zh-CN/api/shell.md index 1f36046b1e..22fa0d1cd1 100644 --- a/docs-translations/zh-CN/api/shell.md +++ b/docs-translations/zh-CN/api/shell.md @@ -1,4 +1,7 @@ # shell +> 使用系统默认应用管理文件和 URL . + +进程: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process) `shell` 模块提供了集成其他桌面客户端的关联功能. @@ -11,7 +14,7 @@ const {shell} = require('electron') shell.openExternal('https://github.com') ``` -## Methods +## 方法 `shell` 模块包含以下函数: @@ -19,27 +22,60 @@ shell.openExternal('https://github.com') * `fullPath` String -打开文件所在文件夹,一般情况下还会选中它. +Returns `Boolean` - +是否成功打开文件所在文件夹,一般情况下还会选中它. ### `shell.openItem(fullPath)` * `fullPath` String -以默认打开方式打开文件. +Returns `Boolean` - 是否成功的以默认打开方式打开文件. + ### `shell.openExternal(url)` * `url` String +* `options` Object (可选) _macOS_ + * `activate` Boolean - `true` 让打开的应用在前面显示,默认为 `true`. +* `callback` Function (可选) - 如果指定将执行异步打开. _macOS_ + * `error` Error -以系统默认设置打开外部协议.(例如,mailto: somebody@somewhere.io会打开用户默认的邮件客户端) +Returns `Boolean` - 应用程序是否打开URL.如果指定了 callback 回调方法, 则返回 true. + +以系统默认设置打开外部协议.(例如,mailto: URLs 会打开用户默认的邮件客户端) ### `shell.moveItemToTrash(fullPath)` * `fullPath` String +Returns `Boolean` - 文件是否成功移动到垃圾桶 + 删除指定路径文件,并返回此操作的状态值(boolean类型). ### `shell.beep()` 播放 beep 声音. + +### `shell.writeShortcutLink(shortcutPath[, operation], options)` _Windows_ + +* `shortcutPath` String +* `operation` String (可选) - 默认为 `create`, 可以为下列的值: + * `create` - 创建一个新的快捷方式,如果存在的话会覆盖. + * `update` - 仅在现有快捷方式上更新指定属性. + * `replace` - 覆盖现有的快捷方式,如果快捷方式不存在则会失败. +* `options` [ShortcutDetails](structures/shortcut-details.md) + +Returns `Boolean` - 快捷方式是否成功创建 + +为 `shortcutPath` 创建或更新快捷链接. + +### `shell.readShortcutLink(shortcutPath)` _Windows_ + +* `shortcutPath` String + +Returns [`ShortcutDetails`](structures/shortcut-details.md) + +读取 `shortcutPath` 的快捷连接的信息. + +发生错误时,会抛出异常信息. From ea6890aa5ce178ec993ab805b4e29f174dcb090b Mon Sep 17 00:00:00 2001 From: Ryohei Ikegami Date: Thu, 13 Apr 2017 23:26:42 +0900 Subject: [PATCH 12/80] Use const --- atom/browser/api/atom_api_app.cc | 2 +- atom/browser/api/atom_api_app.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index d8e79171f8..acf7ce8c74 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -655,7 +655,7 @@ void App::OnGpuProcessCrashed(base::TerminationStatus status) { status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED); } -base::FilePath App::GetAppPath() { +base::FilePath App::GetAppPath() const { return app_path_; } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 78871f6920..a87b88bc46 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -70,7 +70,7 @@ class App : public AtomBrowserClient::Delegate, std::unique_ptr model); #endif - base::FilePath GetAppPath(); + base::FilePath GetAppPath() const; protected: explicit App(v8::Isolate* isolate); From eee0b35d19a1934d2fb456a1f2eb9d8e66400d82 Mon Sep 17 00:00:00 2001 From: Junyoung Jung Date: Thu, 13 Apr 2017 23:47:01 +0900 Subject: [PATCH 13/80] Update protocol.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 오타 수정, Edit typo --- docs-translations/ko-KR/api/protocol.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/protocol.md b/docs-translations/ko-KR/api/protocol.md index dc3bb51ba2..38a17bed14 100644 --- a/docs-translations/ko-KR/api/protocol.md +++ b/docs-translations/ko-KR/api/protocol.md @@ -1,6 +1,6 @@ # protocol -> 커스텀 프로토콜을 등록하거나 이미 존재하능 프로토콜의 요청의 동작을 변경합니다. +> 커스텀 프로토콜을 등록하거나 이미 존재하는 프로토콜의 요청의 동작을 변경합니다. 프로세스: [메인](../tutorial/quick-start.md#main-process) From 228517edde1e61f1dae93ad70dbfe6cca38f5c2c Mon Sep 17 00:00:00 2001 From: "Mustafa C. Izol" Date: Fri, 14 Apr 2017 19:38:46 +0200 Subject: [PATCH 14/80] add turkish quick start file --- .../tr-TR/tutorial/quick-start.md | 252 ++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 docs-translations/tr-TR/tutorial/quick-start.md diff --git a/docs-translations/tr-TR/tutorial/quick-start.md b/docs-translations/tr-TR/tutorial/quick-start.md new file mode 100644 index 0000000000..1941060df2 --- /dev/null +++ b/docs-translations/tr-TR/tutorial/quick-start.md @@ -0,0 +1,252 @@ +# Hızlı Başlangıç + +Electron, zengin native(işletim sistemi) API runtime sağlayarak, saf Javascript +ile masaüstü uygulamalar geliştirmenize yarar. Electron'u Node.js in, web serverları +yerine masaüstü uygulamalara odaklanmış bir variyasyonu olarak kabul edebilirsiniz. + +Bu Electronun, grafik kullanıcı arayüzüne bir JavaScript bağlantısı olduğu +anlamına gelmez. Aksine, Electron web sayfalarını GUI'si olarak kullanır, +yani onu Javascript tarafından kontrol edilen bir minimal Chromium tarayıcısı +olarak görebilirsiniz. + +### Ana İşlem + +Electron da, `package.json` nun `main` skriptini cağıran işlem _the main process__ dir. +Ana işlemde çalışan bu script, GUI'yi web sayfalarını oluşturarak gösterebilir. + +### Render İşlemi + +Electron, web sayfalarını görüntülemek için Chromium kullandığından, +aynı zamanda Chromiumun multi-işlem mimarisinide kullanmaktadır. +Electron da calıştırılan her web sayfası, __the renderer process__ +adı altında kendi işlemlerini çalıştırırlar. + +Normal tarayıcılarda, web sayfaları genellikle korumalı bir ortamda çalışır ve +yerel kaynaklara erişmesine izin verilmez. Bununla birlikte, elektron kullanıcıları, +alt düzey işletim sistemi etkileşimlerine izin veren web sayfalarında +Node.js API'lerini kullanma imkanina sahiplerdir. + +### Ana işlem ile render işlemi arasındaki farklar + +Ana işlem, `BrowserWindow` örneklerini oluşturarak, web sayfalarını hazır +hale getirir. Her bir `BrowserWindow` örneği web sayfasını kendi render +işleminde çalıştırır. Eger bir `BrowserWindow` örneği ortadan kaldırıldıysa, +bununla bağlantılı olan render işlemide aynı şekilde sonlandırılır. + +Ana işlem tüm web sayfaları ve onların ilgili olduğu render işlemlerini yönetir. +Her bir render işlemi izole edilmiş ve sadece kendisinde çalışan web sayfasıyla ilgilenir. + +Native GUI ile çalışan API ları web sayfalarında çalıştırmaya izin verilmemektedir, +çünkü native GUI kaynaklarının web sayfalarında yönetimi çok tehlikeli ve +kaynakların sızdırılması gayet kolaydır. Eğer GUI operasyonlarını bir web sayfasinda +gerçekleştirmek istiyorsanız, web sayfasının render işlemi, ana işlem ile, bu tür +işlemleri gerçekleştirilmesini talep etmek için kommunikasyon halinde olmalı. + +Electron da ana işlem ve render işlemi arasında birden fazla kommunikasyon yolu vardır. +[`ipcRenderer`](../api/ipc-renderer.md) gibi ve mesaj gönderimi icin +[`ipcMain`](../api/ipc-main.md) modülleri, RPC tarzında kommunikasyon +için ise [remote](../api/remote.md) modülü barındırmakta. +Ayrıca SSS başlıkları [how to share data between web pages][share-data] adresinde bulunabilir. + +## İlk Electron uygulamanızı yazın + +Electron uygulaması genellikle aşağıdaki gibi yapılandırılmıştır: + +```text +your-app/ +├── package.json +├── main.js +└── index.html +``` + +`package.json` dosyasının formatı tamamen Node modüllerine benzer veya aynıdır ve +`main` şeklinde adlandırılmış script uygulamanızı başlatan komut dosyasıdır, +bu komut dosyası daha sonra main process'i çalıştıracak dosyadır. +`package.json` dosyasınızın bir örneği aşağıdaki gibi olabilir: + + +```json +{ + "name" : "your-app", + "version" : "0.1.0", + "main" : "main.js" +} +``` + +__Note__: Eğer `package.json` dosyasında `main` kısmı bulunmuyorsa, Electron standart olarak +`index.js` dosyasını cağıracaktır. + +`main.js` dosyası pencereleri oluşturur, sistem durumlarını handle eder, tipik bir +örnek asağıdaki gibidir: + +```javascript +const {app, BrowserWindow} = require('electron') +const path = require('path') +const url = require('url') + +// Pencere objesini daima global referans olarak tanımla, aksi takdirde, +// eğer JavaScript objesi gereksiz veriler toplayacağı için, pencere +// otomatik olarak kapanacaktır. + +let win + +function createWindow () { + // Tarayıcı pencerelerini oluşturur. + win = new BrowserWindow({width: 800, height: 600}) + + // ve uygulamanın index.html sayfasını yükler. + win.loadURL(url.format({ + pathname: path.join(__dirname, 'index.html'), + protocol: 'file:', + slashes: true + })) + + // DevTools her uygulama başlatıldığında açılır. + + win.webContents.openDevTools() + + // Pencere kapandıktan sonra çağrılacaktır. + win.on('closed', () => { + // Dereference the window object, usually you would store windows + // in an array if your app supports multi windows, this is the time + // when you should delete the corresponding element. + win = null + }) +} + +// Bu metod Electronun başlatılması tamamlandıktan sonra +// çagrılacak ve yeni tarayıcı pencereleri açmaya hazır hale gelecektir. +// Bazı API lar sadece bu event gerçekleştikten sonra kullanılabilir. + +app.on('ready', createWindow) + +// Eğer tüm pencereler kapandıysa, çıkış yap. + +app.on('window-all-closed', () => { + // On macOS it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== 'darwin') { + app.quit() + } +}) + +app.on('activate', () => { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (win === null) { + createWindow() + } +}) + +// Bu sayfada, uygulamanızın spesifik main process kodlarını dahil edebilirsiniz. +// Aynı zamanda bu kodları ayrı dosyalar halinde oluştura bilir +// ve buraya require yoluyla ekleye bilirsiniz. + +``` + +Son olarak `index.html` yani göstermek istediğiniz web sayfası: + +```html + + + + + Hello World! + + +

Hello World!

+ We are using node , + Chrome , + and Electron . + + +``` + +## Uygulamanızı çalıştırın + +`main.js`, `index.html`, ve `package.json` dosyalarını oluşturduktan sonra, +uygulamanızı lokal olarak test ederek, doğru çalışıp çalışmadığını +test etmek isteye bilirsiniz. O halde aşağıdaki yönergeleri takip edin: + +### `electron` + +[`electron`](https://github.com/electron-userland/electron-prebuilt), +Electron'un pre-compiled versiyonunu içeren bir `npm` modülüdür. + + +Eğer bunu global olarak `npm` yoluyla yüklediyseniz, o halde sadece aşağıdaki komutu +uygulamanızın kaynak klasöründe çalıstırmanız yeterlidir: + +```bash +electron . +``` + +Eğer lokal olarak yüklediyseniz, o zaman aşağıda ki gibi +çalıştırın: + +#### macOS / Linux + +```bash +$ ./node_modules/.bin/electron . +``` + +#### Windows + +```bash +$ .\node_modules\.bin\electron . +``` + +### Manuel olarak indirilmiş Electron mimarisi + +Eğer Electronu manuel olarak indirdiyseniz, aynı zamanda dahili olan +mimariyide kullanarak, uygulamanızı çalıştıra bilirsiniz. + +#### Windows + +```bash +$ .\electron\electron.exe your-app\ +``` + +#### Linux + +```bash +$ ./electron/electron your-app/ +``` + +#### macOS + +```bash +$ ./Electron.app/Contents/MacOS/Electron your-app/ +``` + +`Electron.app` Electron un dağı₺tım paketinin bir parçasıdır, +bunu [adresinden](https://github.com/electron/electron/releases) indirebilirsiniz. + +### Dağıtım olarak çalıştır + +Uygulamanızı yazdıktan sonra, bir dağıtım oluşturmak için +[Application Distribution](./application-distribution.md) +sayfasında ki yönergeleri izleyin ve daha sonra arşivlenmiş uygulamayı çalıştırın. + +### Örneği deneyin + +[`electron/electron-quick-start`](https://github.com/electron/electron-quick-start) repository klonlayarak bu eğitimdeki kodu çalıştıra bilirsiniz. + +**Note**: Bu işlemleri uygulamak için [Git](https://git-scm.com) ve [Node.js](https://nodejs.org/en/download/) ([npm](https://npmjs.org) da bununla birlikte gelir) sisteminizde yüklü olması gerekmektedir. + +```bash +# Repository klonla +$ git clone https://github.com/electron/electron-quick-start +# Electron repositorye git +$ cd electron-quick-start +# Gerekli kütüphaneleri yükle +$ npm install +# Uygulamayı çalıştır +$ npm start +``` + +Daha fazla örnek uygulama için, harika electron topluluğu tarafından oluşturulan, +[list of boilerplates](https://electron.atom.io/community/#boilerplates) +sayfasını ziyaret edin. + +[share-data]: ../faq.md#how-to-share-data-between-web-pages From 7b3f1b5d91c77f0c6e38fda34c5d3fed5f587825 Mon Sep 17 00:00:00 2001 From: "Mustafa C. Izol" Date: Fri, 14 Apr 2017 19:47:39 +0200 Subject: [PATCH 15/80] update link to turkish quick-start --- docs-translations/tr-TR/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/tr-TR/README.md b/docs-translations/tr-TR/README.md index a3487d298a..ac11a02f4d 100644 --- a/docs-translations/tr-TR/README.md +++ b/docs-translations/tr-TR/README.md @@ -23,7 +23,7 @@ Bir problem(issue) bildirmeden önce sıkça sorulan sorulara göz atın: ## Eğitimler -* [Quick Start](https://github.com/electron/electron/tree/master/docs/tutorial/quick-start.md) +* [Hızlı Başlangıç](tutorial/quick-start.md) * [Desktop Environment Integration](https://github.com/electron/electron/tree/master/docs/tutorial/desktop-environment-integration.md) * [Online/Offline Event Detection](https://github.com/electron/electron/tree/master/docs/tutorial/online-offline-events.md) From 75184046f6c6cc3af31e8a086694d4f11cef0486 Mon Sep 17 00:00:00 2001 From: Yuya Ochiai Date: Tue, 4 Apr 2017 01:44:26 +0900 Subject: [PATCH 16/80] Add events to manage sheets of macOS BrowserWindow --- atom/browser/api/atom_api_window.cc | 10 ++++++ atom/browser/api/atom_api_window.h | 5 +++ atom/browser/native_window.cc | 12 +++++++ atom/browser/native_window.h | 5 +++ atom/browser/native_window_mac.mm | 8 +++++ atom/browser/native_window_observer.h | 5 +++ docs/api/browser-window.md | 8 +++++ spec/api-browser-window-spec.js | 48 +++++++++++++++++++++++++++ 8 files changed, 101 insertions(+) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index c670762491..573d0215d2 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -298,6 +298,16 @@ void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) { } #endif +#if defined(OS_MACOSX) +void Window::OnWindowSheetBegin() { + Emit("sheet-begin"); +} + +void Window::OnWindowSheetEnd() { + Emit("sheet-end"); +} +#endif + // static mate::WrappableBase* Window::New(mate::Arguments* args) { if (!Browser::Get()->is_ready()) { diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index d464af58ea..79e757833e 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -93,6 +93,11 @@ class Window : public mate::TrackableObject, void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override; #endif + #if defined(OS_MACOSX) + void OnWindowSheetBegin() override; + void OnWindowSheetEnd() override; + #endif + private: void Init(v8::Isolate* isolate, v8::Local wrapper, diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 316cc8dc2e..eec00996de 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -590,6 +590,18 @@ void NativeWindow::NotifyWindowMessage( } #endif +#if defined(OS_MACOSX) +void NativeWindow::NotifyWindowSheetBegin() { + for (NativeWindowObserver& observer : observers_) + observer.OnWindowSheetBegin(); +} + +void NativeWindow::NotifyWindowSheetEnd() { + for (NativeWindowObserver& observer : observers_) + observer.OnWindowSheetEnd(); +} +#endif + std::unique_ptr NativeWindow::DraggableRegionsToSkRegion( const std::vector& regions) { std::unique_ptr sk_region(new SkRegion); diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 56702daef6..83ac0e521f 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -245,6 +245,11 @@ class NativeWindow : public base::SupportsUserData, void NotifyWindowMessage(UINT message, WPARAM w_param, LPARAM l_param); #endif + #if defined(OS_MACOSX) + void NotifyWindowSheetBegin(); + void NotifyWindowSheetEnd(); + #endif + void AddObserver(NativeWindowObserver* obs) { observers_.AddObserver(obs); } diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index b695f8eafa..9dc119e239 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -313,6 +313,14 @@ bool ScopedDisableResize::disable_resize_ = false; return rect; } +- (void)windowWillBeginSheet:(NSNotification *)notification { + shell_->NotifyWindowSheetBegin(); +} + +- (void)windowDidEndSheet:(NSNotification *)notification { + shell_->NotifyWindowSheetEnd(); +} + @end @interface AtomPreviewItem : NSObject diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 3b8d86e6fb..3235976e24 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -79,6 +79,11 @@ class NativeWindowObserver { virtual void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {} #endif + #if defined(OS_MACOSX) + virtual void OnWindowSheetBegin() {} + virtual void OnWindowSheetEnd() {} + #endif + // Called when renderer is hung. virtual void OnRendererUnresponsive() {} diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 2c720fdfac..cd55ba0bbd 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -498,6 +498,14 @@ Returns: Emitted on 3-finger swipe. Possible directions are `up`, `right`, `down`, `left`. +#### Event: 'sheet-begin' _macOS_ + +Emitted when the window opens a sheet. + +#### Event: 'sheet-end' _macOS_ + +Emitted when the window has closed a sheet. + ### Static Methods The `BrowserWindow` class has the following static methods: diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index d83c173f26..eb5e1bd957 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -1191,6 +1191,54 @@ describe('BrowserWindow module', function () { }) }) + describe('sheet-begin event', function () { + if (process.platform !== 'darwin') { + return + } + + let sheet = null + + afterEach(function () { + return closeWindow(sheet, {assertSingleWindow: false}).then(function () { sheet = null }) + }) + + it('emits when window opens a sheet', function (done) { + w.show() + w.once('sheet-begin', function () { + sheet.close() + done() + }) + sheet = new BrowserWindow({ + modal: true, + parent: w + }) + }) + }) + + describe('sheet-end event', function () { + if (process.platform !== 'darwin') { + return + } + + let sheet = null + + afterEach(function () { + return closeWindow(sheet, {assertSingleWindow: false}).then(function () { sheet = null }) + }) + + it('emits when window has closed a sheet', function (done) { + w.show() + sheet = new BrowserWindow({ + modal: true, + parent: w + }) + w.once('sheet-end', function () { + done() + }) + sheet.close() + }) + }) + describe('beginFrameSubscription method', function () { // This test is too slow, only test it on CI. if (!isCI) return From 39caa6ad2339ea35360091ba1c8231325942c931 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 17 Apr 2017 14:37:05 +0700 Subject: [PATCH 17/80] :memo: Add docs tip about testing Touch Bar usage Disclosure: I made it. Most devs don't have the new MacBook with Touch Bar, but would like to support it. I think it would be useful to point out how to easily develop and test Touch Bar usage in Electron apps. [ci skip] --- docs/api/touch-bar.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/api/touch-bar.md b/docs/api/touch-bar.md index 7ac578da46..0a0827a2b2 100644 --- a/docs/api/touch-bar.md +++ b/docs/api/touch-bar.md @@ -16,6 +16,10 @@ Creates a new touch bar with the specified items. Use **Note:** The TouchBar API is currently experimental and may change or be removed in future Electron releases. +**Tip:** If you don't have a MacBook with Touch Bar, you can use +[Touch Bar Simulator](https://github.com/sindresorhus/touch-bar-simulator) +to test Touch Bar usage in your app. + ### Instance Properties The following properties are available on instances of `TouchBar`: From 11c7c107a958f3de2bbb7f6df4f5340e8c40ef03 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 17 Apr 2017 12:26:33 +1200 Subject: [PATCH 18/80] add iconPosition property to touch bar buttons --- atom/browser/ui/cocoa/atom_touch_bar.mm | 9 +++++++++ docs/api/touch-bar-button.md | 1 + lib/browser/api/touch-bar.js | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/atom/browser/ui/cocoa/atom_touch_bar.mm b/atom/browser/ui/cocoa/atom_touch_bar.mm index a3e846df48..95f36cf02d 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.mm +++ b/atom/browser/ui/cocoa/atom_touch_bar.mm @@ -307,9 +307,18 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item"; settings.Get("label", &label); button.title = base::SysUTF8ToNSString(label); + std::string iconPosition = "left"; + settings.Get("iconPosition", &iconPosition); gfx::Image image; if (settings.Get("icon", &image)) { button.image = image.AsNSImage(); + if (iconPosition == "overlay") { + button.imagePosition = NSImageOverlaps; + } else if (iconPosition == "right") { + button.imagePosition = NSImageRight; + } else { + button.imagePosition = NSImageLeft; + } } } diff --git a/docs/api/touch-bar-button.md b/docs/api/touch-bar-button.md index 177e51bcdb..456fc207fe 100644 --- a/docs/api/touch-bar-button.md +++ b/docs/api/touch-bar-button.md @@ -11,6 +11,7 @@ Process: [Main](../tutorial/quick-start.md#main-process) * `backgroundColor` String (optional) - Button background color in hex format, i.e `#ABCDEF`. * `icon` [NativeImage](native-image.md) (optional) - Button icon. + * `iconPosition` String - Can be `left`, `right` or `overlay`. * `click` Function (optional) - Function to call when the button is clicked. ### Instance Properties diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index 1a9c3238a9..4bb129449e 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -159,10 +159,11 @@ TouchBar.TouchBarButton = class TouchBarButton extends TouchBarItem { super() if (config == null) config = {} this.type = 'button' - const {click, icon, label, backgroundColor} = config + const {click, icon, iconPosition, label, backgroundColor} = config this._addLiveProperty('label', label) this._addLiveProperty('backgroundColor', backgroundColor) this._addLiveProperty('icon', icon) + this._addLiveProperty('iconPosition', iconPosition) if (typeof click === 'function') { this.onInteraction = () => { config.click() From 526d287d25787f657b015c9f379ee51339de2cb3 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 17 Apr 2017 12:30:55 +1200 Subject: [PATCH 19/80] Make iconPosition non-breaking by defaulting to overlay --- atom/browser/ui/cocoa/atom_touch_bar.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/atom/browser/ui/cocoa/atom_touch_bar.mm b/atom/browser/ui/cocoa/atom_touch_bar.mm index 95f36cf02d..97eebf73f6 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.mm +++ b/atom/browser/ui/cocoa/atom_touch_bar.mm @@ -307,17 +307,17 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item"; settings.Get("label", &label); button.title = base::SysUTF8ToNSString(label); - std::string iconPosition = "left"; + std::string iconPosition = "overlay"; settings.Get("iconPosition", &iconPosition); gfx::Image image; if (settings.Get("icon", &image)) { button.image = image.AsNSImage(); - if (iconPosition == "overlay") { - button.imagePosition = NSImageOverlaps; + if (iconPosition == "left") { + button.imagePosition = NSImageLeft; } else if (iconPosition == "right") { button.imagePosition = NSImageRight; } else { - button.imagePosition = NSImageLeft; + button.imagePosition = NSImageOverlaps; } } } From c32a723e2906de3741bf5abd95234e7efdb1703b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 18 Apr 2017 08:58:54 -0700 Subject: [PATCH 20/80] Only read iconPosition when icon is present --- atom/browser/ui/cocoa/atom_touch_bar.mm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/atom/browser/ui/cocoa/atom_touch_bar.mm b/atom/browser/ui/cocoa/atom_touch_bar.mm index 97eebf73f6..a21fbc5497 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.mm +++ b/atom/browser/ui/cocoa/atom_touch_bar.mm @@ -307,17 +307,18 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item"; settings.Get("label", &label); button.title = base::SysUTF8ToNSString(label); - std::string iconPosition = "overlay"; - settings.Get("iconPosition", &iconPosition); gfx::Image image; if (settings.Get("icon", &image)) { button.image = image.AsNSImage(); + + std::string iconPosition; + settings.Get("iconPosition", &iconPosition); if (iconPosition == "left") { - button.imagePosition = NSImageLeft; + button.imagePosition = NSImageLeft; } else if (iconPosition == "right") { - button.imagePosition = NSImageRight; + button.imagePosition = NSImageRight; } else { - button.imagePosition = NSImageOverlaps; + button.imagePosition = NSImageOverlaps; } } } From ca46d52b0c9b1f43c0b5daf877bef774fc74cc29 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 18 Apr 2017 09:01:43 -0700 Subject: [PATCH 21/80] Add button with icon to touch bar spec --- spec/api-touch-bar-spec.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index 420ef3fc7b..6177e3cb85 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -1,4 +1,5 @@ const assert = require('assert') +const path = require('path') const {BrowserWindow, TouchBar} = require('electron').remote const {closeWindow} = require('./window-helpers') @@ -48,6 +49,11 @@ describe('TouchBar module', function () { const label = new TouchBarLabel({label: 'bar'}) const touchBar = new TouchBar([ new TouchBarButton({label: 'foo', backgroundColor: '#F00', click: () => {}}), + new TouchBarButton({ + icon: path.join(__dirname, 'fixtures', 'assets', 'logo.png'), + iconPosition: 'right', + click: () => {} + }), new TouchBarColorPicker({selectedColor: '#F00', change: () => {}}), new TouchBarGroup({items: new TouchBar([new TouchBarLabel({label: 'hello'})])}), label, From 19709a50e9490cb1add345ba614de2c61ce6fab9 Mon Sep 17 00:00:00 2001 From: Hari Krishna Reddy Juturu Date: Fri, 14 Apr 2017 06:12:22 -0700 Subject: [PATCH 22/80] Adding cookie flush store api --- atom/browser/api/atom_api_cookies.cc | 16 +++++++++++++++- atom/browser/api/atom_api_cookies.h | 1 + docs/api/cookies.md | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_cookies.cc b/atom/browser/api/atom_api_cookies.cc index ddb6910b50..d3607fe502 100644 --- a/atom/browser/api/atom_api_cookies.cc +++ b/atom/browser/api/atom_api_cookies.cc @@ -179,6 +179,12 @@ void OnSetCookie(const Cookies::SetCallback& callback, bool success) { base::Bind(callback, success ? Cookies::SUCCESS : Cookies::FAILED)); } +// Flushes cookie store in IO thread. +void FlushCookieStoreOnIOThread(scoped_refptr getter, + const base::Closure& callback) { + GetCookieStore(getter)->FlushStore(base::Bind(RunCallbackInUI, callback)); +} + // Sets cookie with |details| in IO thread. void SetCookieOnIO(scoped_refptr getter, std::unique_ptr details, @@ -265,6 +271,13 @@ void Cookies::Set(const base::DictionaryValue& details, base::Bind(SetCookieOnIO, getter, Passed(&copied), callback)); } +void Cookies::FlushStore(const base::Closure& callback) { + auto getter = make_scoped_refptr(request_context_getter_); + content::BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(FlushCookieStoreOnIOThread, getter, callback)); +} + void Cookies::OnCookieChanged(const net::CanonicalCookie& cookie, bool removed, net::CookieStore::ChangeCause cause) { @@ -286,7 +299,8 @@ void Cookies::BuildPrototype(v8::Isolate* isolate, mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("get", &Cookies::Get) .SetMethod("remove", &Cookies::Remove) - .SetMethod("set", &Cookies::Set); + .SetMethod("set", &Cookies::Set) + .SetMethod("flushStore", &Cookies::FlushStore); } } // namespace api diff --git a/atom/browser/api/atom_api_cookies.h b/atom/browser/api/atom_api_cookies.h index 3a7a98fbaf..d20dab8394 100644 --- a/atom/browser/api/atom_api_cookies.h +++ b/atom/browser/api/atom_api_cookies.h @@ -53,6 +53,7 @@ class Cookies : public mate::TrackableObject, void Remove(const GURL& url, const std::string& name, const base::Closure& callback); void Set(const base::DictionaryValue& details, const SetCallback& callback); + void FlushStore(const base::Closure& callback); // AtomCookieDelegate::Observer: void OnCookieChanged(const net::CanonicalCookie& cookie, diff --git a/docs/api/cookies.md b/docs/api/cookies.md index 8e64202967..060034a16c 100644 --- a/docs/api/cookies.md +++ b/docs/api/cookies.md @@ -104,3 +104,7 @@ on complete. Removes the cookies matching `url` and `name`, `callback` will called with `callback()` on complete. + +#### `cookies.flushStore()` + +Writes any unwritten cookies data to disk. From efca0a6e07434dddebd7fa50d90824ad52554cef Mon Sep 17 00:00:00 2001 From: Hari Krishna Reddy Juturu Date: Fri, 14 Apr 2017 10:03:52 -0700 Subject: [PATCH 23/80] fixup! Adding cookie flush store api --- docs/api/cookies.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/api/cookies.md b/docs/api/cookies.md index 060034a16c..ba3cff3360 100644 --- a/docs/api/cookies.md +++ b/docs/api/cookies.md @@ -105,6 +105,8 @@ on complete. Removes the cookies matching `url` and `name`, `callback` will called with `callback()` on complete. -#### `cookies.flushStore()` +#### `cookies.flushStore(callback)` + +* `callback` Function Writes any unwritten cookies data to disk. From fe88697348a88b975564afb1b89795d58af77cf8 Mon Sep 17 00:00:00 2001 From: Hari Krishna Reddy Juturu Date: Mon, 17 Apr 2017 04:37:10 -0700 Subject: [PATCH 24/80] fixup! fixup! Adding cookie flush store api --- atom/browser/api/atom_api_cookies.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_cookies.cc b/atom/browser/api/atom_api_cookies.cc index d3607fe502..2ce9e12f6c 100644 --- a/atom/browser/api/atom_api_cookies.cc +++ b/atom/browser/api/atom_api_cookies.cc @@ -180,8 +180,9 @@ void OnSetCookie(const Cookies::SetCallback& callback, bool success) { } // Flushes cookie store in IO thread. -void FlushCookieStoreOnIOThread(scoped_refptr getter, - const base::Closure& callback) { +void FlushCookieStoreOnIOThread( + scoped_refptr getter, + const base::Closure& callback) { GetCookieStore(getter)->FlushStore(base::Bind(RunCallbackInUI, callback)); } From 8f0ac057e303558877cdf9630802b194f44c52a7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 18 Apr 2017 09:08:27 -0700 Subject: [PATCH 25/80] Add initial spec for cookies.flushStore --- spec/api-session-spec.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/spec/api-session-spec.js b/spec/api-session-spec.js index c34cdfdab0..d361c10d94 100644 --- a/spec/api-session-spec.js +++ b/spec/api-session-spec.js @@ -219,6 +219,21 @@ describe('session module', function () { if (error) return done(error) }) }) + + describe('ses.cookies.flushStore(callback)', function () { + it('flushes the cookies to disk and invokes the callback when done', function (done) { + session.defaultSession.cookies.set({ + url: url, + name: 'foo', + value: 'bar' + }, (error) => { + if (error) return done(error) + session.defaultSession.cookies.flushStore(() => { + done() + }) + }) + }) + }) }) describe('ses.clearStorageData(options)', function () { From 4a9383b50bc2f15f42c027d7369e4a8129820cf1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 18 Apr 2017 09:17:16 -0700 Subject: [PATCH 26/80] Bump v1.6.7 --- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- electron.gyp | 2 +- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 5509969014..ecd6a28b5c 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile electron.icns CFBundleVersion - 1.6.6 + 1.6.7 CFBundleShortVersionString - 1.6.6 + 1.6.7 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index d572d20ada..f7a9b32351 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -56,8 +56,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,6,6,0 - PRODUCTVERSION 1,6,6,0 + FILEVERSION 1,6,7,0 + PRODUCTVERSION 1,6,7,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "1.6.6" + VALUE "FileVersion", "1.6.7" 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.6" + VALUE "ProductVersion", "1.6.7" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 3afa163b90..79ece65408 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 1 #define ATOM_MINOR_VERSION 6 -#define ATOM_PATCH_VERSION 6 +#define ATOM_PATCH_VERSION 7 #define ATOM_VERSION_IS_RELEASE 1 diff --git a/electron.gyp b/electron.gyp index 8c3718b1cd..ce3673abf1 100644 --- a/electron.gyp +++ b/electron.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '1.6.6', + 'version%': '1.6.7', 'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c', }, 'includes': [ diff --git a/package.json b/package.json index c34a27e275..bfb35f2968 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "1.6.6", + "version": "1.6.7", "devDependencies": { "asar": "^0.11.0", "browserify": "^13.1.0", From 4af44b1be69abec3dcffc5e6ad060b632c514898 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 18 Apr 2017 16:04:27 -0700 Subject: [PATCH 27/80] Consolidate window closing --- spec/chromium-spec.js | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index a54c6744f7..2f8c24c258 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -13,6 +13,7 @@ const isCI = remote.getGlobal('isCi') describe('chromium feature', function () { var fixtures = path.resolve(__dirname, 'fixtures') var listener = null + let w = null afterEach(function () { if (listener != null) { @@ -21,6 +22,10 @@ describe('chromium feature', function () { listener = null }) + afterEach(function () { + return closeWindow(w).then(function () { w = null }) + }) + describe('heap snapshot', function () { it('does not crash', function () { if (process.env.TRAVIS === 'true') return @@ -44,11 +49,6 @@ describe('chromium feature', function () { describe('document.hidden', function () { var url = 'file://' + fixtures + '/pages/document-hidden.html' - var w = null - - afterEach(function () { - return closeWindow(w).then(function () { w = null }) - }) it('is set correctly when window is not shown', function (done) { w = new BrowserWindow({ @@ -119,7 +119,7 @@ describe('chromium feature', function () { } const deviceIds = [] const ses = session.fromPartition('persist:media-device-id') - let w = new BrowserWindow({ + w = new BrowserWindow({ show: false, webPreferences: { session: ses @@ -155,11 +155,6 @@ describe('chromium feature', function () { describe('navigator.serviceWorker', function () { var url = 'file://' + fixtures + '/pages/service-worker/index.html' - var w = null - - afterEach(function () { - return closeWindow(w).then(function () { w = null }) - }) it('should register for file scheme', function (done) { w = new BrowserWindow({ @@ -188,12 +183,6 @@ describe('chromium feature', function () { return } - let w = null - - afterEach(() => { - return closeWindow(w).then(function () { w = null }) - }) - it('returns a BrowserWindowProxy object', function () { var b = window.open('about:blank', '', 'show=no') assert.equal(b.closed, false) @@ -343,11 +332,6 @@ describe('chromium feature', function () { describe('window.opener', function () { let url = 'file://' + fixtures + '/pages/window-opener.html' - let w = null - - afterEach(function () { - return closeWindow(w).then(function () { w = null }) - }) it('is null for main window', function (done) { w = new BrowserWindow({ @@ -849,7 +833,6 @@ describe('chromium feature', function () { }) describe('PDF Viewer', function () { - let w = null const pdfSource = url.format({ pathname: path.join(fixtures, 'assets', 'cat.pdf').replace(/\\/g, '/'), protocol: 'file', @@ -865,10 +848,6 @@ describe('chromium feature', function () { }) }) - afterEach(function () { - return closeWindow(w).then(function () { w = null }) - }) - it('opens when loading a pdf resource as top level navigation', function (done) { ipcMain.once('pdf-loaded', function (event, success) { if (success) done() From f891df55d443eb425769753d186920123da505e1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 18 Apr 2017 16:06:10 -0700 Subject: [PATCH 28/80] Call done callback with Error --- spec/chromium-spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 2f8c24c258..a67c109a5e 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -107,7 +107,7 @@ describe('chromium feature', function () { if (labelFound) { done() } else { - done('No device labels found: ' + JSON.stringify(labels)) + done(new Error(`No device labels found: ${JSON.stringify(labels)}`)) } }).catch(done) }) From 5153c1f353b093c929affad9ef02e5e5df5159d6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 18 Apr 2017 16:16:08 -0700 Subject: [PATCH 29/80] Disable media device specs on CI where they may not be available --- spec/chromium-spec.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index a67c109a5e..6a5937bbce 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -90,13 +90,7 @@ describe('chromium feature', function () { }) describe('navigator.mediaDevices', function () { - if (process.env.TRAVIS === 'true') { - return - } - if (isCI && process.platform === 'linux') { - return - } - if (isCI && process.platform === 'win32') { + if (isCI) { return } From 6b13fab83a32462c93163c17bdf3074516640df8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 18 Apr 2017 16:42:01 -0700 Subject: [PATCH 30/80] Wait for full screen event before leaving kiosk mode --- spec/api-browser-window-spec.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index d83c173f26..a50ff0bc0d 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -1474,13 +1474,19 @@ describe('BrowserWindow module', function () { // Only implemented on macOS. if (process.platform !== 'darwin') return - it('can be changed with setKiosk method', function () { + it('can be changed with setKiosk method', function (done) { w.destroy() w = new BrowserWindow() w.setKiosk(true) assert.equal(w.isKiosk(), true) - w.setKiosk(false) - assert.equal(w.isKiosk(), false) + + w.once('enter-full-screen', () => { + w.setKiosk(false) + assert.equal(w.isKiosk(), false) + }) + w.once('leave-full-screen', () => { + done() + }) }) }) From c05c324464cfe72439b2573ff3c8adfff44ed54a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 19 Apr 2017 09:28:52 -0700 Subject: [PATCH 31/80] Remove extra space in description --- spec/api-crash-reporter-spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index a0fde2d54f..b5ae5ae8a7 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -176,7 +176,7 @@ describe('crashReporter module', function () { } generateSpecs('without sandbox', {}) - generateSpecs('with sandbox ', { + generateSpecs('with sandbox', { webPreferences: { sandbox: true, preload: path.join(fixtures, 'module', 'preload-sandbox.js') From ece4df0ac7b23d4d9c6324862be8a8ff99e2ac7e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 19 Apr 2017 09:30:03 -0700 Subject: [PATCH 32/80] Increase timeout to 2 minutes --- spec/api-crash-reporter-spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index b5ae5ae8a7..8e22c8a1e0 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -157,7 +157,7 @@ describe('crashReporter module', function () { if (process.env.APPVEYOR === 'True') return done() if (process.env.TRAVIS === 'true') return done() - this.timeout(10000) + this.timeout(120000) startServer({ callback (port) { From 4d9cdad37a8c1832491127958608f09f84e5e105 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 19 Apr 2017 09:48:32 -0700 Subject: [PATCH 33/80] Close server and connections after each spec --- spec/api-crash-reporter-spec.js | 38 ++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index 8e22c8a1e0..ca30cacb7f 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -33,8 +33,10 @@ describe('crashReporter module', function () { const generateSpecs = (description, browserWindowOpts) => { describe(description, function () { var w = null + var stopServer = null beforeEach(function () { + stopServer = null w = new BrowserWindow(Object.assign({ show: false }, browserWindowOpts)) @@ -44,13 +46,19 @@ describe('crashReporter module', function () { return closeWindow(w).then(function () { w = null }) }) + afterEach(function (done) { + if (stopServer != null) { + stopServer(done) + } + }) + it('should send minidump when renderer crashes', function (done) { if (process.env.APPVEYOR === 'True') return done() if (process.env.TRAVIS === 'true') return done() this.timeout(120000) - startServer({ + stopServer = startServer({ callback (port) { const crashUrl = url.format({ protocol: 'file', @@ -70,7 +78,7 @@ describe('crashReporter module', function () { this.timeout(120000) - startServer({ + stopServer = startServer({ callback (port) { const crashesDir = path.join(app.getPath('temp'), `${app.getName()} Crashes`) const version = app.getVersion() @@ -85,7 +93,6 @@ describe('crashReporter module', function () { it('should not send minidump if uploadToServer is false', function (done) { this.timeout(120000) - let server let dumpFile let crashesDir = crashReporter.getCrashesDirectory() const existingDumpFiles = new Set() @@ -98,7 +105,6 @@ describe('crashReporter module', function () { if (uploaded) { return done(new Error('fail')) } - server.close() if (process.platform === 'darwin') { crashReporter.setUploadToServer(true) } @@ -139,7 +145,7 @@ describe('crashReporter module', function () { }) }) - server = startServer({ + stopServer = startServer({ callback (port) { const crashUrl = url.format({ protocol: 'file', @@ -159,7 +165,7 @@ describe('crashReporter module', function () { this.timeout(120000) - startServer({ + stopServer = startServer({ callback (port) { const crashUrl = url.format({ protocol: 'file', @@ -254,7 +260,6 @@ const waitForCrashReport = () => { const startServer = ({callback, processType, done}) => { var called = false var server = http.createServer((req, res) => { - server.close() var form = new multiparty.Form() form.parse(req, (error, fields) => { if (error) throw error @@ -283,6 +288,15 @@ const startServer = ({callback, processType, done}) => { }) }) }) + + const activeConnections = new Set() + server.on('connection', (connection) => { + activeConnections.add(connection) + connection.once('close', () => { + activeConnections.delete(connection) + }) + }) + let {port} = remote.process server.listen(port, '127.0.0.1', () => { port = server.address().port @@ -295,5 +309,13 @@ const startServer = ({callback, processType, done}) => { } callback(port) }) - return server + + return function stopServer (done) { + for (const connection of activeConnections) { + connection.destroy() + } + server.close(function () { + done() + }) + } } From a7a92e1cd30b3c4ee1f2040c460bfeb325a5b675 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 19 Apr 2017 09:52:28 -0700 Subject: [PATCH 34/80] Still call done when stop server function is null --- spec/api-crash-reporter-spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index ca30cacb7f..e016b05f1d 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -49,6 +49,8 @@ describe('crashReporter module', function () { afterEach(function (done) { if (stopServer != null) { stopServer(done) + } else { + done() } }) From de62f1ea6cd7015d1c4cf951cbe7f054d87dc0e4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 19 Apr 2017 16:32:43 -0700 Subject: [PATCH 35/80] Restart crash service in each spec --- lib/common/api/crash-reporter.js | 2 +- spec/api-crash-reporter-spec.js | 37 ++++++++++++++++++++++++++-- spec/fixtures/api/crash-restart.html | 6 ++++- spec/fixtures/api/crash.html | 5 ++++ spec/static/main.js | 10 +++++++- 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/lib/common/api/crash-reporter.js b/lib/common/api/crash-reporter.js index 658622e8f5..7a54e24fbc 100644 --- a/lib/common/api/crash-reporter.js +++ b/lib/common/api/crash-reporter.js @@ -56,7 +56,7 @@ class CrashReporter { const env = { ELECTRON_INTERNAL_CRASH_SERVICE: 1 } - spawn(process.execPath, args, { + this._crashServiceProcess = spawn(process.execPath, args, { env: env, detached: true }) diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index e016b05f1d..3ed81c40b1 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -46,6 +46,10 @@ describe('crashReporter module', function () { return closeWindow(w).then(function () { w = null }) }) + afterEach(function () { + stopCrashService() + }) + afterEach(function (done) { if (stopServer != null) { stopServer(done) @@ -82,9 +86,24 @@ describe('crashReporter module', function () { stopServer = startServer({ callback (port) { - const crashesDir = path.join(app.getPath('temp'), `${app.getName()} Crashes`) + const crashesDir = path.join(app.getPath('temp'), `Zombies Crashes`) const version = app.getVersion() const crashPath = path.join(fixtures, 'module', 'crash.js') + + if (process.platform === 'win32') { + const crashServiceProcess = childProcess.spawn(process.execPath, [ + `--reporter-url=http://127.0.0.1:${port}`, + '--application-name=Zombies', + `--crashes-directory=${crashesDir}` + ], { + env: { + ELECTRON_INTERNAL_CRASH_SERVICE: 1 + }, + detached: true + }) + remote.process.crashServicePid = crashServiceProcess.pid + } + childProcess.fork(crashPath, [port, version, crashesDir], {silent: true}) }, processType: 'browser', @@ -105,7 +124,7 @@ describe('crashReporter module', function () { } const testDone = (uploaded) => { if (uploaded) { - return done(new Error('fail')) + return done(new Error('Uploaded crash report')) } if (process.platform === 'darwin') { crashReporter.setUploadToServer(true) @@ -321,3 +340,17 @@ const startServer = ({callback, processType, done}) => { }) } } + +const stopCrashService = () => { + const {crashServicePid} = remote.process + if (crashServicePid) { + remote.process.crashServicePid = 0 + try { + process.kill(crashServicePid) + } catch (error) { + if (error.code !== 'ESRCH') { + throw error + } + } + } +} diff --git a/spec/fixtures/api/crash-restart.html b/spec/fixtures/api/crash-restart.html index 2f55c539bb..22f3b45b5c 100644 --- a/spec/fixtures/api/crash-restart.html +++ b/spec/fixtures/api/crash-restart.html @@ -3,7 +3,7 @@ +
Docs @@ -162,25 +162,15 @@ Console (or Terminal):

- +

 
     

The path-to-your-app should be the path to your own Electron app.

-

You can read the - - guide in Electron's - +

You can read the quick start + guide in Electron's docs to learn how to write one.

@@ -214,6 +204,12 @@ }).unref(); return false; }; + + const version = process.versions.electron; + document.querySelector('.header-version').innerText = version; + document.querySelector('.command-example').innerText = command; + document.querySelector('.quick-start-link').href = `https://github.com/electron/electron/blob/v${version}/docs/tutorial/quick-start.md`; + document.querySelector('.docs-link').href = `https://github.com/electron/electron/tree/v${version}/docs#readme`; From a00d36fb071be1344396ee90279cb5bbadcf9e0e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 21 Apr 2017 12:19:37 -0700 Subject: [PATCH 54/80] Add spec for alert/confirm toString errors --- spec/chromium-spec.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 6a5937bbce..4c5b85521a 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -880,4 +880,28 @@ describe('chromium feature', function () { }) }) }) + + describe('window.alert(message, title)', function () { + it('throws an exception when the arguments cannot be converted to strings', function () { + assert.throws(function () { + window.alert({toString: null}) + }, /Cannot convert object to primitive value/) + + assert.throws(function () { + window.alert('message', {toString: 3}) + }, /Cannot convert object to primitive value/) + }) + }) + + describe('window.confirm(message, title)', function () { + it('throws an exception when the arguments cannot be converted to strings', function () { + assert.throws(function () { + window.confirm({toString: null}, 'title') + }, /Cannot convert object to primitive value/) + + assert.throws(function () { + window.confirm('message', {toString: 3}) + }, /Cannot convert object to primitive value/) + }) + }) }) From c90fd4dc888662599a2f13d60eb39849db926abc Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 21 Apr 2017 12:21:05 -0700 Subject: [PATCH 55/80] Convert message/title to strings in render process --- lib/renderer/window-setup.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/renderer/window-setup.js b/lib/renderer/window-setup.js index 21f0741a22..d29133c88f 100644 --- a/lib/renderer/window-setup.js +++ b/lib/renderer/window-setup.js @@ -121,11 +121,11 @@ module.exports = (ipcRenderer, guestInstanceId, openerId, hiddenPage) => { } window.alert = function (message, title) { - ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_ALERT', message, title) + ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_ALERT', `${message}`, `${title}`) } window.confirm = function (message, title) { - return ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CONFIRM', message, title) + return ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CONFIRM', `${message}`, `${title}`) } // But we do not support prompt(). From 35a627fd603b4f340aa60eaaf397c0dad985b9b2 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 21 Apr 2017 12:29:46 -0700 Subject: [PATCH 56/80] Log all crashes during specs --- spec/static/main.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/spec/static/main.js b/spec/static/main.js index 033a0c5546..7e56da623b 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -2,20 +2,15 @@ process.throwDeprecation = true const electron = require('electron') -const app = electron.app -const crashReporter = electron.crashReporter -const ipcMain = electron.ipcMain -const dialog = electron.dialog -const BrowserWindow = electron.BrowserWindow -const protocol = electron.protocol -const webContents = electron.webContents -const v8 = require('v8') +const {app, BrowserWindow, crashReporter, dialog, ipcMain, protocol, webContents} = electron + +const {Coverage} = require('electabul') -const Coverage = require('electabul').Coverage const fs = require('fs') const path = require('path') const url = require('url') const util = require('util') +const v8 = require('v8') var argv = require('yargs') .boolean('ci') @@ -103,6 +98,12 @@ app.on('window-all-closed', function () { app.quit() }) +app.on('web-contents-created', (event, contents) => { + contents.on('crashed', (event, killed) => { + console.log(`webContents ${contents.id} crashed: ${contents.getURL()} (killed=${killed})`) + }) +}) + app.on('ready', function () { // Test if using protocol module would crash. electron.protocol.registerStringProtocol('test-if-crashes', function () {}) From 423dd4d57aebd8ba83b8a291d95618b71eb5b5e0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 21 Apr 2017 15:12:08 -0700 Subject: [PATCH 57/80] Add spec for remote autoUpdater error event --- spec/api-auto-updater-spec.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/spec/api-auto-updater-spec.js b/spec/api-auto-updater-spec.js index 0716c2245d..3e2be93d13 100644 --- a/spec/api-auto-updater-spec.js +++ b/spec/api-auto-updater-spec.js @@ -1,6 +1,6 @@ const assert = require('assert') -const autoUpdater = require('electron').remote.autoUpdater -const ipcRenderer = require('electron').ipcRenderer +const {autoUpdater} = require('electron').remote +const {ipcRenderer} = require('electron') // Skip autoUpdater tests in MAS build. if (!process.mas) { @@ -64,5 +64,21 @@ if (!process.mas) { autoUpdater.quitAndInstall() }) }) + + describe('error event', function () { + it('serializes correctly over the remote module', function (done) { + autoUpdater.once('error', function (error) { + assert.equal(error instanceof Error, true) + assert.deepEqual(Object.getOwnPropertyNames(error), ['stack', 'message', 'name']) + done() + }) + + autoUpdater.setFeedURL('') + + if (process.platform === 'win32') { + autoUpdater.checkForUpdates() + } + }) + }) }) } From 13e4582697e8df68c8271ac6c813e81ec20722a1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 21 Apr 2017 15:13:43 -0700 Subject: [PATCH 58/80] Emit autoUpdater error directly as Error object --- atom/browser/api/atom_api_auto_updater.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_auto_updater.cc b/atom/browser/api/atom_api_auto_updater.cc index ea3024191e..c23e488f64 100644 --- a/atom/browser/api/atom_api_auto_updater.cc +++ b/atom/browser/api/atom_api_auto_updater.cc @@ -7,6 +7,7 @@ #include "atom/browser/browser.h" #include "atom/browser/native_window.h" #include "atom/browser/window_list.h" +#include "atom/common/api/event_emitter_caller.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/node_includes.h" #include "base/time/time.h" @@ -47,7 +48,9 @@ void AutoUpdater::OnError(const std::string& message) { v8::Locker locker(isolate()); v8::HandleScope handle_scope(isolate()); auto error = v8::Exception::Error(mate::StringToV8(isolate(), message)); - EmitCustomEvent( + mate::EmitEvent( + isolate(), + GetWrapper(), "error", error->ToObject(isolate()->GetCurrentContext()).ToLocalChecked(), // Message is also emitted to keep compatibility with old code. From c2d4c93e12da6af51158bb31fd46f7f6ba261813 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 21 Apr 2017 16:50:19 -0700 Subject: [PATCH 59/80] Don't run error event on Linux --- spec/api-auto-updater-spec.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/api-auto-updater-spec.js b/spec/api-auto-updater-spec.js index 3e2be93d13..df77822e45 100644 --- a/spec/api-auto-updater-spec.js +++ b/spec/api-auto-updater-spec.js @@ -67,6 +67,10 @@ if (!process.mas) { describe('error event', function () { it('serializes correctly over the remote module', function (done) { + if (process.platform === 'linux') { + return done() + } + autoUpdater.once('error', function (error) { assert.equal(error instanceof Error, true) assert.deepEqual(Object.getOwnPropertyNames(error), ['stack', 'message', 'name']) From 9e70372c1fa408946bfbd8339ad65f583d6c9d73 Mon Sep 17 00:00:00 2001 From: Hari Krishna Reddy Juturu Date: Mon, 24 Apr 2017 10:16:11 -0700 Subject: [PATCH 60/80] change endsession event name to session-end --- atom/browser/api/atom_api_window.cc | 2 +- docs/api/browser-window.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 1914899297..95168efe9a 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -193,7 +193,7 @@ void Window::OnWindowClosed() { #if defined(OS_WIN) void Window::OnWindowEndSession() { - Emit("endsession"); + Emit("session-end"); } #endif diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 2147645b21..8fcc3f8213 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -376,7 +376,7 @@ window.onbeforeunload = (e) => { Emitted when the window is closed. After you have received this event you should remove the reference to the window and avoid using it any more. -#### Event: 'endsession' _Windows_ +#### Event: 'session-end' _Windows_ Emitted when window session is going to end due to force shutdown or machine restart or session log off. From 8a328268763d23377bfb06f573c5942077f26645 Mon Sep 17 00:00:00 2001 From: Hari Krishna Reddy Juturu Date: Mon, 24 Apr 2017 11:49:21 -0700 Subject: [PATCH 61/80] Removing #ifdef windows for endsession methods --- atom/browser/api/atom_api_window.h | 2 +- atom/browser/native_window.cc | 2 -- atom/browser/native_window.h | 2 +- atom/browser/native_window_observer.h | 4 +++- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 9620a6bf4a..75f0328ba6 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -63,6 +63,7 @@ class Window : public mate::TrackableObject, void WillCloseWindow(bool* prevent_default) override; void WillDestroyNativeObject() override; void OnWindowClosed() override; + void OnWindowEndSession() override; void OnWindowBlur() override; void OnWindowFocus() override; void OnWindowShow() override; @@ -92,7 +93,6 @@ class Window : public mate::TrackableObject, const base::DictionaryValue& details) override; #if defined(OS_WIN) - void Window::OnWindowEndSession() override; void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override; #endif diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index f97e34378a..9e2c11aec4 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -474,12 +474,10 @@ void NativeWindow::NotifyWindowClosed() { observer.OnWindowClosed(); } -#if defined(OS_WIN) void NativeWindow::NotifyWindowEndSession() { for (NativeWindowObserver& observer : observers_) observer.OnWindowEndSession(); } -#endif void NativeWindow::NotifyWindowBlur() { for (NativeWindowObserver& observer : observers_) diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index f8c75352ed..d3f18d8fb9 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -218,6 +218,7 @@ class NativeWindow : public base::SupportsUserData, // Public API used by platform-dependent delegates and observers to send UI // related notifications. void NotifyWindowClosed(); + void NotifyWindowEndSession(); void NotifyWindowBlur(); void NotifyWindowFocus(); void NotifyWindowShow(); @@ -244,7 +245,6 @@ class NativeWindow : public base::SupportsUserData, const base::DictionaryValue& details); #if defined(OS_WIN) - void NotifyWindowEndSession(); void NotifyWindowMessage(UINT message, WPARAM w_param, LPARAM l_param); #endif diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index ba99b5b0c8..8c908dc823 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -40,6 +40,9 @@ class NativeWindowObserver { // Called when the window is closed. virtual void OnWindowClosed() {} + // Called when Windows sends WM_ENDSESSION message + virtual void OnWindowEndSession() {} + // Called when window loses focus. virtual void OnWindowBlur() {} @@ -78,7 +81,6 @@ class NativeWindowObserver { // Called when window message received #if defined(OS_WIN) - virtual void OnWindowEndSession() {} virtual void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {} #endif From 8458acff2600b2d2384c653b23ecaea74306be94 Mon Sep 17 00:00:00 2001 From: Hari Krishna Reddy Juturu Date: Mon, 24 Apr 2017 11:58:08 -0700 Subject: [PATCH 62/80] Removing #ifdef on endsession api --- atom/browser/api/atom_api_window.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 95168efe9a..72b8e33ef7 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -191,11 +191,9 @@ void Window::OnWindowClosed() { FROM_HERE, GetDestroyClosure()); } -#if defined(OS_WIN) void Window::OnWindowEndSession() { Emit("session-end"); } -#endif void Window::OnWindowBlur() { Emit("blur"); From ca5a8b6166e7ae4d9677d44c9fcc4d0804e322a4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 24 Apr 2017 11:54:05 -0700 Subject: [PATCH 63/80] Extract script tags to renderer.js file --- default_app/index.html | 44 +--------------------------------------- default_app/renderer.js | 45 +++++++++++++++++++++++++++++++++++++++++ filenames.gypi | 1 + 3 files changed, 47 insertions(+), 43 deletions(-) create mode 100644 default_app/renderer.js diff --git a/default_app/index.html b/default_app/index.html index 86100e19dd..41b5396360 100644 --- a/default_app/index.html +++ b/default_app/index.html @@ -113,24 +113,6 @@ - -
diff --git a/default_app/renderer.js b/default_app/renderer.js new file mode 100644 index 0000000000..6196195eab --- /dev/null +++ b/default_app/renderer.js @@ -0,0 +1,45 @@ +const {remote, shell} = require('electron') +const {execFile} = require('child_process') + +const {execPath} = remote.process + +document.onclick = function (e) { + e.preventDefault() + if (e.target.tagName === 'A') { + shell.openExternal(e.target.href) + } + return false +} + +document.ondragover = document.ondrop = function (e) { + e.preventDefault() + return false +} + +const holder = document.getElementById('holder') +holder.ondragover = function () { + this.className = 'hover' + return false +} + +holder.ondragleave = holder.ondragend = function () { + this.className = '' + return false +} + +holder.ondrop = function (e) { + this.className = '' + e.preventDefault() + + const file = e.dataTransfer.files[0] + execFile(execPath, [file.path], { + detached: true, stdio: 'ignore' + }).unref() + return false +} + +const version = process.versions.electron +document.querySelector('.header-version').innerText = version +document.querySelector('.command-example').innerText = `${execPath} path-to-your-app` +document.querySelector('.quick-start-link').href = `https://github.com/electron/electron/blob/v${version}/docs/tutorial/quick-start.md` +document.querySelector('.docs-link').href = `https://github.com/electron/electron/tree/v${version}/docs#readme` diff --git a/filenames.gypi b/filenames.gypi index 8f14b29883..6107ab956e 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -89,6 +89,7 @@ 'default_app/index.html', 'default_app/main.js', 'default_app/package.json', + 'default_app/renderer.js', ], 'lib_sources': [ 'atom/app/atom_content_client.cc', From 6ec74060b4dae3f44c7d73358071f44ad77a01b3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 21 Apr 2017 10:57:22 -0700 Subject: [PATCH 64/80] Enable setting javascript and contextIsolation via window.open --- lib/browser/guest-window-manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/browser/guest-window-manager.js b/lib/browser/guest-window-manager.js index e5bfa74123..e96fc12ac5 100644 --- a/lib/browser/guest-window-manager.js +++ b/lib/browser/guest-window-manager.js @@ -48,7 +48,7 @@ const mergeBrowserWindowOptions = function (embedder, options) { options.webPreferences.nodeIntegration = false } - // Enable context isolation on child window if enable on parent window + // Enable context isolation on child window if enabled on parent window if (embedder.getWebPreferences().contextIsolation === true) { options.webPreferences.contextIsolation = true } @@ -186,7 +186,7 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, url, frameName, const options = {} const ints = ['x', 'y', 'width', 'height', 'minWidth', 'maxWidth', 'minHeight', 'maxHeight', 'zoomFactor'] - const webPreferences = ['zoomFactor', 'nodeIntegration', 'preload'] + const webPreferences = ['zoomFactor', 'nodeIntegration', 'preload', 'javascript', 'contextIsolation'] const disposition = 'new-window' // Used to store additional features From cee050709017144e567c7b6ca1494e56ddc93ade Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 21 Apr 2017 10:58:47 -0700 Subject: [PATCH 65/80] Add failing spec for inheriting Javascript web preference --- spec/chromium-spec.js | 25 +++++++++++++++++++ spec/fixtures/pages/window-no-javascript.html | 12 +++++++++ 2 files changed, 37 insertions(+) create mode 100644 spec/fixtures/pages/window-no-javascript.html diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 4c5b85521a..977f25e103 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -229,6 +229,31 @@ describe('chromium feature', function () { b = window.open(windowUrl, '', 'nodeIntegration=no,show=no') }) + it('disables JavaScript when it is disabled on the parent window', function (done) { + var b + app.once('web-contents-created', (event, contents) => { + contents.once('did-finish-load', () => { + app.once('browser-window-created', (event, window) => { + const preferences = window.webContents.getWebPreferences() + assert.equal(preferences.javascript, false) + window.destroy() + b.close() + done() + }) + // Click link on page + contents.sendInputEvent({type: 'mouseDown', clickCount: 1, x: 1, y: 1}) + contents.sendInputEvent({type: 'mouseUp', clickCount: 1, x: 1, y: 1}) + }) + }) + + var windowUrl = require('url').format({ + pathname: `${fixtures}/pages/window-no-javascript.html`, + protocol: 'file', + slashes: true + }) + b = window.open(windowUrl, '', 'javascript=no,show=no') + }) + it('does not override child options', function (done) { var b, size size = { diff --git a/spec/fixtures/pages/window-no-javascript.html b/spec/fixtures/pages/window-no-javascript.html new file mode 100644 index 0000000000..9c38c9e0bb --- /dev/null +++ b/spec/fixtures/pages/window-no-javascript.html @@ -0,0 +1,12 @@ + + + + +CLICK + + From 3e2a1034af80c369e7c3d89dcbee9965eb5611a7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 21 Apr 2017 10:59:33 -0700 Subject: [PATCH 66/80] Disable JavaScript on child when disabled on parent --- lib/browser/guest-window-manager.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/browser/guest-window-manager.js b/lib/browser/guest-window-manager.js index e96fc12ac5..8a8e9f46b8 100644 --- a/lib/browser/guest-window-manager.js +++ b/lib/browser/guest-window-manager.js @@ -53,6 +53,11 @@ const mergeBrowserWindowOptions = function (embedder, options) { options.webPreferences.contextIsolation = true } + // Disable JavaScript on child window if disabled on parent window + if (embedder.getWebPreferences().javascript === false) { + options.webPreferences.javascript = false + } + // Sets correct openerId here to give correct options to 'new-window' event handler options.webPreferences.openerId = embedder.id From 87db1b8aa718530a7b9ad050d145d21dee985cc4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 21 Apr 2017 11:00:31 -0700 Subject: [PATCH 67/80] Document other inherited web preferences --- docs/api/window-open.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/api/window-open.md b/docs/api/window-open.md index 56216f551a..41332aa6cf 100644 --- a/docs/api/window-open.md +++ b/docs/api/window-open.md @@ -30,6 +30,10 @@ has to be a field of `BrowserWindow`'s options. * Node integration will always be disabled in the opened `window` if it is disabled on the parent window. +* Context isolation will always be enabled in the opened `window` if it is + enabled on the parent window. +* JavaScript will always be disabled in the opened `window` if it is disabled on + the parent window. * Non-standard features (that are not handled by Chromium or Electron) given in `features` will be passed to any registered `webContent`'s `new-window` event handler in the `additionalFeatures` argument. From 3f88eb2f867f4340320b378a18605bd060fc97f5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 24 Apr 2017 10:25:12 -0700 Subject: [PATCH 68/80] Add spec for chrome-devtools URL with no node integration --- spec/chromium-spec.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 977f25e103..9cce9fe280 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -229,6 +229,20 @@ describe('chromium feature', function () { b = window.open(windowUrl, '', 'nodeIntegration=no,show=no') }) + it('disables node integration when it is disabled on the parent window for chrome devtools URLs', function (done) { + var b + app.once('web-contents-created', (event, contents) => { + contents.once('did-finish-load', () => { + contents.executeJavaScript('typeof process').then((typeofProcessGlobal) => { + assert.equal(typeofProcessGlobal, 'undefined') + b.close() + done() + }).catch(done) + }) + }) + b = window.open('chrome-devtools://devtools/bundled/inspector.html', '', 'nodeIntegration=no,show=no') + }) + it('disables JavaScript when it is disabled on the parent window', function (done) { var b app.once('web-contents-created', (event, contents) => { From 05b6d91bf4c1e0ee65eeef70cd5d1bd1df125644 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 24 Apr 2017 10:25:40 -0700 Subject: [PATCH 69/80] Disable node integration in chrome-devtools: URLs --- lib/renderer/init.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/renderer/init.js b/lib/renderer/init.js index 0306463bc4..9b7ea9dabd 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -78,7 +78,7 @@ for (let arg of process.argv) { if (window.location.protocol === 'chrome-devtools:') { // Override some inspector APIs. require('./inspector') - nodeIntegration = 'true' + nodeIntegration = 'false' } else if (window.location.protocol === 'chrome-extension:') { // Add implementations of chrome API. require('./chrome-api').injectTo(window.location.hostname, isBackgroundPage, window) From 7e285711ca7d72a45bcec19039796354a9abbc6c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Apr 2017 13:16:07 -0700 Subject: [PATCH 70/80] Add spec for window.open toString errors --- spec/chromium-spec.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 9cce9fe280..dd992dc0ae 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -361,6 +361,16 @@ describe('chromium feature', function () { }) b = window.open() }) + + it('throws an exception when the arguments cannot be converted to strings', function () { + assert.throws(function () { + window.open('', {toString: null}) + }, /Cannot convert object to primitive value/) + + assert.throws(function () { + window.open('', '', {toString: 3}) + }, /Cannot convert object to primitive value/) + }) }) describe('window.opener', function () { From 3894c1c625c568d77a539fb8ff60b39145e43e20 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Apr 2017 13:16:28 -0700 Subject: [PATCH 71/80] Convert frameName/features to strings in render process --- lib/renderer/window-setup.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/renderer/window-setup.js b/lib/renderer/window-setup.js index d29133c88f..0bd43fb9a1 100644 --- a/lib/renderer/window-setup.js +++ b/lib/renderer/window-setup.js @@ -32,6 +32,10 @@ const resolveURL = function (url) { return a.href } +const toString = (value) => { + return value != null ? `${value}` : value +} + const windowProxies = {} const getOrCreateProxy = (ipcRenderer, guestId) => { @@ -112,7 +116,7 @@ module.exports = (ipcRenderer, guestInstanceId, openerId, hiddenPage) => { if (url != null && url !== '') { url = resolveURL(url) } - const guestId = ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', url, frameName, features) + const guestId = ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', url, toString(frameName), toString(features)) if (guestId != null) { return getOrCreateProxy(ipcRenderer, guestId) } else { @@ -121,11 +125,11 @@ module.exports = (ipcRenderer, guestInstanceId, openerId, hiddenPage) => { } window.alert = function (message, title) { - ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_ALERT', `${message}`, `${title}`) + ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_ALERT', toString(message), toString(title)) } window.confirm = function (message, title) { - return ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CONFIRM', `${message}`, `${title}`) + return ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CONFIRM', toString(message), toString(title)) } // But we do not support prompt(). From 246937a37209810779d43bd2c02c71174df29f28 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Apr 2017 13:26:47 -0700 Subject: [PATCH 72/80] Convert targetOrigin to string in render process --- lib/renderer/window-setup.js | 5 ++++- spec/chromium-spec.js | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/renderer/window-setup.js b/lib/renderer/window-setup.js index 0bd43fb9a1..87a31f0624 100644 --- a/lib/renderer/window-setup.js +++ b/lib/renderer/window-setup.js @@ -32,6 +32,9 @@ const resolveURL = function (url) { return a.href } +// Use this method to ensure value expected as string in the main process +// are convertible to string in the renderer process. This ensures exceptions +// converting values to string are thrown in this process. const toString = (value) => { return value != null ? `${value}` : value } @@ -86,7 +89,7 @@ function BrowserWindowProxy (ipcRenderer, guestId) { } this.postMessage = (message, targetOrigin) => { - ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', guestId, message, targetOrigin, window.location.origin) + ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', guestId, message, toString(targetOrigin), window.location.origin) } this.eval = (...args) => { diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index dd992dc0ae..b0ae69af51 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -548,6 +548,14 @@ describe('chromium feature', function () { }) b = window.open('file://' + fixtures + '/pages/window-open-postMessage.html', '', 'show=no') }) + + it('throws an exception when the targetOrigin cannot be converted to a string', function () { + var b = window.open('') + assert.throws(function () { + b.postMessage('test', {toString: null}) + }, /Cannot convert object to primitive value/) + b.close() + }) }) describe('window.opener.postMessage', function () { From 2c48300daa487fdfab0c9786e3aa2ffe467d89c5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 26 Apr 2017 09:09:42 -0700 Subject: [PATCH 73/80] Fix typos in comment --- lib/renderer/window-setup.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/renderer/window-setup.js b/lib/renderer/window-setup.js index 87a31f0624..5ccb6fec46 100644 --- a/lib/renderer/window-setup.js +++ b/lib/renderer/window-setup.js @@ -32,9 +32,9 @@ const resolveURL = function (url) { return a.href } -// Use this method to ensure value expected as string in the main process -// are convertible to string in the renderer process. This ensures exceptions -// converting values to string are thrown in this process. +// Use this method to ensure values expected as strings in the main process +// are convertible to strings in the renderer process. This ensures exceptions +// converting values to strings are thrown in this process. const toString = (value) => { return value != null ? `${value}` : value } From 9643b2a5c52e4d81b4d267920cd78f42027244a1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Apr 2017 13:52:56 -0700 Subject: [PATCH 74/80] Add specs for window.open frameName argument --- spec/chromium-spec.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index b0ae69af51..1b88d78e2a 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -371,6 +371,26 @@ describe('chromium feature', function () { window.open('', '', {toString: 3}) }, /Cannot convert object to primitive value/) }) + + it('sets the window title to the specified frameName', function (done) { + let b + app.once('browser-window-created', (event, createdWindow) => { + assert.equal(createdWindow.getTitle(), 'hello') + b.close() + done() + }) + b = window.open('', 'hello') + }) + + it('does not throw an exception when the frameName is a built-in object property', function (done) { + let b + app.once('browser-window-created', (event, createdWindow) => { + assert.equal(createdWindow.getTitle(), '__proto__') + b.close() + done() + }) + b = window.open('', '__proto__') + }) }) describe('window.opener', function () { From 91a1e5cdfef0e7efed130de5aff0d83af629c970 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Apr 2017 13:53:29 -0700 Subject: [PATCH 75/80] Store frame to guests in map --- lib/browser/guest-window-manager.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/browser/guest-window-manager.js b/lib/browser/guest-window-manager.js index 8a8e9f46b8..33ec15a101 100644 --- a/lib/browser/guest-window-manager.js +++ b/lib/browser/guest-window-manager.js @@ -5,7 +5,7 @@ const {isSameOrigin} = process.atomBinding('v8_util') const parseFeaturesString = require('../common/parse-features-string') const hasProp = {}.hasOwnProperty -const frameToGuest = {} +const frameToGuest = new Map() // Copy attribute of |parent| to |child| if it is not defined in |child|. const mergeOptions = function (child, parent, visited) { @@ -92,10 +92,10 @@ const setupGuest = function (embedder, frameName, guest, options) { guest.once('closed', closedByUser) } if (frameName) { - frameToGuest[frameName] = guest + frameToGuest.set(frameName, guest) guest.frameName = frameName guest.once('closed', function () { - delete frameToGuest[frameName] + frameToGuest.delete(frameName) }) } return guestId @@ -103,7 +103,7 @@ const setupGuest = function (embedder, frameName, guest, options) { // Create a new guest created by |embedder| with |options|. const createGuest = function (embedder, url, frameName, options, postData) { - let guest = frameToGuest[frameName] + let guest = frameToGuest.get(frameName) if (frameName && (guest != null)) { guest.loadURL(url) return guest.webContents.id From 7726c7c6c4eb6cf037eef207958705578ad2271a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Apr 2017 14:19:59 -0700 Subject: [PATCH 76/80] Add spec for webPreferences in features string --- spec/chromium-spec.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 1b88d78e2a..700983bb5a 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -391,6 +391,14 @@ describe('chromium feature', function () { }) b = window.open('', '__proto__') }) + + it('does not throw an exception when the features include webPreferences', function () { + let b + assert.doesNotThrow(function () { + b = window.open('', '', 'webPreferences=') + }) + b.close() + }) }) describe('window.opener', function () { From 507f60e33e656248aeb40cc0d5fd8065a7dde5e4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Apr 2017 14:20:39 -0700 Subject: [PATCH 77/80] Don't allow webPreferences to be overrideden in features string --- lib/browser/guest-window-manager.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/browser/guest-window-manager.js b/lib/browser/guest-window-manager.js index 33ec15a101..e668a3114a 100644 --- a/lib/browser/guest-window-manager.js +++ b/lib/browser/guest-window-manager.js @@ -202,6 +202,10 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, url, frameName, if (value === undefined) { additionalFeatures.push(key) } else { + // Don't allow webPreferences to be set since it must be an object + // that cannot be directly overridden + if (key === 'webPreferences') return + if (webPreferences.includes(key)) { if (options.webPreferences == null) { options.webPreferences = {} From 775753c3d738b50c3d02c18f0e48cd55ee258385 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Apr 2017 14:48:01 -0700 Subject: [PATCH 78/80] Add spec for invalid window.history.go offset --- spec/chromium-spec.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 700983bb5a..d5d1b3f478 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -989,4 +989,12 @@ describe('chromium feature', function () { }, /Cannot convert object to primitive value/) }) }) + + describe('window.history.go(offset)', function () { + it('throws an exception when the argumnet cannot be converted to a string', function () { + assert.throws(function () { + window.history.go({toString: null}) + }, /Cannot convert object to primitive value/) + }) + }) }) From 95ef422ab4c350c089ecc4f8fbce24b97c958f19 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Apr 2017 14:49:14 -0700 Subject: [PATCH 79/80] Coerce offset to number in renderer process --- lib/renderer/window-setup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/renderer/window-setup.js b/lib/renderer/window-setup.js index 5ccb6fec46..99f7aef542 100644 --- a/lib/renderer/window-setup.js +++ b/lib/renderer/window-setup.js @@ -164,7 +164,7 @@ module.exports = (ipcRenderer, guestInstanceId, openerId, hiddenPage) => { } window.history.go = function (offset) { - sendHistoryOperation(ipcRenderer, 'goToOffset', offset) + sendHistoryOperation(ipcRenderer, 'goToOffset', +offset) } defineProperty(window.history, 'length', { From f6bbcc6efa198e1215bc99fdb6919aa507adbeb6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 26 Apr 2017 09:06:10 -0700 Subject: [PATCH 80/80] Fix typos --- docs/api/menu-item.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/menu-item.md b/docs/api/menu-item.md index 494bdb74f1..a7486f3003 100644 --- a/docs/api/menu-item.md +++ b/docs/api/menu-item.md @@ -70,7 +70,7 @@ The `role` property can have following values: * `editMenu` - Whole default "Edit" menu (Undo, Copy, etc.) * `windowMenu` - Whole default "Window" menu (Minimize, Close, etc.) -The following additional roles are avaiable on macOS: +The following additional roles are available on macOS: * `about` - Map to the `orderFrontStandardAboutPanel` action * `hide` - Map to the `hide` action @@ -120,4 +120,4 @@ A String representing the menu items visible label #### `menuItem.click` -A Function that is fired when the MenuItem recieves a click event +A Function that is fired when the MenuItem receives a click event