From 8bd07af5e579da36140191fbea59f561964fbda3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 16:22:16 -0800 Subject: [PATCH 001/173] Correct typo in comment --- atom/browser/lib/chrome-extension.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/lib/chrome-extension.js b/atom/browser/lib/chrome-extension.js index fbb537d052c..eaed9b655a6 100644 --- a/atom/browser/lib/chrome-extension.js +++ b/atom/browser/lib/chrome-extension.js @@ -70,7 +70,7 @@ app.once('ready', function() { var BrowserWindow, chromeExtensionHandler, i, init, len, protocol, srcDirectory; protocol = electron.protocol, BrowserWindow = electron.BrowserWindow; - // Load persistented extensions. + // Load persisted extensions. loadedExtensionsPath = path.join(app.getPath('userData'), 'DevTools Extensions'); try { loadedExtensions = JSON.parse(fs.readFileSync(loadedExtensionsPath)); From 5714ae0b73c722d2a57bbac182d671384b705314 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 17:08:46 -0800 Subject: [PATCH 002/173] Add failing spec for dev tools extensions file --- spec/api-browser-window-spec.js | 17 +++++++++++++++++ .../devtools-extensions/foo/manifest.json | 3 +++ 2 files changed, 20 insertions(+) create mode 100644 spec/fixtures/devtools-extensions/foo/manifest.json diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index fc8d3523c8f..328325a376a 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -8,6 +8,7 @@ const os = require('os'); const remote = require('electron').remote; const screen = require('electron').screen; +const app = remote.require('electron').app; const ipcMain = remote.require('electron').ipcMain; const BrowserWindow = remote.require('electron').BrowserWindow; @@ -618,4 +619,20 @@ describe('browser-window module', function() { }); }); }); + + describe('dev tool extensions', function () { + it('serializes the registered extensions on quit', function () { + var extensionName = 'foo' + var extensionPath = path.join(__dirname, 'fixtures', 'devtools-extensions', extensionName); + var serializedPath = path.join(app.getPath('userData'), 'DevTools Extensions'); + + BrowserWindow.addDevToolsExtension(extensionPath); + app.emit('will-quit'); + assert.deepEqual(JSON.parse(fs.readFileSync(serializedPath)), [extensionPath]); + + BrowserWindow.removeDevToolsExtension(extensionName); + app.emit('will-quit'); + assert.equal(fs.existsSync(serializedPath), false); + }) + }) }); diff --git a/spec/fixtures/devtools-extensions/foo/manifest.json b/spec/fixtures/devtools-extensions/foo/manifest.json new file mode 100644 index 00000000000..bde99de9287 --- /dev/null +++ b/spec/fixtures/devtools-extensions/foo/manifest.json @@ -0,0 +1,3 @@ +{ + "name": "foo" +} From 6252511b7fa5505ba4f47dfad9ff16f26fe0c5e0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 17:12:09 -0800 Subject: [PATCH 003/173] Delete extensions file when there are no loaded extensions --- atom/browser/lib/chrome-extension.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/atom/browser/lib/chrome-extension.js b/atom/browser/lib/chrome-extension.js index eaed9b655a6..e396989bcf3 100644 --- a/atom/browser/lib/chrome-extension.js +++ b/atom/browser/lib/chrome-extension.js @@ -54,12 +54,16 @@ app.on('will-quit', function() { loadedExtensions = Object.keys(extensionInfoMap).map(function(key) { return extensionInfoMap[key].srcDirectory; }); - try { - fs.mkdirSync(path.dirname(loadedExtensionsPath)); - } catch (error) { - // Ignore error + if (loadedExtensions.length > 0) { + try { + fs.mkdirSync(path.dirname(loadedExtensionsPath)); + } catch (error) { + // Ignore error + } + return fs.writeFileSync(loadedExtensionsPath, JSON.stringify(loadedExtensions)); + } else { + fs.unlinkSync(loadedExtensionsPath); } - return fs.writeFileSync(loadedExtensionsPath, JSON.stringify(loadedExtensions)); } catch (error) { // Ignore error } From adfa4844d1b1849b1b6ea7f2839fc037a5aba020 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 17:15:28 -0800 Subject: [PATCH 004/173] Don't return anything from will-quit handler --- atom/browser/lib/chrome-extension.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/lib/chrome-extension.js b/atom/browser/lib/chrome-extension.js index e396989bcf3..fcbb8c7f15f 100644 --- a/atom/browser/lib/chrome-extension.js +++ b/atom/browser/lib/chrome-extension.js @@ -60,7 +60,7 @@ app.on('will-quit', function() { } catch (error) { // Ignore error } - return fs.writeFileSync(loadedExtensionsPath, JSON.stringify(loadedExtensions)); + fs.writeFileSync(loadedExtensionsPath, JSON.stringify(loadedExtensions)); } else { fs.unlinkSync(loadedExtensionsPath); } From 00261a5571d71d77850cd268e8ae8890716924bd Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 17:17:11 -0800 Subject: [PATCH 005/173] Remove lint warnings --- spec/api-browser-window-spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 328325a376a..a7d58d7feb8 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -622,7 +622,7 @@ describe('browser-window module', function() { describe('dev tool extensions', function () { it('serializes the registered extensions on quit', function () { - var extensionName = 'foo' + var extensionName = 'foo'; var extensionPath = path.join(__dirname, 'fixtures', 'devtools-extensions', extensionName); var serializedPath = path.join(app.getPath('userData'), 'DevTools Extensions'); @@ -633,6 +633,6 @@ describe('browser-window module', function() { BrowserWindow.removeDevToolsExtension(extensionName); app.emit('will-quit'); assert.equal(fs.existsSync(serializedPath), false); - }) - }) + }); + }); }); From e9aa24e340a3dd9b6ab3794c7bee1da1d359b37d Mon Sep 17 00:00:00 2001 From: ShiningRay Date: Thu, 4 Feb 2016 18:10:26 +0800 Subject: [PATCH 006/173] fix broken link --- docs-translations/zh-CN/tutorial/quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/zh-CN/tutorial/quick-start.md b/docs-translations/zh-CN/tutorial/quick-start.md index 5e9c752d1d4..c4d668417e4 100644 --- a/docs-translations/zh-CN/tutorial/quick-start.md +++ b/docs-translations/zh-CN/tutorial/quick-start.md @@ -127,7 +127,7 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/ 在你完成了你的应用后,你可以按照[应用部署][4]指导发布一个版本,并且以已经打包好的形式运行应用。 - [1]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/ipc-renderer.md + [1]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/ipc-main-process.md [2]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/remote.md [3]: https://github.com/atom/electron/releases [4]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/tutorial/application-distribution.md From 6c8d9a5ccf2cd2970ea0aa7e627b374e38f57e45 Mon Sep 17 00:00:00 2001 From: ShiningRay Date: Thu, 4 Feb 2016 21:11:59 +0800 Subject: [PATCH 007/173] translate --- docs-translations/zh-CN/api/remote.md | 150 ++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 docs-translations/zh-CN/api/remote.md diff --git a/docs-translations/zh-CN/api/remote.md b/docs-translations/zh-CN/api/remote.md new file mode 100644 index 00000000000..049ce5fb32c --- /dev/null +++ b/docs-translations/zh-CN/api/remote.md @@ -0,0 +1,150 @@ +# remote + +`remote` 模块提供了一种在渲染进程(网页)和主进程之间进行进程间通讯(IPC)的简便途径。 + +Electron中, 与GUI相关的模块(如 `dialog`, `menu` 等)只存在于主进程,而不在渲染进程中 +。为了能从渲染进程中使用它们,需要用`ipc`模块来给主进程发送进程间消息。使用 `remote` +模块,可以调用主进程对象的方法,而无需显式地发送进程间消息,这类似于 Java 的 [RMI][rmi]。 +下面是从渲染进程创建一个浏览器窗口的例子: + +```javascript +const remote = require('electron').remote; +const BrowserWindow = remote.BrowserWindow; + +var win = new BrowserWindow({ width: 800, height: 600 }); +win.loadURL('https://github.com'); +``` + +**注意:** 反向操作(从主进程访问渲染进程),可以使用[webContents.executeJavascript](web-contents.md#webcontentsexecutejavascriptcode-usergesture). + +## 远程对象 + +`remote`模块返回的每个对象(包括函数)都代表了主进程中的一个对象(我们称之为远程对象或者远程函数)。 +当调用远程对象的方法、执行远程函数或者使用远程构造器(函数)创建新对象时,其实就是在发送同步的进程间消息。 + +在上面的例子中, `BrowserWindow` 和 `win` 都是远程对象,然而 +`new BrowserWindow` 并没有在渲染进程中创建 `BrowserWindow` 对象。 +而是在主进程中创建了 `BrowserWindow` 对象,并在渲染进程中返回了对应的远程对象,即 +`win` 对象。 + +请注意只有 [可枚举属性](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties) 才能通过 remote 进行访问. + +## 远程对象的生命周期 + +Electron 确保在渲染进程中的远程对象存在(换句话说,没有被垃圾收集),那主进程中的对应对象也不会被释放。 +当远程对象被垃圾收集之后,主进程中的对应对象才会被取消关联。 + +如果远程对象在渲染进程泄露了(即,存在某个表中但永远不会释放),那么主进程中的对应对象也一样会泄露, +所以你必须小心不要泄露了远程对象。If the remote object is leaked in the renderer process (e.g. stored in a map but +never freed), the corresponding object in the main process will also be leaked, +so you should be very careful not to leak remote objects. + +不过,主要的值类型如字符串和数字,是传递的副本。 + +## 给主进程传递回调函数 + +在主进程中的代码可以从渲染进程——`remote`模块——中接受回调函数,但是使用这个功能的时候必须非常非常小心。Code in the main process can accept callbacks from the renderer - for instance +the `remote` module - but you should be extremely careful when using this +feature. + +首先,为了避免死锁,传递给主进程的回调函数会进行异步调用。所以不能期望主进程来获得传递过去的回调函数的返回值。First, in order to avoid deadlocks, the callbacks passed to the main process +are called asynchronously. You should not expect the main process to +get the return value of the passed callbacks. + +比如,在渲染进程For instance you can't use a function from the renderer process in an +`Array.map` called in the main process: + +```javascript +// 主进程 mapNumbers.js +exports.withRendererCallback = function(mapper) { + return [1,2,3].map(mapper); +} + +exports.withLocalCallback = function() { + return exports.mapNumbers(function(x) { + return x + 1; + }); +} +``` + +```javascript +// 渲染进程 +var mapNumbers = require("remote").require("./mapNumbers"); + +var withRendererCb = mapNumbers.withRendererCallback(function(x) { + return x + 1; +}) + +var withLocalCb = mapNumbers.withLocalCallback() + +console.log(withRendererCb, withLocalCb) // [true, true, true], [2, 3, 4] +``` + +As you can see, the renderer callback's synchronous return value was not as +expected, and didn't match the return value of an identical callback that lives +in the main process. + +Second, the callbacks passed to the main process will persist until the +main process garbage-collects them. + +For example, the following code seems innocent at first glance. It installs a +callback for the `close` event on a remote object: + +```javascript +remote.getCurrentWindow().on('close', function() { + // blabla... +}); +``` + +But remember the callback is referenced by the main process until you +explicitly uninstall it. If you do not, each time you reload your window the +callback will be installed again, leaking one callback for each restart. + +To make things worse, since the context of previously installed callbacks has +been released, exceptions will be raised in the main process when the `close` +event is emitted. + +To avoid this problem, ensure you clean up any references to renderer callbacks +passed to the main process. This involves cleaning up event handlers, or +ensuring the main process is explicitly told to deference callbacks that came +from a renderer process that is exiting. + +## Accessing built-in modules in the main process + +The built-in modules in the main process are added as getters in the `remote` +module, so you can use them directly like the `electron` module. + +```javascript +const app = remote.app; +``` + +## 方法 + +`remote` 模块有以下方法: + +### `remote.require(module)` + +* `module` String + +返回在主进程中执行 `require(module)` 所返回的对象。 + +### `remote.getCurrentWindow()` + +返回该网页所属的 [`BrowserWindow`](browser-window.md) 对象。 + +### `remote.getCurrentWebContents()` + +返回该网页的 [`WebContents`](web-contents.md) 对象 + +### `remote.getGlobal(name)` + +* `name` String + +返回在主进程中名为 `name` 的全局变量(即 `global[name]`) 。 + +### `remote.process` + +返回主进程中的 `process` 对象。等同于 +`remote.getGlobal('process')` 但是有缓存。 + +[rmi]: http://en.wikipedia.org/wiki/Java_remote_method_invocation From 55950281e8b0eccafe72372a8e668382c1bb21a4 Mon Sep 17 00:00:00 2001 From: ShiningRay Date: Thu, 4 Feb 2016 22:55:30 +0800 Subject: [PATCH 008/173] translate --- docs-translations/zh-CN/api/remote.md | 31 ++++++++------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/docs-translations/zh-CN/api/remote.md b/docs-translations/zh-CN/api/remote.md index 049ce5fb32c..a686abf2f61 100644 --- a/docs-translations/zh-CN/api/remote.md +++ b/docs-translations/zh-CN/api/remote.md @@ -51,8 +51,7 @@ feature. are called asynchronously. You should not expect the main process to get the return value of the passed callbacks. -比如,在渲染进程For instance you can't use a function from the renderer process in an -`Array.map` called in the main process: +比如,你不能主进程中给`Array.map`传递来自渲染进程的函数。 ```javascript // 主进程 mapNumbers.js @@ -80,15 +79,11 @@ var withLocalCb = mapNumbers.withLocalCallback() console.log(withRendererCb, withLocalCb) // [true, true, true], [2, 3, 4] ``` -As you can see, the renderer callback's synchronous return value was not as -expected, and didn't match the return value of an identical callback that lives -in the main process. +如你所见,渲染器回调函数的同步返回值没有按预期产生,与主进程中的一模一样的回调函数的返回值不同。 -Second, the callbacks passed to the main process will persist until the -main process garbage-collects them. +其次,传递给主进程的函数会持续到主进程对他们进行垃圾回收。 -For example, the following code seems innocent at first glance. It installs a -callback for the `close` event on a remote object: +例如,下面的代码第一眼看上去毫无问题。给远程对象的`close`事件绑定了一个回调函数: ```javascript remote.getCurrentWindow().on('close', function() { @@ -96,23 +91,15 @@ remote.getCurrentWindow().on('close', function() { }); ``` -But remember the callback is referenced by the main process until you -explicitly uninstall it. If you do not, each time you reload your window the -callback will be installed again, leaking one callback for each restart. +但记住主进程会一直保持对这个回调函数的引用,除非明确的卸载它。如果不卸载,每次重新载入窗口都会再次绑定,这样每次重启就会泄露一个回调函数。 -To make things worse, since the context of previously installed callbacks has -been released, exceptions will be raised in the main process when the `close` -event is emitted. +更严重的是,由于前面安装了回调函数的上下文已经被释放,所以当主进程的 `close` 事件触发的时候,会抛出异常。 -To avoid this problem, ensure you clean up any references to renderer callbacks -passed to the main process. This involves cleaning up event handlers, or -ensuring the main process is explicitly told to deference callbacks that came -from a renderer process that is exiting. +为了避免这个问题,要确保对传递给主进程的渲染器的回调函数进行清理。可以清理事件处理器,或者明确告诉主进行取消来自已经退出的渲染器进程中的回调函数。 -## Accessing built-in modules in the main process +## 访问主进程中的内置模块 -The built-in modules in the main process are added as getters in the `remote` -module, so you can use them directly like the `electron` module. +在主进程中的内置模块已经被添加为`remote`模块中的属性,所以可以直接像使用`electron`模块一样直接使用它们。 ```javascript const app = remote.app; From 8df3856c8f26ed3f1e9ece48850a26fc4466eced Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Feb 2016 09:16:40 -0800 Subject: [PATCH 009/173] Use const for fs/path requires --- atom/browser/default_app/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index 895e3df6366..c24fc12ac3c 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -4,8 +4,8 @@ const dialog = electron.dialog; const shell = electron.shell; const Menu = electron.Menu; -var fs = require('fs'); -var path = require('path'); +const fs = require('fs'); +const path = require('path'); // Quit when all windows are closed and no other one is listening to this. app.on('window-all-closed', function() { From 2e96cab6aa82fd9e77778699a761f19112181463 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Feb 2016 10:07:19 -0800 Subject: [PATCH 010/173] Extract helper function to load specified app --- atom/browser/default_app/main.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index c24fc12ac3c..c562824daff 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -234,12 +234,10 @@ if (option.modules.length > 0) { require('module')._preloadModules(option.modules); } -// Start the specified app if there is one specified in command line, otherwise -// start the default app. -if (option.file && !option.webdriver) { +function loadPackagePath(packagePath) { try { // Override app name and version. - var packagePath = path.resolve(option.file); + packagePath = path.resolve(packagePath); var packageJsonPath = path.join(packagePath, 'package.json'); if (fs.existsSync(packageJsonPath)) { var packageJson = JSON.parse(fs.readFileSync(packageJsonPath)); @@ -270,6 +268,12 @@ if (option.file && !option.webdriver) { throw e; } } +} + +// Start the specified app if there is one specified in command line, otherwise +// start the default app. +if (option.file && !option.webdriver) { + loadPackagePath(option.file); } else if (option.version) { console.log('v' + process.versions.electron); process.exit(0); From 69687c92e96cf59a5a66ff029cfd18d6ad62ad00 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Feb 2016 10:26:11 -0800 Subject: [PATCH 011/173] Add support for launching http URL directly --- atom/browser/default_app/default_app.js | 20 +++++++++++--------- atom/browser/default_app/main.js | 14 ++++++++++++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/atom/browser/default_app/default_app.js b/atom/browser/default_app/default_app.js index 2ec765d0d69..ebcca2a5d9a 100644 --- a/atom/browser/default_app/default_app.js +++ b/atom/browser/default_app/default_app.js @@ -9,13 +9,15 @@ app.on('window-all-closed', function() { app.quit(); }); -app.on('ready', function() { - mainWindow = new BrowserWindow({ - width: 800, - height: 600, - autoHideMenuBar: true, - useContentSize: true, +exports.load = function(appUrl) { + app.on('ready', function() { + mainWindow = new BrowserWindow({ + width: 800, + height: 600, + autoHideMenuBar: true, + useContentSize: true, + }); + mainWindow.loadURL(appUrl); + mainWindow.focus(); }); - mainWindow.loadURL('file://' + __dirname + '/index.html'); - mainWindow.focus(); -}); +}; diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index c562824daff..2b5c916749d 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -6,6 +6,7 @@ const Menu = electron.Menu; const fs = require('fs'); const path = require('path'); +const url = require('url'); // Quit when all windows are closed and no other one is listening to this. app.on('window-all-closed', function() { @@ -270,10 +271,19 @@ function loadPackagePath(packagePath) { } } +function loadApplicationByUrl(appUrl) { + require('./default_app').load(appUrl); +} + // Start the specified app if there is one specified in command line, otherwise // start the default app. if (option.file && !option.webdriver) { - loadPackagePath(option.file); + var protocol = url.parse(option.file).protocol; + if (protocol === 'http:' || protocol === 'https:') { + loadApplicationByUrl(option.file); + } else { + loadPackagePath(option.file); + } } else if (option.version) { console.log('v' + process.versions.electron); process.exit(0); @@ -289,5 +299,5 @@ if (option.file && !option.webdriver) { console.log(helpMessage); process.exit(0); } else { - require('./default_app'); + loadApplicationByUrl('file://' + __dirname + '/index.html'); } From 312182e0bdd8d71cf7a26ffaa54daf825ad7fbb8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Feb 2016 10:33:22 -0800 Subject: [PATCH 012/173] Add support for launching HTML files directly --- atom/browser/default_app/main.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index 2b5c916749d..09082804b3c 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -278,11 +278,15 @@ function loadApplicationByUrl(appUrl) { // Start the specified app if there is one specified in command line, otherwise // start the default app. if (option.file && !option.webdriver) { - var protocol = url.parse(option.file).protocol; + var file = option.file; + var protocol = url.parse(file).protocol; + var extension = path.extname(file); if (protocol === 'http:' || protocol === 'https:') { - loadApplicationByUrl(option.file); + loadApplicationByUrl(file); + } else if (extension === '.html' || extension === '.htm') { + loadApplicationByUrl('file://' + path.resolve(file)); } else { - loadPackagePath(option.file); + loadPackagePath(file); } } else if (option.version) { console.log('v' + process.versions.electron); From b74dd43ff564430a54b261688f9cd78dfb46b0b4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Feb 2016 10:34:36 -0800 Subject: [PATCH 013/173] Support opening file: URLs directly --- atom/browser/default_app/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index 09082804b3c..3ec80a6975f 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -281,7 +281,7 @@ if (option.file && !option.webdriver) { var file = option.file; var protocol = url.parse(file).protocol; var extension = path.extname(file); - if (protocol === 'http:' || protocol === 'https:') { + if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:') { loadApplicationByUrl(file); } else if (extension === '.html' || extension === '.htm') { loadApplicationByUrl('file://' + path.resolve(file)); From f482ea4902738e3135a732b24daa50ef2a494383 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Feb 2016 10:35:17 -0800 Subject: [PATCH 014/173] loadPackagePath -> loadApplicationPackage --- atom/browser/default_app/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index 3ec80a6975f..855d2463d25 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -235,7 +235,7 @@ if (option.modules.length > 0) { require('module')._preloadModules(option.modules); } -function loadPackagePath(packagePath) { +function loadApplicationPackage(packagePath) { try { // Override app name and version. packagePath = path.resolve(packagePath); @@ -286,7 +286,7 @@ if (option.file && !option.webdriver) { } else if (extension === '.html' || extension === '.htm') { loadApplicationByUrl('file://' + path.resolve(file)); } else { - loadPackagePath(file); + loadApplicationPackage(file); } } else if (option.version) { console.log('v' + process.versions.electron); From acd5d40ab088d6d88a77d21c6027ff464528d79a Mon Sep 17 00:00:00 2001 From: Vjekoslav Ratkajec Date: Thu, 4 Feb 2016 19:38:47 +0100 Subject: [PATCH 015/173] Adding support to write RTF to clipboard. --- atom/common/api/atom_api_clipboard.cc | 11 +++++++++++ docs/api/clipboard.md | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/atom/common/api/atom_api_clipboard.cc b/atom/common/api/atom_api_clipboard.cc index 0837a3dc93f..5060db17e9a 100644 --- a/atom/common/api/atom_api_clipboard.cc +++ b/atom/common/api/atom_api_clipboard.cc @@ -60,6 +60,11 @@ void Write(const mate::Dictionary& data, if (data.Get("text", &text)) writer.WriteText(text); + if (data.Get("rtf", &text)) { + std::string rtf = base::UTF16ToUTF8(text); + writer.WriteRTF(rtf); + } + if (data.Get("html", &html)) writer.WriteHTML(html, std::string()); @@ -88,6 +93,11 @@ void WriteText(const base::string16& text, mate::Arguments* args) { writer.WriteText(text); } +void WriteRtf(const std::string& text, mate::Arguments* args) { + ui::ScopedClipboardWriter writer(GetClipboardType(args)); + writer.WriteRTF(text); +} + base::string16 ReadHtml(mate::Arguments* args) { base::string16 data; base::string16 html; @@ -129,6 +139,7 @@ void Initialize(v8::Local exports, v8::Local unused, dict.SetMethod("write", &Write); dict.SetMethod("readText", &ReadText); dict.SetMethod("writeText", &WriteText); + dict.SetMethod("writeRtf", &WriteRtf); dict.SetMethod("readHtml", &ReadHtml); dict.SetMethod("writeHtml", &WriteHtml); dict.SetMethod("readImage", &ReadImage); diff --git a/docs/api/clipboard.md b/docs/api/clipboard.md index 7cb5b840bc1..a655977a0e6 100644 --- a/docs/api/clipboard.md +++ b/docs/api/clipboard.md @@ -61,6 +61,12 @@ Returns the content in the clipboard as a [NativeImage](native-image.md). Writes `image` to the clipboard. +### `clipboard.writeRtf(text)` + +* `text` String + +Writes the `text` into the clipboard in RTF. + ### `clipboard.clear([type])` * `type` String (optional) From fa4ad9d95f6ad7243783a6e7de24ce0b0f9e819d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Feb 2016 10:45:52 -0800 Subject: [PATCH 016/173] Tweak help message for new path options --- atom/browser/default_app/main.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index 855d2463d25..6ff26e9ea67 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -294,9 +294,14 @@ if (option.file && !option.webdriver) { } else if (option.help) { var helpMessage = "Electron v" + process.versions.electron + " - Cross Platform Desktop Application Shell\n\n"; helpMessage += "Usage: electron [options] [path]\n\n"; - helpMessage += "A path to an Electron application may be specified. The path must be to \n"; - helpMessage += "an index.js file or to a folder containing a package.json or index.js file.\n\n"; - helpMessage += "Options:\n"; + helpMessage += "A path to an Electron application may be specified.\n"; + helpMessage += "The path must be one of the following:\n\n"; + helpMessage += " - index.js file.\n"; + helpMessage += " - Folder containing a package.json file.\n"; + helpMessage += " - Folder containing an index.js file.\n"; + helpMessage += " - .html/.htm file.\n"; + helpMessage += " - http://, https://, or file:// URL.\n"; + helpMessage += "\nOptions:\n"; helpMessage += " -r, --require Module to preload (option can be repeated)\n"; helpMessage += " -h, --help Print this usage message.\n"; helpMessage += " -v, --version Print the version."; From 252b12be13d2e92a93835b2e9c99ff43fedc18cd Mon Sep 17 00:00:00 2001 From: Vjekoslav Ratkajec Date: Fri, 5 Feb 2016 09:06:21 +0100 Subject: [PATCH 017/173] Add readRtf feature with appropriate spec test. Docs updated as well. --- atom/common/api/atom_api_clipboard.cc | 8 ++++++++ docs/api/clipboard.md | 10 +++++++++- spec/api-clipboard-spec.js | 12 +++++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/atom/common/api/atom_api_clipboard.cc b/atom/common/api/atom_api_clipboard.cc index 5060db17e9a..5186e22c8d9 100644 --- a/atom/common/api/atom_api_clipboard.cc +++ b/atom/common/api/atom_api_clipboard.cc @@ -93,6 +93,13 @@ void WriteText(const base::string16& text, mate::Arguments* args) { writer.WriteText(text); } +base::string16 ReadRtf(mate::Arguments* args) { + std::string data; + ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); + clipboard->ReadRTF(GetClipboardType(args), &data); + return base::UTF8ToUTF16(data); +} + void WriteRtf(const std::string& text, mate::Arguments* args) { ui::ScopedClipboardWriter writer(GetClipboardType(args)); writer.WriteRTF(text); @@ -139,6 +146,7 @@ void Initialize(v8::Local exports, v8::Local unused, dict.SetMethod("write", &Write); dict.SetMethod("readText", &ReadText); dict.SetMethod("writeText", &WriteText); + dict.SetMethod("readRtf", &ReadRtf); dict.SetMethod("writeRtf", &WriteRtf); dict.SetMethod("readHtml", &ReadHtml); dict.SetMethod("writeHtml", &WriteHtml); diff --git a/docs/api/clipboard.md b/docs/api/clipboard.md index a655977a0e6..dcb9fa398a9 100644 --- a/docs/api/clipboard.md +++ b/docs/api/clipboard.md @@ -61,9 +61,17 @@ Returns the content in the clipboard as a [NativeImage](native-image.md). Writes `image` to the clipboard. -### `clipboard.writeRtf(text)` +### `clipboard.readRtf([type])` + +* `type` String (optional) + +Returns the content in the clipboard as RTF. + + +### `clipboard.writeRtf(text[, type])` * `text` String +* `type` String (optional) Writes the `text` into the clipboard in RTF. diff --git a/spec/api-clipboard-spec.js b/spec/api-clipboard-spec.js index 6154181f092..fe94e330d41 100644 --- a/spec/api-clipboard-spec.js +++ b/spec/api-clipboard-spec.js @@ -35,20 +35,30 @@ describe('clipboard module', function() { return assert.equal(clipboard.readHtml(), markup); }); }); + describe('clipboard.readRtf', function() { + return it('returns rtf text correctly', function() { + var rtf = "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}"; + clipboard.writeRtf(rtf); + return assert.equal(clipboard.readRtf(), rtf); + }); + }); return describe('clipboard.write()', function() { return it('returns data correctly', function() { - var i, markup, p, text; + var i, markup, p, text, rtf; text = 'test'; + rtf = '{\\rtf1\\utf8 text}'; p = path.join(fixtures, 'assets', 'logo.png'); i = nativeImage.createFromPath(p); markup = process.platform === 'darwin' ? 'Hi' : process.platform === 'linux' ? 'Hi' : 'Hi'; clipboard.write({ text: "test", html: 'Hi', + rtf: '{\\rtf1\\utf8 text}', image: p }); assert.equal(clipboard.readText(), text); assert.equal(clipboard.readHtml(), markup); + assert.equal(clipboard.readRtf(), rtf); return assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); }); }); From fa734d7824ae9bf1bae7fe0fad2e35fde40b1406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Aur=C3=A8le=20DARCHE?= Date: Sat, 6 Feb 2016 19:57:21 +0100 Subject: [PATCH 018/173] Document different techniques to share objects This has been discussed in --- docs/faq/electron-faq.md | 34 ++++++++++++++++++++++++++++++++++ docs/tutorial/quick-start.md | 3 +++ 2 files changed, 37 insertions(+) diff --git a/docs/faq/electron-faq.md b/docs/faq/electron-faq.md index 643bde7409b..d5470f70173 100644 --- a/docs/faq/electron-faq.md +++ b/docs/faq/electron-faq.md @@ -18,6 +18,40 @@ New features of Node.js are usually brought by V8 upgrades, since Electron is using the V8 shipped by Chrome browser, the shiny new JavaScript feature of a new Node.js version is usually already in Electron. +## What are the different techniques to share objects between web pages? + +To share objects between web pages (that is on the renderer side) the simplest +and more natural technique is to use a web standard API already available in all +browsers. A good candidate is the +[Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Storage), +through either the +[`window.localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) property or the +[`window.sessionStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) property. +Note that the Storage API allows only to store strings, so objects must be +serialized as JSON. +Another candidate is +[IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API). + +Another technique, but this time specific to Electron, is to store objects in +the main process as a global variable and then to access them from the renderers +through the `remote` module: + +```javascript +// In main.js of browser process +global.sharedObject = {}; +``` + +```javascript +// js in page-1.html +require('remote').getGlobal('sharedObject').someProperty = 'some value'; +``` + +```javascript +// js in page-2.html +console.log(require('remote').getGlobal('sharedObject').someProperty); +``` + + ## My app's window/tray disappeared after a few minutes. This happens when the variable which is used to store the window/tray gets diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index ebf907e070f..ccb3836ba1f 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -47,6 +47,9 @@ In Electron, we have provided the [ipc](../api/ipc-renderer.md) module for communication between the main process and renderer process. There is also a [remote](../api/remote.md) module for RPC style communication. +And finally there are different techniques [to share objects between web +pages](../faq/electron-faq.md#) of the same window or of different windows. + ## Write your First Electron App Generally, an Electron app is structured like this: From 702455674bbf721f2191bf294b54a2107eb2dfd2 Mon Sep 17 00:00:00 2001 From: Michael Vasseur Date: Sun, 7 Feb 2016 10:20:38 +0100 Subject: [PATCH 019/173] Using node::Buffer::Copy() instead of node::Buffer::New() to copy the handle bytes to buffer make the buffer really contains the data. --- atom/browser/api/atom_api_window.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index bcf6ccc5a33..ea1d95b79ca 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -109,7 +109,7 @@ void TranslateOldOptions(v8::Isolate* isolate, v8::Local options) { // Converts binary data to Buffer. v8::Local ToBuffer(v8::Isolate* isolate, void* val, int size) { - auto buffer = node::Buffer::New(isolate, static_cast(val), size); + auto buffer = node::Buffer::Copy(isolate, static_cast(val), size); if (buffer.IsEmpty()) return v8::Null(isolate); else From 756aeffe03fabb7939a1fd156217f67dabeebc88 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Feb 2016 15:18:05 -0800 Subject: [PATCH 020/173] Set icon on NSAlert when specified --- atom/browser/ui/message_box_mac.mm | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/atom/browser/ui/message_box_mac.mm b/atom/browser/ui/message_box_mac.mm index f9e9718ebf5..9380f01e384 100644 --- a/atom/browser/ui/message_box_mac.mm +++ b/atom/browser/ui/message_box_mac.mm @@ -8,7 +8,9 @@ #include "atom/browser/native_window.h" #include "base/callback.h" +#include "base/mac/mac_util.h" #include "base/strings/sys_string_conversions.h" +#include "skia/ext/skia_utils_mac.h" @interface ModalDelegate : NSObject { @private @@ -57,7 +59,8 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window, int default_id, const std::string& title, const std::string& message, - const std::string& detail) { + const std::string& detail, + const gfx::ImageSkia& icon) { // Ignore the title; it's the window title on other platforms and ignorable. NSAlert* alert = [[NSAlert alloc] init]; [alert setMessageText:base::SysUTF8ToNSString(message)]; @@ -92,6 +95,12 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window, [[ns_buttons objectAtIndex:default_id] setKeyEquivalent:@"\r"]; } + if (!icon.isNull()) { + NSImage* image = gfx::SkBitmapToNSImageWithColorSpace( + *icon.bitmap(), base::mac::GetGenericRGBColorSpace()); + [alert setIcon:image]; + } + return alert; } @@ -113,7 +122,7 @@ int ShowMessageBox(NativeWindow* parent_window, const gfx::ImageSkia& icon) { NSAlert* alert = CreateNSAlert( parent_window, type, buttons, default_id, title, message, - detail); + detail, icon); // Use runModal for synchronous alert without parent, since we don't have a // window to wait for. @@ -149,7 +158,7 @@ void ShowMessageBox(NativeWindow* parent_window, const MessageBoxCallback& callback) { NSAlert* alert = CreateNSAlert( parent_window, type, buttons, default_id, title, message, - detail); + detail, icon); ModalDelegate* delegate = [[ModalDelegate alloc] initWithCallback:callback andAlert:alert callEndModal:false]; From c842ca1f127cb6e9b1850929c7b6a319c323536b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 09:52:04 -0800 Subject: [PATCH 021/173] Don't use ES6 class for AutoUpdater windows class --- .../api/lib/auto-updater/auto-updater-win.js | 88 +++++++++---------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.js b/atom/browser/api/lib/auto-updater/auto-updater-win.js index f8a07902f21..1c81763f35e 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.js +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.js @@ -4,59 +4,59 @@ const app = require('electron').app; const EventEmitter = require('events').EventEmitter; const squirrelUpdate = require('./squirrel-update-win'); -class AutoUpdater extends EventEmitter { - constructor() { - super(); - } +function AutoUpdater() { + EventEmitter.call(this) +} - quitAndInstall() { - squirrelUpdate.processStart(); - return app.quit(); - } +require('util').inherits(AutoUpdater, EventEmitter); - setFeedURL(updateURL) { - return this.updateURL = updateURL; - } +AutoUpdater.prototype.quitAndInstall = function() { + squirrelUpdate.processStart(); + return app.quit(); +} - checkForUpdates() { - if (!this.updateURL) { - return this.emitError('Update URL is not set'); - } - if (!squirrelUpdate.supported()) { - return this.emitError('Can not find Squirrel'); - } - this.emit('checking-for-update'); - return squirrelUpdate.download(this.updateURL, (function(_this) { - return function(error, update) { +AutoUpdater.prototype.setFeedURL = function(updateURL) { + return this.updateURL = updateURL; +} + +AutoUpdater.prototype.checkForUpdates = function() { + if (!this.updateURL) { + return this.emitError('Update URL is not set'); + } + if (!squirrelUpdate.supported()) { + return this.emitError('Can not find Squirrel'); + } + this.emit('checking-for-update'); + return squirrelUpdate.download(this.updateURL, (function(_this) { + return function(error, update) { + if (error != null) { + return _this.emitError(error); + } + if (update == null) { + return _this.emit('update-not-available'); + } + _this.emit('update-available'); + return squirrelUpdate.update(_this.updateURL, function(error) { + var date, releaseNotes, version; if (error != null) { return _this.emitError(error); } - if (update == null) { - return _this.emit('update-not-available'); - } - _this.emit('update-available'); - return squirrelUpdate.update(_this.updateURL, function(error) { - var date, releaseNotes, version; - if (error != null) { - return _this.emitError(error); - } - releaseNotes = update.releaseNotes, version = update.version; + releaseNotes = update.releaseNotes, version = update.version; - // Following information is not available on Windows, so fake them. - date = new Date; - return _this.emit('update-downloaded', {}, releaseNotes, version, date, _this.updateURL, function() { - return _this.quitAndInstall(); - }); + // Following information is not available on Windows, so fake them. + date = new Date; + return _this.emit('update-downloaded', {}, releaseNotes, version, date, _this.updateURL, function() { + return _this.quitAndInstall(); }); - }; - })(this)); - } + }); + }; + })(this)); +} - // Private: Emit both error object and message, this is to keep compatibility - // with Old APIs. - emitError(message) { - return this.emit('error', new Error(message), message); - } +// Private: Emit both error object and message, this is to keep compatibility +// with Old APIs. +AutoUpdater.prototype.emitError = (message) { + return this.emit('error', new Error(message), message); } module.exports = new AutoUpdater; From 6617592224a9e57e0513e9e05ed59e8a235d67d6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 10:01:01 -0800 Subject: [PATCH 022/173] Remove lint errors --- .../browser/api/lib/auto-updater/auto-updater-win.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.js b/atom/browser/api/lib/auto-updater/auto-updater-win.js index 1c81763f35e..f5f2202f58d 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.js +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.js @@ -5,7 +5,7 @@ const EventEmitter = require('events').EventEmitter; const squirrelUpdate = require('./squirrel-update-win'); function AutoUpdater() { - EventEmitter.call(this) + EventEmitter.call(this); } require('util').inherits(AutoUpdater, EventEmitter); @@ -13,11 +13,11 @@ require('util').inherits(AutoUpdater, EventEmitter); AutoUpdater.prototype.quitAndInstall = function() { squirrelUpdate.processStart(); return app.quit(); -} +}; AutoUpdater.prototype.setFeedURL = function(updateURL) { return this.updateURL = updateURL; -} +}; AutoUpdater.prototype.checkForUpdates = function() { if (!this.updateURL) { @@ -51,12 +51,12 @@ AutoUpdater.prototype.checkForUpdates = function() { }); }; })(this)); -} +}; // Private: Emit both error object and message, this is to keep compatibility // with Old APIs. -AutoUpdater.prototype.emitError = (message) { +AutoUpdater.prototype.emitError = function(message) { return this.emit('error', new Error(message), message); -} +}; module.exports = new AutoUpdater; From 7da4c3acf7b2ac901ef5c5ff2828cec55e434c09 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 11:00:34 -0800 Subject: [PATCH 023/173] Use const for util require --- atom/browser/api/lib/auto-updater/auto-updater-win.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.js b/atom/browser/api/lib/auto-updater/auto-updater-win.js index f5f2202f58d..1270f8f2bdb 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.js +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.js @@ -3,12 +3,13 @@ const app = require('electron').app; const EventEmitter = require('events').EventEmitter; const squirrelUpdate = require('./squirrel-update-win'); +const util = require('util'); function AutoUpdater() { EventEmitter.call(this); } -require('util').inherits(AutoUpdater, EventEmitter); +util.inherits(AutoUpdater, EventEmitter); AutoUpdater.prototype.quitAndInstall = function() { squirrelUpdate.processStart(); From 3ab14e14e9fae0a78ff7f9e88ac7087b87ef1182 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 12:53:56 -0800 Subject: [PATCH 024/173] Add initial auto updater specs --- spec/api-auto-updater-spec.js | 34 ++++++++++++++++++++++++++++++++++ spec/static/main.js | 5 +++++ 2 files changed, 39 insertions(+) create mode 100644 spec/api-auto-updater-spec.js diff --git a/spec/api-auto-updater-spec.js b/spec/api-auto-updater-spec.js new file mode 100644 index 00000000000..72a1d90a7fe --- /dev/null +++ b/spec/api-auto-updater-spec.js @@ -0,0 +1,34 @@ +const assert = require('assert'); +const autoUpdater = require('electron').remote.autoUpdater; +const ipcRenderer = require('electron').ipcRenderer; + +describe('autoUpdater module', function() { + describe('checkForUpdates', function() { + it('emits an error on Windows when called the feed URL is not set', function (done) { + if (process.platform !== 'win32') { + return done(); + } + + ipcRenderer.once('auto-updater-error', function(event, message) { + assert.equal(message, 'Update URL is not set'); + done(); + }); + autoUpdater.setFeedURL(''); + autoUpdater.checkForUpdates(); + }); + }); + + describe('setFeedURL', function() { + it('emits an error on Mac OS X when the application is unsigned', function (done) { + if (process.platform !== 'darwin') { + return done(); + } + + ipcRenderer.once('auto-updater-error', function(event, message) { + assert.equal(message, 'Could not get code signature for running application'); + done(); + }); + autoUpdater.setFeedURL(''); + }); + }); +}); diff --git a/spec/static/main.js b/spec/static/main.js index 13d2dd6a6e1..125ef72f609 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -72,6 +72,11 @@ app.on('ready', function() { // Test if using protocol module would crash. electron.protocol.registerStringProtocol('test-if-crashes', function() {}); + // Send auto updater errors to window to be verified in specs + electron.autoUpdater.on('error', function (error) { + window.send('auto-updater-error', error.message) + }); + window = new BrowserWindow({ title: 'Electron Tests', show: false, From 16594d6ed08240cf4c26b00c3e779095957bd541 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Feb 2016 09:37:44 -0800 Subject: [PATCH 025/173] Add bootstrap script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f0983bc441..218454372fb 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "lint": "python ./script/eslint.py && python ./script/cpplint.py", "preinstall": "node -e 'process.exit(0)'", "start": "python ./script/start.py", - "test": "python ./script/test.py" + "test": "python ./script/test.py", + "bootstrap": "python ./script/bootstrap.py" } } From 03482a442728c7222a6fb38a0346b0395e690461 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Feb 2016 09:39:22 -0800 Subject: [PATCH 026/173] Add build script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 218454372fb..2060e54a1e3 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "preinstall": "node -e 'process.exit(0)'", "start": "python ./script/start.py", "test": "python ./script/test.py", - "bootstrap": "python ./script/bootstrap.py" + "bootstrap": "python ./script/bootstrap.py", + "build": "python ./script/build.py -c D" } } From a8e6e24e58f7bdcd2fecd6e70379aa23baeedeca Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Feb 2016 09:43:29 -0800 Subject: [PATCH 027/173] Sort scripts keys --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 2060e54a1e3..6d812087199 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,11 @@ }, "private": true, "scripts": { + "bootstrap": "python ./script/bootstrap.py", + "build": "python ./script/build.py -c D", "lint": "python ./script/eslint.py && python ./script/cpplint.py", "preinstall": "node -e 'process.exit(0)'", "start": "python ./script/start.py", - "test": "python ./script/test.py", - "bootstrap": "python ./script/bootstrap.py", - "build": "python ./script/build.py -c D" + "test": "python ./script/test.py" } } From 5a8bebc2f8faf6a84073e7dd27fd519a14e5ce67 Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 11 Feb 2016 08:24:50 +0530 Subject: [PATCH 028/173] browser: emit did-fail-load for invalid url --- atom/browser/api/atom_api_web_contents.cc | 8 ++++++++ spec/api-browser-window-spec.js | 17 +++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 80e5b606ef8..a7946786c51 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -710,6 +710,14 @@ bool WebContents::Equal(const WebContents* web_contents) const { } void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) { + if (!url.is_valid()) { + Emit("did-fail-load", + static_cast(net::ERR_INVALID_URL), + net::ErrorToShortString(net::ERR_INVALID_URL), + url.possibly_invalid_spec()); + return; + } + content::NavigationController::LoadURLParams params(url); GURL http_referrer; diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index fc8d3523c8f..72d28bcb6ed 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -94,11 +94,20 @@ describe('browser-window module', function() { }); return w.loadURL('about:blank'); }); - return it('should emit did-fail-load event', function(done) { - w.webContents.on('did-fail-load', function() { - return done(); + it('should emit did-fail-load event for files that do not exist', function(done) { + w.webContents.on('did-fail-load', function(event, code) { + assert.equal(code, -6); + done(); }); - return w.loadURL('file://a.txt'); + w.loadURL('file://a.txt'); + }); + it('should emit did-fail-load event for invalid URL', function(done) { + w.webContents.on('did-fail-load', function(event, code, desc) { + assert.equal(desc, 'ERR_INVALID_URL'); + assert.equal(code, -300); + done(); + }); + w.loadURL('http://example:port'); }); }); describe('BrowserWindow.show()', function() { From 6d2ad5ae5881c2d4af9b41a69eef3e5e83814b60 Mon Sep 17 00:00:00 2001 From: Kevin Jose Martin Date: Thu, 11 Feb 2016 15:34:19 -0500 Subject: [PATCH 029/173] Add ability to specify command line switches in package.json --- atom/browser/lib/init.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/atom/browser/lib/init.js b/atom/browser/lib/init.js index 272cebbf875..df0f1b6685a 100644 --- a/atom/browser/lib/init.js +++ b/atom/browser/lib/init.js @@ -132,6 +132,19 @@ if (packageJson.desktopName != null) { // Chrome 42 disables NPAPI plugins by default, reenable them here app.commandLine.appendSwitch('enable-npapi'); +// Add othercommand line switches +if (packageJson.commandLineSwitches) { + for (let i = 0; i < packageJson.commandLineSwitches.length; ++i) { + const option = packageJson.commandLineSwitches[i]; + + if (typeof option === 'string') { + app.commandLine.appendSwitch(option); + } else { + app.commandLine.appendSwitch(option[0], option[1]); + } + } +} + // Set the user path according to application's name. app.setPath('userData', path.join(app.getPath('appData'), app.getName())); From dbb4e21684a37ce20553c4b04672937d2e6ff887 Mon Sep 17 00:00:00 2001 From: Kevin Jose Martin Date: Thu, 11 Feb 2016 15:41:36 -0500 Subject: [PATCH 030/173] Fix index increment --- atom/browser/lib/init.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/lib/init.js b/atom/browser/lib/init.js index df0f1b6685a..b687aa6eeda 100644 --- a/atom/browser/lib/init.js +++ b/atom/browser/lib/init.js @@ -132,9 +132,9 @@ if (packageJson.desktopName != null) { // Chrome 42 disables NPAPI plugins by default, reenable them here app.commandLine.appendSwitch('enable-npapi'); -// Add othercommand line switches +// Add other command line switches if (packageJson.commandLineSwitches) { - for (let i = 0; i < packageJson.commandLineSwitches.length; ++i) { + for (let i = 0; i < packageJson.commandLineSwitches.length; i++) { const option = packageJson.commandLineSwitches[i]; if (typeof option === 'string') { From 55d4db1387c4f97dc72b00d8524d64dbfa8feeb8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:03:49 -0800 Subject: [PATCH 031/173] :art: --- atom/browser/api/lib/web-contents.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/lib/web-contents.js b/atom/browser/api/lib/web-contents.js index 709694bcf72..08252923fc2 100644 --- a/atom/browser/api/lib/web-contents.js +++ b/atom/browser/api/lib/web-contents.js @@ -76,8 +76,8 @@ let wrapWebContents = function(webContents) { // WebContents::send(channel, args..) webContents.send = function() { - var args, channel; - channel = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + var args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + var channel = arguments[0]; return this._send(channel, slice.call(args)); }; From 4828835998f05e2b59d2ff48a17768472de6636a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:12:45 -0800 Subject: [PATCH 032/173] Clean up returns after CoffeeScript migration --- spec/api-browser-window-spec.js | 240 +++++++++++++++++++------------- 1 file changed, 140 insertions(+), 100 deletions(-) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index fc8d3523c8f..69b895c366d 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -14,29 +14,31 @@ const BrowserWindow = remote.require('electron').BrowserWindow; const isCI = remote.getGlobal('isCi'); describe('browser-window module', function() { - var fixtures, w; - fixtures = path.resolve(__dirname, 'fixtures'); - w = null; + var fixtures = path.resolve(__dirname, 'fixtures'); + var w = null; + beforeEach(function() { if (w != null) { w.destroy(); } - return w = new BrowserWindow({ + w = new BrowserWindow({ show: false, width: 400, height: 400 }); }); + afterEach(function() { if (w != null) { w.destroy(); } - return w = null; + w = null; }); + describe('BrowserWindow.close()', function() { it('should emit unload handler', function(done) { w.webContents.on('did-finish-load', function() { - return w.close(); + w.close(); }); w.on('closed', function() { var content, test; @@ -44,20 +46,22 @@ describe('browser-window module', function() { content = fs.readFileSync(test); fs.unlinkSync(test); assert.equal(String(content), 'unload'); - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'unload.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'unload.html')); }); - return it('should emit beforeunload handler', function(done) { + + it('should emit beforeunload handler', function(done) { w.on('onbeforeunload', function() { - return done(); + done(); }); w.webContents.on('did-finish-load', function() { - return w.close(); + w.close(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'beforeunload-false.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'beforeunload-false.html')); }); }); + describe('window.close()', function() { it('should emit unload handler', function(done) { w.on('closed', function() { @@ -66,104 +70,113 @@ describe('browser-window module', function() { content = fs.readFileSync(test); fs.unlinkSync(test); assert.equal(String(content), 'close'); - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close.html')); }); - return it('should emit beforeunload handler', function(done) { + + it('should emit beforeunload handler', function(done) { w.on('onbeforeunload', function() { - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html')); }); }); + describe('BrowserWindow.destroy()', function() { - return it('prevents users to access methods of webContents', function() { + it('prevents users to access methods of webContents', function() { var webContents; webContents = w.webContents; w.destroy(); - return assert.throws((function() { - return webContents.getId(); + assert.throws((function() { + webContents.getId(); }), /Object has been destroyed/); }); }); + describe('BrowserWindow.loadURL(url)', function() { it('should emit did-start-loading event', function(done) { w.webContents.on('did-start-loading', function() { - return done(); + done(); }); - return w.loadURL('about:blank'); + w.loadURL('about:blank'); }); - return it('should emit did-fail-load event', function(done) { + + it('should emit did-fail-load event', function(done) { w.webContents.on('did-fail-load', function() { - return done(); + done(); }); - return w.loadURL('file://a.txt'); + w.loadURL('file://a.txt'); }); }); + describe('BrowserWindow.show()', function() { - return it('should focus on window', function() { + it('should focus on window', function() { if (isCI) { return; } + w.show(); - return assert(w.isFocused()); + assert(w.isFocused()); }); }); + describe('BrowserWindow.showInactive()', function() { - return it('should not focus on window', function() { + it('should not focus on window', function() { w.showInactive(); - return assert(!w.isFocused()); + assert(!w.isFocused()); }); }); + describe('BrowserWindow.focus()', function() { - return it('does not make the window become visible', function() { + it('does not make the window become visible', function() { assert.equal(w.isVisible(), false); w.focus(); - return assert.equal(w.isVisible(), false); + assert.equal(w.isVisible(), false); }); }); + describe('BrowserWindow.capturePage(rect, callback)', function() { - return it('calls the callback with a Buffer', function(done) { - return w.capturePage({ + it('calls the callback with a Buffer', function(done) { + w.capturePage({ x: 0, y: 0, width: 100, height: 100 }, function(image) { assert.equal(image.isEmpty(), true); - return done(); + done(); }); }); }); + describe('BrowserWindow.setSize(width, height)', function() { - return it('sets the window size', function(done) { - var size; - size = [300, 400]; + it('sets the window size', function(done) { + var size = [300, 400]; w.once('resize', function() { - var newSize; - newSize = w.getSize(); + var newSize = w.getSize(); assert.equal(newSize[0], size[0]); assert.equal(newSize[1], size[1]); - return done(); + done(); }); - return w.setSize(size[0], size[1]); + w.setSize(size[0], size[1]); }); }); + describe('BrowserWindow.setPosition(x, y)', function() { - return it('sets the window position', function(done) { - var pos; - pos = [10, 10]; + it('sets the window position', function(done) { + var pos = [10, 10]; w.once('move', function() { var newPos; newPos = w.getPosition(); assert.equal(newPos[0], pos[0]); assert.equal(newPos[1], pos[1]); - return done(); + done(); }); - return w.setPosition(pos[0], pos[1]); + w.setPosition(pos[0], pos[1]); }); }); + describe('BrowserWindow.setContentSize(width, height)', function() { it('sets the content size', function() { var after, size; @@ -171,9 +184,10 @@ describe('browser-window module', function() { w.setContentSize(size[0], size[1]); after = w.getContentSize(); assert.equal(after[0], size[0]); - return assert.equal(after[1], size[1]); + assert.equal(after[1], size[1]); }); - return it('works for framless window', function() { + + it('works for framless window', function() { var after, size; w.destroy(); w = new BrowserWindow({ @@ -186,14 +200,16 @@ describe('browser-window module', function() { w.setContentSize(size[0], size[1]); after = w.getContentSize(); assert.equal(after[0], size[0]); - return assert.equal(after[1], size[1]); + assert.equal(after[1], size[1]); }); }); + describe('BrowserWindow.fromId(id)', function() { - return it('returns the window with id', function() { - return assert.equal(w.id, BrowserWindow.fromId(w.id).id); + it('returns the window with id', function() { + assert.equal(w.id, BrowserWindow.fromId(w.id).id); }); }); + describe('"useContentSize" option', function() { it('make window created with content size when used', function() { var contentSize; @@ -206,15 +222,16 @@ describe('browser-window module', function() { }); contentSize = w.getContentSize(); assert.equal(contentSize[0], 400); - return assert.equal(contentSize[1], 400); + assert.equal(contentSize[1], 400); }); + it('make window created with window size when not used', function() { - var size; - size = w.getSize(); + var size = w.getSize(); assert.equal(size[0], 400); - return assert.equal(size[1], 400); + assert.equal(size[1], 400); }); - return it('works for framless window', function() { + + it('works for framless window', function() { var contentSize, size; w.destroy(); w = new BrowserWindow({ @@ -229,9 +246,10 @@ describe('browser-window module', function() { assert.equal(contentSize[1], 400); size = w.getSize(); assert.equal(size[0], 400); - return assert.equal(size[1], 400); + assert.equal(size[1], 400); }); }); + describe('"title-bar-style" option', function() { if (process.platform !== 'darwin') { return; @@ -239,6 +257,7 @@ describe('browser-window module', function() { if (parseInt(os.release().split('.')[0]) < 14) { return; } + it('creates browser window with hidden title bar', function() { var contentSize; w.destroy(); @@ -249,9 +268,10 @@ describe('browser-window module', function() { titleBarStyle: 'hidden' }); contentSize = w.getContentSize(); - return assert.equal(contentSize[1], 400); + assert.equal(contentSize[1], 400); }); - return it('creates browser window with hidden inset title bar', function() { + + it('creates browser window with hidden inset title bar', function() { var contentSize; w.destroy(); w = new BrowserWindow({ @@ -261,30 +281,34 @@ describe('browser-window module', function() { titleBarStyle: 'hidden-inset' }); contentSize = w.getContentSize(); - return assert.equal(contentSize[1], 400); + assert.equal(contentSize[1], 400); }); }); + describe('"enableLargerThanScreen" option', function() { if (process.platform === 'linux') { return; } + beforeEach(function() { w.destroy(); - return w = new BrowserWindow({ + w = new BrowserWindow({ show: true, width: 400, height: 400, enableLargerThanScreen: true }); }); + it('can move the window out of screen', function() { var after; w.setPosition(-10, -10); after = w.getPosition(); assert.equal(after[0], -10); - return assert.equal(after[1], -10); + assert.equal(after[1], -10); }); - return it('can set the window larger than screen', function() { + + it('can set the window larger than screen', function() { var after, size; size = screen.getPrimaryDisplay().size; size.width += 100; @@ -292,21 +316,22 @@ describe('browser-window module', function() { w.setSize(size.width, size.height); after = w.getSize(); assert.equal(after[0], size.width); - return assert.equal(after[1], size.height); + assert.equal(after[1], size.height); }); }); describe('"web-preferences" option', function() { afterEach(function() { - return ipcMain.removeAllListeners('answer'); + ipcMain.removeAllListeners('answer'); }); + describe('"preload" option', function() { - return it('loads the script before other scripts in window', function(done) { + it('loads the script before other scripts in window', function(done) { var preload; preload = path.join(fixtures, 'module', 'set-global.js'); ipcMain.once('answer', function(event, test) { assert.equal(test, 'preload'); - return done(); + done(); }); w.destroy(); w = new BrowserWindow({ @@ -315,16 +340,17 @@ describe('browser-window module', function() { preload: preload } }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'preload.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'preload.html')); }); }); - return describe('"node-integration" option', function() { - return it('disables node integration when specified to false', function(done) { + + describe('"node-integration" option', function() { + it('disables node integration when specified to false', function(done) { var preload; preload = path.join(fixtures, 'module', 'send-later.js'); ipcMain.once('answer', function(event, test) { assert.equal(test, 'undefined'); - return done(); + done(); }); w.destroy(); w = new BrowserWindow({ @@ -334,107 +360,121 @@ describe('browser-window module', function() { nodeIntegration: false } }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'blank.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'blank.html')); }); }); }); + describe('beforeunload handler', function() { it('returning true would not prevent close', function(done) { w.on('closed', function() { - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-true.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-true.html')); }); + it('returning non-empty string would not prevent close', function(done) { w.on('closed', function() { - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-string.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-string.html')); }); + it('returning false would prevent close', function(done) { w.on('onbeforeunload', function() { - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html')); }); - return it('returning empty string would prevent close', function(done) { + + it('returning empty string would prevent close', function(done) { w.on('onbeforeunload', function() { - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-empty-string.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-empty-string.html')); }); }); + describe('new-window event', function() { if (isCI && process.platform === 'darwin') { return; } + it('emits when window.open is called', function(done) { w.webContents.once('new-window', function(e, url, frameName) { e.preventDefault(); assert.equal(url, 'http://host/'); assert.equal(frameName, 'host'); - return done(); + done(); }); - return w.loadURL("file://" + fixtures + "/pages/window-open.html"); + w.loadURL("file://" + fixtures + "/pages/window-open.html"); }); - return it('emits when link with target is called', function(done) { + + it('emits when link with target is called', function(done) { this.timeout(10000); w.webContents.once('new-window', function(e, url, frameName) { e.preventDefault(); assert.equal(url, 'http://host/'); assert.equal(frameName, 'target'); - return done(); + done(); }); - return w.loadURL("file://" + fixtures + "/pages/target-name.html"); + w.loadURL("file://" + fixtures + "/pages/target-name.html"); }); }); + describe('maximize event', function() { if (isCI) { return; } - return it('emits when window is maximized', function(done) { + + it('emits when window is maximized', function(done) { this.timeout(10000); w.once('maximize', function() { - return done(); + done(); }); w.show(); - return w.maximize(); + w.maximize(); }); }); + describe('unmaximize event', function() { if (isCI) { return; } - return it('emits when window is unmaximized', function(done) { + + it('emits when window is unmaximized', function(done) { this.timeout(10000); w.once('unmaximize', function() { - return done(); + done(); }); w.show(); w.maximize(); - return w.unmaximize(); + w.unmaximize(); }); }); + describe('minimize event', function() { if (isCI) { return; } - return it('emits when window is minimized', function(done) { + + it('emits when window is minimized', function(done) { this.timeout(10000); w.once('minimize', function() { - return done(); + done(); }); w.show(); - return w.minimize(); + w.minimize(); }); }); + xdescribe('beginFrameSubscription method', function() { - return it('subscribes frame updates', function(done) { + it('subscribes frame updates', function(done) { w.loadURL("file://" + fixtures + "/api/blank.html"); - return w.webContents.beginFrameSubscription(function(data) { + w.webContents.beginFrameSubscription(function(data) { assert.notEqual(data.length, 0); w.webContents.endFrameSubscription(); - return done(); + done(); }); }); }); @@ -472,13 +512,13 @@ describe('browser-window module', function() { }); describe('BrowserWindow options argument is optional', function() { - return it('should create a window with default size (800x600)', function() { + it('should create a window with default size (800x600)', function() { var size; w.destroy(); w = new BrowserWindow(); size = w.getSize(); assert.equal(size[0], 800); - return assert.equal(size[1], 600); + assert.equal(size[1], 600); }); }); From cead84d5d118bfc6b6a8d5418474959fd3021c54 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:18:01 -0800 Subject: [PATCH 033/173] Add failing spec --- spec/api-browser-window-spec.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 69b895c366d..d91e9d410e0 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -658,4 +658,12 @@ describe('browser-window module', function() { }); }); }); + + describe('window.webContents.send(channel, args...)', function() { + it('throws an error when the channel is missing', function() { + assert.throws(function () { + w.webContents.send(); + }, 'channel must be specified'); + }); + }); }); From c94f1fc857e0c07303e60d8df0e89e48808f207c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:20:55 -0800 Subject: [PATCH 034/173] Throw error when IPC channel is missing --- atom/browser/api/lib/web-contents.js | 3 +++ spec/api-browser-window-spec.js | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/atom/browser/api/lib/web-contents.js b/atom/browser/api/lib/web-contents.js index 08252923fc2..8dde10df4d1 100644 --- a/atom/browser/api/lib/web-contents.js +++ b/atom/browser/api/lib/web-contents.js @@ -78,6 +78,9 @@ let wrapWebContents = function(webContents) { webContents.send = function() { var args = 2 <= arguments.length ? slice.call(arguments, 1) : []; var channel = arguments[0]; + if (channel == null) { + throw new Error('channel must be specified'); + } return this._send(channel, slice.call(args)); }; diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index d91e9d410e0..ee34ba2c576 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -664,6 +664,10 @@ describe('browser-window module', function() { assert.throws(function () { w.webContents.send(); }, 'channel must be specified'); + + assert.throws(function () { + w.webContents.send(null); + }, 'channel must be specified'); }); }); }); From 3e399d09d7bdcd21154f65a233e487ca2c65c15f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:24:48 -0800 Subject: [PATCH 035/173] Match existing function style --- spec/api-browser-window-spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index ee34ba2c576..cb041a9320d 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -661,11 +661,11 @@ describe('browser-window module', function() { describe('window.webContents.send(channel, args...)', function() { it('throws an error when the channel is missing', function() { - assert.throws(function () { + assert.throws(function() { w.webContents.send(); }, 'channel must be specified'); - assert.throws(function () { + assert.throws(function() { w.webContents.send(null); }, 'channel must be specified'); }); From 704bd4d191a399107a0a3ea187628a851940adb5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:34:50 -0800 Subject: [PATCH 036/173] Improve error message --- atom/browser/api/lib/web-contents.js | 2 +- spec/api-browser-window-spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/lib/web-contents.js b/atom/browser/api/lib/web-contents.js index 8dde10df4d1..e0c16999c72 100644 --- a/atom/browser/api/lib/web-contents.js +++ b/atom/browser/api/lib/web-contents.js @@ -79,7 +79,7 @@ let wrapWebContents = function(webContents) { var args = 2 <= arguments.length ? slice.call(arguments, 1) : []; var channel = arguments[0]; if (channel == null) { - throw new Error('channel must be specified'); + throw new Error('Missing required channel argument'); } return this._send(channel, slice.call(args)); }; diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index cb041a9320d..d59eb9a8baa 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -663,11 +663,11 @@ describe('browser-window module', function() { it('throws an error when the channel is missing', function() { assert.throws(function() { w.webContents.send(); - }, 'channel must be specified'); + }, 'Missing required channel argument'); assert.throws(function() { w.webContents.send(null); - }, 'channel must be specified'); + }, 'Missing required channel argument'); }); }); }); From a4d21cadfa3d6a7e706d1bae61b424e599301c08 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Feb 2016 10:27:05 -0800 Subject: [PATCH 037/173] Format webview spec post CoffeeScript conversion --- spec/webview-spec.js | 335 ++++++++++++++++++++++++------------------- 1 file changed, 188 insertions(+), 147 deletions(-) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index cac5fb56b44..904dfcab6e0 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -1,166 +1,175 @@ -var assert, http, path, url; - -assert = require('assert'); - -path = require('path'); - -http = require('http'); - -url = require('url'); +const assert = require('assert'); +const path = require('path'); +const http = require('http'); +const url = require('url'); describe(' tag', function() { - var fixtures, webview; this.timeout(10000); - fixtures = path.join(__dirname, 'fixtures'); - webview = null; + + var fixtures = path.join(__dirname, 'fixtures'); + var webview = null; + beforeEach(function() { - return webview = new WebView; + webview = new WebView; }); + afterEach(function() { if (document.body.contains(webview)) { - return document.body.removeChild(webview); + document.body.removeChild(webview); } }); + describe('src attribute', function() { it('specifies the page to load', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'a'); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/a.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('navigates to new page when changed', function(done) { + + it('navigates to new page when changed', function(done) { var listener = function() { webview.src = "file://" + fixtures + "/pages/b.html"; webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'b'); - return done(); + done(); }); - return webview.removeEventListener('did-finish-load', listener); + webview.removeEventListener('did-finish-load', listener); }; webview.addEventListener('did-finish-load', listener); webview.src = "file://" + fixtures + "/pages/a.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('nodeintegration attribute', function() { it('inserts no node symbols when not set', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'undefined undefined undefined undefined'); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/c.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('inserts node symbols when set', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'function object object'); - return done(); + done(); }); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/d.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('loads node symbols after POST navigation when set', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'function object object'); - return done(); + done(); }); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/post.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) { - return it('loads native modules when navigation happens', function(done) { + it('loads native modules when navigation happens', function(done) { var listener = function() { webview.removeEventListener('did-finish-load', listener); var listener2 = function(e) { assert.equal(e.message, 'function'); - return done(); + done(); }; webview.addEventListener('console-message', listener2); - return webview.reload(); + webview.reload(); }; webview.addEventListener('did-finish-load', listener); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/native-module.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); } }); + describe('preload attribute', function() { it('loads the script before other scripts in window', function(done) { var listener; listener = function(e) { assert.equal(e.message, 'function object object'); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.setAttribute('preload', fixtures + "/module/preload.js"); webview.src = "file://" + fixtures + "/pages/e.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('preload script can still use "process" in required modules when nodeintegration is off', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'object undefined object'); - return done(); + done(); }); webview.setAttribute('preload', fixtures + "/module/preload-node-off.js"); webview.src = "file://" + fixtures + "/api/blank.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('receives ipc message in preload script', function(done) { + + it('receives ipc message in preload script', function(done) { var listener, listener2, message; message = 'boom!'; listener = function(e) { assert.equal(e.channel, 'pong'); assert.deepEqual(e.args, [message]); webview.removeEventListener('ipc-message', listener); - return done(); + done(); }; listener2 = function() { webview.send('ping', message); - return webview.removeEventListener('did-finish-load', listener2); + webview.removeEventListener('did-finish-load', listener2); }; webview.addEventListener('ipc-message', listener); webview.addEventListener('did-finish-load', listener2); webview.setAttribute('preload', fixtures + "/module/preload-ipc.js"); webview.src = "file://" + fixtures + "/pages/e.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('httpreferrer attribute', function() { - return it('sets the referrer url', function(done) { + it('sets the referrer url', function(done) { var listener, referrer; referrer = 'http://github.com/'; listener = function(e) { assert.equal(e.message, referrer); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.setAttribute('httpreferrer', referrer); webview.src = "file://" + fixtures + "/pages/referrer.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('useragent attribute', function() { - return it('sets the user agent', function(done) { + it('sets the user agent', function(done) { var listener, referrer; referrer = 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'; listener = function(e) { assert.equal(e.message, referrer); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.setAttribute('useragent', referrer); webview.src = "file://" + fixtures + "/pages/useragent.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('disablewebsecurity attribute', function() { it('does not disable web security when not set', function(done) { var encoded, listener, src; @@ -169,164 +178,177 @@ describe(' tag', function() { listener = function(e) { assert(/Not allowed to load local resource/.test(e.message)); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.src = "data:text/html;base64," + encoded; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('disables web security when set', function(done) { + + it('disables web security when set', function(done) { var encoded, listener, src; src = " "; encoded = btoa(unescape(encodeURIComponent(src))); listener = function(e) { assert.equal(e.message, 'ok'); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.setAttribute('disablewebsecurity', ''); webview.src = "data:text/html;base64," + encoded; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); describe('partition attribute', function() { it('inserts no node symbols when not set', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'undefined undefined undefined undefined'); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/c.html"; webview.partition = 'test1'; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('inserts node symbols when set', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'function object object'); - return done(); + done(); }); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/d.html"; webview.partition = 'test2'; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('isolates storage for different id', function(done) { var listener; listener = function(e) { assert.equal(e.message, " 0"); webview.removeEventListener('console-message', listener); - return done(); + done(); }; window.localStorage.setItem('test', 'one'); webview.addEventListener('console-message', listener); webview.src = "file://" + fixtures + "/pages/partition/one.html"; webview.partition = 'test3'; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('uses current session storage when no id is provided', function(done) { + + it('uses current session storage when no id is provided', function(done) { var listener; listener = function(e) { assert.equal(e.message, "one 1"); webview.removeEventListener('console-message', listener); - return done(); + done(); }; window.localStorage.setItem('test', 'one'); webview.addEventListener('console-message', listener); webview.src = "file://" + fixtures + "/pages/partition/one.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('allowpopups attribute', function() { it('can not open new window when not set', function(done) { var listener; listener = function(e) { assert.equal(e.message, 'null'); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.src = "file://" + fixtures + "/pages/window-open-hide.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('can open new window when set', function(done) { + + it('can open new window when set', function(done) { var listener; listener = function(e) { assert.equal(e.message, 'window'); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.setAttribute('allowpopups', 'on'); webview.src = "file://" + fixtures + "/pages/window-open-hide.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('new-window event', function() { it('emits when window.open is called', function(done) { webview.addEventListener('new-window', function(e) { assert.equal(e.url, 'http://host/'); assert.equal(e.frameName, 'host'); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/window-open.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('emits when link with target is called', function(done) { + + it('emits when link with target is called', function(done) { webview.addEventListener('new-window', function(e) { assert.equal(e.url, 'http://host/'); assert.equal(e.frameName, 'target'); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/target-name.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('ipc-message event', function() { - return it('emits when guest sends a ipc message to browser', function(done) { + it('emits when guest sends a ipc message to browser', function(done) { webview.addEventListener('ipc-message', function(e) { assert.equal(e.channel, 'channel'); assert.deepEqual(e.args, ['arg1', 'arg2']); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/ipc-message.html"; webview.setAttribute('nodeintegration', 'on'); - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('page-title-set event', function() { - return it('emits when title is set', function(done) { + it('emits when title is set', function(done) { webview.addEventListener('page-title-set', function(e) { assert.equal(e.title, 'test'); assert(e.explicitSet); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/a.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('page-favicon-updated event', function() { - return it('emits when favicon urls are received', function(done) { + it('emits when favicon urls are received', function(done) { webview.addEventListener('page-favicon-updated', function(e) { var pageUrl; assert.equal(e.favicons.length, 2); pageUrl = process.platform === 'win32' ? 'file:///C:/favicon.png' : 'file:///favicon.png'; assert.equal(e.favicons[0], pageUrl); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/a.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('will-navigate event', function() { - return it('emits when a url that leads to oustide of the page is clicked', function(done) { + it('emits when a url that leads to oustide of the page is clicked', function(done) { webview.addEventListener('will-navigate', function(e) { assert.equal(e.url, "http://host/"); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/webview-will-navigate.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('did-navigate event', function() { var p, pageUrl; p = path.join(fixtures, 'pages', 'webview-will-navigate.html'); @@ -336,13 +358,14 @@ describe(' tag', function() { slashes: true, pathname: p }); - return it('emits when a url that leads to outside of the page is clicked', function(done) { + + it('emits when a url that leads to outside of the page is clicked', function(done) { webview.addEventListener('did-navigate', function(e) { assert.equal(e.url, pageUrl); - return done(); + done(); }); webview.src = pageUrl; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); describe('did-navigate-in-page event', function() { @@ -357,20 +380,22 @@ describe(' tag', function() { }); webview.addEventListener('did-navigate-in-page', function(e) { assert.equal(e.url, pageUrl + "#test_content"); - return done(); + done(); }); webview.src = pageUrl; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('emits when window.history.replaceState is called', function(done) { webview.addEventListener('did-navigate-in-page', function(e) { assert.equal(e.url, "http://host/"); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/webview-did-navigate-in-page-with-history.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('emits when window.location.hash is changed', function(done) { + + it('emits when window.location.hash is changed', function(done) { var p, pageUrl; p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page-with-hash.html'); p = p.replace(/\\/g, '/'); @@ -381,94 +406,100 @@ describe(' tag', function() { }); webview.addEventListener('did-navigate-in-page', function(e) { assert.equal(e.url, pageUrl + "#test"); - return done(); + done(); }); webview.src = pageUrl; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('close event', function() { - return it('should fire when interior page calls window.close', function(done) { + it('should fire when interior page calls window.close', function(done) { webview.addEventListener('close', function() { - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/close.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('devtools-opened event', function() { - return it('should fire when webview.openDevTools() is called', function(done) { + it('should fire when webview.openDevTools() is called', function(done) { var listener; listener = function() { webview.removeEventListener('devtools-opened', listener); webview.closeDevTools(); - return done(); + done(); }; webview.addEventListener('devtools-opened', listener); webview.addEventListener('dom-ready', function() { - return webview.openDevTools(); + webview.openDevTools(); }); webview.src = "file://" + fixtures + "/pages/base-page.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('devtools-closed event', function() { - return it('should fire when webview.closeDevTools() is called', function(done) { + it('should fire when webview.closeDevTools() is called', function(done) { var listener, listener2; listener2 = function() { webview.removeEventListener('devtools-closed', listener2); - return done(); + done(); }; listener = function() { webview.removeEventListener('devtools-opened', listener); - return webview.closeDevTools(); + webview.closeDevTools(); }; webview.addEventListener('devtools-opened', listener); webview.addEventListener('devtools-closed', listener2); webview.addEventListener('dom-ready', function() { - return webview.openDevTools(); + webview.openDevTools(); }); webview.src = "file://" + fixtures + "/pages/base-page.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('devtools-focused event', function() { - return it('should fire when webview.openDevTools() is called', function(done) { + it('should fire when webview.openDevTools() is called', function(done) { var listener; listener = function() { webview.removeEventListener('devtools-focused', listener); webview.closeDevTools(); - return done(); + done(); }; webview.addEventListener('devtools-focused', listener); webview.addEventListener('dom-ready', function() { - return webview.openDevTools(); + webview.openDevTools(); }); webview.src = "file://" + fixtures + "/pages/base-page.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('.reload()', function() { - return it('should emit beforeunload handler', function(done) { + it('should emit beforeunload handler', function(done) { var listener, listener2; listener = function(e) { assert.equal(e.channel, 'onbeforeunload'); webview.removeEventListener('ipc-message', listener); - return done(); + done(); }; listener2 = function() { webview.reload(); - return webview.removeEventListener('did-finish-load', listener2); + webview.removeEventListener('did-finish-load', listener2); }; webview.addEventListener('ipc-message', listener); webview.addEventListener('did-finish-load', listener2); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/beforeunload-false.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('.clearHistory()', function() { - return it('should clear the navigation history', function(done) { + it('should clear the navigation history', function(done) { var listener; listener = function(e) { assert.equal(e.channel, 'history'); @@ -477,18 +508,19 @@ describe(' tag', function() { webview.clearHistory(); assert(!webview.canGoBack()); webview.removeEventListener('ipc-message', listener); - return done(); + done(); }; webview.addEventListener('ipc-message', listener); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/history.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('basic auth', function() { var auth; auth = require('basic-auth'); - return it('should authenticate with correct credentials', function(done) { + it('should authenticate with correct credentials', function(done) { var message, server; message = 'Authenticated'; server = http.createServer(function(req, res) { @@ -499,67 +531,71 @@ describe(' tag', function() { } else { res.end('failed'); } - return server.close(); + server.close(); }); - return server.listen(0, '127.0.0.1', function() { + server.listen(0, '127.0.0.1', function() { var port; port = server.address().port; webview.addEventListener('ipc-message', function(e) { assert.equal(e.channel, message); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/basic-auth.html?port=" + port; webview.setAttribute('nodeintegration', 'on'); - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); }); + describe('dom-ready event', function() { - return it('emits when document is loaded', function(done) { + it('emits when document is loaded', function(done) { var server; server = http.createServer(function() {}); - return server.listen(0, '127.0.0.1', function() { + server.listen(0, '127.0.0.1', function() { var port; port = server.address().port; webview.addEventListener('dom-ready', function() { - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/dom-ready.html?port=" + port; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); }); + describe('executeJavaScript', function() { if (process.env.TRAVIS !== 'true') { return; } - return it('should support user gesture', function(done) { + + it('should support user gesture', function(done) { var listener, listener2; listener = function() { webview.removeEventListener('enter-html-full-screen', listener); - return done(); + done(); }; listener2 = function() { var jsScript; jsScript = 'document.getElementsByTagName("video")[0].webkitRequestFullScreen()'; webview.executeJavaScript(jsScript, true); - return webview.removeEventListener('did-finish-load', listener2); + webview.removeEventListener('did-finish-load', listener2); }; webview.addEventListener('enter-html-full-screen', listener); webview.addEventListener('did-finish-load', listener2); webview.src = "file://" + fixtures + "/pages/fullscreen.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('sendInputEvent', function() { it('can send keyboard event', function(done) { webview.addEventListener('ipc-message', function(e) { assert.equal(e.channel, 'keyup'); assert.deepEqual(e.args, [67, true, false]); - return done(); + done(); }); webview.addEventListener('dom-ready', function() { - return webview.sendInputEvent({ + webview.sendInputEvent({ type: 'keyup', keyCode: 'c', modifiers: ['shift'] @@ -567,16 +603,17 @@ describe(' tag', function() { }); webview.src = "file://" + fixtures + "/pages/onkeyup.html"; webview.setAttribute('nodeintegration', 'on'); - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('can send mouse event', function(done) { + + it('can send mouse event', function(done) { webview.addEventListener('ipc-message', function(e) { assert.equal(e.channel, 'mouseup'); assert.deepEqual(e.args, [10, 20, false, true]); - return done(); + done(); }); webview.addEventListener('dom-ready', function() { - return webview.sendInputEvent({ + webview.sendInputEvent({ type: 'mouseup', modifiers: ['ctrl'], x: 10, @@ -585,26 +622,28 @@ describe(' tag', function() { }); webview.src = "file://" + fixtures + "/pages/onmouseup.html"; webview.setAttribute('nodeintegration', 'on'); - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('media-started-playing media-paused events', function() { - return it('emits when audio starts and stops playing', function(done) { + it('emits when audio starts and stops playing', function(done) { var audioPlayed; audioPlayed = false; webview.addEventListener('media-started-playing', function() { - return audioPlayed = true; + audioPlayed = true; }); webview.addEventListener('media-paused', function() { assert(audioPlayed); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/audio.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('found-in-page event', function() { - return it('emits when a request is made', function(done) { + it('emits when a request is made', function(done) { var listener, listener2, requestId; requestId = null; listener = function(e) { @@ -612,27 +651,29 @@ describe(' tag', function() { if (e.result.finalUpdate) { assert.equal(e.result.matches, 3); webview.stopFindInPage("clearSelection"); - return done(); + done(); } }; listener2 = function() { - return requestId = webview.findInPage("virtual"); + requestId = webview.findInPage("virtual"); }; webview.addEventListener('found-in-page', listener); webview.addEventListener('did-finish-load', listener2); webview.src = "file://" + fixtures + "/pages/content.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + xdescribe('did-change-theme-color event', function() { - return it('emits when theme color changes', function(done) { + it('emits when theme color changes', function(done) { webview.addEventListener('did-change-theme-color', function() { - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/theme-color.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('permission-request event', function() { function setUpRequestHandler(webview, requested_permission) { const session = require('electron').remote.session; @@ -645,7 +686,7 @@ describe(' tag', function() { session.fromPartition(webview.partition).setPermissionRequestHandler(listener); } - it ('emits when using navigator.getUserMedia api', function(done) { + it('emits when using navigator.getUserMedia api', function(done) { webview.addEventListener('ipc-message', function(e) { assert(e.channel, 'message'); assert(e.args, ['PermissionDeniedError']); @@ -658,7 +699,7 @@ describe(' tag', function() { document.body.appendChild(webview); }); - it ('emits when using navigator.geolocation api', function(done) { + it('emits when using navigator.geolocation api', function(done) { webview.addEventListener('ipc-message', function(e) { assert(e.channel, 'message'); assert(e.args, ['ERROR(1): User denied Geolocation']); @@ -671,7 +712,7 @@ describe(' tag', function() { document.body.appendChild(webview); }); - it ('emits when using navigator.requestMIDIAccess api', function(done) { + it('emits when using navigator.requestMIDIAccess api', function(done) { webview.addEventListener('ipc-message', function(e) { assert(e.channel, 'message'); assert(e.args, ['SecurityError']); From 6bc48ba123f31148f9d41790447ff0c58fd16b70 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Feb 2016 10:48:07 -0800 Subject: [PATCH 038/173] Add failing spec for custom error message --- spec/webview-spec.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 904dfcab6e0..faafec73db3 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -561,6 +561,17 @@ describe(' tag', function() { document.body.appendChild(webview); }); }); + + it('throws a custom error when an API method is called before the event is emitted', function() { + var readyError = null; + try { + webview.stop(); + } catch (error) { + readyError = error; + } + + assert.equal(readyError.message, 'stop can only be called after the dom-ready event is emitted'); + }); }); describe('executeJavaScript', function() { From 8cacd0b931fe842afe3c54e618344924dc3fc0f6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Feb 2016 10:55:32 -0800 Subject: [PATCH 039/173] Throw custom error when WebView API is unavailable --- atom/renderer/lib/web-view/web-view.js | 11 +++++++---- spec/webview-spec.js | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 5257f0c12f9..4e34d2e5592 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -404,10 +404,13 @@ var registerWebViewElement = function() { // Forward proto.foo* method calls to WebViewImpl.foo*. createBlockHandler = function(m) { return function() { - var args, internal, ref1; - args = 1 <= arguments.length ? slice.call(arguments, 0) : []; - internal = v8Util.getHiddenValue(this, 'internal'); - return (ref1 = internal.webContents)[m].apply(ref1, args); + var args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + var internal = v8Util.getHiddenValue(this, 'internal'); + if (internal.webContents) { + return internal.webContents[m].apply(internal.webContents, args); + } else { + throw new Error('Cannot call ' + m + ' before the dom-ready event is emitted') + } }; }; for (i = 0, len = methods.length; i < len; i++) { diff --git a/spec/webview-spec.js b/spec/webview-spec.js index faafec73db3..072a51f36a5 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -570,7 +570,7 @@ describe(' tag', function() { readyError = error; } - assert.equal(readyError.message, 'stop can only be called after the dom-ready event is emitted'); + assert.equal(readyError.message, 'Cannot call stop before the dom-ready event is emitted'); }); }); From 42a8674cea58ab3fe73c391e21a403ee66b40d86 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Feb 2016 11:05:17 -0800 Subject: [PATCH 040/173] Add missing semicolon --- atom/renderer/lib/web-view/web-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 4e34d2e5592..29af92e9bd3 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -409,7 +409,7 @@ var registerWebViewElement = function() { if (internal.webContents) { return internal.webContents[m].apply(internal.webContents, args); } else { - throw new Error('Cannot call ' + m + ' before the dom-ready event is emitted') + throw new Error('Cannot call ' + m + ' before the dom-ready event is emitted'); } }; }; From 674af4211c403e767882781c44ba282c591b84af Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 13:24:58 -0800 Subject: [PATCH 041/173] Use interpolated string --- atom/renderer/lib/web-view/web-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 29af92e9bd3..49440527c40 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -409,7 +409,7 @@ var registerWebViewElement = function() { if (internal.webContents) { return internal.webContents[m].apply(internal.webContents, args); } else { - throw new Error('Cannot call ' + m + ' before the dom-ready event is emitted'); + throw new Error(`Cannot call ${m} before the dom-ready event is emitted`); } }; }; From bad48169764278154cb47e218024ed224de9ae7d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 13:51:35 -0800 Subject: [PATCH 042/173] Expand error message --- atom/renderer/lib/web-view/web-view.js | 2 +- spec/webview-spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 49440527c40..9cc6ac4e880 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -409,7 +409,7 @@ var registerWebViewElement = function() { if (internal.webContents) { return internal.webContents[m].apply(internal.webContents, args); } else { - throw new Error(`Cannot call ${m} before the dom-ready event is emitted`); + throw new Error(`Cannot call ${m} because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.`); } }; }; diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 072a51f36a5..0b6572a5084 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -570,7 +570,7 @@ describe(' tag', function() { readyError = error; } - assert.equal(readyError.message, 'Cannot call stop before the dom-ready event is emitted'); + assert.equal(readyError.message, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.'); }); }); From da6ebac7424e931a5789b95a5b6c70effacfffd1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 13:53:10 -0800 Subject: [PATCH 043/173] Use assert.throws --- spec/webview-spec.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 0b6572a5084..eb1427e0855 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -563,14 +563,9 @@ describe(' tag', function() { }); it('throws a custom error when an API method is called before the event is emitted', function() { - var readyError = null; - try { - webview.stop(); - } catch (error) { - readyError = error; - } - - assert.equal(readyError.message, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.'); + assert.throws(function () { + webview.stop() + }, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.'); }); }); From 9609b36b3cab670b5274d4c77b767ba1123db4b7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 13:55:49 -0800 Subject: [PATCH 044/173] Add missing semicolon --- spec/webview-spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index eb1427e0855..973c1c24031 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -564,7 +564,7 @@ describe(' tag', function() { it('throws a custom error when an API method is called before the event is emitted', function() { assert.throws(function () { - webview.stop() + webview.stop(); }, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.'); }); }); From 042825e8fb40244c665b720266ff7112333d5eb2 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Feb 2016 13:32:34 -0800 Subject: [PATCH 045/173] emmitted -> emitted --- atom/renderer/lib/web-view/web-view.js | 2 +- spec/webview-spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 9cc6ac4e880..7e38bb33715 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -409,7 +409,7 @@ var registerWebViewElement = function() { if (internal.webContents) { return internal.webContents[m].apply(internal.webContents, args); } else { - throw new Error(`Cannot call ${m} because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.`); + throw new Error(`Cannot call ${m} because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emitted before this method can be called.`); } }; }; diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 973c1c24031..a18e152ea6a 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -565,7 +565,7 @@ describe(' tag', function() { it('throws a custom error when an API method is called before the event is emitted', function() { assert.throws(function () { webview.stop(); - }, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.'); + }, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emitted before this method can be called.'); }); }); From c09ff40916bec47b6c7a09ea8c0c8a1d0e591642 Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 12 Feb 2016 05:07:06 +0530 Subject: [PATCH 046/173] browser: handle desktop capture devices in media permission request --- atom/browser/web_contents_permission_helper.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/web_contents_permission_helper.cc b/atom/browser/web_contents_permission_helper.cc index f5ce414dd2c..d018e1d09db 100644 --- a/atom/browser/web_contents_permission_helper.cc +++ b/atom/browser/web_contents_permission_helper.cc @@ -23,7 +23,7 @@ void MediaAccessAllowed( bool allowed) { brightray::MediaStreamDevicesController controller(request, callback); if (allowed) - controller.Accept(); + controller.TakeAction(); else controller.Deny(content::MEDIA_DEVICE_PERMISSION_DENIED); } From 3adcaa7681fdff87186aa08689c2b3567aaa78cb Mon Sep 17 00:00:00 2001 From: Habib Rehman Date: Fri, 12 Feb 2016 00:11:02 +0000 Subject: [PATCH 047/173] Fix electron binary relative path The relative path for Electron's binary is Contents/MacOS/Electron --- docs/tutorial/using-selenium-and-webdriver.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/using-selenium-and-webdriver.md b/docs/tutorial/using-selenium-and-webdriver.md index 035dabdfe79..2d296548dd9 100644 --- a/docs/tutorial/using-selenium-and-webdriver.md +++ b/docs/tutorial/using-selenium-and-webdriver.md @@ -49,7 +49,7 @@ var driver = new webdriver.Builder() .withCapabilities({ chromeOptions: { // Here is the path to your Electron binary. - binary: '/Path-to-Your-App.app/Contents/MacOS/Atom', + binary: '/Path-to-Your-App.app/Contents/MacOS/Electron', } }) .forBrowser('electron') From 91c96559fa40e50e7c364bb7f0dafc594692390f Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Fri, 12 Feb 2016 02:18:13 +0100 Subject: [PATCH 048/173] Fixing the problem related to FrameSubscriber --- atom/browser/api/atom_api_web_contents.cc | 8 +++-- atom/browser/api/frame_subscriber.cc | 40 ++++++++++++++++++++--- atom/browser/api/frame_subscriber.h | 27 ++++++++++++--- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 80e5b606ef8..b04553e654b 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1064,9 +1064,11 @@ void WebContents::BeginFrameSubscription( const FrameSubscriber::FrameCaptureCallback& callback) { const auto view = web_contents()->GetRenderWidgetHostView(); if (view) { - scoped_ptr frame_subscriber(new FrameSubscriber( - isolate(), view->GetVisibleViewportSize(), callback)); - view->BeginFrameSubscription(frame_subscriber.Pass()); + FrameSubscriber* frame_subscriber = new FrameSubscriber( + isolate(), view->GetVisibleViewportSize(), callback); + scoped_ptr del_frame_subscriber( + frame_subscriber->GetSubscriber()); + view->BeginFrameSubscription(del_frame_subscriber.Pass()); } } diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index 5b7241486b7..9bcf16fef85 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -13,28 +13,58 @@ namespace atom { namespace api { +using Subscriber = FrameSubscriber::Subscriber; + FrameSubscriber::FrameSubscriber(v8::Isolate* isolate, const gfx::Size& size, const FrameCaptureCallback& callback) - : isolate_(isolate), size_(size), callback_(callback) { + : isolate_(isolate), size_(size), callback_(callback), pending_frames(0) { + subscriber_ = new Subscriber(this); } -bool FrameSubscriber::ShouldCaptureFrame( +Subscriber::Subscriber( + FrameSubscriber* frame_subscriber) : frame_subscriber_(frame_subscriber) { +} + +Subscriber::~Subscriber() { + frame_subscriber_->subscriber_ = NULL; + frame_subscriber_->RequestDestruct(); +} + +bool Subscriber::ShouldCaptureFrame( const gfx::Rect& damage_rect, base::TimeTicks present_time, scoped_refptr* storage, DeliverFrameCallback* callback) { *storage = media::VideoFrame::CreateFrame( media::PIXEL_FORMAT_YV12, - size_, gfx::Rect(size_), size_, base::TimeDelta()); + frame_subscriber_->size_, gfx::Rect(frame_subscriber_->size_), + frame_subscriber_->size_, base::TimeDelta()); *callback = base::Bind(&FrameSubscriber::OnFrameDelivered, - base::Unretained(this), *storage); + base::Unretained(frame_subscriber_), *storage); + frame_subscriber_->pending_frames++; return true; } +Subscriber* FrameSubscriber::GetSubscriber() { + return subscriber_; +} + +bool FrameSubscriber::RequestDestruct() { + bool deletable = (subscriber_ == NULL && pending_frames == 0); + // Destruct FrameSubscriber if we're not waiting for frames and the + // subscription has ended + if (deletable) + delete this; + + return deletable; +} + void FrameSubscriber::OnFrameDelivered( scoped_refptr frame, base::TimeTicks, bool result) { - if (!result) + pending_frames--; + + if (!result || RequestDestruct()) return; v8::Locker locker(isolate_); diff --git a/atom/browser/api/frame_subscriber.h b/atom/browser/api/frame_subscriber.h index f7748aa5790..6f6d66b6be8 100644 --- a/atom/browser/api/frame_subscriber.h +++ b/atom/browser/api/frame_subscriber.h @@ -14,26 +14,43 @@ namespace atom { namespace api { -class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber { +class FrameSubscriber { public: using FrameCaptureCallback = base::Callback)>; + // Inner class that is the actual subscriber sent to chromium + class Subscriber : + public content::RenderWidgetHostViewFrameSubscriber { + public: + explicit Subscriber(FrameSubscriber* frame_subscriber); + + bool ShouldCaptureFrame(const gfx::Rect& damage_rect, + base::TimeTicks present_time, + scoped_refptr* storage, + DeliverFrameCallback* callback) override; + + ~Subscriber(); + private: + FrameSubscriber* frame_subscriber_; + }; + FrameSubscriber(v8::Isolate* isolate, const gfx::Size& size, const FrameCaptureCallback& callback); - bool ShouldCaptureFrame(const gfx::Rect& damage_rect, - base::TimeTicks present_time, - scoped_refptr* storage, - DeliverFrameCallback* callback) override; + Subscriber* GetSubscriber(); private: void OnFrameDelivered( scoped_refptr frame, base::TimeTicks, bool); + bool RequestDestruct(); + v8::Isolate* isolate_; gfx::Size size_; FrameCaptureCallback callback_; + Subscriber* subscriber_; + int pending_frames; DISALLOW_COPY_AND_ASSIGN(FrameSubscriber); }; From f36e2841bff038de2f7cf7649544a589979a06a3 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Fri, 12 Feb 2016 13:30:11 +0100 Subject: [PATCH 049/173] Don't fire callbacks after we end the subscription --- atom/browser/api/frame_subscriber.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index 9bcf16fef85..7d973892405 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -64,7 +64,7 @@ void FrameSubscriber::OnFrameDelivered( scoped_refptr frame, base::TimeTicks, bool result) { pending_frames--; - if (!result || RequestDestruct()) + if (RequestDestruct() || subscriber_ == NULL || !result) return; v8::Locker locker(isolate_); From 2677dc68444398f20210291dfaf7349fc17dc48d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Aur=C3=A8le=20DARCHE?= Date: Fri, 12 Feb 2016 13:50:15 +0100 Subject: [PATCH 050/173] Fix: add missing fragment in FAQ section URL --- docs/tutorial/quick-start.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index ccb3836ba1f..67fe5d608a1 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -48,7 +48,8 @@ communication between the main process and renderer process. There is also a [remote](../api/remote.md) module for RPC style communication. And finally there are different techniques [to share objects between web -pages](../faq/electron-faq.md#) of the same window or of different windows. +pages](../faq/electron-faq.md#what-are-the-different-techniques-to-share-objects-between-web-pages) +of the same window or of different windows. ## Write your First Electron App From e71eeda73c5f8d8a760ce63d6976d394257a5e27 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 12 Feb 2016 22:38:08 +0900 Subject: [PATCH 051/173] Remove unnecessary line feeds [ci skip] --- docs/api/clipboard.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/api/clipboard.md b/docs/api/clipboard.md index dcb9fa398a9..7f95a1af26d 100644 --- a/docs/api/clipboard.md +++ b/docs/api/clipboard.md @@ -67,7 +67,6 @@ Writes `image` to the clipboard. Returns the content in the clipboard as RTF. - ### `clipboard.writeRtf(text[, type])` * `text` String From d76f6fe8e0d6faee5c542e79f86202a6f89245b5 Mon Sep 17 00:00:00 2001 From: Yuya Ochiai Date: Sat, 13 Feb 2016 17:03:58 +0900 Subject: [PATCH 052/173] :memo::checkered_flag: Add icon overlays in taskbar to docs [ci skip] --- .../desktop-environment-integration.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/tutorial/desktop-environment-integration.md b/docs/tutorial/desktop-environment-integration.md index 7d7eb44ecb6..54246a11c5c 100644 --- a/docs/tutorial/desktop-environment-integration.md +++ b/docs/tutorial/desktop-environment-integration.md @@ -271,6 +271,33 @@ var window = new BrowserWindow({...}); window.setProgressBar(0.5); ``` +## Icon Overlays in Taskbar (Windows) + +On Windows a taskbar button can use a small overlay to display application +status, as quoted from MSDN: + +> Icon overlays serve as a contextual notification of status, and are intended +> to negate the need for a separate notification area status icon to communicate +> that information to the user. For instance, the new mail status in Microsoft +> Outlook, currently shown in the notification area, can now be indicated +> through an overlay on the taskbar button. Again, you must decide during your +> development cycle which method is best for your application. Overlay icons are +> intended to supply important, long-standing status or notifications such as +> network status, messenger status, or new mail. The user should not be +> presented with constantly changing overlays or animations. + +__Overlay on taskbar button:__ + +![Overlay on taskbar button](https://i-msdn.sec.s-msft.com/dynimg/IC420441.png) + +To set the overlay icon for a window, you can use the +[BrowserWindow.setOverlayIcon][setoverlayicon] API: + +```javascript +var window = new BrowserWindow({...}); +window.setOverlayIcon('path/to/overlay.png', 'Description for overlay'); +``` + ## Represented File of Window (OS X) On OS X a window can set its represented file, so the file's icon can show in @@ -298,6 +325,7 @@ window.setDocumentEdited(true); [clearrecentdocuments]: ../api/app.md#appclearrecentdocuments [setusertaskstasks]: ../api/app.md#appsetusertaskstasks [setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress +[setoverlayicon]: ../api/browser-window.md#winsetoverlayiconoverlay-description-windows-7 [setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename [setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited [app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx From adf89a1e0eff739c9bfef7af614fbb403c982349 Mon Sep 17 00:00:00 2001 From: Remi Sezille Date: Sat, 13 Feb 2016 11:29:08 +0100 Subject: [PATCH 053/173] Translate README in french [ci skip] --- docs-translations/fr-FR/README.md | 91 +++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 docs-translations/fr-FR/README.md diff --git a/docs-translations/fr-FR/README.md b/docs-translations/fr-FR/README.md new file mode 100644 index 00000000000..04aed455612 --- /dev/null +++ b/docs-translations/fr-FR/README.md @@ -0,0 +1,91 @@ +Vérifiez que vous utilisez la bonne version de la documentation. +Le numéro de version devrait faire partie de l'URL de la page. +Si ce n'est pas le cas, vous utilisez probablement la documentation d'une branche +de développement qui peut contenir des changements API qui ne sont pas compatibles +avec votre version d'Electron. Si c'est le cas, vous pouvez changer de version sur la +liste [versions disponibles](http://electron.atom.io/docs/), ou, si vous utilisez +l'interface de GitHub, ouvrez la liste déroulante "Switch branches/tags" afin de sélectionner +le tag de votre version. + +## FAQ + +Avant de créer un ticket, vérifiez que votre problème n'a pas déjà sa réponse +dans la FAQ : + +* [Electron FAQ](faq/electron-faq.md) + +## Guides + +* [Plateformes supportées](tutorial/supported-platforms.md) +* [Distribution de l'Application](tutorial/application-distribution.md) +* [Guide de Soumission Mac App Store](tutorial/mac-app-store-submission-guide.md) +* [Créer une archive](tutorial/application-packaging.md) +* [Utiliser Modules Natifs de Node](tutorial/using-native-node-modules.md) +* [Debugger Processus Principal](tutorial/debugging-main-process.md) +* [Utiliser Selenium et WebDriver](tutorial/using-selenium-and-webdriver.md) +* [Extension DevTools](tutorial/devtools-extension.md) +* [Utiliser le Plugin Pepper Flash](tutorial/using-pepper-flash-plugin.md) +* [Utiliser le Plugin Widevine CDM](tutorial/using-widevine-cdm-plugin.md) + +## Tutoriels + +* [Démarrage Rapide](tutorial/quick-start.md) +* [Intégration Environnement de Bureau](tutorial/desktop-environment-integration.md) +* [Détection des Evènements En ligne/Hors ligne](tutorial/online-offline-events.md) + +## Références API + +* [Synopsis](api/synopsis.md) +* [L'objet Process](api/process.md) +* [Commandes Chromes Supportées](api/chrome-command-line-switches.md) +* [Variables d'Environnement](api/environment-variables.md) + +### Eléments DOM Personnalisés: + +* [Objet `File`](api/file-object.md) +* [Tag ``](api/web-view-tag.md) +* [Fonction `window.open`](api/window-open.md) + +### Modules pour le Processus Principal : + +* [app](api/app.md) +* [autoUpdater](api/auto-updater.md) +* [BrowserWindow](api/browser-window.md) +* [contentTracing](api/content-tracing.md) +* [dialog](api/dialog.md) +* [globalShortcut](api/global-shortcut.md) +* [ipcMain](api/ipc-main.md) +* [Menu](api/menu.md) +* [MenuItem](api/menu-item.md) +* [powerMonitor](api/power-monitor.md) +* [powerSaveBlocker](api/power-save-blocker.md) +* [protocol](api/protocol.md) +* [session](api/session.md) +* [webContents](api/web-contents.md) +* [Tray](api/tray.md) + +### Modules pour le Processus d'Affichage (Page Web) : + +* [desktopCapturer](api/desktop-capturer.md) +* [ipcRenderer](api/ipc-renderer.md) +* [remote](api/remote.md) +* [webFrame](api/web-frame.md) + +### Modules pour les deux Processus : + +* [clipboard](api/clipboard.md) +* [crashReporter](api/crash-reporter.md) +* [nativeImage](api/native-image.md) +* [screen](api/screen.md) +* [shell](api/shell.md) + +## Développement + +* [Style de Code](development/coding-style.md) +* [Hiérarchie du Code Source](development/source-code-directory-structure.md) +* [Différences Techniques par rapport à NW.js (anciennement node-webkit)](development/atom-shell-vs-node-webkit.md) +* [Aperçu du Système de Build](development/build-system-overview.md) +* [Instructions de Build (OS X)](development/build-instructions-osx.md) +* [Instructions de Build (Windows)](development/build-instructions-windows.md) +* [Instructions de Build (Linux)](development/build-instructions-linux.md) +* [Installer un Serveur de Symbol dans le debugger](development/setting-up-symbol-server.md) From 940c325e7f89f90e8151b9ed56734a03bea5e1d1 Mon Sep 17 00:00:00 2001 From: Remi Sezille Date: Sat, 13 Feb 2016 11:32:47 +0100 Subject: [PATCH 054/173] Add french docs link on main README [ci skip] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a7306ddabbb..ce6d483f0df 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ contains documents describing how to build and contribute to Electron. - [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW) - [Ukrainian](https://github.com/atom/electron/tree/master/docs-translations/uk-UA) - [Russian](https://github.com/atom/electron/tree/master/docs-translations/ru-RU) +- [French](https://github.com/atom/electron/tree/master/docs-translations/fr-FR) ## Quick Start From a69341f551e0078d843edab7e289f3c65b4db0d9 Mon Sep 17 00:00:00 2001 From: Remi Sezille Date: Sat, 13 Feb 2016 18:19:49 +0100 Subject: [PATCH 055/173] Fix line length wrap [ci skip] --- docs-translations/fr-FR/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs-translations/fr-FR/README.md b/docs-translations/fr-FR/README.md index 04aed455612..666a03e99a3 100644 --- a/docs-translations/fr-FR/README.md +++ b/docs-translations/fr-FR/README.md @@ -1,11 +1,11 @@ Vérifiez que vous utilisez la bonne version de la documentation. Le numéro de version devrait faire partie de l'URL de la page. -Si ce n'est pas le cas, vous utilisez probablement la documentation d'une branche -de développement qui peut contenir des changements API qui ne sont pas compatibles -avec votre version d'Electron. Si c'est le cas, vous pouvez changer de version sur la -liste [versions disponibles](http://electron.atom.io/docs/), ou, si vous utilisez -l'interface de GitHub, ouvrez la liste déroulante "Switch branches/tags" afin de sélectionner -le tag de votre version. +Si ce n'est pas le cas, vous utilisez probablement la documentation d'une +branche de développement qui peut contenir des changements API qui ne sont pas +compatibles avec votre version d'Electron. Si c'est le cas, vous pouvez changer +de version sur la liste [versions disponibles](http://electron.atom.io/docs/), +ou, si vous utilisez l'interface de GitHub, ouvrez la liste déroulante "Switch +branches/tags" afin de sélectionner le tag de votre version. ## FAQ From efd25efaf4ea00c2fac14f1d6ee4a76fab89c57f Mon Sep 17 00:00:00 2001 From: Remi Sezille Date: Sat, 13 Feb 2016 18:20:34 +0100 Subject: [PATCH 056/173] Add FAQ [ci skip] --- docs-translations/fr-FR/faq/electron-faq.md | 129 ++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 docs-translations/fr-FR/faq/electron-faq.md diff --git a/docs-translations/fr-FR/faq/electron-faq.md b/docs-translations/fr-FR/faq/electron-faq.md new file mode 100644 index 00000000000..1a82bce6800 --- /dev/null +++ b/docs-translations/fr-FR/faq/electron-faq.md @@ -0,0 +1,129 @@ +# Electron FAQ + +## Quand est mise à jour la version de Chrome utilisée par Electron ? + +La version de Chrome qu'utilise Electron est en général mise à jour une ou deux +semaines après la sortie d'une nouvelle version stable de Chrome. + +Etant donné que nous n'utilisons que les versions stables de Chrome, si un fix +important est en beta ou en dev, nous l'intégrerons à la version que nous +utilisons. + +## Quand est mise à jour la version de Node.js utilisée par Electron ? + +Quand une nouvelle version de Node.js sort, nous attendons en général un mois +avant de mettre à jour celle que nous utilisons dans Electron. Ceci afin +d'éviter les bugs introduits par les nouvelles versions, ce qui arrive très +souvent. + +Les nouvelles fonctionnalités de Node.js arrivant la plupart du temps via V8, +et Electron utilisant le V8 du navigateur Chrome, la nouvelle fonctionnalité +JavaScript de la nouvelle version de Node.js est bien souvent déjà dans +Electron. + +## La fenêtre/barre d'état de mon application disparait après quelques minutes. + +Cela se produit quand la variable qui est utilisée pour stocker la fenêtre/barre +d'état est libérée par le ramasse-miettes. + +Nous vous recommandons de lire les articles suivants quand vous rencontrez le +problème : + +* [Management de la Mémoire][memory-management] (Anglais) +* [Portée d'une Variable][variable-scope] (Anglais) + +Si vous voulez corriger rapidement le problème, vous pouvez rendre les variables +globales en changeant votre code de ça : + +```javascript +app.on('ready', function() { + var tray = new Tray('/path/to/icon.png'); +}) +``` + +à ça : + +```javascript +var tray = null; +app.on('ready', function() { + tray = new Tray('/path/to/icon.png'); +}) +``` + +## Je n'arrive pas à utiliser jQuery/RequireJS/Meteor/AngularJS dans Electron. + +A cause de l'intégration de Node.js dans Electron, certains mots-clés sont +insérés dans la DOM, comme `module`, `exports`, `require`. Ceci pose des +problèmes pour certaines bibliothèques qui utilisent les mêmes mots-clés. + +Pour résoudre ce problème, vous pouvez désactiver l'intégration de node dans +Electron : + +```javascript +// Dans le processus principal. +var mainWindow = new BrowserWindow({ + webPreferences: { + nodeIntegration: false + } +}); +``` + +Mais si vous voulez garder la possibilité d'utiliser Node.js et les APIs +Electron, vous devez renommer les mots-clés dans la page avant d'inclure +d'autres bibliothèques : + +```html + + + + +``` + +## `require('electron').xxx` is undefined. + +Lors de l'utilisation des modules d'Electron, vous pouvez avoir une erreur : + +``` +> require('electron').webFrame.setZoomFactor(1.0); +Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined +``` + +Ceci se produit quand vous avez le [module npm `electron`][electron-module] +d'installé, soit en local ou en global, ce qui a pour effet d'écraser les +modules de base d'Electron. + +Vous vérifiez que vous utilisez les bons modules, vous pouvez afficher le +chemin du module `electron` : + +```javascript +console.log(require.resolve('electron')); +``` + +et vérifier si il est de la forme : + +``` +"/path/to/Electron.app/Contents/Resources/atom.asar/renderer/api/lib/exports/electron.js" +``` + +S'il est de la forme `node_modules/electron/index.js`, vous devez supprimer le +module npm `electron`, ou le renommer. + +```bash +npm uninstall electron +npm uninstall -g electron +``` + +Si vous utilisez le module de base mais que vous continuez d'avoir +l'erreur, ça vient probablement du fait que vous utilisez le module dans le +mauvais processus. Par exemple `electron.app` peut uniquement être utilisé +dans le processus principal, tandis que `electron.webFrame` est uniquement +disponible dans le processus d'affichage. + +[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management +[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx +[electron-module]: https://www.npmjs.com/package/electron From ef290ffcf2c1b3fdffb1eb004f0090026150bbe6 Mon Sep 17 00:00:00 2001 From: Remi Sezille Date: Sat, 13 Feb 2016 19:28:12 +0100 Subject: [PATCH 057/173] Add styleguide in french [ci skip] --- docs-translations/fr-FR/styleguide.md | 101 ++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 docs-translations/fr-FR/styleguide.md diff --git a/docs-translations/fr-FR/styleguide.md b/docs-translations/fr-FR/styleguide.md new file mode 100644 index 00000000000..5fe781773c1 --- /dev/null +++ b/docs-translations/fr-FR/styleguide.md @@ -0,0 +1,101 @@ +# Règles de style pour la documentation d'Electron + +Choisissez la section appropriée : [lire la documentation d'Electron](#reading-electron-documentation) +ou [écrire de la documentation pour Electron](#writing-electron-documentation). + +## Ecrire de la documentation pour Electron + +La documentation d'Electron a été écrite en suivant les règles ci-dessous : + +- Maximum un titre `h1` par page. +- Utilisation de `bash` au lieu de `cmd` dans les blocs de code (à cause de la + coloration syntaxique). +- Les titres `h1` devraient reprendre le nom de l'objet (i.e. `browser-window` → + `BrowserWindow`). + - Cependant, les traits d'union sont acceptés pour les noms de fichier. +- Pas de titre directement après un autre, ajoutez au minimum une ligne de + description entre les deux. +- Les entêtes des méthodes sont entre accents graves (backquotes) `code`. +- Les entêtes des évènements sont entre des apostrophes 'quotation'. +- Les listes ne doivent pas dépasser 2 niveaux (à cause du formattage du + markdown). +- Ajouter des titres de section: Evènements, Méthodes de classe, et Méthodes + d'instance. +- Utiliser 'will' au lieu de 'would' lors de la description du retour. +- Les évènements et méthodes sont des titres `h3`. +- Les arguments optionnels sont notés `function (required[, optional])`. +- Les arguments optionnels sont indiqués quand appelés dans la liste. +- La longueur des lignes ne dépasse pas 80 caractères. +- Les méthodes spécifiques à une plateforme sont notées en italique. + - ```### `method(foo, bar)` _OS X_``` +- Préférer 'in the ___ process' au lieu de 'on' + +### Traductions de la Documentation + +Les traductions de la documentation d'Electron sont dans le dossier +`docs-translations`. + +Pour ajouter une nouvelle langue (ou commencer) : + +- Créer un sous-dossier avec comme nom le code langage. +- A l'intérieur de ce dossier, dupliquer le dossier `docs`, en gardant le même + nom de dossiers et de fichiers. +- Traduire les fichiers. +- Mettre à jour le `README.md` à l'intérieur du dossier de langue en mettant les + liens vers les fichiers traduits. +- Ajouter un lien vers le nouveau dossier de langue dans le [README](https://github.com/atom/electron#documentation-translations) + principal d'Electron. + +## Lire la documentation d'Electron + +Quelques indications pour comprendre la syntaxe de la documentation d'Electron. + +### Méthodes + +Un exemple de la documentation d'une [méthode](https://developer.mozilla.org/en-US/docs/Glossary/Method) +(Anglais) + +--- + +`methodName(required[, optional]))` + +* `require` String (**required**) +* `optional` Integer + +--- + +Le nom de la méthode est suivi des arguments de celle-ci. Les arguments +optionnels sont notés entre crochets, avec une virgule si ceux-ci suivent un +autre argument. + +En-dessous de la méthode, chaque argument est détaillé avec son type. +Celui-ci peut être un type générique : +[`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String), +[`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number), +[`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object), +[`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) +ou un type personnalisé comme le [`webContent`](api/web-content.md) d'Electron. + +### Evènements + +Un exemple d'une documentation d'un [évènement](https://developer.mozilla.org/en-US/docs/Web/API/Event) +(Anglais) +--- + +Event: 'wake-up' + +Returns: + +* `time` String + +--- + +L'évènement est une chaine utilisée après un listener `.on`. Si il retourne une +valeur, elle est écrite en dessous ainsi que son type. Si vous voulez écouter et +répondre à l'évènement wake-up, ça donne quelque chose comme : + +```javascript +Alarm.on('wake-up', function(time) { + console.log(time) +}) +``` From f63d8b4d5ec2a139e616acd14330630fd254105d Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sun, 7 Feb 2016 16:02:48 +0900 Subject: [PATCH 058/173] :memo: Update as upstream [ci skip] --- docs-translations/ko-KR/api/app.md | 2 +- docs-translations/ko-KR/api/browser-window.md | 2 +- docs-translations/ko-KR/api/clipboard.md | 13 +++++++++++++ docs-translations/ko-KR/api/ipc-renderer.md | 8 ++++---- docs-translations/ko-KR/api/session.md | 8 ++++---- .../ko-KR/tutorial/application-distribution.md | 5 ++--- .../ko-KR/tutorial/using-selenium-and-webdriver.md | 2 +- 7 files changed, 26 insertions(+), 14 deletions(-) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index ec4cb74c253..32412d13180 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -92,7 +92,7 @@ Returns: 이 이벤트를 처리할 땐 반드시 `event.preventDefault()`를 호출해야 합니다. -Windows에선 `process.argv`를 통해 파일 경로를 얻을 수 있습니다. +Windows에선 `process.argv` (메인 프로세스에서)를 통해 파일 경로를 얻을 수 있습니다. ### Event: 'open-url' _OS X_ diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index f79b201d0a1..f487a38f5da 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -773,7 +773,7 @@ Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. 그리고 아이콘입니다. `null`로 지정하면 빈 오버레이가 사용됩니다 * `description` String - 접근성 설정에 의한 스크린 리더에 제공될 설명입니다 -현재 작업표시줄 아이콘에 16px 크기의 오버레이를 지정합니다. 보통 이 기능은 +현재 작업표시줄 아이콘에 16 x 16 픽셀 크기의 오버레이를 지정합니다. 보통 이 기능은 어플리케이션의 여러 상태를 사용자에게 소극적으로 알리기 위한 방법으로 사용됩니다. ### `win.setHasShadow(hasShadow)` _OS X_ diff --git a/docs-translations/ko-KR/api/clipboard.md b/docs-translations/ko-KR/api/clipboard.md index 2a0c98da2c0..df6475ad611 100644 --- a/docs-translations/ko-KR/api/clipboard.md +++ b/docs-translations/ko-KR/api/clipboard.md @@ -62,6 +62,19 @@ console.log(clipboard.readText('selection')); 클립보드에 `image`를 씁니다. +### `clipboard.readRtf([type])` + +* `type` String (optional) + +클립보드로부터 RTF 형식으로 컨텐츠를 읽어옵니다. + +### `clipboard.writeRtf(text[, type])` + +* `text` String +* `type` String (optional) + +클립보드에 `text`를 RTF 형식으로 씁니다. + ### `clipboard.clear([type])` * `type` String (optional) diff --git a/docs-translations/ko-KR/api/ipc-renderer.md b/docs-translations/ko-KR/api/ipc-renderer.md index aba632430b5..12fac95bbee 100644 --- a/docs-translations/ko-KR/api/ipc-renderer.md +++ b/docs-translations/ko-KR/api/ipc-renderer.md @@ -17,7 +17,7 @@ 이벤트가 일어나면 `event` 객체와 임의의 인자와 함께 `callback` 함수가 호출됩니다. -### `ipcMain.removeListener(channel, callback)` +### `ipcRenderer.removeListener(channel, callback)` * `channel` String - 이벤트의 이름 * `callback` Function - `ipcMain.on(channel, callback)`에서 사용한 함수의 레퍼런스 @@ -26,15 +26,15 @@ 메시지 전송을 멈출수 없을 때, 이 함수를 통해 지정한 채널에 대한 콜백을 삭제할 수 있습니다. -### `ipcMain.removeAllListeners(channel)` +### `ipcRenderer.removeAllListeners(channel)` * `channel` String - 이벤트의 이름 이 ipc 채널에 등록된 *모든* 핸들러들을 삭제합니다. -### `ipcMain.once(channel, callback)` +### `ipcRenderer.once(channel, callback)` -`ipcMain.on()` 대신 이 함수를 사용할 경우 핸들러가 단 한 번만 호출됩니다. +`ipcRenderer.on()` 대신 이 함수를 사용할 경우 핸들러가 단 한 번만 호출됩니다. `callback`이 한 번 호출된 이후 활성화되지 않습니다. ## 메시지 보내기 diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index 59eceb05a7a..5598fb6eb26 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -293,23 +293,23 @@ myWindow.webContents.session.setCertificateVerifyProc(function(hostname, cert, c * `handler` Function * `webContents` Object - [WebContents](web-contents.md) 권한을 요청. * `permission` String - 'media', 'geolocation', 'notifications', - 'midiSysex'의 나열. + 'midiSysex', 'pointerLock', 'fullscreen'의 나열. * `callback` Function - 권한 허용 및 거부. `session`의 권한 요청에 응답을 하는데 사용하는 핸들러를 설정합니다. -`callback('granted')`를 호출하면 권한 제공을 허용하고 `callback('denied')`를 +`callback(true)`를 호출하면 권한 제공을 허용하고 `callback(false)`를 호출하면 권한 제공을 거부합니다. ```javascript session.fromPartition(partition).setPermissionRequestHandler(function(webContents, permission, callback) { if (webContents.getURL() === host) { if (permission == "notifications") { - callback(); // 거부됨. + callback(false); // 거부됨. return; } } - callback('granted'); + callback(true); }); ``` diff --git a/docs-translations/ko-KR/tutorial/application-distribution.md b/docs-translations/ko-KR/tutorial/application-distribution.md index 63533757415..7072d7c4d95 100644 --- a/docs-translations/ko-KR/tutorial/application-distribution.md +++ b/docs-translations/ko-KR/tutorial/application-distribution.md @@ -59,9 +59,8 @@ electron/resources/ ### Windows -`electron.exe`을 원하는 이름으로 변경할 수 있습니다. -그리고 [rcedit](https://github.com/atom/rcedit) -를 사용하여 아이콘을 변경할 수 있습니다. +[rcedit](https://github.com/atom/rcedit)를 통해 `electron.exe`을 원하는 이름으로 +변경할 수 있고, 또한 아이콘과 기타 정보도 변경할 수 있습니다. ### OS X diff --git a/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md b/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md index d0684e0cfe1..6cc5472bb12 100644 --- a/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md +++ b/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md @@ -48,7 +48,7 @@ var driver = new webdriver.Builder() .withCapabilities({ chromeOptions: { // 여기에 사용중인 Electron 바이너리의 경로를 지정하세요. - binary: '/Path-to-Your-App.app/Contents/MacOS/Atom', + binary: '/Path-to-Your-App.app/Contents/MacOS/Electron', } }) .forBrowser('electron') From 17603d5dfbc7a98583e704502378c9867b26e999 Mon Sep 17 00:00:00 2001 From: Jacob Page Date: Sun, 14 Feb 2016 19:13:11 -0800 Subject: [PATCH 059/173] makeSingleInstance clarification Removed callback return value from the sample code for makeSingleInstance because it appears to not be used for anything. --- docs/api/app.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/api/app.md b/docs/api/app.md index adba230b0e2..5e56e970e1b 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -398,7 +398,7 @@ quit. On OS X the system enforces single instance automatically when users try to open a second instance of your app in Finder, and the `open-file` and `open-url` events will be emitted for that. However when users start your app in command -line the system's single instance machanism will be bypassed and you have to +line the system's single instance mechanism will be bypassed and you have to use this method to ensure single instance. An example of activating the window of primary instance when a second instance @@ -413,7 +413,6 @@ var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) if (myWindow.isMinimized()) myWindow.restore(); myWindow.focus(); } - return true; }); if (shouldQuit) { From 2c6e5d046440081dea4f7ce66925796d820c1b44 Mon Sep 17 00:00:00 2001 From: Luke Page Date: Fri, 12 Feb 2016 05:47:27 +0100 Subject: [PATCH 060/173] Clarify arguments sent via ipc --- docs/api/ipc-renderer.md | 2 +- docs/api/web-contents.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/ipc-renderer.md b/docs/api/ipc-renderer.md index 96936632563..d8f344a204a 100644 --- a/docs/api/ipc-renderer.md +++ b/docs/api/ipc-renderer.md @@ -52,7 +52,7 @@ The `ipcRenderer` module has the following methods for sending messages: * `arg` (optional) Send an event to the main process asynchronously via a `channel`, you can also -send arbitrary arguments. The main process handles it by listening for the +send arbitrary arguments. Arguments will be serialized (json) and hence no functions or prototype chain will be included. The main process handles it by listening for the `channel` event with `ipcMain`. ### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])` diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index afdd08c4d00..61c2ab1f691 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -693,7 +693,7 @@ Opens the developer tools for the service worker context. * `arg` (optional) Send an asynchronous message to renderer process via `channel`, you can also -send arbitrary arguments. The renderer process can handle the message by +send arbitrary arguments. Arguments will be serialized (json) and hence no functions or prototype chain will be included. The renderer process can handle the message by listening to the `channel` event with the `ipcRenderer` module. An example of sending messages from the main process to the renderer process: From a141d6b3d474fef058f5c152bb35e52597242926 Mon Sep 17 00:00:00 2001 From: Luke Page Date: Mon, 15 Feb 2016 06:51:20 +0100 Subject: [PATCH 061/173] spelling fixes and americanisms --- docs/api/app.md | 4 ++-- docs/api/browser-window.md | 4 ++-- docs/api/web-view-tag.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/api/app.md b/docs/api/app.md index adba230b0e2..4c806246e8f 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -246,7 +246,7 @@ returning `false` in the `beforeunload` event handler. ### `app.hide()` _OS X_ -Hides all application windows without minimising them. +Hides all application windows without minimizing them. ### `app.show()` _OS X_ @@ -398,7 +398,7 @@ quit. On OS X the system enforces single instance automatically when users try to open a second instance of your app in Finder, and the `open-file` and `open-url` events will be emitted for that. However when users start your app in command -line the system's single instance machanism will be bypassed and you have to +line the system's single instance mechanism will be bypassed and you have to use this method to ensure single instance. An example of activating the window of primary instance when a second instance diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 7cf684a3953..25e1de72933 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -58,7 +58,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `alwaysOnTop` Boolean - Whether the window should always stay on top of other windows. Default is `false`. * `fullscreen` Boolean - Whether the window should show in fullscreen. When - explicity set to `false` the fullscreen button will be hidden or disabled + explicitly set to `false` the fullscreen button will be hidden or disabled on OS X, or the maximize button will be disabled on Windows. Default is `false`. * `fullscreenable` Boolean - Whether the maximize/zoom button on OS X should @@ -717,7 +717,7 @@ Returns the pathname of the file the window represents. * `edited` Boolean Specifies whether the window’s document has been edited, and the icon in title -bar will become grey when set to `true`. +bar will become gray when set to `true`. ### `win.isDocumentEdited()` _OS X_ diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index c410287553a..6bdbb6826e8 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -522,7 +522,7 @@ Returns: * `explicitSet` Boolean Fired when page title is set during navigation. `explicitSet` is false when -title is synthesised from file url. +title is synthesized from file url. ### Event: 'page-favicon-updated' From 7c7e6ffc77c8b074949c2e0f7422db1db5c21c68 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 15 Feb 2016 16:36:01 +0800 Subject: [PATCH 062/173] Fix broken links in desktop-environment-integration.md Close #4404. --- docs/tutorial/desktop-environment-integration.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/tutorial/desktop-environment-integration.md b/docs/tutorial/desktop-environment-integration.md index 7d7eb44ecb6..ac38f1088e7 100644 --- a/docs/tutorial/desktop-environment-integration.md +++ b/docs/tutorial/desktop-environment-integration.md @@ -294,15 +294,15 @@ window.setRepresentedFilename('/etc/passwd'); window.setDocumentEdited(true); ``` -[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath -[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments -[setusertaskstasks]: ../api/app.md#appsetusertaskstasks -[setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress -[setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename -[setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited +[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-os-x-windows +[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows +[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows +[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress +[setrepresentedfilename]: ../api/browser-window.md#winsetrepresentedfilenamefilename-os-x +[setdocumentedited]: ../api/browser-window.md#winsetdocumenteditededited-os-x [app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx [unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher -[setthumbarbuttons]: ../api/browser-window.md#browserwindowsetthumbarbuttonsbuttons +[setthumbarbuttons]: ../api/browser-window.md#winsetthumbarbuttonsbuttons-windows-7 [tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx [notification-spec]: https://developer.gnome.org/notification-spec/ From 367a3524b9686791d5b19e3aab2181e4ebce4035 Mon Sep 17 00:00:00 2001 From: Prayag Verma Date: Tue, 16 Feb 2016 07:51:14 +0530 Subject: [PATCH 063/173] docs: fix a minor typo Remove extra `will` --- docs/api/content-tracing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/content-tracing.md b/docs/api/content-tracing.md index aae5306523a..0b83c2759c6 100644 --- a/docs/api/content-tracing.md +++ b/docs/api/content-tracing.md @@ -155,7 +155,7 @@ called. * `eventName` String * `callback` Function -`callback` will will be called every time the given event occurs on any +`callback` will be called every time the given event occurs on any process. ### `contentTracing.cancelWatchEvent()` From ed1966ac760dcd2a7e80234c81319098bcf48ecb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Feb 2016 10:30:18 +0800 Subject: [PATCH 064/173] spec: Bring back beginFrameSubscription test --- spec/api-browser-window-spec.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 1c92d408c4c..89e9b770ab2 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -478,10 +478,16 @@ describe('browser-window module', function() { }); }); - xdescribe('beginFrameSubscription method', function() { + describe('beginFrameSubscription method', function() { it('subscribes frame updates', function(done) { + let called = false; w.loadURL("file://" + fixtures + "/api/blank.html"); w.webContents.beginFrameSubscription(function(data) { + // This callback might be called twice. + if (called) + return; + called = true; + assert.notEqual(data.length, 0); w.webContents.endFrameSubscription(); done(); From 66bb6a85341f67dbeed92b1aa2a149fa1b84d18c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Feb 2016 10:44:10 +0800 Subject: [PATCH 065/173] Use weak pointer instead of manual bookkeeping --- atom/browser/api/atom_api_web_contents.cc | 8 ++--- atom/browser/api/frame_subscriber.cc | 40 +++-------------------- atom/browser/api/frame_subscriber.h | 30 +++++------------ 3 files changed, 16 insertions(+), 62 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 1f441801407..a7946786c51 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1072,11 +1072,9 @@ void WebContents::BeginFrameSubscription( const FrameSubscriber::FrameCaptureCallback& callback) { const auto view = web_contents()->GetRenderWidgetHostView(); if (view) { - FrameSubscriber* frame_subscriber = new FrameSubscriber( - isolate(), view->GetVisibleViewportSize(), callback); - scoped_ptr del_frame_subscriber( - frame_subscriber->GetSubscriber()); - view->BeginFrameSubscription(del_frame_subscriber.Pass()); + scoped_ptr frame_subscriber(new FrameSubscriber( + isolate(), view->GetVisibleViewportSize(), callback)); + view->BeginFrameSubscription(frame_subscriber.Pass()); } } diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index 7d973892405..b2b049ce8b7 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -13,58 +13,28 @@ namespace atom { namespace api { -using Subscriber = FrameSubscriber::Subscriber; - FrameSubscriber::FrameSubscriber(v8::Isolate* isolate, const gfx::Size& size, const FrameCaptureCallback& callback) - : isolate_(isolate), size_(size), callback_(callback), pending_frames(0) { - subscriber_ = new Subscriber(this); + : isolate_(isolate), size_(size), callback_(callback), weak_factory_(this) { } -Subscriber::Subscriber( - FrameSubscriber* frame_subscriber) : frame_subscriber_(frame_subscriber) { -} - -Subscriber::~Subscriber() { - frame_subscriber_->subscriber_ = NULL; - frame_subscriber_->RequestDestruct(); -} - -bool Subscriber::ShouldCaptureFrame( +bool FrameSubscriber::ShouldCaptureFrame( const gfx::Rect& damage_rect, base::TimeTicks present_time, scoped_refptr* storage, DeliverFrameCallback* callback) { *storage = media::VideoFrame::CreateFrame( media::PIXEL_FORMAT_YV12, - frame_subscriber_->size_, gfx::Rect(frame_subscriber_->size_), - frame_subscriber_->size_, base::TimeDelta()); + size_, gfx::Rect(size_), size_, base::TimeDelta()); *callback = base::Bind(&FrameSubscriber::OnFrameDelivered, - base::Unretained(frame_subscriber_), *storage); - frame_subscriber_->pending_frames++; + weak_factory_.GetWeakPtr(), *storage); return true; } -Subscriber* FrameSubscriber::GetSubscriber() { - return subscriber_; -} - -bool FrameSubscriber::RequestDestruct() { - bool deletable = (subscriber_ == NULL && pending_frames == 0); - // Destruct FrameSubscriber if we're not waiting for frames and the - // subscription has ended - if (deletable) - delete this; - - return deletable; -} - void FrameSubscriber::OnFrameDelivered( scoped_refptr frame, base::TimeTicks, bool result) { - pending_frames--; - - if (RequestDestruct() || subscriber_ == NULL || !result) + if (!result) return; v8::Locker locker(isolate_); diff --git a/atom/browser/api/frame_subscriber.h b/atom/browser/api/frame_subscriber.h index 6f6d66b6be8..089c4922d79 100644 --- a/atom/browser/api/frame_subscriber.h +++ b/atom/browser/api/frame_subscriber.h @@ -6,6 +6,7 @@ #define ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_ #include "base/callback.h" +#include "base/memory/weak_ptr.h" #include "content/public/browser/render_widget_host_view_frame_subscriber.h" #include "ui/gfx/geometry/size.h" #include "v8/include/v8.h" @@ -14,43 +15,28 @@ namespace atom { namespace api { -class FrameSubscriber { +class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber { public: using FrameCaptureCallback = base::Callback)>; - // Inner class that is the actual subscriber sent to chromium - class Subscriber : - public content::RenderWidgetHostViewFrameSubscriber { - public: - explicit Subscriber(FrameSubscriber* frame_subscriber); - - bool ShouldCaptureFrame(const gfx::Rect& damage_rect, - base::TimeTicks present_time, - scoped_refptr* storage, - DeliverFrameCallback* callback) override; - - ~Subscriber(); - private: - FrameSubscriber* frame_subscriber_; - }; - FrameSubscriber(v8::Isolate* isolate, const gfx::Size& size, const FrameCaptureCallback& callback); - Subscriber* GetSubscriber(); + bool ShouldCaptureFrame(const gfx::Rect& damage_rect, + base::TimeTicks present_time, + scoped_refptr* storage, + DeliverFrameCallback* callback) override; private: void OnFrameDelivered( scoped_refptr frame, base::TimeTicks, bool); - bool RequestDestruct(); - v8::Isolate* isolate_; gfx::Size size_; FrameCaptureCallback callback_; - Subscriber* subscriber_; - int pending_frames; + + base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(FrameSubscriber); }; From 3c4043fd3968a2c153b978251de3e84d4f58ace9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Feb 2016 11:00:36 +0800 Subject: [PATCH 066/173] spec: Skip autoUpdater tests in MAS build --- 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 72a1d90a7fe..efd3afe3882 100644 --- a/spec/api-auto-updater-spec.js +++ b/spec/api-auto-updater-spec.js @@ -2,6 +2,10 @@ const assert = require('assert'); const autoUpdater = require('electron').remote.autoUpdater; const ipcRenderer = require('electron').ipcRenderer; +// Skip autoUpdater tests in MAS build. +if (process.mas) + return; + describe('autoUpdater module', function() { describe('checkForUpdates', function() { it('emits an error on Windows when called the feed URL is not set', function (done) { From 2aff0c47d03458947dad5866069523fca717042f Mon Sep 17 00:00:00 2001 From: cesine Date: Mon, 15 Feb 2016 21:26:25 -0500 Subject: [PATCH 067/173] :arrow_up: :shirt: updated to eslint 2.1.0 Verified migration doc (nothing to be done) http://eslint.org/docs/user-guide/migrating-to-2.0.0 And made sure the eslint tasks passed --- atom/browser/lib/rpc-server.js | 6 ++++-- package.json | 2 +- spec/asar-spec.js | 1 - spec/fixtures/api/quit-app/main.js | 12 ++++++------ spec/fixtures/module/call.js | 4 ++-- spec/fixtures/module/id.js | 2 +- spec/fixtures/module/locale-compare.js | 2 +- spec/fixtures/module/original-fs.js | 2 +- spec/fixtures/module/print_name.js | 4 ++-- spec/fixtures/module/promise.js | 2 +- spec/fixtures/module/property.js | 2 +- spec/fixtures/module/send-later.js | 2 +- spec/fixtures/module/set-immediate.js | 2 +- spec/fixtures/workers/shared_worker.js | 6 +++--- spec/fixtures/workers/worker.js | 2 +- spec/static/main.js | 4 ++-- 16 files changed, 28 insertions(+), 27 deletions(-) diff --git a/atom/browser/lib/rpc-server.js b/atom/browser/lib/rpc-server.js index 2f2b739e4a1..976a42331b6 100644 --- a/atom/browser/lib/rpc-server.js +++ b/atom/browser/lib/rpc-server.js @@ -130,7 +130,7 @@ var unwrapArgs = function(sender, args) { return Promise.resolve({ then: metaToValue(meta.then) }); - case 'object': + case 'object': { let ret = v8Util.createObjectWithName(meta.name); ref = meta.members; for (i = 0, len = ref.length; i < len; i++) { @@ -138,12 +138,13 @@ var unwrapArgs = function(sender, args) { ret[member.name] = metaToValue(member.value); } return ret; + } case 'function-with-return-value': returnValue = metaToValue(meta.value); return function() { return returnValue; }; - case 'function': + case 'function': { // Cache the callbacks in renderer. if (!sender.callbacks) { sender.callbacks = new IDWeakMap; @@ -172,6 +173,7 @@ var unwrapArgs = function(sender, args) { }); sender.callbacks.set(meta.id, callIntoRenderer); return callIntoRenderer; + } default: throw new TypeError("Unknown type: " + meta.type); } diff --git a/package.json b/package.json index 6d812087199..f684386269e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.36.7", "devDependencies": { "asar": "^0.9.0", - "eslint": "^1.10.3", + "eslint": "^2.1.0", "request": "*" }, "optionalDependencies": { diff --git a/spec/asar-spec.js b/spec/asar-spec.js index 81d881f7eb4..a8f449451fc 100644 --- a/spec/asar-spec.js +++ b/spec/asar-spec.js @@ -517,7 +517,6 @@ describe('asar package', function() { }); }); describe('child_process.fork', function() { - child_process = require('child_process'); it('opens a normal js file', function(done) { var child; child = child_process.fork(path.join(fixtures, 'asar', 'a.asar', 'ping.js')); diff --git a/spec/fixtures/api/quit-app/main.js b/spec/fixtures/api/quit-app/main.js index e2f97affe6d..114e830076a 100644 --- a/spec/fixtures/api/quit-app/main.js +++ b/spec/fixtures/api/quit-app/main.js @@ -1,12 +1,12 @@ -var app = require('electron').app +var app = require('electron').app; app.on('ready', function () { // This setImmediate call gets the spec passing on Linux setImmediate(function () { - app.exit(123) - }) -}) + app.exit(123); + }); +}); process.on('exit', function (code) { - console.log('Exit event with code: ' + code) -}) + console.log('Exit event with code: ' + code); +}); diff --git a/spec/fixtures/module/call.js b/spec/fixtures/module/call.js index 4cf232e220d..ce0eb6324df 100644 --- a/spec/fixtures/module/call.js +++ b/spec/fixtures/module/call.js @@ -1,7 +1,7 @@ exports.call = function(func) { return func(); -} +}; exports.constructor = function() { this.test = 'test'; -} +}; diff --git a/spec/fixtures/module/id.js b/spec/fixtures/module/id.js index 2faec9d3832..5bfae457fe0 100644 --- a/spec/fixtures/module/id.js +++ b/spec/fixtures/module/id.js @@ -1 +1 @@ -exports.id = 1127 +exports.id = 1127; diff --git a/spec/fixtures/module/locale-compare.js b/spec/fixtures/module/locale-compare.js index f99e7c3be11..32dfb309926 100644 --- a/spec/fixtures/module/locale-compare.js +++ b/spec/fixtures/module/locale-compare.js @@ -1,4 +1,4 @@ -process.on('message', function (msg) { +process.on('message', function () { process.send([ 'a'.localeCompare('a'), 'ä'.localeCompare('z', 'de'), diff --git a/spec/fixtures/module/original-fs.js b/spec/fixtures/module/original-fs.js index 90b6abcf9b7..7a527c63358 100644 --- a/spec/fixtures/module/original-fs.js +++ b/spec/fixtures/module/original-fs.js @@ -1,3 +1,3 @@ -process.on('message', function (msg) { +process.on('message', function () { process.send(typeof require('original-fs')); }); diff --git a/spec/fixtures/module/print_name.js b/spec/fixtures/module/print_name.js index 01d13f4ba8b..96ac2d6f3cb 100644 --- a/spec/fixtures/module/print_name.js +++ b/spec/fixtures/module/print_name.js @@ -1,7 +1,7 @@ exports.print = function(obj) { return obj.constructor.name; -} +}; exports.echo = function(obj) { return obj; -} +}; diff --git a/spec/fixtures/module/promise.js b/spec/fixtures/module/promise.js index 2e52ed37440..b9b568855e3 100644 --- a/spec/fixtures/module/promise.js +++ b/spec/fixtures/module/promise.js @@ -2,4 +2,4 @@ exports.twicePromise = function (promise) { return promise.then(function (value) { return value * 2; }); -} +}; diff --git a/spec/fixtures/module/property.js b/spec/fixtures/module/property.js index 88e596f7308..36286d800e1 100644 --- a/spec/fixtures/module/property.js +++ b/spec/fixtures/module/property.js @@ -1 +1 @@ -exports.property = 1127 +exports.property = 1127; diff --git a/spec/fixtures/module/send-later.js b/spec/fixtures/module/send-later.js index 13f02452db1..704f47d328d 100644 --- a/spec/fixtures/module/send-later.js +++ b/spec/fixtures/module/send-later.js @@ -1,4 +1,4 @@ var ipcRenderer = require('electron').ipcRenderer; window.onload = function() { ipcRenderer.send('answer', typeof window.process); -} +}; diff --git a/spec/fixtures/module/set-immediate.js b/spec/fixtures/module/set-immediate.js index e7d44a75d1f..d36355ee23b 100644 --- a/spec/fixtures/module/set-immediate.js +++ b/spec/fixtures/module/set-immediate.js @@ -3,7 +3,7 @@ process.on('uncaughtException', function(error) { process.exit(1); }); -process.on('message', function(msg) { +process.on('message', function() { setImmediate(function() { process.send('ok'); process.exit(0); diff --git a/spec/fixtures/workers/shared_worker.js b/spec/fixtures/workers/shared_worker.js index d35b47435e8..40220793979 100644 --- a/spec/fixtures/workers/shared_worker.js +++ b/spec/fixtures/workers/shared_worker.js @@ -1,7 +1,7 @@ -onconnect = function(event) { +this.onconnect = function(event) { var port = event.ports[0]; port.start(); port.onmessage = function(event) { port.postMessage(event.data); - } -} + }; +}; diff --git a/spec/fixtures/workers/worker.js b/spec/fixtures/workers/worker.js index 6f9533708a0..4f445470b9a 100644 --- a/spec/fixtures/workers/worker.js +++ b/spec/fixtures/workers/worker.js @@ -1,3 +1,3 @@ this.onmessage = function(msg) { this.postMessage(msg.data); -} +}; diff --git a/spec/static/main.js b/spec/static/main.js index 125ef72f609..48fdf17c3dc 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -74,7 +74,7 @@ app.on('ready', function() { // Send auto updater errors to window to be verified in specs electron.autoUpdater.on('error', function (error) { - window.send('auto-updater-error', error.message) + window.send('auto-updater-error', error.message); }); window = new BrowserWindow({ @@ -108,7 +108,7 @@ app.on('ready', function() { // reply the result to renderer for verifying var downloadFilePath = path.join(__dirname, '..', 'fixtures', 'mock.pdf'); ipcMain.on('set-download-option', function(event, need_cancel, prevent_default) { - window.webContents.session.once('will-download', function(e, item, webContents) { + window.webContents.session.once('will-download', function(e, item) { if (prevent_default) { e.preventDefault(); const url = item.getURL(); From b8e8e4c930b3d06a2ae71f995b8b329ea41bd545 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Feb 2016 11:34:39 +0800 Subject: [PATCH 068/173] docs: Cleanup the IPC docs --- docs/api/ipc-main.md | 46 +++++++++++++++--------------- docs/api/ipc-renderer.md | 61 +++++++++++++++++++++------------------- docs/api/web-contents.md | 7 +++-- 3 files changed, 61 insertions(+), 53 deletions(-) diff --git a/docs/api/ipc-main.md b/docs/api/ipc-main.md index 337d86be217..84fbcfd5a72 100644 --- a/docs/api/ipc-main.md +++ b/docs/api/ipc-main.md @@ -9,7 +9,7 @@ module. ## Sending Messages It is also possible to send messages from the main process to the renderer -process, see [webContents.send](web-contents.md#webcontentssendchannel-arg1-arg2-) for more information. +process, see [webContents.send][web-contents-send] for more information. * When sending a message, the event name is the `channel`. * To reply a synchronous message, you need to set `event.returnValue`. @@ -48,37 +48,37 @@ ipcRenderer.send('asynchronous-message', 'ping'); The `ipcMain` module has the following method to listen for events: -### `ipcMain.on(channel, callback)` +### `ipcMain.on(channel, listener)` -* `channel` String - The event name. -* `callback` Function +* `channel` String +* `listener` Function -When the event occurs the `callback` is called with an `event` object and -arbitrary arguments. +Listens to `channel`, when a new message arrives `listener` would be called with +`listener(event, args...)`. -### `ipcMain.removeListener(channel, callback)` +### `ipcMain.once(channel, listener)` -* `channel` String - The event name. -* `callback` Function - The reference to the same function that you used for - `ipcMain.on(channel, callback)` +* `channel` String +* `listener` Function -Once done listening for messages, if you no longer want to activate this -callback and for whatever reason can't merely stop sending messages on the -channel, this function will remove the callback handler for the specified -channel. +Adds a one time `listener` function for the event. This `listener` is invoked +only the next time a message is sent to `channel`, after which it is removed. -### `ipcMain.removeAllListeners(channel)` +### `ipcMain.removeListener(channel, listener)` -* `channel` String - The event name. +* `channel` String +* `listener` Function -This removes *all* handlers to this ipc channel. +Removes the specified `listener` from the listener array for the specified +`channel`. -### `ipcMain.once(channel, callback)` +### `ipcMain.removeAllListeners([channel])` -Use this in place of `ipcMain.on()` to fire handlers meant to occur only once, -as in, they won't be activated after one call of `callback` +* `channel` String (optional) -## IPC Event +Removes all listeners, or those of the specified `channel`. + +## Event object The `event` object passed to the `callback` has the following methods: @@ -90,4 +90,6 @@ Set this to the value to be returned in a synchronous message. Returns the `webContents` that sent the message, you can call `event.sender.send` to reply to the asynchronous message, see -[webContents.send](web-contents.md#webcontentssendchannel-arg1-arg2-) for more information. +[webContents.send][web-contents-send] for more information. + +[web-contents-send]: web-contents.md#webcontentssendchannel-arg1-arg2- diff --git a/docs/api/ipc-renderer.md b/docs/api/ipc-renderer.md index d8f344a204a..f17843702b5 100644 --- a/docs/api/ipc-renderer.md +++ b/docs/api/ipc-renderer.md @@ -12,35 +12,35 @@ See [ipcMain](ipc-main.md) for code examples. The `ipcRenderer` module has the following method to listen for events: -### `ipcRenderer.on(channel, callback)` +### `ipcRenderer.on(channel, listener)` -* `channel` String - The event name. -* `callback` Function +* `channel` String +* `listener` Function -When the event occurs the `callback` is called with an `event` object and -arbitrary arguments. +Listens to `channel`, when a new message arrives `listener` would be called with +`listener(event, args...)`. -### `ipcRenderer.removeListener(channel, callback)` +### `ipcRenderer.once(channel, listener)` -* `channel` String - The event name. -* `callback` Function - The reference to the same function that you used for - `ipcRenderer.on(channel, callback)` +* `channel` String +* `listener` Function -Once done listening for messages, if you no longer want to activate this -callback and for whatever reason can't merely stop sending messages on the -channel, this function will remove the callback handler for the specified -channel. +Adds a one time `listener` function for the event. This `listener` is invoked +only the next time a message is sent to `channel`, after which it is removed. -### `ipcRenderer.removeAllListeners(channel)` +### `ipcRenderer.removeListener(channel, listener)` -* `channel` String - The event name. +* `channel` String +* `listener` Function -This removes *all* handlers to this ipc channel. +Removes the specified `listener` from the listener array for the specified +`channel`. -### `ipcRenderer.once(channel, callback)` +### `ipcRenderer.removeAllListeners([channel])` -Use this in place of `ipcRenderer.on()` to fire handlers meant to occur only once, -as in, they won't be activated after one call of `callback` +* `channel` String (optional) + +Removes all listeners, or those of the specified `channel`. ## Sending Messages @@ -48,30 +48,33 @@ The `ipcRenderer` module has the following methods for sending messages: ### `ipcRenderer.send(channel[, arg1][, arg2][, ...])` -* `channel` String - The event name. +* `channel` String * `arg` (optional) -Send an event to the main process asynchronously via a `channel`, you can also -send arbitrary arguments. Arguments will be serialized (json) and hence no functions or prototype chain will be included. The main process handles it by listening for the -`channel` event with `ipcMain`. +Send a message to the main process asynchronously via `channel`, you can also +send arbitrary arguments. Arguments will be serialized in JSON internally and +hence no functions or prototype chain will be included. + +The main process handles it by listening for `channel` with `ipcMain` module. ### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])` -* `channel` String - The event name. +* `channel` String * `arg` (optional) -Send an event to the main process synchronously via a `channel`, you can also -send arbitrary arguments. +Send a message to the main process synchronously via `channel`, you can also +send arbitrary arguments. Arguments will be serialized in JSON internally and +hence no functions or prototype chain will be included. -The main process handles it by listening for the `channel` event with -`ipcMain` and replies by setting `event.returnValue`. +The main process handles it by listening for `channel` with `ipcMain` module, +and replies by setting `event.returnValue`. __Note:__ Sending a synchronous message will block the whole renderer process, unless you know what you are doing you should never use it. ### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])` -* `channel` String - The event name. +* `channel` String * `arg` (optional) Like `ipcRenderer.send` but the event will be sent to the `` element in diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 61c2ab1f691..b868bea9ed5 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -693,8 +693,11 @@ Opens the developer tools for the service worker context. * `arg` (optional) Send an asynchronous message to renderer process via `channel`, you can also -send arbitrary arguments. Arguments will be serialized (json) and hence no functions or prototype chain will be included. The renderer process can handle the message by -listening to the `channel` event with the `ipcRenderer` module. +send arbitrary arguments. Arguments will be serialized in JSON internally and +hence no functions or prototype chain will be included. + +The renderer process can handle the message by listening to `channel` with the +`ipcRenderer` module. An example of sending messages from the main process to the renderer process: From f58bab70c5146d63583af9179941d87fe11d7e60 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Feb 2016 11:52:47 +0800 Subject: [PATCH 069/173] docs: Improve the docs on sharing data --- docs/faq/electron-faq.md | 40 +++++++++++++++++------------------- docs/tutorial/quick-start.md | 18 ++++++++-------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/docs/faq/electron-faq.md b/docs/faq/electron-faq.md index d5470f70173..a58d31107b6 100644 --- a/docs/faq/electron-faq.md +++ b/docs/faq/electron-faq.md @@ -18,40 +18,34 @@ New features of Node.js are usually brought by V8 upgrades, since Electron is using the V8 shipped by Chrome browser, the shiny new JavaScript feature of a new Node.js version is usually already in Electron. -## What are the different techniques to share objects between web pages? +## How to share data between web pages? -To share objects between web pages (that is on the renderer side) the simplest -and more natural technique is to use a web standard API already available in all -browsers. A good candidate is the -[Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Storage), -through either the -[`window.localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) property or the -[`window.sessionStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) property. -Note that the Storage API allows only to store strings, so objects must be -serialized as JSON. -Another candidate is -[IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API). +To share data between web pages (the renderer processes) the simplest way is to +use HTML5 APIs which are already available in browsers. Good candidates are +[Storage API][storage], [`localStorage`][local-storage], +[`sessionStorage`][session-storage], and [IndexedDB][indexed-db]. -Another technique, but this time specific to Electron, is to store objects in -the main process as a global variable and then to access them from the renderers -through the `remote` module: +Or you can use the IPC system, which are specific to Electron, to store objects +in the main process as a global variable, and then to access them from the +renderers through the `remote` module: ```javascript -// In main.js of browser process -global.sharedObject = {}; +// In the main process. +global.sharedObject = { + someProperty: 'default value' +}; ``` ```javascript -// js in page-1.html -require('remote').getGlobal('sharedObject').someProperty = 'some value'; +// In page 1. +require('remote').getGlobal('sharedObject').someProperty = 'new value'; ``` ```javascript -// js in page-2.html +// In page 2. console.log(require('remote').getGlobal('sharedObject').someProperty); ``` - ## My app's window/tray disappeared after a few minutes. This happens when the variable which is used to store the window/tray gets @@ -154,3 +148,7 @@ is only available in renderer processes. [memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management [variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx [electron-module]: https://www.npmjs.com/package/electron +[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage +[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage +[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage +[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index 67fe5d608a1..684c72c6669 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -34,8 +34,8 @@ The main process creates web pages by creating `BrowserWindow` instances. Each is also terminated. The main process manages all web pages and their corresponding renderer -processes. Each renderer process is isolated and only cares -about the web page running in it. +processes. Each renderer process is isolated and only cares about the web page +running in it. In web pages, calling native GUI related APIs is not allowed because managing native GUI resources in web pages is very dangerous and it is easy to leak @@ -43,13 +43,11 @@ resources. If you want to perform GUI operations in a web page, the renderer process of the web page must communicate with the main process to request that the main process perform those operations. -In Electron, we have provided the [ipc](../api/ipc-renderer.md) module for -communication between the main process and renderer process. There is also a -[remote](../api/remote.md) module for RPC style communication. - -And finally there are different techniques [to share objects between web -pages](../faq/electron-faq.md#what-are-the-different-techniques-to-share-objects-between-web-pages) -of the same window or of different windows. +In Electron, we have several ways to communicate between the main process and +renderer processes. Like [`ipcRenderer`](../api/ipc-renderer.md) and +[`ipcMain`](../api/ipc-main.md) modules for sending messages, and the +[remote](../api/remote.md) module for RPC style communication. There is also +an FAQ entry on [how to share data between web pages][share-data]. ## Write your First Electron App @@ -209,3 +207,5 @@ $ cd electron-quick-start # Install dependencies and run the app $ npm install && npm start ``` + +[share-data]: ../faq/electron-faq.md#how-to-share-data-between-web-pages From 2b406ccaf751bb2541b1924aae8204863bab6d4f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Feb 2016 11:54:41 +0800 Subject: [PATCH 070/173] Optional => optional --- docs/api/web-contents.md | 6 +++--- docs/api/web-view-tag.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index b868bea9ed5..c243425c5d9 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -259,8 +259,8 @@ Returns: * `result` Object * `requestId` Integer * `finalUpdate` Boolean - Indicates if more responses are to follow. - * `matches` Integer (Optional) - Number of Matches. - * `selectionArea` Object (Optional) - Coordinates of first match region. + * `matches` Integer (optional) - Number of Matches. + * `selectionArea` Object (optional) - Coordinates of first match region. Emitted when a result is available for [`webContents.findInPage`](web-contents.md#webcontentsfindinpage) request. @@ -503,7 +503,7 @@ Inserts `text` to the focused element. ### `webContents.findInPage(text[, options])` * `text` String - Content to be searched, must not be empty. -* `options` Object (Optional) +* `options` Object (optional) * `forward` Boolean - Whether to search forward or backward, defaults to `true`. * `findNext` Boolean - Whether the operation is first request or a follow up, defaults to `false`. diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index c410287553a..976f859efca 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -382,7 +382,7 @@ Inserts `text` to the focused element. ### `.findInPage(text[, options])` * `text` String - Content to be searched, must not be empty. -* `options` Object (Optional) +* `options` Object (optional) * `forward` Boolean - Whether to search forward or backward, defaults to `true`. * `findNext` Boolean - Whether the operation is first request or a follow up, defaults to `false`. @@ -567,8 +567,8 @@ Returns: * `result` Object * `requestId` Integer * `finalUpdate` Boolean - Indicates if more responses are to follow. - * `matches` Integer (Optional) - Number of Matches. - * `selectionArea` Object (Optional) - Coordinates of first match region. + * `matches` Integer (optional) - Number of Matches. + * `selectionArea` Object (optional) - Coordinates of first match region. Fired when a result is available for [`webview.findInPage`](web-view-tag.md#webviewtagfindinpage) request. From fded8d80b118fa39cb5fd225e4412434f0bb31ee Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Feb 2016 12:11:05 +0800 Subject: [PATCH 071/173] docs: Remove unnecessary "properties: " suffix --- docs/api/browser-window.md | 53 +++++++++++++++++++------------------- docs/api/crash-reporter.md | 23 +++++++---------- docs/api/web-contents.md | 46 +++++++++++++-------------------- docs/api/web-view-tag.md | 2 +- 4 files changed, 56 insertions(+), 68 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 7cf684a3953..2bd6c1a9635 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -458,7 +458,7 @@ Returns a boolean, whether the window is in fullscreen mode. * `aspectRatio` The aspect ratio we want to maintain for some portion of the content view. * `extraSize` Object (optional) - The extra size not to be included while -maintaining the aspect ratio. Properties: +maintaining the aspect ratio. * `width` Integer * `height` Integer @@ -478,13 +478,11 @@ height areas you have within the overall content view. ### `win.setBounds(options[, animate])` -* `options` Object, properties: - +* `options` Object * `x` Integer * `y` Integer * `width` Integer * `height` Integer - * `animate` Boolean (optional) _OS X_ Resizes and moves the window to `width`, `height`, `x`, `y`. @@ -729,7 +727,7 @@ Whether the window's document has been edited. ### `win.capturePage([rect, ]callback)` -* `rect` Object (optional)- The area of page to be captured, properties: +* `rect` Object (optional) - The area of page to be captured * `x` Integer * `y` Integer * `width` Integer @@ -802,27 +800,7 @@ Returns whether the window has a shadow. On Windows and Linux always returns ### `win.setThumbarButtons(buttons)` _Windows 7+_ -`buttons` Array of `button` Objects: - -`button` Object, properties: - -* `icon` [NativeImage](native-image.md) - The icon showing in thumbnail - toolbar. -* `tooltip` String (optional) - The text of the button's tooltip. -* `flags` Array (optional) - Control specific states and behaviors - of the button. By default, it uses `enabled`. It can include following - Strings: - * `enabled` - The button is active and available to the user. - * `disabled` - The button is disabled. It is present, but has a visual - state indicating it will not respond to user action. - * `dismissonclick` - When the button is clicked, the taskbar button's - flyout closes immediately. - * `nobackground` - Do not draw a button border, use only the image. - * `hidden` - The button is not shown to the user. - * `noninteractive` - The button is enabled but not interactive; no - pressed button state is drawn. This value is intended for instances - where the button is used in a notification. -* `click` - Function +* `buttons` Array Add a thumbnail toolbar with a specified set of buttons to the thumbnail image of a window in a taskbar button layout. Returns a `Boolean` object indicates @@ -833,6 +811,29 @@ the limited room. Once you setup the thumbnail toolbar, the toolbar cannot be removed due to the platform's limitation. But you can call the API with an empty array to clean the buttons. +The `buttons` is an array of `Button` objects: + +* `Button` Object + * `icon` [NativeImage](native-image.md) - The icon showing in thumbnail + toolbar. + * `click` Function + * `tooltip` String (optional) - The text of the button's tooltip. + * `flags` Array (optional) - Control specific states and behaviors of the + button. By default, it is `['enabled']`. + +The `flags` is an array that can include following `String`s: + +* `enabled` - The button is active and available to the user. +* `disabled` - The button is disabled. It is present, but has a visual state + indicating it will not respond to user action. +* `dismissonclick` - When the button is clicked, the thumbnail window closes + immediately. +* `nobackground` - Do not draw a button border, use only the image. +* `hidden` - The button is not shown to the user. +* `noninteractive` - The button is enabled but not interactive; no pressed + button state is drawn. This value is intended for instances where the button + is used in a notification. + ### `win.showDefinitionForSelection()` _OS X_ Shows pop-up dictionary that searches the selected word on the page. diff --git a/docs/api/crash-reporter.md b/docs/api/crash-reporter.md index 1b092826356..98465dffc97 100644 --- a/docs/api/crash-reporter.md +++ b/docs/api/crash-reporter.md @@ -22,19 +22,16 @@ The `crash-reporter` module has the following methods: ### `crashReporter.start(options)` -`options` Object, properties: - -* `productName` String, default: Electron. -* `companyName` String (**required**) -* `submitURL` String, (**required**) - * URL that crash reports will be sent to as POST. -* `autoSubmit` Boolean, default: `true`. - * Send the crash report without user interaction. -* `ignoreSystemCrashHandler` Boolean, default: `false`. -* `extra` Object - * An object you can define that will be sent along with the report. - * Only string properties are sent correctly. - * Nested objects are not supported. +* `options` Object + * `companyName` String + * `submitURL` String - URL that crash reports will be sent to as POST. + * `productName` String (optional) - Default is `Electron`. + * `autoSubmit` Boolean - Send the crash report without user interaction. + Default is `true`. + * `ignoreSystemCrashHandler` Boolean - Default is `false`. + * `extra` Object - An object you can define that will be sent along with the + report. Only string properties are sent correctly, Nested objects are not + supported. You are required to call this method before using other `crashReporter` APIs. diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index c243425c5d9..e0139a29fa6 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -310,7 +310,7 @@ The `webContents` object has the following instance methods: ### `webContents.loadURL(url[, options])` * `url` URL -* `options` Object (optional), properties: +* `options` Object (optional) * `httpReferrer` String - A HTTP Referrer url. * `userAgent` String - A user agent originating the request. * `extraHeaders` String - Extra headers separated by "\n" @@ -556,11 +556,10 @@ when the JS promise is rejected. ### `webContents.print([options])` -`options` Object (optional), properties: - -* `silent` Boolean - Don't ask user for print settings, defaults to `false` -* `printBackground` Boolean - Also prints the background color and image of - the web page, defaults to `false`. +* `options` Object (optional) + * `silent` Boolean - Don't ask user for print settings. Default is `false`. + * `printBackground` Boolean - Also prints the background color and image of + the web page. Default is `false`. Prints window's web page. When `silent` is set to `false`, Electron will pick up system's default printer and default settings for printing. @@ -574,31 +573,22 @@ size. ### `webContents.printToPDF(options, callback)` -`options` Object, properties: - -* `marginsType` Integer - Specify the type of margins to use - * 0 - default - * 1 - none - * 2 - minimum -* `pageSize` String - Specify page size of the generated PDF. - * `A5` - * `A4` - * `A3` - * `Legal` - * `Letter` - * `Tabloid` -* `printBackground` Boolean - Whether to print CSS backgrounds. -* `printSelectionOnly` Boolean - Whether to print selection only. -* `landscape` Boolean - `true` for landscape, `false` for portrait. - -`callback` Function - `function(error, data) {}` - -* `error` Error -* `data` Buffer - PDF file content. +* `options` Object + * `marginsType` Integer - Specifies the type of margins to use. Uses 0 for + default margin, 1 for no margin, and 2 for minimum margin. + * `pageSize` String - Specify page size of the generated PDF. Can be `A3`, + `A4`, `A5`, `Legal`, `Letter` and `Tabloid`. + * `printBackground` Boolean - Whether to print CSS backgrounds. + * `printSelectionOnly` Boolean - Whether to print selection only. + * `landscape` Boolean - `true` for landscape, `false` for portrait. +* `callback` Function Prints window's web page as PDF with Chromium's preview printing custom settings. +The `callback` will be called with `callback(error, data)` on completion. The +`data` is a `Buffer` that contains the generated PDF data. + By default, an empty `options` will be regarded as: ```javascript @@ -651,7 +641,7 @@ Removes the specified path from DevTools workspace. ### `webContents.openDevTools([options])` -* `options` Object (optional). Properties: +* `options` Object (optional) * `detach` Boolean - opens DevTools in a new window Opens the devtools. diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 976f859efca..3ba9a602e8b 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -184,7 +184,7 @@ webview.addEventListener("dom-ready", function() { ### `.loadURL(url[, options])` * `url` URL -* `options` Object (optional), properties: +* `options` Object (optional) * `httpReferrer` String - A HTTP Referrer url. * `userAgent` String - A user agent originating the request. * `extraHeaders` String - Extra headers separated by "\n" From 81ffde3c2a88f7f2bc25532b97a26e96cc28432e Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Tue, 16 Feb 2016 09:55:59 +0900 Subject: [PATCH 072/173] :memo: Update as upstream [ci skip] --- .../desktop-environment-integration.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md index 91fc59a8f2e..cd6ff545e14 100644 --- a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md +++ b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md @@ -283,13 +283,15 @@ window.setRepresentedFilename('/etc/passwd'); window.setDocumentEdited(true); ``` -[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath -[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments -[setusertaskstasks]: ../api/app.md#appsetusertaskstasks -[setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress -[setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename -[setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited +[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-os-x-windows +[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows +[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows +[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress +[setrepresentedfilename]: ../api/browser-window.md#winsetrepresentedfilenamefilename-os-x +[setdocumentedited]: ../api/browser-window.md#winsetdocumenteditededited-os-x [app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx [unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher -[setthumbarbuttons]: ../api/browser-window.md#browserwindowsetthumbarbuttonsbuttons -[trayballoon]: ../api/tray.md#traydisplayballoonoptions-windows +[setthumbarbuttons]: ../api/browser-window.md#winsetthumbarbuttonsbuttons-windows-7 +[tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows +[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx +[notification-spec]: https://developer.gnome.org/notification-spec/ From aaca93046c5a6d0a16880ac0bc17c6890c57ffa9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Feb 2016 16:20:15 +0800 Subject: [PATCH 073/173] spec: Give beginFrameSubscription test more time to run --- spec/api-browser-window-spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index a38bdb16904..b64ef6145b7 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -480,6 +480,8 @@ describe('browser-window module', function() { }); describe('beginFrameSubscription method', function() { + this.timeout(20000); + it('subscribes frame updates', function(done) { let called = false; w.loadURL("file://" + fixtures + "/api/blank.html"); From afacca252e21804a4351570de7a7e879c95b5753 Mon Sep 17 00:00:00 2001 From: Destan Sarpkaya Date: Tue, 16 Feb 2016 16:24:05 +0200 Subject: [PATCH 074/173] add a new platform definition for linux On Linux in order for changes made to individual `MenuItem`s to take effect, you have to call `setContextMenu` again Regarding https://github.com/atom/electron/issues/1473 --- docs/api/tray.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/api/tray.md b/docs/api/tray.md index 08a43638be1..3d6f94ad0e5 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -32,6 +32,12 @@ __Platform limitations:__ install `libappindicator1` to make the tray icon work. * App indicator will only be shown when it has a context menu. * When app indicator is used on Linux, the `click` event is ignored. +* On Linux in order for changes made to individual `MenuItem`s to take effect, you have to call `setContextMenu` again. For example: + +```javascript +appIcon.menu.items[2].checked = false; +appIcon.setContextMenu(trayIcon.menu); +``` If you want to keep exact same behaviors on all platforms, you should not rely on the `click` event and always attach a context menu to the tray icon. From 0ba86b971633399b7d18086fdce1389718198f43 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Feb 2016 23:10:05 +0800 Subject: [PATCH 075/173] docs: Make variable names follow previous example --- docs/api/tray.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/api/tray.md b/docs/api/tray.md index 3d6f94ad0e5..22ab9aea5b7 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -32,11 +32,12 @@ __Platform limitations:__ install `libappindicator1` to make the tray icon work. * App indicator will only be shown when it has a context menu. * When app indicator is used on Linux, the `click` event is ignored. -* On Linux in order for changes made to individual `MenuItem`s to take effect, you have to call `setContextMenu` again. For example: +* On Linux in order for changes made to individual `MenuItem`s to take effect, + you have to call `setContextMenu` again. For example: ```javascript -appIcon.menu.items[2].checked = false; -appIcon.setContextMenu(trayIcon.menu); +contextMenu.items[2].checked = false; +appIcon.setContextMenu(contextMenu); ``` If you want to keep exact same behaviors on all platforms, you should not From 959c08a1ecdc31bb7c39ff3a4fcdf0c59bfbe50b Mon Sep 17 00:00:00 2001 From: dmnlk Date: Wed, 17 Feb 2016 02:20:38 +0900 Subject: [PATCH 076/173] add Japanese Electron Community --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ce6d483f0df..0080585b54c 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ forums - [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack - [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)* - [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)* +- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(Japanese)* Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron) for a community maintained list of useful example apps, tools and resources. From 2346caf6fbb691b7a2c7fe73e363344f371a8027 Mon Sep 17 00:00:00 2001 From: Seemann Date: Tue, 16 Feb 2016 23:19:20 +0300 Subject: [PATCH 077/173] fixed typo in the russian translation of README.md --- docs-translations/ru-RU/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ru-RU/README.md b/docs-translations/ru-RU/README.md index 07e50028df9..4e7ed443468 100644 --- a/docs-translations/ru-RU/README.md +++ b/docs-translations/ru-RU/README.md @@ -1,6 +1,6 @@ Пожалуйста, убедитесь, что вы используете документацию, которые соответствует вашей версии Electron. Номер версии должен быть частью адреса страницы. Если это не так, вы -возможно,используете документицию ветки разработки, которая может содержать изменения api, +возможно, используете документацию ветки разработки, которая может содержать изменения api, которые не совместимы с вашей версией Electron. Если это так, Вы можете переключиться на другую версию документации в списке [доступные версии](http://electron.atom.io/docs/) на atom.io, или From ccef805e9b85c4e17114e68cb14070c98e8a166c Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 16 Feb 2016 15:09:35 -0800 Subject: [PATCH 078/173] Add API for custom handling of deprecations --- atom/common/api/lib/deprecate.js | 14 ++++++++++++- atom/common/api/lib/deprecations.js | 11 ++++++++++ atom/common/api/lib/exports/electron.js | 6 ++++++ filenames.gypi | 1 + spec/api-deprecations-spec.js | 27 +++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 atom/common/api/lib/deprecations.js create mode 100644 spec/api-deprecations-spec.js diff --git a/atom/common/api/lib/deprecate.js b/atom/common/api/lib/deprecate.js index dcaf5f6cf6f..04b56e06b96 100644 --- a/atom/common/api/lib/deprecate.js +++ b/atom/common/api/lib/deprecate.js @@ -88,9 +88,13 @@ deprecate.warn = function(oldName, newName) { return deprecate.log(oldName + " is deprecated. Use " + newName + " instead."); }; +var deprecationHandler = null; + // Print deprecation message. deprecate.log = function(message) { - if (process.throwDeprecation) { + if (typeof deprecationHandler === 'function') { + deprecationHandler(message); + } else if (process.throwDeprecation) { throw new Error(message); } else if (process.traceDeprecation) { return console.trace(message); @@ -99,4 +103,12 @@ deprecate.log = function(message) { } }; +deprecate.setHandler = function(handler) { + deprecationHandler = handler; +}; + +deprecate.getHandler = function() { + return deprecationHandler; +} + module.exports = deprecate; diff --git a/atom/common/api/lib/deprecations.js b/atom/common/api/lib/deprecations.js new file mode 100644 index 00000000000..871ad036272 --- /dev/null +++ b/atom/common/api/lib/deprecations.js @@ -0,0 +1,11 @@ +'use strict'; + +const deprecate = require('electron').deprecate; + +exports.setHandler = function (deprecationHandler) { + deprecate.setHandler(deprecationHandler); +}; + +exports.getHandler = function () { + return deprecate.getHandler(); +} diff --git a/atom/common/api/lib/exports/electron.js b/atom/common/api/lib/exports/electron.js index 6811e73a10b..51ab48ded83 100644 --- a/atom/common/api/lib/exports/electron.js +++ b/atom/common/api/lib/exports/electron.js @@ -31,6 +31,12 @@ exports.defineProperties = function(exports) { return require('../crash-reporter'); } }, + deprecations: { + enumerable: true, + get: function() { + return require('../deprecations'); + } + }, nativeImage: { enumerable: true, get: function() { diff --git a/filenames.gypi b/filenames.gypi index a5369570cad..abb11453210 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -41,6 +41,7 @@ 'atom/common/api/lib/clipboard.js', 'atom/common/api/lib/crash-reporter.js', 'atom/common/api/lib/deprecate.js', + 'atom/common/api/lib/deprecations.js', 'atom/common/api/lib/exports/electron.js', 'atom/common/api/lib/native-image.js', 'atom/common/api/lib/shell.js', diff --git a/spec/api-deprecations-spec.js b/spec/api-deprecations-spec.js new file mode 100644 index 00000000000..282991a6858 --- /dev/null +++ b/spec/api-deprecations-spec.js @@ -0,0 +1,27 @@ +const assert = require('assert'); +const deprecations = require('electron').deprecations; + +describe('deprecations', function() { + beforeEach(function() { + deprecations.setHandler(null); + process.throwDeprecation = true; + }); + + it('allows a deprecation handler function to be specified', function() { + var messages = []; + + deprecations.setHandler(function (message) { + messages.push(message) + }); + + require('electron').webFrame.registerUrlSchemeAsSecure('some-scheme') + + assert.deepEqual(messages, ['registerUrlSchemeAsSecure is deprecated. Use registerURLSchemeAsSecure instead.']); + }); + + it('throws an exception if no deprecation handler is specified', function() { + assert.throws(function() { + require('electron').webFrame.registerUrlSchemeAsPrivileged('some-scheme') + }, "registerUrlSchemeAsPrivileged is deprecated. Use registerURLSchemeAsPrivileged instead."); + }); +}) From 3e3e59336600c88ebb5220c5be35fd3c07549878 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 16 Feb 2016 15:26:58 -0800 Subject: [PATCH 079/173] :shirt: Add missing semicolons --- atom/common/api/lib/deprecate.js | 2 +- atom/common/api/lib/deprecations.js | 2 +- spec/api-deprecations-spec.js | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/atom/common/api/lib/deprecate.js b/atom/common/api/lib/deprecate.js index 04b56e06b96..852d544deea 100644 --- a/atom/common/api/lib/deprecate.js +++ b/atom/common/api/lib/deprecate.js @@ -109,6 +109,6 @@ deprecate.setHandler = function(handler) { deprecate.getHandler = function() { return deprecationHandler; -} +}; module.exports = deprecate; diff --git a/atom/common/api/lib/deprecations.js b/atom/common/api/lib/deprecations.js index 871ad036272..e4290c74947 100644 --- a/atom/common/api/lib/deprecations.js +++ b/atom/common/api/lib/deprecations.js @@ -8,4 +8,4 @@ exports.setHandler = function (deprecationHandler) { exports.getHandler = function () { return deprecate.getHandler(); -} +}; diff --git a/spec/api-deprecations-spec.js b/spec/api-deprecations-spec.js index 282991a6858..2f010059059 100644 --- a/spec/api-deprecations-spec.js +++ b/spec/api-deprecations-spec.js @@ -11,17 +11,17 @@ describe('deprecations', function() { var messages = []; deprecations.setHandler(function (message) { - messages.push(message) + messages.push(message); }); - require('electron').webFrame.registerUrlSchemeAsSecure('some-scheme') + require('electron').webFrame.registerUrlSchemeAsSecure('some-scheme'); assert.deepEqual(messages, ['registerUrlSchemeAsSecure is deprecated. Use registerURLSchemeAsSecure instead.']); }); it('throws an exception if no deprecation handler is specified', function() { assert.throws(function() { - require('electron').webFrame.registerUrlSchemeAsPrivileged('some-scheme') + require('electron').webFrame.registerUrlSchemeAsPrivileged('some-scheme'); }, "registerUrlSchemeAsPrivileged is deprecated. Use registerURLSchemeAsPrivileged instead."); }); -}) +}); From 407bef5727a8bf36fd011d4e6e6800386b236ac3 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 17 Feb 2016 00:40:35 +0900 Subject: [PATCH 080/173] :memo: Update as upstream [ci skip] --- README-ko.md | 1 + docs-translations/ko-KR/api/browser-window.md | 46 +++++++------- docs-translations/ko-KR/api/crash-reporter.md | 22 +++---- docs-translations/ko-KR/api/ipc-main.md | 44 +++++++------ docs-translations/ko-KR/api/ipc-renderer.md | 51 +++++++++------- docs-translations/ko-KR/api/web-contents.md | 61 ++++++++----------- docs-translations/ko-KR/api/web-view-tag.md | 8 +-- docs-translations/ko-KR/faq/electron-faq.md | 32 ++++++++++ .../desktop-environment-integration.md | 28 +++++++++ .../ko-KR/tutorial/quick-start.md | 5 +- 10 files changed, 182 insertions(+), 116 deletions(-) diff --git a/README-ko.md b/README-ko.md index 664075dd481..b9085828d46 100644 --- a/README-ko.md +++ b/README-ko.md @@ -57,6 +57,7 @@ API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝 - [중국어 번체](https://github.com/atom/electron/tree/master/docs-translations/zh-TW) - [우크라이나어](https://github.com/atom/electron/tree/master/docs-translations/uk-UA) - [러시아어](https://github.com/atom/electron/tree/master/docs-translations/ru-RU) +- [프랑스어](https://github.com/atom/electron/tree/master/docs-translations/fr-FR) ## 시작하기 diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index f487a38f5da..8bc4a1545fc 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -451,7 +451,6 @@ var win = new BrowserWindow({ width: 800, height: 600 }); * `aspectRatio` 유지하려 하는 컨텐츠 뷰 일부의 종횡비 * `extraSize` Object (optional) - 종횡비를 유지하는 동안 포함되지 않을 엑스트라 크기. - 사용 가능한 속성: * `width` Integer * `height` Integer @@ -469,7 +468,7 @@ var win = new BrowserWindow({ width: 800, height: 600 }); ### `win.setBounds(options[, animate])` -* `options` Object, properties: +* `options` Object * `x` Integer * `y` Integer @@ -719,8 +718,7 @@ Windows 메시지 훅을 등록합니다. `callback`은 WndProc에서 메시지 ### `win.capturePage([rect, ]callback)` -* `rect` Object (optional) - 캡쳐할 페이지의 영역. - 사용할 수 있는 속성은 다음과 같습니다: +* `rect` Object (optional) - 캡쳐할 페이지의 영역 * `x` Integer * `y` Integer * `width` Integer @@ -790,34 +788,34 @@ Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. 그리고 ### `win.setThumbarButtons(buttons)` _Windows 7+_ -`buttons` - `button` 객체의 배열 - -`button` 객체는 다음과 같은 속성을 가지고 있습니다: - -* `icon` [NativeImage](native-image.md) - 미리보기 툴바에 보여질 아이콘. -* `tooltip` String (optional) - 버튼의 툴팁 텍스트. -* `flags` Array (optional) - 버튼의 특정 동작 및 상태 제어. 기본적으로 `enabled`이 - 사용됩니다. 이 속성은 다음 문자열들을 포함할 수 있습니다: - * `enabled` - 사용자가 사용할 수 있도록 버튼이 활성화 됩니다. - * `disabled` - 버튼이 비활성화 됩니다. 버튼은 표시되지만 시각적인 상태는 사용자의 - 동작에 응답하지 않는 비활성화 상태로 표시됩니다. - * `dismissonclick` - 버튼이 클릭되면 작업표시줄 버튼의 미리보기(flyout)가 즉시 - 종료됩니다. - * `nobackground` - 버튼의 테두리를 표시하지 않습니다. 이미지에만 사용할 수 있습니다. - * `hidden` - 버튼을 사용자에게 표시되지 않도록 숨깁니다. - * `noninteractive` - 버튼은 활성화되어 있지만 반응이 제거되며 버튼을 눌러도 - 눌려지지 않은 상태를 유지합니다. 이 값은 버튼을 알림의 용도로 사용하기 위해 - 만들어졌습니다. -* `click` - Function +* `buttons` - Array 윈도우 작업표시줄 버튼 레이아웃의 미리보기 이미지 영역에 미리보기 툴바와 버튼 세트를 -지정합니다. 반환되는 `Boolean` 값은 미리보기 툴바가 성공적으로 추가됬는지를 알려줍니다. +추가합니다. 반환되는 `Boolean` 값은 미리보기 툴바가 성공적으로 추가됬는지를 알려줍니다. 미리보기 이미지 영역의 제한된 크기로 인해 미리보기 툴바에 추가될 수 있는 최대 버튼의 개수는 7개이며 이 이상 추가될 수 없습니다. 플랫폼의 제약으로 인해 미리보기 툴바는 한 번 설정되면 삭제할 수 없습니다. 하지만 이 API에 빈 배열을 전달하여 버튼들을 제거할 수 있습니다. +`buttons`는 `Button` 객체의 배열입니다: + +* `Button` 객체 + * `icon` [NativeImage](native-image.md) - 미리보기 툴바에 보여질 아이콘. + * `tooltip` String (optional) - 버튼의 툴팁 텍스트. + * `flags` Array (optional) - 버튼의 특정 동작 및 상태 제어. 기본적으로 `enabled`이 + 사용됩니다. 이 속성은 다음 문자열들을 포함할 수 있습니다: + * `enabled` - 사용자가 사용할 수 있도록 버튼이 활성화 됩니다. + * `disabled` - 버튼이 비활성화 됩니다. 버튼은 표시되지만 시각적인 상태는 사용자의 + 동작에 응답하지 않는 비활성화 상태로 표시됩니다. + * `dismissonclick` - 버튼이 클릭되면 작업표시줄 버튼의 미리보기(flyout)가 즉시 + 종료됩니다. + * `nobackground` - 버튼의 테두리를 표시하지 않습니다. 이미지에만 사용할 수 있습니다. + * `hidden` - 버튼을 사용자에게 표시되지 않도록 숨깁니다. + * `noninteractive` - 버튼은 활성화되어 있지만 반응이 제거되며 버튼을 눌러도 + 눌려지지 않은 상태를 유지합니다. 이 값은 버튼을 알림의 용도로 사용하기 위해 + 만들어졌습니다. + ### `win.showDefinitionForSelection()` _OS X_ 페이지의 선택된 단어에 대한 사전 검색 결과 팝업을 표시합니다. diff --git a/docs-translations/ko-KR/api/crash-reporter.md b/docs-translations/ko-KR/api/crash-reporter.md index 0b7daba14dd..81713760a85 100644 --- a/docs-translations/ko-KR/api/crash-reporter.md +++ b/docs-translations/ko-KR/api/crash-reporter.md @@ -22,19 +22,15 @@ crashReporter.start({ ### `crashReporter.start(options)` -* `options` Object, properties: - -* `productName` String, 기본값: Electron -* `companyName` String (**필수항목**) -* `submitURL` String, (**필수항목**) - * 크래시 리포트는 POST 방식으로 이 URL로 전송됩니다. -* `autoSubmit` Boolean, 기본값: true - * true로 지정할 경우 유저의 승인 없이 자동으로 오류를 보고합니다. -* `ignoreSystemCrashHandler` Boolean, 기본값: false -* `extra` Object - * 크래시 리포트 시 같이 보낼 추가 정보를 지정하는 객체입니다. - * 문자열로 된 속성만 정상적으로 보내집니다. - * 중첩 객체는 지원되지 않습니다. (Nested objects are not supported) +* `options` Object + * `companyName` String + * `submitURL` String - 크래시 리포트는 POST 방식으로 이 URL로 전송됩니다. + * `productName` String (optional) - 기본값은 `Electron` 입니다. + * `autoSubmit` Boolean - 유저의 승인 없이 자동으로 오류를 보고합니다. 기본값은 + `true` 입니다. + * `ignoreSystemCrashHandler` Boolean - 기본값은 `false` 입니다. + * `extra` Object - 크래시 리포트 시 같이 보낼 추가 정보를 지정하는 객체입니다. + 문자열로 된 속성만 정상적으로 보내집니다. 중첩된 객체는 지원되지 않습니다. 다른 crashReporter API를 사용하기 전에 이 메서드를 먼저 호출해야 합니다. diff --git a/docs-translations/ko-KR/api/ipc-main.md b/docs-translations/ko-KR/api/ipc-main.md index 3ae519d294b..30b10247f9d 100644 --- a/docs-translations/ko-KR/api/ipc-main.md +++ b/docs-translations/ko-KR/api/ipc-main.md @@ -8,8 +8,7 @@ ## 메시지 전송 물론 메시지를 받는 것 말고도 메인 프로세스에서 랜더러 프로세스로 보내는 것도 가능합니다. -자세한 내용은 [webContents.send](web-contents.md#webcontentssendchannel-arg1-arg2-)를 -참고하세요. +자세한 내용은 [webContents.send][web-contents-send]를 참고하세요. * 메시지를 전송할 때 이벤트 이름은 `channel`이 됩니다. * 메시지에 동기로 응답할 땐 반드시 `event.returnValue`를 설정해야 합니다. @@ -46,34 +45,40 @@ ipcRenderer.send('asynchronous-message', 'ping'); `ipcMain`은 다음과 같은 이벤트 리스닝 메서드를 가지고 있습니다: -### `ipcMain.on(channel, callback)` +### `ipcMain.on(channel, listener)` -* `channel` String - 이벤트 이름 -* `callback` Function +* `channel` String +* `listener` Function -이벤트가 발생하면 `event` 객체와 임의 메시지와 함께 `callback`이 호출됩니다. +`channel`에 대해 이벤트를 리스닝합니다. 새로운 메시지가 도착하면 `listener`가 +`listener(event, args...)` 형식으로 호출됩니다. -### `ipcMain.removeListener(channel, callback)` +### `ipcMain.once(channel, listener)` -* `channel` String - 이벤트의 이름 -* `callback` Function - `ipcMain.on(channel, callback)`에서 사용한 함수의 레퍼런스 +* `channel` String +* `listener` Function + +이벤트에 대해 한 번만 작동하는 `listener` 함수를 등록합니다. 이 `listener`는 등록된 +후 `channel`에 보내지는 메시지에 한해 호출됩니다. 호출된 이후엔 리스너가 삭제됩니다. + +### `ipcMain.removeListener(channel, listener)` + +* `channel` String +* `listener` Function 메시지 수신을 완료한 후, 더 이상의 콜백이 필요하지 않을 때 또는 몇 가지 이유로 채널의 메시지 전송을 멈출수 없을 때, 이 함수를 통해 지정한 채널에 대한 콜백을 삭제할 수 있습니다. +지정한 `channel`에 대한 리스너를 저장하는 배열에서 지정한 `listener`를 삭제합니다. + ### `ipcMain.removeAllListeners(channel)` -* `channel` String - 이벤트의 이름 +* `channel` String (optional) -이 ipc 채널에 등록된 *모든* 핸들러들을 삭제합니다. +이 ipc 채널에 등록된 모든 핸들러들을 삭제하거나 지정한 `channel`을 삭제합니다. -### `ipcMain.once(channel, callback)` - -`ipcMain.on()` 대신 이 함수를 사용할 경우 핸들러가 단 한 번만 호출됩니다. -`callback`이 한 번 호출된 이후 활성화되지 않습니다. - -## IPC Event +## Event 객체 `callback`에서 전달된 `event` 객체는 다음과 같은 메서드와 속성을 가지고 있습니다: @@ -85,5 +90,6 @@ ipcRenderer.send('asynchronous-message', 'ping'); 메시지를 보낸 `webContents` 객체를 반환합니다. `event.sender.send` 메서드를 통해 비동기로 메시지를 전달할 수 있습니다. 자세한 내용은 -[webContents.send](web-contents.md#webcontentssendchannel-arg1-arg2-)를 -참고하세요. +[webContents.send][web-contents-send]를 참고하세요. + +[web-contents-send]: web-contents.md#webcontentssendchannel-arg1-arg2- diff --git a/docs-translations/ko-KR/api/ipc-renderer.md b/docs-translations/ko-KR/api/ipc-renderer.md index 12fac95bbee..0d43b157d16 100644 --- a/docs-translations/ko-KR/api/ipc-renderer.md +++ b/docs-translations/ko-KR/api/ipc-renderer.md @@ -10,32 +10,38 @@ `ipcRenderer`는 다음과 같은 이벤트 리스닝 메서드를 가지고 있습니다: -### `ipcRenderer.on(channel, callback)` +### `ipcMain.on(channel, listener)` -* `channel` String - 이벤트 이름 -* `callback` Function +* `channel` String +* `listener` Function -이벤트가 일어나면 `event` 객체와 임의의 인자와 함께 `callback` 함수가 호출됩니다. +`channel`에 대해 이벤트를 리스닝합니다. 새로운 메시지가 도착하면 `listener`가 +`listener(event, args...)` 형식으로 호출됩니다. -### `ipcRenderer.removeListener(channel, callback)` +### `ipcMain.once(channel, listener)` -* `channel` String - 이벤트의 이름 -* `callback` Function - `ipcMain.on(channel, callback)`에서 사용한 함수의 레퍼런스 +* `channel` String +* `listener` Function + +이벤트에 대해 한 번만 작동하는 `listener` 함수를 등록합니다. 이 `listener`는 등록된 +후 `channel`에 보내지는 메시지에 한해 호출됩니다. 호출된 이후엔 리스너가 삭제됩니다. + +### `ipcMain.removeListener(channel, listener)` + +* `channel` String +* `listener` Function 메시지 수신을 완료한 후, 더 이상의 콜백이 필요하지 않을 때 또는 몇 가지 이유로 채널의 메시지 전송을 멈출수 없을 때, 이 함수를 통해 지정한 채널에 대한 콜백을 삭제할 수 있습니다. -### `ipcRenderer.removeAllListeners(channel)` +지정한 `channel`에 대한 리스너를 저장하는 배열에서 지정한 `listener`를 삭제합니다. -* `channel` String - 이벤트의 이름 +### `ipcMain.removeAllListeners(channel)` -이 ipc 채널에 등록된 *모든* 핸들러들을 삭제합니다. +* `channel` String (optional) -### `ipcRenderer.once(channel, callback)` - -`ipcRenderer.on()` 대신 이 함수를 사용할 경우 핸들러가 단 한 번만 호출됩니다. -`callback`이 한 번 호출된 이후 활성화되지 않습니다. +이 ipc 채널에 등록된 모든 핸들러들을 삭제하거나 지정한 `channel`을 삭제합니다. ## 메시지 보내기 @@ -43,23 +49,26 @@ ### `ipcRenderer.send(channel[, arg1][, arg2][, ...])` -* `channel` String - 이벤트 이름 +* `channel` String * `arg` (optional) `channel`을 통해 메인 프로세스에 비동기 메시지를 보냅니다. 그리고 필요에 따라 임의의 -인자를 사용할 수도 있습니다. 메인 프로세스는 `ipcMain` 모듈의 `channel` 이벤트를 통해 +인수를 사용할 수도 있습니다. 인수들은 내부적으로 JSON 포맷으로 직렬화 되며, 이후 함수와 +프로토타입 체인은 포함되지 않게 됩니다. + +메인 프로세스는 `ipcMain` 모듈의 `channel` 이벤트를 통해 이벤트를 리스닝 할 수 있습니다. ### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])` -* `channel` String - 이벤트 이름 +* `channel` String * `arg` (optional) `channel`을 통해 메인 프로세스에 동기 메시지를 보냅니다. 그리고 필요에 따라 임의의 -인자를 사용할 수도 있습니다. 메인 프로세스는 `ipc`를 통해 `channel` 이벤트를 리스닝 -할 수 있습니다. +인자를 사용할 수도 있습니다. 인수들은 내부적으로 JSON 포맷으로 직렬화 되며, 이후 함수와 +프로토타입 체인은 포함되지 않게 됩니다. -메인 프로세스에선 `ipcMain` 모듈의 `channel` 이벤트를 통해 받은 +메인 프로세스는 `ipcMain` 모듈을 통해 `channel` 이벤트를 리스닝 할 수 있고, `event.returnValue`로 회신 할 수 있습니다. __참고:__ 동기 메서드는 모든 랜더러 프로세스의 작업을 일시 중단시킵니다. 사용 목적이 @@ -67,7 +76,7 @@ __참고:__ 동기 메서드는 모든 랜더러 프로세스의 작업을 일 ### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])` -* `channel` String - 이벤트 이름 +* `channel` String * `arg` (optional) `ipcRenderer.send`와 비슷하지만 이벤트를 메인 프로세스 대신 호스트 페이지내의 diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index 3f9a7daaaa7..6e41f31155c 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -255,8 +255,8 @@ Returns: * `result` Object * `requestId` Integer * `finalUpdate` Boolean - 더 많은 응답이 따르는 경우를 표시합니다. - * `matches` Integer (Optional) - 일치하는 개수. - * `selectionArea` Object (Optional) - 첫 일치 부위의 좌표. + * `matches` Integer (optional) - 일치하는 개수. + * `selectionArea` Object (optional) - 첫 일치 부위의 좌표. [`webContents.findInPage`](web-contents.md#webcontentsfindinpage) 요청의 결과를 사용할 수 있을 때 발생하는 이벤트입니다. @@ -307,7 +307,7 @@ Returns: ### `webContents.loadURL(url[, options])` * `url` URL -* `options` Object (optional), 속성들: +* `options` Object (optional) * `httpReferrer` String - HTTP 레퍼러 url. * `userAgent` String - 요청을 시작한 유저 에이전트. * `extraHeaders` String - "\n"로 구분된 Extra 헤더들. @@ -493,7 +493,7 @@ CSS 코드를 현재 웹 페이지에 삽입합니다. ### `webContents.findInPage(text[, options])` * `text` String - 찾을 컨텐츠, 반드시 공백이 아니여야 합니다. -* `options` Object (Optional) +* `options` Object (optional) * `forward` Boolean - 앞에서부터 검색할지 뒤에서부터 검색할지 여부입니다. 기본값은 `true`입니다. * `findNext` Boolean - 작업을 계속 처리할지 첫 요청만 처리할지 여부입니다. 기본값은 @@ -546,11 +546,10 @@ ServiceWorker가 존재하면 모두 등록을 해제하고 JS Promise가 만족 ### `webContents.print([options])` -`options` Object (optional), properties: - -* `silent` Boolean - 사용자에게 프린트 설정을 묻지 않습니다. 기본값을 `false`입니다. -* `printBackground` Boolean - 웹 페이지의 배경 색과 이미지를 출력합니다. 기본값은 - `false`입니다. +`options` Object (optional) + * `silent` Boolean - 사용자에게 프린트 설정을 묻지 않습니다. 기본값을 `false`입니다. + * `printBackground` Boolean - 웹 페이지의 배경 색과 이미지를 출력합니다. 기본값은 + `false`입니다. 윈도우의 웹 페이지를 프린트합니다. `silent`가 `false`로 지정되어있을 땐, Electron이 시스템의 기본 프린터와 기본 프린터 설정을 가져옵니다. @@ -565,32 +564,23 @@ print기능을 사용하지 않는 경우 전체 바이너리 크기를 줄이 ### `webContents.printToPDF(options, callback)` -`options` Object, properties: - -* `marginsType` Integer - 사용할 마진의 종류를 지정합니다. - * 0 - default - * 1 - none - * 2 - minimum -* `pageSize` String - 생성되는 PDF의 페이지 크기를 지정합니다. - * `A5` - * `A4` - * `A3` - * `Legal` - * `Letter` - * `Tabloid` -* `printBackground` Boolean - CSS 배경을 프린트할지 여부를 정합니다. -* `printSelectionOnly` Boolean - 선택된 영역만 프린트할지 여부를 정합니다. -* `landscape` Boolean - landscape을 위해선 `true`를, portrait를 위해선 `false`를 - 사용합니다. - -`callback` Function - `function(error, data) {}` - -* `error` Error -* `data` Buffer - PDF 파일 내용. +* `options` Object + * `marginsType` Integer - 사용할 마진의 종류를 지정합니다. 0 부터 2 사이 값을 사용할 + 수 있고 각각 기본 마진, 마진 없음, 최소 마진입니다. + * `pageSize` String - 생성되는 PDF의 페이지 크기를 지정합니다. 값은 `A3`, `A4`, + `A5`, `Legal`, `Letter` 와 `Tabloid`가 사용될 수 있습니다. + * `printBackground` Boolean - CSS 배경을 프린트할지 여부를 정합니다. + * `printSelectionOnly` Boolean - 선택된 영역만 프린트할지 여부를 정합니다. + * `landscape` Boolean - landscape을 위해선 `true`를, portrait를 위해선 `false`를 + 사용합니다. +* `callback` Function - `function(error, data) {}` Chromium의 미리보기 프린팅 커스텀 설정을 이용하여 윈도우의 웹 페이지를 PDF로 프린트합니다. +`callback`은 작업이 완료되면 `callback(error, data)` 형식으로 호출됩니다. `data`는 +생성된 PDF 데이터를 담고있는 `Buffer`입니다. + 기본으로 비어있는 `options`은 다음과 같이 여겨지게 됩니다: ```javascript @@ -643,7 +633,7 @@ mainWindow.webContents.on('devtools-opened', function() { ### `webContents.openDevTools([options])` -* `options` Object (optional). Properties: +* `options` Object (optional) * `detach` Boolean - 새 창에서 개발자 도구를 엽니다. 개발자 도구를 엽니다. @@ -681,8 +671,11 @@ mainWindow.webContents.on('devtools-opened', function() { * `arg` (optional) `channel`을 통하여 렌더러 프로세스에 비동기 메시지를 보냅니다. 임의의 인수를 보낼수도 -있습니다. 렌더러 프로세스는 `ipcRenderer` 모듈을 통하여 `channel`를 리슨하여 메시지를 -처리할 수 있습니다. +있습니다. 인수들은 내부적으로 JSON 포맷으로 직렬화 되며, 이후 함수와 프로토타입 체인은 +포함되지 않게 됩니다. + +렌더러 프로세스는 `ipcRenderer` 모듈을 통하여 `channel`를 리스닝하여 메시지를 처리할 +수 있습니다. 메인 프로세스에서 렌더러 프로세스로 메시지를 보내는 예시 입니다: diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index bd07c883e06..30da9f253b4 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -178,7 +178,7 @@ webview.addEventListener("dom-ready", function() { ### `.loadURL(url[, options])` * `url` URL -* `options` Object (optional), 속성들: +* `options` Object (optional) * `httpReferrer` String - HTTP 레퍼러 url. * `userAgent` String - 요청을 시작한 유저 에이전트. * `extraHeaders` String - "\n"로 구분된 Extra 헤더들. @@ -370,7 +370,7 @@ Service worker에 대한 개발자 도구를 엽니다. ### `webContents.findInPage(text[, options])` * `text` String - 찾을 컨텐츠, 반드시 공백이 아니여야 합니다. -* `options` Object (Optional) +* `options` Object (optional) * `forward` Boolean - 앞에서부터 검색할지 뒤에서부터 검색할지 여부입니다. 기본값은 `true`입니다. * `findNext` Boolean - 작업을 계속 처리할지 첫 요청만 처리할지 여부입니다. 기본값은 @@ -557,8 +557,8 @@ Returns: * `result` Object * `requestId` Integer * `finalUpdate` Boolean - 더 많은 응답이 따르는 경우를 표시합니다. - * `matches` Integer (Optional) - 일치하는 개수. - * `selectionArea` Object (Optional) - 첫 일치 부위의 좌표. + * `matches` Integer (optional) - 일치하는 개수. + * `selectionArea` Object (optional) - 첫 일치 부위의 좌표. [`webContents.findInPage`](web-contents.md#webcontentsfindinpage) 요청의 결과를 사용할 수 있을 때 발생하는 이벤트입니다. diff --git a/docs-translations/ko-KR/faq/electron-faq.md b/docs-translations/ko-KR/faq/electron-faq.md index 0978dc00539..ea9953fcd4c 100644 --- a/docs-translations/ko-KR/faq/electron-faq.md +++ b/docs-translations/ko-KR/faq/electron-faq.md @@ -18,6 +18,34 @@ Node.js의 새로운 기능은 보통 V8 업그레이드에서 가져옵니다. 브라우저에 탑재된 V8을 사용하고 있습니다. 눈부신 새로운 Node.js 버전의 자바스크립트 기능은 보통 이미 Electron에 있습니다. +## 어떻게 웹 페이지 간에 데이터를 공유할 수 있나요? + +두 웹페이지 간에 (랜더러 프로세스) 데이터를 공유하려면 간단히 이미 모든 브라우저에서 +사용할 수 있는 HTML5 API들을 사용하면 됩니다. 가장 좋은 후보는 +[Storage API][storage], [`localStorage`][local-storage], +[`sessionStorage`][session-storage], 그리고 [IndexedDB][indexed-db]가 있습니다. + +또는 Electron에서만 사용할 수 있는 IPC 시스템을 사용하여 메인 프로세스의 global +변수에 데이터를 저장한 후 다음과 같이 랜더러 프로세스에서 `remote` 모듈을 사용하여 +접근할 수 있습니다: + +```javascript +// 메인 프로세스에서 +global.sharedObject = { + someProperty: 'default value' +}; +``` + +```javascript +// 첫 번째 페이지에서 +require('remote').getGlobal('sharedObject').someProperty = 'new value'; +``` + +```javascript +// 두 번째 페이지에서 +console.log(require('remote').getGlobal('sharedObject').someProperty); +``` + ## 제작한 어플리케이션의 윈도우/트레이가 몇 분 후에나 나타납니다. 이러한 문제가 발생하는 이유는 보통 윈도우/트레이를 담은 변수에 가비지 컬렉션이 작동해서 @@ -119,3 +147,7 @@ npm uninstall -g electron [memory-management]: https://developer.mozilla.org/ko/docs/Web/JavaScript/Memory_Management [variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx [electron-module]: https://www.npmjs.com/package/electron +[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage +[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage +[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage +[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API diff --git a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md index cd6ff545e14..38830b91e82 100644 --- a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md +++ b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md @@ -263,6 +263,33 @@ var window = new BrowserWindow({...}); window.setProgressBar(0.5); ``` +## 작업 표시줄의 아이콘 오버레이 (Windows) + +Windows에선 작업 표시줄 버튼에 어플리케이션의 상태를 표시하는 작은 오버레이를 사용할 +수 있습니다. MSDN에서 인용하자면 (영문): + +> Icon overlays serve as a contextual notification of status, and are intended +> to negate the need for a separate notification area status icon to communicate +> that information to the user. For instance, the new mail status in Microsoft +> Outlook, currently shown in the notification area, can now be indicated +> through an overlay on the taskbar button. Again, you must decide during your +> development cycle which method is best for your application. Overlay icons are +> intended to supply important, long-standing status or notifications such as +> network status, messenger status, or new mail. The user should not be +> presented with constantly changing overlays or animations. + +__작업 표시줄 버튼 위의 오버레이:__ + +![작업 표시줄 버튼 위의 오버레이](https://i-msdn.sec.s-msft.com/dynimg/IC420441.png) + +윈도우에 오버레이 아이콘을 설정하려면 [BrowserWindow.setOverlayIcon][setoverlayicon] +API를 사용할 수 있습니다: + +```javascript +var window = new BrowserWindow({...}); +window.setOverlayIcon('path/to/overlay.png', 'Description for overlay'); +``` + ## 대표 파일 제시 (OS X) OS X는 창에서 대표 파일을 설정할 수 있습니다. 타이틀바에서 파일 아이콘이 있고, 사용자가 @@ -287,6 +314,7 @@ window.setDocumentEdited(true); [clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows [setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows [setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress +[setoverlayicon]: ../api/browser-window.md#winsetoverlayiconoverlay-description-windows-7 [setrepresentedfilename]: ../api/browser-window.md#winsetrepresentedfilenamefilename-os-x [setdocumentedited]: ../api/browser-window.md#winsetdocumenteditededited-os-x [app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 708a48080ff..82d359e0de5 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -12,7 +12,7 @@ Electron은 웹 페이지의 GUI를 사용합니다. 쉽게 말해 Electron은 ### 메인 프로세스 -Electron은 실행될 때 __메인 프로세스__로 불리는 `package.json`의 `main` 스크립트를 +Electron은 실행될 때 __메인 프로세스__ 로 불리는 `package.json`의 `main` 스크립트를 호출합니다. 이 스크립트는 메인 프로세스에서 작동합니다. GUI 컴포넌트를 조작하거나 웹 페이지 창을 생성할 수 있습니다. @@ -43,6 +43,7 @@ API를 사용하여 low-level 수준으로 운영체제와 상호작용할 수 Electron에는 메인 프로세스와 랜더러 프로세스 사이에 통신을 할 수 있도록 [ipc](../api/ipc-renderer.md) 모듈을 제공하고 있습니다. 또는 [remote](../api/remote.md) 모듈을 사용하여 RPC 스타일로 통신할 수도 있습니다. +또한 FAQ에서 [다양한 객체를 공유하는 방법](share-data)도 소개하고 있습니다. ## 첫번째 Electron 앱 만들기 @@ -211,3 +212,5 @@ $ cd electron-quick-start # 어플리케이션의 종속성 모듈을 설치한 후 실행합니다 $ npm install && npm start ``` + +[share-data]: ../faq/electron-faq.md#어떻게-웹-페이지-간에-데이터를-공유할-수-있나요 From ee0cac7d5475549802fadcf0ab67a9a24354eef4 Mon Sep 17 00:00:00 2001 From: Kevin Jose Martin Date: Tue, 16 Feb 2016 21:23:13 -0500 Subject: [PATCH 081/173] Remove command line switches, add v8 flags --- atom/browser/lib/init.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/atom/browser/lib/init.js b/atom/browser/lib/init.js index b687aa6eeda..4769faee0a3 100644 --- a/atom/browser/lib/init.js +++ b/atom/browser/lib/init.js @@ -2,6 +2,7 @@ const fs = require('fs'); const path = require('path'); const util = require('util'); const Module = require('module'); +const v8 = require('v8'); var slice = [].slice; @@ -129,22 +130,14 @@ if (packageJson.desktopName != null) { app.setDesktopName((app.getName()) + ".desktop"); } +// Set v8 flags +if (packageJson.v8Flags != null) { + v8.setFlagsFromString(packageJson.v8Flags); +} + // Chrome 42 disables NPAPI plugins by default, reenable them here app.commandLine.appendSwitch('enable-npapi'); -// Add other command line switches -if (packageJson.commandLineSwitches) { - for (let i = 0; i < packageJson.commandLineSwitches.length; i++) { - const option = packageJson.commandLineSwitches[i]; - - if (typeof option === 'string') { - app.commandLine.appendSwitch(option); - } else { - app.commandLine.appendSwitch(option[0], option[1]); - } - } -} - // Set the user path according to application's name. app.setPath('userData', path.join(app.getPath('appData'), app.getName())); From baf44c7a4144c3c78a9bcf01708f5a580fbcd889 Mon Sep 17 00:00:00 2001 From: deenjun Date: Wed, 17 Feb 2016 10:42:59 +0800 Subject: [PATCH 082/173] tanslate file-object.md --- docs-translations/zh-CN/api/file-object.md | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 docs-translations/zh-CN/api/file-object.md diff --git a/docs-translations/zh-CN/api/file-object.md b/docs-translations/zh-CN/api/file-object.md new file mode 100644 index 00000000000..343fc4dc53a --- /dev/null +++ b/docs-translations/zh-CN/api/file-object.md @@ -0,0 +1,33 @@ +# `文件`对象 + +为了让用户能够通过HTML5的file API直接操作本地文件,DOM的File接口提供了对本地文件的抽象。Electron在File接口中增加了一个path属性,它是文件在系统中的真实路径。 + +The DOM’s File interface provides abstraction around native files in order to let users work on native files directly with the HTML5 file API. Electron has added a path attribute to the File interface which exposes the file’s real path on filesystem. + +--- + +获取拖动到APP中文件的真实路径的例子: + +Example on getting a real path from a dragged-onto-the-app file: + +``` +
+ Drag your file here +
+ + +``` From 01ede11cb885cc0f77fd23258f37aaaf92c30652 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 17 Feb 2016 10:54:44 +0800 Subject: [PATCH 083/173] Skip eslint on our Windows build machine for now --- script/eslint.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/script/eslint.py b/script/eslint.py index 8fa2c3a7e3a..7b912e0e1d6 100755 --- a/script/eslint.py +++ b/script/eslint.py @@ -4,6 +4,7 @@ import glob import os import sys +from lib.config import PLATFORM from lib.util import execute @@ -13,6 +14,10 @@ SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) def main(): os.chdir(SOURCE_ROOT) + # Skip eslint on our Windows build machine for now. + if PLATFORM == 'win32' and os.getenv('JANKY_SHA1'): + return + eslint = os.path.join(SOURCE_ROOT, 'node_modules', '.bin', 'eslint') if sys.platform in ['win32', 'cygwin']: eslint += '.cmd' From 28635e5f2c20f2d8642965460e9e5eb378cd32df Mon Sep 17 00:00:00 2001 From: deenjun Date: Wed, 17 Feb 2016 14:54:57 +0800 Subject: [PATCH 084/173] remove original English text --- docs-translations/zh-CN/api/file-object.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs-translations/zh-CN/api/file-object.md b/docs-translations/zh-CN/api/file-object.md index 343fc4dc53a..ef320b36994 100644 --- a/docs-translations/zh-CN/api/file-object.md +++ b/docs-translations/zh-CN/api/file-object.md @@ -1,15 +1,11 @@ -# `文件`对象 +# `File`对象 为了让用户能够通过HTML5的file API直接操作本地文件,DOM的File接口提供了对本地文件的抽象。Electron在File接口中增加了一个path属性,它是文件在系统中的真实路径。 -The DOM’s File interface provides abstraction around native files in order to let users work on native files directly with the HTML5 file API. Electron has added a path attribute to the File interface which exposes the file’s real path on filesystem. - --- 获取拖动到APP中文件的真实路径的例子: -Example on getting a real path from a dragged-onto-the-app file: - ```
Drag your file here From 7fece7e9b3ecfa57b5a37e07c2f4eb65169589dd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 17 Feb 2016 22:21:14 +0800 Subject: [PATCH 085/173] Link with ffmpeg --- atom.gyp | 3 +++ vendor/brightray | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/atom.gyp b/atom.gyp index dbaf6db5629..c8c714858b4 100644 --- a/atom.gyp +++ b/atom.gyp @@ -144,6 +144,7 @@ }, { 'copied_libraries': [ '<(libchromiumcontent_dir)/pdf.dll', + '<(libchromiumcontent_dir)/ffmpeg.dll', ], }], ], @@ -193,6 +194,7 @@ }, { 'copied_libraries': [ '<(PRODUCT_DIR)/lib/libnode.so', + '<(libchromiumcontent_dir)/libffmpeg.so', ], }], ], @@ -461,6 +463,7 @@ }, { 'copied_libraries': [ '<(PRODUCT_DIR)/libnode.dylib', + '<(libchromiumcontent_dir)/libffmpeg.dylib', ], }], ], diff --git a/vendor/brightray b/vendor/brightray index 2a5cd7178b6..d06de26dff8 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 2a5cd7178b641de91ca6eb0bca826fea588f923a +Subproject commit d06de26dff8b641d9aee4c78ee830b416710f554 From 3d3fc18a3ab8aa409296b41ed00c8474911ad254 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 17 Feb 2016 22:21:59 +0800 Subject: [PATCH 086/173] Update libchromiumcontent to use shared ffmpeg --- script/lib/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/lib/config.py b/script/lib/config.py index 279fa7340a9..004e87dd070 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = 'ad63d8ba890bcaad2f1b7e6de148b7992f4d3af7' +LIBCHROMIUMCONTENT_COMMIT = '1be1a55abba527d6fb0fc2a589cbaef2f5a6a79e' PLATFORM = { 'cygwin': 'win32', From d8679b38993ae66c9e6d60968da19124005d09b6 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Tue, 2 Feb 2016 23:01:00 -0800 Subject: [PATCH 087/173] Allow openExternal to open URLs in the background #3224 --- .../atom_resource_dispatcher_host_delegate.cc | 2 +- atom/common/api/atom_api_shell.cc | 12 +++++++++++- atom/common/platform_util.h | 2 +- atom/common/platform_util_linux.cc | 2 +- atom/common/platform_util_mac.mm | 12 ++++++++++-- atom/common/platform_util_win.cc | 2 +- docs/api/shell.md | 10 ++++++++-- 7 files changed, 33 insertions(+), 9 deletions(-) diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index aaba1f31045..33e90671aba 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -26,7 +26,7 @@ bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( bool has_user_gesture) { GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(base::IgnoreResult(platform_util::OpenExternal), escaped_url)); + base::Bind(base::IgnoreResult(platform_util::OpenExternal), escaped_url, false)); return true; } diff --git a/atom/common/api/atom_api_shell.cc b/atom/common/api/atom_api_shell.cc index a4599ee0c35..d479911fbe3 100644 --- a/atom/common/api/atom_api_shell.cc +++ b/atom/common/api/atom_api_shell.cc @@ -12,12 +12,22 @@ namespace { +bool OpenExternal(const GURL& url, mate::Arguments* args) { + bool without_activation = false; + if (args->Length() == 2) { + mate::Dictionary options; + args->GetNext(&options); + options.Get("withoutActivation", &without_activation); + } + return platform_util::OpenExternal(url, without_activation); +} + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); dict.SetMethod("showItemInFolder", &platform_util::ShowItemInFolder); dict.SetMethod("openItem", &platform_util::OpenItem); - dict.SetMethod("openExternal", &platform_util::OpenExternal); + dict.SetMethod("openExternal", &OpenExternal); dict.SetMethod("moveItemToTrash", &platform_util::MoveItemToTrash); dict.SetMethod("beep", &platform_util::Beep); } diff --git a/atom/common/platform_util.h b/atom/common/platform_util.h index 312942c4f5d..3550c243bb6 100644 --- a/atom/common/platform_util.h +++ b/atom/common/platform_util.h @@ -23,7 +23,7 @@ void OpenItem(const base::FilePath& full_path); // Open the given external protocol URL in the desktop's default manner. // (For example, mailto: URLs in the default mail user agent.) -bool OpenExternal(const GURL& url); +bool OpenExternal(const GURL& url, const bool without_activation); // Move a file to trash. bool MoveItemToTrash(const base::FilePath& full_path); diff --git a/atom/common/platform_util_linux.cc b/atom/common/platform_util_linux.cc index aa7439968da..fd4dcba6973 100644 --- a/atom/common/platform_util_linux.cc +++ b/atom/common/platform_util_linux.cc @@ -64,7 +64,7 @@ void OpenItem(const base::FilePath& full_path) { XDGOpen(full_path.value()); } -bool OpenExternal(const GURL& url) { +bool OpenExternal(const GURL& url, const bool without_activation) { if (url.SchemeIs("mailto")) return XDGEmail(url.spec()); else diff --git a/atom/common/platform_util_mac.mm b/atom/common/platform_util_mac.mm index 7184593ae19..e84b3fbec30 100644 --- a/atom/common/platform_util_mac.mm +++ b/atom/common/platform_util_mac.mm @@ -119,7 +119,7 @@ void OpenItem(const base::FilePath& full_path) { } } -bool OpenExternal(const GURL& url) { +bool OpenExternal(const GURL& url, const bool without_activation) { DCHECK([NSThread isMainThread]); NSURL* ns_url = net::NSURLWithGURL(url); if (!ns_url) { @@ -136,7 +136,15 @@ bool OpenExternal(const GURL& url) { } CFRelease(openingApp); // NOT A BUG; LSGetApplicationForURL retains for us - return [[NSWorkspace sharedWorkspace] openURL:ns_url]; + NSUInteger launchOptions = NSWorkspaceLaunchDefault; + if (without_activation) + launchOptions = launchOptions | NSWorkspaceLaunchWithoutActivation; + + return [[NSWorkspace sharedWorkspace] openURLs: @[ns_url] + withAppBundleIdentifier: nil + options: launchOptions + additionalEventParamDescriptor: NULL + launchIdentifiers: NULL]; } bool MoveItemToTrash(const base::FilePath& full_path) { diff --git a/atom/common/platform_util_win.cc b/atom/common/platform_util_win.cc index 4de5224668b..76b71cb7f70 100644 --- a/atom/common/platform_util_win.cc +++ b/atom/common/platform_util_win.cc @@ -301,7 +301,7 @@ void OpenItem(const base::FilePath& full_path) { ui::win::OpenFileViaShell(full_path); } -bool OpenExternal(const GURL& url) { +bool OpenExternal(const GURL& url, const bool without_activation) { // Quote the input scheme to be sure that the command does not have // parameters unexpected by the external program. This url should already // have been escaped. diff --git a/docs/api/shell.md b/docs/api/shell.md index e6678a95536..a7f03a52f9c 100644 --- a/docs/api/shell.md +++ b/docs/api/shell.md @@ -26,12 +26,18 @@ Show the given file in a file manager. If possible, select the file. Open the given file in the desktop's default manner. -### `shell.openExternal(url)` +### `shell.openExternal(url[, options])` * `url` String Open the given external protocol URL in the desktop's default manner. (For -example, mailto: URLs in the user's default mail agent.) +example, mailto: URLs in the user's default mail agent.) Returns true if an +application was available to open the URL, false otherwise. + +On Mac OS X, you can pass additional options to openExternal: + +- withoutActivation: Pass true to open the URL without bringing the + application into the foreground. ### `shell.moveItemToTrash(fullPath)` From 52db43eee55975ab1cbd4926beedbd4b037c2a38 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Wed, 3 Feb 2016 11:35:01 -0800 Subject: [PATCH 088/173] Fix linter error --- atom/browser/atom_resource_dispatcher_host_delegate.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index 33e90671aba..0ed59b71be9 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -26,7 +26,8 @@ bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( bool has_user_gesture) { GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(base::IgnoreResult(platform_util::OpenExternal), escaped_url, false)); + base::Bind( + base::IgnoreResult(platform_util::OpenExternal), escaped_url, false)); return true; } From f5bed87199732cfac34b4dfe5ddcc6072fd5b549 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Feb 2016 15:55:37 -0800 Subject: [PATCH 089/173] without_activation -> activate --- atom/common/api/atom_api_shell.cc | 12 +----------- atom/common/api/lib/shell.js | 18 +++++++++++++++++- atom/common/platform_util.h | 2 +- atom/common/platform_util_linux.cc | 2 +- atom/common/platform_util_mac.mm | 6 +++--- atom/common/platform_util_win.cc | 2 +- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/atom/common/api/atom_api_shell.cc b/atom/common/api/atom_api_shell.cc index d479911fbe3..d0e795e8745 100644 --- a/atom/common/api/atom_api_shell.cc +++ b/atom/common/api/atom_api_shell.cc @@ -12,22 +12,12 @@ namespace { -bool OpenExternal(const GURL& url, mate::Arguments* args) { - bool without_activation = false; - if (args->Length() == 2) { - mate::Dictionary options; - args->GetNext(&options); - options.Get("withoutActivation", &without_activation); - } - return platform_util::OpenExternal(url, without_activation); -} - void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); dict.SetMethod("showItemInFolder", &platform_util::ShowItemInFolder); dict.SetMethod("openItem", &platform_util::OpenItem); - dict.SetMethod("openExternal", &OpenExternal); + dict.SetMethod("_openExternal", &platform_util::OpenExternal); dict.SetMethod("moveItemToTrash", &platform_util::MoveItemToTrash); dict.SetMethod("beep", &platform_util::Beep); } diff --git a/atom/common/api/lib/shell.js b/atom/common/api/lib/shell.js index 08cc4e8eb41..e032a737076 100644 --- a/atom/common/api/lib/shell.js +++ b/atom/common/api/lib/shell.js @@ -1 +1,17 @@ -module.exports = process.atomBinding('shell'); +'use strict'; + +const bindings = process.atomBinding('shell'); + +exports.beep = bindings.beep; +exports.moveItemToTrash = bindings.moveItemToTrash; +exports.openItem = bindings.openItem; +exports.showItemInFolder = bindings.showItemInFolder; + +exports.openExternal = (url, options) => { + var activate = true; + if (options != null && options.activate != null) { + activate = !!options.activate; + } + + bindings._openExternal(url, activate); +} diff --git a/atom/common/platform_util.h b/atom/common/platform_util.h index 3550c243bb6..4565221e9d8 100644 --- a/atom/common/platform_util.h +++ b/atom/common/platform_util.h @@ -23,7 +23,7 @@ void OpenItem(const base::FilePath& full_path); // Open the given external protocol URL in the desktop's default manner. // (For example, mailto: URLs in the default mail user agent.) -bool OpenExternal(const GURL& url, const bool without_activation); +bool OpenExternal(const GURL& url, bool activate); // Move a file to trash. bool MoveItemToTrash(const base::FilePath& full_path); diff --git a/atom/common/platform_util_linux.cc b/atom/common/platform_util_linux.cc index fd4dcba6973..1e437b866cc 100644 --- a/atom/common/platform_util_linux.cc +++ b/atom/common/platform_util_linux.cc @@ -64,7 +64,7 @@ void OpenItem(const base::FilePath& full_path) { XDGOpen(full_path.value()); } -bool OpenExternal(const GURL& url, const bool without_activation) { +bool OpenExternal(const GURL& url, bool activate) { if (url.SchemeIs("mailto")) return XDGEmail(url.spec()); else diff --git a/atom/common/platform_util_mac.mm b/atom/common/platform_util_mac.mm index e84b3fbec30..98bc4e537d8 100644 --- a/atom/common/platform_util_mac.mm +++ b/atom/common/platform_util_mac.mm @@ -119,7 +119,7 @@ void OpenItem(const base::FilePath& full_path) { } } -bool OpenExternal(const GURL& url, const bool without_activation) { +bool OpenExternal(const GURL& url, bool activate) { DCHECK([NSThread isMainThread]); NSURL* ns_url = net::NSURLWithGURL(url); if (!ns_url) { @@ -137,8 +137,8 @@ bool OpenExternal(const GURL& url, const bool without_activation) { CFRelease(openingApp); // NOT A BUG; LSGetApplicationForURL retains for us NSUInteger launchOptions = NSWorkspaceLaunchDefault; - if (without_activation) - launchOptions = launchOptions | NSWorkspaceLaunchWithoutActivation; + if (!activate) + launchOptions |= NSWorkspaceLaunchWithoutActivation; return [[NSWorkspace sharedWorkspace] openURLs: @[ns_url] withAppBundleIdentifier: nil diff --git a/atom/common/platform_util_win.cc b/atom/common/platform_util_win.cc index 76b71cb7f70..12591a94d56 100644 --- a/atom/common/platform_util_win.cc +++ b/atom/common/platform_util_win.cc @@ -301,7 +301,7 @@ void OpenItem(const base::FilePath& full_path) { ui::win::OpenFileViaShell(full_path); } -bool OpenExternal(const GURL& url, const bool without_activation) { +bool OpenExternal(const GURL& url, bool activate) { // Quote the input scheme to be sure that the command does not have // parameters unexpected by the external program. This url should already // have been escaped. From 42041cd40273851d694bff1da6abd67489cb53e9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Feb 2016 15:58:33 -0800 Subject: [PATCH 090/173] Use markdown list for new options param --- docs/api/shell.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/api/shell.md b/docs/api/shell.md index a7f03a52f9c..823dc481bb0 100644 --- a/docs/api/shell.md +++ b/docs/api/shell.md @@ -29,16 +29,14 @@ Open the given file in the desktop's default manner. ### `shell.openExternal(url[, options])` * `url` String +* `options` Object (optional) _OS X_ + * `activate` Boolean - `true` to bring the opened application to the + foreground. The default is `true`. Open the given external protocol URL in the desktop's default manner. (For example, mailto: URLs in the user's default mail agent.) Returns true if an application was available to open the URL, false otherwise. -On Mac OS X, you can pass additional options to openExternal: - -- withoutActivation: Pass true to open the URL without bringing the - application into the foreground. - ### `shell.moveItemToTrash(fullPath)` * `fullPath` String From 5e5313d8b1659f9fbdee5ff3cf6198c696928005 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Feb 2016 16:02:41 -0800 Subject: [PATCH 091/173] Return value from bindings method --- atom/common/api/lib/shell.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/common/api/lib/shell.js b/atom/common/api/lib/shell.js index e032a737076..7caf8518395 100644 --- a/atom/common/api/lib/shell.js +++ b/atom/common/api/lib/shell.js @@ -13,5 +13,5 @@ exports.openExternal = (url, options) => { activate = !!options.activate; } - bindings._openExternal(url, activate); + return bindings._openExternal(url, activate); } From 04517caf36265055505c6dbec085c34aa0e14b33 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Feb 2016 16:08:36 -0800 Subject: [PATCH 092/173] Add missing semicolon --- atom/common/api/lib/shell.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/common/api/lib/shell.js b/atom/common/api/lib/shell.js index 7caf8518395..d62280277c5 100644 --- a/atom/common/api/lib/shell.js +++ b/atom/common/api/lib/shell.js @@ -14,4 +14,4 @@ exports.openExternal = (url, options) => { } return bindings._openExternal(url, activate); -} +}; From 3f42909ecfe46fc786cb7e9eb662bb7f6e255154 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Feb 2016 16:09:30 -0800 Subject: [PATCH 093/173] Call OpenExternal with new true default to activate arg --- atom/browser/atom_resource_dispatcher_host_delegate.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index 0ed59b71be9..4d969786c19 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -27,7 +27,7 @@ bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( - base::IgnoreResult(platform_util::OpenExternal), escaped_url, false)); + base::IgnoreResult(platform_util::OpenExternal), escaped_url, true)); return true; } From b3ac48cf52f0b36831fb8366fc16ecf2be287cf8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 17 Feb 2016 09:05:21 -0800 Subject: [PATCH 094/173] Handle argument parsing in C++ --- atom/common/api/atom_api_shell.cc | 13 ++++++++++++- atom/common/api/lib/shell.js | 18 +----------------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/atom/common/api/atom_api_shell.cc b/atom/common/api/atom_api_shell.cc index d0e795e8745..f99e2ba1854 100644 --- a/atom/common/api/atom_api_shell.cc +++ b/atom/common/api/atom_api_shell.cc @@ -12,12 +12,23 @@ namespace { +bool OpenExternal(const GURL& url, mate::Arguments* args) { + bool activate = true; + if (args->Length() == 2) { + mate::Dictionary options; + if (args->GetNext(&options)) { + options.Get("activate", &activate); + } + } + return platform_util::OpenExternal(url, activate); +} + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); dict.SetMethod("showItemInFolder", &platform_util::ShowItemInFolder); dict.SetMethod("openItem", &platform_util::OpenItem); - dict.SetMethod("_openExternal", &platform_util::OpenExternal); + dict.SetMethod("openExternal", &OpenExternal); dict.SetMethod("moveItemToTrash", &platform_util::MoveItemToTrash); dict.SetMethod("beep", &platform_util::Beep); } diff --git a/atom/common/api/lib/shell.js b/atom/common/api/lib/shell.js index d62280277c5..08cc4e8eb41 100644 --- a/atom/common/api/lib/shell.js +++ b/atom/common/api/lib/shell.js @@ -1,17 +1 @@ -'use strict'; - -const bindings = process.atomBinding('shell'); - -exports.beep = bindings.beep; -exports.moveItemToTrash = bindings.moveItemToTrash; -exports.openItem = bindings.openItem; -exports.showItemInFolder = bindings.showItemInFolder; - -exports.openExternal = (url, options) => { - var activate = true; - if (options != null && options.activate != null) { - activate = !!options.activate; - } - - return bindings._openExternal(url, activate); -}; +module.exports = process.atomBinding('shell'); From 709661156a0d9bb4b96bbcb98687912af6f6aa83 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Feb 2016 16:46:49 -0800 Subject: [PATCH 095/173] Use const for requires --- spec/api-app-spec.js | 16 ++++++---------- spec/api-clipboard-spec.js | 10 ++++------ spec/api-crash-reporter-spec.js | 27 +++++++++++---------------- spec/api-debugger-spec.js | 12 +++--------- spec/api-ipc-spec.js | 15 +++++++-------- spec/api-menu-spec.js | 10 +++++----- spec/api-screen-spec.js | 7 ++----- spec/api-web-frame-spec.js | 10 +++------- 8 files changed, 41 insertions(+), 66 deletions(-) diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index 0019ec59d5f..176a94a0437 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -1,14 +1,10 @@ -var BrowserWindow, ChildProcess, app, assert, path, ref, remote; +const assert = require('assert'); +const ChildProcess = require('child_process'); +const path = require('path'); +const remote = require('electron').remote; -assert = require('assert'); - -ChildProcess = require('child_process'); - -path = require('path'); - -remote = require('electron').remote; - -ref = remote.require('electron'), app = ref.app, BrowserWindow = ref.BrowserWindow; +const app = remote.require('electron').app; +const BrowserWindow = remote.require('electron').BrowserWindow; describe('electron module', function() { it ('can prevent exposing internal modules to require', function(done) { diff --git a/spec/api-clipboard-spec.js b/spec/api-clipboard-spec.js index fe94e330d41..48ba558dfd0 100644 --- a/spec/api-clipboard-spec.js +++ b/spec/api-clipboard-spec.js @@ -1,10 +1,8 @@ -var assert, clipboard, nativeImage, path, ref; +const assert = require('assert'); +const path = require('path'); -assert = require('assert'); - -path = require('path'); - -ref = require('electron'), clipboard = ref.clipboard, nativeImage = ref.nativeImage; +const clipboard = require('electron').clipboard; +const nativeImage = require('electron').nativeImage; describe('clipboard module', function() { var fixtures; diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index b3c4c311589..dac1307a8e8 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -1,18 +1,13 @@ -var BrowserWindow, app, assert, crashReporter, http, multiparty, path, ref, remote, url; +const assert = require('assert'); +const http = require('http'); +const multiparty = require('multiparty'); +const path = require('path'); +const url = require('url'); -assert = require('assert'); - -path = require('path'); - -http = require('http'); - -url = require('url'); - -multiparty = require('multiparty'); - -remote = require('electron').remote; - -ref = remote.require('electron'), app = ref.app, crashReporter = ref.crashReporter, BrowserWindow = ref.BrowserWindow; +const remote = require('electron').remote; +const app = remote.require('electron').app; +const crashReporter = remote.require('electron').crashReporter; +const BrowserWindow = remote.require('electron').BrowserWindow; describe('crash-reporter module', function() { var fixtures, isCI, w; @@ -63,7 +58,7 @@ describe('crash-reporter module', function() { return server.listen(port, '127.0.0.1', function() { port = server.address().port; remote.process.port = port; - url = url.format({ + const crashUrl = url.format({ protocol: 'file', pathname: path.join(fixtures, 'api', 'crash.html'), search: "?port=" + port @@ -74,7 +69,7 @@ describe('crash-reporter module', function() { submitURL: "http://127.0.0.1:" + port }); } - return w.loadURL(url); + return w.loadURL(crashUrl); }); }); return describe(".start(options)", function() { diff --git a/spec/api-debugger-spec.js b/spec/api-debugger-spec.js index 7a16ca7263c..3c69d38ed32 100644 --- a/spec/api-debugger-spec.js +++ b/spec/api-debugger-spec.js @@ -1,12 +1,6 @@ -var assert, path, remote, BrowserWindow; - -assert = require('assert'); - -path = require('path'); - -remote = require('electron').remote; - -BrowserWindow = remote.BrowserWindow; +const assert = require('assert'); +const path = require('path'); +const BrowserWindow = require('electron').remote.BrowserWindow; describe('debugger module', function() { var fixtures, w; diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index 66f392a577c..ce5641b71cb 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -1,14 +1,13 @@ -var BrowserWindow, assert, comparePaths, ipcMain, ipcRenderer, path, ref, ref1, remote; +const assert = require('assert'); +const path = require('path'); -assert = require('assert'); +const ipcRenderer = require('electron').ipcRenderer; +const remote = require('electron').remote; -path = require('path'); +const ipcMain = remote.require('electron').ipcMain; +const BrowserWindow = remote.require('electron').BrowserWindow; -ref = require('electron'), ipcRenderer = ref.ipcRenderer, remote = ref.remote; - -ref1 = remote.require('electron'), ipcMain = ref1.ipcMain, BrowserWindow = ref1.BrowserWindow; - -comparePaths = function(path1, path2) { +const comparePaths = function(path1, path2) { if (process.platform === 'win32') { path1 = path1.toLowerCase(); path2 = path2.toLowerCase(); diff --git a/spec/api-menu-spec.js b/spec/api-menu-spec.js index 5771358337e..67705d22b3d 100644 --- a/spec/api-menu-spec.js +++ b/spec/api-menu-spec.js @@ -1,10 +1,10 @@ -var Menu, MenuItem, assert, ipcRenderer, ref, ref1, remote; +const assert = require('assert'); -assert = require('assert'); +const remote = require('electron').remote; +const ipcRenderer = require('electron').ipcRenderer; -ref = require('electron'), remote = ref.remote, ipcRenderer = ref.ipcRenderer; - -ref1 = remote.require('electron'), Menu = ref1.Menu, MenuItem = ref1.MenuItem; +const Menu = remote.require('electron').Menu; +const MenuItem = remote.require('electron').MenuItem; describe('menu module', function() { describe('Menu.buildFromTemplate', function() { diff --git a/spec/api-screen-spec.js b/spec/api-screen-spec.js index b393d4b99ee..abc12784165 100644 --- a/spec/api-screen-spec.js +++ b/spec/api-screen-spec.js @@ -1,8 +1,5 @@ -var assert, screen; - -assert = require('assert'); - -screen = require('electron').screen; +const assert = require('assert'); +const screen = require('electron').screen; describe('screen module', function() { describe('screen.getCursorScreenPoint()', function() { diff --git a/spec/api-web-frame-spec.js b/spec/api-web-frame-spec.js index 3d287a6acba..d3d43986ec8 100644 --- a/spec/api-web-frame-spec.js +++ b/spec/api-web-frame-spec.js @@ -1,10 +1,6 @@ -var assert, path, webFrame; - -assert = require('assert'); - -path = require('path'); - -webFrame = require('electron').webFrame; +const assert = require('assert'); +const path = require('path'); +const webFrame = require('electron').webFrame; describe('webFrame module', function() { var fixtures; From e63c3c727a2d42a266b3a020d882a9b0c3a0bf83 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Feb 2016 17:09:41 -0800 Subject: [PATCH 096/173] Add newlines between describe/it blocks --- spec/api-app-spec.js | 18 ++- spec/api-clipboard-spec.js | 8 +- spec/api-crash-reporter-spec.js | 21 ++- spec/api-debugger-spec.js | 7 +- spec/api-ipc-spec.js | 63 ++++---- spec/api-menu-spec.js | 48 +++--- spec/api-protocol-spec.js | 160 ++++++++++--------- spec/api-screen-spec.js | 7 +- spec/api-session-spec.js | 16 +- spec/api-web-frame-spec.js | 6 +- spec/api-web-request-spec.js | 36 ++++- spec/asar-spec.js | 271 ++++++++++++++++++-------------- spec/chromium-spec.js | 59 +++++-- spec/modules-spec.js | 7 +- spec/node-spec.js | 23 ++- 15 files changed, 455 insertions(+), 295 deletions(-) diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index 176a94a0437..ea305ae9535 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -27,6 +27,7 @@ describe('app module', function() { return assert.equal(app.getVersion(), '0.1.0'); }); }); + describe('app.setVersion(version)', function() { return it('overrides the version', function() { assert.equal(app.getVersion(), '0.1.0'); @@ -35,11 +36,13 @@ describe('app module', function() { return app.setVersion('0.1.0'); }); }); + describe('app.getName()', function() { return it('returns the name field of package.json', function() { return assert.equal(app.getName(), 'Electron Test'); }); }); + describe('app.setName(name)', function() { return it('overrides the name', function() { assert.equal(app.getName(), 'Electron Test'); @@ -48,17 +51,20 @@ describe('app module', function() { return app.setName('Electron Test'); }); }); + describe('app.getLocale()', function() { return it('should not be empty', function() { return assert.notEqual(app.getLocale(), ''); }); }); + describe('app.exit(exitCode)', function() { - var appProcess; - appProcess = null; + var appProcess = null; + afterEach(function() { return appProcess != null ? appProcess.kill() : void 0; }); + return it('emits a process exit event with the code', function(done) { var appPath, electronPath, output; appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app'); @@ -77,15 +83,17 @@ describe('app module', function() { }); }); }); + return describe('BrowserWindow events', function() { - var w; - w = null; + var w = null; + afterEach(function() { if (w != null) { w.destroy(); } return w = null; }); + it('should emit browser-window-focus event when window is focused', function(done) { app.once('browser-window-focus', function(e, window) { assert.equal(w.id, window.id); @@ -96,6 +104,7 @@ describe('app module', function() { }); return w.emit('focus'); }); + it('should emit browser-window-blur event when window is blured', function(done) { app.once('browser-window-blur', function(e, window) { assert.equal(w.id, window.id); @@ -106,6 +115,7 @@ describe('app module', function() { }); return w.emit('blur'); }); + return it('should emit browser-window-created event when window is created', function(done) { app.once('browser-window-created', function(e, window) { return setImmediate(function() { diff --git a/spec/api-clipboard-spec.js b/spec/api-clipboard-spec.js index 48ba558dfd0..28afb4a5307 100644 --- a/spec/api-clipboard-spec.js +++ b/spec/api-clipboard-spec.js @@ -5,8 +5,8 @@ const clipboard = require('electron').clipboard; const nativeImage = require('electron').nativeImage; describe('clipboard module', function() { - var fixtures; - fixtures = path.resolve(__dirname, 'fixtures'); + var fixtures = path.resolve(__dirname, 'fixtures'); + describe('clipboard.readImage()', function() { return it('returns NativeImage intance', function() { var i, p; @@ -16,6 +16,7 @@ describe('clipboard module', function() { return assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); }); }); + describe('clipboard.readText()', function() { return it('returns unicode string correctly', function() { var text; @@ -24,6 +25,7 @@ describe('clipboard module', function() { return assert.equal(clipboard.readText(), text); }); }); + describe('clipboard.readHtml()', function() { return it('returns markup correctly', function() { var markup, text; @@ -33,6 +35,7 @@ describe('clipboard module', function() { return assert.equal(clipboard.readHtml(), markup); }); }); + describe('clipboard.readRtf', function() { return it('returns rtf text correctly', function() { var rtf = "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}"; @@ -40,6 +43,7 @@ describe('clipboard module', function() { return assert.equal(clipboard.readRtf(), rtf); }); }); + return describe('clipboard.write()', function() { return it('returns data correctly', function() { var i, markup, p, text, rtf; diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index dac1307a8e8..72662aa3d93 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -10,29 +10,33 @@ const crashReporter = remote.require('electron').crashReporter; const BrowserWindow = remote.require('electron').BrowserWindow; describe('crash-reporter module', function() { - var fixtures, isCI, w; - fixtures = path.resolve(__dirname, 'fixtures'); - w = null; + var fixtures = path.resolve(__dirname, 'fixtures'); + var w = null; + beforeEach(function() { return w = new BrowserWindow({ show: false }); }); + afterEach(function() { return w.destroy(); }); + if (process.mas) { return; } - isCI = remote.getGlobal('isCi'); + + var isCI = remote.getGlobal('isCi'); if (isCI) { return; } + it('should send minidump when renderer crashes', function(done) { - var called, port, server; this.timeout(120000); - called = false; - server = http.createServer(function(req, res) { + + var called = false; + var server = http.createServer(function(req, res) { var form; server.close(); form = new multiparty.Form(); @@ -54,7 +58,7 @@ describe('crash-reporter module', function() { return done(); }); }); - port = remote.process.port; + var port = remote.process.port; return server.listen(port, '127.0.0.1', function() { port = server.address().port; remote.process.port = port; @@ -72,6 +76,7 @@ describe('crash-reporter module', function() { return w.loadURL(crashUrl); }); }); + return describe(".start(options)", function() { return it('requires that the companyName and submitURL options be specified', function() { assert.throws(function() { diff --git a/spec/api-debugger-spec.js b/spec/api-debugger-spec.js index 3c69d38ed32..714d5fda48c 100644 --- a/spec/api-debugger-spec.js +++ b/spec/api-debugger-spec.js @@ -3,9 +3,9 @@ const path = require('path'); const BrowserWindow = require('electron').remote.BrowserWindow; describe('debugger module', function() { - var fixtures, w; - fixtures = path.resolve(__dirname, 'fixtures'); - w = null; + var fixtures = path.resolve(__dirname, 'fixtures'); + var w = null; + beforeEach(function() { if (w != null) { w.destroy(); @@ -16,6 +16,7 @@ describe('debugger module', function() { height: 400 }); }); + afterEach(function() { if (w != null) { w.destroy(); diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index ce5641b71cb..6b1c99779b2 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -16,8 +16,8 @@ const comparePaths = function(path1, path2) { }; describe('ipc module', function() { - var fixtures; - fixtures = path.join(__dirname, 'fixtures'); + var fixtures = path.join(__dirname, 'fixtures'); + describe('remote.require', function() { it('should returns same object for the same module', function() { var dialog1, dialog2; @@ -25,36 +25,39 @@ describe('ipc module', function() { dialog2 = remote.require('electron'); return assert.equal(dialog1, dialog2); }); + it('should work when object contains id property', function() { var a; a = remote.require(path.join(fixtures, 'module', 'id.js')); return assert.equal(a.id, 1127); }); + return it('should search module from the user app', function() { comparePaths(path.normalize(remote.process.mainModule.filename), path.resolve(__dirname, 'static', 'main.js')); return comparePaths(path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules')); }); }); + describe('remote.createFunctionWithReturnValue', function() { return it('should be called in browser synchronously', function() { - var buf, call, result; - buf = new Buffer('test'); - call = remote.require(path.join(fixtures, 'module', 'call.js')); - result = call.call(remote.createFunctionWithReturnValue(buf)); + var buf = new Buffer('test'); + var call = remote.require(path.join(fixtures, 'module', 'call.js')); + var result = call.call(remote.createFunctionWithReturnValue(buf)); return assert.equal(result.constructor.name, 'Buffer'); }); }); + describe('remote object in renderer', function() { it('can change its properties', function() { - var property, property2; - property = remote.require(path.join(fixtures, 'module', 'property.js')); + var property = remote.require(path.join(fixtures, 'module', 'property.js')); assert.equal(property.property, 1127); property.property = 1007; assert.equal(property.property, 1007); - property2 = remote.require(path.join(fixtures, 'module', 'property.js')); + var property2 = remote.require(path.join(fixtures, 'module', 'property.js')); assert.equal(property2.property, 1007); return property.property = 1127; }); + return it('can construct an object from its member', function() { var call, obj; call = remote.require(path.join(fixtures, 'module', 'call.js')); @@ -62,37 +65,37 @@ describe('ipc module', function() { return assert.equal(obj.test, 'test'); }); }); + describe('remote value in browser', function() { - var print; - print = path.join(fixtures, 'module', 'print_name.js'); + var print = path.join(fixtures, 'module', 'print_name.js'); + it('keeps its constructor name for objects', function() { - var buf, print_name; - buf = new Buffer('test'); - print_name = remote.require(print); + var buf = new Buffer('test'); + var print_name = remote.require(print); return assert.equal(print_name.print(buf), 'Buffer'); }); + return it('supports instanceof Date', function() { - var now, print_name; - now = new Date(); - print_name = remote.require(print); + var now = new Date(); + var print_name = remote.require(print); assert.equal(print_name.print(now), 'Date'); return assert.deepEqual(print_name.echo(now), now); }); }); + describe('remote promise', function() { return it('can be used as promise in each side', function(done) { - var promise; - promise = remote.require(path.join(fixtures, 'module', 'promise.js')); + var promise = remote.require(path.join(fixtures, 'module', 'promise.js')); return promise.twicePromise(Promise.resolve(1234)).then(function(value) { assert.equal(value, 2468); return done(); }); }); }); + describe('ipc.sender.send', function() { return it('should work when sending an object containing id property', function(done) { - var obj; - obj = { + var obj = { id: 1, name: 'ly' }; @@ -103,16 +106,17 @@ describe('ipc module', function() { return ipcRenderer.send('message', obj); }); }); + describe('ipc.sendSync', function() { it('can be replied by setting event.returnValue', function() { - var msg; - msg = ipcRenderer.sendSync('echo', 'test'); + var msg = ipcRenderer.sendSync('echo', 'test'); return assert.equal(msg, 'test'); }); + return it('does not crash when reply is not sent and browser is destroyed', function(done) { - var w; this.timeout(10000); - w = new BrowserWindow({ + + var w = new BrowserWindow({ show: false }); ipcMain.once('send-sync-message', function(event) { @@ -123,18 +127,19 @@ describe('ipc module', function() { return w.loadURL('file://' + path.join(fixtures, 'api', 'send-sync-message.html')); }); }); + return describe('remote listeners', function() { - var w; - w = null; + var w = null; + afterEach(function() { return w.destroy(); }); + return it('can be added and removed correctly', function() { - var listener; w = new BrowserWindow({ show: false }); - listener = function() {}; + var listener = function() {}; w.on('test', listener); assert.equal(w.listenerCount('test'), 1); w.removeListener('test', listener); diff --git a/spec/api-menu-spec.js b/spec/api-menu-spec.js index 67705d22b3d..292a65a0f08 100644 --- a/spec/api-menu-spec.js +++ b/spec/api-menu-spec.js @@ -9,8 +9,7 @@ const MenuItem = remote.require('electron').MenuItem; describe('menu module', function() { describe('Menu.buildFromTemplate', function() { it('should be able to attach extra fields', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: 'text', extra: 'field' @@ -18,9 +17,9 @@ describe('menu module', function() { ]); return assert.equal(menu.items[0].extra, 'field'); }); + it('does not modify the specified template', function() { - var template; - template = ipcRenderer.sendSync('eval', "var template = [{label: 'text', submenu: [{label: 'sub'}]}];\nrequire('electron').Menu.buildFromTemplate(template);\ntemplate;"); + var template = ipcRenderer.sendSync('eval', "var template = [{label: 'text', submenu: [{label: 'sub'}]}];\nrequire('electron').Menu.buildFromTemplate(template);\ntemplate;"); return assert.deepStrictEqual(template, [ { label: 'text', @@ -32,10 +31,10 @@ describe('menu module', function() { } ]); }); + return describe('Menu.buildFromTemplate should reorder based on item position specifiers', function() { it('should position before existing item', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: '2', id: '2' @@ -52,9 +51,9 @@ describe('menu module', function() { assert.equal(menu.items[1].label, '2'); return assert.equal(menu.items[2].label, '3'); }); + it('should position after existing item', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: '1', id: '1' @@ -71,9 +70,9 @@ describe('menu module', function() { assert.equal(menu.items[1].label, '2'); return assert.equal(menu.items[2].label, '3'); }); + it('should position at endof existing separator groups', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { type: 'separator', id: 'numbers' @@ -115,9 +114,9 @@ describe('menu module', function() { assert.equal(menu.items[6].label, 'b'); return assert.equal(menu.items[7].label, 'c'); }); + it('should create separator group if endof does not reference existing separator group', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: 'a', id: 'a', @@ -153,9 +152,9 @@ describe('menu module', function() { assert.equal(menu.items[6].label, '2'); return assert.equal(menu.items[7].label, '3'); }); + return it('should continue inserting items at next index when no specifier is present', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: '4', id: '4' @@ -182,10 +181,10 @@ describe('menu module', function() { }); }); }); + describe('Menu.insert', function() { return it('should store item in @items by its index', function() { - var item, menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: '1' }, { @@ -194,7 +193,7 @@ describe('menu module', function() { label: '3' } ]); - item = new MenuItem({ + var item = new MenuItem({ label: 'inserted' }); menu.insert(1, item); @@ -204,10 +203,10 @@ describe('menu module', function() { return assert.equal(menu.items[3].label, '3'); }); }); + describe('MenuItem.click', function() { return it('should be called with the item object passed', function(done) { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: 'text', click: function(item) { @@ -220,10 +219,10 @@ describe('menu module', function() { return menu.delegate.executeCommand(menu.items[0].commandId); }); }); + return describe('MenuItem with checked property', function() { it('clicking an checkbox item should flip the checked property', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: 'text', type: 'checkbox' @@ -233,9 +232,9 @@ describe('menu module', function() { menu.delegate.executeCommand(menu.items[0].commandId); return assert.equal(menu.items[0].checked, true); }); + it('clicking an radio item should always make checked property true', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: 'text', type: 'radio' @@ -246,6 +245,7 @@ describe('menu module', function() { menu.delegate.executeCommand(menu.items[0].commandId); return assert.equal(menu.items[0].checked, true); }); + it('at least have one item checked in each group', function() { var i, j, k, menu, template; template = []; @@ -269,6 +269,7 @@ describe('menu module', function() { assert.equal(menu.items[0].checked, true); return assert.equal(menu.items[12].checked, true); }); + it('should assign groupId automatically', function() { var groupId, i, j, k, l, m, menu, results, template; template = []; @@ -298,6 +299,7 @@ describe('menu module', function() { } return results; }); + return it("setting 'checked' should flip other items' 'checked' property", function() { var i, j, k, l, m, menu, n, o, p, q, results, template; template = []; diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index 284033b967d..6426e3312ec 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -6,13 +6,13 @@ const remote = require('electron').remote; const protocol = remote.require('electron').protocol; describe('protocol module', function() { - var postData, protocolName, text; - protocolName = 'sp'; - text = 'valar morghulis'; - postData = { + var protocolName = 'sp'; + var text = 'valar morghulis'; + var postData = { name: 'post test', type: 'string' }; + afterEach(function(done) { return protocol.unregisterProtocol(protocolName, function() { return protocol.uninterceptProtocol('http', function() { @@ -20,11 +20,12 @@ describe('protocol module', function() { }); }); }); + describe('protocol.register(Any)Protocol', function() { - var emptyHandler; - emptyHandler = function(request, callback) { + var emptyHandler = function(request, callback) { return callback(); }; + it('throws error when scheme is already registered', function(done) { return protocol.registerStringProtocol(protocolName, emptyHandler, function(error) { assert.equal(error, null); @@ -34,9 +35,9 @@ describe('protocol module', function() { }); }); }); + it('does not crash when handler is called twice', function(done) { - var doubleHandler; - doubleHandler = function(request, callback) { + var doubleHandler = function(request, callback) { try { callback(text); return callback(); @@ -60,6 +61,7 @@ describe('protocol module', function() { }); }); }); + it('sends error when callback is called with nothing', function(done) { return protocol.registerBufferProtocol(protocolName, emptyHandler, function(error) { if (error) { @@ -77,9 +79,9 @@ describe('protocol module', function() { }); }); }); + return it('does not crash when callback is called in next tick', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return setImmediate(function() { return callback(text); }); @@ -101,6 +103,7 @@ describe('protocol module', function() { }); }); }); + describe('protocol.unregisterProtocol', function() { return it('returns error when scheme does not exist', function(done) { return protocol.unregisterProtocol('not-exist', function(error) { @@ -109,10 +112,10 @@ describe('protocol module', function() { }); }); }); + describe('protocol.registerStringProtocol', function() { it('sends string as response', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(text); }; return protocol.registerStringProtocol(protocolName, handler, function(error) { @@ -131,9 +134,9 @@ describe('protocol module', function() { }); }); }); + it('sets Access-Control-Allow-Origin', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(text); }; return protocol.registerStringProtocol(protocolName, handler, function(error) { @@ -153,9 +156,9 @@ describe('protocol module', function() { }); }); }); + it('sends object as response', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback({ data: text, mimeType: 'text/html' @@ -177,9 +180,9 @@ describe('protocol module', function() { }); }); }); + return it('fails when sending object other than string', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(new Date); }; return protocol.registerBufferProtocol(protocolName, handler, function(error) { @@ -199,12 +202,12 @@ describe('protocol module', function() { }); }); }); + describe('protocol.registerBufferProtocol', function() { - var buffer; - buffer = new Buffer(text); + var buffer = new Buffer(text); + it('sends Buffer as response', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(buffer); }; return protocol.registerBufferProtocol(protocolName, handler, function(error) { @@ -223,11 +226,12 @@ describe('protocol module', function() { }); }); }); + it('sets Access-Control-Allow-Origin', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(buffer); }; + return protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); @@ -245,9 +249,9 @@ describe('protocol module', function() { }); }); }); + it('sends object as response', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback({ data: buffer, mimeType: 'text/html' @@ -269,9 +273,9 @@ describe('protocol module', function() { }); }); }); + return it('fails when sending string', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(text); }; return protocol.registerBufferProtocol(protocolName, handler, function(error) { @@ -291,15 +295,15 @@ describe('protocol module', function() { }); }); }); + describe('protocol.registerFileProtocol', function() { - var fileContent, filePath, normalContent, normalPath; - filePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'file1'); - fileContent = require('fs').readFileSync(filePath); - normalPath = path.join(__dirname, 'fixtures', 'pages', 'a.html'); - normalContent = require('fs').readFileSync(normalPath); + var filePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'file1'); + var fileContent = require('fs').readFileSync(filePath); + var normalPath = path.join(__dirname, 'fixtures', 'pages', 'a.html'); + var normalContent = require('fs').readFileSync(normalPath); + it('sends file path as response', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(filePath); }; return protocol.registerFileProtocol(protocolName, handler, function(error) { @@ -318,9 +322,9 @@ describe('protocol module', function() { }); }); }); + it('sets Access-Control-Allow-Origin', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(filePath); }; return protocol.registerFileProtocol(protocolName, handler, function(error) { @@ -363,11 +367,12 @@ describe('protocol module', function() { }); }); }); + it('can send normal file', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(normalPath); }; + return protocol.registerFileProtocol(protocolName, handler, function(error) { if (error) { return done(error); @@ -384,10 +389,10 @@ describe('protocol module', function() { }); }); }); + it('fails when sending unexist-file', function(done) { - var fakeFilePath, handler; - fakeFilePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'not-exist'); - handler = function(request, callback) { + var fakeFilePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'not-exist'); + var handler = function(request, callback) { return callback(fakeFilePath); }; return protocol.registerBufferProtocol(protocolName, handler, function(error) { @@ -406,9 +411,9 @@ describe('protocol module', function() { }); }); }); + return it('fails when sending unsupported content', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(new Date); }; return protocol.registerBufferProtocol(protocolName, handler, function(error) { @@ -428,10 +433,10 @@ describe('protocol module', function() { }); }); }); + describe('protocol.registerHttpProtocol', function() { it('sends url as response', function(done) { - var server; - server = http.createServer(function(req, res) { + var server = http.createServer(function(req, res) { assert.notEqual(req.headers.accept, ''); res.end(text); return server.close(); @@ -462,9 +467,9 @@ describe('protocol module', function() { }); }); }); + it('fails when sending invalid url', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback({ url: 'url' }); @@ -485,9 +490,9 @@ describe('protocol module', function() { }); }); }); + return it('fails when sending unsupported content', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(new Date); }; return protocol.registerHttpProtocol(protocolName, handler, function(error) { @@ -507,6 +512,7 @@ describe('protocol module', function() { }); }); }); + describe('protocol.isProtocolHandled', function() { it('returns true for file:', function(done) { return protocol.isProtocolHandled('file', function(result) { @@ -514,27 +520,30 @@ describe('protocol module', function() { return done(); }); }); + it('returns true for http:', function(done) { return protocol.isProtocolHandled('http', function(result) { assert.equal(result, true); return done(); }); }); + it('returns true for https:', function(done) { return protocol.isProtocolHandled('https', function(result) { assert.equal(result, true); return done(); }); }); + it('returns false when scheme is not registred', function(done) { return protocol.isProtocolHandled('no-exist', function(result) { assert.equal(result, false); return done(); }); }); + it('returns true for custom protocol', function(done) { - var emptyHandler; - emptyHandler = function(request, callback) { + var emptyHandler = function(request, callback) { return callback(); }; return protocol.registerStringProtocol(protocolName, emptyHandler, function(error) { @@ -545,9 +554,9 @@ describe('protocol module', function() { }); }); }); + return it('returns true for intercepted protocol', function(done) { - var emptyHandler; - emptyHandler = function(request, callback) { + var emptyHandler = function(request, callback) { return callback(); }; return protocol.interceptStringProtocol('http', emptyHandler, function(error) { @@ -559,11 +568,12 @@ describe('protocol module', function() { }); }); }); + describe('protocol.intercept(Any)Protocol', function() { - var emptyHandler; - emptyHandler = function(request, callback) { + var emptyHandler = function(request, callback) { return callback(); }; + it('throws error when scheme is already intercepted', function(done) { return protocol.interceptStringProtocol('http', emptyHandler, function(error) { assert.equal(error, null); @@ -573,9 +583,9 @@ describe('protocol module', function() { }); }); }); + it('does not crash when handler is called twice', function(done) { - var doubleHandler; - doubleHandler = function(request, callback) { + var doubleHandler = function(request, callback) { try { callback(text); return callback(); @@ -599,6 +609,7 @@ describe('protocol module', function() { }); }); }); + return it('sends error when callback is called with nothing', function(done) { if (process.env.TRAVIS === 'true') { return done(); @@ -620,10 +631,10 @@ describe('protocol module', function() { }); }); }); + describe('protocol.interceptStringProtocol', function() { it('can intercept http protocol', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(text); }; return protocol.interceptStringProtocol('http', handler, function(error) { @@ -642,9 +653,9 @@ describe('protocol module', function() { }); }); }); + it('can set content-type', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback({ mimeType: 'application/json', data: '{"value": 1}' @@ -667,9 +678,9 @@ describe('protocol module', function() { }); }); }); + return it('can receive post data', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { var uploadData; uploadData = request.uploadData[0].bytes.toString(); return callback({ @@ -695,10 +706,10 @@ describe('protocol module', function() { }); }); }); + describe('protocol.interceptBufferProtocol', function() { it('can intercept http protocol', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback(new Buffer(text)); }; return protocol.interceptBufferProtocol('http', handler, function(error) { @@ -717,9 +728,9 @@ describe('protocol module', function() { }); }); }); + return it('can receive post data', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { var uploadData; uploadData = request.uploadData[0].bytes; return callback(uploadData); @@ -743,10 +754,10 @@ describe('protocol module', function() { }); }); }); + describe('protocol.interceptHttpProtocol', function() { return it('can send POST request', function(done) { - var server; - server = http.createServer(function(req, res) { + var server = http.createServer(function(req, res) { var body; body = ''; req.on('data', function(chunk) { @@ -758,10 +769,9 @@ describe('protocol module', function() { return server.close(); }); return server.listen(0, '127.0.0.1', function() { - var handler, port, url; - port = server.address().port; - url = "http://127.0.0.1:" + port; - handler = function(request, callback) { + var port = server.address().port; + var url = "http://127.0.0.1:" + port; + var handler = function(request, callback) { var data; data = { url: url, @@ -794,6 +804,7 @@ describe('protocol module', function() { }); }); }); + return describe('protocol.uninterceptProtocol', function() { it('returns error when scheme does not exist', function(done) { return protocol.uninterceptProtocol('not-exist', function(error) { @@ -801,6 +812,7 @@ describe('protocol module', function() { return done(); }); }); + return it('returns error when scheme is not intercepted', function(done) { return protocol.uninterceptProtocol('http', function(error) { assert.notEqual(error, null); diff --git a/spec/api-screen-spec.js b/spec/api-screen-spec.js index abc12784165..9329c01823d 100644 --- a/spec/api-screen-spec.js +++ b/spec/api-screen-spec.js @@ -4,16 +4,15 @@ const screen = require('electron').screen; describe('screen module', function() { describe('screen.getCursorScreenPoint()', function() { return it('returns a point object', function() { - var point; - point = screen.getCursorScreenPoint(); + var point = screen.getCursorScreenPoint(); assert.equal(typeof point.x, 'number'); return assert.equal(typeof point.y, 'number'); }); }); + return describe('screen.getPrimaryDisplay()', function() { return it('returns a display object', function() { - var display; - display = screen.getPrimaryDisplay(); + var display = screen.getPrimaryDisplay(); assert.equal(typeof display.scaleFactor, 'number'); assert(display.size.width > 0); return assert(display.size.height > 0); diff --git a/spec/api-session-spec.js b/spec/api-session-spec.js index fe27f932cee..a4421a18ed0 100644 --- a/spec/api-session-spec.js +++ b/spec/api-session-spec.js @@ -11,11 +11,12 @@ const session = remote.session; const BrowserWindow = remote.BrowserWindow; describe('session module', function() { - var fixtures, url, w; this.timeout(10000); - fixtures = path.resolve(__dirname, 'fixtures'); - w = null; - url = "http://127.0.0.1"; + + var fixtures = path.resolve(__dirname, 'fixtures'); + var w = null; + var url = "http://127.0.0.1"; + beforeEach(function() { return w = new BrowserWindow({ show: false, @@ -23,6 +24,7 @@ describe('session module', function() { height: 400 }); }); + afterEach(function() { return w.destroy(); }); @@ -62,6 +64,7 @@ describe('session module', function() { }); }); }); + it('should over-write the existent cookie', function(done) { return session.defaultSession.cookies.set({ url: url, @@ -92,6 +95,7 @@ describe('session module', function() { }); }); }); + it('should remove cookies', function(done) { return session.defaultSession.cookies.set({ url: url, @@ -155,6 +159,7 @@ describe('session module', function() { height: 400 }); }); + afterEach(function() { return w.destroy(); }); @@ -213,6 +218,7 @@ describe('session module', function() { assert(fs.existsSync(downloadFilePath)); return fs.unlinkSync(downloadFilePath); }; + it('can download using BrowserWindow.loadURL', function(done) { return downloadServer.listen(0, '127.0.0.1', function() { var port; @@ -225,6 +231,7 @@ describe('session module', function() { }); }); }); + it('can download using WebView.downloadURL', function(done) { return downloadServer.listen(0, '127.0.0.1', function() { var port, webview; @@ -243,6 +250,7 @@ describe('session module', function() { return document.body.appendChild(webview); }); }); + it('can cancel download', function(done) { return downloadServer.listen(0, '127.0.0.1', function() { var port; diff --git a/spec/api-web-frame-spec.js b/spec/api-web-frame-spec.js index d3d43986ec8..1a3eca6d584 100644 --- a/spec/api-web-frame-spec.js +++ b/spec/api-web-frame-spec.js @@ -3,13 +3,11 @@ const path = require('path'); const webFrame = require('electron').webFrame; describe('webFrame module', function() { - var fixtures; - fixtures = path.resolve(__dirname, 'fixtures'); + var fixtures = path.resolve(__dirname, 'fixtures'); return describe('webFrame.registerURLSchemeAsPrivileged', function() { return it('supports fetch api', function(done) { - var url; webFrame.registerURLSchemeAsPrivileged('file'); - url = "file://" + fixtures + "/assets/logo.png"; + var url = "file://" + fixtures + "/assets/logo.png"; return fetch(url).then(function(response) { assert(response.ok); return done(); diff --git a/spec/api-web-request-spec.js b/spec/api-web-request-spec.js index 91b84c77e1b..e2a3a1ca38f 100644 --- a/spec/api-web-request-spec.js +++ b/spec/api-web-request-spec.js @@ -5,9 +5,8 @@ const remote = require('electron').remote; const session = remote.session; describe('webRequest module', function() { - var defaultURL, server, ses; - ses = session.defaultSession; - server = http.createServer(function(req, res) { + var ses = session.defaultSession; + var server = http.createServer(function(req, res) { var content; res.setHeader('Custom', ['Header']); content = req.url; @@ -16,7 +15,8 @@ describe('webRequest module', function() { } return res.end(content); }); - defaultURL = null; + var defaultURL = null; + before(function(done) { return server.listen(0, '127.0.0.1', function() { var port; @@ -25,13 +25,16 @@ describe('webRequest module', function() { return done(); }); }); + after(function() { return server.close(); }); + describe('webRequest.onBeforeRequest', function() { afterEach(function() { return ses.webRequest.onBeforeRequest(null); }); + it('can cancel the request', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { return callback({ @@ -48,9 +51,9 @@ describe('webRequest module', function() { } }); }); + it('can filter URLs', function(done) { - var filter; - filter = { + var filter = { urls: [defaultURL + "filter/*"] }; ses.webRequest.onBeforeRequest(filter, function(details, callback) { @@ -77,6 +80,7 @@ describe('webRequest module', function() { } }); }); + it('receives details object', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { assert.equal(typeof details.id, 'number'); @@ -98,6 +102,7 @@ describe('webRequest module', function() { } }); }); + it('receives post data in details object', function(done) { var postData = { name: 'post test', @@ -125,6 +130,7 @@ describe('webRequest module', function() { } }); }); + return it('can redirect the request', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { if (details.url === defaultURL) { @@ -147,10 +153,12 @@ describe('webRequest module', function() { }); }); }); + describe('webRequest.onBeforeSendHeaders', function() { afterEach(function() { return ses.webRequest.onBeforeSendHeaders(null); }); + it('receives details object', function(done) { ses.webRequest.onBeforeSendHeaders(function(details, callback) { assert.equal(typeof details.requestHeaders, 'object'); @@ -167,6 +175,7 @@ describe('webRequest module', function() { } }); }); + it('can change the request headers', function(done) { ses.webRequest.onBeforeSendHeaders(function(details, callback) { var requestHeaders; @@ -187,6 +196,7 @@ describe('webRequest module', function() { } }); }); + return it('resets the whole headers', function(done) { var requestHeaders; requestHeaders = { @@ -209,10 +219,12 @@ describe('webRequest module', function() { }); }); }); + describe('webRequest.onSendHeaders', function() { afterEach(function() { return ses.webRequest.onSendHeaders(null); }); + return it('receives details object', function(done) { ses.webRequest.onSendHeaders(function(details) { return assert.equal(typeof details.requestHeaders, 'object'); @@ -229,10 +241,12 @@ describe('webRequest module', function() { }); }); }); + describe('webRequest.onHeadersReceived', function() { afterEach(function() { return ses.webRequest.onHeadersReceived(null); }); + it('receives details object', function(done) { ses.webRequest.onHeadersReceived(function(details, callback) { assert.equal(details.statusLine, 'HTTP/1.1 200 OK'); @@ -251,6 +265,7 @@ describe('webRequest module', function() { } }); }); + it('can change the response header', function(done) { ses.webRequest.onHeadersReceived(function(details, callback) { var responseHeaders; @@ -272,6 +287,7 @@ describe('webRequest module', function() { } }); }); + return it('does not change header by default', function(done) { ses.webRequest.onHeadersReceived(function(details, callback) { return callback({}); @@ -289,10 +305,12 @@ describe('webRequest module', function() { }); }); }); + describe('webRequest.onResponseStarted', function() { afterEach(function() { return ses.webRequest.onResponseStarted(null); }); + return it('receives details object', function(done) { ses.webRequest.onResponseStarted(function(details) { assert.equal(typeof details.fromCache, 'boolean'); @@ -313,11 +331,13 @@ describe('webRequest module', function() { }); }); }); + describe('webRequest.onBeforeRedirect', function() { afterEach(function() { ses.webRequest.onBeforeRedirect(null); return ses.webRequest.onBeforeRequest(null); }); + return it('receives details object', function(done) { var redirectURL; redirectURL = defaultURL + "redirect"; @@ -348,10 +368,12 @@ describe('webRequest module', function() { }); }); }); + describe('webRequest.onCompleted', function() { afterEach(function() { return ses.webRequest.onCompleted(null); }); + return it('receives details object', function(done) { ses.webRequest.onCompleted(function(details) { assert.equal(typeof details.fromCache, 'boolean'); @@ -370,11 +392,13 @@ describe('webRequest module', function() { }); }); }); + return describe('webRequest.onErrorOccurred', function() { afterEach(function() { ses.webRequest.onErrorOccurred(null); return ses.webRequest.onBeforeRequest(null); }); + return it('receives details object', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { return callback({ diff --git a/spec/asar-spec.js b/spec/asar-spec.js index a8f449451fc..064212e7c7e 100644 --- a/spec/asar-spec.js +++ b/spec/asar-spec.js @@ -10,8 +10,8 @@ const ipcMain = remote.require('electron').ipcMain; const BrowserWindow = remote.require('electron').BrowserWindow; describe('asar package', function() { - var fixtures; - fixtures = path.join(__dirname, 'fixtures'); + var fixtures = path.join(__dirname, 'fixtures'); + describe('node api', function() { describe('fs.readFileSync', function() { it('does not leak fd', function() { @@ -21,6 +21,7 @@ describe('asar package', function() { readCalls++; } }); + it('reads a normal file', function() { var file1, file2, file3; file1 = path.join(fixtures, 'asar', 'a.asar', 'file1'); @@ -30,6 +31,7 @@ describe('asar package', function() { file3 = path.join(fixtures, 'asar', 'a.asar', 'file3'); return assert.equal(fs.readFileSync(file3).toString().trim(), 'file3'); }); + it('reads from a empty file', function() { var buffer, file; file = path.join(fixtures, 'asar', 'empty.asar', 'file1'); @@ -37,11 +39,13 @@ describe('asar package', function() { assert.equal(buffer.length, 0); return assert.equal(buffer.toString(), ''); }); + it('reads a linked file', function() { var p; p = path.join(fixtures, 'asar', 'a.asar', 'link1'); return assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); }); + it('reads a file from linked directory', function() { var p; p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1'); @@ -49,6 +53,7 @@ describe('asar package', function() { p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); return assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); }); + it('throws ENOENT error when can not find file', function() { var p, throws; p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); @@ -57,6 +62,7 @@ describe('asar package', function() { }; return assert.throws(throws, /ENOENT/); }); + it('passes ENOENT error to callback when can not find file', function() { var async, p; p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); @@ -67,12 +73,14 @@ describe('asar package', function() { }); return async = true; }); + return it('reads a normal file with unpacked files', function() { var p; p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt'); return assert.equal(fs.readFileSync(p).toString().trim(), 'a'); }); }); + describe('fs.readFile', function() { it('reads a normal file', function(done) { var p; @@ -83,6 +91,7 @@ describe('asar package', function() { return done(); }); }); + it('reads from a empty file', function(done) { var p; p = path.join(fixtures, 'asar', 'empty.asar', 'file1'); @@ -92,6 +101,7 @@ describe('asar package', function() { return done(); }); }); + it('reads a linked file', function(done) { var p; p = path.join(fixtures, 'asar', 'a.asar', 'link1'); @@ -101,6 +111,7 @@ describe('asar package', function() { return done(); }); }); + it('reads a file from linked directory', function(done) { var p; p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); @@ -110,6 +121,7 @@ describe('asar package', function() { return done(); }); }); + return it('throws ENOENT error when can not find file', function(done) { var p; p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); @@ -119,6 +131,7 @@ describe('asar package', function() { }); }); }); + describe('fs.lstatSync', function() { it('handles path with trailing slash correctly', function() { var p; @@ -126,6 +139,7 @@ describe('asar package', function() { fs.lstatSync(p); return fs.lstatSync(p + '/'); }); + it('returns information of root', function() { var p, stats; p = path.join(fixtures, 'asar', 'a.asar'); @@ -135,6 +149,7 @@ describe('asar package', function() { assert.equal(stats.isSymbolicLink(), false); return assert.equal(stats.size, 0); }); + it('returns information of a normal file', function() { var file, j, len, p, ref2, results, stats; ref2 = ['file1', 'file2', 'file3', path.join('dir1', 'file1'), path.join('link2', 'file1')]; @@ -150,6 +165,7 @@ describe('asar package', function() { } return results; }); + it('returns information of a normal directory', function() { var file, j, len, p, ref2, results, stats; ref2 = ['dir1', 'dir2', 'dir3']; @@ -165,6 +181,7 @@ describe('asar package', function() { } return results; }); + it('returns information of a linked file', function() { var file, j, len, p, ref2, results, stats; ref2 = ['link1', path.join('dir1', 'link1'), path.join('link2', 'link2')]; @@ -180,6 +197,7 @@ describe('asar package', function() { } return results; }); + it('returns information of a linked directory', function() { var file, j, len, p, ref2, results, stats; ref2 = ['link2', path.join('dir1', 'link2'), path.join('link2', 'link2')]; @@ -195,6 +213,7 @@ describe('asar package', function() { } return results; }); + return it('throws ENOENT error when can not find file', function() { var file, j, len, p, ref2, results, throws; ref2 = ['file4', 'file5', path.join('dir1', 'file4')]; @@ -210,12 +229,13 @@ describe('asar package', function() { return results; }); }); + describe('fs.lstat', function() { it('handles path with trailing slash correctly', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); + var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); return fs.lstat(p + '/', done); }); + it('returns information of root', function(done) { var p = path.join(fixtures, 'asar', 'a.asar'); fs.lstat(p, function(err, stats) { @@ -227,6 +247,7 @@ describe('asar package', function() { return done(); }); }); + it('returns information of a normal file', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1'); fs.lstat(p, function(err, stats) { @@ -238,6 +259,7 @@ describe('asar package', function() { return done(); }); }); + it('returns information of a normal directory', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'dir1'); fs.lstat(p, function(err, stats) { @@ -249,6 +271,7 @@ describe('asar package', function() { return done(); }); }); + it('returns information of a linked file', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link1'); fs.lstat(p, function(err, stats) { @@ -260,6 +283,7 @@ describe('asar package', function() { return done(); }); }); + it('returns information of a linked directory', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2'); fs.lstat(p, function(err, stats) { @@ -271,6 +295,7 @@ describe('asar package', function() { return done(); }); }); + return it('throws ENOENT error when can not find file', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'file4'); fs.lstat(p, function(err) { @@ -279,97 +304,97 @@ describe('asar package', function() { }); }); }); + describe('fs.realpathSync', function() { it('returns real path root', function() { - var p, parent, r; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = 'a.asar'; - r = fs.realpathSync(path.join(parent, p)); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = 'a.asar'; + var r = fs.realpathSync(path.join(parent, p)); return assert.equal(r, path.join(parent, p)); }); + it('returns real path of a normal file', function() { - var p, parent, r; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'file1'); - r = fs.realpathSync(path.join(parent, p)); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'file1'); + var r = fs.realpathSync(path.join(parent, p)); return assert.equal(r, path.join(parent, p)); }); + it('returns real path of a normal directory', function() { - var p, parent, r; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'dir1'); - r = fs.realpathSync(path.join(parent, p)); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'dir1'); + var r = fs.realpathSync(path.join(parent, p)); return assert.equal(r, path.join(parent, p)); }); + it('returns real path of a linked file', function() { - var p, parent, r; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'link2', 'link1'); - r = fs.realpathSync(path.join(parent, p)); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'link2', 'link1'); + var r = fs.realpathSync(path.join(parent, p)); return assert.equal(r, path.join(parent, 'a.asar', 'file1')); }); + it('returns real path of a linked directory', function() { - var p, parent, r; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'link2', 'link2'); - r = fs.realpathSync(path.join(parent, p)); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'link2', 'link2'); + var r = fs.realpathSync(path.join(parent, p)); return assert.equal(r, path.join(parent, 'a.asar', 'dir1')); }); + return it('throws ENOENT error when can not find file', function() { - var p, parent, throws; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'not-exist'); - throws = function() { + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'not-exist'); + var throws = function() { return fs.realpathSync(path.join(parent, p)); }; return assert.throws(throws, /ENOENT/); }); }); + describe('fs.realpath', function() { it('returns real path root', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = 'a.asar'; + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = 'a.asar'; return fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, p)); return done(); }); }); + it('returns real path of a normal file', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'file1'); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'file1'); return fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, p)); return done(); }); }); + it('returns real path of a normal directory', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'dir1'); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'dir1'); return fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, p)); return done(); }); }); + it('returns real path of a linked file', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'link2', 'link1'); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'link2', 'link1'); return fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, 'a.asar', 'file1')); return done(); }); }); + it('returns real path of a linked directory', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'link2', 'link2'); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'link2', 'link2'); return fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, 'a.asar', 'dir1')); @@ -377,9 +402,8 @@ describe('asar package', function() { }); }); return it('throws ENOENT error when can not find file', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'not-exist'); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'not-exist'); return fs.realpath(path.join(parent, p), function(err) { assert.equal(err.code, 'ENOENT'); return done(); @@ -388,32 +412,32 @@ describe('asar package', function() { }); describe('fs.readdirSync', function() { it('reads dirs from root', function() { - var dirs, p; - p = path.join(fixtures, 'asar', 'a.asar'); - dirs = fs.readdirSync(p); + var p = path.join(fixtures, 'asar', 'a.asar'); + var dirs = fs.readdirSync(p); return assert.deepEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); }); + it('reads dirs from a normal dir', function() { - var dirs, p; - p = path.join(fixtures, 'asar', 'a.asar', 'dir1'); - dirs = fs.readdirSync(p); + var p = path.join(fixtures, 'asar', 'a.asar', 'dir1'); + var dirs = fs.readdirSync(p); return assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); }); + it('reads dirs from a linked dir', function() { - var dirs, p; - p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2'); - dirs = fs.readdirSync(p); + var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2'); + var dirs = fs.readdirSync(p); return assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); }); + return it('throws ENOENT error when can not find file', function() { - var p, throws; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - throws = function() { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var throws = function() { return fs.readdirSync(p); }; return assert.throws(throws, /ENOENT/); }); }); + describe('fs.readdir', function() { it('reads dirs from root', function(done) { var p = path.join(fixtures, 'asar', 'a.asar'); @@ -423,6 +447,7 @@ describe('asar package', function() { return done(); }); }); + it('reads dirs from a normal dir', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'dir1'); fs.readdir(p, function(err, dirs) { @@ -439,15 +464,16 @@ describe('asar package', function() { return done(); }); }); + return it('throws ENOENT error when can not find file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); return fs.readdir(p, function(err) { assert.equal(err.code, 'ENOENT'); return done(); }); }); }); + describe('fs.openSync', function() { it('opens a normal/linked/under-linked-directory file', function() { var buffer, fd, file, j, len, p, ref2, results; @@ -464,19 +490,19 @@ describe('asar package', function() { } return results; }); + return it('throws ENOENT error when can not find file', function() { - var p, throws; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - throws = function() { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var throws = function() { return fs.openSync(p); }; return assert.throws(throws, /ENOENT/); }); }); + describe('fs.open', function() { it('opens a normal file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var p = path.join(fixtures, 'asar', 'a.asar', 'file1'); return fs.open(p, 'r', function(err, fd) { var buffer; assert.equal(err, null); @@ -488,48 +514,48 @@ describe('asar package', function() { }); }); }); + return it('throws ENOENT error when can not find file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); return fs.open(p, 'r', function(err) { assert.equal(err.code, 'ENOENT'); return done(); }); }); }); + describe('fs.mkdir', function() { return it('throws error when calling inside asar archive', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); return fs.mkdir(p, function(err) { assert.equal(err.code, 'ENOTDIR'); return done(); }); }); }); + describe('fs.mkdirSync', function() { return it('throws error when calling inside asar archive', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); return assert.throws((function() { return fs.mkdirSync(p); }), new RegExp('ENOTDIR')); }); }); + describe('child_process.fork', function() { it('opens a normal js file', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'asar', 'a.asar', 'ping.js')); + var child = child_process.fork(path.join(fixtures, 'asar', 'a.asar', 'ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); return done(); }); return child.send('message'); }); + return it('supports asar in the forked js', function(done) { - var child, file; - file = path.join(fixtures, 'asar', 'a.asar', 'file1'); - child = child_process.fork(path.join(fixtures, 'module', 'asar.js')); + var file = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var child = child_process.fork(path.join(fixtures, 'module', 'asar.js')); child.on('message', function(content) { assert.equal(content, fs.readFileSync(file).toString()); return done(); @@ -537,6 +563,7 @@ describe('asar package', function() { return child.send(file); }); }); + describe('child_process.execFile', function() { var echo, execFile, execFileSync, ref2; if (process.platform !== 'darwin') { @@ -544,6 +571,7 @@ describe('asar package', function() { } ref2 = require('child_process'), execFile = ref2.execFile, execFileSync = ref2.execFileSync; echo = path.join(fixtures, 'asar', 'echo.asar', 'echo'); + it('executes binaries', function(done) { execFile(echo, ['test'], function(error, stdout) { assert.equal(error, null); @@ -551,15 +579,17 @@ describe('asar package', function() { return done(); }); }); + return xit('execFileSync executes binaries', function() { var output; output = execFileSync(echo, ['test']); return assert.equal(String(output), 'test\n'); }); }); + describe('internalModuleReadFile', function() { - var internalModuleReadFile; - internalModuleReadFile = process.binding('fs').internalModuleReadFile; + var internalModuleReadFile = process.binding('fs').internalModuleReadFile; + it('read a normal file', function() { var file1, file2, file3; file1 = path.join(fixtures, 'asar', 'a.asar', 'file1'); @@ -569,25 +599,28 @@ describe('asar package', function() { file3 = path.join(fixtures, 'asar', 'a.asar', 'file3'); return assert.equal(internalModuleReadFile(file3).toString().trim(), 'file3'); }); + return it('reads a normal file with unpacked files', function() { var p; p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt'); return assert.equal(internalModuleReadFile(p).toString().trim(), 'a'); }); }); + return describe('process.noAsar', function() { - var errorName; - errorName = process.platform === 'win32' ? 'ENOENT' : 'ENOTDIR'; + var errorName = process.platform === 'win32' ? 'ENOENT' : 'ENOTDIR'; + beforeEach(function() { return process.noAsar = true; }); + afterEach(function() { return process.noAsar = false; }); + it('disables asar support in sync API', function() { - var dir, file; - file = path.join(fixtures, 'asar', 'a.asar', 'file1'); - dir = path.join(fixtures, 'asar', 'a.asar', 'dir1'); + var file = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var dir = path.join(fixtures, 'asar', 'a.asar', 'dir1'); assert.throws((function() { return fs.readFileSync(file); }), new RegExp(errorName)); @@ -601,6 +634,7 @@ describe('asar package', function() { return fs.readdirSync(dir); }), new RegExp(errorName)); }); + it('disables asar support in async API', function(done) { var dir, file; file = path.join(fixtures, 'asar', 'a.asar', 'file1'); @@ -619,6 +653,7 @@ describe('asar package', function() { }); }); }); + return it('treats *.asar as normal file', function() { var asar, content1, content2, originalFs; originalFs = require('original-fs'); @@ -632,44 +667,44 @@ describe('asar package', function() { }); }); }); + describe('asar protocol', function() { - var url; - url = require('url'); + var url = require('url'); + it('can request a file in package', function(done) { - var p; - p = path.resolve(fixtures, 'asar', 'a.asar', 'file1'); + var p = path.resolve(fixtures, 'asar', 'a.asar', 'file1'); return $.get("file://" + p, function(data) { assert.equal(data.trim(), 'file1'); return done(); }); }); + it('can request a file in package with unpacked files', function(done) { - var p; - p = path.resolve(fixtures, 'asar', 'unpack.asar', 'a.txt'); + var p = path.resolve(fixtures, 'asar', 'unpack.asar', 'a.txt'); return $.get("file://" + p, function(data) { assert.equal(data.trim(), 'a'); return done(); }); }); + it('can request a linked file in package', function(done) { - var p; - p = path.resolve(fixtures, 'asar', 'a.asar', 'link2', 'link1'); + var p = path.resolve(fixtures, 'asar', 'a.asar', 'link2', 'link1'); return $.get("file://" + p, function(data) { assert.equal(data.trim(), 'file1'); return done(); }); }); + it('can request a file in filesystem', function(done) { - var p; - p = path.resolve(fixtures, 'asar', 'file'); + var p = path.resolve(fixtures, 'asar', 'file'); return $.get("file://" + p, function(data) { assert.equal(data.trim(), 'file'); return done(); }); }); + it('gets 404 when file is not found', function(done) { - var p; - p = path.resolve(fixtures, 'asar', 'a.asar', 'no-exist'); + var p = path.resolve(fixtures, 'asar', 'a.asar', 'no-exist'); return $.ajax({ url: "file://" + p, error: function(err) { @@ -678,19 +713,20 @@ describe('asar package', function() { } }); }); + it('sets __dirname correctly', function(done) { - var p, u, w; after(function() { w.destroy(); return ipcMain.removeAllListeners('dirname'); }); - w = new BrowserWindow({ + + var w = new BrowserWindow({ show: false, width: 400, height: 400 }); - p = path.resolve(fixtures, 'asar', 'web.asar', 'index.html'); - u = url.format({ + var p = path.resolve(fixtures, 'asar', 'web.asar', 'index.html'); + var u = url.format({ protocol: 'file', slashed: true, pathname: p @@ -701,19 +737,20 @@ describe('asar package', function() { }); return w.loadURL(u); }); + return it('loads script tag in html', function(done) { - var p, u, w; after(function() { w.destroy(); return ipcMain.removeAllListeners('ping'); }); - w = new BrowserWindow({ + + var w = new BrowserWindow({ show: false, width: 400, height: 400 }); - p = path.resolve(fixtures, 'asar', 'script.asar', 'index.html'); - u = url.format({ + var p = path.resolve(fixtures, 'asar', 'script.asar', 'index.html'); + var u = url.format({ protocol: 'file', slashed: true, pathname: p @@ -725,15 +762,17 @@ describe('asar package', function() { }); }); }); + describe('original-fs module', function() { - var originalFs; - originalFs = require('original-fs'); + var originalFs = require('original-fs'); + it('treats .asar as file', function() { var file, stats; file = path.join(fixtures, 'asar', 'a.asar'); stats = originalFs.statSync(file); return assert(stats.isFile()); }); + return it('is available in forked scripts', function(done) { var child; child = child_process.fork(path.join(fixtures, 'module', 'original-fs.js')); @@ -744,9 +783,10 @@ describe('asar package', function() { return child.send('message'); }); }); + describe('graceful-fs module', function() { - var gfs; - gfs = require('graceful-fs'); + var gfs = require('graceful-fs'); + it('recognize asar archvies', function() { var p; p = path.join(fixtures, 'asar', 'a.asar', 'link1'); @@ -756,9 +796,10 @@ describe('asar package', function() { return assert.notEqual(fs.readdir, gfs.readdir); }); }); + describe('mkdirp module', function() { - var mkdirp; - mkdirp = require('mkdirp'); + var mkdirp = require('mkdirp'); + return it('throws error when calling inside asar archive', function() { var p; p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); @@ -767,20 +808,20 @@ describe('asar package', function() { }), new RegExp('ENOTDIR')); }); }); + return describe('native-image', function() { it('reads image from asar archive', function() { - var logo, p; - p = path.join(fixtures, 'asar', 'logo.asar', 'logo.png'); - logo = nativeImage.createFromPath(p); + var p = path.join(fixtures, 'asar', 'logo.asar', 'logo.png'); + var logo = nativeImage.createFromPath(p); return assert.deepEqual(logo.getSize(), { width: 55, height: 55 }); }); + return it('reads image from asar archive with unpacked files', function() { - var logo, p; - p = path.join(fixtures, 'asar', 'unpack.asar', 'atom.png'); - logo = nativeImage.createFromPath(p); + var p = path.join(fixtures, 'asar', 'unpack.asar', 'atom.png'); + var logo = nativeImage.createFromPath(p); return assert.deepEqual(logo.getSize(), { width: 1024, height: 1024 diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 56fa21c89a7..21cefb0b0bc 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -8,20 +8,22 @@ const BrowserWindow = remote.require('electron').BrowserWindow; const session = remote.require('electron').session; describe('chromium feature', function() { - var fixtures, listener; - fixtures = path.resolve(__dirname, 'fixtures'); - listener = null; + var fixtures = path.resolve(__dirname, 'fixtures'); + var listener = null; + afterEach(function() { if (listener != null) { window.removeEventListener('message', listener); } return listener = null; }); + xdescribe('heap snapshot', function() { return it('does not crash', function() { return process.atomBinding('v8_util').takeHeapSnapshot(); }); }); + describe('sending request of http protocol urls', function() { return it('does not crash', function(done) { var server; @@ -38,13 +40,15 @@ describe('chromium feature', function() { }); }); }); + describe('document.hidden', function() { - var url, w; - url = "file://" + fixtures + "/pages/document-hidden.html"; - w = null; + var url = "file://" + fixtures + "/pages/document-hidden.html"; + var w = null; + afterEach(function() { return w != null ? w.destroy() : void 0; }); + it('is set correctly when window is not shown', function(done) { w = new BrowserWindow({ show: false @@ -55,6 +59,7 @@ describe('chromium feature', function() { }); return w.loadURL(url); }); + return it('is set correctly when window is inactive', function(done) { w = new BrowserWindow({ show: false @@ -67,6 +72,7 @@ describe('chromium feature', function() { return w.loadURL(url); }); }); + xdescribe('navigator.webkitGetUserMedia', function() { return it('calls its callbacks', function(done) { this.timeout(5000); @@ -80,18 +86,21 @@ describe('chromium feature', function() { }); }); }); + describe('navigator.language', function() { return it('should not be empty', function() { return assert.notEqual(navigator.language, ''); }); }); + describe('navigator.serviceWorker', function() { - var url, w; - url = "file://" + fixtures + "/pages/service-worker/index.html"; - w = null; + var url = "file://" + fixtures + "/pages/service-worker/index.html"; + var w = null; + afterEach(function() { return w != null ? w.destroy() : void 0; }); + return it('should register for file scheme', function(done) { w = new BrowserWindow({ show: false @@ -113,8 +122,10 @@ describe('chromium feature', function() { return w.loadURL(url); }); }); + describe('window.open', function() { this.timeout(20000); + it('returns a BrowserWindowProxy object', function() { var b; b = window.open('about:blank', '', 'show=no'); @@ -122,6 +133,7 @@ describe('chromium feature', function() { assert.equal(b.constructor.name, 'BrowserWindowProxy'); return b.close(); }); + it('accepts "node-integration" as feature', function(done) { var b; listener = function(event) { @@ -132,6 +144,7 @@ describe('chromium feature', function() { window.addEventListener('message', listener); return b = window.open("file://" + fixtures + "/pages/window-opener-node.html", '', 'nodeIntegration=no,show=no'); }); + it('inherit options of parent window', function(done) { var b; listener = function(event) { @@ -144,6 +157,7 @@ describe('chromium feature', function() { window.addEventListener('message', listener); return b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', 'show=no'); }); + return it('does not override child options', function(done) { var b, size; size = { @@ -159,6 +173,7 @@ describe('chromium feature', function() { return b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', "show=no,width=" + size.width + ",height=" + size.height); }); }); + describe('window.opener', function() { var url, w; this.timeout(10000); @@ -188,6 +203,7 @@ describe('chromium feature', function() { return b = window.open(url, '', 'show=no'); }); }); + describe('window.postMessage', function() { return it('sets the source and origin correctly', function(done) { var b, sourceId; @@ -211,6 +227,7 @@ describe('chromium feature', function() { }); }); }); + describe('window.opener.postMessage', function() { return it('sets source and origin correctly', function(done) { var b; @@ -225,6 +242,7 @@ describe('chromium feature', function() { return b = window.open("file://" + fixtures + "/pages/window-opener-postMessage.html", '', 'show=no'); }); }); + describe('creating a Uint8Array under browser side', function() { return it('does not crash', function() { var RUint8Array; @@ -232,6 +250,7 @@ describe('chromium feature', function() { return new RUint8Array; }); }); + describe('webgl', function() { return it('can be get as context in canvas', function() { var webgl; @@ -242,6 +261,7 @@ describe('chromium feature', function() { return assert.notEqual(webgl, null); }); }); + describe('web workers', function() { it('Worker can work', function(done) { var message, worker; @@ -254,6 +274,7 @@ describe('chromium feature', function() { }; return worker.postMessage(message); }); + return it('SharedWorker can work', function(done) { var message, worker; worker = new SharedWorker('../fixtures/workers/shared_worker.js'); @@ -265,15 +286,18 @@ describe('chromium feature', function() { return worker.port.postMessage(message); }); }); + describe('iframe', function() { - var iframe; - iframe = null; + var iframe = null; + beforeEach(function() { return iframe = document.createElement('iframe'); }); + afterEach(function() { return document.body.removeChild(iframe); }); + return it('does not have node integration', function(done) { iframe.src = "file://" + fixtures + "/pages/set-global.html"; document.body.appendChild(iframe); @@ -283,6 +307,7 @@ describe('chromium feature', function() { }; }); }); + describe('storage', function() { return it('requesting persitent quota works', function(done) { return navigator.webkitPersistentStorage.requestQuota(1024 * 1024, function(grantedBytes) { @@ -291,15 +316,17 @@ describe('chromium feature', function() { }); }); }); + describe('websockets', function() { - var WebSocketServer, server, wss; - wss = null; - server = null; - WebSocketServer = ws.Server; + var wss = null; + var server = null; + var WebSocketServer = ws.Server; + afterEach(function() { wss.close(); return server.close(); }); + return it('has user agent', function(done) { server = http.createServer(); return server.listen(0, '127.0.0.1', function() { @@ -319,6 +346,7 @@ describe('chromium feature', function() { }); }); }); + return describe('Promise', function() { it('resolves correctly in Node.js calls', function(done) { document.registerElement('x-element', { @@ -338,6 +366,7 @@ describe('chromium feature', function() { return called = true; }); }); + return it('resolves correctly in Electron calls', function(done) { document.registerElement('y-element', { prototype: Object.create(HTMLElement.prototype, { diff --git a/spec/modules-spec.js b/spec/modules-spec.js index 6a0471e4cea..e3d5bd75c6d 100644 --- a/spec/modules-spec.js +++ b/spec/modules-spec.js @@ -3,14 +3,15 @@ const path = require('path'); const temp = require('temp'); describe('third-party module', function() { - var fixtures; - fixtures = path.join(__dirname, 'fixtures'); + var fixtures = path.join(__dirname, 'fixtures'); temp.track(); + if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) { describe('runas', function() { it('can be required in renderer', function() { return require('runas'); }); + return it('can be required in node binary', function(done) { var child, runas; runas = path.join(fixtures, 'module', 'runas.js'); @@ -21,6 +22,7 @@ describe('third-party module', function() { }); }); }); + describe('ffi', function() { return it('does not crash', function() { var ffi, libm; @@ -32,6 +34,7 @@ describe('third-party module', function() { }); }); } + return describe('q', function() { var Q; Q = require('q'); diff --git a/spec/node-spec.js b/spec/node-spec.js index 6f84f59921f..9ead9202653 100644 --- a/spec/node-spec.js +++ b/spec/node-spec.js @@ -6,8 +6,8 @@ const os = require('os'); const remote = require('electron').remote; describe('node feature', function() { - var fixtures; - fixtures = path.join(__dirname, 'fixtures'); + var fixtures = path.join(__dirname, 'fixtures'); + describe('child_process', function() { return describe('child_process.fork', function() { it('works in current process', function(done) { @@ -19,6 +19,7 @@ describe('node feature', function() { }); return child.send('message'); }); + it('preserves args', function(done) { var args, child; args = ['--expose_gc', '-test', '1']; @@ -29,6 +30,7 @@ describe('node feature', function() { }); return child.send('message'); }); + it('works in forked process', function(done) { var child; child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js')); @@ -38,6 +40,7 @@ describe('node feature', function() { }); return child.send('message'); }); + it('works in forked process when options.env is specifed', function(done) { var child; child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js'), [], { @@ -49,6 +52,7 @@ describe('node feature', function() { }); return child.send('message'); }); + it('works in browser process', function(done) { var child, fork; fork = remote.require('child_process').fork; @@ -59,6 +63,7 @@ describe('node feature', function() { }); return child.send('message'); }); + it('has String::localeCompare working in script', function(done) { var child; child = child_process.fork(path.join(fixtures, 'module', 'locale-compare.js')); @@ -68,6 +73,7 @@ describe('node feature', function() { }); return child.send('message'); }); + return it('has setImmediate working in script', function(done) { var child; child = child_process.fork(path.join(fixtures, 'module', 'set-immediate.js')); @@ -79,17 +85,20 @@ describe('node feature', function() { }); }); }); + describe('contexts', function() { describe('setTimeout in fs callback', function() { if (process.env.TRAVIS === 'true') { return; } + return it('does not crash', function(done) { return fs.readFile(__filename, function() { return setTimeout(done, 0); }); }); }); + describe('throw error in node context', function() { return it('gets caught', function(done) { var error, lsts; @@ -110,11 +119,13 @@ describe('node feature', function() { }); }); }); + describe('setTimeout called under Chromium event loop in browser process', function() { return it('can be scheduled in time', function(done) { return remote.getGlobal('setTimeout')(done, 0); }); }); + return describe('setInterval called under Chromium event loop in browser process', function() { return it('can be scheduled in time', function(done) { var clear, interval; @@ -126,11 +137,13 @@ describe('node feature', function() { }); }); }); + describe('message loop', function() { describe('process.nextTick', function() { it('emits the callback', function(done) { return process.nextTick(done); }); + return it('works in nested calls', function(done) { return process.nextTick(function() { return process.nextTick(function() { @@ -139,10 +152,12 @@ describe('node feature', function() { }); }); }); + return describe('setImmediate', function() { it('emits the callback', function(done) { return setImmediate(done); }); + return it('works in nested calls', function(done) { return setImmediate(function() { return setImmediate(function() { @@ -152,10 +167,12 @@ describe('node feature', function() { }); }); }); + describe('net.connect', function() { if (process.platform !== 'darwin') { return; } + return it('emit error when connect to a socket path without listeners', function(done) { var child, script, socketPath; socketPath = path.join(os.tmpdir(), 'atom-shell-test.sock'); @@ -172,6 +189,7 @@ describe('node feature', function() { }); }); }); + describe('Buffer', function() { it('can be created from WebKit external string', function() { var b, p; @@ -181,6 +199,7 @@ describe('node feature', function() { assert.equal(b.toString(), '闲云潭影日悠悠,物换星移几度秋'); return assert.equal(Buffer.byteLength(p.innerText), 45); }); + return it('correctly parses external one-byte UTF8 string', function() { var b, p; p = document.createElement('p'); From 12adaa0570e6d8ef6a64272027d4a622ea8bc17e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Feb 2016 17:39:11 -0800 Subject: [PATCH 097/173] Remove unneeded returns --- spec/api-app-spec.js | 50 ++--- spec/api-clipboard-spec.js | 46 ++-- spec/api-crash-reporter-spec.js | 22 +- spec/api-ipc-spec.js | 57 +++-- spec/api-menu-spec.js | 46 ++-- spec/api-protocol-spec.js | 384 ++++++++++++++++---------------- spec/api-screen-spec.js | 10 +- spec/api-session-spec.js | 88 ++++---- spec/api-web-frame-spec.js | 12 +- spec/api-web-request-spec.js | 185 ++++++++------- spec/asar-spec.js | 376 +++++++++++++++---------------- spec/chromium-spec.js | 177 +++++++-------- spec/modules-spec.js | 35 ++- spec/node-spec.js | 111 +++++---- 14 files changed, 773 insertions(+), 826 deletions(-) diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index ea305ae9535..7b2535d5404 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -23,38 +23,38 @@ describe('electron module', function() { describe('app module', function() { describe('app.getVersion()', function() { - return it('returns the version field of package.json', function() { - return assert.equal(app.getVersion(), '0.1.0'); + it('returns the version field of package.json', function() { + assert.equal(app.getVersion(), '0.1.0'); }); }); describe('app.setVersion(version)', function() { - return it('overrides the version', function() { + it('overrides the version', function() { assert.equal(app.getVersion(), '0.1.0'); app.setVersion('test-version'); assert.equal(app.getVersion(), 'test-version'); - return app.setVersion('0.1.0'); + app.setVersion('0.1.0'); }); }); describe('app.getName()', function() { - return it('returns the name field of package.json', function() { - return assert.equal(app.getName(), 'Electron Test'); + it('returns the name field of package.json', function() { + assert.equal(app.getName(), 'Electron Test'); }); }); describe('app.setName(name)', function() { - return it('overrides the name', function() { + it('overrides the name', function() { assert.equal(app.getName(), 'Electron Test'); app.setName('test-name'); assert.equal(app.getName(), 'test-name'); - return app.setName('Electron Test'); + app.setName('Electron Test'); }); }); describe('app.getLocale()', function() { - return it('should not be empty', function() { - return assert.notEqual(app.getLocale(), ''); + it('should not be empty', function() { + assert.notEqual(app.getLocale(), ''); }); }); @@ -62,71 +62,71 @@ describe('app module', function() { var appProcess = null; afterEach(function() { - return appProcess != null ? appProcess.kill() : void 0; + appProcess != null ? appProcess.kill() : void 0; }); - return it('emits a process exit event with the code', function(done) { + it('emits a process exit event with the code', function(done) { var appPath, electronPath, output; appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app'); electronPath = remote.getGlobal('process').execPath; appProcess = ChildProcess.spawn(electronPath, [appPath]); output = ''; appProcess.stdout.on('data', function(data) { - return output += data; + output += data; }); - return appProcess.on('close', function(code) { + appProcess.on('close', function(code) { if (process.platform !== 'win32') { assert.notEqual(output.indexOf('Exit event with code: 123'), -1); } assert.equal(code, 123); - return done(); + done(); }); }); }); - return describe('BrowserWindow events', function() { + describe('BrowserWindow events', function() { var w = null; afterEach(function() { if (w != null) { w.destroy(); } - return w = null; + w = null; }); it('should emit browser-window-focus event when window is focused', function(done) { app.once('browser-window-focus', function(e, window) { assert.equal(w.id, window.id); - return done(); + done(); }); w = new BrowserWindow({ show: false }); - return w.emit('focus'); + w.emit('focus'); }); it('should emit browser-window-blur event when window is blured', function(done) { app.once('browser-window-blur', function(e, window) { assert.equal(w.id, window.id); - return done(); + done(); }); w = new BrowserWindow({ show: false }); - return w.emit('blur'); + w.emit('blur'); }); - return it('should emit browser-window-created event when window is created', function(done) { + it('should emit browser-window-created event when window is created', function(done) { app.once('browser-window-created', function(e, window) { - return setImmediate(function() { + setImmediate(function() { assert.equal(w.id, window.id); - return done(); + done(); }); }); w = new BrowserWindow({ show: false }); - return w.emit('blur'); + w.emit('blur'); }); }); }); diff --git a/spec/api-clipboard-spec.js b/spec/api-clipboard-spec.js index 28afb4a5307..0b4a9f9521c 100644 --- a/spec/api-clipboard-spec.js +++ b/spec/api-clipboard-spec.js @@ -8,50 +8,46 @@ describe('clipboard module', function() { var fixtures = path.resolve(__dirname, 'fixtures'); describe('clipboard.readImage()', function() { - return it('returns NativeImage intance', function() { - var i, p; - p = path.join(fixtures, 'assets', 'logo.png'); - i = nativeImage.createFromPath(p); + it('returns NativeImage intance', function() { + var p = path.join(fixtures, 'assets', 'logo.png'); + var i = nativeImage.createFromPath(p); clipboard.writeImage(p); - return assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); + assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); }); }); describe('clipboard.readText()', function() { - return it('returns unicode string correctly', function() { - var text; - text = '千江有水千江月,万里无云万里天'; + it('returns unicode string correctly', function() { + var text = '千江有水千江月,万里无云万里天'; clipboard.writeText(text); - return assert.equal(clipboard.readText(), text); + assert.equal(clipboard.readText(), text); }); }); describe('clipboard.readHtml()', function() { - return it('returns markup correctly', function() { - var markup, text; - text = 'Hi'; - markup = process.platform === 'darwin' ? 'Hi' : process.platform === 'linux' ? 'Hi' : 'Hi'; + it('returns markup correctly', function() { + var text = 'Hi'; + var markup = process.platform === 'darwin' ? 'Hi' : process.platform === 'linux' ? 'Hi' : 'Hi'; clipboard.writeHtml(text); - return assert.equal(clipboard.readHtml(), markup); + assert.equal(clipboard.readHtml(), markup); }); }); describe('clipboard.readRtf', function() { - return it('returns rtf text correctly', function() { + it('returns rtf text correctly', function() { var rtf = "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}"; clipboard.writeRtf(rtf); - return assert.equal(clipboard.readRtf(), rtf); + assert.equal(clipboard.readRtf(), rtf); }); }); - return describe('clipboard.write()', function() { - return it('returns data correctly', function() { - var i, markup, p, text, rtf; - text = 'test'; - rtf = '{\\rtf1\\utf8 text}'; - p = path.join(fixtures, 'assets', 'logo.png'); - i = nativeImage.createFromPath(p); - markup = process.platform === 'darwin' ? 'Hi' : process.platform === 'linux' ? 'Hi' : 'Hi'; + describe('clipboard.write()', function() { + it('returns data correctly', function() { + var text = 'test'; + var rtf = '{\\rtf1\\utf8 text}'; + var p = path.join(fixtures, 'assets', 'logo.png'); + var i = nativeImage.createFromPath(p); + var markup = process.platform === 'darwin' ? 'Hi' : process.platform === 'linux' ? 'Hi' : 'Hi'; clipboard.write({ text: "test", html: 'Hi', @@ -61,7 +57,7 @@ describe('clipboard module', function() { assert.equal(clipboard.readText(), text); assert.equal(clipboard.readHtml(), markup); assert.equal(clipboard.readRtf(), rtf); - return assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); + assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); }); }); }); diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index 72662aa3d93..43830dd4ee1 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -14,13 +14,13 @@ describe('crash-reporter module', function() { var w = null; beforeEach(function() { - return w = new BrowserWindow({ + w = new BrowserWindow({ show: false }); }); afterEach(function() { - return w.destroy(); + w.destroy(); }); if (process.mas) { @@ -40,7 +40,7 @@ describe('crash-reporter module', function() { var form; server.close(); form = new multiparty.Form(); - return form.parse(req, function(error, fields) { + form.parse(req, function(error, fields) { if (called) { return; } @@ -55,11 +55,11 @@ describe('crash-reporter module', function() { assert.equal(fields['_companyName'], 'Umbrella Corporation'); assert.equal(fields['_version'], app.getVersion()); res.end('abc-123-def'); - return done(); + done(); }); }); var port = remote.process.port; - return server.listen(port, '127.0.0.1', function() { + server.listen(port, '127.0.0.1', function() { port = server.address().port; remote.process.port = port; const crashUrl = url.format({ @@ -73,19 +73,19 @@ describe('crash-reporter module', function() { submitURL: "http://127.0.0.1:" + port }); } - return w.loadURL(crashUrl); + w.loadURL(crashUrl); }); }); - return describe(".start(options)", function() { - return it('requires that the companyName and submitURL options be specified', function() { + describe(".start(options)", function() { + it('requires that the companyName and submitURL options be specified', function() { assert.throws(function() { - return crashReporter.start({ + crashReporter.start({ companyName: 'Missing submitURL' }); }); - return assert.throws(function() { - return crashReporter.start({ + assert.throws(function() { + crashReporter.start({ submitURL: 'Missing companyName' }); }); diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index 6b1c99779b2..25d8c925688 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -12,7 +12,7 @@ const comparePaths = function(path1, path2) { path1 = path1.toLowerCase(); path2 = path2.toLowerCase(); } - return assert.equal(path1, path2); + assert.equal(path1, path2); }; describe('ipc module', function() { @@ -23,27 +23,26 @@ describe('ipc module', function() { var dialog1, dialog2; dialog1 = remote.require('electron'); dialog2 = remote.require('electron'); - return assert.equal(dialog1, dialog2); + assert.equal(dialog1, dialog2); }); it('should work when object contains id property', function() { - var a; - a = remote.require(path.join(fixtures, 'module', 'id.js')); - return assert.equal(a.id, 1127); + var a = remote.require(path.join(fixtures, 'module', 'id.js')); + assert.equal(a.id, 1127); }); - return it('should search module from the user app', function() { + it('should search module from the user app', function() { comparePaths(path.normalize(remote.process.mainModule.filename), path.resolve(__dirname, 'static', 'main.js')); - return comparePaths(path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules')); + comparePaths(path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules')); }); }); describe('remote.createFunctionWithReturnValue', function() { - return it('should be called in browser synchronously', function() { + it('should be called in browser synchronously', function() { var buf = new Buffer('test'); var call = remote.require(path.join(fixtures, 'module', 'call.js')); var result = call.call(remote.createFunctionWithReturnValue(buf)); - return assert.equal(result.constructor.name, 'Buffer'); + assert.equal(result.constructor.name, 'Buffer'); }); }); @@ -55,14 +54,14 @@ describe('ipc module', function() { assert.equal(property.property, 1007); var property2 = remote.require(path.join(fixtures, 'module', 'property.js')); assert.equal(property2.property, 1007); - return property.property = 1127; + property.property = 1127; }); - return it('can construct an object from its member', function() { + it('can construct an object from its member', function() { var call, obj; call = remote.require(path.join(fixtures, 'module', 'call.js')); obj = new call.constructor; - return assert.equal(obj.test, 'test'); + assert.equal(obj.test, 'test'); }); }); @@ -72,48 +71,48 @@ describe('ipc module', function() { it('keeps its constructor name for objects', function() { var buf = new Buffer('test'); var print_name = remote.require(print); - return assert.equal(print_name.print(buf), 'Buffer'); + assert.equal(print_name.print(buf), 'Buffer'); }); - return it('supports instanceof Date', function() { + it('supports instanceof Date', function() { var now = new Date(); var print_name = remote.require(print); assert.equal(print_name.print(now), 'Date'); - return assert.deepEqual(print_name.echo(now), now); + assert.deepEqual(print_name.echo(now), now); }); }); describe('remote promise', function() { - return it('can be used as promise in each side', function(done) { + it('can be used as promise in each side', function(done) { var promise = remote.require(path.join(fixtures, 'module', 'promise.js')); - return promise.twicePromise(Promise.resolve(1234)).then(function(value) { + promise.twicePromise(Promise.resolve(1234)).then(function(value) { assert.equal(value, 2468); - return done(); + done(); }); }); }); describe('ipc.sender.send', function() { - return it('should work when sending an object containing id property', function(done) { + it('should work when sending an object containing id property', function(done) { var obj = { id: 1, name: 'ly' }; ipcRenderer.once('message', function(event, message) { assert.deepEqual(message, obj); - return done(); + done(); }); - return ipcRenderer.send('message', obj); + ipcRenderer.send('message', obj); }); }); describe('ipc.sendSync', function() { it('can be replied by setting event.returnValue', function() { var msg = ipcRenderer.sendSync('echo', 'test'); - return assert.equal(msg, 'test'); + assert.equal(msg, 'test'); }); - return it('does not crash when reply is not sent and browser is destroyed', function(done) { + it('does not crash when reply is not sent and browser is destroyed', function(done) { this.timeout(10000); var w = new BrowserWindow({ @@ -122,20 +121,20 @@ describe('ipc module', function() { ipcMain.once('send-sync-message', function(event) { event.returnValue = null; w.destroy(); - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'send-sync-message.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'send-sync-message.html')); }); }); - return describe('remote listeners', function() { + describe('remote listeners', function() { var w = null; afterEach(function() { - return w.destroy(); + w.destroy(); }); - return it('can be added and removed correctly', function() { + it('can be added and removed correctly', function() { w = new BrowserWindow({ show: false }); @@ -143,7 +142,7 @@ describe('ipc module', function() { w.on('test', listener); assert.equal(w.listenerCount('test'), 1); w.removeListener('test', listener); - return assert.equal(w.listenerCount('test'), 0); + assert.equal(w.listenerCount('test'), 0); }); }); }); diff --git a/spec/api-menu-spec.js b/spec/api-menu-spec.js index 292a65a0f08..60464c73275 100644 --- a/spec/api-menu-spec.js +++ b/spec/api-menu-spec.js @@ -15,12 +15,12 @@ describe('menu module', function() { extra: 'field' } ]); - return assert.equal(menu.items[0].extra, 'field'); + assert.equal(menu.items[0].extra, 'field'); }); it('does not modify the specified template', function() { var template = ipcRenderer.sendSync('eval', "var template = [{label: 'text', submenu: [{label: 'sub'}]}];\nrequire('electron').Menu.buildFromTemplate(template);\ntemplate;"); - return assert.deepStrictEqual(template, [ + assert.deepStrictEqual(template, [ { label: 'text', submenu: [ @@ -32,7 +32,7 @@ describe('menu module', function() { ]); }); - return describe('Menu.buildFromTemplate should reorder based on item position specifiers', function() { + describe('Menu.buildFromTemplate should reorder based on item position specifiers', function() { it('should position before existing item', function() { var menu = Menu.buildFromTemplate([ { @@ -49,7 +49,7 @@ describe('menu module', function() { ]); assert.equal(menu.items[0].label, '1'); assert.equal(menu.items[1].label, '2'); - return assert.equal(menu.items[2].label, '3'); + assert.equal(menu.items[2].label, '3'); }); it('should position after existing item', function() { @@ -68,7 +68,7 @@ describe('menu module', function() { ]); assert.equal(menu.items[0].label, '1'); assert.equal(menu.items[1].label, '2'); - return assert.equal(menu.items[2].label, '3'); + assert.equal(menu.items[2].label, '3'); }); it('should position at endof existing separator groups', function() { @@ -112,7 +112,7 @@ describe('menu module', function() { assert.equal(menu.items[4].id, 'letters'); assert.equal(menu.items[5].label, 'a'); assert.equal(menu.items[6].label, 'b'); - return assert.equal(menu.items[7].label, 'c'); + assert.equal(menu.items[7].label, 'c'); }); it('should create separator group if endof does not reference existing separator group', function() { @@ -150,10 +150,10 @@ describe('menu module', function() { assert.equal(menu.items[4].id, 'numbers'); assert.equal(menu.items[5].label, '1'); assert.equal(menu.items[6].label, '2'); - return assert.equal(menu.items[7].label, '3'); + assert.equal(menu.items[7].label, '3'); }); - return it('should continue inserting items at next index when no specifier is present', function() { + it('should continue inserting items at next index when no specifier is present', function() { var menu = Menu.buildFromTemplate([ { label: '4', @@ -177,13 +177,13 @@ describe('menu module', function() { assert.equal(menu.items[1].label, '2'); assert.equal(menu.items[2].label, '3'); assert.equal(menu.items[3].label, '4'); - return assert.equal(menu.items[4].label, '5'); + assert.equal(menu.items[4].label, '5'); }); }); }); describe('Menu.insert', function() { - return it('should store item in @items by its index', function() { + it('should store item in @items by its index', function() { var menu = Menu.buildFromTemplate([ { label: '1' @@ -200,27 +200,27 @@ describe('menu module', function() { assert.equal(menu.items[0].label, '1'); assert.equal(menu.items[1].label, 'inserted'); assert.equal(menu.items[2].label, '2'); - return assert.equal(menu.items[3].label, '3'); + assert.equal(menu.items[3].label, '3'); }); }); describe('MenuItem.click', function() { - return it('should be called with the item object passed', function(done) { + it('should be called with the item object passed', function(done) { var menu = Menu.buildFromTemplate([ { label: 'text', click: function(item) { assert.equal(item.constructor.name, 'MenuItem'); assert.equal(item.label, 'text'); - return done(); + done(); } } ]); - return menu.delegate.executeCommand(menu.items[0].commandId); + menu.delegate.executeCommand(menu.items[0].commandId); }); }); - return describe('MenuItem with checked property', function() { + describe('MenuItem with checked property', function() { it('clicking an checkbox item should flip the checked property', function() { var menu = Menu.buildFromTemplate([ { @@ -230,7 +230,7 @@ describe('menu module', function() { ]); assert.equal(menu.items[0].checked, false); menu.delegate.executeCommand(menu.items[0].commandId); - return assert.equal(menu.items[0].checked, true); + assert.equal(menu.items[0].checked, true); }); it('clicking an radio item should always make checked property true', function() { @@ -243,7 +243,7 @@ describe('menu module', function() { menu.delegate.executeCommand(menu.items[0].commandId); assert.equal(menu.items[0].checked, true); menu.delegate.executeCommand(menu.items[0].commandId); - return assert.equal(menu.items[0].checked, true); + assert.equal(menu.items[0].checked, true); }); it('at least have one item checked in each group', function() { @@ -267,7 +267,7 @@ describe('menu module', function() { menu = Menu.buildFromTemplate(template); menu.delegate.menuWillShow(); assert.equal(menu.items[0].checked, true); - return assert.equal(menu.items[12].checked, true); + assert.equal(menu.items[12].checked, true); }); it('should assign groupId automatically', function() { @@ -293,14 +293,12 @@ describe('menu module', function() { for (i = l = 0; l <= 10; i = ++l) { assert.equal(menu.items[i].groupId, groupId); } - results = []; for (i = m = 12; m <= 20; i = ++m) { - results.push(assert.equal(menu.items[i].groupId, groupId + 1)); + assert.equal(menu.items[i].groupId, groupId + 1); } - return results; }); - return it("setting 'checked' should flip other items' 'checked' property", function() { + it("setting 'checked' should flip other items' 'checked' property", function() { var i, j, k, l, m, menu, n, o, p, q, results, template; template = []; for (i = j = 0; j <= 10; i = ++j) { @@ -341,11 +339,9 @@ describe('menu module', function() { assert.equal(menu.items[i].checked, false); } assert.equal(menu.items[12].checked, true); - results = []; for (i = q = 13; q <= 20; i = ++q) { - results.push(assert.equal(menu.items[i].checked, false)); + assert.equal(menu.items[i].checked, false); } - return results; }); }); }); diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index 6426e3312ec..a7de60d8c36 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -14,24 +14,24 @@ describe('protocol module', function() { }; afterEach(function(done) { - return protocol.unregisterProtocol(protocolName, function() { - return protocol.uninterceptProtocol('http', function() { - return done(); + protocol.unregisterProtocol(protocolName, function() { + protocol.uninterceptProtocol('http', function() { + done(); }); }); }); describe('protocol.register(Any)Protocol', function() { var emptyHandler = function(request, callback) { - return callback(); + callback(); }; it('throws error when scheme is already registered', function(done) { - return protocol.registerStringProtocol(protocolName, emptyHandler, function(error) { + protocol.registerStringProtocol(protocolName, emptyHandler, function(error) { assert.equal(error, null); - return protocol.registerBufferProtocol(protocolName, emptyHandler, function(error) { + protocol.registerBufferProtocol(protocolName, emptyHandler, function(error) { assert.notEqual(error, null); - return done(); + done(); }); }); }); @@ -40,34 +40,34 @@ describe('protocol module', function() { var doubleHandler = function(request, callback) { try { callback(text); - return callback(); + callback(); } catch (error) { // Ignore error } }; - return protocol.registerStringProtocol(protocolName, doubleHandler, function(error) { + protocol.registerStringProtocol(protocolName, doubleHandler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); it('sends error when callback is called with nothing', function(done) { - return protocol.registerBufferProtocol(protocolName, emptyHandler, function(error) { + protocol.registerBufferProtocol(protocolName, emptyHandler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { return done('request succeeded but it should not'); @@ -80,24 +80,24 @@ describe('protocol module', function() { }); }); - return it('does not crash when callback is called in next tick', function(done) { + it('does not crash when callback is called in next tick', function(done) { var handler = function(request, callback) { - return setImmediate(function() { - return callback(text); + setImmediate(function() { + callback(text); }); }; - return protocol.registerStringProtocol(protocolName, handler, function(error) { + protocol.registerStringProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -105,10 +105,10 @@ describe('protocol module', function() { }); describe('protocol.unregisterProtocol', function() { - return it('returns error when scheme does not exist', function(done) { - return protocol.unregisterProtocol('not-exist', function(error) { + it('returns error when scheme does not exist', function(done) { + protocol.unregisterProtocol('not-exist', function(error) { assert.notEqual(error, null); - return done(); + done(); }); }); }); @@ -116,9 +116,9 @@ describe('protocol module', function() { describe('protocol.registerStringProtocol', function() { it('sends string as response', function(done) { var handler = function(request, callback) { - return callback(text); + callback(text); }; - return protocol.registerStringProtocol(protocolName, handler, function(error) { + protocol.registerStringProtocol(protocolName, handler, function(error) { if (error) { return done(error); } @@ -126,10 +126,10 @@ describe('protocol module', function() { url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -137,21 +137,21 @@ describe('protocol module', function() { it('sets Access-Control-Allow-Origin', function(done) { var handler = function(request, callback) { - return callback(text); + callback(text); }; - return protocol.registerStringProtocol(protocolName, handler, function(error) { + protocol.registerStringProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data, status, request) { assert.equal(data, text); assert.equal(request.getResponseHeader('Access-Control-Allow-Origin'), '*'); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -159,44 +159,44 @@ describe('protocol module', function() { it('sends object as response', function(done) { var handler = function(request, callback) { - return callback({ + callback({ data: text, mimeType: 'text/html' }); }; - return protocol.registerStringProtocol(protocolName, handler, function(error) { + protocol.registerStringProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); - return it('fails when sending object other than string', function(done) { + it('fails when sending object other than string', function(done) { var handler = function(request, callback) { - return callback(new Date); + callback(new Date); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); @@ -208,20 +208,20 @@ describe('protocol module', function() { it('sends Buffer as response', function(done) { var handler = function(request, callback) { - return callback(buffer); + callback(buffer); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -229,22 +229,22 @@ describe('protocol module', function() { it('sets Access-Control-Allow-Origin', function(done) { var handler = function(request, callback) { - return callback(buffer); + callback(buffer); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data, status, request) { assert.equal(data, text); assert.equal(request.getResponseHeader('Access-Control-Allow-Origin'), '*'); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -252,44 +252,44 @@ describe('protocol module', function() { it('sends object as response', function(done) { var handler = function(request, callback) { - return callback({ + callback({ data: buffer, mimeType: 'text/html' }); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); - return it('fails when sending string', function(done) { + it('fails when sending string', function(done) { var handler = function(request, callback) { - return callback(text); + callback(text); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); @@ -304,9 +304,9 @@ describe('protocol module', function() { it('sends file path as response', function(done) { var handler = function(request, callback) { - return callback(filePath); + callback(filePath); }; - return protocol.registerFileProtocol(protocolName, handler, function(error) { + protocol.registerFileProtocol(protocolName, handler, function(error) { if (error) { return done(error); } @@ -327,42 +327,41 @@ describe('protocol module', function() { var handler = function(request, callback) { return callback(filePath); }; - return protocol.registerFileProtocol(protocolName, handler, function(error) { + protocol.registerFileProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data, status, request) { assert.equal(data, String(fileContent)); assert.equal(request.getResponseHeader('Access-Control-Allow-Origin'), '*'); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); it('sends object as response', function(done) { - var handler; - handler = function(request, callback) { + var handler = function(request, callback) { return callback({ path: filePath }); }; - return protocol.registerFileProtocol(protocolName, handler, function(error) { + protocol.registerFileProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, String(fileContent)); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -370,21 +369,21 @@ describe('protocol module', function() { it('can send normal file', function(done) { var handler = function(request, callback) { - return callback(normalPath); + callback(normalPath); }; - return protocol.registerFileProtocol(protocolName, handler, function(error) { + protocol.registerFileProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, String(normalContent)); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -393,41 +392,41 @@ describe('protocol module', function() { it('fails when sending unexist-file', function(done) { var fakeFilePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'not-exist'); var handler = function(request, callback) { - return callback(fakeFilePath); + callback(fakeFilePath); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); }); - return it('fails when sending unsupported content', function(done) { + it('fails when sending unsupported content', function(done) { var handler = function(request, callback) { - return callback(new Date); + callback(new Date); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); @@ -439,29 +438,28 @@ describe('protocol module', function() { var server = http.createServer(function(req, res) { assert.notEqual(req.headers.accept, ''); res.end(text); - return server.close(); + server.close(); }); return server.listen(0, '127.0.0.1', function() { - var handler, port, url; - port = server.address().port; - url = "http://127.0.0.1:" + port; - handler = function(request, callback) { - return callback({ + var port = server.address().port; + var url = "http://127.0.0.1:" + port; + var handler = function(request, callback) { + callback({ url: url }); }; - return protocol.registerHttpProtocol(protocolName, handler, function(error) { + protocol.registerHttpProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -470,43 +468,43 @@ describe('protocol module', function() { it('fails when sending invalid url', function(done) { var handler = function(request, callback) { - return callback({ + callback({ url: 'url' }); }; - return protocol.registerHttpProtocol(protocolName, handler, function(error) { + protocol.registerHttpProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); }); - return it('fails when sending unsupported content', function(done) { + it('fails when sending unsupported content', function(done) { var handler = function(request, callback) { - return callback(new Date); + callback(new Date); }; - return protocol.registerHttpProtocol(protocolName, handler, function(error) { + protocol.registerHttpProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); @@ -515,55 +513,55 @@ describe('protocol module', function() { describe('protocol.isProtocolHandled', function() { it('returns true for file:', function(done) { - return protocol.isProtocolHandled('file', function(result) { + protocol.isProtocolHandled('file', function(result) { assert.equal(result, true); - return done(); + done(); }); }); it('returns true for http:', function(done) { - return protocol.isProtocolHandled('http', function(result) { + protocol.isProtocolHandled('http', function(result) { assert.equal(result, true); - return done(); + done(); }); }); it('returns true for https:', function(done) { - return protocol.isProtocolHandled('https', function(result) { + protocol.isProtocolHandled('https', function(result) { assert.equal(result, true); - return done(); + done(); }); }); it('returns false when scheme is not registred', function(done) { - return protocol.isProtocolHandled('no-exist', function(result) { + protocol.isProtocolHandled('no-exist', function(result) { assert.equal(result, false); - return done(); + done(); }); }); it('returns true for custom protocol', function(done) { var emptyHandler = function(request, callback) { - return callback(); + callback(); }; - return protocol.registerStringProtocol(protocolName, emptyHandler, function(error) { + protocol.registerStringProtocol(protocolName, emptyHandler, function(error) { assert.equal(error, null); - return protocol.isProtocolHandled(protocolName, function(result) { + protocol.isProtocolHandled(protocolName, function(result) { assert.equal(result, true); - return done(); + done(); }); }); }); - return it('returns true for intercepted protocol', function(done) { + it('returns true for intercepted protocol', function(done) { var emptyHandler = function(request, callback) { - return callback(); + callback(); }; - return protocol.interceptStringProtocol('http', emptyHandler, function(error) { + protocol.interceptStringProtocol('http', emptyHandler, function(error) { assert.equal(error, null); - return protocol.isProtocolHandled('http', function(result) { + protocol.isProtocolHandled('http', function(result) { assert.equal(result, true); - return done(); + done(); }); }); }); @@ -571,15 +569,15 @@ describe('protocol module', function() { describe('protocol.intercept(Any)Protocol', function() { var emptyHandler = function(request, callback) { - return callback(); + callback(); }; it('throws error when scheme is already intercepted', function(done) { - return protocol.interceptStringProtocol('http', emptyHandler, function(error) { + protocol.interceptStringProtocol('http', emptyHandler, function(error) { assert.equal(error, null); - return protocol.interceptBufferProtocol('http', emptyHandler, function(error) { + protocol.interceptBufferProtocol('http', emptyHandler, function(error) { assert.notEqual(error, null); - return done(); + done(); }); }); }); @@ -593,39 +591,39 @@ describe('protocol module', function() { // Ignore error } }; - return protocol.interceptStringProtocol('http', doubleHandler, function(error) { + protocol.interceptStringProtocol('http', doubleHandler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: 'http://fake-host', success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); - return it('sends error when callback is called with nothing', function(done) { + it('sends error when callback is called with nothing', function(done) { if (process.env.TRAVIS === 'true') { return done(); } - return protocol.interceptBufferProtocol('http', emptyHandler, function(error) { + protocol.interceptBufferProtocol('http', emptyHandler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: 'http://fake-host', success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); @@ -635,20 +633,20 @@ describe('protocol module', function() { describe('protocol.interceptStringProtocol', function() { it('can intercept http protocol', function(done) { var handler = function(request, callback) { - return callback(text); + callback(text); }; - return protocol.interceptStringProtocol('http', handler, function(error) { + protocol.interceptStringProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: 'http://fake-host', success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -656,51 +654,50 @@ describe('protocol module', function() { it('can set content-type', function(done) { var handler = function(request, callback) { - return callback({ + callback({ mimeType: 'application/json', data: '{"value": 1}' }); }; - return protocol.interceptStringProtocol('http', handler, function(error) { + protocol.interceptStringProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: 'http://fake-host', success: function(data) { assert.equal(typeof data, 'object'); assert.equal(data.value, 1); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); - return it('can receive post data', function(done) { + it('can receive post data', function(done) { var handler = function(request, callback) { - var uploadData; - uploadData = request.uploadData[0].bytes.toString(); - return callback({ + var uploadData = request.uploadData[0].bytes.toString(); + callback({ data: uploadData }); }; - return protocol.interceptStringProtocol('http', handler, function(error) { + protocol.interceptStringProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: "http://fake-host", type: "POST", data: postData, success: function(data) { assert.deepEqual(qs.parse(data), postData); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -710,45 +707,44 @@ describe('protocol module', function() { describe('protocol.interceptBufferProtocol', function() { it('can intercept http protocol', function(done) { var handler = function(request, callback) { - return callback(new Buffer(text)); + callback(new Buffer(text)); }; - return protocol.interceptBufferProtocol('http', handler, function(error) { + protocol.interceptBufferProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: 'http://fake-host', success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); - return it('can receive post data', function(done) { + it('can receive post data', function(done) { var handler = function(request, callback) { - var uploadData; - uploadData = request.uploadData[0].bytes; - return callback(uploadData); + var uploadData = request.uploadData[0].bytes; + callback(uploadData); }; - return protocol.interceptBufferProtocol('http', handler, function(error) { + protocol.interceptBufferProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: "http://fake-host", type: "POST", data: postData, success: function(data) { assert.equal(data, $.param(postData)); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -756,24 +752,22 @@ describe('protocol module', function() { }); describe('protocol.interceptHttpProtocol', function() { - return it('can send POST request', function(done) { + it('can send POST request', function(done) { var server = http.createServer(function(req, res) { - var body; - body = ''; + var body = ''; req.on('data', function(chunk) { - return body += chunk; + body += chunk; }); req.on('end', function() { - return res.end(body); + res.end(body); }); - return server.close(); + server.close(); }); - return server.listen(0, '127.0.0.1', function() { + server.listen(0, '127.0.0.1', function() { var port = server.address().port; var url = "http://127.0.0.1:" + port; var handler = function(request, callback) { - var data; - data = { + var data = { url: url, method: 'POST', uploadData: { @@ -782,22 +776,22 @@ describe('protocol module', function() { }, session: null }; - return callback(data); + callback(data); }; - return protocol.interceptHttpProtocol('http', handler, function(error) { + protocol.interceptHttpProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: "http://fake-host", type: "POST", data: postData, success: function(data) { assert.deepEqual(qs.parse(data), postData); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); @@ -805,18 +799,18 @@ describe('protocol module', function() { }); }); - return describe('protocol.uninterceptProtocol', function() { + describe('protocol.uninterceptProtocol', function() { it('returns error when scheme does not exist', function(done) { - return protocol.uninterceptProtocol('not-exist', function(error) { + protocol.uninterceptProtocol('not-exist', function(error) { assert.notEqual(error, null); - return done(); + done(); }); }); - return it('returns error when scheme is not intercepted', function(done) { - return protocol.uninterceptProtocol('http', function(error) { + it('returns error when scheme is not intercepted', function(done) { + protocol.uninterceptProtocol('http', function(error) { assert.notEqual(error, null); - return done(); + done(); }); }); }); diff --git a/spec/api-screen-spec.js b/spec/api-screen-spec.js index 9329c01823d..34828e863e8 100644 --- a/spec/api-screen-spec.js +++ b/spec/api-screen-spec.js @@ -3,19 +3,19 @@ const screen = require('electron').screen; describe('screen module', function() { describe('screen.getCursorScreenPoint()', function() { - return it('returns a point object', function() { + it('returns a point object', function() { var point = screen.getCursorScreenPoint(); assert.equal(typeof point.x, 'number'); - return assert.equal(typeof point.y, 'number'); + assert.equal(typeof point.y, 'number'); }); }); - return describe('screen.getPrimaryDisplay()', function() { - return it('returns a display object', function() { + describe('screen.getPrimaryDisplay()', function() { + it('returns a display object', function() { var display = screen.getPrimaryDisplay(); assert.equal(typeof display.scaleFactor, 'number'); assert(display.size.width > 0); - return assert(display.size.height > 0); + assert(display.size.height > 0); }); }); }); diff --git a/spec/api-session-spec.js b/spec/api-session-spec.js index a4421a18ed0..049309eda58 100644 --- a/spec/api-session-spec.js +++ b/spec/api-session-spec.js @@ -18,7 +18,7 @@ describe('session module', function() { var url = "http://127.0.0.1"; beforeEach(function() { - return w = new BrowserWindow({ + w = new BrowserWindow({ show: false, width: 400, height: 400 @@ -26,7 +26,7 @@ describe('session module', function() { }); afterEach(function() { - return w.destroy(); + w.destroy(); }); describe('session.cookies', function() { @@ -35,14 +35,14 @@ describe('session module', function() { server = http.createServer(function(req, res) { res.setHeader('Set-Cookie', ['0=0']); res.end('finished'); - return server.close(); + server.close(); }); - return server.listen(0, '127.0.0.1', function() { + server.listen(0, '127.0.0.1', function() { var port; port = server.address().port; w.loadURL(url + ":" + port); - return w.webContents.on('did-finish-load', function() { - return w.webContents.session.cookies.get({ + w.webContents.on('did-finish-load', function() { + w.webContents.session.cookies.get({ url: url }, function(error, list) { var cookie, i, len; @@ -59,14 +59,14 @@ describe('session module', function() { } } } - return done('Can not find cookie'); + done('Can not find cookie'); }); }); }); }); it('should over-write the existent cookie', function(done) { - return session.defaultSession.cookies.set({ + session.defaultSession.cookies.set({ url: url, name: '1', value: '1' @@ -74,7 +74,7 @@ describe('session module', function() { if (error) { return done(error); } - return session.defaultSession.cookies.get({ + session.defaultSession.cookies.get({ url: url }, function(error, list) { var cookie, i, len; @@ -91,13 +91,13 @@ describe('session module', function() { } } } - return done('Can not find cookie'); + done('Can not find cookie'); }); }); }); it('should remove cookies', function(done) { - return session.defaultSession.cookies.set({ + session.defaultSession.cookies.set({ url: url, name: '2', value: '2' @@ -105,8 +105,8 @@ describe('session module', function() { if (error) { return done(error); } - return session.defaultSession.cookies.remove(url, '2', function() { - return session.defaultSession.cookies.get({ + session.defaultSession.cookies.remove(url, '2', function() { + session.defaultSession.cookies.get({ url: url }, function(error, list) { var cookie, i, len; @@ -119,7 +119,7 @@ describe('session module', function() { return done('Cookie not deleted'); } } - return done(); + done(); }); }); }); @@ -128,22 +128,22 @@ describe('session module', function() { describe('session.clearStorageData(options)', function() { fixtures = path.resolve(__dirname, 'fixtures'); - return it('clears localstorage data', function(done) { + it('clears localstorage data', function(done) { ipcMain.on('count', function(event, count) { ipcMain.removeAllListeners('count'); assert(!count); - return done(); + done(); }); w.loadURL('file://' + path.join(fixtures, 'api', 'localstorage.html')); - return w.webContents.on('did-finish-load', function() { + w.webContents.on('did-finish-load', function() { var options; options = { origin: "file://", storages: ['localstorage'], quotas: ['persistent'] }; - return w.webContents.session.clearStorageData(options, function() { - return w.webContents.send('getcount'); + w.webContents.session.clearStorageData(options, function() { + w.webContents.send('getcount'); }); }); }); @@ -161,7 +161,7 @@ describe('session module', function() { }); afterEach(function() { - return w.destroy(); + w.destroy(); }); it('can cancel default download behavior', function(done) { @@ -193,21 +193,20 @@ describe('session module', function() { }); }); - return describe('DownloadItem', function() { - var assertDownload, contentDisposition, downloadFilePath, downloadServer, mockPDF; - mockPDF = new Buffer(1024 * 1024 * 5); - contentDisposition = 'inline; filename="mock.pdf"'; - downloadFilePath = path.join(fixtures, 'mock.pdf'); - downloadServer = http.createServer(function(req, res) { + describe('DownloadItem', function() { + var mockPDF = new Buffer(1024 * 1024 * 5); + var contentDisposition = 'inline; filename="mock.pdf"'; + var downloadFilePath = path.join(fixtures, 'mock.pdf'); + var downloadServer = http.createServer(function(req, res) { res.writeHead(200, { 'Content-Length': mockPDF.length, 'Content-Type': 'application/pdf', 'Content-Disposition': contentDisposition }); res.end(mockPDF); - return downloadServer.close(); + downloadServer.close(); }); - assertDownload = function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port) { + var assertDownload = function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port) { assert.equal(state, 'completed'); assert.equal(filename, 'mock.pdf'); assert.equal(url, "http://127.0.0.1:" + port + "/"); @@ -216,55 +215,52 @@ describe('session module', function() { assert.equal(totalBytes, mockPDF.length); assert.equal(disposition, contentDisposition); assert(fs.existsSync(downloadFilePath)); - return fs.unlinkSync(downloadFilePath); + fs.unlinkSync(downloadFilePath); }; it('can download using BrowserWindow.loadURL', function(done) { - return downloadServer.listen(0, '127.0.0.1', function() { - var port; - port = downloadServer.address().port; + downloadServer.listen(0, '127.0.0.1', function() { + var port = downloadServer.address().port; ipcRenderer.sendSync('set-download-option', false, false); w.loadURL(url + ":" + port); - return ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { + ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { assertDownload(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port); - return done(); + done(); }); }); }); it('can download using WebView.downloadURL', function(done) { - return downloadServer.listen(0, '127.0.0.1', function() { - var port, webview; - port = downloadServer.address().port; + downloadServer.listen(0, '127.0.0.1', function() { + var port = downloadServer.address().port; ipcRenderer.sendSync('set-download-option', false, false); - webview = new WebView; + var webview = new WebView; webview.src = "file://" + fixtures + "/api/blank.html"; webview.addEventListener('did-finish-load', function() { - return webview.downloadURL(url + ":" + port + "/"); + webview.downloadURL(url + ":" + port + "/"); }); ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { assertDownload(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port); document.body.removeChild(webview); - return done(); + done(); }); - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); it('can cancel download', function(done) { - return downloadServer.listen(0, '127.0.0.1', function() { - var port; - port = downloadServer.address().port; + downloadServer.listen(0, '127.0.0.1', function() { + var port = downloadServer.address().port; ipcRenderer.sendSync('set-download-option', true, false); w.loadURL(url + ":" + port + "/"); - return ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { + ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { assert.equal(state, 'cancelled'); assert.equal(filename, 'mock.pdf'); assert.equal(mimeType, 'application/pdf'); assert.equal(receivedBytes, 0); assert.equal(totalBytes, mockPDF.length); assert.equal(disposition, contentDisposition); - return done(); + done(); }); }); }); diff --git a/spec/api-web-frame-spec.js b/spec/api-web-frame-spec.js index 1a3eca6d584..15f31aa8f09 100644 --- a/spec/api-web-frame-spec.js +++ b/spec/api-web-frame-spec.js @@ -4,15 +4,15 @@ const webFrame = require('electron').webFrame; describe('webFrame module', function() { var fixtures = path.resolve(__dirname, 'fixtures'); - return describe('webFrame.registerURLSchemeAsPrivileged', function() { - return it('supports fetch api', function(done) { + describe('webFrame.registerURLSchemeAsPrivileged', function() { + it('supports fetch api', function(done) { webFrame.registerURLSchemeAsPrivileged('file'); var url = "file://" + fixtures + "/assets/logo.png"; - return fetch(url).then(function(response) { + fetch(url).then(function(response) { assert(response.ok); - return done(); - })["catch"](function(err) { - return done('unexpected error : ' + err); + done(); + }).catch(function(err) { + done('unexpected error : ' + err); }); }); }); diff --git a/spec/api-web-request-spec.js b/spec/api-web-request-spec.js index e2a3a1ca38f..f64c91b610c 100644 --- a/spec/api-web-request-spec.js +++ b/spec/api-web-request-spec.js @@ -13,41 +13,41 @@ describe('webRequest module', function() { if (req.headers.accept === '*/*;test/header') { content += 'header/received'; } - return res.end(content); + res.end(content); }); var defaultURL = null; before(function(done) { - return server.listen(0, '127.0.0.1', function() { + server.listen(0, '127.0.0.1', function() { var port; port = server.address().port; defaultURL = "http://127.0.0.1:" + port + "/"; - return done(); + done(); }); }); after(function() { - return server.close(); + server.close(); }); describe('webRequest.onBeforeRequest', function() { afterEach(function() { - return ses.webRequest.onBeforeRequest(null); + ses.webRequest.onBeforeRequest(null); }); it('can cancel the request', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { - return callback({ + callback({ cancel: true }); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function() { - return done('unexpected success'); + done('unexpected success'); }, error: function() { - return done(); + done(); } }); }); @@ -57,26 +57,26 @@ describe('webRequest module', function() { urls: [defaultURL + "filter/*"] }; ses.webRequest.onBeforeRequest(filter, function(details, callback) { - return callback({ + callback({ cancel: true }); }); - return $.ajax({ + $.ajax({ url: defaultURL + "nofilter/test", success: function(data) { assert.equal(data, '/nofilter/test'); - return $.ajax({ + $.ajax({ url: defaultURL + "filter/test", success: function() { - return done('unexpected success'); + done('unexpected success'); }, error: function() { - return done(); + done(); } }); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); @@ -89,16 +89,16 @@ describe('webRequest module', function() { assert.equal(details.method, 'GET'); assert.equal(details.resourceType, 'xhr'); assert(!details.uploadData); - return callback({}); + callback({}); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); @@ -115,11 +115,11 @@ describe('webRequest module', function() { assert.equal(details.uploadData.length, 1); data = qs.parse(details.uploadData[0].bytes.toString()); assert.deepEqual(data, postData); - return callback({ + callback({ cancel: true }); }); - return $.ajax({ + $.ajax({ url: defaultURL, type: 'POST', data: postData, @@ -131,24 +131,24 @@ describe('webRequest module', function() { }); }); - return it('can redirect the request', function(done) { + it('can redirect the request', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { if (details.url === defaultURL) { - return callback({ + callback({ redirectURL: defaultURL + "redirect" }); } else { - return callback({}); + callback({}); } }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/redirect'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); @@ -156,22 +156,22 @@ describe('webRequest module', function() { describe('webRequest.onBeforeSendHeaders', function() { afterEach(function() { - return ses.webRequest.onBeforeSendHeaders(null); + ses.webRequest.onBeforeSendHeaders(null); }); it('receives details object', function(done) { ses.webRequest.onBeforeSendHeaders(function(details, callback) { assert.equal(typeof details.requestHeaders, 'object'); - return callback({}); + callback({}); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); @@ -181,40 +181,39 @@ describe('webRequest module', function() { var requestHeaders; requestHeaders = details.requestHeaders; requestHeaders.Accept = '*/*;test/header'; - return callback({ + callback({ requestHeaders: requestHeaders }); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/header/received'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); - return it('resets the whole headers', function(done) { - var requestHeaders; - requestHeaders = { + it('resets the whole headers', function(done) { + var requestHeaders = { Test: 'header' }; ses.webRequest.onBeforeSendHeaders(function(details, callback) { - return callback({ + callback({ requestHeaders: requestHeaders }); }); ses.webRequest.onSendHeaders(function(details) { assert.deepEqual(details.requestHeaders, requestHeaders); - return done(); + done(); }); - return $.ajax({ + $.ajax({ url: defaultURL, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); @@ -222,21 +221,21 @@ describe('webRequest module', function() { describe('webRequest.onSendHeaders', function() { afterEach(function() { - return ses.webRequest.onSendHeaders(null); + ses.webRequest.onSendHeaders(null); }); - return it('receives details object', function(done) { + it('receives details object', function(done) { ses.webRequest.onSendHeaders(function(details) { - return assert.equal(typeof details.requestHeaders, 'object'); + assert.equal(typeof details.requestHeaders, 'object'); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); @@ -244,7 +243,7 @@ describe('webRequest module', function() { describe('webRequest.onHeadersReceived', function() { afterEach(function() { - return ses.webRequest.onHeadersReceived(null); + ses.webRequest.onHeadersReceived(null); }); it('receives details object', function(done) { @@ -252,55 +251,54 @@ describe('webRequest module', function() { assert.equal(details.statusLine, 'HTTP/1.1 200 OK'); assert.equal(details.statusCode, 200); assert.equal(details.responseHeaders['Custom'], 'Header'); - return callback({}); + callback({}); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); it('can change the response header', function(done) { ses.webRequest.onHeadersReceived(function(details, callback) { - var responseHeaders; - responseHeaders = details.responseHeaders; + var responseHeaders = details.responseHeaders; responseHeaders['Custom'] = ['Changed']; - return callback({ + callback({ responseHeaders: responseHeaders }); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data, status, xhr) { assert.equal(xhr.getResponseHeader('Custom'), 'Changed'); assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); - return it('does not change header by default', function(done) { + it('does not change header by default', function(done) { ses.webRequest.onHeadersReceived(function(details, callback) { - return callback({}); + callback({}); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data, status, xhr) { assert.equal(xhr.getResponseHeader('Custom'), 'Header'); assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); @@ -308,25 +306,25 @@ describe('webRequest module', function() { describe('webRequest.onResponseStarted', function() { afterEach(function() { - return ses.webRequest.onResponseStarted(null); + ses.webRequest.onResponseStarted(null); }); - return it('receives details object', function(done) { + it('receives details object', function(done) { ses.webRequest.onResponseStarted(function(details) { assert.equal(typeof details.fromCache, 'boolean'); assert.equal(details.statusLine, 'HTTP/1.1 200 OK'); assert.equal(details.statusCode, 200); - return assert.equal(details.responseHeaders['Custom'], 'Header'); + assert.equal(details.responseHeaders['Custom'], 'Header'); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data, status, xhr) { assert.equal(xhr.getResponseHeader('Custom'), 'Header'); assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); @@ -335,35 +333,34 @@ describe('webRequest module', function() { describe('webRequest.onBeforeRedirect', function() { afterEach(function() { ses.webRequest.onBeforeRedirect(null); - return ses.webRequest.onBeforeRequest(null); + ses.webRequest.onBeforeRequest(null); }); - return it('receives details object', function(done) { - var redirectURL; - redirectURL = defaultURL + "redirect"; + it('receives details object', function(done) { + var redirectURL = defaultURL + "redirect"; ses.webRequest.onBeforeRequest(function(details, callback) { if (details.url === defaultURL) { - return callback({ + callback({ redirectURL: redirectURL }); } else { - return callback({}); + callback({}); } }); ses.webRequest.onBeforeRedirect(function(details) { assert.equal(typeof details.fromCache, 'boolean'); assert.equal(details.statusLine, 'HTTP/1.1 307 Internal Redirect'); assert.equal(details.statusCode, 307); - return assert.equal(details.redirectURL, redirectURL); + assert.equal(details.redirectURL, redirectURL); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/redirect'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); @@ -371,48 +368,48 @@ describe('webRequest module', function() { describe('webRequest.onCompleted', function() { afterEach(function() { - return ses.webRequest.onCompleted(null); + ses.webRequest.onCompleted(null); }); - return it('receives details object', function(done) { + it('receives details object', function(done) { ses.webRequest.onCompleted(function(details) { assert.equal(typeof details.fromCache, 'boolean'); assert.equal(details.statusLine, 'HTTP/1.1 200 OK'); - return assert.equal(details.statusCode, 200); + assert.equal(details.statusCode, 200); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); }); - return describe('webRequest.onErrorOccurred', function() { + describe('webRequest.onErrorOccurred', function() { afterEach(function() { ses.webRequest.onErrorOccurred(null); - return ses.webRequest.onBeforeRequest(null); + ses.webRequest.onBeforeRequest(null); }); - return it('receives details object', function(done) { + it('receives details object', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { - return callback({ + callback({ cancel: true }); }); ses.webRequest.onErrorOccurred(function(details) { assert.equal(details.error, 'net::ERR_BLOCKED_BY_CLIENT'); - return done(); + done(); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function() { - return done('unexpected success'); + done('unexpected success'); } }); }); diff --git a/spec/asar-spec.js b/spec/asar-spec.js index 064212e7c7e..d35cf186c65 100644 --- a/spec/asar-spec.js +++ b/spec/asar-spec.js @@ -23,121 +23,108 @@ describe('asar package', function() { }); it('reads a normal file', function() { - var file1, file2, file3; - file1 = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var file1 = path.join(fixtures, 'asar', 'a.asar', 'file1'); assert.equal(fs.readFileSync(file1).toString().trim(), 'file1'); - file2 = path.join(fixtures, 'asar', 'a.asar', 'file2'); + var file2 = path.join(fixtures, 'asar', 'a.asar', 'file2'); assert.equal(fs.readFileSync(file2).toString().trim(), 'file2'); - file3 = path.join(fixtures, 'asar', 'a.asar', 'file3'); - return assert.equal(fs.readFileSync(file3).toString().trim(), 'file3'); + var file3 = path.join(fixtures, 'asar', 'a.asar', 'file3'); + assert.equal(fs.readFileSync(file3).toString().trim(), 'file3'); }); it('reads from a empty file', function() { - var buffer, file; - file = path.join(fixtures, 'asar', 'empty.asar', 'file1'); - buffer = fs.readFileSync(file); + var file = path.join(fixtures, 'asar', 'empty.asar', 'file1'); + var buffer = fs.readFileSync(file); assert.equal(buffer.length, 0); - return assert.equal(buffer.toString(), ''); + assert.equal(buffer.toString(), ''); }); it('reads a linked file', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link1'); - return assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); + var p = path.join(fixtures, 'asar', 'a.asar', 'link1'); + assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); }); it('reads a file from linked directory', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1'); + var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1'); assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); - return assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); + assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); }); it('throws ENOENT error when can not find file', function() { - var p, throws; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - throws = function() { - return fs.readFileSync(p); + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var throws = function() { + fs.readFileSync(p); }; - return assert.throws(throws, /ENOENT/); + assert.throws(throws, /ENOENT/); }); it('passes ENOENT error to callback when can not find file', function() { - var async, p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - async = false; + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var async = false; fs.readFile(p, function(e) { assert(async); - return assert(/ENOENT/.test(e)); + assert(/ENOENT/.test(e)); }); - return async = true; + async = true; }); - return it('reads a normal file with unpacked files', function() { - var p; - p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt'); - return assert.equal(fs.readFileSync(p).toString().trim(), 'a'); + it('reads a normal file with unpacked files', function() { + var p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt'); + assert.equal(fs.readFileSync(p).toString().trim(), 'a'); }); }); describe('fs.readFile', function() { it('reads a normal file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'file1'); - return fs.readFile(p, function(err, content) { + var p = path.join(fixtures, 'asar', 'a.asar', 'file1'); + fs.readFile(p, function(err, content) { assert.equal(err, null); assert.equal(String(content).trim(), 'file1'); - return done(); + done(); }); }); it('reads from a empty file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'empty.asar', 'file1'); - return fs.readFile(p, function(err, content) { + var p = path.join(fixtures, 'asar', 'empty.asar', 'file1'); + fs.readFile(p, function(err, content) { assert.equal(err, null); assert.equal(String(content), ''); - return done(); + done(); }); }); it('reads a linked file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link1'); - return fs.readFile(p, function(err, content) { + var p = path.join(fixtures, 'asar', 'a.asar', 'link1'); + fs.readFile(p, function(err, content) { assert.equal(err, null); assert.equal(String(content).trim(), 'file1'); - return done(); + done(); }); }); it('reads a file from linked directory', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); - return fs.readFile(p, function(err, content) { + var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); + fs.readFile(p, function(err, content) { assert.equal(err, null); assert.equal(String(content).trim(), 'file1'); - return done(); + done(); }); }); - return it('throws ENOENT error when can not find file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return fs.readFile(p, function(err) { + it('throws ENOENT error when can not find file', function(done) { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + fs.readFile(p, function(err) { assert.equal(err.code, 'ENOENT'); - return done(); + done(); }); }); }); describe('fs.lstatSync', function() { it('handles path with trailing slash correctly', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); + var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); fs.lstatSync(p); - return fs.lstatSync(p + '/'); + fs.lstatSync(p + '/'); }); it('returns information of root', function() { @@ -147,7 +134,7 @@ describe('asar package', function() { assert.equal(stats.isFile(), false); assert.equal(stats.isDirectory(), true); assert.equal(stats.isSymbolicLink(), false); - return assert.equal(stats.size, 0); + assert.equal(stats.size, 0); }); it('returns information of a normal file', function() { @@ -163,7 +150,7 @@ describe('asar package', function() { assert.equal(stats.isSymbolicLink(), false); results.push(assert.equal(stats.size, 6)); } - return results; + results; }); it('returns information of a normal directory', function() { @@ -179,7 +166,7 @@ describe('asar package', function() { assert.equal(stats.isSymbolicLink(), false); results.push(assert.equal(stats.size, 0)); } - return results; + results; }); it('returns information of a linked file', function() { @@ -195,7 +182,7 @@ describe('asar package', function() { assert.equal(stats.isSymbolicLink(), true); results.push(assert.equal(stats.size, 0)); } - return results; + results; }); it('returns information of a linked directory', function() { @@ -211,29 +198,27 @@ describe('asar package', function() { assert.equal(stats.isSymbolicLink(), true); results.push(assert.equal(stats.size, 0)); } - return results; + results; }); - return it('throws ENOENT error when can not find file', function() { - var file, j, len, p, ref2, results, throws; + it('throws ENOENT error when can not find file', function() { + var file, j, len, p, ref2, throws; ref2 = ['file4', 'file5', path.join('dir1', 'file4')]; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); throws = function() { - return fs.lstatSync(p); + fs.lstatSync(p); }; - results.push(assert.throws(throws, /ENOENT/)); + assert.throws(throws, /ENOENT/); } - return results; }); }); describe('fs.lstat', function() { it('handles path with trailing slash correctly', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); - return fs.lstat(p + '/', done); + fs.lstat(p + '/', done); }); it('returns information of root', function(done) { @@ -244,7 +229,7 @@ describe('asar package', function() { assert.equal(stats.isDirectory(), true); assert.equal(stats.isSymbolicLink(), false); assert.equal(stats.size, 0); - return done(); + done(); }); }); @@ -256,7 +241,7 @@ describe('asar package', function() { assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), false); assert.equal(stats.size, 6); - return done(); + done(); }); }); @@ -268,7 +253,7 @@ describe('asar package', function() { assert.equal(stats.isDirectory(), true); assert.equal(stats.isSymbolicLink(), false); assert.equal(stats.size, 0); - return done(); + done(); }); }); @@ -280,7 +265,7 @@ describe('asar package', function() { assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), true); assert.equal(stats.size, 0); - return done(); + done(); }); }); @@ -292,15 +277,15 @@ describe('asar package', function() { assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), true); assert.equal(stats.size, 0); - return done(); + done(); }); }); - return it('throws ENOENT error when can not find file', function(done) { + it('throws ENOENT error when can not find file', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'file4'); fs.lstat(p, function(err) { assert.equal(err.code, 'ENOENT'); - return done(); + done(); }); }); }); @@ -310,44 +295,44 @@ describe('asar package', function() { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = 'a.asar'; var r = fs.realpathSync(path.join(parent, p)); - return assert.equal(r, path.join(parent, p)); + assert.equal(r, path.join(parent, p)); }); it('returns real path of a normal file', function() { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = path.join('a.asar', 'file1'); var r = fs.realpathSync(path.join(parent, p)); - return assert.equal(r, path.join(parent, p)); + assert.equal(r, path.join(parent, p)); }); it('returns real path of a normal directory', function() { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = path.join('a.asar', 'dir1'); var r = fs.realpathSync(path.join(parent, p)); - return assert.equal(r, path.join(parent, p)); + assert.equal(r, path.join(parent, p)); }); it('returns real path of a linked file', function() { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = path.join('a.asar', 'link2', 'link1'); var r = fs.realpathSync(path.join(parent, p)); - return assert.equal(r, path.join(parent, 'a.asar', 'file1')); + assert.equal(r, path.join(parent, 'a.asar', 'file1')); }); it('returns real path of a linked directory', function() { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = path.join('a.asar', 'link2', 'link2'); var r = fs.realpathSync(path.join(parent, p)); - return assert.equal(r, path.join(parent, 'a.asar', 'dir1')); + assert.equal(r, path.join(parent, 'a.asar', 'dir1')); }); - return it('throws ENOENT error when can not find file', function() { + it('throws ENOENT error when can not find file', function() { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = path.join('a.asar', 'not-exist'); var throws = function() { - return fs.realpathSync(path.join(parent, p)); + fs.realpathSync(path.join(parent, p)); }; - return assert.throws(throws, /ENOENT/); + assert.throws(throws, /ENOENT/); }); }); @@ -355,58 +340,58 @@ describe('asar package', function() { it('returns real path root', function(done) { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = 'a.asar'; - return fs.realpath(path.join(parent, p), function(err, r) { + fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, p)); - return done(); + done(); }); }); it('returns real path of a normal file', function(done) { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = path.join('a.asar', 'file1'); - return fs.realpath(path.join(parent, p), function(err, r) { + fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, p)); - return done(); + done(); }); }); it('returns real path of a normal directory', function(done) { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = path.join('a.asar', 'dir1'); - return fs.realpath(path.join(parent, p), function(err, r) { + fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, p)); - return done(); + done(); }); }); it('returns real path of a linked file', function(done) { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = path.join('a.asar', 'link2', 'link1'); - return fs.realpath(path.join(parent, p), function(err, r) { + fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, 'a.asar', 'file1')); - return done(); + done(); }); }); it('returns real path of a linked directory', function(done) { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = path.join('a.asar', 'link2', 'link2'); - return fs.realpath(path.join(parent, p), function(err, r) { + fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, 'a.asar', 'dir1')); - return done(); + done(); }); }); - return it('throws ENOENT error when can not find file', function(done) { + it('throws ENOENT error when can not find file', function(done) { var parent = fs.realpathSync(path.join(fixtures, 'asar')); var p = path.join('a.asar', 'not-exist'); - return fs.realpath(path.join(parent, p), function(err) { + fs.realpath(path.join(parent, p), function(err) { assert.equal(err.code, 'ENOENT'); - return done(); + done(); }); }); }); @@ -414,27 +399,27 @@ describe('asar package', function() { it('reads dirs from root', function() { var p = path.join(fixtures, 'asar', 'a.asar'); var dirs = fs.readdirSync(p); - return assert.deepEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); + assert.deepEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); }); it('reads dirs from a normal dir', function() { var p = path.join(fixtures, 'asar', 'a.asar', 'dir1'); var dirs = fs.readdirSync(p); - return assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); + assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); }); it('reads dirs from a linked dir', function() { var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2'); var dirs = fs.readdirSync(p); - return assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); + assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); }); - return it('throws ENOENT error when can not find file', function() { + it('throws ENOENT error when can not find file', function() { var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); var throws = function() { - return fs.readdirSync(p); + fs.readdirSync(p); }; - return assert.throws(throws, /ENOENT/); + assert.throws(throws, /ENOENT/); }); }); @@ -444,7 +429,7 @@ describe('asar package', function() { fs.readdir(p, function(err, dirs) { assert.equal(err, null); assert.deepEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); - return done(); + done(); }); }); @@ -453,7 +438,7 @@ describe('asar package', function() { fs.readdir(p, function(err, dirs) { assert.equal(err, null); assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); - return done(); + done(); }); }); it('reads dirs from a linked dir', function(done) { @@ -461,15 +446,15 @@ describe('asar package', function() { fs.readdir(p, function(err, dirs) { assert.equal(err, null); assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); - return done(); + done(); }); }); - return it('throws ENOENT error when can not find file', function(done) { + it('throws ENOENT error when can not find file', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return fs.readdir(p, function(err) { + fs.readdir(p, function(err) { assert.equal(err.code, 'ENOENT'); - return done(); + done(); }); }); }); @@ -478,7 +463,6 @@ describe('asar package', function() { it('opens a normal/linked/under-linked-directory file', function() { var buffer, fd, file, j, len, p, ref2, results; ref2 = ['file1', 'link1', path.join('link2', 'file1')]; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); @@ -486,59 +470,57 @@ describe('asar package', function() { buffer = new Buffer(6); fs.readSync(fd, buffer, 0, 6, 0); assert.equal(String(buffer).trim(), 'file1'); - results.push(fs.closeSync(fd)); + fs.closeSync(fd); } - return results; }); - return it('throws ENOENT error when can not find file', function() { + it('throws ENOENT error when can not find file', function() { var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); var throws = function() { - return fs.openSync(p); + fs.openSync(p); }; - return assert.throws(throws, /ENOENT/); + assert.throws(throws, /ENOENT/); }); }); describe('fs.open', function() { it('opens a normal file', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'file1'); - return fs.open(p, 'r', function(err, fd) { - var buffer; + fs.open(p, 'r', function(err, fd) { assert.equal(err, null); - buffer = new Buffer(6); - return fs.read(fd, buffer, 0, 6, 0, function(err) { + var buffer = new Buffer(6); + fs.read(fd, buffer, 0, 6, 0, function(err) { assert.equal(err, null); assert.equal(String(buffer).trim(), 'file1'); - return fs.close(fd, done); + fs.close(fd, done); }); }); }); - return it('throws ENOENT error when can not find file', function(done) { + it('throws ENOENT error when can not find file', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return fs.open(p, 'r', function(err) { + fs.open(p, 'r', function(err) { assert.equal(err.code, 'ENOENT'); - return done(); + done(); }); }); }); describe('fs.mkdir', function() { - return it('throws error when calling inside asar archive', function(done) { + it('throws error when calling inside asar archive', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return fs.mkdir(p, function(err) { + fs.mkdir(p, function(err) { assert.equal(err.code, 'ENOTDIR'); - return done(); + done(); }); }); }); describe('fs.mkdirSync', function() { - return it('throws error when calling inside asar archive', function() { + it('throws error when calling inside asar archive', function() { var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return assert.throws((function() { - return fs.mkdirSync(p); + assert.throws((function() { + fs.mkdirSync(p); }), new RegExp('ENOTDIR')); }); }); @@ -548,19 +530,19 @@ describe('asar package', function() { var child = child_process.fork(path.join(fixtures, 'asar', 'a.asar', 'ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); - return it('supports asar in the forked js', function(done) { + it('supports asar in the forked js', function(done) { var file = path.join(fixtures, 'asar', 'a.asar', 'file1'); var child = child_process.fork(path.join(fixtures, 'module', 'asar.js')); child.on('message', function(content) { assert.equal(content, fs.readFileSync(file).toString()); - return done(); + done(); }); - return child.send(file); + child.send(file); }); }); @@ -576,14 +558,13 @@ describe('asar package', function() { execFile(echo, ['test'], function(error, stdout) { assert.equal(error, null); assert.equal(stdout, 'test\n'); - return done(); + done(); }); }); - return xit('execFileSync executes binaries', function() { - var output; - output = execFileSync(echo, ['test']); - return assert.equal(String(output), 'test\n'); + xit('execFileSync executes binaries', function() { + var output = execFileSync(echo, ['test']); + assert.equal(String(output), 'test\n'); }); }); @@ -591,47 +572,45 @@ describe('asar package', function() { var internalModuleReadFile = process.binding('fs').internalModuleReadFile; it('read a normal file', function() { - var file1, file2, file3; - file1 = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var file1 = path.join(fixtures, 'asar', 'a.asar', 'file1'); assert.equal(internalModuleReadFile(file1).toString().trim(), 'file1'); - file2 = path.join(fixtures, 'asar', 'a.asar', 'file2'); + var file2 = path.join(fixtures, 'asar', 'a.asar', 'file2'); assert.equal(internalModuleReadFile(file2).toString().trim(), 'file2'); - file3 = path.join(fixtures, 'asar', 'a.asar', 'file3'); - return assert.equal(internalModuleReadFile(file3).toString().trim(), 'file3'); + var file3 = path.join(fixtures, 'asar', 'a.asar', 'file3'); + assert.equal(internalModuleReadFile(file3).toString().trim(), 'file3'); }); - return it('reads a normal file with unpacked files', function() { - var p; - p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt'); - return assert.equal(internalModuleReadFile(p).toString().trim(), 'a'); + it('reads a normal file with unpacked files', function() { + var p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt'); + assert.equal(internalModuleReadFile(p).toString().trim(), 'a'); }); }); - return describe('process.noAsar', function() { + describe('process.noAsar', function() { var errorName = process.platform === 'win32' ? 'ENOENT' : 'ENOTDIR'; beforeEach(function() { - return process.noAsar = true; + process.noAsar = true; }); afterEach(function() { - return process.noAsar = false; + process.noAsar = false; }); it('disables asar support in sync API', function() { var file = path.join(fixtures, 'asar', 'a.asar', 'file1'); var dir = path.join(fixtures, 'asar', 'a.asar', 'dir1'); assert.throws((function() { - return fs.readFileSync(file); + fs.readFileSync(file); }), new RegExp(errorName)); assert.throws((function() { - return fs.lstatSync(file); + fs.lstatSync(file); }), new RegExp(errorName)); assert.throws((function() { - return fs.realpathSync(file); + fs.realpathSync(file); }), new RegExp(errorName)); - return assert.throws((function() { - return fs.readdirSync(dir); + assert.throws((function() { + fs.readdirSync(dir); }), new RegExp(errorName)); }); @@ -639,30 +618,29 @@ describe('asar package', function() { var dir, file; file = path.join(fixtures, 'asar', 'a.asar', 'file1'); dir = path.join(fixtures, 'asar', 'a.asar', 'dir1'); - return fs.readFile(file, function(error) { + fs.readFile(file, function(error) { assert.equal(error.code, errorName); - return fs.lstat(file, function(error) { + fs.lstat(file, function(error) { assert.equal(error.code, errorName); - return fs.realpath(file, function(error) { + fs.realpath(file, function(error) { assert.equal(error.code, errorName); - return fs.readdir(dir, function(error) { + fs.readdir(dir, function(error) { assert.equal(error.code, errorName); - return done(); + done(); }); }); }); }); }); - return it('treats *.asar as normal file', function() { - var asar, content1, content2, originalFs; - originalFs = require('original-fs'); - asar = path.join(fixtures, 'asar', 'a.asar'); - content1 = fs.readFileSync(asar); - content2 = originalFs.readFileSync(asar); + it('treats *.asar as normal file', function() { + var originalFs = require('original-fs'); + var asar = path.join(fixtures, 'asar', 'a.asar'); + var content1 = fs.readFileSync(asar); + var content2 = originalFs.readFileSync(asar); assert.equal(content1.compare(content2), 0); - return assert.throws((function() { - return fs.readdirSync(asar); + assert.throws((function() { + fs.readdirSync(asar); }), /ENOTDIR/); }); }); @@ -673,43 +651,43 @@ describe('asar package', function() { it('can request a file in package', function(done) { var p = path.resolve(fixtures, 'asar', 'a.asar', 'file1'); - return $.get("file://" + p, function(data) { + $.get("file://" + p, function(data) { assert.equal(data.trim(), 'file1'); - return done(); + done(); }); }); it('can request a file in package with unpacked files', function(done) { var p = path.resolve(fixtures, 'asar', 'unpack.asar', 'a.txt'); - return $.get("file://" + p, function(data) { + $.get("file://" + p, function(data) { assert.equal(data.trim(), 'a'); - return done(); + done(); }); }); it('can request a linked file in package', function(done) { var p = path.resolve(fixtures, 'asar', 'a.asar', 'link2', 'link1'); - return $.get("file://" + p, function(data) { + $.get("file://" + p, function(data) { assert.equal(data.trim(), 'file1'); - return done(); + done(); }); }); it('can request a file in filesystem', function(done) { var p = path.resolve(fixtures, 'asar', 'file'); - return $.get("file://" + p, function(data) { + $.get("file://" + p, function(data) { assert.equal(data.trim(), 'file'); - return done(); + done(); }); }); it('gets 404 when file is not found', function(done) { var p = path.resolve(fixtures, 'asar', 'a.asar', 'no-exist'); - return $.ajax({ + $.ajax({ url: "file://" + p, error: function(err) { assert.equal(err.status, 404); - return done(); + done(); } }); }); @@ -717,7 +695,7 @@ describe('asar package', function() { it('sets __dirname correctly', function(done) { after(function() { w.destroy(); - return ipcMain.removeAllListeners('dirname'); + ipcMain.removeAllListeners('dirname'); }); var w = new BrowserWindow({ @@ -733,15 +711,15 @@ describe('asar package', function() { }); ipcMain.once('dirname', function(event, dirname) { assert.equal(dirname, path.dirname(p)); - return done(); + done(); }); - return w.loadURL(u); + w.loadURL(u); }); - return it('loads script tag in html', function(done) { + it('loads script tag in html', function(done) { after(function() { w.destroy(); - return ipcMain.removeAllListeners('ping'); + ipcMain.removeAllListeners('ping'); }); var w = new BrowserWindow({ @@ -756,9 +734,9 @@ describe('asar package', function() { pathname: p }); w.loadURL(u); - return ipcMain.once('ping', function(event, message) { + ipcMain.once('ping', function(event, message) { assert.equal(message, 'pong'); - return done(); + done(); }); }); }); @@ -770,17 +748,17 @@ describe('asar package', function() { var file, stats; file = path.join(fixtures, 'asar', 'a.asar'); stats = originalFs.statSync(file); - return assert(stats.isFile()); + assert(stats.isFile()); }); - return it('is available in forked scripts', function(done) { + it('is available in forked scripts', function(done) { var child; child = child_process.fork(path.join(fixtures, 'module', 'original-fs.js')); child.on('message', function(msg) { assert.equal(msg, 'object'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); }); @@ -788,41 +766,39 @@ describe('asar package', function() { var gfs = require('graceful-fs'); it('recognize asar archvies', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link1'); - return assert.equal(gfs.readFileSync(p).toString().trim(), 'file1'); + var p = path.join(fixtures, 'asar', 'a.asar', 'link1'); + assert.equal(gfs.readFileSync(p).toString().trim(), 'file1'); }); - return it('does not touch global fs object', function() { - return assert.notEqual(fs.readdir, gfs.readdir); + it('does not touch global fs object', function() { + assert.notEqual(fs.readdir, gfs.readdir); }); }); describe('mkdirp module', function() { var mkdirp = require('mkdirp'); - return it('throws error when calling inside asar archive', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return assert.throws((function() { - return mkdirp.sync(p); + it('throws error when calling inside asar archive', function() { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + assert.throws((function() { + mkdirp.sync(p); }), new RegExp('ENOTDIR')); }); }); - return describe('native-image', function() { + describe('native-image', function() { it('reads image from asar archive', function() { var p = path.join(fixtures, 'asar', 'logo.asar', 'logo.png'); var logo = nativeImage.createFromPath(p); - return assert.deepEqual(logo.getSize(), { + assert.deepEqual(logo.getSize(), { width: 55, height: 55 }); }); - return it('reads image from asar archive with unpacked files', function() { + it('reads image from asar archive with unpacked files', function() { var p = path.join(fixtures, 'asar', 'unpack.asar', 'atom.png'); var logo = nativeImage.createFromPath(p); - return assert.deepEqual(logo.getSize(), { + assert.deepEqual(logo.getSize(), { width: 1024, height: 1024 }); diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 21cefb0b0bc..9efe22a263c 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -15,28 +15,27 @@ describe('chromium feature', function() { if (listener != null) { window.removeEventListener('message', listener); } - return listener = null; + listener = null; }); xdescribe('heap snapshot', function() { - return it('does not crash', function() { - return process.atomBinding('v8_util').takeHeapSnapshot(); + it('does not crash', function() { + process.atomBinding('v8_util').takeHeapSnapshot(); }); }); describe('sending request of http protocol urls', function() { - return it('does not crash', function(done) { - var server; + it('does not crash', function(done) { this.timeout(5000); - server = http.createServer(function(req, res) { + + var server = http.createServer(function(req, res) { res.end(); server.close(); - return done(); + done(); }); - return server.listen(0, '127.0.0.1', function() { - var port; - port = server.address().port; - return $.get("http://127.0.0.1:" + port); + server.listen(0, '127.0.0.1', function() { + var port = server.address().port; + $.get("http://127.0.0.1:" + port); }); }); }); @@ -46,7 +45,7 @@ describe('chromium feature', function() { var w = null; afterEach(function() { - return w != null ? w.destroy() : void 0; + w != null ? w.destroy() : void 0; }); it('is set correctly when window is not shown', function(done) { @@ -55,41 +54,42 @@ describe('chromium feature', function() { }); w.webContents.on('ipc-message', function(event, args) { assert.deepEqual(args, ['hidden', true]); - return done(); + done(); }); - return w.loadURL(url); + w.loadURL(url); }); - return it('is set correctly when window is inactive', function(done) { + it('is set correctly when window is inactive', function(done) { w = new BrowserWindow({ show: false }); w.webContents.on('ipc-message', function(event, args) { assert.deepEqual(args, ['hidden', false]); - return done(); + done(); }); w.showInactive(); - return w.loadURL(url); + w.loadURL(url); }); }); xdescribe('navigator.webkitGetUserMedia', function() { - return it('calls its callbacks', function(done) { + it('calls its callbacks', function(done) { this.timeout(5000); - return navigator.webkitGetUserMedia({ + + navigator.webkitGetUserMedia({ audio: true, video: false }, function() { - return done(); + done(); }, function() { - return done(); + done(); }); }); }); describe('navigator.language', function() { - return it('should not be empty', function() { - return assert.notEqual(navigator.language, ''); + it('should not be empty', function() { + assert.notEqual(navigator.language, ''); }); }); @@ -98,28 +98,28 @@ describe('chromium feature', function() { var w = null; afterEach(function() { - return w != null ? w.destroy() : void 0; + w != null ? w.destroy() : void 0; }); - return it('should register for file scheme', function(done) { + it('should register for file scheme', function(done) { w = new BrowserWindow({ show: false }); w.webContents.on('ipc-message', function(event, args) { if (args[0] === 'reload') { - return w.webContents.reload(); + w.webContents.reload(); } else if (args[0] === 'error') { - return done('unexpected error : ' + args[1]); + done('unexpected error : ' + args[1]); } else if (args[0] === 'response') { assert.equal(args[1], 'Hello from serviceWorker!'); - return session.defaultSession.clearStorageData({ + session.defaultSession.clearStorageData({ storages: ['serviceworkers'] }, function() { - return done(); + done(); }); } }); - return w.loadURL(url); + sw.loadURL(url); }); }); @@ -127,11 +127,10 @@ describe('chromium feature', function() { this.timeout(20000); it('returns a BrowserWindowProxy object', function() { - var b; - b = window.open('about:blank', '', 'show=no'); + var b = window.open('about:blank', '', 'show=no'); assert.equal(b.closed, false); assert.equal(b.constructor.name, 'BrowserWindowProxy'); - return b.close(); + b.close(); }); it('accepts "node-integration" as feature', function(done) { @@ -139,10 +138,10 @@ describe('chromium feature', function() { listener = function(event) { assert.equal(event.data, 'undefined'); b.close(); - return done(); + done(); }; window.addEventListener('message', listener); - return b = window.open("file://" + fixtures + "/pages/window-opener-node.html", '', 'nodeIntegration=no,show=no'); + b = window.open("file://" + fixtures + "/pages/window-opener-node.html", '', 'nodeIntegration=no,show=no'); }); it('inherit options of parent window', function(done) { @@ -152,13 +151,13 @@ describe('chromium feature', function() { ref1 = remote.getCurrentWindow().getSize(), width = ref1[0], height = ref1[1]; assert.equal(event.data, "size: " + width + " " + height); b.close(); - return done(); + done(); }; window.addEventListener('message', listener); - return b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', 'show=no'); + b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', 'show=no'); }); - return it('does not override child options', function(done) { + it('does not override child options', function(done) { var b, size; size = { width: 350, @@ -167,45 +166,48 @@ describe('chromium feature', function() { listener = function(event) { assert.equal(event.data, "size: " + size.width + " " + size.height); b.close(); - return done(); + done(); }; window.addEventListener('message', listener); - return b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', "show=no,width=" + size.width + ",height=" + size.height); + b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', "show=no,width=" + size.width + ",height=" + size.height); }); }); describe('window.opener', function() { - var url, w; this.timeout(10000); - url = "file://" + fixtures + "/pages/window-opener.html"; - w = null; + + var url = "file://" + fixtures + "/pages/window-opener.html"; + var w = null; + afterEach(function() { - return w != null ? w.destroy() : void 0; + w != null ? w.destroy() : void 0; }); + it('is null for main window', function(done) { w = new BrowserWindow({ show: false }); w.webContents.on('ipc-message', function(event, args) { assert.deepEqual(args, ['opener', null]); - return done(); + done(); }); - return w.loadURL(url); + w.loadURL(url); }); - return it('is not null for window opened by window.open', function(done) { + + it('is not null for window opened by window.open', function(done) { var b; listener = function(event) { assert.equal(event.data, 'object'); b.close(); - return done(); + done(); }; window.addEventListener('message', listener); - return b = window.open(url, '', 'show=no'); + b = window.open(url, '', 'show=no'); }); }); describe('window.postMessage', function() { - return it('sets the source and origin correctly', function(done) { + it('sets the source and origin correctly', function(done) { var b, sourceId; sourceId = remote.getCurrentWindow().id; listener = function(event) { @@ -218,47 +220,47 @@ describe('chromium feature', function() { assert.equal(message.sourceEqualsOpener, true); assert.equal(message.sourceId, sourceId); assert.equal(event.origin, 'file://'); - return done(); + done(); }; window.addEventListener('message', listener); b = window.open("file://" + fixtures + "/pages/window-open-postMessage.html", '', 'show=no'); - return BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function() { - return b.postMessage('testing', '*'); + BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function() { + b.postMessage('testing', '*'); }); }); }); describe('window.opener.postMessage', function() { - return it('sets source and origin correctly', function(done) { + it('sets source and origin correctly', function(done) { var b; listener = function(event) { window.removeEventListener('message', listener); b.close(); assert.equal(event.source, b); assert.equal(event.origin, 'file://'); - return done(); + done(); }; window.addEventListener('message', listener); - return b = window.open("file://" + fixtures + "/pages/window-opener-postMessage.html", '', 'show=no'); + b = window.open("file://" + fixtures + "/pages/window-opener-postMessage.html", '', 'show=no'); }); }); describe('creating a Uint8Array under browser side', function() { - return it('does not crash', function() { + it('does not crash', function() { var RUint8Array; RUint8Array = remote.getGlobal('Uint8Array'); - return new RUint8Array; + new RUint8Array; }); }); describe('webgl', function() { - return it('can be get as context in canvas', function() { + it('can be get as context in canvas', function() { var webgl; if (process.platform === 'linux') { return; } webgl = document.createElement('canvas').getContext('webgl'); - return assert.notEqual(webgl, null); + assert.notEqual(webgl, null); }); }); @@ -270,20 +272,20 @@ describe('chromium feature', function() { worker.onmessage = function(event) { assert.equal(event.data, message); worker.terminate(); - return done(); + done(); }; - return worker.postMessage(message); + worker.postMessage(message); }); - return it('SharedWorker can work', function(done) { + it('SharedWorker can work', function(done) { var message, worker; worker = new SharedWorker('../fixtures/workers/shared_worker.js'); message = 'ping'; worker.port.onmessage = function(event) { assert.equal(event.data, message); - return done(); + done(); }; - return worker.port.postMessage(message); + worker.port.postMessage(message); }); }); @@ -291,28 +293,28 @@ describe('chromium feature', function() { var iframe = null; beforeEach(function() { - return iframe = document.createElement('iframe'); + iframe = document.createElement('iframe'); }); afterEach(function() { - return document.body.removeChild(iframe); + document.body.removeChild(iframe); }); - return it('does not have node integration', function(done) { + it('does not have node integration', function(done) { iframe.src = "file://" + fixtures + "/pages/set-global.html"; document.body.appendChild(iframe); - return iframe.onload = function() { + iframe.onload = function() { assert.equal(iframe.contentWindow.test, 'undefined undefined undefined'); - return done(); + done(); }; }); }); describe('storage', function() { - return it('requesting persitent quota works', function(done) { - return navigator.webkitPersistentStorage.requestQuota(1024 * 1024, function(grantedBytes) { + it('requesting persitent quota works', function(done) { + navigator.webkitPersistentStorage.requestQuota(1024 * 1024, function(grantedBytes) { assert.equal(grantedBytes, 1048576); - return done(); + done(); }); }); }); @@ -324,12 +326,12 @@ describe('chromium feature', function() { afterEach(function() { wss.close(); - return server.close(); + server.close(); }); - return it('has user agent', function(done) { + it('has user agent', function(done) { server = http.createServer(); - return server.listen(0, '127.0.0.1', function() { + server.listen(0, '127.0.0.1', function() { var port = server.address().port; wss = new WebSocketServer({ server: server @@ -337,9 +339,9 @@ describe('chromium feature', function() { wss.on('error', done); wss.on('connection', function(ws) { if (ws.upgradeReq.headers['user-agent']) { - return done(); + done(); } else { - return done('user agent is empty'); + done('user agent is empty'); } }); new WebSocket("ws://127.0.0.1:" + port); @@ -347,7 +349,7 @@ describe('chromium feature', function() { }); }); - return describe('Promise', function() { + describe('Promise', function() { it('resolves correctly in Node.js calls', function(done) { document.registerElement('x-element', { prototype: Object.create(HTMLElement.prototype, { @@ -356,18 +358,17 @@ describe('chromium feature', function() { } }) }); - return setImmediate(function() { - var called; - called = false; + setImmediate(function() { + var called = false; Promise.resolve().then(function() { - return done(called ? void 0 : new Error('wrong sequence')); + done(called ? void 0 : new Error('wrong sequence')); }); document.createElement('x-element'); - return called = true; + called = true; }); }); - return it('resolves correctly in Electron calls', function(done) { + it('resolves correctly in Electron calls', function(done) { document.registerElement('y-element', { prototype: Object.create(HTMLElement.prototype, { createdCallback: { @@ -375,14 +376,14 @@ describe('chromium feature', function() { } }) }); - return remote.getGlobal('setImmediate')(function() { + remote.getGlobal('setImmediate')(function() { var called; called = false; Promise.resolve().then(function() { - return done(called ? void 0 : new Error('wrong sequence')); + done(called ? void 0 : new Error('wrong sequence')); }); document.createElement('y-element'); - return called = true; + called = true; }); }); }); diff --git a/spec/modules-spec.js b/spec/modules-spec.js index e3d5bd75c6d..fb53a90cf73 100644 --- a/spec/modules-spec.js +++ b/spec/modules-spec.js @@ -9,40 +9,37 @@ describe('third-party module', function() { if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) { describe('runas', function() { it('can be required in renderer', function() { - return require('runas'); + require('runas'); }); - return it('can be required in node binary', function(done) { - var child, runas; - runas = path.join(fixtures, 'module', 'runas.js'); - child = require('child_process').fork(runas); - return child.on('message', function(msg) { + it('can be required in node binary', function(done) { + var runas = path.join(fixtures, 'module', 'runas.js'); + var child = require('child_process').fork(runas); + child.on('message', function(msg) { assert.equal(msg, 'ok'); - return done(); + done(); }); }); }); describe('ffi', function() { - return it('does not crash', function() { - var ffi, libm; - ffi = require('ffi'); - libm = ffi.Library('libm', { + it('does not crash', function() { + var ffi = require('ffi'); + var libm = ffi.Library('libm', { ceil: ['double', ['double']] }); - return assert.equal(libm.ceil(1.5), 2); + assert.equal(libm.ceil(1.5), 2); }); }); } - return describe('q', function() { - var Q; - Q = require('q'); - return describe('Q.when', function() { - return it('emits the fullfil callback', function(done) { - return Q(true).then(function(val) { + describe('q', function() { + var Q = require('q'); + describe('Q.when', function() { + it('emits the fullfil callback', function(done) { + Q(true).then(function(val) { assert.equal(val, true); - return done(); + done(); }); }); }); diff --git a/spec/node-spec.js b/spec/node-spec.js index 9ead9202653..2961b14b02b 100644 --- a/spec/node-spec.js +++ b/spec/node-spec.js @@ -9,48 +9,45 @@ describe('node feature', function() { var fixtures = path.join(__dirname, 'fixtures'); describe('child_process', function() { - return describe('child_process.fork', function() { + describe('child_process.fork', function() { it('works in current process', function(done) { var child; child = child_process.fork(path.join(fixtures, 'module', 'ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); it('preserves args', function(done) { - var args, child; - args = ['--expose_gc', '-test', '1']; - child = child_process.fork(path.join(fixtures, 'module', 'process_args.js'), args); + var args = ['--expose_gc', '-test', '1']; + var child = child_process.fork(path.join(fixtures, 'module', 'process_args.js'), args); child.on('message', function(msg) { assert.deepEqual(args, msg.slice(2)); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); it('works in forked process', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js')); + var child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); it('works in forked process when options.env is specifed', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js'), [], { + var child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js'), [], { path: process.env['PATH'] }); child.on('message', function(msg) { assert.equal(msg, 'message'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); it('works in browser process', function(done) { @@ -59,9 +56,9 @@ describe('node feature', function() { child = fork(path.join(fixtures, 'module', 'ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); it('has String::localeCompare working in script', function(done) { @@ -69,19 +66,18 @@ describe('node feature', function() { child = child_process.fork(path.join(fixtures, 'module', 'locale-compare.js')); child.on('message', function(msg) { assert.deepEqual(msg, [0, -1, 1]); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); - return it('has setImmediate working in script', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'set-immediate.js')); + it('has setImmediate working in script', function(done) { + var child = child_process.fork(path.join(fixtures, 'module', 'set-immediate.js')); child.on('message', function(msg) { assert.equal(msg, 'ok'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); }); }); @@ -92,18 +88,17 @@ describe('node feature', function() { return; } - return it('does not crash', function(done) { - return fs.readFile(__filename, function() { - return setTimeout(done, 0); + it('does not crash', function(done) { + fs.readFile(__filename, function() { + setTimeout(done, 0); }); }); }); describe('throw error in node context', function() { - return it('gets caught', function(done) { - var error, lsts; - error = new Error('boo!'); - lsts = process.listeners('uncaughtException'); + it('gets caught', function(done) { + var error = new Error('boo!'); + var lsts = process.listeners('uncaughtException'); process.removeAllListeners('uncaughtException'); process.on('uncaughtException', function() { var i, len, lst; @@ -112,28 +107,28 @@ describe('node feature', function() { lst = lsts[i]; process.on('uncaughtException', lst); } - return done(); + done(); }); - return fs.readFile(__filename, function() { + fs.readFile(__filename, function() { throw error; }); }); }); describe('setTimeout called under Chromium event loop in browser process', function() { - return it('can be scheduled in time', function(done) { - return remote.getGlobal('setTimeout')(done, 0); + it('can be scheduled in time', function(done) { + remote.getGlobal('setTimeout')(done, 0); }); }); - return describe('setInterval called under Chromium event loop in browser process', function() { - return it('can be scheduled in time', function(done) { + describe('setInterval called under Chromium event loop in browser process', function() { + it('can be scheduled in time', function(done) { var clear, interval; clear = function() { remote.getGlobal('clearInterval')(interval); - return done(); + done(); }; - return interval = remote.getGlobal('setInterval')(clear, 10); + interval = remote.getGlobal('setInterval')(clear, 10); }); }); }); @@ -141,27 +136,27 @@ describe('node feature', function() { describe('message loop', function() { describe('process.nextTick', function() { it('emits the callback', function(done) { - return process.nextTick(done); + process.nextTick(done); }); - return it('works in nested calls', function(done) { - return process.nextTick(function() { - return process.nextTick(function() { - return process.nextTick(done); + it('works in nested calls', function(done) { + process.nextTick(function() { + process.nextTick(function() { + process.nextTick(done); }); }); }); }); - return describe('setImmediate', function() { + describe('setImmediate', function() { it('emits the callback', function(done) { - return setImmediate(done); + setImmediate(done); }); - return it('works in nested calls', function(done) { - return setImmediate(function() { - return setImmediate(function() { - return setImmediate(done); + it('works in nested calls', function(done) { + setImmediate(function() { + setImmediate(function() { + setImmediate(done); }); }); }); @@ -173,18 +168,18 @@ describe('node feature', function() { return; } - return it('emit error when connect to a socket path without listeners', function(done) { + it('emit error when connect to a socket path without listeners', function(done) { var child, script, socketPath; socketPath = path.join(os.tmpdir(), 'atom-shell-test.sock'); script = path.join(fixtures, 'module', 'create_socket.js'); child = child_process.fork(script, [socketPath]); - return child.on('exit', function(code) { + child.on('exit', function(code) { var client; assert.equal(code, 0); client = require('net').connect(socketPath); - return client.on('error', function(error) { + client.on('error', function(error) { assert.equal(error.code, 'ECONNREFUSED'); - return done(); + done(); }); }); }); @@ -197,16 +192,16 @@ describe('node feature', function() { p.innerText = '闲云潭影日悠悠,物换星移几度秋'; b = new Buffer(p.innerText); assert.equal(b.toString(), '闲云潭影日悠悠,物换星移几度秋'); - return assert.equal(Buffer.byteLength(p.innerText), 45); + assert.equal(Buffer.byteLength(p.innerText), 45); }); - return it('correctly parses external one-byte UTF8 string', function() { + it('correctly parses external one-byte UTF8 string', function() { var b, p; p = document.createElement('p'); p.innerText = 'Jøhänñéß'; b = new Buffer(p.innerText); assert.equal(b.toString(), 'Jøhänñéß'); - return assert.equal(Buffer.byteLength(p.innerText), 13); + assert.equal(Buffer.byteLength(p.innerText), 13); }); }); From 8a9395101e259e6cc16142793654bab16824362c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Feb 2016 17:45:18 -0800 Subject: [PATCH 098/173] Remove unused results --- spec/api-menu-spec.js | 4 ++-- spec/asar-spec.js | 26 +++++++++----------------- spec/chromium-spec.js | 2 +- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/spec/api-menu-spec.js b/spec/api-menu-spec.js index 60464c73275..b27840ec4f2 100644 --- a/spec/api-menu-spec.js +++ b/spec/api-menu-spec.js @@ -271,7 +271,7 @@ describe('menu module', function() { }); it('should assign groupId automatically', function() { - var groupId, i, j, k, l, m, menu, results, template; + var groupId, i, j, k, l, m, menu, template; template = []; for (i = j = 0; j <= 10; i = ++j) { template.push({ @@ -299,7 +299,7 @@ describe('menu module', function() { }); it("setting 'checked' should flip other items' 'checked' property", function() { - var i, j, k, l, m, menu, n, o, p, q, results, template; + var i, j, k, l, m, menu, n, o, p, q, template; template = []; for (i = j = 0; j <= 10; i = ++j) { template.push({ diff --git a/spec/asar-spec.js b/spec/asar-spec.js index d35cf186c65..3bdff95ae3d 100644 --- a/spec/asar-spec.js +++ b/spec/asar-spec.js @@ -138,9 +138,8 @@ describe('asar package', function() { }); it('returns information of a normal file', function() { - var file, j, len, p, ref2, results, stats; + var file, j, len, p, ref2, stats; ref2 = ['file1', 'file2', 'file3', path.join('dir1', 'file1'), path.join('link2', 'file1')]; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); @@ -148,15 +147,13 @@ describe('asar package', function() { assert.equal(stats.isFile(), true); assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), false); - results.push(assert.equal(stats.size, 6)); + assert.equal(stats.size, 6); } - results; }); it('returns information of a normal directory', function() { - var file, j, len, p, ref2, results, stats; + var file, j, len, p, ref2, stats; ref2 = ['dir1', 'dir2', 'dir3']; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); @@ -164,15 +161,13 @@ describe('asar package', function() { assert.equal(stats.isFile(), false); assert.equal(stats.isDirectory(), true); assert.equal(stats.isSymbolicLink(), false); - results.push(assert.equal(stats.size, 0)); + assert.equal(stats.size, 0); } - results; }); it('returns information of a linked file', function() { - var file, j, len, p, ref2, results, stats; + var file, j, len, p, ref2, stats; ref2 = ['link1', path.join('dir1', 'link1'), path.join('link2', 'link2')]; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); @@ -180,15 +175,13 @@ describe('asar package', function() { assert.equal(stats.isFile(), false); assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), true); - results.push(assert.equal(stats.size, 0)); + assert.equal(stats.size, 0); } - results; }); it('returns information of a linked directory', function() { - var file, j, len, p, ref2, results, stats; + var file, j, len, p, ref2, stats; ref2 = ['link2', path.join('dir1', 'link2'), path.join('link2', 'link2')]; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); @@ -196,9 +189,8 @@ describe('asar package', function() { assert.equal(stats.isFile(), false); assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), true); - results.push(assert.equal(stats.size, 0)); + assert.equal(stats.size, 0); } - results; }); it('throws ENOENT error when can not find file', function() { @@ -461,7 +453,7 @@ describe('asar package', function() { describe('fs.openSync', function() { it('opens a normal/linked/under-linked-directory file', function() { - var buffer, fd, file, j, len, p, ref2, results; + var buffer, fd, file, j, len, p, ref2; ref2 = ['file1', 'link1', path.join('link2', 'file1')]; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 9efe22a263c..4b894b4bbc8 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -119,7 +119,7 @@ describe('chromium feature', function() { }); } }); - sw.loadURL(url); + w.loadURL(url); }); }); From 54d7c580bdca5091bf5749058a16f1591bfcc34c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Feb 2016 17:46:44 -0800 Subject: [PATCH 099/173] Remove unneeded returns --- spec/api-protocol-spec.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index a7de60d8c36..215868bfdc8 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -122,7 +122,7 @@ describe('protocol module', function() { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); @@ -310,7 +310,7 @@ describe('protocol module', function() { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, String(fileContent)); @@ -325,7 +325,7 @@ describe('protocol module', function() { it('sets Access-Control-Allow-Origin', function(done) { var handler = function(request, callback) { - return callback(filePath); + callback(filePath); }; protocol.registerFileProtocol(protocolName, handler, function(error) { if (error) { @@ -346,7 +346,7 @@ describe('protocol module', function() { }); it('sends object as response', function(done) { var handler = function(request, callback) { - return callback({ + callback({ path: filePath }); }; @@ -440,7 +440,7 @@ describe('protocol module', function() { res.end(text); server.close(); }); - return server.listen(0, '127.0.0.1', function() { + server.listen(0, '127.0.0.1', function() { var port = server.address().port; var url = "http://127.0.0.1:" + port; var handler = function(request, callback) { @@ -586,7 +586,7 @@ describe('protocol module', function() { var doubleHandler = function(request, callback) { try { callback(text); - return callback(); + callback(); } catch (error) { // Ignore error } From 31028ab6366654d1b52d387d14054a5bd8e7c5bf Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 17 Feb 2016 09:27:25 -0800 Subject: [PATCH 100/173] Update var declarations --- spec/api-app-spec.js | 7 +- spec/api-browser-window-spec.js | 57 ++++++--------- spec/api-crash-reporter-spec.js | 3 +- spec/api-ipc-spec.js | 10 ++- spec/api-session-spec.js | 9 +-- spec/api-web-request-spec.js | 12 ++-- spec/asar-spec.js | 18 ++--- spec/chromium-spec.js | 22 +++--- spec/node-spec.js | 31 ++++---- spec/webview-spec.js | 122 ++++++++++++-------------------- 10 files changed, 110 insertions(+), 181 deletions(-) diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index 7b2535d5404..cbf8223401c 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -66,11 +66,10 @@ describe('app module', function() { }); it('emits a process exit event with the code', function(done) { - var appPath, electronPath, output; - appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app'); - electronPath = remote.getGlobal('process').execPath; + var appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app'); + var electronPath = remote.getGlobal('process').execPath; + var output = ''; appProcess = ChildProcess.spawn(electronPath, [appPath]); - output = ''; appProcess.stdout.on('data', function(data) { output += data; }); diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index b64ef6145b7..58cf57cc8d0 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -42,9 +42,8 @@ describe('browser-window module', function() { w.close(); }); w.on('closed', function() { - var content, test; - test = path.join(fixtures, 'api', 'unload'); - content = fs.readFileSync(test); + var test = path.join(fixtures, 'api', 'unload'); + var content = fs.readFileSync(test); fs.unlinkSync(test); assert.equal(String(content), 'unload'); done(); @@ -66,9 +65,8 @@ describe('browser-window module', function() { describe('window.close()', function() { it('should emit unload handler', function(done) { w.on('closed', function() { - var content, test; - test = path.join(fixtures, 'api', 'close'); - content = fs.readFileSync(test); + var test = path.join(fixtures, 'api', 'close'); + var content = fs.readFileSync(test); fs.unlinkSync(test); assert.equal(String(content), 'close'); done(); @@ -86,8 +84,7 @@ describe('browser-window module', function() { describe('BrowserWindow.destroy()', function() { it('prevents users to access methods of webContents', function() { - var webContents; - webContents = w.webContents; + var webContents = w.webContents; w.destroy(); assert.throws((function() { webContents.getId(); @@ -178,8 +175,7 @@ describe('browser-window module', function() { it('sets the window position', function(done) { var pos = [10, 10]; w.once('move', function() { - var newPos; - newPos = w.getPosition(); + var newPos = w.getPosition(); assert.equal(newPos[0], pos[0]); assert.equal(newPos[1], pos[1]); done(); @@ -190,16 +186,14 @@ describe('browser-window module', function() { describe('BrowserWindow.setContentSize(width, height)', function() { it('sets the content size', function() { - var after, size; - size = [400, 400]; + var size = [400, 400]; w.setContentSize(size[0], size[1]); - after = w.getContentSize(); + var after = w.getContentSize(); assert.equal(after[0], size[0]); assert.equal(after[1], size[1]); }); it('works for framless window', function() { - var after, size; w.destroy(); w = new BrowserWindow({ show: false, @@ -207,9 +201,9 @@ describe('browser-window module', function() { width: 400, height: 400 }); - size = [400, 400]; + var size = [400, 400]; w.setContentSize(size[0], size[1]); - after = w.getContentSize(); + var after = w.getContentSize(); assert.equal(after[0], size[0]); assert.equal(after[1], size[1]); }); @@ -223,7 +217,6 @@ describe('browser-window module', function() { describe('"useContentSize" option', function() { it('make window created with content size when used', function() { - var contentSize; w.destroy(); w = new BrowserWindow({ show: false, @@ -231,7 +224,7 @@ describe('browser-window module', function() { height: 400, useContentSize: true }); - contentSize = w.getContentSize(); + var contentSize = w.getContentSize(); assert.equal(contentSize[0], 400); assert.equal(contentSize[1], 400); }); @@ -243,7 +236,6 @@ describe('browser-window module', function() { }); it('works for framless window', function() { - var contentSize, size; w.destroy(); w = new BrowserWindow({ show: false, @@ -252,10 +244,10 @@ describe('browser-window module', function() { height: 400, useContentSize: true }); - contentSize = w.getContentSize(); + var contentSize = w.getContentSize(); assert.equal(contentSize[0], 400); assert.equal(contentSize[1], 400); - size = w.getSize(); + var size = w.getSize(); assert.equal(size[0], 400); assert.equal(size[1], 400); }); @@ -270,7 +262,6 @@ describe('browser-window module', function() { } it('creates browser window with hidden title bar', function() { - var contentSize; w.destroy(); w = new BrowserWindow({ show: false, @@ -278,12 +269,11 @@ describe('browser-window module', function() { height: 400, titleBarStyle: 'hidden' }); - contentSize = w.getContentSize(); + var contentSize = w.getContentSize(); assert.equal(contentSize[1], 400); }); it('creates browser window with hidden inset title bar', function() { - var contentSize; w.destroy(); w = new BrowserWindow({ show: false, @@ -291,7 +281,7 @@ describe('browser-window module', function() { height: 400, titleBarStyle: 'hidden-inset' }); - contentSize = w.getContentSize(); + var contentSize = w.getContentSize(); assert.equal(contentSize[1], 400); }); }); @@ -312,20 +302,18 @@ describe('browser-window module', function() { }); it('can move the window out of screen', function() { - var after; w.setPosition(-10, -10); - after = w.getPosition(); + var after = w.getPosition(); assert.equal(after[0], -10); assert.equal(after[1], -10); }); it('can set the window larger than screen', function() { - var after, size; - size = screen.getPrimaryDisplay().size; + var size = screen.getPrimaryDisplay().size; size.width += 100; size.height += 100; w.setSize(size.width, size.height); - after = w.getSize(); + var after = w.getSize(); assert.equal(after[0], size.width); assert.equal(after[1], size.height); }); @@ -338,8 +326,7 @@ describe('browser-window module', function() { describe('"preload" option', function() { it('loads the script before other scripts in window', function(done) { - var preload; - preload = path.join(fixtures, 'module', 'set-global.js'); + var preload = path.join(fixtures, 'module', 'set-global.js'); ipcMain.once('answer', function(event, test) { assert.equal(test, 'preload'); done(); @@ -357,8 +344,7 @@ describe('browser-window module', function() { describe('"node-integration" option', function() { it('disables node integration when specified to false', function(done) { - var preload; - preload = path.join(fixtures, 'module', 'send-later.js'); + var preload = path.join(fixtures, 'module', 'send-later.js'); ipcMain.once('answer', function(event, test) { assert.equal(test, 'undefined'); done(); @@ -532,10 +518,9 @@ describe('browser-window module', function() { describe('BrowserWindow options argument is optional', function() { it('should create a window with default size (800x600)', function() { - var size; w.destroy(); w = new BrowserWindow(); - size = w.getSize(); + var size = w.getSize(); assert.equal(size[0], 800); assert.equal(size[1], 600); }); diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index 43830dd4ee1..68dc1375fc3 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -37,9 +37,8 @@ describe('crash-reporter module', function() { var called = false; var server = http.createServer(function(req, res) { - var form; server.close(); - form = new multiparty.Form(); + var form = new multiparty.Form(); form.parse(req, function(error, fields) { if (called) { return; diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index 25d8c925688..2c8bc28f156 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -20,9 +20,8 @@ describe('ipc module', function() { describe('remote.require', function() { it('should returns same object for the same module', function() { - var dialog1, dialog2; - dialog1 = remote.require('electron'); - dialog2 = remote.require('electron'); + var dialog1 = remote.require('electron'); + var dialog2 = remote.require('electron'); assert.equal(dialog1, dialog2); }); @@ -58,9 +57,8 @@ describe('ipc module', function() { }); it('can construct an object from its member', function() { - var call, obj; - call = remote.require(path.join(fixtures, 'module', 'call.js')); - obj = new call.constructor; + var call = remote.require(path.join(fixtures, 'module', 'call.js')); + var obj = new call.constructor; assert.equal(obj.test, 'test'); }); }); diff --git a/spec/api-session-spec.js b/spec/api-session-spec.js index 049309eda58..9fedcc29e77 100644 --- a/spec/api-session-spec.js +++ b/spec/api-session-spec.js @@ -31,15 +31,13 @@ describe('session module', function() { describe('session.cookies', function() { it('should get cookies', function(done) { - var server; - server = http.createServer(function(req, res) { + var server = http.createServer(function(req, res) { res.setHeader('Set-Cookie', ['0=0']); res.end('finished'); server.close(); }); server.listen(0, '127.0.0.1', function() { - var port; - port = server.address().port; + var port = server.address().port; w.loadURL(url + ":" + port); w.webContents.on('did-finish-load', function() { w.webContents.session.cookies.get({ @@ -136,8 +134,7 @@ describe('session module', function() { }); w.loadURL('file://' + path.join(fixtures, 'api', 'localstorage.html')); w.webContents.on('did-finish-load', function() { - var options; - options = { + var options = { origin: "file://", storages: ['localstorage'], quotas: ['persistent'] diff --git a/spec/api-web-request-spec.js b/spec/api-web-request-spec.js index f64c91b610c..77f160a2004 100644 --- a/spec/api-web-request-spec.js +++ b/spec/api-web-request-spec.js @@ -7,9 +7,8 @@ const session = remote.session; describe('webRequest module', function() { var ses = session.defaultSession; var server = http.createServer(function(req, res) { - var content; res.setHeader('Custom', ['Header']); - content = req.url; + var content = req.url; if (req.headers.accept === '*/*;test/header') { content += 'header/received'; } @@ -19,8 +18,7 @@ describe('webRequest module', function() { before(function(done) { server.listen(0, '127.0.0.1', function() { - var port; - port = server.address().port; + var port = server.address().port; defaultURL = "http://127.0.0.1:" + port + "/"; done(); }); @@ -109,11 +107,10 @@ describe('webRequest module', function() { type: 'string' }; ses.webRequest.onBeforeRequest(function(details, callback) { - var data; assert.equal(details.url, defaultURL); assert.equal(details.method, 'POST'); assert.equal(details.uploadData.length, 1); - data = qs.parse(details.uploadData[0].bytes.toString()); + var data = qs.parse(details.uploadData[0].bytes.toString()); assert.deepEqual(data, postData); callback({ cancel: true @@ -178,8 +175,7 @@ describe('webRequest module', function() { it('can change the request headers', function(done) { ses.webRequest.onBeforeSendHeaders(function(details, callback) { - var requestHeaders; - requestHeaders = details.requestHeaders; + var requestHeaders = details.requestHeaders; requestHeaders.Accept = '*/*;test/header'; callback({ requestHeaders: requestHeaders diff --git a/spec/asar-spec.js b/spec/asar-spec.js index 3bdff95ae3d..060074390f1 100644 --- a/spec/asar-spec.js +++ b/spec/asar-spec.js @@ -128,9 +128,8 @@ describe('asar package', function() { }); it('returns information of root', function() { - var p, stats; - p = path.join(fixtures, 'asar', 'a.asar'); - stats = fs.lstatSync(p); + var p = path.join(fixtures, 'asar', 'a.asar'); + var stats = fs.lstatSync(p); assert.equal(stats.isFile(), false); assert.equal(stats.isDirectory(), true); assert.equal(stats.isSymbolicLink(), false); @@ -607,9 +606,8 @@ describe('asar package', function() { }); it('disables asar support in async API', function(done) { - var dir, file; - file = path.join(fixtures, 'asar', 'a.asar', 'file1'); - dir = path.join(fixtures, 'asar', 'a.asar', 'dir1'); + var file = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var dir = path.join(fixtures, 'asar', 'a.asar', 'dir1'); fs.readFile(file, function(error) { assert.equal(error.code, errorName); fs.lstat(file, function(error) { @@ -737,15 +735,13 @@ describe('asar package', function() { var originalFs = require('original-fs'); it('treats .asar as file', function() { - var file, stats; - file = path.join(fixtures, 'asar', 'a.asar'); - stats = originalFs.statSync(file); + var file = path.join(fixtures, 'asar', 'a.asar'); + var stats = originalFs.statSync(file); assert(stats.isFile()); }); it('is available in forked scripts', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'original-fs.js')); + var child = child_process.fork(path.join(fixtures, 'module', 'original-fs.js')); child.on('message', function(msg) { assert.equal(msg, 'object'); done(); diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 4b894b4bbc8..e4444f55b11 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -211,10 +211,9 @@ describe('chromium feature', function() { var b, sourceId; sourceId = remote.getCurrentWindow().id; listener = function(event) { - var message; window.removeEventListener('message', listener); b.close(); - message = JSON.parse(event.data); + var message = JSON.parse(event.data); assert.equal(message.data, 'testing'); assert.equal(message.origin, 'file://'); assert.equal(message.sourceEqualsOpener, true); @@ -247,28 +246,25 @@ describe('chromium feature', function() { describe('creating a Uint8Array under browser side', function() { it('does not crash', function() { - var RUint8Array; - RUint8Array = remote.getGlobal('Uint8Array'); + var RUint8Array = remote.getGlobal('Uint8Array'); new RUint8Array; }); }); describe('webgl', function() { it('can be get as context in canvas', function() { - var webgl; if (process.platform === 'linux') { return; } - webgl = document.createElement('canvas').getContext('webgl'); + var webgl = document.createElement('canvas').getContext('webgl'); assert.notEqual(webgl, null); }); }); describe('web workers', function() { it('Worker can work', function(done) { - var message, worker; - worker = new Worker('../fixtures/workers/worker.js'); - message = 'ping'; + var worker = new Worker('../fixtures/workers/worker.js'); + var message = 'ping'; worker.onmessage = function(event) { assert.equal(event.data, message); worker.terminate(); @@ -278,9 +274,8 @@ describe('chromium feature', function() { }); it('SharedWorker can work', function(done) { - var message, worker; - worker = new SharedWorker('../fixtures/workers/shared_worker.js'); - message = 'ping'; + var worker = new SharedWorker('../fixtures/workers/shared_worker.js'); + var message = 'ping'; worker.port.onmessage = function(event) { assert.equal(event.data, message); done(); @@ -377,8 +372,7 @@ describe('chromium feature', function() { }) }); remote.getGlobal('setImmediate')(function() { - var called; - called = false; + var called = false; Promise.resolve().then(function() { done(called ? void 0 : new Error('wrong sequence')); }); diff --git a/spec/node-spec.js b/spec/node-spec.js index 2961b14b02b..83f685d95f0 100644 --- a/spec/node-spec.js +++ b/spec/node-spec.js @@ -11,8 +11,7 @@ describe('node feature', function() { describe('child_process', function() { describe('child_process.fork', function() { it('works in current process', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'ping.js')); + var child = child_process.fork(path.join(fixtures, 'module', 'ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); done(); @@ -51,9 +50,8 @@ describe('node feature', function() { }); it('works in browser process', function(done) { - var child, fork; - fork = remote.require('child_process').fork; - child = fork(path.join(fixtures, 'module', 'ping.js')); + var fork = remote.require('child_process').fork; + var child = fork(path.join(fixtures, 'module', 'ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); done(); @@ -62,8 +60,7 @@ describe('node feature', function() { }); it('has String::localeCompare working in script', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'locale-compare.js')); + var child = child_process.fork(path.join(fixtures, 'module', 'locale-compare.js')); child.on('message', function(msg) { assert.deepEqual(msg, [0, -1, 1]); done(); @@ -169,14 +166,12 @@ describe('node feature', function() { } it('emit error when connect to a socket path without listeners', function(done) { - var child, script, socketPath; - socketPath = path.join(os.tmpdir(), 'atom-shell-test.sock'); - script = path.join(fixtures, 'module', 'create_socket.js'); - child = child_process.fork(script, [socketPath]); + var socketPath = path.join(os.tmpdir(), 'atom-shell-test.sock'); + var script = path.join(fixtures, 'module', 'create_socket.js'); + var child = child_process.fork(script, [socketPath]); child.on('exit', function(code) { - var client; assert.equal(code, 0); - client = require('net').connect(socketPath); + var client = require('net').connect(socketPath); client.on('error', function(error) { assert.equal(error.code, 'ECONNREFUSED'); done(); @@ -187,19 +182,17 @@ describe('node feature', function() { describe('Buffer', function() { it('can be created from WebKit external string', function() { - var b, p; - p = document.createElement('p'); + var p = document.createElement('p'); p.innerText = '闲云潭影日悠悠,物换星移几度秋'; - b = new Buffer(p.innerText); + var b = new Buffer(p.innerText); assert.equal(b.toString(), '闲云潭影日悠悠,物换星移几度秋'); assert.equal(Buffer.byteLength(p.innerText), 45); }); it('correctly parses external one-byte UTF8 string', function() { - var b, p; - p = document.createElement('p'); + var p = document.createElement('p'); p.innerText = 'Jøhänñéß'; - b = new Buffer(p.innerText); + var b = new Buffer(p.innerText); assert.equal(b.toString(), 'Jøhänñéß'); assert.equal(Buffer.byteLength(p.innerText), 13); }); diff --git a/spec/webview-spec.js b/spec/webview-spec.js index a18e152ea6a..54b544def0d 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -95,8 +95,7 @@ describe(' tag', function() { describe('preload attribute', function() { it('loads the script before other scripts in window', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.message, 'function object object'); webview.removeEventListener('console-message', listener); done(); @@ -118,15 +117,14 @@ describe(' tag', function() { }); it('receives ipc message in preload script', function(done) { - var listener, listener2, message; - message = 'boom!'; - listener = function(e) { + var message = 'boom!'; + var listener = function(e) { assert.equal(e.channel, 'pong'); assert.deepEqual(e.args, [message]); webview.removeEventListener('ipc-message', listener); done(); }; - listener2 = function() { + var listener2 = function() { webview.send('ping', message); webview.removeEventListener('did-finish-load', listener2); }; @@ -140,9 +138,8 @@ describe(' tag', function() { describe('httpreferrer attribute', function() { it('sets the referrer url', function(done) { - var listener, referrer; - referrer = 'http://github.com/'; - listener = function(e) { + var referrer = 'http://github.com/'; + var listener = function(e) { assert.equal(e.message, referrer); webview.removeEventListener('console-message', listener); done(); @@ -156,9 +153,8 @@ describe(' tag', function() { describe('useragent attribute', function() { it('sets the user agent', function(done) { - var listener, referrer; - referrer = 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'; - listener = function(e) { + var referrer = 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'; + var listener = function(e) { assert.equal(e.message, referrer); webview.removeEventListener('console-message', listener); done(); @@ -172,10 +168,9 @@ describe(' tag', function() { describe('disablewebsecurity attribute', function() { it('does not disable web security when not set', function(done) { - var encoded, listener, src; - src = " "; - encoded = btoa(unescape(encodeURIComponent(src))); - listener = function(e) { + var src = " "; + var encoded = btoa(unescape(encodeURIComponent(src))); + var listener = function(e) { assert(/Not allowed to load local resource/.test(e.message)); webview.removeEventListener('console-message', listener); done(); @@ -186,10 +181,9 @@ describe(' tag', function() { }); it('disables web security when set', function(done) { - var encoded, listener, src; - src = " "; - encoded = btoa(unescape(encodeURIComponent(src))); - listener = function(e) { + var src = " "; + var encoded = btoa(unescape(encodeURIComponent(src))); + var listener = function(e) { assert.equal(e.message, 'ok'); webview.removeEventListener('console-message', listener); done(); @@ -223,8 +217,7 @@ describe(' tag', function() { }); it('isolates storage for different id', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.message, " 0"); webview.removeEventListener('console-message', listener); done(); @@ -237,8 +230,7 @@ describe(' tag', function() { }); it('uses current session storage when no id is provided', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.message, "one 1"); webview.removeEventListener('console-message', listener); done(); @@ -252,8 +244,7 @@ describe(' tag', function() { describe('allowpopups attribute', function() { it('can not open new window when not set', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.message, 'null'); webview.removeEventListener('console-message', listener); done(); @@ -264,8 +255,7 @@ describe(' tag', function() { }); it('can open new window when set', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.message, 'window'); webview.removeEventListener('console-message', listener); done(); @@ -327,9 +317,8 @@ describe(' tag', function() { describe('page-favicon-updated event', function() { it('emits when favicon urls are received', function(done) { webview.addEventListener('page-favicon-updated', function(e) { - var pageUrl; assert.equal(e.favicons.length, 2); - pageUrl = process.platform === 'win32' ? 'file:///C:/favicon.png' : 'file:///favicon.png'; + var pageUrl = process.platform === 'win32' ? 'file:///C:/favicon.png' : 'file:///favicon.png'; assert.equal(e.favicons[0], pageUrl); done(); }); @@ -350,10 +339,9 @@ describe(' tag', function() { }); describe('did-navigate event', function() { - var p, pageUrl; - p = path.join(fixtures, 'pages', 'webview-will-navigate.html'); + var p = path.join(fixtures, 'pages', 'webview-will-navigate.html'); p = p.replace(/\\/g, '/'); - pageUrl = url.format({ + var pageUrl = url.format({ protocol: 'file', slashes: true, pathname: p @@ -370,10 +358,9 @@ describe(' tag', function() { }); describe('did-navigate-in-page event', function() { it('emits when an anchor link is clicked', function(done) { - var p, pageUrl; - p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page.html'); + var p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page.html'); p = p.replace(/\\/g, '/'); - pageUrl = url.format({ + var pageUrl = url.format({ protocol: 'file', slashes: true, pathname: p @@ -396,10 +383,9 @@ describe(' tag', function() { }); it('emits when window.location.hash is changed', function(done) { - var p, pageUrl; - p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page-with-hash.html'); + var p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page-with-hash.html'); p = p.replace(/\\/g, '/'); - pageUrl = url.format({ + var pageUrl = url.format({ protocol: 'file', slashes: true, pathname: p @@ -425,8 +411,7 @@ describe(' tag', function() { describe('devtools-opened event', function() { it('should fire when webview.openDevTools() is called', function(done) { - var listener; - listener = function() { + var listener = function() { webview.removeEventListener('devtools-opened', listener); webview.closeDevTools(); done(); @@ -442,12 +427,11 @@ describe(' tag', function() { describe('devtools-closed event', function() { it('should fire when webview.closeDevTools() is called', function(done) { - var listener, listener2; - listener2 = function() { + var listener2 = function() { webview.removeEventListener('devtools-closed', listener2); done(); }; - listener = function() { + var listener = function() { webview.removeEventListener('devtools-opened', listener); webview.closeDevTools(); }; @@ -463,8 +447,7 @@ describe(' tag', function() { describe('devtools-focused event', function() { it('should fire when webview.openDevTools() is called', function(done) { - var listener; - listener = function() { + var listener = function() { webview.removeEventListener('devtools-focused', listener); webview.closeDevTools(); done(); @@ -480,13 +463,12 @@ describe(' tag', function() { describe('.reload()', function() { it('should emit beforeunload handler', function(done) { - var listener, listener2; - listener = function(e) { + var listener = function(e) { assert.equal(e.channel, 'onbeforeunload'); webview.removeEventListener('ipc-message', listener); done(); }; - listener2 = function() { + var listener2 = function() { webview.reload(); webview.removeEventListener('did-finish-load', listener2); }; @@ -500,8 +482,7 @@ describe(' tag', function() { describe('.clearHistory()', function() { it('should clear the navigation history', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.channel, 'history'); assert.equal(e.args[0], 2); assert(webview.canGoBack()); @@ -518,14 +499,12 @@ describe(' tag', function() { }); describe('basic auth', function() { - var auth; - auth = require('basic-auth'); + var auth = require('basic-auth'); + it('should authenticate with correct credentials', function(done) { - var message, server; - message = 'Authenticated'; - server = http.createServer(function(req, res) { - var credentials; - credentials = auth(req); + var message = 'Authenticated'; + var server = http.createServer(function(req, res) { + var credentials = auth(req); if (credentials.name === 'test' && credentials.pass === 'test') { res.end(message); } else { @@ -534,8 +513,7 @@ describe(' tag', function() { server.close(); }); server.listen(0, '127.0.0.1', function() { - var port; - port = server.address().port; + var port = server.address().port; webview.addEventListener('ipc-message', function(e) { assert.equal(e.channel, message); done(); @@ -549,11 +527,9 @@ describe(' tag', function() { describe('dom-ready event', function() { it('emits when document is loaded', function(done) { - var server; - server = http.createServer(function() {}); + var server = http.createServer(function() {}); server.listen(0, '127.0.0.1', function() { - var port; - port = server.address().port; + var port = server.address().port; webview.addEventListener('dom-ready', function() { done(); }); @@ -575,14 +551,12 @@ describe(' tag', function() { } it('should support user gesture', function(done) { - var listener, listener2; - listener = function() { + var listener = function() { webview.removeEventListener('enter-html-full-screen', listener); done(); }; - listener2 = function() { - var jsScript; - jsScript = 'document.getElementsByTagName("video")[0].webkitRequestFullScreen()'; + var listener2 = function() { + var jsScript = 'document.getElementsByTagName("video")[0].webkitRequestFullScreen()'; webview.executeJavaScript(jsScript, true); webview.removeEventListener('did-finish-load', listener2); }; @@ -634,8 +608,7 @@ describe(' tag', function() { describe('media-started-playing media-paused events', function() { it('emits when audio starts and stops playing', function(done) { - var audioPlayed; - audioPlayed = false; + var audioPlayed = false; webview.addEventListener('media-started-playing', function() { audioPlayed = true; }); @@ -650,9 +623,8 @@ describe(' tag', function() { describe('found-in-page event', function() { it('emits when a request is made', function(done) { - var listener, listener2, requestId; - requestId = null; - listener = function(e) { + var requestId = null; + var listener = function(e) { assert.equal(e.result.requestId, requestId); if (e.result.finalUpdate) { assert.equal(e.result.matches, 3); @@ -660,7 +632,7 @@ describe(' tag', function() { done(); } }; - listener2 = function() { + var listener2 = function() { requestId = webview.findInPage("virtual"); }; webview.addEventListener('found-in-page', listener); From a252b9b5702ae171af8a56d9ca73d3c20814d8c2 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 17 Feb 2016 16:31:26 -0500 Subject: [PATCH 101/173] Initial ISSUE_TEMPLATE draft --- ISSUE_TEMPLATE.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 ISSUE_TEMPLATE.md diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 00000000000..b19649cad84 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,24 @@ +### Flow + +* [ ] Bug + * [ ] Did you create a code snippet that reliably reproduces the issue in an isolated environment? + * [ ] Did you include what operating system you were on? + * [ ] Did you [perform a cursory search](https://github.com/issues?q=is%3Aissue+repo%3Aatom%2Felectron) to see if it is already reported? + * For more information on how to write a good bug report [look at the CONTRIBUTING guide](https://github.com/atom/electron/blob/master/CONTRIBUTING.md#submitting-issues). +* [ ] Enhancement + * [ ] Are you running the [latest version of Electron](https://github.com/atom/electron/releases)? + * [ ] Did you [perform a cursory search](https://github.com/issues?q=is%3Aissue+repo%3Aatom%2Felectron) to see if it is already requested? + +### Description + +[Description of the bug or feature] + +### Repro Steps + +1. [First Step] +2. [Second Step] +3. [and so on...] + +**Expected:** [What you expected to happen] + +**Actual:** [What actually happened] From 7bf17f2541680835fa60f9666becb6224061ae41 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 18 Feb 2016 01:15:00 +0100 Subject: [PATCH 102/173] Improved frame subscriber - now we only use framesubscription events as an event, and we copy from the backing store directly (instead of accessing it through a videoframe) --- atom/browser/api/atom_api_web_contents.cc | 2 +- atom/browser/api/frame_subscriber.cc | 63 ++++++++++++++--------- atom/browser/api/frame_subscriber.h | 10 ++-- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index b04553e654b..6531874e6a9 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1065,7 +1065,7 @@ void WebContents::BeginFrameSubscription( const auto view = web_contents()->GetRenderWidgetHostView(); if (view) { FrameSubscriber* frame_subscriber = new FrameSubscriber( - isolate(), view->GetVisibleViewportSize(), callback); + isolate(), view, callback); scoped_ptr del_frame_subscriber( frame_subscriber->GetSubscriber()); view->BeginFrameSubscription(del_frame_subscriber.Pass()); diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index 7d973892405..60bf84c0eb9 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -8,6 +8,8 @@ #include "base/bind.h" #include "media/base/video_frame.h" #include "media/base/yuv_convert.h" +#include "content/public/browser/render_widget_host.h" +#include "ui/gfx/screen.h" namespace atom { @@ -16,10 +18,11 @@ namespace api { using Subscriber = FrameSubscriber::Subscriber; FrameSubscriber::FrameSubscriber(v8::Isolate* isolate, - const gfx::Size& size, + content::RenderWidgetHostView* view, const FrameCaptureCallback& callback) - : isolate_(isolate), size_(size), callback_(callback), pending_frames(0) { + : isolate_(isolate), callback_(callback), pending_frames(0), view_(view) { subscriber_ = new Subscriber(this); + size_ = view->GetVisibleViewportSize(); } Subscriber::Subscriber( @@ -36,14 +39,32 @@ bool Subscriber::ShouldCaptureFrame( base::TimeTicks present_time, scoped_refptr* storage, DeliverFrameCallback* callback) { - *storage = media::VideoFrame::CreateFrame( - media::PIXEL_FORMAT_YV12, - frame_subscriber_->size_, gfx::Rect(frame_subscriber_->size_), - frame_subscriber_->size_, base::TimeDelta()); - *callback = base::Bind(&FrameSubscriber::OnFrameDelivered, - base::Unretained(frame_subscriber_), *storage); + const auto view = frame_subscriber_->view_; + const auto host = view ? view->GetRenderWidgetHost() : nullptr; + if (!view || !host) { + return false; + } + + const gfx::Size view_size = view->GetViewBounds().size(); + + gfx::Size bitmap_size = view_size; + const gfx::NativeView native_view = view->GetNativeView(); + gfx::Screen* const screen = gfx::Screen::GetScreenFor(native_view); + const float scale = + screen->GetDisplayNearestWindow(native_view).device_scale_factor(); + if (scale > 1.0f) + bitmap_size = gfx::ScaleToCeiledSize(view_size, scale); + + host->CopyFromBackingStore( + gfx::Rect(view_size), + bitmap_size, + base::Bind(&FrameSubscriber::OnFrameDelivered, + base::Unretained(frame_subscriber_), + frame_subscriber_->callback_), + kBGRA_8888_SkColorType); + frame_subscriber_->pending_frames++; - return true; + return false; } Subscriber* FrameSubscriber::GetSubscriber() { @@ -60,33 +81,25 @@ bool FrameSubscriber::RequestDestruct() { return deletable; } -void FrameSubscriber::OnFrameDelivered( - scoped_refptr frame, base::TimeTicks, bool result) { +void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback, + const SkBitmap& bitmap, content::ReadbackResponse response){ pending_frames--; - if (RequestDestruct() || subscriber_ == NULL || !result) + if (RequestDestruct() || subscriber_ == NULL || bitmap.computeSize64() == 0) return; v8::Locker locker(isolate_); v8::HandleScope handle_scope(isolate_); - gfx::Rect rect = frame->visible_rect(); - size_t rgb_arr_size = rect.width() * rect.height() * 4; + size_t rgb_arr_size = bitmap.width() * bitmap.height() * + bitmap.bytesPerPixel(); v8::MaybeLocal buffer = node::Buffer::New(isolate_, rgb_arr_size); if (buffer.IsEmpty()) return; - // Convert a frame of YUV to 32 bit ARGB. - media::ConvertYUVToRGB32(frame->data(media::VideoFrame::kYPlane), - frame->data(media::VideoFrame::kUPlane), - frame->data(media::VideoFrame::kVPlane), - reinterpret_cast( - node::Buffer::Data(buffer.ToLocalChecked())), - rect.width(), rect.height(), - frame->stride(media::VideoFrame::kYPlane), - frame->stride(media::VideoFrame::kUVPlane), - rect.width() * 4, - media::YV12); + bitmap.copyPixelsTo( + reinterpret_cast(node::Buffer::Data(buffer.ToLocalChecked())), + rgb_arr_size); callback_.Run(buffer.ToLocalChecked()); } diff --git a/atom/browser/api/frame_subscriber.h b/atom/browser/api/frame_subscriber.h index 6f6d66b6be8..745cf382adb 100644 --- a/atom/browser/api/frame_subscriber.h +++ b/atom/browser/api/frame_subscriber.h @@ -6,7 +6,10 @@ #define ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_ #include "base/callback.h" +#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view_frame_subscriber.h" +#include "content/public/browser/readback_types.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/size.h" #include "v8/include/v8.h" @@ -35,19 +38,20 @@ class FrameSubscriber { }; FrameSubscriber(v8::Isolate* isolate, - const gfx::Size& size, + content::RenderWidgetHostView* view, const FrameCaptureCallback& callback); Subscriber* GetSubscriber(); private: - void OnFrameDelivered( - scoped_refptr frame, base::TimeTicks, bool); + void OnFrameDelivered(const FrameCaptureCallback& callback, + const SkBitmap& bitmap, content::ReadbackResponse response); bool RequestDestruct(); v8::Isolate* isolate_; gfx::Size size_; + content::RenderWidgetHostView* view_; FrameCaptureCallback callback_; Subscriber* subscriber_; int pending_frames; From 2610aa60e955cb34271d57c062e5962e58325652 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 18 Feb 2016 01:19:41 +0100 Subject: [PATCH 103/173] :art: lint fix --- atom/browser/api/frame_subscriber.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index 60bf84c0eb9..ec3bcd05ab7 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -41,9 +41,8 @@ bool Subscriber::ShouldCaptureFrame( DeliverFrameCallback* callback) { const auto view = frame_subscriber_->view_; const auto host = view ? view->GetRenderWidgetHost() : nullptr; - if (!view || !host) { + if (!view || !host) return false; - } const gfx::Size view_size = view->GetViewBounds().size(); @@ -82,7 +81,7 @@ bool FrameSubscriber::RequestDestruct() { } void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback, - const SkBitmap& bitmap, content::ReadbackResponse response){ + const SkBitmap& bitmap, content::ReadbackResponse response) { pending_frames--; if (RequestDestruct() || subscriber_ == NULL || bitmap.computeSize64() == 0) From f81f4479b62b02a2dab8804ba8968c76b29dfa4f Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 17 Feb 2016 21:29:36 -0500 Subject: [PATCH 104/173] Drastically simplify the template [ci skip] --- ISSUE_TEMPLATE.md | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index b19649cad84..4b32023e925 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,24 +1,11 @@ -### Flow +### Prerequisites -* [ ] Bug - * [ ] Did you create a code snippet that reliably reproduces the issue in an isolated environment? - * [ ] Did you include what operating system you were on? - * [ ] Did you [perform a cursory search](https://github.com/issues?q=is%3Aissue+repo%3Aatom%2Felectron) to see if it is already reported? - * For more information on how to write a good bug report [look at the CONTRIBUTING guide](https://github.com/atom/electron/blob/master/CONTRIBUTING.md#submitting-issues). -* [ ] Enhancement - * [ ] Are you running the [latest version of Electron](https://github.com/atom/electron/releases)? - * [ ] Did you [perform a cursory search](https://github.com/issues?q=is%3Aissue+repo%3Aatom%2Felectron) to see if it is already requested? +* [ ] Did you [perform a cursory search](https://github.com/issues?q=is%3Aissue+repo%3Aatom%2Felectron) to see if it is already reported? ### Description -[Description of the bug or feature] +[Description of the bug or feature, for example, what you were doing when the issue arose and what you expected to happen] -### Repro Steps +Electron version: -1. [First Step] -2. [Second Step] -3. [and so on...] - -**Expected:** [What you expected to happen] - -**Actual:** [What actually happened] +Operating system: From 1f248e6ea6e966c3023c5520aa3d91c07b393564 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 17 Feb 2016 21:41:14 -0500 Subject: [PATCH 105/173] :memo: Move Electron and OS versions above the description [ci skip] --- ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 4b32023e925..d2d66066f40 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -4,8 +4,8 @@ ### Description -[Description of the bug or feature, for example, what you were doing when the issue arose and what you expected to happen] - Electron version: Operating system: + +[Description of the bug or feature, for example, what you were doing when the issue arose and what you expected to happen] From 651264d098f05735473fde1dae2636fb0af35268 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 18 Feb 2016 11:39:35 +0800 Subject: [PATCH 106/173] spec: Fix failing tests on Windows --- spec/api-debugger-spec.js | 4 +++- vendor/node | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/spec/api-debugger-spec.js b/spec/api-debugger-spec.js index 714d5fda48c..56b642e76e4 100644 --- a/spec/api-debugger-spec.js +++ b/spec/api-debugger-spec.js @@ -95,7 +95,9 @@ describe('debugger module', function() { }); it('fires message event', function(done) { - var url = 'file://' + path.join(fixtures, 'pages', 'a.html'); + var url = process.platform != 'win32' ? + 'file://' + path.join(fixtures, 'pages', 'a.html') : + 'file:///' + path.join(fixtures, 'pages', 'a.html').replace(/\\/g, '/'); w.webContents.loadURL(url); try { w.webContents.debugger.attach(); diff --git a/vendor/node b/vendor/node index a130651f868..a507a3c3816 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit a130651f868f5ad23cb366abacea02f9ed50b769 +Subproject commit a507a3c3816d6ac085ed46250c489a3d76ab8b3c From 1e894df102f685f0959f8137d83176c93d457930 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 18 Feb 2016 12:14:25 +0800 Subject: [PATCH 107/173] Update libchromiumcontent, fix #3666 --- script/lib/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/lib/config.py b/script/lib/config.py index 004e87dd070..02e06948866 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '1be1a55abba527d6fb0fc2a589cbaef2f5a6a79e' +LIBCHROMIUMCONTENT_COMMIT = 'fc5174471ccccce7030d0960f5228e73ca7c2ac6' PLATFORM = { 'cygwin': 'win32', From 9c9759a683436a8d35ec593ecc18512d47512fb9 Mon Sep 17 00:00:00 2001 From: Jacob Page Date: Wed, 17 Feb 2016 21:30:01 -0800 Subject: [PATCH 108/173] Link to Menu documentation Added link to documentation about `Menu` objects --- docs/api/app.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/app.md b/docs/api/app.md index f88d0297994..b5f8e919b82 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -515,7 +515,7 @@ Shows the dock icon. ### `app.dock.setMenu(menu)` _OS X_ -* `menu` Menu +* `menu` [Menu](menu.md) Sets the application's [dock menu][dock-menu]. From 12569f2c9d7a21eda65fd0656f92d2aedea35f68 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 18 Feb 2016 18:32:13 +0800 Subject: [PATCH 109/173] mac: Simulate the behavior of cmd+~ when OS X didn't handle it --- atom/browser/native_window_mac.mm | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 7967a177173..9d9f2a2392d 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -892,12 +892,25 @@ void NativeWindowMac::HandleKeyboardEvent( return; BOOL handled = [[NSApp mainMenu] performKeyEquivalent:event.os_event]; - if (!handled && event.os_event.window != window_.get()) { - // The event comes from detached devtools view, and it has already been - if (!handled && (event.os_event.modifierFlags & NSCommandKeyMask) && - (event.os_event.keyCode == 50 /* ~ key */)) { - // Handle the cmd+~ shortcut. - Focus(true); + if (!handled && event.os_event.window) { + // Handle the cmd+~ shortcut. + if ((event.os_event.modifierFlags & NSCommandKeyMask) /* cmd */ && + (event.os_event.keyCode == 50 /* ~ */)) { + // Switch to next visible window. + NSArray* windows = [NSApp windows]; + NSIndexSet* indexes = [windows indexesOfObjectsPassingTest: + ^BOOL(id window, NSUInteger idx, BOOL* stop) { + return [window isVisible]; + }]; + if ([indexes count] == 0) + return; + NSUInteger current = [windows indexOfObject:event.os_event.window]; + if (current == NSNotFound) // Some faked event. + return; + NSUInteger next = [indexes indexGreaterThanIndex:current]; + if (next == NSNotFound) + next = [indexes firstIndex]; + [[windows objectAtIndex:next] makeKeyAndOrderFront:nil]; } } } From 35815387abd1bbbc147a73a8161a99f7111e8691 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 18 Feb 2016 18:57:31 +0800 Subject: [PATCH 110/173] Ship ffmpeg in dist, close #4536 --- script/create-dist.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/script/create-dist.py b/script/create-dist.py index a619e04d3ea..2ec67d4f6c5 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -38,6 +38,7 @@ TARGET_BINARIES = { 'libGLESv2.dll', 'msvcp120.dll', 'msvcr120.dll', + 'ffmpeg.dll', 'node.dll', 'pdf.dll', 'content_resources_200_percent.pak', @@ -51,6 +52,7 @@ TARGET_BINARIES = { PROJECT_NAME, # 'electron' 'content_shell.pak', 'icudtl.dat', + 'libffmpeg.so', 'libnode.so', 'natives_blob.bin', 'snapshot_blob.bin', From 0d77fd4a2c7af3ac05d7c4a023e28c8420e6c20c Mon Sep 17 00:00:00 2001 From: Robo Date: Wed, 17 Feb 2016 13:27:46 +0530 Subject: [PATCH 111/173] remote: return webcontents instance from cache --- atom/renderer/api/lib/remote.js | 7 +++++++ spec/api-ipc-spec.js | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/atom/renderer/api/lib/remote.js b/atom/renderer/api/lib/remote.js index ad01e77ac51..d8a5508621e 100644 --- a/atom/renderer/api/lib/remote.js +++ b/atom/renderer/api/lib/remote.js @@ -1,11 +1,14 @@ const ipcRenderer = require('electron').ipcRenderer; const CallbacksRegistry = require('electron').CallbacksRegistry; const v8Util = process.atomBinding('v8_util'); +const IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap; const callbacksRegistry = new CallbacksRegistry; var includes = [].includes; +var remoteObjectCache = new IDWeakMap; + // Check for circular reference. var isCircular = function(field, visited) { if (typeof field === 'object') { @@ -154,6 +157,9 @@ var metaToValue = function(meta) { } } + if (remoteObjectCache.has(meta.id)) + return remoteObjectCache.get(meta.id); + // Track delegate object's life time, and tell the browser to clean up // when the object is GCed. v8Util.setDestructor(ret, function() { @@ -162,6 +168,7 @@ var metaToValue = function(meta) { // Remember object's id. v8Util.setHiddenValue(ret, 'atomId', meta.id); + remoteObjectCache.set(meta.id, ret); return ret; } }; diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index 2c8bc28f156..9cf741412b0 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -90,6 +90,14 @@ describe('ipc module', function() { }); }); + describe('remote webContents', function() { + it('can return same object with different getters', function() { + var contents1 = remote.getCurrentWindow().webContents; + var contents2 = remote.getCurrentWebContents(); + assert(contents1 == contents2); + }); + }); + describe('ipc.sender.send', function() { it('should work when sending an object containing id property', function(done) { var obj = { From 68f48c9456dbca1d5e84b92f3d93ffa8e0808c7a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 18 Feb 2016 23:28:19 +0800 Subject: [PATCH 112/173] docs: Add note on Chrome version when using widevine Refs #4519. --- docs/tutorial/using-widevine-cdm-plugin.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/tutorial/using-widevine-cdm-plugin.md b/docs/tutorial/using-widevine-cdm-plugin.md index 340dad343c8..630c18ab8e5 100644 --- a/docs/tutorial/using-widevine-cdm-plugin.md +++ b/docs/tutorial/using-widevine-cdm-plugin.md @@ -8,6 +8,10 @@ Electron doesn't ship with the Widevine CDM plugin for license reasons, to get it, you need to install the official Chrome browser first, which should match the architecture and Chrome version of the Electron build you use. +__Note:__ The major version of Chrome browser has to be the same with the Chrome +version used by Electron, otherwise the plugin will not work even though +`navigator.plugins` would show it has been loaded. + ### Windows & OS X Open `chrome://components/` in Chrome browser, find `WidevineCdm` and make From 8ce3ab1e262ef4ab641d3083ce5be711ea8afd0d Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 17 Feb 2016 22:46:36 +0900 Subject: [PATCH 113/173] :memo: Update as upstream [ci skip] --- docs-translations/ko-KR/api/app.md | 2 +- docs-translations/ko-KR/api/session.md | 9 ++++++++- docs-translations/ko-KR/api/shell.md | 8 ++++++-- docs-translations/ko-KR/api/tray.md | 7 +++++++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index 32412d13180..89cc1732263 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -523,7 +523,7 @@ dock 아이콘을 표시합니다. ### `app.dock.setMenu(menu)` _OS X_ -* `menu` Menu +* `menu` [Menu](menu.md) 어플리케이션의 [dock menu][dock-menu]를 설정합니다. diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index 5598fb6eb26..5bb4867eda0 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -59,7 +59,8 @@ var ses = session.fromPartition('persist:name'); Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이벤트입니다. -`event.preventDefault()` 메서드를 호출하면 다운로드를 취소합니다. +`event.preventDefault()` 메서드를 호출하면 다운로드를 취소하고, 프로세스의 다음 +틱부터 `item`을 사용할 수 없게 됩니다. ```javascript session.defaultSession.on('will-download', function(event, item, webContents) { @@ -313,6 +314,12 @@ session.fromPartition(partition).setPermissionRequestHandler(function(webContent }); ``` +#### `ses.clearHostResolverCache([callback])` + +* `callback` Function (optional) - 작업이 완료되면 호출됩니다. + +호스트 리소버(resolver) 캐시를 지웁니다. + #### `ses.webRequest` `webRequest` API는 생명주기의 다양한 단계에 맞춰 요청 컨텐츠를 가로채거나 변경할 수 diff --git a/docs-translations/ko-KR/api/shell.md b/docs-translations/ko-KR/api/shell.md index 4183d3b2502..c4831092f3c 100644 --- a/docs-translations/ko-KR/api/shell.md +++ b/docs-translations/ko-KR/api/shell.md @@ -25,12 +25,16 @@ shell.openExternal('https://github.com'); 지정한 파일을 데스크톱 기본 프로그램으로 엽니다. -### `shell.openExternal(url)` +### `shell.openExternal(url[, options])` * `url` String +* `options` Object (optional) _OS X_ + * `activate` Boolean - `true`로 설정하면 어플리케이션을 바로 활성화 상태로 + 실행합니다. 기본값은 `true`입니다. 제공된 외부 프로토콜 URL을 기반으로 데스크톱의 기본 프로그램으로 엽니다. (예를 들어 -mailto: URL은 유저의 기본 이메일 에이전트로 URL을 엽니다.) +mailto: URL은 유저의 기본 이메일 에이전트로 URL을 엽니다.) 어플리케이션이 해당 URL을 +열 수 있을 때 `true`를 반환합니다. 아니라면 `false`를 반환합니다. 역주: 폴더는 'file:\\\\C:\\'와 같이 지정하여 열 수 있습니다. (Windows의 경우) diff --git a/docs-translations/ko-KR/api/tray.md b/docs-translations/ko-KR/api/tray.md index e182f6471e7..d82b0a9d7e4 100644 --- a/docs-translations/ko-KR/api/tray.md +++ b/docs-translations/ko-KR/api/tray.md @@ -32,6 +32,13 @@ __플랫폼별 한계:__ 트레이 아이콘이 작동하도록 만들 수 있습니다. * 앱 알림 표시기는 컨텍스트 메뉴를 가지고 있을 때만 보입니다. * Linux에서 앱 표시기가 사용될 경우, `click` 이벤트는 무시됩니다. +* Linux에서 각각 개별 `MenuItem`의 변경을 적용하려면 `setContextMenu`를 다시 + 호출해야 합니다. 예를 들면: + +```javascript +contextMenu.items[2].checked = false; +appIcon.setContextMenu(contextMenu); +``` 이러한 이유로 Tray API가 모든 플랫폼에서 똑같이 작동하게 하고 싶다면 `click` 이벤트에 의존해선 안되며 언제나 컨텍스트 메뉴를 포함해야 합니다. From cc6ba0fd10e852d17fb46fbf37ad2f62c1238935 Mon Sep 17 00:00:00 2001 From: Lee Dohm Date: Thu, 18 Feb 2016 08:57:31 -0800 Subject: [PATCH 114/173] Remove all but prompts for version numbers --- ISSUE_TEMPLATE.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index d2d66066f40..a78e30d8620 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,11 +1,2 @@ -### Prerequisites - -* [ ] Did you [perform a cursory search](https://github.com/issues?q=is%3Aissue+repo%3Aatom%2Felectron) to see if it is already reported? - -### Description - -Electron version: - -Operating system: - -[Description of the bug or feature, for example, what you were doing when the issue arose and what you expected to happen] +* Electron version: +* Operating system: From c4859c3dc6a7167936db275a1e58398d46757807 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 17 Feb 2016 09:51:24 -0800 Subject: [PATCH 115/173] Use colors from Electron site --- atom/browser/default_app/index.html | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/atom/browser/default_app/index.html b/atom/browser/default_app/index.html index ec16a38bc42..95080867bcd 100644 --- a/atom/browser/default_app/index.html +++ b/atom/browser/default_app/index.html @@ -3,23 +3,23 @@ Electron From 9b373f2e152d3642af0fe613185edde9735237fa Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 17 Feb 2016 10:10:36 -0800 Subject: [PATCH 122/173] on -> to learn --- atom/browser/default_app/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/default_app/index.html b/atom/browser/default_app/index.html index 915a38fe792..3abcefd914b 100644 --- a/atom/browser/default_app/index.html +++ b/atom/browser/default_app/index.html @@ -121,7 +121,7 @@ `docs` ); - on how to write one. + to learn how to write one.

From 1c377310651144de398cb93c477b0d755bfdcc7a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 17 Feb 2016 10:11:35 -0800 Subject: [PATCH 123/173] under -> in --- atom/browser/default_app/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/default_app/index.html b/atom/browser/default_app/index.html index 3abcefd914b..c5672466bcc 100644 --- a/atom/browser/default_app/index.html +++ b/atom/browser/default_app/index.html @@ -98,7 +98,7 @@

- To run your app with Electron, execute the following command under your + To run your app with Electron, execute the following command in your Console (or Terminal):

From d3c6075841ec280cd14e9c4fa73a8ad1cff4e1f3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 17 Feb 2016 10:21:05 -0800 Subject: [PATCH 124/173] Use background color as border color --- atom/browser/default_app/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/default_app/index.html b/atom/browser/default_app/index.html index c5672466bcc..80c347eff6d 100644 --- a/atom/browser/default_app/index.html +++ b/atom/browser/default_app/index.html @@ -33,7 +33,7 @@ pre, code { font-family: "Menlo","Lucida Console",monospace; - border: 1px solid #ddd; + border: 1px solid #076274; background-color: #076274; color: #C5F3FC; border-radius: 3px; From 2a6fcf48e51b1d9125a8cf42c3a348028d73237f Mon Sep 17 00:00:00 2001 From: Brad Metcalf Date: Thu, 18 Feb 2016 13:41:22 -0600 Subject: [PATCH 125/173] Changed session to app to reflect rest of document --- docs/api/app.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/app.md b/docs/api/app.md index b5f8e919b82..bdf0a8a5587 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -156,7 +156,7 @@ certificate you should prevent the default behavior with `event.preventDefault()` and call `callback(true)`. ```javascript -session.on('certificate-error', function(event, webContents, url, error, certificate, callback) { +app.on('certificate-error', function(event, webContents, url, error, certificate, callback) { if (url == "https://github.com") { // Verification logic. event.preventDefault(); From 632c18ab370b7fab418a8cdfc301b8f1beb7f855 Mon Sep 17 00:00:00 2001 From: Rafael G Firmino Date: Thu, 18 Feb 2016 22:51:23 -0200 Subject: [PATCH 126/173] Translated --- docs-translations/pt-BR/api/window-open.md | 67 ++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 docs-translations/pt-BR/api/window-open.md diff --git a/docs-translations/pt-BR/api/window-open.md b/docs-translations/pt-BR/api/window-open.md new file mode 100644 index 00000000000..eb2b31cd0e4 --- /dev/null +++ b/docs-translations/pt-BR/api/window-open.md @@ -0,0 +1,67 @@ +# The `window.open` function + +Qunado `window.open` é chamado para criar uma nova janela de uma pagina web uma nova instância de `BrowserWindow` será criado para a `url` e um proxy será devolvido para o `windows.open`, para permitir que a página tenha limitado controle sobre ele. + +O proxy tem funcionalidade limitada padrão implementada para ser compatível com as páginas web tradicionais. +Para controle total da nova janela você deveria criar um `BrowserWindow` diretamente + + +The newly created `BrowserWindow` will inherit parent window's options by +default, to override inherited options you can set them in the `features` +string. + +O recém-criado `BrowserWindow` herdará as opções da janela pai por padrão, para substituir as opções herdadas você pode definilos no `features`(string). +### `window.open(url[, frameName][, features])` + +* `url` String +* `frameName` String (opcional) +* `features` String (opcional) + +Cria uma nova janela e retorna uma instância da classe `BrowserWindowProxy'. + +A string `features` segue o formato padrão do browser, mas cada recurso (feature) tem que ser um campo de opções do `BrowserWindow`. + +### `window.opener.postMessage(message, targetOrigin)` + +* `message` String +* `targetOrigin` String + +Envia uma mensagem para a janela pai com a origem especificada ou `*` preferência de origem não especificada. +Sends a message to the parent window with the specified origin or `*` +origin preference. + +## Class: BrowserWindowProxy + +O objeto `BrowserWindowProxy` é retornado de `window.open` e fornece uma funcionalidade limitada para a janela filha. + +### `BrowserWindowProxy.blur()` + +Remove o foco da janela filha. + +### `BrowserWindowProxy.close()` + +Forçadamente fecha a janela filha sem chamar o evento de descarregamento. + +### `BrowserWindowProxy.closed` + +Define como true após a janela filha ficar fechada. + +### `BrowserWindowProxy.eval(code)` + +* `code` String + +Avalia o código na jánela filha. + +### `BrowserWindowProxy.focus()` + +Concentra-se a janela filha (traz a janela para frente) +### `BrowserWindowProxy.postMessage(message, targetOrigin)` + +* `message` String +* `targetOrigin` String + +Sends a message to the child window with the specified origin or `*` for no +origin preference. + +In addition to these methods, the child window implements `window.opener` object +with no properties and a single method. From cd303087110f76d3232498456b02958ea03fea17 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 19 Feb 2016 10:01:39 +0800 Subject: [PATCH 127/173] Update libchromiumcontent with free version of ffmpeg --- script/lib/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/lib/config.py b/script/lib/config.py index 02e06948866..e3404918ce4 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = 'fc5174471ccccce7030d0960f5228e73ca7c2ac6' +LIBCHROMIUMCONTENT_COMMIT = '599c8941e1884e155218ec1013cba9fc5c7c7072' PLATFORM = { 'cygwin': 'win32', From daffb4881ee72c2299a407d78a6d9296e5050bec Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 19 Feb 2016 10:26:18 +0800 Subject: [PATCH 128/173] Create and upload free version of ffmpeg --- script/create-dist.py | 19 +++++++++++++++++++ script/upload.py | 12 ++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/script/create-dist.py b/script/create-dist.py index 2ec67d4f6c5..32d8f52aff3 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -99,6 +99,7 @@ def main(): create_dist_zip() create_chrome_binary_zip('chromedriver', get_chromedriver_version()) create_chrome_binary_zip('mksnapshot', ATOM_SHELL_VERSION) + create_ffmpeg_zip() create_symbols_zip() @@ -205,6 +206,24 @@ def create_chrome_binary_zip(binary, version): make_zip(zip_file, files, []) +def create_ffmpeg_zip(): + dist_name = 'ffmpeg-{0}-{1}-{2}.zip'.format( + ATOM_SHELL_VERSION, get_platform_key(), get_target_arch()) + zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name) + + if PLATFORM == 'darwin': + ffmpeg_name = 'libffmpeg.dylib' + elif PLATFORM == 'linux': + ffmpeg_name = 'libffmpeg.so' + elif PLATFORM == 'win32': + ffmpeg_name = 'ffmpeg.dll' + + shutil.copy2(os.path.join(CHROMIUM_DIR, '..', 'ffmpeg', ffmpeg_name), + DIST_DIR) + with scoped_cwd(DIST_DIR): + make_zip(zip_file, [ffmpeg_name, 'LICENSE', 'LICENSES.chromium.html'], []) + + def create_symbols_zip(): dist_name = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION, diff --git a/script/upload.py b/script/upload.py index 3245d9caaa7..d23bc554c3c 100755 --- a/script/upload.py +++ b/script/upload.py @@ -35,9 +35,6 @@ DSYM_NAME = '{0}-{1}-{2}-{3}-dsym.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION, get_platform_key(), get_target_arch()) -MKSNAPSHOT_NAME = 'mksnapshot-{0}-{1}-{2}.zip'.format(ATOM_SHELL_VERSION, - get_platform_key(), - get_target_arch()) def main(): @@ -89,12 +86,19 @@ def main(): if PLATFORM == 'darwin': upload_atom_shell(github, release, os.path.join(DIST_DIR, DSYM_NAME)) + # Upload free version of ffmpeg. + ffmpeg = 'ffmpeg-{0}-{1}-{2}.zip'.format( + ATOM_SHELL_VERSION, get_platform_key(), get_target_arch()) + upload_atom_shell(github, release, os.path.join(DIST_DIR, ffmpeg)) + # Upload chromedriver and mksnapshot for minor version update. if parse_version(args.version)[2] == '0': chromedriver = 'chromedriver-{0}-{1}-{2}.zip'.format( get_chromedriver_version(), get_platform_key(), get_target_arch()) upload_atom_shell(github, release, os.path.join(DIST_DIR, chromedriver)) - upload_atom_shell(github, release, os.path.join(DIST_DIR, MKSNAPSHOT_NAME)) + mksnapshot = 'mksnapshot-{0}-{1}-{2}.zip'.format( + ATOM_SHELL_VERSION, get_platform_key(), get_target_arch()) + upload_atom_shell(github, release, os.path.join(DIST_DIR, mksnapshot)) if PLATFORM == 'win32' and not tag_exists: # Upload node headers. From 4b18317e7c2a05e440e8a04c3ab4a12f4b573dcd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 19 Feb 2016 10:27:04 +0800 Subject: [PATCH 129/173] Bump v0.36.8 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/atom.gyp b/atom.gyp index c8c714858b4..68a30cc637f 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.36.7', + 'version%': '0.36.8', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 74725c94dc5..e1a5694d27a 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.36.7 + 0.36.8 CFBundleShortVersionString - 0.36.7 + 0.36.8 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 298d0bce73c..ff125b3edf7 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 0,36,7,0 - PRODUCTVERSION 0,36,7,0 + FILEVERSION 0,36,8,0 + PRODUCTVERSION 0,36,8,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.36.7" + VALUE "FileVersion", "0.36.8" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.36.7" + VALUE "ProductVersion", "0.36.8" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index a4f886c7e7d..b464ebdae4f 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 0 #define ATOM_MINOR_VERSION 36 -#define ATOM_PATCH_VERSION 7 +#define ATOM_PATCH_VERSION 8 #define ATOM_VERSION_IS_RELEASE 1 diff --git a/package.json b/package.json index f684386269e..a7eaa1a9420 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "0.36.7", + "version": "0.36.8", "devDependencies": { "asar": "^0.9.0", "eslint": "^2.1.0", From 85800256deb7c2eb543bba8d28eb369e3521eb54 Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 19 Feb 2016 19:39:01 +0530 Subject: [PATCH 130/173] protocol: respect requests from partition --- atom/browser/api/atom_api_protocol.cc | 70 +++++++++++---------------- atom/browser/api/atom_api_protocol.h | 11 +++-- atom/browser/api/atom_api_session.cc | 10 ++++ atom/browser/api/atom_api_session.h | 2 + atom/browser/api/lib/protocol.js | 9 +++- atom/common/node_bindings.cc | 1 - spec/api-protocol-spec.js | 51 +++++++++++++++++++ 7 files changed, 105 insertions(+), 49 deletions(-) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 09da9c71cad..335c20e11e3 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -28,33 +28,6 @@ Protocol::Protocol(AtomBrowserContext* browser_context) CHECK(job_factory_); } -mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return mate::ObjectTemplateBuilder(isolate) - .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes) - .SetMethod("registerServiceWorkerSchemes", - &Protocol::RegisterServiceWorkerSchemes) - .SetMethod("registerStringProtocol", - &Protocol::RegisterProtocol) - .SetMethod("registerBufferProtocol", - &Protocol::RegisterProtocol) - .SetMethod("registerFileProtocol", - &Protocol::RegisterProtocol) - .SetMethod("registerHttpProtocol", - &Protocol::RegisterProtocol) - .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol) - .SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled) - .SetMethod("interceptStringProtocol", - &Protocol::InterceptProtocol) - .SetMethod("interceptBufferProtocol", - &Protocol::InterceptProtocol) - .SetMethod("interceptFileProtocol", - &Protocol::InterceptProtocol) - .SetMethod("interceptHttpProtocol", - &Protocol::InterceptProtocol) - .SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol); -} - void Protocol::RegisterStandardSchemes( const std::vector& schemes) { atom::AtomBrowserClient::SetCustomSchemes(schemes); @@ -153,21 +126,34 @@ mate::Handle Protocol::Create( return mate::CreateHandle(isolate, new Protocol(browser_context)); } +// static +void Protocol::BuildPrototype(v8::Isolate* isolate, + v8::Local prototype) { + mate::ObjectTemplateBuilder(isolate, prototype) + .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes) + .SetMethod("registerServiceWorkerSchemes", + &Protocol::RegisterServiceWorkerSchemes) + .SetMethod("registerStringProtocol", + &Protocol::RegisterProtocol) + .SetMethod("registerBufferProtocol", + &Protocol::RegisterProtocol) + .SetMethod("registerFileProtocol", + &Protocol::RegisterProtocol) + .SetMethod("registerHttpProtocol", + &Protocol::RegisterProtocol) + .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol) + .SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled) + .SetMethod("interceptStringProtocol", + &Protocol::InterceptProtocol) + .SetMethod("interceptBufferProtocol", + &Protocol::InterceptProtocol) + .SetMethod("interceptFileProtocol", + &Protocol::InterceptProtocol) + .SetMethod("interceptHttpProtocol", + &Protocol::InterceptProtocol) + .SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol); +} + } // namespace api } // namespace atom - -namespace { - -void Initialize(v8::Local exports, v8::Local unused, - v8::Local context, void* priv) { - v8::Isolate* isolate = context->GetIsolate(); - mate::Dictionary dict(isolate, exports); - auto browser_context = static_cast( - atom::AtomBrowserMainParts::Get()->browser_context()); - dict.Set("protocol", atom::api::Protocol::Create(isolate, browser_context)); -} - -} // namespace - -NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_protocol, Initialize) diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index 8aef406fbc3..36ab46ba823 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -9,6 +9,7 @@ #include #include +#include "atom/browser/api/trackable_object.h" #include "atom/browser/net/atom_url_request_job_factory.h" #include "base/callback.h" #include "base/containers/scoped_ptr_hash_map.h" @@ -30,7 +31,7 @@ class AtomURLRequestJobFactory; namespace api { -class Protocol : public mate::Wrappable { +class Protocol : public mate::TrackableObject { public: using Handler = base::Callback)>; @@ -40,13 +41,13 @@ class Protocol : public mate::Wrappable { static mate::Handle Create( v8::Isolate* isolate, AtomBrowserContext* browser_context); + // mate::TrackableObject: + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); + protected: explicit Protocol(AtomBrowserContext* browser_context); - // mate::Wrappable implementations: - virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate); - private: // Possible errors. enum ProtocolError { diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index e5c5198f034..51f7c1bb811 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -9,6 +9,7 @@ #include "atom/browser/api/atom_api_cookies.h" #include "atom/browser/api/atom_api_download_item.h" +#include "atom/browser/api/atom_api_protocol.h" #include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/api/atom_api_web_request.h" #include "atom/browser/api/save_page_handler.h" @@ -443,6 +444,14 @@ v8::Local Session::Cookies(v8::Isolate* isolate) { return v8::Local::New(isolate, cookies_); } +v8::Local Session::Protocol(v8::Isolate* isolate) { + if (protocol_.IsEmpty()) { + auto handle = atom::api::Protocol::Create(isolate, browser_context()); + protocol_.Reset(isolate, handle.ToV8()); + } + return v8::Local::New(isolate, protocol_); +} + v8::Local Session::WebRequest(v8::Isolate* isolate) { if (web_request_.IsEmpty()) { auto handle = atom::api::WebRequest::Create(isolate, browser_context()); @@ -490,6 +499,7 @@ void Session::BuildPrototype(v8::Isolate* isolate, &Session::SetPermissionRequestHandler) .SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache) .SetProperty("cookies", &Session::Cookies) + .SetProperty("protocol", &Session::Protocol) .SetProperty("webRequest", &Session::WebRequest); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 02d8ba5cdec..63c4cfc612b 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -80,10 +80,12 @@ class Session: public mate::TrackableObject, mate::Arguments* args); void ClearHostResolverCache(mate::Arguments* args); v8::Local Cookies(v8::Isolate* isolate); + v8::Local Protocol(v8::Isolate* isolate); v8::Local WebRequest(v8::Isolate* isolate); // Cached object. v8::Global cookies_; + v8::Global protocol_; v8::Global web_request_; scoped_refptr browser_context_; diff --git a/atom/browser/api/lib/protocol.js b/atom/browser/api/lib/protocol.js index 41cb48db09b..caef0ad646b 100644 --- a/atom/browser/api/lib/protocol.js +++ b/atom/browser/api/lib/protocol.js @@ -4,7 +4,10 @@ if (!app.isReady()) { throw new Error('Can not initialize protocol module before app is ready'); } -const protocol = process.atomBinding('protocol').protocol; +const session = require('electron').session; + +// Returns the protocol property for default session. +const protocol = session.defaultSession.protocol; // Warn about removed APIs. var logAndThrow = function(callback, message) { @@ -16,6 +19,10 @@ var logAndThrow = function(callback, message) { } }; +protocol.fromPartition = function(partition) { + return session.fromPartition(partition).protocol; +}; + protocol.registerProtocol = function(scheme, handler, callback) { return logAndThrow(callback, 'registerProtocol API has been replaced by the register[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.'); }; diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index 69e7906ffbb..4af3ba5b64b 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -41,7 +41,6 @@ REFERENCE_MODULE(atom_browser_download_item); REFERENCE_MODULE(atom_browser_menu); REFERENCE_MODULE(atom_browser_power_monitor); REFERENCE_MODULE(atom_browser_power_save_blocker); -REFERENCE_MODULE(atom_browser_protocol); REFERENCE_MODULE(atom_browser_global_shortcut); REFERENCE_MODULE(atom_browser_session); REFERENCE_MODULE(atom_browser_tray); diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index 215868bfdc8..483155b7065 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -3,6 +3,7 @@ const http = require('http'); const path = require('path'); const qs = require('querystring'); const remote = require('electron').remote; +const BrowserWindow = remote.require('electron').BrowserWindow; const protocol = remote.require('electron').protocol; describe('protocol module', function() { @@ -814,4 +815,54 @@ describe('protocol module', function() { }); }); }); + + describe('protocol.fromPartition', function() { + var partitionName = 'temp'; + var tempProtocol = protocol.fromPartition(partitionName); + var w = null; + + beforeEach(function() { + if (w != null) { + w.destroy(); + } + w = new BrowserWindow({ + show: false, + width: 400, + height: 400, + webPreferences: { + partition: partitionName + } + }); + }); + + afterEach(function() { + if (w != null) { + w.destroy(); + } + w = null; + }); + + it('handles requests from a partition', function(done) { + var handler = function(error, callback) { + callback({ + data: text + }); + }; + tempProtocol.registerStringProtocol(protocolName, handler, function(error) { + if (error) { + return done(error); + } + protocol.isProtocolHandled(protocolName, function(result) { + assert.equal(result, false); + }); + tempProtocol.isProtocolHandled(protocolName, function(result) { + assert.equal(result, true); + }); + }); + w.webContents.on('did-finish-load', function() { + done(); + }); + w.loadURL(protocolName + "://fake-host"); + }); + }); }); From e45e2460275fafd965aab20354d17c86d01f5b35 Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 19 Feb 2016 23:24:56 -0500 Subject: [PATCH 131/173] a new version of asar is out 0.10.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f684386269e..78618c06bd9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "electron", "version": "0.36.7", "devDependencies": { - "asar": "^0.9.0", + "asar": "^0.10.0", "eslint": "^2.1.0", "request": "*" }, From a737e15ddba97227a83a6cd3bf3cacafb0935ee2 Mon Sep 17 00:00:00 2001 From: Magica Date: Sat, 20 Feb 2016 16:09:56 +0800 Subject: [PATCH 132/173] Update README.md to 45739ce434ec3c3eb190d35d3948b702b54706cd --- docs-translations/zh-CN/README.md | 76 +++++++++++++++++-------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/docs-translations/zh-CN/README.md b/docs-translations/zh-CN/README.md index 5c4303a0a6f..d7a8442ad4a 100644 --- a/docs-translations/zh-CN/README.md +++ b/docs-translations/zh-CN/README.md @@ -1,13 +1,19 @@ +## 常见问题 + ++ [Electron 常见问题](faq/electron-faq.md) + ## 向导 * [支持平台](tutorial/supported-platforms.md) -* [应用部署](tutorial/application-distribution.md) -* [应用打包](tutorial/application-packaging.md) -* [使用原生模块](tutorial/using-native-node-modules.md) +* [分发应用](tutorial/application-distribution.md) +* [提交应用到 Mac App Store](tutorial/mac-app-store-submission-guide.md) +* [打包应用](tutorial/application-packaging.md) +* [使用 Node 原生模块](tutorial/using-native-node-modules.md) * [主进程调试](tutorial/debugging-main-process.md) * [使用 Selenium 和 WebDriver](tutorial/using-selenium-and-webdriver.md) -* [调试工具扩展](tutorial/devtools-extension.md) -* [使用 PepperFlash 插件](tutorial/using-pepper-flash-plugin.md) +* [使用开发人员工具扩展](tutorial/devtools-extension.md) +* [使用 Pepper Flash 插件](tutorial/using-pepper-flash-plugin.md) +* [使用 Widevine CDM 插件](tutorial/using-widevine-cdm-plugin.md) ## 教程 @@ -19,53 +25,55 @@ * [简介](api/synopsis.md) * [进程对象](api/process.md) -* [支持的Chrome命令行开关](api/chrome-command-line-switches.md) +* [支持的 Chrome 命令行开关](api/chrome-command-line-switches.md) +* [环境变量](api/environment-variables.md) -定制的DOM元素: +自定义的 DOM 元素: -* [`File`对象](api/file-object.md) -* [``标签](api/web-view-tag.md) -* [`window.open`函数](api/window-open.md) +* [`File` 对象](api/file-object.md) +* [`` 标签](api/web-view-tag.md) +* [`window.open` 函数](api/window-open.md) -主进程可用的模块: +在主进程内可用的模块: * [app](api/app.md) -* [auto-updater](api/auto-updater.md) -* [browser-window](api/browser-window.md) -* [content-tracing](api/content-tracing.md) +* [autoUpdater](api/auto-updater.md) +* [BrowserWindow](api/browser-window.md) +* [contentTracing](api/content-tracing.md) * [dialog](api/dialog.md) -* [global-shortcut](api/global-shortcut.md) -* [ipc (main process)](api/ipc-main-process.md) -* [menu](api/menu.md) -* [menu-item](api/menu-item.md) -* [power-monitor](api/power-monitor.md) -* [power-save-blocker](api/power-save-blocker.md) +* [globalShortcut](api/global-shortcut.md) +* [ipcMain](api/ipc-main.md) +* [Menu](api/menu.md) +* [MenuItem](api/menu-item.md) +* [powerMonitor](api/power-monitor.md) +* [powerSaveBlocker](api/power-save-blocker.md) * [protocol](api/protocol.md) * [session](api/session.md) * [webContents](api/web-contents.md) -* [tray](api/tray.md) +* [Tray](api/tray.md) -渲染进程(网页)可用的模块: +在渲染进程(网页)内可用的模块: -* [ipc (renderer)](api/ipc-renderer.md) +* [desktopCapturer](api/desktop-capturer.md) +* [ipcRenderer](api/ipc-renderer.md) * [remote](api/remote.md) -* [web-frame](api/web-frame.md) +* [webFrame](api/web-frame.md) -两种进程都可用的模块: +在两种进程中都可用的模块: * [clipboard](api/clipboard.md) -* [crash-reporter](api/crash-reporter.md) -* [native-image](api/native-image.md) +* [crashReporter](api/crash-reporter.md) +* [nativeImage](api/native-image.md) * [screen](api/screen.md) * [shell](api/shell.md) ## 开发 -* [编码规范](development/coding-style.md) +* [代码规范](development/coding-style.md) * [源码目录结构](development/source-code-directory-structure.md) -* [与 NW.js (原名 node-webkit) 在技术上的差异](development/atom-shell-vs-node-webkit.md) -* [构建系统概况](development/build-system-overview.md) -* [构建步骤 (Mac)](development/build-instructions-mac.md) -* [构建步骤 (Windows)](development/build-instructions-windows.md) -* [构建步骤 (Linux)](development/build-instructions-linux.md) -* [在调试中使用 SymbolServer](development/setting-up-symbol-server.md) +* [与 NW.js(原 node-webkit)在技术上的差异](development/atom-shell-vs-node-webkit.md) +* [构建系统概览](development/build-system-overview.md) +* [构建步骤(Mac)](development/build-instructions-mac.md) +* [构建步骤(Windows)](development/build-instructions-windows.md) +* [构建步骤(Linux)](development/build-instructions-linux.md) +* [在调试中使用 Symbol Server](development/setting-up-symbol-server.md) From 060d06d39676049d66b6598b8773604864a87dca Mon Sep 17 00:00:00 2001 From: Magica Date: Sat, 20 Feb 2016 17:00:58 +0800 Subject: [PATCH 133/173] Translate electron-faq.md#45739ce434ec3c3eb190d35d3948b702b54706cd --- docs-translations/zh-CN/faq/electron-faq.md | 139 ++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 docs-translations/zh-CN/faq/electron-faq.md diff --git a/docs-translations/zh-CN/faq/electron-faq.md b/docs-translations/zh-CN/faq/electron-faq.md new file mode 100644 index 00000000000..3431c6018ab --- /dev/null +++ b/docs-translations/zh-CN/faq/electron-faq.md @@ -0,0 +1,139 @@ +# Electron 常见问题 + +## Electron 会在什么时候升级到最新版本的 Chrome? + +通常来说,在稳定版的 Chrome 发布后两周内,我们会更新 Electron 内的 Chrome 版本。 + +我们只会使用 stable 版本的 Chrome。但如果在 beta 或 dev 版本中有一个重要的更新,我们会把补丁应用到现版本的 Chrome 上。 + +## Electron 会在什么时候升级到最新版本的 Node.js? + +我们通常会在最新版的 Node.js 发布后一个月左右将 Electron 更新到这个版本的 Node.js。我们通过这种方式来避免新版本的 Node.js +带来的 bug(这种 bug 太常见了)。 + +Node.js 的新特性通常是由新版本的 V8 带来的。由于 Electron 使用的是 Chrome 浏览器中附带的 V8 引擎,所以 Electron 内往往已经 +有了部分新版本 Node.js 才有的崭新特性。 + +## 如何在两个网页间共享数据? + +在两个网页(渲染进程)间共享数据最简单的方法是使用浏览器中已经实现的 HTML5 API,比较好的方案是用 [Storage API][storage], +[`localStorage`][local-storage],[`sessionStorage`][session-storage] 或者 [IndexedDB][indexed-db]。 + +你还可以用 Electron 内的 IPC 机制实现。将数据存在主进程的某个全局变量中,然后在多个渲染进程中使用 `remote` 模块来访问它。 + +```javascript +// 在主进程中 +global.sharedObject = { + someProperty: 'default value' +}; +``` + +```javascript +// 在第一个页面中 +require('remote').getGlobal('sharedObject').someProperty = 'new value'; +``` + +```javascript +// 在第二个页面中 +console.log(require('remote').getGlobal('sharedObject').someProperty); +``` + +## 为什么应用的窗口、托盘在一段时间后不见了? + +这通常是因为用来存放窗口、托盘的变量被垃圾收集了。 + +你可以参考以下两篇文章来了解为什么会遇到这个问题。 + +* [内存管理][memory-management] +* [变量作用域][variable-scope] + +如果你只是要一个快速的修复方案,你可以用下面的方式改变变量的作用域,防止这个变量被垃圾收集。 + +从 + +```javascript +app.on('ready', function() { + var tray = new Tray('/path/to/icon.png'); +}) +``` + +改为 + +```javascript +var tray = null; +app.on('ready', function() { + tray = new Tray('/path/to/icon.png'); +}) +``` + +## 在 Electron 中,我为什么不能用 jQuery、RequireJS、Meteor、AngularJS? + +因为 Electron 在运行环境中引入了 Node.js,所以在 DOM 中有一些额外的变量,比如 `module`、`exports` 和 `require`。这导致 +了许多库不能正常运行,因为它们也需要将同名的变量加入运行环境中。 + +我们可以通过禁用 Node.js 来解决这个问题,用如下的方式: + +```javascript +// 在主进程中 +var mainWindow = new BrowserWindow({ + webPreferences: { + nodeIntegration: false + } +}); +``` + +假如你依然需要使用 Node.js 和 Electron 提供的 API,你需要在引入那些库之前将这些变量重命名,比如: + +```html + + + + +``` + +## 为什么 `require('electron').xxx` 的结果是 undefined? + +在使用 Electron 的提供的模块时,你可能会遇到和以下类似的错误: + +``` +> require('electron').webFrame.setZoomFactor(1.0); +Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined +``` + +这是因为你在项目中或者在全局中安装了[npm 上获取的 `electron` 模块][electron-module],它把 Electron 的内置模块覆写了。 + +你可以通过以下方式输出 `electron` 模块的路径来确认你是否使用了正确的模块。 + +```javascript +console.log(require.resolve('electron')); +``` + +确认以下它是不是像下面这样的: + +``` +"/path/to/Electron.app/Contents/Resources/atom.asar/renderer/api/lib/exports/electron.js" +``` + +假如输出的路径类似于 `node_modules/electron/index.js`,那么你需要移除或者重命名 npm 上的 `electron` 模块。 + +```bash +npm uninstall electron +npm uninstall -g electron +``` + +如果你依然遇到了这个问题,你可能需要检查一下拼写或者是否在错误的进程中调用了这个模块。比如, +`require('electron').app` 只能在主进程中使用, 然而 `require('electron').webFrame` 只能在渲染进程中使用。 + +[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management +[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx +[electron-module]: https://www.npmjs.com/package/electron +[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage +[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage +[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage +[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API From 1db72f8010e46567e16182e3f6cddf0155239c6c Mon Sep 17 00:00:00 2001 From: Magica Date: Sat, 20 Feb 2016 18:51:04 +0800 Subject: [PATCH 134/173] Translate accelerator.md of 45739ce434ec3c3eb190d35d3948b702b54706cd --- docs-translations/zh-CN/api/accelerator.md | 47 ++++++++++------------ 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/docs-translations/zh-CN/api/accelerator.md b/docs-translations/zh-CN/api/accelerator.md index 8858d18e856..06e7397c849 100644 --- a/docs-translations/zh-CN/api/accelerator.md +++ b/docs-translations/zh-CN/api/accelerator.md @@ -1,46 +1,43 @@ # Accelerator -An accelerator is a string that represents a keyboard shortcut. It can contain -multiple modifiers and key codes, combined by the `+` character. +一个 `Accelerator` 是一个表示某个快捷键组合的字符串。它包含了用 `+` 连接的若干个按键。 -Examples: +例如: * `Command+A` * `Ctrl+Shift+Z` -## Platform notice +## 运行平台相关的提示 -On Linux and Windows, the `Command` key does not have any effect so -use `CommandOrControl` which represents `Command` on OS X and `Control` on -Linux and Windows to define some accelerators. +在 Linux 和 Windows 上,`Command` 键并不存在,因此我们通常用 `CommandOrControl` 来表示“在 OS X 下为 `Command` 键,但在 +Linux 和 Windows 下为 `Control` 键。 -The `Super` key is mapped to the `Windows` key on Windows and Linux and -`Cmd` on OS X. +`Super` 键是指 Linux 和 Windows 上的 `Windows` 键,但是在 OS X 下为 `Command` 键。 -## Available modifiers +## 可用的功能按键 -* `Command` (or `Cmd` for short) -* `Control` (or `Ctrl` for short) -* `CommandOrControl` (or `CmdOrCtrl` for short) +* `Command`(缩写为 `Cmd`) +* `Control`(缩写为 `Ctrl`) +* `CommandOrControl`(缩写为 `CmdOrCtrl`) * `Alt` * `Shift` * `Super` -## Available key codes +## 可用的普通按键 -* `0` to `9` -* `A` to `Z` -* `F1` to `F24` -* Punctuations like `~`, `!`, `@`, `#`, `$`, etc. +* `0` 到 `9` +* `A` 到 `Z` +* `F1` 到 `F24` +* 类似与 `~`、`!`、`@`、`#`、`$` 的标点符号。 * `Plus` * `Space` * `Backspace` * `Delete` * `Insert` -* `Return` (or `Enter` as alias) -* `Up`, `Down`, `Left` and `Right` -* `Home` and `End` -* `PageUp` and `PageDown` -* `Escape` (or `Esc` for short) -* `VolumeUp`, `VolumeDown` and `VolumeMute` -* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` and `MediaPlayPause` +* `Return`(和 `Enter` 等同) +* `Up`、`Down`、`Left` 和 `Right` +* `Home` 和 `End` +* `PageUp` 和 `PageDown` +* `Escape`(缩写为 `Esc`) +* `VolumeUp`、`VolumeDown` 和 `VolumeMute` +* `MediaNextTrack`、`MediaPreviousTrack`、`MediaStop` 和 `MediaPlayPause` From f64dc5f57d1d11a5701b4391a9fbb5f679d28358 Mon Sep 17 00:00:00 2001 From: Magica Date: Sun, 21 Feb 2016 13:49:51 +0800 Subject: [PATCH 135/173] Translate app.md in commit 45739ce434ec3c3eb190d35d3948b702b54706cd --- docs-translations/zh-CN/api/app.md | 301 ++++++++++++++--------------- 1 file changed, 146 insertions(+), 155 deletions(-) diff --git a/docs-translations/zh-CN/api/app.md b/docs-translations/zh-CN/api/app.md index 448a5a373e9..dd8d6bcfdf6 100644 --- a/docs-translations/zh-CN/api/app.md +++ b/docs-translations/zh-CN/api/app.md @@ -11,11 +11,11 @@ app.on('window-all-closed', function() { }); ``` -## 事件 +## 事件列表 `app` 对象会触发以下的事件: -### 事件: 'will-finish-launching' +### 事件:'will-finish-launching' 当应用程序完成基础的启动的时候被触发。在 Windows 和 Linux 中, `will-finish-launching` 事件与 `ready` 事件是相同的; 在 OS X 中, @@ -24,11 +24,11 @@ app.on('window-all-closed', function() { 在大多数的情况下,你应该只在 `ready` 事件处理器中完成所有的业务。 -### 事件: 'ready' +### 事件:'ready' 当 Electron 完成初始化时被触发。 -### 事件: 'window-all-closed' +### 事件:'window-all-closed' 当所有的窗口都被关闭时触发。 @@ -36,20 +36,20 @@ app.on('window-all-closed', function() { 或者开发者调用了 `app.quit()` ,Electron 将会先尝试关闭所有的窗口再触发 `will-quit` 事件, 在这种情况下 `window-all-closed` 不会被触发。 -### 事件: 'before-quit' +### 事件:'before-quit' 返回: -* `event` 事件 +* `event` Event 在应用程序开始关闭它的窗口的时候被触发。 调用 `event.preventDefault()` 将会阻止终止应用程序的默认行为。 -### 事件: 'will-quit' +### 事件:'will-quit' 返回: -* `event` 事件 +* `event` Event 当所有的窗口已经被关闭,应用即将退出时被触发。 调用 `event.preventDefault()` 将会阻止终止应用程序的默认行为。 @@ -57,20 +57,20 @@ app.on('window-all-closed', function() { 你可以在 `window-all-closed` 事件的描述中看到 `will-quit` 事件 和 `window-all-closed` 事件的区别。 -### 事件: 'quit' +### 事件:'quit' 返回: -* `event` 事件 -* `exitCode` 整数 +* `event` Event +* `exitCode` Integer 当应用程序正在退出时触发。 -### 事件: 'open-file' _OS X_ +### 事件:'open-file' _OS X_ 返回: -* `event` 事件 -* `path` 字符串 +* `event` Event +* `path` String 当用户想要在应用中打开一个文件时触发。`open-file` 事件常常在应用已经打开并且系统想要再次使用应用打开文件时被触发。 `open-file` 也会在一个文件被拖入 dock 且应用还没有运行的时候被触发。 @@ -78,73 +78,74 @@ app.on('window-all-closed', function() { 如果你想处理这个事件,你应该调用 `event.preventDefault()` 。 在 Windows系统中, 你需要通过解析 process.argv 来获取文件路径。 -### 事件: 'open-url' _OS X_ + +### 事件:'open-url' _OS X_ 返回: -* `event` 事件 -* `url` 字符串 +* `event` Event +* `url` String 当用户想要在应用中打开一个url的时候被触发。URL格式必须要提前标识才能被你的应用打开。 如果你想处理这个事件,你应该调用 `event.preventDefault()` 。 -### 事件: 'activate' _OS X_ +### 事件:'activate' _OS X_ 返回: -* `event` 事件 -* `hasVisibleWindows` 布尔值 +* `event` Event +* `hasVisibleWindows` Boolean 当应用被激活时触发,常用于点击应用的 dock 图标的时候。 -### 事件: 'browser-window-blur' +### 事件:'browser-window-blur' 返回: -* `event` 事件 -* `window` 浏览器窗口 +* `event` Event +* `window` BrowserWindow -当一个 [浏览器窗口](browser-window.md) 失去焦点的时候触发。 +当一个 [BrowserWindow](browser-window.md) 失去焦点的时候触发。 -### 事件: 'browser-window-focus' +### 事件:'browser-window-focus' 返回: -* `event` 事件 -* `window` 浏览器窗口 +* `event` Event +* `window` BrowserWindow -当一个 [浏览器窗口](browser-window.md) 获得焦点的时候触发。 +当一个 [BrowserWindow](browser-window.md) 获得焦点的时候触发。 -### 事件: 'browser-window-created' +### 事件:'browser-window-created' 返回: -* `event` 事件 -* `window` 浏览器窗口 +* `event` Event +* `window` BrowserWindow -当一个 [浏览器窗口](browser-window.md) 被创建的时候触发。 +当一个 [BrowserWindow](browser-window.md) 被创建的时候触发。 -### 事件: 'certificate-error' +### 事件:'certificate-error' 返回: -* `event` 事件 -* `webContents` [web组件](web-contents.md) -* `url` 字符串 -* `certificateList` 对象 - * `data` PEM 编码数据 - * `issuerName` 发行者的公有名称 -* `callback` 函数 +* `event` Event +* `webContents` [WebContents](web-contents.md) +* `url` String - URL 地址 +* `error` String - 错误码 +* `certificate` Object + * `data` Buffer - PEM 编码数据 + * `issuerName` String - 发行者的公有名称 +* `callback` Function -Emitted when failed to verify the `certificate` for `url`, to trust the -certificate you should prevent the default behavior with -`event.preventDefault()` and call `callback(true)`. +当对 `url` 验证 `certificate` 证书失败的时候触发,如果需要信任这个证书,你需要阻止默认行为 `event.preventDefault()` 并且 +调用 `callback(true)`。 ```javascript session.on('certificate-error', function(event, webContents, url, error, certificate, callback) { if (url == "https://github.com") { - // Verification logic. + // 验证逻辑。 event.preventDefault(); callback(true); } else { @@ -153,37 +154,37 @@ session.on('certificate-error', function(event, webContents, url, error, certifi }); ``` -### 事件: 'select-client-certificate' +### 事件:'select-client-certificate' 返回: -* `event` 事件 -* `webContents` [web组件](web-contents.md) -* `url` 字符串 -* `certificateList` 对象 - * `data` PEM 编码数据 - * `issuerName` 发行者的公有名称 -* `callback` 函数 +* `event` Event +* `webContents` [WebContents](web-contents.md) +* `url` String - URL 地址 +* `certificateList` [Object] + * `data` Buffer - PEM 编码数据 + * `issuerName` String - 发行者的公有名称 +* `callback` Function 当一个客户端认证被请求的时候被触发。 -The `url` corresponds to the navigation entry requesting the client certificate -and `callback` needs to be called with an entry filtered from the list. -Using `event.preventDefault()` prevents the application from using the first -certificate from the store. +`url` 指的是请求客户端认证的网页地址,调用 `callback` 时需要传入一个证书列表中的证书。 + +需要通过调用 `event.preventDefault()` 来防止应用自动使用第一个证书进行验证。如下所示: + ```javascript app.on('select-certificate', function(event, host, url, list, callback) { event.preventDefault(); callback(list[0]); }) ``` -### Event: 'login' +### 事件: 'login' -Returns: +返回: * `event` Event -* `webContents` [Web组件](web-contents.md) +* `webContents` [WebContents](web-contents.md) * `request` Object * `method` String * `url` URL @@ -196,11 +197,10 @@ Returns: * `realm` String * `callback` Function -当 `webContents` 要做验证时被触发。 +当 `webContents` 要做进行一次 HTTP 登陆验证时被触发。 -The default behavior is to cancel all authentications, to override this you -should prevent the default behavior with `event.preventDefault()` and call -`callback(username, password)` with the credentials. +默认情况下,Electron 会取消所有的验证行为,如果需要重写这个行为,你需要用 `event.preventDefault()` 来阻止默认行为,并且 +用 `callback(username, password)` 来进行验证。 ```javascript app.on('login', function(event, webContents, request, authInfo, callback) { @@ -208,22 +208,22 @@ app.on('login', function(event, webContents, request, authInfo, callback) { callback('username', 'secret'); }) ``` -### 事件: 'gpu-process-crashed' +### 事件:'gpu-process-crashed' -当GPU进程崩溃时触发。 +当 GPU 进程崩溃时触发。 -## 方法 +## 方法列表 `app` 对象拥有以下的方法: -**提示:** 有的方法只能用于特定的操作系统。 +**请注意** 有的方法只能用于特定的操作系统。 ### `app.quit()` -试图关掉所有的窗口。`before-quit` 事件将会被最先触发。如果所有的窗口都被成功关闭了, +试图关掉所有的窗口。`before-quit` 事件将会最先被触发。如果所有的窗口都被成功关闭了, `will-quit` 事件将会被触发,默认下应用将会被关闭。 -这个方法保证了所有的 `beforeunload` 和 `unload` 事件处理器被正确执行。会存在一个窗口被 `beforeunload` 事件处理器返回 `false` 取消退出的可能性。 +这个方法保证了所有的 `beforeunload` 和 `unload` 事件处理器被正确执行。假如一个窗口的 `beforeunload` 事件处理器返回 `false`,那么整个应用可能会取消退出。 ### `app.hide()` _OS X_ @@ -241,30 +241,29 @@ app.on('login', function(event, webContents, request, authInfo, callback) { 所有的窗口会被立刻关闭,不会询问用户。`before-quit` 和 `will-quit` 这2个事件不会被触发 - ### `app.getAppPath()` 返回当前应用所在的文件路径。 ### `app.getPath(name)` -* `name` 字符串 +* `name` String 返回一个与 `name` 参数相关的特殊文件夹或文件路径。当失败时抛出一个 `Error` 。 你可以通过名称请求以下的路径: -* `home` 用户的 home 文件夹。 -* `appData` 所有用户的应用数据文件夹,默认对应: +* `home` 用户的 home 文件夹(主目录) +* `appData` 当前用户的应用数据文件夹,默认对应: * `%APPDATA%` Windows 中 * `$XDG_CONFIG_HOME` or `~/.config` Linux 中 * `~/Library/Application Support` OS X 中 -* `userData` 储存你应用程序设置文件的文件夹,默认是 `appData` 文件夹附加应用的名称。 -* `temp` 临时文件夹。 +* `userData` 储存你应用程序设置文件的文件夹,默认是 `appData` 文件夹附加应用的名称 +* `temp` 临时文件夹 * `exe` 当前的可执行文件 -* `module` `libchromiumcontent` 库. -* `desktop` 当前用户的桌面文件夹。 -* `documents` "我的文件夹"的路径. +* `module` `libchromiumcontent` 库 +* `desktop` 当前用户的桌面文件夹 +* `documents` 用户文档目录的路径 * `downloads` 用户下载目录的路径. * `music` 用户音乐目录的路径. * `pictures` 用户图片目录的路径. @@ -272,14 +271,14 @@ app.on('login', function(event, webContents, request, authInfo, callback) { ### `app.setPath(name, path)` -* `name` 字符串 -* `path` 字符串 +* `name` String +* `path` String -重写 `path` 参数到一个特别的文件夹或者是一个和 `name` 参数有关系的文件。 +重写某个 `name` 的路径为 `path`,`path` 可以是一个文件夹或者一个文件,这个和 `name` 的类型有关。 如果这个路径指向的文件夹不存在,这个文件夹将会被这个方法创建。 -如果错误则抛出 `Error` 。 +如果错误则会抛出 `Error`。 -你只可以指向 `app.getPath` 中定义过 `name` 的路径。 +`name` 参数只能使用 `app.getPath` 中定义过 `name`。 默认情况下,网页的 cookie 和缓存都会储存在 `userData` 文件夹。 如果你想要改变这个位置,你需要在 `app` 模块中的 `ready` 事件被触发之前重写 `userData` 的路径。 @@ -293,22 +292,20 @@ app.on('login', function(event, webContents, request, authInfo, callback) { 返回当前应用程序的 `package.json` 文件中的名称。 -通常 `name` 字段是一个短的小写字符串,其命名规则按照 npm 中的模块命名规则。你应该单独列举一个 -`productName` 字段,用于表示你的应用程序的完整名称,这个名称将会被 Electron 优先采用。 +由于 npm 的命名规则,通常 `name` 字段是一个短的小写字符串。但是应用名的完整名称通常是首字母大写的,你应该单独使用一个 +`productName` 字段,用于表示你的应用程序的完整名称。Electron 会优先使用这个字段作为应用名。 ### `app.getLocale()` -返回当前应用程序的语言种类。 - - +返回当前应用程序的语言。 ### `app.addRecentDocument(path)` _OS X_ _Windows_ -* `path` 字符串 +* `path` String -为最近访问的文档列表中添加 `path` 。 +在最近访问的文档列表中添加 `path`。 -这个列表由操作系统进行管理。在 Windows 中您可以通过任务条进行访问,在 OS X 中你可以通过dock 菜单进行访问。 +这个列表由操作系统进行管理。在 Windows 中您可以通过任务条进行访问,在 OS X 中你可以通过 dock 菜单进行访问。 ### `app.clearRecentDocuments()` _OS X_ _Windows_ @@ -316,66 +313,55 @@ app.on('login', function(event, webContents, request, authInfo, callback) { ### `app.setUserTasks(tasks)` _Windows_ -* `tasks` 由 `Task` 对象构成的数组 +* `tasks` [Task] - 一个由 Task 对象构成的数组 将 `tasks` 添加到 Windows 中 JumpList 功能的 [Tasks][tasks] 分类中。 `tasks` 中的 `Task` 对象格式如下: -`Task` 对象 -* `program` 字符串 - 执行程序的路径,通常你应该说明当前程序的路径为 `process.execPath` 字段。 -* `arguments` 字符串 - 当 `program` 执行时的命令行参数。 -* `title` 字符串 - JumpList 中显示的标题。 -* `description` 字符串 - 对这个任务的描述。 -* `iconPath` 字符串 - JumpList 中显示的 icon 的绝对路径,可以是一个任意包含一个icon的资源文件。你通常可以通过指明 `process.execPath` 来显示程序中的icon。 -* `iconIndex` 整数 - icon文件中的icon目录。如果一个icon文件包括了两个或多个icon,就需要设置这个值以确定icon。如果一个文件仅包含一个icon,那么这个值为0。 +`Task` Object +* `program` String - 执行程序的路径,通常你应该说明当前程序的路径为 `process.execPath` 字段。 +* `arguments` String - 当 `program` 执行时的命令行参数。 +* `title` String - JumpList 中显示的标题。 +* `description` String - 对这个任务的描述。 +* `iconPath` String - JumpList 中显示的图标的绝对路径,可以是一个任意包含一个图标的资源文件。通常来说,你可以通过指明 `process.execPath` 来显示程序中的图标。 +* `iconIndex` Integer - 图标文件中的采用的图标位置。如果一个图标文件包括了多个图标,就需要设置这个值以确定使用的是哪一个图标。 +如果这个图标文件中只包含一个图标,那么这个值为 0。 ### `app.allowNTLMCredentialsForAllDomains(allow)` * `allow` Boolean -Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate -authentication - normally, Electron will only send NTLM/Kerberos credentials for -URLs that fall under "Local Intranet" sites (i.e. are in the same domain as you). -However, this detection often fails when corporate networks are badly configured, -so this lets you co-opt this behavior and enable it for all URLs. +动态设置是否总是为 HTTP NTLM 或 Negotiate 认证发送证书。通常来说,Electron 只会对本地网络(比如和你处在一个域中的计算机)发 +送 NTLM / Kerberos 证书。但是假如网络设置得不太好,可能这个自动探测会失效,所以你可以通过这个接口自定义 Electron 对所有 URL +的行为。 + ### `app.makeSingleInstance(callback)` * `callback` Function -This method makes your application a Single Instance Application - instead of -allowing multiple instances of your app to run, this will ensure that only a -single instance of your app is running, and other instances signal this -instance and exit. +这个方法可以让你的应用在同一时刻最多只会有一个实例,否则你的应用可以被运行多次并产生多个实例。你可以利用这个接口保证只有一个实例正 +常运行,其余的实例全部会被终止并退出。 -`callback` will be called with `callback(argv, workingDirectory)` when a second -instance has been executed. `argv` is an Array of the second instance's command -line arguments, and `workingDirectory` is its current working directory. Usually -applications respond to this by making their primary window focused and -non-minimized. +如果多个实例同时运行,那么第一个被运行的实例中 `callback` 会以 `callback(argv, workingDirectory)` 的形式被调用。其余的实例 +会被终止。 +`argv` 是一个包含了这个实例的命令行参数列表的数组,`workingDirectory` 是这个实例目前的运行目录。通常来说,我们会用通过将应用在 +主屏幕上激活,并且取消最小化,来提醒用户这个应用已经被打开了。 -The `callback` is guaranteed to be executed after the `ready` event of `app` -gets emitted. +在 `app` 的 `ready` 事件后,`callback` 才有可能被调用。 -This method returns `false` if your process is the primary instance of the -application and your app should continue loading. And returns `true` if your -process has sent its parameters to another instance, and you should immediately -quit. +如果当前实例为第一个实例,那么在这个方法将会返回 `false` 来保证它继续运行。否则将会返回 `true` 来让它立刻退出。 -On OS X the system enforces single instance automatically when users try to open -a second instance of your app in Finder, and the `open-file` and `open-url` -events will be emitted for that. However when users start your app in command -line the system's single instance machanism will be bypassed and you have to -use this method to ensure single instance. +在 OS X 中,如果用户通过 Finder、`open-file` 或者 `open-url` 打开应用,系统会强制确保只有一个实例在运行。但是如果用户是通过 +命令行打开,这个系统机制会被忽略,所以你仍然需要靠这个方法来保证应用为单实例运行的。 -An example of activating the window of primary instance when a second instance -starts: +下面是一个简单的例子。我们可以通过这个例子了解如何确保应用为单实例运行状态。 ```js var myWindow = null; var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) { - // Someone tried to run a second instance, we should focus our window. + // 当另一个实例运行的时候,这里将会被调用,我们需要激活应用的窗口 if (myWindow) { if (myWindow.isMinimized()) myWindow.restore(); myWindow.focus(); @@ -383,104 +369,109 @@ var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) return true; }); +// 这个实例是多余的实例,需要退出 if (shouldQuit) { app.quit(); return; } -// Create myWindow, load the rest of the app, etc... +// 创建窗口、继续加载应用、应用逻辑等…… app.on('ready', function() { }); + ``` ### `app.setAppUserModelId(id)` _Windows_ * `id` String -改变 [Application User Model ID][app-user-model-id] 的 `id`. +改变当前应用的 [Application User Model ID][app-user-model-id] 为 `id`. ### `app.isAeroGlassEnabled()` _Windows_ -This method returns `true` if [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx) -(Aero Glass) is enabled, and `false` otherwise. You can use it to determine if -you should create a transparent window or not (transparent windows won't work -correctly when DWM composition is disabled). +如果 [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx)(Aero Glass) 启用 +了,那么这个方法会返回 `true`,否则是 `false`。你可以用这个方法来决定是否要开启透明窗口特效,因为如果用户没开启 DWM,那么透明窗 +口特效是无效的。 -Usage example: +举个例子: ```js let browserOptions = {width: 1000, height: 800}; -// Make the window transparent only if the platform supports it. +// 只有平台支持的时候才使用透明窗口 if (process.platform !== 'win32' || app.isAeroGlassEnabled()) { browserOptions.transparent = true; browserOptions.frame = false; } -// Create the window. +// 创建窗口 win = new BrowserWindow(browserOptions); -// Navigate. +// 转到某个网页 if (browserOptions.transparent) { win.loadURL('file://' + __dirname + '/index.html'); } else { - // No transparency, so we load a fallback that uses basic styles. + // 没有透明特效,我们应该用某个只包含基本样式的替代解决方案。 win.loadURL('file://' + __dirname + '/fallback.html'); } ``` ### `app.commandLine.appendSwitch(switch[, value])` -通过可选的参数 `value` 给 Chromium 命令行中添加一个开关。 -Append a switch (with optional `value`) to Chromium's command line. +通过可选的参数 `value` 给 Chromium 中添加一个命令行开关。 -**贴士:** 这不会影响 `process.argv` ,这个方法主要被开发者用于控制一些低层级的 Chromium 行为。 +**注意** 这个方法不会影响 `process.argv`,我们通常用这个方法控制一些底层 Chromium 行为。 ### `app.commandLine.appendArgument(value)` -给 Chromium 命令行中加入一个参数。这个参数是当前正在被引用的。 +给 Chromium 中直接添加一个命令行参数,这个参数 `value` 的引号和格式必须正确。 -**贴士:** 这不会影响 `process.argv`。 +**注意** 这个方法不会影响 `process.argv`。 ### `app.dock.bounce([type])` _OS X_ -* `type` 字符串 (可选的) - 可以是 `critical` 或 `informational`。默认下是 `informational` +* `type` String - 可选参数,可以是 `critical` 或 `informational`。默认为 `informational`。 -当输入 `critical` 时,dock 中的 icon 将会开始弹跳直到应用被激活或者这个请求被取消。 +当传入的是 `critical` 时,dock 中的应用将会开始弹跳,直到这个应用被激活或者这个请求被取消。 -当输入 `informational` 时,dock 中的 icon 只会弹跳一秒钟。 -然而,这个请求仍然会激活,直到应用被激活或者请求被取消。 +当传入的是 `informational` 时,dock 中的图标只会弹跳一秒钟。但是,这个请求仍然会激活,直到应用被激活或者请求被取消。 -返回一个表示这个请求的 ID。 +这个方法返回的返回值表示这个请求的 ID。 ### `app.dock.cancelBounce(id)` _OS X_ -* `id` 整数 +* `id` Integer 取消这个 `id` 对应的请求。 ### `app.dock.setBadge(text)` _OS X_ -* `text` 字符串 +* `text` String -设置 dock 中显示的字符。 +设置应用在 dock 中显示的字符串。 ### `app.dock.getBadge()` _OS X_ -返回 dock 中显示的字符。 +返回应用在 dock 中显示的字符串。 ### `app.dock.hide()` _OS X_ -隐藏 dock 中的 icon。 +隐藏应用在 dock 中的图标。 ### `app.dock.show()` _OS X_ -显示 dock 中的 icon。 +显示应用在 dock 中的图标。 ### `app.dock.setMenu(menu)` _OS X_ -* `menu` 菜单 +* `menu` [Menu](menu.md) 设置应用的 [dock 菜单][dock-menu]. +### `app.dock.setIcon(image)` _OS X_ + +* `image` [NativeImage](native-image.md) + +设置应用在 dock 中显示的图标。 + [dock-menu]:https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/concepts/dockconcepts.html#//apple_ref/doc/uid/TP30000986-CH2-TPXREF103 [tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx From a05e98f4638909bf1557755a0d9838d4988328b9 Mon Sep 17 00:00:00 2001 From: Magica Date: Sun, 21 Feb 2016 14:09:34 +0800 Subject: [PATCH 136/173] Translate auto-updater.md in commit 45739ce434ec3c3eb190d35d3948b702b54706cd --- docs-translations/zh-CN/api/auto-updater.md | 88 +++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 docs-translations/zh-CN/api/auto-updater.md diff --git a/docs-translations/zh-CN/api/auto-updater.md b/docs-translations/zh-CN/api/auto-updater.md new file mode 100644 index 00000000000..f027fbc6e50 --- /dev/null +++ b/docs-translations/zh-CN/api/auto-updater.md @@ -0,0 +1,88 @@ +# autoUpdater + +这个模块提供了一个到 `Squirrel` 自动更新框架的接口。 + +## 平台相关的提示 + +虽然 `autoUpdater` 模块提供了一套各平台通用的接口,但是在每个平台间依然会有一些微小的差异。 + +### OS X + +在 OS X 上,`autoUpdater` 模块依靠的是内置的 [Squirrel.Mac][squirrel-mac],这意味着你不需要依靠其他的设置就能使用。关于 +更新服务器的配置,你可以通过阅读 [Server Support][server-support] 这篇文章来了解。 + +### Windows + +在 Windows 上,你必须使用安装程序将你的应用装到用户的计算机上,所以比较推荐的方法是用 [grunt-electron-installer][installer] 这个模块来自动生成一个 Windows 安装向导。 + +Squirrel 自动生成的安装向导会生成一个带 [Application User Model ID][app-user-model-id] 的快捷方式。 +Application User Model ID 的格式是 `com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`, 比如 +像 `com.squirrel.slack.Slack` 和 `com.squirrel.code.Code` 这样的。你应该在自己的应用中使用 `app.setAppUserModelId` 方法设置相同的 API,不然 Windows 将不能正确地把你的应用固定在任务栏上。 + +服务器端的配置和 OS X 也是不一样的,你可以阅读 [Squirrel.Windows][squirrel-windows] 这个文档来获得详细信息。 + +### Linux + +Linux 下没有任何的自动更新支持,所以我们推荐用各个 Linux 发行版的包管理器来分发你的应用。 + +## 事件列表 + +`autoUpdater` 对象会触发以下的事件: + +### 事件:'error' + +返回: + +* `error` Error + +当更新发生错误的时候触发。 + +### 事件:'checking-for-update' + +当开始检查更新的时候触发。 + +### 事件:'update-available' + +当发现一个可用更新的时候触发,更新包下载会自动开始。 + +### 事件:'update-not-available' + +当没有可用更新的时候触发。 + +### 事件:'update-downloaded' + +返回: + +* `event` Event +* `releaseNotes` String - 新版本更新公告 +* `releaseName` String - 新的版本号 +* `releaseDate` Date - 新版本发布的日期 +* `updateURL` String - 更新地址 + +在更新下载完成的时候触发。 + +在 Windows 上只有 `releaseName` 是有效的。 + +## 方法列表 + +`autoUpdater` 对象有以下的方法: + +### `autoUpdater.setFeedURL(url)` + +* `url` String + +设置检查更新的 `url`,并且初始化自动更新。这个 `url` 一旦设置就无法更改。 + +### `autoUpdater.checkForUpdates()` + +向服务端查询现在是否有可用的更新。在调用这个方法之前,必须要先调用 `setFeedURL`。 + +### `autoUpdater.quitAndInstall()` + +在下载完成后,重启当前的应用并且安装更新。这个方法应该仅在 `update-downloaded` 事件触发后被调用。 + +[squirrel-mac]: https://github.com/Squirrel/Squirrel.Mac +[server-support]: https://github.com/Squirrel/Squirrel.Mac#server-support +[squirrel-windows]: https://github.com/Squirrel/Squirrel.Windows +[installer]: https://github.com/atom/grunt-electron-installer +[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx From 078c7bf8ab2293ebb1a5b0bde489a5f6da42c443 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Sun, 21 Feb 2016 00:14:34 -0800 Subject: [PATCH 137/173] Rename constant `PERSIST_PERFIX` to `PERSIST_PREFIX` in `session.js`. --- atom/browser/api/lib/session.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/lib/session.js b/atom/browser/api/lib/session.js index dc65264349f..8662759192d 100644 --- a/atom/browser/api/lib/session.js +++ b/atom/browser/api/lib/session.js @@ -1,6 +1,6 @@ const EventEmitter = require('events').EventEmitter; const bindings = process.atomBinding('session'); -const PERSIST_PERFIX = 'persist:'; +const PERSIST_PREFIX = 'persist:'; // Returns the Session from |partition| string. exports.fromPartition = function(partition) { @@ -10,8 +10,8 @@ exports.fromPartition = function(partition) { if (partition === '') { return exports.defaultSession; } - if (partition.startsWith(PERSIST_PERFIX)) { - return bindings.fromPartition(partition.substr(PERSIST_PERFIX.length), false); + if (partition.startsWith(PERSIST_PREFIX)) { + return bindings.fromPartition(partition.substr(PERSIST_PREFIX.length), false); } else { return bindings.fromPartition(partition, true); } From f63532fa9558dc435764ea8b94f4acdb38ae8469 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 19 Feb 2016 09:39:43 +0900 Subject: [PATCH 138/173] :memo: Update as upstream [ci skip] --- docs-translations/ko-KR/api/app.md | 2 +- docs-translations/ko-KR/tutorial/using-widevine-cdm-plugin.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index 89cc1732263..048026e0d59 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -164,7 +164,7 @@ Returns: 기본 동작을 방지하고 인증을 승인할 수 있습니다. ```javascript -session.on('certificate-error', function(event, webContents, url, error, certificate, callback) { +app.on('certificate-error', function(event, webContents, url, error, certificate, callback) { if (url == "https://github.com") { // Verification logic. event.preventDefault(); diff --git a/docs-translations/ko-KR/tutorial/using-widevine-cdm-plugin.md b/docs-translations/ko-KR/tutorial/using-widevine-cdm-plugin.md index d729c0efc08..b9fec886769 100644 --- a/docs-translations/ko-KR/tutorial/using-widevine-cdm-plugin.md +++ b/docs-translations/ko-KR/tutorial/using-widevine-cdm-plugin.md @@ -8,6 +8,10 @@ Electron은 라이센스상의 문제로 Widevine CDM 플러그인을 직접 제 따라서 플러그인을 얻으려면 먼저 사용할 Electron 빌드의 아키텍쳐와 버전에 맞춰 공식 Chrome 브라우저를 설치해야 합니다. +__참고:__ Chrome 브라우저의 메이저 버전은 Electron에서 사용하는 Chrome 버전과 +같습니다, 만약 그렇지 않다면 `navigator.plugins`가 로드됐더라도 정상적으로 작동하지 +않습니다. + ### Windows & OS X Chrome 브라우저에서 `chrome://components/`를 열고 `WidevineCdm`을 찾은 후 확실히 From 9e1da8f097bf22b3cef4d0a4d4b3dee1c179d428 Mon Sep 17 00:00:00 2001 From: Takahito Yamatoya Date: Mon, 22 Feb 2016 00:59:18 +0900 Subject: [PATCH 139/173] Update as upstream --- docs-translations/jp/faq/electron-faq.md | 25 +++++++++++++++ .../desktop-environment-integration.md | 32 +++++++++++++++---- docs-translations/jp/tutorial/quick-start.md | 4 +++ .../tutorial/using-selenium-and-webdriver.md | 2 +- .../jp/tutorial/using-widevine-cdm-plugin.md | 2 ++ 5 files changed, 57 insertions(+), 8 deletions(-) diff --git a/docs-translations/jp/faq/electron-faq.md b/docs-translations/jp/faq/electron-faq.md index c8a65227717..eef30c013a3 100644 --- a/docs-translations/jp/faq/electron-faq.md +++ b/docs-translations/jp/faq/electron-faq.md @@ -12,6 +12,27 @@ Node.js の新しいバージョンがリリースされたとき、私たちは 通常、Node.js の新しい機能は V8 のアップグレードによってもたらされますが、Electron は Chrome ブラウザーに搭載されている V8 を使用しているので、新しい Node.js に入ったばかりのピカピカに新しい JavaScript 機能は Electron ではたいてい既に導入されています。 +## ウェブページ間のデータを共有する方法は? + +ウェブページ(レンダラープロセス)間のデータを共有するために最も単純な方法は、ブラウザで、すでに提供されているHTML5 APIを使用することです。もっとも良い方法は、[Storage API][storage]、[`localStorage`][local-storage]、[`sessionStorage`][session-storage]、[IndexedDB][indexed-db]です。 + +```javascript +// In the main process. +global.sharedObject = { + someProperty: 'default value' +}; +``` + +```javascript +// In page 1. +require('remote').getGlobal('sharedObject').someProperty = 'new value'; +``` + +```javascript +// In page 2. +console.log(require('remote').getGlobal('sharedObject').someProperty); +``` + ## 何分か経つと、アプリの Window/tray が消えてしまいます これは、Window/trayを格納するのに使用している変数がガベージコレクトされたときに発生します。 @@ -104,3 +125,7 @@ npm uninstall -g electron [memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management [variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx [electron-module]: https://www.npmjs.com/package/electron +[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage +[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage +[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage +[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API diff --git a/docs-translations/jp/tutorial/desktop-environment-integration.md b/docs-translations/jp/tutorial/desktop-environment-integration.md index 0ef44b2f47c..96bf76d7370 100644 --- a/docs-translations/jp/tutorial/desktop-environment-integration.md +++ b/docs-translations/jp/tutorial/desktop-environment-integration.md @@ -210,6 +210,23 @@ var window = new BrowserWindow({...}); window.setProgressBar(0.5); ``` +## タスクバーでアイコンをオーバーレイする (Windows) + +Windowsで、タスクバーボタンはアプリケーションステータスを表示するために小さなオーバーレイを使うことができます。MSDNから引用します。 + +> アイコン オーバーレイは、状況に応じた状態通知として機能し、通知領域に状態アイコンを個別に表示する必要性をなくして、情報をユーザーに伝えることを目的としています。たとえば、現在、通知領域に表示される Microsoft Office Outlook の新着メールの通知は、タスク バー ボタンのオーバーレイとして表示できるようになります。ここでも、開発サイクルの間に、アプリケーションに最適な方法を決定する必要があります。アイコン オーバーレイは、重要で長期にわたる状態や通知 (ネットワークの状態、メッセンジャーの状態、新着メールなど) を提供することを目的としています。ユーザーに対して、絶えず変化するオーバーレイやアニメーションを表示しないようにしてください。 + +__タスクバーボタンでのオーバーレイ:__ + +![Overlay on taskbar button](https://i-msdn.sec.s-msft.com/dynimg/IC420441.png) + +ウィンドウでオーバーレイアイコンを設定するために、[BrowserWindow.setOverlayIcon][setoverlayicon] APIを使用できます。 + +```javascript +var window = new BrowserWindow({...}); +window.setOverlayIcon('path/to/overlay.png', 'Description for overlay'); +``` + ## Windowのファイル表示 (OS X) OS Xでは、ウィンドウがrepresented fileを設定でき、タイトルバー上にファイルのアイコンを表示でき、タイトル上でCommand-クリックまたはControl-クリックをすると、パスがポップアップ表示されます。 @@ -228,15 +245,16 @@ window.setRepresentedFilename('/etc/passwd'); window.setDocumentEdited(true); ``` -[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath -[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments -[setusertaskstasks]: ../api/app.md#appsetusertaskstasks -[setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress -[setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename -[setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited +[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-os-x-windows +[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows +[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows +[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress +[setoverlayicon]: ../api/browser-window.md#winsetoverlayiconoverlay-description-windows-7 +[setrepresentedfilename]: ../api/browser-window.md#winsetrepresentedfilenamefilename-os-x +[setdocumentedited]: ../api/browser-window.md#winsetdocumenteditededited-os-x [app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx [unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher -[setthumbarbuttons]: ../api/browser-window.md#browserwindowsetthumbarbuttonsbuttons +[setthumbarbuttons]: ../api/browser-window.md#winsetthumbarbuttonsbuttons-windows-7 [tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx [notification-spec]: https://developer.gnome.org/notification-spec/ diff --git a/docs-translations/jp/tutorial/quick-start.md b/docs-translations/jp/tutorial/quick-start.md index bfb6e2a51f7..4f2e5c9a52e 100644 --- a/docs-translations/jp/tutorial/quick-start.md +++ b/docs-translations/jp/tutorial/quick-start.md @@ -24,6 +24,8 @@ Electron はウェブページを表示させるために Chromium を使用し Electron では、メインプロセスとレンダラープロセスとのコミュニケーションをするために [ipc](../api/ipc-renderer.md) モジュールを提供しています。またそれと、RPC 形式の通信を行う [remote](../api/remote.md) モジュールもあります。 +Electron では、メインプロセスとレンダラープロセスとのコミュニケーションをするには幾つかのほうほうがあります。メッセージを送信する[`ipcRenderer`](../api/ipc-renderer.md)モジュールと[`ipcMain`](../api/ipc-main.md)モジュールのように、RPC 形式の通信を行う[remote](../api/remote.md)モジュールです。[ウェブページ間のデータを共有する方法][share-data]にFAQエントリーがあります。 + ## Electronアプリを作成する 一般的に Electron アプリの構成は次のようになります: @@ -169,3 +171,5 @@ $ cd electron-quick-start # Install dependencies and run the app $ npm install && npm start ``` + +[share-data]: ../faq/electron-faq.md#how-to-share-data-between-web-pages diff --git a/docs-translations/jp/tutorial/using-selenium-and-webdriver.md b/docs-translations/jp/tutorial/using-selenium-and-webdriver.md index 3202028ebf5..a1fd0f21d7f 100644 --- a/docs-translations/jp/tutorial/using-selenium-and-webdriver.md +++ b/docs-translations/jp/tutorial/using-selenium-and-webdriver.md @@ -41,7 +41,7 @@ var driver = new webdriver.Builder() .withCapabilities({ chromeOptions: { // Here is the path to your Electron binary. - binary: '/Path-to-Your-App.app/Contents/MacOS/Atom', + binary: '/Path-to-Your-App.app/Contents/MacOS/Electron', } }) .forBrowser('electron') diff --git a/docs-translations/jp/tutorial/using-widevine-cdm-plugin.md b/docs-translations/jp/tutorial/using-widevine-cdm-plugin.md index 5cee7f26dc6..55f9d039f61 100644 --- a/docs-translations/jp/tutorial/using-widevine-cdm-plugin.md +++ b/docs-translations/jp/tutorial/using-widevine-cdm-plugin.md @@ -6,6 +6,8 @@ Electronで、Chromeブラウザーに同梱される Widevine CDMプラグイ Electronは、ライセンス的な理由でWidevine CDMプラグインは同梱されません。Widevine CDMプラグインを取得するために、最初に、使用するElectronビルドのChromバージョンとアーキテクチャを合わせた公式のChromeブラウザーをインストールする必要があります。 +__Note:__ Chromeブラウザの主要バージョンは、Electronが使用するChromeバージョンと同じでなければなりません。そうでなければ、プラグインは、`navigator.plugins`経由でロードされて表示されるにも関わらず動作しません。 + ### Windows & OS X Chromeブラウザーで、`chrome://components/`を開き、 `WidevineCdm` を探し、それが最新であることを確認し、`APP_DATA/Google/Chrome/WidevineCDM/VERSION/_platform_specific/PLATFORM_ARCH/`ディレクトリからすべてのプラグインバイナリを探します。 From 67324ce732f7cf88d4850f1584d048387bb8385b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Feb 2016 10:52:21 +0800 Subject: [PATCH 140/173] Keep the prototype chain in remote objects --- atom/browser/lib/rpc-server.js | 57 ++++++++--- atom/renderer/api/lib/remote.js | 173 +++++++++++++++----------------- 2 files changed, 127 insertions(+), 103 deletions(-) diff --git a/atom/browser/lib/rpc-server.js b/atom/browser/lib/rpc-server.js index 976a42331b6..64785879b3f 100644 --- a/atom/browser/lib/rpc-server.js +++ b/atom/browser/lib/rpc-server.js @@ -6,11 +6,52 @@ const objectsRegistry = require('./objects-registry'); const v8Util = process.atomBinding('v8_util'); const IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap; +// The internal properties of Function. +const FUNCTION_PROPERTIES = [ + 'length', 'name', 'arguments', 'caller', 'prototype', +]; + var slice = [].slice; +// Return the description of object's members: +let getObjectMemebers = function(object) { + let names = Object.getOwnPropertyNames(object); + // For Function, we should not override following properties even though they + // are "own" properties. + if (typeof object === 'function') { + names = names.filter((name) => { + return !FUNCTION_PROPERTIES.includes(name); + }); + } + // Map properties to descriptors. + return names.map((name) => { + let descriptor = Object.getOwnPropertyDescriptor(object, name); + let member = {name, enumerable: descriptor.enumerable, writable: false}; + if (descriptor.get === undefined && typeof object[name] === 'function') { + member.type = 'method'; + } else { + if (descriptor.set || descriptor.writable) + member.writable = true; + member.type = 'get'; + } + return member; + }); +}; + +// Return the description of object's prototype. +let getObjectPrototype = function(object) { + let proto = Object.getPrototypeOf(object); + if (proto === null || proto === Object.prototype) + return null; + return { + members: getObjectMemebers(proto), + proto: getObjectPrototype(proto), + }; +}; + // Convert a real value into meta data. var valueToMeta = function(sender, value, optimizeSimpleObject) { - var el, field, i, len, meta, name; + var el, i, len, meta; if (optimizeSimpleObject == null) { optimizeSimpleObject = false; } @@ -58,18 +99,8 @@ var valueToMeta = function(sender, value, optimizeSimpleObject) { // passed to renderer we would assume the renderer keeps a reference of // it. meta.id = objectsRegistry.add(sender.getId(), value); - meta.members = (function() { - var results; - results = []; - for (name in value) { - field = value[name]; - results.push({ - name: name, - type: typeof field - }); - } - return results; - })(); + meta.members = getObjectMemebers(value); + meta.proto = getObjectPrototype(value); } else if (meta.type === 'buffer') { meta.value = Array.prototype.slice.call(value, 0); } else if (meta.type === 'promise') { diff --git a/atom/renderer/api/lib/remote.js b/atom/renderer/api/lib/remote.js index d8a5508621e..d28ec6dfcbd 100644 --- a/atom/renderer/api/lib/remote.js +++ b/atom/renderer/api/lib/remote.js @@ -1,3 +1,5 @@ +'use strict'; + const ipcRenderer = require('electron').ipcRenderer; const CallbacksRegistry = require('electron').CallbacksRegistry; const v8Util = process.atomBinding('v8_util'); @@ -88,9 +90,59 @@ var wrapArgs = function(args, visited) { return Array.prototype.slice.call(args).map(valueToMeta); }; +// Populate object's members from descriptors. +// This matches |getObjectMemebers| in rpc-server. +let setObjectMembers = function(object, metaId, members) { + for (let member of members) { + if (object.hasOwnProperty(member.name)) + continue; + + let descriptor = { enumerable: member.enumerable }; + if (member.type === 'method') { + let remoteMemberFunction = function() { + if (this && this.constructor === remoteMemberFunction) { + // Constructor call. + let ret = ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(arguments)); + return metaToValue(ret); + } else { + // Call member function. + let ret = ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(arguments)); + return metaToValue(ret); + } + }; + descriptor.value = remoteMemberFunction; + } else if (member.type === 'get') { + descriptor.get = function() { + return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_GET', metaId, member.name)); + }; + + // Only set setter when it is writable. + if (member.writable) { + descriptor.set = function(value) { + ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_SET', metaId, member.name, value); + return value; + }; + } + } + + Object.defineProperty(object, member.name, descriptor); + } +}; + +// Populate object's prototype from descriptor. +// This matches |getObjectPrototype| in rpc-server. +let setObjectPrototype = function(object, metaId, descriptor) { + if (descriptor === null) + return; + let proto = {}; + setObjectMembers(proto, metaId, descriptor.members); + setObjectPrototype(proto, metaId, descriptor.proto); + Object.setPrototypeOf(object, proto); +}; + // Convert meta data from browser into real value. var metaToValue = function(meta) { - var el, i, j, len, len1, member, ref1, ref2, results, ret; + var el, i, len, ref1, results, ret; switch (meta.type) { case 'value': return meta.value; @@ -115,55 +167,42 @@ var metaToValue = function(meta) { case 'exception': throw new Error(meta.message + "\n" + meta.stack); default: - if (meta.type === 'function') { - // A shadow class to represent the remote function object. - ret = (function() { - function RemoteFunction() { - var obj; - if (this.constructor === RemoteFunction) { - - // Constructor call. - obj = ipcRenderer.sendSync('ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments)); - - /* - Returning object in constructor will replace constructed object - with the returned object. - http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this - */ - return metaToValue(obj); - } else { - - // Function call. - obj = ipcRenderer.sendSync('ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments)); - return metaToValue(obj); - } - } - - return RemoteFunction; - - })(); - } else { - ret = v8Util.createObjectWithName(meta.name); - } - - // Polulate delegate members. - ref2 = meta.members; - for (j = 0, len1 = ref2.length; j < len1; j++) { - member = ref2[j]; - if (member.type === 'function') { - ret[member.name] = createRemoteMemberFunction(meta.id, member.name); - } else { - Object.defineProperty(ret, member.name, createRemoteMemberProperty(meta.id, member.name)); - } - } - if (remoteObjectCache.has(meta.id)) return remoteObjectCache.get(meta.id); + if (meta.type === 'function') { + // A shadow class to represent the remote function object. + let remoteFunction = function() { + if (this && this.constructor === remoteFunction) { + // Constructor call. + let obj = ipcRenderer.sendSync('ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments)); + // Returning object in constructor will replace constructed object + // with the returned object. + // http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this + return metaToValue(obj); + } else { + // Function call. + let obj = ipcRenderer.sendSync('ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments)); + return metaToValue(obj); + } + }; + ret = remoteFunction; + } else { + ret = {}; + } + + // Populate delegate members. + setObjectMembers(ret, meta.id, meta.members); + // Populate delegate prototype. + setObjectPrototype(ret, meta.id, meta.proto); + + // Set constructor.name to object's name. + Object.defineProperty(ret.constructor, 'name', { value: meta.name }); + // Track delegate object's life time, and tell the browser to clean up // when the object is GCed. v8Util.setDestructor(ret, function() { - return ipcRenderer.send('ATOM_BROWSER_DEREFERENCE', meta.id); + ipcRenderer.send('ATOM_BROWSER_DEREFERENCE', meta.id); }); // Remember object's id. @@ -192,52 +231,6 @@ var metaToPlainObject = function(meta) { return obj; }; -// Create a RemoteMemberFunction instance. -// This function's content should not be inlined into metaToValue, otherwise V8 -// may consider it circular reference. -var createRemoteMemberFunction = function(metaId, name) { - return (function() { - function RemoteMemberFunction() { - var ret; - if (this.constructor === RemoteMemberFunction) { - - // Constructor call. - ret = ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_CONSTRUCTOR', metaId, name, wrapArgs(arguments)); - return metaToValue(ret); - } else { - - // Call member function. - ret = ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_CALL', metaId, name, wrapArgs(arguments)); - return metaToValue(ret); - } - } - - return RemoteMemberFunction; - - })(); -}; - -// Create configuration for defineProperty. -// This function's content should not be inlined into metaToValue, otherwise V8 -// may consider it circular reference. -var createRemoteMemberProperty = function(metaId, name) { - return { - enumerable: true, - configurable: false, - set: function(value) { - - // Set member data. - ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_SET', metaId, name, value); - return value; - }, - get: function() { - - // Get member data. - return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_GET', metaId, name)); - } - }; -}; - // Browser calls a callback in renderer. ipcRenderer.on('ATOM_RENDERER_CALLBACK', function(event, id, args) { return callbacksRegistry.apply(id, metaToValue(args)); From f610e332b3e31d9713724d701798e3f945da7311 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Feb 2016 12:13:26 +0800 Subject: [PATCH 141/173] spec: Tests for remote ES6 class --- spec/api-ipc-spec.js | 37 +++++++++++++++++++++++++++++++++++ spec/fixtures/module/class.js | 29 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 spec/fixtures/module/class.js diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index 9cf741412b0..90e099fa612 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -1,3 +1,5 @@ +'use strict'; + const assert = require('assert'); const path = require('path'); @@ -98,6 +100,41 @@ describe('ipc module', function() { }); }); + describe('remote class', function() { + let cl = remote.require(path.join(fixtures, 'module', 'class.js')); + let base = cl.base; + let derived = cl.derived; + + it('can get methods', function() { + assert.equal(base.method(), 'method'); + }); + + it('can get properties', function() { + assert.equal(base.readonly, 'readonly'); + }); + + it('can change properties', function() { + assert.equal(base.value, 'old'); + base.value = 'new'; + assert.equal(base.value, 'new'); + base.value = 'old'; + }); + + it('has unenumerable methods', function() { + assert(!base.hasOwnProperty('method')); + assert(Object.getPrototypeOf(base).hasOwnProperty('method')); + }); + + it('keeps prototype chain in derived class', function() { + assert.equal(derived.method(), 'method'); + assert.equal(derived.readonly, 'readonly'); + assert(!derived.hasOwnProperty('method')); + let proto = Object.getPrototypeOf(derived); + assert(!proto.hasOwnProperty('method')); + assert(Object.getPrototypeOf(proto).hasOwnProperty('method')); + }); + }); + describe('ipc.sender.send', function() { it('should work when sending an object containing id property', function(done) { var obj = { diff --git a/spec/fixtures/module/class.js b/spec/fixtures/module/class.js new file mode 100644 index 00000000000..f25eb2593ff --- /dev/null +++ b/spec/fixtures/module/class.js @@ -0,0 +1,29 @@ +'use strict'; + +let value = 'old'; + +class BaseClass { + method() { + return 'method'; + } + + get readonly() { + return 'readonly'; + } + + get value() { + return value; + } + + set value(val) { + value = val; + } +} + +class DerivedClass extends BaseClass { +} + +module.exports = { + base: new BaseClass, + derived: new DerivedClass, +} From c65cfadd094f951d65b5561df40c778d3ba583d6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Feb 2016 11:51:41 +0800 Subject: [PATCH 142/173] v8Util.createObjectWithName is no longer used --- atom/browser/lib/rpc-server.js | 4 +++- atom/common/api/atom_api_v8_util.cc | 35 ----------------------------- 2 files changed, 3 insertions(+), 36 deletions(-) diff --git a/atom/browser/lib/rpc-server.js b/atom/browser/lib/rpc-server.js index 64785879b3f..c3e5159cd9e 100644 --- a/atom/browser/lib/rpc-server.js +++ b/atom/browser/lib/rpc-server.js @@ -162,7 +162,9 @@ var unwrapArgs = function(sender, args) { then: metaToValue(meta.then) }); case 'object': { - let ret = v8Util.createObjectWithName(meta.name); + let ret = {}; + Object.defineProperty(ret.constructor, 'name', { value: meta.name }); + ref = meta.members; for (i = 0, len = ref.length; i < len; i++) { member = ref[i]; diff --git a/atom/common/api/atom_api_v8_util.cc b/atom/common/api/atom_api_v8_util.cc index c86335adb15..f50d3485eba 100644 --- a/atom/common/api/atom_api_v8_util.cc +++ b/atom/common/api/atom_api_v8_util.cc @@ -2,49 +2,15 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#include #include #include "atom/common/api/object_life_monitor.h" #include "atom/common/node_includes.h" -#include "base/stl_util.h" #include "native_mate/dictionary.h" #include "v8/include/v8-profiler.h" namespace { -// A Persistent that can be copied and will not free itself. -template -struct LeakedPersistentTraits { - typedef v8::Persistent > LeakedPersistent; - static const bool kResetInDestructor = false; - template - static V8_INLINE void Copy(const v8::Persistent& source, - LeakedPersistent* dest) { - // do nothing, just allow copy - } -}; - -// The handles are leaked on purpose. -using FunctionTemplateHandle = - LeakedPersistentTraits::LeakedPersistent; -std::map function_templates_; - -v8::Local CreateObjectWithName(v8::Isolate* isolate, - const std::string& name) { - if (name == "Object") - return v8::Object::New(isolate); - - if (ContainsKey(function_templates_, name)) - return v8::Local::New( - isolate, function_templates_[name])->GetFunction()->NewInstance(); - - v8::Local t = v8::FunctionTemplate::New(isolate); - t->SetClassName(mate::StringToV8(isolate, name)); - function_templates_[name] = FunctionTemplateHandle(isolate, t); - return t->GetFunction()->NewInstance(); -} - v8::Local GetHiddenValue(v8::Local object, v8::Local key) { return object->GetHiddenValue(key); @@ -78,7 +44,6 @@ void TakeHeapSnapshot(v8::Isolate* isolate) { void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); - dict.SetMethod("createObjectWithName", &CreateObjectWithName); dict.SetMethod("getHiddenValue", &GetHiddenValue); dict.SetMethod("setHiddenValue", &SetHiddenValue); dict.SetMethod("deleteHiddenValue", &DeleteHiddenValue); From fe7462b3526d9c74534133273305223180ed0fd5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Feb 2016 12:26:41 +0800 Subject: [PATCH 143/173] No longer needs cache for methods of remote Refs #4517. --- atom/renderer/api/lib/remote.js | 56 +++++---------------------------- 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/atom/renderer/api/lib/remote.js b/atom/renderer/api/lib/remote.js index d28ec6dfcbd..a9798338faa 100644 --- a/atom/renderer/api/lib/remote.js +++ b/atom/renderer/api/lib/remote.js @@ -141,7 +141,7 @@ let setObjectPrototype = function(object, metaId, descriptor) { }; // Convert meta data from browser into real value. -var metaToValue = function(meta) { +let metaToValue = function(meta) { var el, i, len, ref1, results, ret; switch (meta.type) { case 'value': @@ -257,73 +257,33 @@ for (var name in browserModules) { } // Get remote module. -// (Just like node's require, the modules are cached permanently, note that this -// is safe leak since the object is not expected to get freed in browser) -var moduleCache = {}; - exports.require = function(module) { - var meta; - if (moduleCache[module] != null) { - return moduleCache[module]; - } - meta = ipcRenderer.sendSync('ATOM_BROWSER_REQUIRE', module); - return moduleCache[module] = metaToValue(meta); + return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_REQUIRE', module)); }; -// Optimize require('electron'). -moduleCache.electron = exports; - // Alias to remote.require('electron').xxx. -var builtinCache = {}; - exports.getBuiltin = function(module) { - var meta; - if (builtinCache[module] != null) { - return builtinCache[module]; - } - meta = ipcRenderer.sendSync('ATOM_BROWSER_GET_BUILTIN', module); - return builtinCache[module] = metaToValue(meta); + return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_GET_BUILTIN', module)); }; -// Get current BrowserWindow object. -var windowCache = null; - +// Get current BrowserWindow. exports.getCurrentWindow = function() { - var meta; - if (windowCache != null) { - return windowCache; - } - meta = ipcRenderer.sendSync('ATOM_BROWSER_CURRENT_WINDOW'); - return windowCache = metaToValue(meta); + return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_CURRENT_WINDOW')); }; // Get current WebContents object. -var webContentsCache = null; - exports.getCurrentWebContents = function() { - var meta; - if (webContentsCache != null) { - return webContentsCache; - } - meta = ipcRenderer.sendSync('ATOM_BROWSER_CURRENT_WEB_CONTENTS'); - return webContentsCache = metaToValue(meta); + return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_CURRENT_WEB_CONTENTS')); }; // Get a global object in browser. exports.getGlobal = function(name) { - var meta; - meta = ipcRenderer.sendSync('ATOM_BROWSER_GLOBAL', name); - return metaToValue(meta); + return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_GLOBAL', name)); }; // Get the process object in browser. -var processCache = null; - exports.__defineGetter__('process', function() { - if (processCache == null) { - processCache = exports.getGlobal('process'); - } - return processCache; + return exports.getGlobal('process'); }); // Create a funtion that will return the specifed value when called in browser. From 2b04af434937d4cde9a5b6584c19603cc586e6c3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Feb 2016 14:03:31 +0800 Subject: [PATCH 144/173] No longer need to count the references in webContents All remote objects are now cached in renderer process, so there is always only one reference to one remote object for each webContents. --- atom/browser/lib/objects-registry.js | 73 +++++++++++----------------- atom/browser/lib/rpc-server.js | 2 +- 2 files changed, 30 insertions(+), 45 deletions(-) diff --git a/atom/browser/lib/objects-registry.js b/atom/browser/lib/objects-registry.js index e9d6d365fa5..90d1fe80e53 100644 --- a/atom/browser/lib/objects-registry.js +++ b/atom/browser/lib/objects-registry.js @@ -15,70 +15,57 @@ class ObjectsRegistry extends EventEmitter { this.storage = {}; // Stores the IDs of objects referenced by WebContents. - // (webContentsId) => {(id) => (count)} + // (webContentsId) => [id] this.owners = {}; } - // Register a new object, the object would be kept referenced until you release - // it explicitly. + // Register a new object and return its assigned ID. If the object is already + // registered then the already assigned ID would be returned. add(webContentsId, obj) { - var base, base1, id; - id = this.saveToStorage(obj); + // Get or assign an ID to the object. + let id = this.saveToStorage(obj); - // Remember the owner. - if ((base = this.owners)[webContentsId] == null) { - base[webContentsId] = {}; + // Add object to the set of referenced objects. + let owner = this.owners[webContentsId]; + if (!owner) + owner = this.owners[webContentsId] = new Set(); + if (!owner.has(id)) { + owner.add(id); + // Increase reference count if not referenced before. + this.storage[id].count++; } - if ((base1 = this.owners[webContentsId])[id] == null) { - base1[id] = 0; - } - this.owners[webContentsId][id]++; - - // Returns object's id return id; } // Get an object according to its ID. get(id) { - var ref; - return (ref = this.storage[id]) != null ? ref.object : void 0; + return this.storage[id].object; } // Dereference an object according to its ID. remove(webContentsId, id) { - var pointer; - this.dereference(id, 1); + // Dereference from the storage. + this.dereference(id); - // Also reduce the count in owner. - pointer = this.owners[webContentsId]; - if (pointer == null) { - return; - } - --pointer[id]; - if (pointer[id] === 0) { - return delete pointer[id]; - } + // Also remove the reference in owner. + this.owners[webContentsId].delete(id); } // Clear all references to objects refrenced by the WebContents. clear(webContentsId) { - var count, id, ref; - this.emit("clear-" + webContentsId); - if (this.owners[webContentsId] == null) { + this.emit(`clear-${webContentsId}`); + + let owner = this.owners[webContentsId]; + if (!owner) return; - } - ref = this.owners[webContentsId]; - for (id in ref) { - count = ref[id]; - this.dereference(id, count); - } - return delete this.owners[webContentsId]; + for (let id of owner) + this.dereference(id); + delete this.owners[webContentsId]; } // Private: Saves the object into storage and assigns an ID for it. saveToStorage(object) { - var id; - id = v8Util.getHiddenValue(object, 'atomId'); + let id = v8Util.getHiddenValue(object, 'atomId'); if (!id) { id = ++this.nextId; this.storage[id] = { @@ -87,18 +74,16 @@ class ObjectsRegistry extends EventEmitter { }; v8Util.setHiddenValue(object, 'atomId', id); } - ++this.storage[id].count; return id; } // Private: Dereference the object from store. - dereference(id, count) { - var pointer; - pointer = this.storage[id]; + dereference(id) { + let pointer = this.storage[id]; if (pointer == null) { return; } - pointer.count -= count; + pointer.count -= 1; if (pointer.count === 0) { v8Util.deleteHiddenValue(pointer.object, 'atomId'); return delete this.storage[id]; diff --git a/atom/browser/lib/rpc-server.js b/atom/browser/lib/rpc-server.js index c3e5159cd9e..f366eb43a52 100644 --- a/atom/browser/lib/rpc-server.js +++ b/atom/browser/lib/rpc-server.js @@ -145,7 +145,7 @@ var exceptionToMeta = function(error) { var unwrapArgs = function(sender, args) { var metaToValue; metaToValue = function(meta) { - var i, len, member, ref, rendererReleased, returnValue; + var i, len, member, ref, returnValue; switch (meta.type) { case 'value': return meta.value; From 59d6e7d6ef769118a7357c2a0d266223819f1459 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Feb 2016 14:10:25 +0800 Subject: [PATCH 145/173] ObjectsRegistry no longer needs to send events --- atom/browser/lib/objects-registry.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/atom/browser/lib/objects-registry.js b/atom/browser/lib/objects-registry.js index 90d1fe80e53..9677c7fea22 100644 --- a/atom/browser/lib/objects-registry.js +++ b/atom/browser/lib/objects-registry.js @@ -1,13 +1,9 @@ 'use strict'; -const EventEmitter = require('events').EventEmitter; const v8Util = process.atomBinding('v8_util'); -class ObjectsRegistry extends EventEmitter { +class ObjectsRegistry { constructor() { - super(); - - this.setMaxListeners(Number.MAX_VALUE); this.nextId = 0; // Stores all objects by ref-counting. @@ -53,8 +49,6 @@ class ObjectsRegistry extends EventEmitter { // Clear all references to objects refrenced by the WebContents. clear(webContentsId) { - this.emit(`clear-${webContentsId}`); - let owner = this.owners[webContentsId]; if (!owner) return; From d4c954870a14c90f114482e03ef4cc3b60b092bd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Feb 2016 14:15:51 +0800 Subject: [PATCH 146/173] Remove a few CoffeeScript generated junks --- atom/browser/lib/rpc-server.js | 35 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/atom/browser/lib/rpc-server.js b/atom/browser/lib/rpc-server.js index f366eb43a52..c3ea8ca6b09 100644 --- a/atom/browser/lib/rpc-server.js +++ b/atom/browser/lib/rpc-server.js @@ -11,8 +11,6 @@ const FUNCTION_PROPERTIES = [ 'length', 'name', 'arguments', 'caller', 'prototype', ]; -var slice = [].slice; - // Return the description of object's members: let getObjectMemebers = function(object) { let names = Object.getOwnPropertyNames(object); @@ -281,14 +279,13 @@ ipcMain.on('ATOM_BROWSER_CURRENT_WEB_CONTENTS', function(event) { }); ipcMain.on('ATOM_BROWSER_CONSTRUCTOR', function(event, id, args) { - var constructor, obj; try { args = unwrapArgs(event.sender, args); - constructor = objectsRegistry.get(id); + let constructor = objectsRegistry.get(id); // Call new with array of arguments. // http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible - obj = new (Function.prototype.bind.apply(constructor, [null].concat(args))); + let obj = new (Function.prototype.bind.apply(constructor, [null].concat(args))); return event.returnValue = valueToMeta(event.sender, obj); } catch (error) { return event.returnValue = exceptionToMeta(error); @@ -296,10 +293,9 @@ ipcMain.on('ATOM_BROWSER_CONSTRUCTOR', function(event, id, args) { }); ipcMain.on('ATOM_BROWSER_FUNCTION_CALL', function(event, id, args) { - var func; try { args = unwrapArgs(event.sender, args); - func = objectsRegistry.get(id); + let func = objectsRegistry.get(id); return callFunction(event, func, global, args); } catch (error) { return event.returnValue = exceptionToMeta(error); @@ -307,13 +303,12 @@ ipcMain.on('ATOM_BROWSER_FUNCTION_CALL', function(event, id, args) { }); ipcMain.on('ATOM_BROWSER_MEMBER_CONSTRUCTOR', function(event, id, method, args) { - var constructor, obj; try { args = unwrapArgs(event.sender, args); - constructor = objectsRegistry.get(id)[method]; + let constructor = objectsRegistry.get(id)[method]; // Call new with array of arguments. - obj = new (Function.prototype.bind.apply(constructor, [null].concat(args))); + let obj = new (Function.prototype.bind.apply(constructor, [null].concat(args))); return event.returnValue = valueToMeta(event.sender, obj); } catch (error) { return event.returnValue = exceptionToMeta(error); @@ -321,10 +316,9 @@ ipcMain.on('ATOM_BROWSER_MEMBER_CONSTRUCTOR', function(event, id, method, args) }); ipcMain.on('ATOM_BROWSER_MEMBER_CALL', function(event, id, method, args) { - var obj; try { args = unwrapArgs(event.sender, args); - obj = objectsRegistry.get(id); + let obj = objectsRegistry.get(id); return callFunction(event, obj[method], obj, args); } catch (error) { return event.returnValue = exceptionToMeta(error); @@ -332,9 +326,8 @@ ipcMain.on('ATOM_BROWSER_MEMBER_CALL', function(event, id, method, args) { }); ipcMain.on('ATOM_BROWSER_MEMBER_SET', function(event, id, name, value) { - var obj; try { - obj = objectsRegistry.get(id); + let obj = objectsRegistry.get(id); obj[name] = value; return event.returnValue = null; } catch (error) { @@ -343,9 +336,8 @@ ipcMain.on('ATOM_BROWSER_MEMBER_SET', function(event, id, name, value) { }); ipcMain.on('ATOM_BROWSER_MEMBER_GET', function(event, id, name) { - var obj; try { - obj = objectsRegistry.get(id); + let obj = objectsRegistry.get(id); return event.returnValue = valueToMeta(event.sender, obj[name]); } catch (error) { return event.returnValue = exceptionToMeta(error); @@ -357,21 +349,18 @@ ipcMain.on('ATOM_BROWSER_DEREFERENCE', function(event, id) { }); ipcMain.on('ATOM_BROWSER_GUEST_WEB_CONTENTS', function(event, guestInstanceId) { - var guestViewManager; try { - guestViewManager = require('./guest-view-manager'); + let guestViewManager = require('./guest-view-manager'); return event.returnValue = valueToMeta(event.sender, guestViewManager.getGuest(guestInstanceId)); } catch (error) { return event.returnValue = exceptionToMeta(error); } }); -ipcMain.on('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function() { - var args, event, guest, guestInstanceId, guestViewManager, method; - event = arguments[0], guestInstanceId = arguments[1], method = arguments[2], args = 4 <= arguments.length ? slice.call(arguments, 3) : []; +ipcMain.on('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function(event, guestInstanceId, method, ...args) { try { - guestViewManager = require('./guest-view-manager'); - guest = guestViewManager.getGuest(guestInstanceId); + let guestViewManager = require('./guest-view-manager'); + let guest = guestViewManager.getGuest(guestInstanceId); return guest[method].apply(guest, args); } catch (error) { return event.returnValue = exceptionToMeta(error); From 593a79ce20296f0178e6f38016039e5e12a1f77a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Feb 2016 14:36:50 +0800 Subject: [PATCH 147/173] Separate renderer functions by renderer process ID Close #4324. --- atom/browser/lib/rpc-server.js | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/atom/browser/lib/rpc-server.js b/atom/browser/lib/rpc-server.js index c3ea8ca6b09..7b59648eda1 100644 --- a/atom/browser/lib/rpc-server.js +++ b/atom/browser/lib/rpc-server.js @@ -11,6 +11,10 @@ const FUNCTION_PROPERTIES = [ 'length', 'name', 'arguments', 'caller', 'prototype', ]; +// The remote functions in renderer processes. +// (webContentsId) => {id: Function} +let rendererFunctions = {}; + // Return the description of object's members: let getObjectMemebers = function(object) { let names = Object.getOwnPropertyNames(object); @@ -177,32 +181,30 @@ var unwrapArgs = function(sender, args) { }; case 'function': { // Cache the callbacks in renderer. - if (!sender.callbacks) { - sender.callbacks = new IDWeakMap; - sender.on('render-view-deleted', function() { - return this.callbacks.clear(); + let webContentsId = sender.getId(); + let callbacks = rendererFunctions[webContentsId]; + if (!callbacks) { + callbacks = rendererFunctions[webContentsId] = new IDWeakMap; + sender.once('render-view-deleted', function(event, id) { + callbacks.clear(); + delete rendererFunctions[id]; }); } - if (sender.callbacks.has(meta.id)) - return sender.callbacks.get(meta.id); - - // Prevent the callback from being called when its page is gone. - rendererReleased = false; - sender.once('render-view-deleted', function() { - rendererReleased = true; - }); + if (callbacks.has(meta.id)) + return callbacks.get(meta.id); let callIntoRenderer = function(...args) { - if (rendererReleased || sender.isDestroyed()) + if ((webContentsId in rendererFunctions) && !sender.isDestroyed()) + sender.send('ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, args)); + else throw new Error(`Attempting to call a function in a renderer window that has been closed or released. Function provided here: ${meta.location}.`); - sender.send('ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, args)); }; v8Util.setDestructor(callIntoRenderer, function() { - if (!rendererReleased && !sender.isDestroyed()) + if ((webContentsId in rendererFunctions) && !sender.isDestroyed()) sender.send('ATOM_RENDERER_RELEASE_CALLBACK', meta.id); }); - sender.callbacks.set(meta.id, callIntoRenderer); + callbacks.set(meta.id, callIntoRenderer); return callIntoRenderer; } default: From 6753fcc1b4bae07bad8cae674770da220bf9fafb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Feb 2016 14:54:55 +0800 Subject: [PATCH 148/173] Get rid of the ATOM_BROWSER_RELEASE_RENDER_VIEW event --- atom/browser/api/atom_api_web_contents.cc | 12 +----------- atom/browser/lib/objects-registry.js | 10 ++++++++-- atom/browser/lib/rpc-server.js | 7 +------ 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index a7946786c51..72443bdb815 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -485,17 +485,7 @@ void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) { } void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) { - int process_id = render_view_host->GetProcess()->GetID(); - Emit("render-view-deleted", process_id); - - // process.emit('ATOM_BROWSER_RELEASE_RENDER_VIEW', processId); - // Tell the rpc server that a render view has been deleted and we need to - // release all objects owned by it. - v8::Locker locker(isolate()); - v8::HandleScope handle_scope(isolate()); - node::Environment* env = node::Environment::GetCurrent(isolate()); - mate::EmitEvent(isolate(), env->process_object(), - "ATOM_BROWSER_RELEASE_RENDER_VIEW", process_id); + Emit("render-view-deleted", render_view_host->GetProcess()->GetID()); } void WebContents::RenderProcessGone(base::TerminationStatus status) { diff --git a/atom/browser/lib/objects-registry.js b/atom/browser/lib/objects-registry.js index 9677c7fea22..c3f70c976ec 100644 --- a/atom/browser/lib/objects-registry.js +++ b/atom/browser/lib/objects-registry.js @@ -17,14 +17,20 @@ class ObjectsRegistry { // Register a new object and return its assigned ID. If the object is already // registered then the already assigned ID would be returned. - add(webContentsId, obj) { + add(webContents, obj) { // Get or assign an ID to the object. let id = this.saveToStorage(obj); // Add object to the set of referenced objects. + let webContentsId = webContents.getId(); let owner = this.owners[webContentsId]; - if (!owner) + if (!owner) { owner = this.owners[webContentsId] = new Set(); + // Clear the storage when webContents is reloaded/navigated. + webContents.once('render-view-deleted', (event, id) => { + this.clear(id); + }); + } if (!owner.has(id)) { owner.add(id); // Increase reference count if not referenced before. diff --git a/atom/browser/lib/rpc-server.js b/atom/browser/lib/rpc-server.js index 7b59648eda1..20ee8fbdeae 100644 --- a/atom/browser/lib/rpc-server.js +++ b/atom/browser/lib/rpc-server.js @@ -100,7 +100,7 @@ var valueToMeta = function(sender, value, optimizeSimpleObject) { // Reference the original value if it's an object, because when it's // passed to renderer we would assume the renderer keeps a reference of // it. - meta.id = objectsRegistry.add(sender.getId(), value); + meta.id = objectsRegistry.add(sender, value); meta.members = getObjectMemebers(value); meta.proto = getObjectPrototype(value); } else if (meta.type === 'buffer') { @@ -239,11 +239,6 @@ var callFunction = function(event, func, caller, args) { } }; -// Send by BrowserWindow when its render view is deleted. -process.on('ATOM_BROWSER_RELEASE_RENDER_VIEW', function(id) { - return objectsRegistry.clear(id); -}); - ipcMain.on('ATOM_BROWSER_REQUIRE', function(event, module) { try { return event.returnValue = valueToMeta(event.sender, process.mainModule.require(module)); From 96b2705bd3ec3fe7a92bc27bf061613d4871ae19 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Feb 2016 15:20:23 +0800 Subject: [PATCH 149/173] Fix render-view-deleted being emitted twice --- atom/browser/api/atom_api_web_contents.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 72443bdb815..ee6ad94ba77 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -296,6 +296,7 @@ WebContents::~WebContents() { // The WebContentsDestroyed will not be called automatically because we // unsubscribe from webContents before destroying it. So we have to manually // call it here to make sure "destroyed" event is emitted. + RenderViewDeleted(web_contents()->GetRenderViewHost()); WebContentsDestroyed(); } } @@ -665,9 +666,6 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) { // be destroyed on close, and WebContentsDestroyed would be called for it, so // we need to make sure the api::WebContents is also deleted. void WebContents::WebContentsDestroyed() { - // The RenderViewDeleted was not called when the WebContents is destroyed. - RenderViewDeleted(web_contents()->GetRenderViewHost()); - // This event is only for internal use, which is emitted when WebContents is // being destroyed. Emit("will-destroy"); From 331bc42d57f04648a5c92e10afdc074d69cc827e Mon Sep 17 00:00:00 2001 From: jin5354 Date: Tue, 23 Feb 2016 10:00:28 +0800 Subject: [PATCH 150/173] docs: update zh-CN doc debugging-main-process.md update zh-CN doc debugging-main-process.md to be up-to-date with English ver. --- .../zh-CN/tutorial/debugging-main-process.md | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/docs-translations/zh-CN/tutorial/debugging-main-process.md b/docs-translations/zh-CN/tutorial/debugging-main-process.md index 48f3579394e..f971a40892f 100644 --- a/docs-translations/zh-CN/tutorial/debugging-main-process.md +++ b/docs-translations/zh-CN/tutorial/debugging-main-process.md @@ -18,16 +18,31 @@ ## 使用 node-inspector 来调试 -__备注:__ Electron 使用 node v0.11.13 版本,目前对 node-inspector支持的不是特别好, +__备注:__ Electron 目前对 node-inspector支持的不是特别好, 如果你通过 node-inspector 的 console 来检查 `process` 对象,主进程就会崩溃。 -### 1. 开始 [node-inspector][node-inspector] 服务 +### 1. 确认你已经安装了 [node-gyp 所需工具](https://github.com/nodejs/node-gyp#installation) + +### 2. 安装 [node-inspector][node-inspector] ```bash -$ node-inspector +$ npm install node-inspector ``` -### 2. 打开 Electron 的调试模式 +### 3. 安装 `node-pre-gyp` 的一个修订版 + +```bash +$ npm install git+https://git@github.com/enlight/node-pre-gyp.git#detect-electron-runtime-in-find +``` + +### 4. 为 Electron 重新编译 `node-inspector` `v8` 模块(将 target 参数修改为你的 Electron 的版本号) + +```bash +$ node_modules/.bin/node-pre-gyp --target=0.36.2 --runtime=electron --fallback-to-build --directory node_modules/v8-debug/ --dist-url=https://atom.io/download/atom-shell reinstall +$ node_modules/.bin/node-pre-gyp --target=0.36.2 --runtime=electron --fallback-to-build --directory node_modules/v8-profiler/ --dist-url=https://atom.io/download/atom-shell reinstall +``` + +### 5. 打开 Electron 的调试模式 你也可以用调试参数来运行 Electron : @@ -41,7 +56,13 @@ $ electron --debug=5858 your/app $ electron --debug-brk=5858 your/app ``` -### 3. 加载调试器界面 +### 6. 使用 Electron 开启 [node-inspector][node-inspector] 服务 + +```bash +$ ELECTRON_RUN_AS_NODE=true path/to/electron.exe node_modules/node-inspector/bin/inspector.js +``` + +### 7. 加载调试器界面 在 Chrome 中打开 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858 From 23268531ae32bc0ac8e847b3bb147f7ef6ba6641 Mon Sep 17 00:00:00 2001 From: Yasunari Fujieda Date: Tue, 23 Feb 2016 15:10:38 +0900 Subject: [PATCH 151/173] docs: update jp doc ipc-renderer.md --- docs-translations/jp/api/ipc-renderer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/jp/api/ipc-renderer.md b/docs-translations/jp/api/ipc-renderer.md index 5854157363f..edbd862ffaa 100644 --- a/docs-translations/jp/api/ipc-renderer.md +++ b/docs-translations/jp/api/ipc-renderer.md @@ -52,7 +52,7 @@ * `channel` String - イベント名 * `arg` (optional) -`channel`経由でメインプロセスに非同期にイベントを送信し、任意の引数を送信できます。 +`channel`経由でメインプロセスに同期的にイベントを送信し、任意の引数を送信できます。 メインプロセスは`ipcMain`で`channel`を受信することでハンドルし、 `event.returnValue`を設定してリプライします。 From bdfc19ad20fff7ef7490420f44aa60cd89f606d2 Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 19 Feb 2016 19:46:03 +0530 Subject: [PATCH 152/173] add docs --- atom/browser/api/lib/protocol.js | 4 ---- docs/api/session.md | 22 ++++++++++++++++++++++ spec/api-protocol-spec.js | 12 +++++++----- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/atom/browser/api/lib/protocol.js b/atom/browser/api/lib/protocol.js index caef0ad646b..de1bdea471f 100644 --- a/atom/browser/api/lib/protocol.js +++ b/atom/browser/api/lib/protocol.js @@ -19,10 +19,6 @@ var logAndThrow = function(callback, message) { } }; -protocol.fromPartition = function(partition) { - return session.fromPartition(partition).protocol; -}; - protocol.registerProtocol = function(scheme, handler, callback) { return logAndThrow(callback, 'registerProtocol API has been replaced by the register[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.'); }; diff --git a/docs/api/session.md b/docs/api/session.md index cc90a0b542c..d492f3d55c5 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -523,3 +523,25 @@ The `listener` will be called with `listener(details)` when an error occurs. * `timestamp` Double * `fromCache` Boolean * `error` String - The error description. + +#### `ses.protocol` + +Returns an instance of [protocol](protocol.md) module for this session. + +```javascript +const electron = require('electron'); +const app = electron.app; +const session = electron.session; +const path = require('path'); + +app.on('ready', function() { + const protocol = session.fromPartition(partitionName).protocol; + protocol.registerFileProtocol('atom', function(request, callback) { + var url = request.url.substr(7); + callback({path: path.normalize(__dirname + '/' + url)}); + }, function (error) { + if (error) + console.error('Failed to register protocol') + }); +}); +``` diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index 483155b7065..beb483e3f80 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -5,6 +5,7 @@ const qs = require('querystring'); const remote = require('electron').remote; const BrowserWindow = remote.require('electron').BrowserWindow; const protocol = remote.require('electron').protocol; +const session = remote.require('electron').session; describe('protocol module', function() { var protocolName = 'sp'; @@ -818,7 +819,7 @@ describe('protocol module', function() { describe('protocol.fromPartition', function() { var partitionName = 'temp'; - var tempProtocol = protocol.fromPartition(partitionName); + var tempProtocol = session.fromPartition(partitionName).protocol; var w = null; beforeEach(function() { @@ -852,17 +853,18 @@ describe('protocol module', function() { if (error) { return done(error); } + protocol.isProtocolHandled(protocolName, function(result) { assert.equal(result, false); }); tempProtocol.isProtocolHandled(protocolName, function(result) { assert.equal(result, true); + w.webContents.on('did-finish-load', function() { + done(); + }); + w.loadURL(protocolName + "://fake-host"); }); }); - w.webContents.on('did-finish-load', function() { - done(); - }); - w.loadURL(protocolName + "://fake-host"); }); }); }); From 49f995925c8981f4d90809d49839e05f349a9b0a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 23 Feb 2016 15:43:32 +0800 Subject: [PATCH 153/173] Notify the global menu bar when window is mapped --- atom/browser/native_window_views.cc | 15 +++++++++++++++ atom/browser/ui/views/global_menu_bar_x11.cc | 8 ++++++++ atom/browser/ui/views/global_menu_bar_x11.h | 4 ++++ 3 files changed, 27 insertions(+) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 44df87da9fb..97a2ee05a33 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -300,14 +300,29 @@ bool NativeWindowViews::IsFocused() { void NativeWindowViews::Show() { window_->native_widget_private()->ShowWithWindowState(GetRestoredState()); + +#if defined(USE_X11) + if (global_menu_bar_) + global_menu_bar_->OnWindowMapped(); +#endif } void NativeWindowViews::ShowInactive() { window_->ShowInactive(); + +#if defined(USE_X11) + if (global_menu_bar_) + global_menu_bar_->OnWindowMapped(); +#endif } void NativeWindowViews::Hide() { window_->Hide(); + +#if defined(USE_X11) + if (global_menu_bar_) + global_menu_bar_->OnWindowUnmapped(); +#endif } bool NativeWindowViews::IsVisible() { diff --git a/atom/browser/ui/views/global_menu_bar_x11.cc b/atom/browser/ui/views/global_menu_bar_x11.cc index 26279ecbe8e..b393e3f4657 100644 --- a/atom/browser/ui/views/global_menu_bar_x11.cc +++ b/atom/browser/ui/views/global_menu_bar_x11.cc @@ -210,6 +210,14 @@ void GlobalMenuBarX11::InitServer(gfx::AcceleratedWidget xid) { server_ = server_new(path.c_str()); } +void GlobalMenuBarX11::OnWindowMapped() { + GlobalMenuBarRegistrarX11::GetInstance()->OnWindowMapped(xid_); +} + +void GlobalMenuBarX11::OnWindowUnmapped() { + GlobalMenuBarRegistrarX11::GetInstance()->OnWindowUnmapped(xid_); +} + void GlobalMenuBarX11::BuildMenuFromModel(ui::MenuModel* model, DbusmenuMenuitem* parent) { for (int i = 0; i < model->GetItemCount(); ++i) { diff --git a/atom/browser/ui/views/global_menu_bar_x11.h b/atom/browser/ui/views/global_menu_bar_x11.h index 51147a26f92..d9e818ce3eb 100644 --- a/atom/browser/ui/views/global_menu_bar_x11.h +++ b/atom/browser/ui/views/global_menu_bar_x11.h @@ -46,6 +46,10 @@ class GlobalMenuBarX11 { void SetMenu(ui::MenuModel* menu_model); bool IsServerStarted() const; + // Called by NativeWindow when it show/hides. + void OnWindowMapped(); + void OnWindowUnmapped(); + private: // Creates a DbusmenuServer. void InitServer(gfx::AcceleratedWidget xid); From 367d12402ae6f3822b769da63fa5adeeaf8643b2 Mon Sep 17 00:00:00 2001 From: Robo Date: Wed, 17 Feb 2016 13:06:18 +0530 Subject: [PATCH 154/173] ipc: allow passing date instances --- .../v8_value_converter.cc | 35 +++++++++++++------ .../v8_value_converter.h | 4 --- spec/api-ipc-spec.js | 9 +++++ 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/atom/common/native_mate_converters/v8_value_converter.cc b/atom/common/native_mate_converters/v8_value_converter.cc index 7d3a1277cb8..f5d7217ae52 100644 --- a/atom/common/native_mate_converters/v8_value_converter.cc +++ b/atom/common/native_mate_converters/v8_value_converter.cc @@ -4,6 +4,7 @@ #include "atom/common/native_mate_converters/v8_value_converter.h" +#include #include #include #include @@ -20,6 +21,14 @@ namespace { const int kMaxRecursionDepth = 100; +const double kMsPerDay = 24 * 60 * 60 * 1000; + +int TimeInDay(double time_ms) { + if (time_ms < 0) time_ms -= (kMsPerDay -1); + int days = static_cast(time_ms / kMsPerDay); + return static_cast(time_ms - days * kMsPerDay); +} + } // namespace // The state of a call to FromV8Value. @@ -76,15 +85,10 @@ class V8ValueConverter::FromV8ValueState { }; V8ValueConverter::V8ValueConverter() - : date_allowed_(false), - reg_exp_allowed_(false), + : reg_exp_allowed_(false), function_allowed_(false), strip_null_from_objects_(false) {} -void V8ValueConverter::SetDateAllowed(bool val) { - date_allowed_ = val; -} - void V8ValueConverter::SetRegExpAllowed(bool val) { reg_exp_allowed_ = val; } @@ -243,12 +247,21 @@ base::Value* V8ValueConverter::FromV8ValueImpl( return NULL; if (val->IsDate()) { - if (!date_allowed_) - // JSON.stringify would convert this to a string, but an object is more - // consistent within this class. - return FromV8Object(val->ToObject(), state, isolate); v8::Date* date = v8::Date::Cast(*val); - return new base::FundamentalValue(date->NumberValue() / 1000.0); + double const time_ms = date->NumberValue(); + int const time_in_day_ms = TimeInDay(time_ms); + std::time_t time_s(time_ms / 1000.0); + char buf[128]; + std::tm* gm_time = std::gmtime(&time_s); + int year = gm_time->tm_year + 1900; + int month = gm_time->tm_mon + 1; + int ms = time_in_day_ms % 1000; + size_t length = snprintf(buf, sizeof buf, + "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", + year, month, gm_time->tm_mday, + gm_time->tm_hour, gm_time->tm_min, + gm_time->tm_sec, ms); + return new base::StringValue(std::string(buf, length)); } if (val->IsRegExp()) { diff --git a/atom/common/native_mate_converters/v8_value_converter.h b/atom/common/native_mate_converters/v8_value_converter.h index 2b695b43747..95840c01ba7 100644 --- a/atom/common/native_mate_converters/v8_value_converter.h +++ b/atom/common/native_mate_converters/v8_value_converter.h @@ -22,7 +22,6 @@ class V8ValueConverter { public: V8ValueConverter(); - void SetDateAllowed(bool val); void SetRegExpAllowed(bool val); void SetFunctionAllowed(bool val); void SetStripNullFromObjects(bool val); @@ -58,9 +57,6 @@ class V8ValueConverter { FromV8ValueState* state, v8::Isolate* isolate) const; - // If true, we will convert Date JavaScript objects to doubles. - bool date_allowed_; - // If true, we will convert RegExp JavaScript objects to string. bool reg_exp_allowed_; diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index 2c8bc28f156..92a8c001bf1 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -102,6 +102,15 @@ describe('ipc module', function() { }); ipcRenderer.send('message', obj); }); + + it('can send instance of Date', function(done) { + const currentDate = new Date(); + ipcRenderer.once('message', function(event, value) { + assert.equal(value, currentDate.toISOString()); + done(); + }); + ipcRenderer.send('message', currentDate); + }); }); describe('ipc.sendSync', function() { From bb1e4c2208fe099faf9138072bdd24a019a29ba6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 24 Feb 2016 13:25:22 +0800 Subject: [PATCH 155/173] Revert "add docs" This reverts commit bdfc19ad20fff7ef7490420f44aa60cd89f606d2. --- atom/browser/api/lib/protocol.js | 4 ++++ docs/api/session.md | 22 ---------------------- spec/api-protocol-spec.js | 12 +++++------- 3 files changed, 9 insertions(+), 29 deletions(-) diff --git a/atom/browser/api/lib/protocol.js b/atom/browser/api/lib/protocol.js index de1bdea471f..caef0ad646b 100644 --- a/atom/browser/api/lib/protocol.js +++ b/atom/browser/api/lib/protocol.js @@ -19,6 +19,10 @@ var logAndThrow = function(callback, message) { } }; +protocol.fromPartition = function(partition) { + return session.fromPartition(partition).protocol; +}; + protocol.registerProtocol = function(scheme, handler, callback) { return logAndThrow(callback, 'registerProtocol API has been replaced by the register[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.'); }; diff --git a/docs/api/session.md b/docs/api/session.md index d492f3d55c5..cc90a0b542c 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -523,25 +523,3 @@ The `listener` will be called with `listener(details)` when an error occurs. * `timestamp` Double * `fromCache` Boolean * `error` String - The error description. - -#### `ses.protocol` - -Returns an instance of [protocol](protocol.md) module for this session. - -```javascript -const electron = require('electron'); -const app = electron.app; -const session = electron.session; -const path = require('path'); - -app.on('ready', function() { - const protocol = session.fromPartition(partitionName).protocol; - protocol.registerFileProtocol('atom', function(request, callback) { - var url = request.url.substr(7); - callback({path: path.normalize(__dirname + '/' + url)}); - }, function (error) { - if (error) - console.error('Failed to register protocol') - }); -}); -``` diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index beb483e3f80..483155b7065 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -5,7 +5,6 @@ const qs = require('querystring'); const remote = require('electron').remote; const BrowserWindow = remote.require('electron').BrowserWindow; const protocol = remote.require('electron').protocol; -const session = remote.require('electron').session; describe('protocol module', function() { var protocolName = 'sp'; @@ -819,7 +818,7 @@ describe('protocol module', function() { describe('protocol.fromPartition', function() { var partitionName = 'temp'; - var tempProtocol = session.fromPartition(partitionName).protocol; + var tempProtocol = protocol.fromPartition(partitionName); var w = null; beforeEach(function() { @@ -853,18 +852,17 @@ describe('protocol module', function() { if (error) { return done(error); } - protocol.isProtocolHandled(protocolName, function(result) { assert.equal(result, false); }); tempProtocol.isProtocolHandled(protocolName, function(result) { assert.equal(result, true); - w.webContents.on('did-finish-load', function() { - done(); - }); - w.loadURL(protocolName + "://fake-host"); }); }); + w.webContents.on('did-finish-load', function() { + done(); + }); + w.loadURL(protocolName + "://fake-host"); }); }); }); From 8ff30a2abc15059fdce79faa1576b12bd6536158 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 24 Feb 2016 13:25:30 +0800 Subject: [PATCH 156/173] Revert "protocol: respect requests from partition" This reverts commit 85800256deb7c2eb543bba8d28eb369e3521eb54. --- atom/browser/api/atom_api_protocol.cc | 70 ++++++++++++++++----------- atom/browser/api/atom_api_protocol.h | 11 ++--- atom/browser/api/atom_api_session.cc | 10 ---- atom/browser/api/atom_api_session.h | 2 - atom/browser/api/lib/protocol.js | 9 +--- atom/common/node_bindings.cc | 1 + spec/api-protocol-spec.js | 51 ------------------- 7 files changed, 49 insertions(+), 105 deletions(-) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 335c20e11e3..09da9c71cad 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -28,6 +28,33 @@ Protocol::Protocol(AtomBrowserContext* browser_context) CHECK(job_factory_); } +mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + return mate::ObjectTemplateBuilder(isolate) + .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes) + .SetMethod("registerServiceWorkerSchemes", + &Protocol::RegisterServiceWorkerSchemes) + .SetMethod("registerStringProtocol", + &Protocol::RegisterProtocol) + .SetMethod("registerBufferProtocol", + &Protocol::RegisterProtocol) + .SetMethod("registerFileProtocol", + &Protocol::RegisterProtocol) + .SetMethod("registerHttpProtocol", + &Protocol::RegisterProtocol) + .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol) + .SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled) + .SetMethod("interceptStringProtocol", + &Protocol::InterceptProtocol) + .SetMethod("interceptBufferProtocol", + &Protocol::InterceptProtocol) + .SetMethod("interceptFileProtocol", + &Protocol::InterceptProtocol) + .SetMethod("interceptHttpProtocol", + &Protocol::InterceptProtocol) + .SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol); +} + void Protocol::RegisterStandardSchemes( const std::vector& schemes) { atom::AtomBrowserClient::SetCustomSchemes(schemes); @@ -126,34 +153,21 @@ mate::Handle Protocol::Create( return mate::CreateHandle(isolate, new Protocol(browser_context)); } -// static -void Protocol::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) - .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes) - .SetMethod("registerServiceWorkerSchemes", - &Protocol::RegisterServiceWorkerSchemes) - .SetMethod("registerStringProtocol", - &Protocol::RegisterProtocol) - .SetMethod("registerBufferProtocol", - &Protocol::RegisterProtocol) - .SetMethod("registerFileProtocol", - &Protocol::RegisterProtocol) - .SetMethod("registerHttpProtocol", - &Protocol::RegisterProtocol) - .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol) - .SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled) - .SetMethod("interceptStringProtocol", - &Protocol::InterceptProtocol) - .SetMethod("interceptBufferProtocol", - &Protocol::InterceptProtocol) - .SetMethod("interceptFileProtocol", - &Protocol::InterceptProtocol) - .SetMethod("interceptHttpProtocol", - &Protocol::InterceptProtocol) - .SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol); -} - } // namespace api } // namespace atom + +namespace { + +void Initialize(v8::Local exports, v8::Local unused, + v8::Local context, void* priv) { + v8::Isolate* isolate = context->GetIsolate(); + mate::Dictionary dict(isolate, exports); + auto browser_context = static_cast( + atom::AtomBrowserMainParts::Get()->browser_context()); + dict.Set("protocol", atom::api::Protocol::Create(isolate, browser_context)); +} + +} // namespace + +NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_protocol, Initialize) diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index 36ab46ba823..8aef406fbc3 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -9,7 +9,6 @@ #include #include -#include "atom/browser/api/trackable_object.h" #include "atom/browser/net/atom_url_request_job_factory.h" #include "base/callback.h" #include "base/containers/scoped_ptr_hash_map.h" @@ -31,7 +30,7 @@ class AtomURLRequestJobFactory; namespace api { -class Protocol : public mate::TrackableObject { +class Protocol : public mate::Wrappable { public: using Handler = base::Callback)>; @@ -41,13 +40,13 @@ class Protocol : public mate::TrackableObject { static mate::Handle Create( v8::Isolate* isolate, AtomBrowserContext* browser_context); - // mate::TrackableObject: - static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); - protected: explicit Protocol(AtomBrowserContext* browser_context); + // mate::Wrappable implementations: + virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate); + private: // Possible errors. enum ProtocolError { diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 51f7c1bb811..e5c5198f034 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -9,7 +9,6 @@ #include "atom/browser/api/atom_api_cookies.h" #include "atom/browser/api/atom_api_download_item.h" -#include "atom/browser/api/atom_api_protocol.h" #include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/api/atom_api_web_request.h" #include "atom/browser/api/save_page_handler.h" @@ -444,14 +443,6 @@ v8::Local Session::Cookies(v8::Isolate* isolate) { return v8::Local::New(isolate, cookies_); } -v8::Local Session::Protocol(v8::Isolate* isolate) { - if (protocol_.IsEmpty()) { - auto handle = atom::api::Protocol::Create(isolate, browser_context()); - protocol_.Reset(isolate, handle.ToV8()); - } - return v8::Local::New(isolate, protocol_); -} - v8::Local Session::WebRequest(v8::Isolate* isolate) { if (web_request_.IsEmpty()) { auto handle = atom::api::WebRequest::Create(isolate, browser_context()); @@ -499,7 +490,6 @@ void Session::BuildPrototype(v8::Isolate* isolate, &Session::SetPermissionRequestHandler) .SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache) .SetProperty("cookies", &Session::Cookies) - .SetProperty("protocol", &Session::Protocol) .SetProperty("webRequest", &Session::WebRequest); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 63c4cfc612b..02d8ba5cdec 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -80,12 +80,10 @@ class Session: public mate::TrackableObject, mate::Arguments* args); void ClearHostResolverCache(mate::Arguments* args); v8::Local Cookies(v8::Isolate* isolate); - v8::Local Protocol(v8::Isolate* isolate); v8::Local WebRequest(v8::Isolate* isolate); // Cached object. v8::Global cookies_; - v8::Global protocol_; v8::Global web_request_; scoped_refptr browser_context_; diff --git a/atom/browser/api/lib/protocol.js b/atom/browser/api/lib/protocol.js index caef0ad646b..41cb48db09b 100644 --- a/atom/browser/api/lib/protocol.js +++ b/atom/browser/api/lib/protocol.js @@ -4,10 +4,7 @@ if (!app.isReady()) { throw new Error('Can not initialize protocol module before app is ready'); } -const session = require('electron').session; - -// Returns the protocol property for default session. -const protocol = session.defaultSession.protocol; +const protocol = process.atomBinding('protocol').protocol; // Warn about removed APIs. var logAndThrow = function(callback, message) { @@ -19,10 +16,6 @@ var logAndThrow = function(callback, message) { } }; -protocol.fromPartition = function(partition) { - return session.fromPartition(partition).protocol; -}; - protocol.registerProtocol = function(scheme, handler, callback) { return logAndThrow(callback, 'registerProtocol API has been replaced by the register[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.'); }; diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index 4af3ba5b64b..69e7906ffbb 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -41,6 +41,7 @@ REFERENCE_MODULE(atom_browser_download_item); REFERENCE_MODULE(atom_browser_menu); REFERENCE_MODULE(atom_browser_power_monitor); REFERENCE_MODULE(atom_browser_power_save_blocker); +REFERENCE_MODULE(atom_browser_protocol); REFERENCE_MODULE(atom_browser_global_shortcut); REFERENCE_MODULE(atom_browser_session); REFERENCE_MODULE(atom_browser_tray); diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index 483155b7065..215868bfdc8 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -3,7 +3,6 @@ const http = require('http'); const path = require('path'); const qs = require('querystring'); const remote = require('electron').remote; -const BrowserWindow = remote.require('electron').BrowserWindow; const protocol = remote.require('electron').protocol; describe('protocol module', function() { @@ -815,54 +814,4 @@ describe('protocol module', function() { }); }); }); - - describe('protocol.fromPartition', function() { - var partitionName = 'temp'; - var tempProtocol = protocol.fromPartition(partitionName); - var w = null; - - beforeEach(function() { - if (w != null) { - w.destroy(); - } - w = new BrowserWindow({ - show: false, - width: 400, - height: 400, - webPreferences: { - partition: partitionName - } - }); - }); - - afterEach(function() { - if (w != null) { - w.destroy(); - } - w = null; - }); - - it('handles requests from a partition', function(done) { - var handler = function(error, callback) { - callback({ - data: text - }); - }; - tempProtocol.registerStringProtocol(protocolName, handler, function(error) { - if (error) { - return done(error); - } - protocol.isProtocolHandled(protocolName, function(result) { - assert.equal(result, false); - }); - tempProtocol.isProtocolHandled(protocolName, function(result) { - assert.equal(result, true); - }); - }); - w.webContents.on('did-finish-load', function() { - done(); - }); - w.loadURL(protocolName + "://fake-host"); - }); - }); }); From 6fcc197db8e98acd1d17c406504e30a5a5f5335b Mon Sep 17 00:00:00 2001 From: Robo Date: Wed, 17 Feb 2016 14:22:19 +0530 Subject: [PATCH 157/173] webview: api to get webcontents and associated host webcontents --- atom/browser/api/atom_api_web_contents.cc | 16 ++++++++++++---- atom/browser/api/atom_api_web_contents.h | 4 ++++ .../native_mate_converters/content_converter.cc | 2 ++ atom/renderer/lib/web-view/web-view.js | 8 +++++++- docs/api/web-contents.md | 4 ++++ docs/api/web-view-tag.md | 4 ++++ spec/webview-spec.js | 13 +++++++++++++ 7 files changed, 46 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index ee6ad94ba77..4935adbc75a 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -218,7 +218,8 @@ WebContents::WebContents(content::WebContents* web_contents) WebContents::WebContents(v8::Isolate* isolate, const mate::Dictionary& options) - : request_id_(0) { + : embedder_(nullptr), + request_id_(0) { // Whether it is a guest WebContents. bool is_guest = false; options.Get("isGuest", &is_guest); @@ -273,10 +274,10 @@ WebContents::WebContents(v8::Isolate* isolate, guest_delegate_->Initialize(this); NativeWindow* owner_window = nullptr; - WebContents* embedder = nullptr; - if (options.Get("embedder", &embedder) && embedder) { + if (options.Get("embedder", &embedder_) && embedder_) { // New WebContents's owner_window is the embedder's owner_window. - auto relay = NativeWindowRelay::FromWebContents(embedder->web_contents()); + auto relay = + NativeWindowRelay::FromWebContents(embedder_->web_contents()); if (relay) owner_window = relay->window.get(); } @@ -1116,6 +1117,12 @@ v8::Local WebContents::Session(v8::Isolate* isolate) { return v8::Local::New(isolate, session_); } +content::WebContents* WebContents::HostWebContents() { + if (!embedder_) + return nullptr; + return embedder_->web_contents(); +} + v8::Local WebContents::DevToolsWebContents(v8::Isolate* isolate) { if (devtools_web_contents_.IsEmpty()) return v8::Null(isolate); @@ -1199,6 +1206,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate, .SetMethod("addWorkSpace", &WebContents::AddWorkSpace) .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace) .SetProperty("session", &WebContents::Session) + .SetProperty("hostWebContents", &WebContents::HostWebContents) .SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents) .SetProperty("debugger", &WebContents::Debugger); } diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 63c4a017771..b4f29090dbd 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -147,6 +147,7 @@ class WebContents : public mate::TrackableObject, // Properties. v8::Local Session(v8::Isolate* isolate); + content::WebContents* HostWebContents(); v8::Local DevToolsWebContents(v8::Isolate* isolate); v8::Local Debugger(v8::Isolate* isolate); @@ -287,6 +288,9 @@ class WebContents : public mate::TrackableObject, scoped_ptr guest_delegate_; + // The host webcontents that may contain this webcontents. + WebContents* embedder_; + // The type of current WebContents. Type type_; diff --git a/atom/common/native_mate_converters/content_converter.cc b/atom/common/native_mate_converters/content_converter.cc index 699f101d0e4..f5d81d085bc 100644 --- a/atom/common/native_mate_converters/content_converter.cc +++ b/atom/common/native_mate_converters/content_converter.cc @@ -173,6 +173,8 @@ bool Converter::FromV8( // static v8::Local Converter::ToV8( v8::Isolate* isolate, content::WebContents* val) { + if (!val) + return v8::Null(isolate); return atom::api::WebContents::CreateFrom(isolate, val).ToV8(); } diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 7e38bb33715..44fc1042162 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -388,7 +388,7 @@ var registerWebViewElement = function() { 'downloadURL', 'inspectServiceWorker', 'print', - 'printToPDF' + 'printToPDF', ]; nonblockMethods = [ 'executeJavaScript', @@ -430,6 +430,12 @@ var registerWebViewElement = function() { proto[m] = createNonBlockHandler(m); } + // WebContents associated with this webview. + proto.getWebContents = function() { + var internal = v8Util.getHiddenValue(this, 'internal'); + return internal.webContents; + }; + // Deprecated. deprecate.rename(proto, 'getUrl', 'getURL'); window.WebView = webFrame.registerEmbedderCustomElement('webview', { diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index e0139a29fa6..dde701d7f48 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -842,6 +842,10 @@ win.webContents.on('did-finish-load', function() { Returns the [session](session.md) object used by this webContents. +### `webContents.hostWebContents` + +Returns the `WebContents` that might own this `WebContents`. + ### `webContents.devToolsWebContents` Get the `WebContents` of DevTools for this `WebContents`. diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index b4f139d475c..4a0697ad843 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -438,6 +438,10 @@ Sends an input `event` to the page. See [webContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent) for detailed description of `event` object. +### `.getWebContents()` + +Returns the [WebContents](web-contents.md) associated with this `webview`. + ## DOM events The following DOM events are available to the `webview` tag: diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 54b544def0d..d73a177d097 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -703,4 +703,17 @@ describe(' tag', function() { document.body.appendChild(webview); }); }); + + describe('.getWebContents', function() { + it('can return the webcontents associated', function(done) { + webview.addEventListener('did-finish-load', function() { + const webviewContents = webview.getWebContents(); + assert(webviewContents); + assert.equal(webviewContents.getURL(), 'about:blank'); + done(); + }); + webview.src = "about:blank"; + document.body.appendChild(webview); + }); + }); }); From 467870deb64f307be89578205a1e5cab7cc9ad6e Mon Sep 17 00:00:00 2001 From: Robo Date: Wed, 24 Feb 2016 16:25:41 +0530 Subject: [PATCH 158/173] use builtin method --- .../v8_value_converter.cc | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/atom/common/native_mate_converters/v8_value_converter.cc b/atom/common/native_mate_converters/v8_value_converter.cc index f5d7217ae52..6a858f2749c 100644 --- a/atom/common/native_mate_converters/v8_value_converter.cc +++ b/atom/common/native_mate_converters/v8_value_converter.cc @@ -4,7 +4,6 @@ #include "atom/common/native_mate_converters/v8_value_converter.h" -#include #include #include #include @@ -21,14 +20,6 @@ namespace { const int kMaxRecursionDepth = 100; -const double kMsPerDay = 24 * 60 * 60 * 1000; - -int TimeInDay(double time_ms) { - if (time_ms < 0) time_ms -= (kMsPerDay -1); - int days = static_cast(time_ms / kMsPerDay); - return static_cast(time_ms - days * kMsPerDay); -} - } // namespace // The state of a call to FromV8Value. @@ -248,20 +239,17 @@ base::Value* V8ValueConverter::FromV8ValueImpl( if (val->IsDate()) { v8::Date* date = v8::Date::Cast(*val); - double const time_ms = date->NumberValue(); - int const time_in_day_ms = TimeInDay(time_ms); - std::time_t time_s(time_ms / 1000.0); - char buf[128]; - std::tm* gm_time = std::gmtime(&time_s); - int year = gm_time->tm_year + 1900; - int month = gm_time->tm_mon + 1; - int ms = time_in_day_ms % 1000; - size_t length = snprintf(buf, sizeof buf, - "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", - year, month, gm_time->tm_mday, - gm_time->tm_hour, gm_time->tm_min, - gm_time->tm_sec, ms); - return new base::StringValue(std::string(buf, length)); + v8::Local toISOString = + date->GetRealNamedPropertyInPrototypeChain( + v8::String::NewFromUtf8(isolate, "toISOString")); + if (toISOString->IsFunction()) { + v8::Local result = + toISOString.As()->Call(val, 0, nullptr); + if (!result.IsEmpty()) { + v8::String::Utf8Value utf8(result->ToString()); + return new base::StringValue(std::string(*utf8, utf8.length())); + } + } } if (val->IsRegExp()) { From d2b48b2aa7ff7ed3bb257f96ef0ed6d46c4c28b9 Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Wed, 24 Feb 2016 14:01:26 +0100 Subject: [PATCH 159/173] Fix crash in mate::Converter::ToV8 The net::URLRequest::url() method calls vector::back(), which is undefined when the url_chain is empty --- atom/common/native_mate_converters/net_converter.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atom/common/native_mate_converters/net_converter.cc b/atom/common/native_mate_converters/net_converter.cc index 94081b88a3d..184f1c3fecf 100644 --- a/atom/common/native_mate_converters/net_converter.cc +++ b/atom/common/native_mate_converters/net_converter.cc @@ -27,7 +27,9 @@ v8::Local Converter::ToV8( v8::Isolate* isolate, const net::URLRequest* val) { scoped_ptr dict(new base::DictionaryValue); dict->SetString("method", val->method()); - dict->SetStringWithoutPathExpansion("url", val->url().spec()); + std::string url; + if (!val->url_chain().empty()) url = val->url().spec(); + dict->SetStringWithoutPathExpansion("url", url); dict->SetString("referrer", val->referrer()); scoped_ptr list(new base::ListValue); atom::GetUploadData(list.get(), val); From fee56df40074b6730e71591db964477c8fce8b91 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Wed, 24 Feb 2016 11:15:21 -0800 Subject: [PATCH 160/173] Rename function `FilterAccecelator` to `FilterAccelerator` in `submenu_button.cc`. --- atom/browser/ui/views/submenu_button.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/ui/views/submenu_button.cc b/atom/browser/ui/views/submenu_button.cc index bedbb98832d..7f413d519c2 100644 --- a/atom/browser/ui/views/submenu_button.cc +++ b/atom/browser/ui/views/submenu_button.cc @@ -15,7 +15,7 @@ namespace atom { namespace { // Filter out the "&" in menu label. -base::string16 FilterAccecelator(const base::string16& label) { +base::string16 FilterAccelerator(const base::string16& label) { base::string16 out; base::RemoveChars(label, base::ASCIIToUTF16("&").c_str(), &out); return out; @@ -26,7 +26,7 @@ base::string16 FilterAccecelator(const base::string16& label) { SubmenuButton::SubmenuButton(views::ButtonListener* listener, const base::string16& title, views::MenuButtonListener* menu_button_listener) - : views::MenuButton(listener, FilterAccecelator(title), + : views::MenuButton(listener, FilterAccelerator(title), menu_button_listener, false), accelerator_(0), show_underline_(false), From a1a17b7ee8d0c1313ef9ac37c33ae979c26b62fd Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 25 Feb 2016 11:21:21 +0530 Subject: [PATCH 161/173] use v8::Object::Get --- atom/common/native_mate_converters/v8_value_converter.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/atom/common/native_mate_converters/v8_value_converter.cc b/atom/common/native_mate_converters/v8_value_converter.cc index 6a858f2749c..1a729dda535 100644 --- a/atom/common/native_mate_converters/v8_value_converter.cc +++ b/atom/common/native_mate_converters/v8_value_converter.cc @@ -240,8 +240,7 @@ base::Value* V8ValueConverter::FromV8ValueImpl( if (val->IsDate()) { v8::Date* date = v8::Date::Cast(*val); v8::Local toISOString = - date->GetRealNamedPropertyInPrototypeChain( - v8::String::NewFromUtf8(isolate, "toISOString")); + date->Get(v8::String::NewFromUtf8(isolate, "toISOString")); if (toISOString->IsFunction()) { v8::Local result = toISOString.As()->Call(val, 0, nullptr); From 2b547bd44a8eca9bd2d0c7872f0a49906d808af7 Mon Sep 17 00:00:00 2001 From: Robo Date: Wed, 17 Feb 2016 22:33:27 +0530 Subject: [PATCH 162/173] webContents: provide responses for executeJavscript method --- atom/browser/api/lib/ipc-main.js | 4 ++ atom/browser/api/lib/web-contents.js | 14 ++++++- .../native_mate_converters/blink_converter.h | 14 +++++++ atom/renderer/api/atom_api_web_frame.cc | 41 +++++++++++++++++-- atom/renderer/lib/init.js | 10 +++++ atom/renderer/lib/web-view/web-view.js | 17 +++++--- docs/api/web-contents.md | 4 +- docs/api/web-view-tag.md | 4 +- spec/webview-spec.js | 18 +++++++- 9 files changed, 113 insertions(+), 13 deletions(-) diff --git a/atom/browser/api/lib/ipc-main.js b/atom/browser/api/lib/ipc-main.js index e253e03eaab..d6a043a92bf 100644 --- a/atom/browser/api/lib/ipc-main.js +++ b/atom/browser/api/lib/ipc-main.js @@ -1,3 +1,7 @@ const EventEmitter = require('events').EventEmitter; module.exports = new EventEmitter; + +// Every webContents would add a listenter to the +// WEB_FRAME_RESPONSE event, so ignore the listenters warning. +module.exports.setMaxListeners(0); diff --git a/atom/browser/api/lib/web-contents.js b/atom/browser/api/lib/web-contents.js index e0c16999c72..c2376af53a2 100644 --- a/atom/browser/api/lib/web-contents.js +++ b/atom/browser/api/lib/web-contents.js @@ -11,6 +11,7 @@ const debuggerBinding = process.atomBinding('debugger'); let slice = [].slice; let nextId = 0; +let responseCallback = {}; let getNextId = function() { return ++nextId; @@ -109,13 +110,24 @@ let wrapWebContents = function(webContents) { // Make sure webContents.executeJavaScript would run the code only when the // webContents has been loaded. const executeJavaScript = webContents.executeJavaScript; - webContents.executeJavaScript = function(code, hasUserGesture) { + webContents.executeJavaScript = function(code, hasUserGesture, callback) { + if (typeof hasUserGesture === "function") { + callback = hasUserGesture; + hasUserGesture = false; + } + if (callback !== null) + responseCallback["executeJavaScript"] = callback; if (this.getURL() && !this.isLoading()) return executeJavaScript.call(this, code, hasUserGesture); else return this.once('did-finish-load', executeJavaScript.bind(this, code, hasUserGesture)); }; + ipcMain.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_RESPONSE', function(event, method, result) { + if (responseCallback[method]) + responseCallback[method].apply(null, [result]); + }); + // Dispatch IPC messages to the ipc module. webContents.on('ipc-message', function(event, packed) { var args, channel; diff --git a/atom/common/native_mate_converters/blink_converter.h b/atom/common/native_mate_converters/blink_converter.h index 6a360192921..f066ea29ccd 100644 --- a/atom/common/native_mate_converters/blink_converter.h +++ b/atom/common/native_mate_converters/blink_converter.h @@ -6,6 +6,7 @@ #define ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_ #include "native_mate/converter.h" +#include "third_party/WebKit/public/platform/WebVector.h" namespace blink { class WebInputEvent; @@ -87,6 +88,19 @@ struct Converter { blink::WebFindOptions* out); }; +template +struct Converter > { + static v8::Local ToV8(v8::Isolate* isolate, + const blink::WebVector& val) { + v8::Local result( + MATE_ARRAY_NEW(isolate, static_cast(val.size()))); + for (size_t i = 0; i < val.size(); ++i) { + result->Set(static_cast(i), Converter::ToV8(isolate, val[i])); + } + return result; + } +}; + } // namespace mate #endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_ diff --git a/atom/renderer/api/atom_api_web_frame.cc b/atom/renderer/api/atom_api_web_frame.cc index c72882886b9..06c9621b820 100644 --- a/atom/renderer/api/atom_api_web_frame.cc +++ b/atom/renderer/api/atom_api_web_frame.cc @@ -8,6 +8,7 @@ #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/gfx_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" +#include "atom/common/native_mate_converters/blink_converter.h" #include "atom/renderer/api/atom_api_spell_check_client.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" @@ -15,7 +16,7 @@ #include "native_mate/object_template_builder.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebScopedUserGesture.h" +#include "third_party/WebKit/public/web/WebScriptExecutionCallback.h" #include "third_party/WebKit/public/web/WebScriptSource.h" #include "third_party/WebKit/public/web/WebSecurityPolicy.h" #include "third_party/WebKit/public/web/WebView.h" @@ -26,6 +27,33 @@ namespace atom { namespace api { +namespace { + +class ScriptExecutionCallback : public blink::WebScriptExecutionCallback { + public: + using CompletionCallback = + base::Callback>& result)>; + + explicit ScriptExecutionCallback(const CompletionCallback& callback) + : callback_(callback) {} + ~ScriptExecutionCallback() {} + + void completed( + const blink::WebVector>& result) override { + if (!callback_.is_null()) + callback_.Run(result); + delete this; + } + + private: + CompletionCallback callback_; + + DISALLOW_COPY_AND_ASSIGN(ScriptExecutionCallback); +}; + +} // namespace + WebFrame::WebFrame() : web_frame_(blink::WebLocalFrame::frameForCurrentContext()) { } @@ -124,9 +152,14 @@ void WebFrame::ExecuteJavaScript(const base::string16& code, mate::Arguments* args) { bool has_user_gesture = false; args->GetNext(&has_user_gesture); - scoped_ptr gesture( - has_user_gesture ? new blink::WebScopedUserGesture : nullptr); - web_frame_->executeScriptAndReturnValue(blink::WebScriptSource(code)); + ScriptExecutionCallback::CompletionCallback completion_callback; + args->GetNext(&completion_callback); + scoped_ptr callback( + new ScriptExecutionCallback(completion_callback)); + web_frame_->requestExecuteScriptAndReturnValue( + blink::WebScriptSource(code), + has_user_gesture, + callback.release()); } mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder( diff --git a/atom/renderer/lib/init.js b/atom/renderer/lib/init.js index 340a1ef5053..ab03a9055ce 100644 --- a/atom/renderer/lib/init.js +++ b/atom/renderer/lib/init.js @@ -32,7 +32,17 @@ v8Util.setHiddenValue(global, 'ipc', new events.EventEmitter); const electron = require('electron'); // Call webFrame method. +const asyncWebFrameMethods = [ + 'executeJavaScript' +]; + electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', (event, method, args) => { + if (asyncWebFrameMethods.includes(method)) { + const responseCallback = function(result) { + event.sender.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_RESPONSE', method, result); + }; + args.push(responseCallback); + } electron.webFrame[method].apply(electron.webFrame, args); }); diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 44fc1042162..892ecf56192 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -307,7 +307,7 @@ var registerBrowserPluginElement = function() { // Registers custom element. var registerWebViewElement = function() { - var createBlockHandler, createNonBlockHandler, i, j, len, len1, m, methods, nonblockMethods, proto; + var createBlockHandler, createNonBlockHandler, i, j, len, len1, m, methods, nonblockMethods, webFrameMethods, proto; proto = Object.create(HTMLObjectElement.prototype); proto.createdCallback = function() { return new WebViewImpl(this); @@ -391,14 +391,16 @@ var registerWebViewElement = function() { 'printToPDF', ]; nonblockMethods = [ - 'executeJavaScript', 'insertCSS', - 'insertText', 'send', - 'sendInputEvent', + 'sendInputEvent' + ]; + webFrameMethods = [ + 'executeJavaScript', + 'insertText', 'setZoomFactor', 'setZoomLevel', - 'setZoomLevelLimits', + 'setZoomLevelLimits' ]; // Forward proto.foo* method calls to WebViewImpl.foo*. @@ -430,6 +432,11 @@ var registerWebViewElement = function() { proto[m] = createNonBlockHandler(m); } + // Forward proto.foo* webframe method calls to WebFrame.foo*. + for (let method of webFrameMethods) { + proto[method] = webFrame[method].bind(webFrame); + } + // WebContents associated with this webview. proto.getWebContents = function() { var internal = v8Util.getHiddenValue(this, 'internal'); diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index dde701d7f48..376860b17f9 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -425,10 +425,12 @@ Returns a `String` representing the user agent for this web page. Injects CSS into the current web page. -### `webContents.executeJavaScript(code[, userGesture])` +### `webContents.executeJavaScript(code[, userGesture, callback])` * `code` String * `userGesture` Boolean (optional) +* `callback` Function (optional) - Called after script has been executed. + * `result` Array Evaluates `code` in page. diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 4a0697ad843..3bc4f0e9f64 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -279,10 +279,12 @@ Returns a `String` representing the user agent for guest page. Injects CSS into the guest page. -### `.executeJavaScript(code, userGesture)` +### `.executeJavaScript(code, userGesture, callback)` * `code` String * `userGesture` Boolean - Default `false`. +* `callback` Function (optional) - Called after script has been executed. + * `result` Array Evaluates `code` in page. If `userGesture` is set, it will create the user gesture context in the page. HTML APIs like `requestFullScreen`, which require diff --git a/spec/webview-spec.js b/spec/webview-spec.js index d73a177d097..fef49de454f 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -194,6 +194,7 @@ describe(' tag', function() { document.body.appendChild(webview); }); }); + describe('partition attribute', function() { it('inserts no node symbols when not set', function(done) { webview.addEventListener('console-message', function(e) { @@ -356,6 +357,7 @@ describe(' tag', function() { document.body.appendChild(webview); }); }); + describe('did-navigate-in-page event', function() { it('emits when an anchor link is clicked', function(done) { var p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page.html'); @@ -556,7 +558,7 @@ describe(' tag', function() { done(); }; var listener2 = function() { - var jsScript = 'document.getElementsByTagName("video")[0].webkitRequestFullScreen()'; + var jsScript = "document.querySelector('video').webkitRequestFullscreen()"; webview.executeJavaScript(jsScript, true); webview.removeEventListener('did-finish-load', listener2); }; @@ -565,6 +567,20 @@ describe(' tag', function() { webview.src = "file://" + fixtures + "/pages/fullscreen.html"; document.body.appendChild(webview); }); + + it('can return the result of the executed script', function(done) { + var listener = function() { + var jsScript = "'4'+2"; + webview.executeJavaScript(jsScript, false, function(result) { + assert.equal(result[0], '42'); + done(); + }); + webview.removeEventListener('did-finish-load', listener); + }; + webview.addEventListener('did-finish-load', listener); + webview.src = "about:blank"; + document.body.appendChild(webview); + }); }); describe('sendInputEvent', function() { From a734326907d4a23c328cf602dabe62d677ec695b Mon Sep 17 00:00:00 2001 From: Robo Date: Mon, 22 Feb 2016 19:30:21 +0530 Subject: [PATCH 163/173] track async api requests --- atom/browser/api/lib/web-contents.js | 29 ++++++++++++++----- .../native_mate_converters/blink_converter.h | 14 --------- atom/renderer/api/atom_api_web_frame.cc | 6 ++-- atom/renderer/lib/init.js | 19 ++++++------ atom/renderer/lib/web-view/web-view.js | 4 +-- docs/api/web-contents.md | 2 +- docs/api/web-view-tag.md | 2 +- spec/webview-spec.js | 2 +- 8 files changed, 39 insertions(+), 39 deletions(-) diff --git a/atom/browser/api/lib/web-contents.js b/atom/browser/api/lib/web-contents.js index c2376af53a2..ed8afef7a52 100644 --- a/atom/browser/api/lib/web-contents.js +++ b/atom/browser/api/lib/web-contents.js @@ -11,6 +11,8 @@ const debuggerBinding = process.atomBinding('debugger'); let slice = [].slice; let nextId = 0; + +// Map of requestId and response callback. let responseCallback = {}; let getNextId = function() { @@ -59,13 +61,16 @@ let PDFPageSize = { // Following methods are mapped to webFrame. const webFrameMethods = [ - 'executeJavaScript', 'insertText', 'setZoomFactor', 'setZoomLevel', 'setZoomLevelLimits' ]; +const asyncWebFrameMethods = [ + 'executeJavaScript', +]; + let wrapWebContents = function(webContents) { // webContents is an EventEmitter. var controller, method, name, ref1; @@ -107,25 +112,35 @@ let wrapWebContents = function(webContents) { }; } + for (let method of asyncWebFrameMethods) { + webContents[method] = function() { + let args = Array.prototype.slice.call(arguments); + this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', method, args); + }; + } + // Make sure webContents.executeJavaScript would run the code only when the // webContents has been loaded. const executeJavaScript = webContents.executeJavaScript; webContents.executeJavaScript = function(code, hasUserGesture, callback) { + let requestId = getNextId(); if (typeof hasUserGesture === "function") { callback = hasUserGesture; hasUserGesture = false; } if (callback !== null) - responseCallback["executeJavaScript"] = callback; + responseCallback[requestId] = callback; if (this.getURL() && !this.isLoading()) - return executeJavaScript.call(this, code, hasUserGesture); + return executeJavaScript.call(this, requestId, code, hasUserGesture); else - return this.once('did-finish-load', executeJavaScript.bind(this, code, hasUserGesture)); + return this.once('did-finish-load', executeJavaScript.bind(this, requestId, code, hasUserGesture)); }; - ipcMain.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_RESPONSE', function(event, method, result) { - if (responseCallback[method]) - responseCallback[method].apply(null, [result]); + ipcMain.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_RESPONSE', function(event, id, result) { + if (responseCallback[id]) { + responseCallback[id].apply(null, [result]); + delete responseCallback[id]; + } }); // Dispatch IPC messages to the ipc module. diff --git a/atom/common/native_mate_converters/blink_converter.h b/atom/common/native_mate_converters/blink_converter.h index f066ea29ccd..6a360192921 100644 --- a/atom/common/native_mate_converters/blink_converter.h +++ b/atom/common/native_mate_converters/blink_converter.h @@ -6,7 +6,6 @@ #define ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_ #include "native_mate/converter.h" -#include "third_party/WebKit/public/platform/WebVector.h" namespace blink { class WebInputEvent; @@ -88,19 +87,6 @@ struct Converter { blink::WebFindOptions* out); }; -template -struct Converter > { - static v8::Local ToV8(v8::Isolate* isolate, - const blink::WebVector& val) { - v8::Local result( - MATE_ARRAY_NEW(isolate, static_cast(val.size()))); - for (size_t i = 0; i < val.size(); ++i) { - result->Set(static_cast(i), Converter::ToV8(isolate, val[i])); - } - return result; - } -}; - } // namespace mate #endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_ diff --git a/atom/renderer/api/atom_api_web_frame.cc b/atom/renderer/api/atom_api_web_frame.cc index 06c9621b820..af9a3c41621 100644 --- a/atom/renderer/api/atom_api_web_frame.cc +++ b/atom/renderer/api/atom_api_web_frame.cc @@ -8,7 +8,6 @@ #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/gfx_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" -#include "atom/common/native_mate_converters/blink_converter.h" #include "atom/renderer/api/atom_api_spell_check_client.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" @@ -33,7 +32,7 @@ class ScriptExecutionCallback : public blink::WebScriptExecutionCallback { public: using CompletionCallback = base::Callback>& result)>; + const v8::Local& result)>; explicit ScriptExecutionCallback(const CompletionCallback& callback) : callback_(callback) {} @@ -42,7 +41,8 @@ class ScriptExecutionCallback : public blink::WebScriptExecutionCallback { void completed( const blink::WebVector>& result) override { if (!callback_.is_null()) - callback_.Run(result); + // Right now only single results per frame is supported. + callback_.Run(result[0]); delete this; } diff --git a/atom/renderer/lib/init.js b/atom/renderer/lib/init.js index ab03a9055ce..f7f78e84a1b 100644 --- a/atom/renderer/lib/init.js +++ b/atom/renderer/lib/init.js @@ -32,17 +32,16 @@ v8Util.setHiddenValue(global, 'ipc', new events.EventEmitter); const electron = require('electron'); // Call webFrame method. -const asyncWebFrameMethods = [ - 'executeJavaScript' -]; - electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', (event, method, args) => { - if (asyncWebFrameMethods.includes(method)) { - const responseCallback = function(result) { - event.sender.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_RESPONSE', method, result); - }; - args.push(responseCallback); - } + electron.webFrame[method].apply(electron.webFrame, args); +}); + +electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (event, method, args) => { + let requestId = args.shift(); + const responseCallback = function(result) { + event.sender.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_RESPONSE', requestId, result); + }; + args.push(responseCallback); electron.webFrame[method].apply(electron.webFrame, args); }); diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 892ecf56192..25e5eead2dd 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -393,14 +393,14 @@ var registerWebViewElement = function() { nonblockMethods = [ 'insertCSS', 'send', - 'sendInputEvent' + 'sendInputEvent', ]; webFrameMethods = [ 'executeJavaScript', 'insertText', 'setZoomFactor', 'setZoomLevel', - 'setZoomLevelLimits' + 'setZoomLevelLimits', ]; // Forward proto.foo* method calls to WebViewImpl.foo*. diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 376860b17f9..e095213bd97 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -430,7 +430,7 @@ Injects CSS into the current web page. * `code` String * `userGesture` Boolean (optional) * `callback` Function (optional) - Called after script has been executed. - * `result` Array + * `result` Evaluates `code` in page. diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 3bc4f0e9f64..fa48ef60f3f 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -284,7 +284,7 @@ Injects CSS into the guest page. * `code` String * `userGesture` Boolean - Default `false`. * `callback` Function (optional) - Called after script has been executed. - * `result` Array + * `result` Evaluates `code` in page. If `userGesture` is set, it will create the user gesture context in the page. HTML APIs like `requestFullScreen`, which require diff --git a/spec/webview-spec.js b/spec/webview-spec.js index fef49de454f..cd2be69d737 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -572,7 +572,7 @@ describe(' tag', function() { var listener = function() { var jsScript = "'4'+2"; webview.executeJavaScript(jsScript, false, function(result) { - assert.equal(result[0], '42'); + assert.equal(result, '42'); done(); }); webview.removeEventListener('did-finish-load', listener); From 8386baf267545157584588f244bdfa8a75652555 Mon Sep 17 00:00:00 2001 From: Robo Date: Wed, 24 Feb 2016 15:41:09 +0530 Subject: [PATCH 164/173] add spec --- atom/browser/api/lib/ipc-main.js | 4 ---- atom/browser/api/lib/web-contents.js | 33 ++++++++++------------------ atom/renderer/lib/init.js | 5 ++--- spec/api-browser-window-spec.js | 19 ++++++++++++++++ spec/static/main.js | 11 ++++++++++ 5 files changed, 44 insertions(+), 28 deletions(-) diff --git a/atom/browser/api/lib/ipc-main.js b/atom/browser/api/lib/ipc-main.js index d6a043a92bf..e253e03eaab 100644 --- a/atom/browser/api/lib/ipc-main.js +++ b/atom/browser/api/lib/ipc-main.js @@ -1,7 +1,3 @@ const EventEmitter = require('events').EventEmitter; module.exports = new EventEmitter; - -// Every webContents would add a listenter to the -// WEB_FRAME_RESPONSE event, so ignore the listenters warning. -module.exports.setMaxListeners(0); diff --git a/atom/browser/api/lib/web-contents.js b/atom/browser/api/lib/web-contents.js index ed8afef7a52..7cd54bfddfb 100644 --- a/atom/browser/api/lib/web-contents.js +++ b/atom/browser/api/lib/web-contents.js @@ -67,10 +67,6 @@ const webFrameMethods = [ 'setZoomLevelLimits' ]; -const asyncWebFrameMethods = [ - 'executeJavaScript', -]; - let wrapWebContents = function(webContents) { // webContents is an EventEmitter. var controller, method, name, ref1; @@ -112,37 +108,32 @@ let wrapWebContents = function(webContents) { }; } - for (let method of asyncWebFrameMethods) { - webContents[method] = function() { - let args = Array.prototype.slice.call(arguments); - this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', method, args); - }; - } + const asyncWebFrameMethods = function(requestId, method, ...args) { + this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args); + ipcMain.once('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_RESPONSE_' + requestId, function(event, result) { + if (responseCallback[requestId]) { + responseCallback[requestId](result); + delete responseCallback[requestId]; + } + }); + }; // Make sure webContents.executeJavaScript would run the code only when the // webContents has been loaded. - const executeJavaScript = webContents.executeJavaScript; webContents.executeJavaScript = function(code, hasUserGesture, callback) { let requestId = getNextId(); if (typeof hasUserGesture === "function") { callback = hasUserGesture; hasUserGesture = false; } - if (callback !== null) + if (callback != null) responseCallback[requestId] = callback; if (this.getURL() && !this.isLoading()) - return executeJavaScript.call(this, requestId, code, hasUserGesture); + return asyncWebFrameMethods.call(this, requestId, "executeJavaScript", code, hasUserGesture); else - return this.once('did-finish-load', executeJavaScript.bind(this, requestId, code, hasUserGesture)); + return this.once('did-finish-load', asyncWebFrameMethods.bind(this, requestId, "executeJavaScript", code, hasUserGesture)); }; - ipcMain.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_RESPONSE', function(event, id, result) { - if (responseCallback[id]) { - responseCallback[id].apply(null, [result]); - delete responseCallback[id]; - } - }); - // Dispatch IPC messages to the ipc module. webContents.on('ipc-message', function(event, packed) { var args, channel; diff --git a/atom/renderer/lib/init.js b/atom/renderer/lib/init.js index f7f78e84a1b..cf42aa27229 100644 --- a/atom/renderer/lib/init.js +++ b/atom/renderer/lib/init.js @@ -36,10 +36,9 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', (event, m electron.webFrame[method].apply(electron.webFrame, args); }); -electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (event, method, args) => { - let requestId = args.shift(); +electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (event, requestId, method, args) => { const responseCallback = function(result) { - event.sender.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_RESPONSE', requestId, result); + event.sender.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_RESPONSE_' + requestId, result); }; args.push(responseCallback); electron.webFrame[method].apply(electron.webFrame, args); diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 58cf57cc8d0..25e92382cca 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -10,6 +10,7 @@ const screen = require('electron').screen; const app = remote.require('electron').app; const ipcMain = remote.require('electron').ipcMain; +const ipcRenderer = require('electron').ipcRenderer; const BrowserWindow = remote.require('electron').BrowserWindow; const isCI = remote.getGlobal('isCi'); @@ -690,4 +691,22 @@ describe('browser-window module', function() { assert.equal(fs.existsSync(serializedPath), false); }); }); + + describe('window.webContents.executeJavaScript', function() { + var expected = 'hello, world!'; + var code = '(() => \"' + expected + '\")()'; + + it('doesnt throw when no calback is provided', function() { + const result = ipcRenderer.sendSync('executeJavaScript', code, false); + assert.equal(result, 'success'); + }); + + it('returns result when calback is provided', function(done) { + ipcRenderer.send('executeJavaScript', code, true); + ipcRenderer.once('executeJavaScript-response', function(event, result) { + assert.equal(result, expected); + done(); + }); + }); + }); }); diff --git a/spec/static/main.js b/spec/static/main.js index 48fdf17c3dc..9a049e3f107 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -138,4 +138,15 @@ app.on('ready', function() { }); event.returnValue = "done"; }); + + ipcMain.on('executeJavaScript', function(event, code, hasCallback) { + if (hasCallback) { + window.webContents.executeJavaScript(code, (result) => { + window.webContents.send('executeJavaScript-response', result); + }); + } else { + window.webContents.executeJavaScript(code); + event.returnValue = "success"; + } + }); }); From 6f45678e9c68874474de2d3727f16a96ac45a528 Mon Sep 17 00:00:00 2001 From: Robert Lyall Date: Thu, 25 Feb 2016 18:28:03 +0000 Subject: [PATCH 165/173] Fix Menu template API example --- docs-translations/jp/api/menu.md | 2 +- docs-translations/ko-KR/api/menu.md | 2 +- docs/api/menu.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs-translations/jp/api/menu.md b/docs-translations/jp/api/menu.md index e68a69cca83..12039b1d6ad 100644 --- a/docs-translations/jp/api/menu.md +++ b/docs-translations/jp/api/menu.md @@ -135,7 +135,7 @@ var template = [ ]; if (process.platform == 'darwin') { - var name = require('electron').app.getName(); + var name = require('electron').remote.app.getName(); template.unshift({ label: name, submenu: [ diff --git a/docs-translations/ko-KR/api/menu.md b/docs-translations/ko-KR/api/menu.md index 347ea880dce..61c68023b07 100644 --- a/docs-translations/ko-KR/api/menu.md +++ b/docs-translations/ko-KR/api/menu.md @@ -140,7 +140,7 @@ var template = [ ]; if (process.platform == 'darwin') { - var name = require('electron').app.getName(); + var name = require('electron').remote.app.getName(); template.unshift({ label: name, submenu: [ diff --git a/docs/api/menu.md b/docs/api/menu.md index 49a499a3d4b..7d05f88aa2b 100644 --- a/docs/api/menu.md +++ b/docs/api/menu.md @@ -143,7 +143,7 @@ var template = [ ]; if (process.platform == 'darwin') { - var name = require('electron').app.getName(); + var name = require('electron').remote.app.getName(); template.unshift({ label: name, submenu: [ From 9a0372b61be525c528919742384ecc56bf3428ec Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 25 Feb 2016 23:48:58 +0100 Subject: [PATCH 166/173] Removed size_ since it's not needed anymore --- atom/browser/api/frame_subscriber.cc | 6 +++--- atom/browser/api/frame_subscriber.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index ec3bcd05ab7..4653fc452ad 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -4,13 +4,14 @@ #include "atom/browser/api/frame_subscriber.h" -#include "atom/common/node_includes.h" #include "base/bind.h" +#include "atom/common/node_includes.h" #include "media/base/video_frame.h" #include "media/base/yuv_convert.h" -#include "content/public/browser/render_widget_host.h" #include "ui/gfx/screen.h" +#include "content/public/browser/render_widget_host.h" + namespace atom { namespace api { @@ -22,7 +23,6 @@ FrameSubscriber::FrameSubscriber(v8::Isolate* isolate, const FrameCaptureCallback& callback) : isolate_(isolate), callback_(callback), pending_frames(0), view_(view) { subscriber_ = new Subscriber(this); - size_ = view->GetVisibleViewportSize(); } Subscriber::Subscriber( diff --git a/atom/browser/api/frame_subscriber.h b/atom/browser/api/frame_subscriber.h index 745cf382adb..7029e0ed33a 100644 --- a/atom/browser/api/frame_subscriber.h +++ b/atom/browser/api/frame_subscriber.h @@ -6,12 +6,13 @@ #define ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_ #include "base/callback.h" +#include "v8/include/v8.h" + #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view_frame_subscriber.h" #include "content/public/browser/readback_types.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/size.h" -#include "v8/include/v8.h" namespace atom { @@ -50,7 +51,6 @@ class FrameSubscriber { bool RequestDestruct(); v8::Isolate* isolate_; - gfx::Size size_; content::RenderWidgetHostView* view_; FrameCaptureCallback callback_; Subscriber* subscriber_; From 12359078357f0d0227864a9700e660a673f764e3 Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 25 Feb 2016 23:35:01 +0530 Subject: [PATCH 167/173] run webframe methods for webview in its context --- atom/browser/api/lib/web-contents.js | 19 ++++++------------ atom/browser/lib/rpc-server.js | 10 ++++++++-- atom/renderer/api/atom_api_web_frame.cc | 2 +- atom/renderer/lib/init.js | 2 +- atom/renderer/lib/web-view/web-view.js | 26 +++++++++++++++---------- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/atom/browser/api/lib/web-contents.js b/atom/browser/api/lib/web-contents.js index 7cd54bfddfb..9486378264b 100644 --- a/atom/browser/api/lib/web-contents.js +++ b/atom/browser/api/lib/web-contents.js @@ -12,9 +12,6 @@ const debuggerBinding = process.atomBinding('debugger'); let slice = [].slice; let nextId = 0; -// Map of requestId and response callback. -let responseCallback = {}; - let getNextId = function() { return ++nextId; }; @@ -108,13 +105,11 @@ let wrapWebContents = function(webContents) { }; } - const asyncWebFrameMethods = function(requestId, method, ...args) { + const asyncWebFrameMethods = function(requestId, method, callback, ...args) { this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args); - ipcMain.once('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_RESPONSE_' + requestId, function(event, result) { - if (responseCallback[requestId]) { - responseCallback[requestId](result); - delete responseCallback[requestId]; - } + ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function(event, result) { + if (callback) + callback(result); }); }; @@ -126,12 +121,10 @@ let wrapWebContents = function(webContents) { callback = hasUserGesture; hasUserGesture = false; } - if (callback != null) - responseCallback[requestId] = callback; if (this.getURL() && !this.isLoading()) - return asyncWebFrameMethods.call(this, requestId, "executeJavaScript", code, hasUserGesture); + return asyncWebFrameMethods.call(this, requestId, "executeJavaScript", callback, code, hasUserGesture); else - return this.once('did-finish-load', asyncWebFrameMethods.bind(this, requestId, "executeJavaScript", code, hasUserGesture)); + return this.once('did-finish-load', asyncWebFrameMethods.bind(this, requestId, "executeJavaScript", callback, code, hasUserGesture)); }; // Dispatch IPC messages to the ipc module. diff --git a/atom/browser/lib/rpc-server.js b/atom/browser/lib/rpc-server.js index 20ee8fbdeae..a31c6e146e8 100644 --- a/atom/browser/lib/rpc-server.js +++ b/atom/browser/lib/rpc-server.js @@ -354,11 +354,17 @@ ipcMain.on('ATOM_BROWSER_GUEST_WEB_CONTENTS', function(event, guestInstanceId) { } }); -ipcMain.on('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function(event, guestInstanceId, method, ...args) { +ipcMain.on('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function(event, requestId, guestInstanceId, method, ...args) { try { let guestViewManager = require('./guest-view-manager'); let guest = guestViewManager.getGuest(guestInstanceId); - return guest[method].apply(guest, args); + if (requestId) { + const responseCallback = function(result) { + event.sender.send(`ATOM_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, result); + }; + args.push(responseCallback); + } + guest[method].apply(guest, args); } catch (error) { return event.returnValue = exceptionToMeta(error); } diff --git a/atom/renderer/api/atom_api_web_frame.cc b/atom/renderer/api/atom_api_web_frame.cc index af9a3c41621..e00b901bfff 100644 --- a/atom/renderer/api/atom_api_web_frame.cc +++ b/atom/renderer/api/atom_api_web_frame.cc @@ -40,7 +40,7 @@ class ScriptExecutionCallback : public blink::WebScriptExecutionCallback { void completed( const blink::WebVector>& result) override { - if (!callback_.is_null()) + if (!callback_.is_null() && !result.isEmpty() && !result[0].IsEmpty()) // Right now only single results per frame is supported. callback_.Run(result[0]); delete this; diff --git a/atom/renderer/lib/init.js b/atom/renderer/lib/init.js index cf42aa27229..166e64237de 100644 --- a/atom/renderer/lib/init.js +++ b/atom/renderer/lib/init.js @@ -38,7 +38,7 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', (event, m electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (event, requestId, method, args) => { const responseCallback = function(result) { - event.sender.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_RESPONSE_' + requestId, result); + event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, result); }; args.push(responseCallback); electron.webFrame[method].apply(electron.webFrame, args); diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 25e5eead2dd..bd128f6fffe 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -307,7 +307,7 @@ var registerBrowserPluginElement = function() { // Registers custom element. var registerWebViewElement = function() { - var createBlockHandler, createNonBlockHandler, i, j, len, len1, m, methods, nonblockMethods, webFrameMethods, proto; + var createBlockHandler, createNonBlockHandler, i, j, len, len1, m, methods, nonblockMethods, proto; proto = Object.create(HTMLObjectElement.prototype); proto.createdCallback = function() { return new WebViewImpl(this); @@ -392,12 +392,9 @@ var registerWebViewElement = function() { ]; nonblockMethods = [ 'insertCSS', + 'insertText', 'send', 'sendInputEvent', - ]; - webFrameMethods = [ - 'executeJavaScript', - 'insertText', 'setZoomFactor', 'setZoomLevel', 'setZoomLevelLimits', @@ -424,7 +421,7 @@ var registerWebViewElement = function() { var args, internal; args = 1 <= arguments.length ? slice.call(arguments, 0) : []; internal = v8Util.getHiddenValue(this, 'internal'); - return ipcRenderer.send.apply(ipcRenderer, ['ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', internal.guestInstanceId, m].concat(slice.call(args))); + return ipcRenderer.send.apply(ipcRenderer, ['ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', null, internal.guestInstanceId, m].concat(slice.call(args))); }; }; for (j = 0, len1 = nonblockMethods.length; j < len1; j++) { @@ -432,10 +429,19 @@ var registerWebViewElement = function() { proto[m] = createNonBlockHandler(m); } - // Forward proto.foo* webframe method calls to WebFrame.foo*. - for (let method of webFrameMethods) { - proto[method] = webFrame[method].bind(webFrame); - } + proto.executeJavaScript = function(code, hasUserGesture, callback) { + var internal = v8Util.getHiddenValue(this, 'internal'); + if (typeof hasUserGesture === "function") { + callback = hasUserGesture; + hasUserGesture = false; + } + let requestId = getNextId(); + ipcRenderer.send('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', requestId, internal.guestInstanceId, "executeJavaScript", code, hasUserGesture); + ipcRenderer.once(`ATOM_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, function(event, result) { + if (callback) + callback(result); + }); + }; // WebContents associated with this webview. proto.getWebContents = function() { From 4bfa03e5f4574ecea0d513b359406ded69449f9c Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Fri, 26 Feb 2016 02:13:17 +0100 Subject: [PATCH 168/173] Removed an include no longer needed --- atom/browser/api/frame_subscriber.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index 89e05d3e2dc..c76d5ffc87d 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -6,8 +6,6 @@ #include "base/bind.h" #include "atom/common/node_includes.h" -#include "ui/gfx/screen.h" - #include "content/public/browser/render_widget_host.h" namespace atom { From a3b8e81c213a157d944937c7c73641040622529e Mon Sep 17 00:00:00 2001 From: Felix Rieseberg Date: Wed, 24 Feb 2016 12:19:43 -0800 Subject: [PATCH 169/173] :memo: Add Headless CI Tutorial --- docs/README.md | 1 + docs/tutorial/testing-on-headless-ci.md | 38 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 docs/tutorial/testing-on-headless-ci.md diff --git a/docs/README.md b/docs/README.md index 9d2b36eb6c1..19ec51343d4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -26,6 +26,7 @@ an issue: * [DevTools Extension](tutorial/devtools-extension.md) * [Using Pepper Flash Plugin](tutorial/using-pepper-flash-plugin.md) * [Using Widevine CDM Plugin](tutorial/using-widevine-cdm-plugin.md) +* [Testing on Headless CI Systems (Travis, Jenkins)](tutorial/testing-on-headless-ci.md) ## Tutorials diff --git a/docs/tutorial/testing-on-headless-ci.md b/docs/tutorial/testing-on-headless-ci.md new file mode 100644 index 00000000000..6b0dacf788f --- /dev/null +++ b/docs/tutorial/testing-on-headless-ci.md @@ -0,0 +1,38 @@ +# Testing Electron with headless CI Systems (Travis CI, Jenkins) + +Being based on Chromium, Electron requires a display driver to function. If Chromium can't find a display driver, Electron will simply fail to launch - and therefore not executing any of your tests, regardless of how you are running them. Testing Electron-based apps on Travis, Circle, Jenkins or similar systems requires therefore a little bit of configuration. In essence, we need to use a virtual display driver. + +## Configuring the Virtual Display Server +First, install [Xvfb](https://en.wikipedia.org/wiki/Xvfb). It's a virtual framebuffer, implementing the X11 display server protocol - it performs all graphical operations in memory without showing any screen output, which is exactly what we need. + +Then, create a virtual xvfb screen and export an environment variable called DISPLAY that points to it. Chromium in Electron will automatically look for `$DISPLAY`, so no further configuration of your app is required. This step can be automated with Paul Betts's [xfvb-maybe](https://github.com/paulcbetts/xvfb-maybe): Prepend your test commands with `xfvb-maybe` and the little tool will automatically configure xfvb, if required by the current system. On Windows or Mac OS X, it will simply do nothing. + +``` +## On Windows or OS X, this just invokes electron-mocha +## On Linux, if we are in a headless environment, this will be equivalent +## to xvfb-run electron-mocha ./test/*.js +xvfb-maybe electron-mocha ./test/*.js +``` + +### Travis CI +On Travis, your `.travis.yml` should look roughly like this: + +``` +addons: + apt: + packages: + - xvfb + +install: + - export DISPLAY=':99.0' + - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +``` + +### Jenkins +For Jenkins, a [Xfvb plugin is available](https://wiki.jenkins-ci.org/display/JENKINS/Xvfb+Plugin). + +### Circle CI +Circle CI is awesome and has xvfb and `$DISPLAY` [already setup, so no further configuration is required](https://circleci.com/docs/environment#browsers). + +### AppVeyor +AppVeyor runs on Windows, supporting Selenium, Chromium, Electron and similar tools out of the box - no configuration is required. From 8a744255facacf54cecc8b5eb526ce08afab1ec4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 26 Feb 2016 09:23:39 +0800 Subject: [PATCH 170/173] Update libchromiumcontent, use harfbuzz 1.06 Close #4513. --- script/lib/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/lib/config.py b/script/lib/config.py index e3404918ce4..d4a055912e4 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '599c8941e1884e155218ec1013cba9fc5c7c7072' +LIBCHROMIUMCONTENT_COMMIT = 'ff714bf7ad79b0d278bcd20c3081a69b40be8bb8' PLATFORM = { 'cygwin': 'win32', From a67b29d8d28c1eb993c89a097dda17c0cf63d99b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 26 Feb 2016 02:18:27 +0000 Subject: [PATCH 171/173] Bump v0.36.9 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/atom.gyp b/atom.gyp index 68a30cc637f..0bccc254b1b 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.36.8', + 'version%': '0.36.9', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index e1a5694d27a..b3eb7d8efaa 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.36.8 + 0.36.9 CFBundleShortVersionString - 0.36.8 + 0.36.9 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index ff125b3edf7..2dee1c0e433 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 0,36,8,0 - PRODUCTVERSION 0,36,8,0 + FILEVERSION 0,36,9,0 + PRODUCTVERSION 0,36,9,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.36.8" + VALUE "FileVersion", "0.36.9" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.36.8" + VALUE "ProductVersion", "0.36.9" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index b464ebdae4f..136c375e2ac 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 0 #define ATOM_MINOR_VERSION 36 -#define ATOM_PATCH_VERSION 8 +#define ATOM_PATCH_VERSION 9 #define ATOM_VERSION_IS_RELEASE 1 diff --git a/package.json b/package.json index e6d399fb3be..504bdd6a4f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "0.36.8", + "version": "0.36.9", "devDependencies": { "asar": "^0.10.0", "eslint": "^2.1.0", From fce641aab64da828cf03afd2e07b7b81333655ad Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 26 Feb 2016 15:47:28 +0530 Subject: [PATCH 172/173] browser: allow enumeration of media device labels --- atom/browser/api/atom_api_web_contents.cc | 7 +++++++ atom/browser/api/atom_api_web_contents.h | 4 ++++ spec/chromium-spec.js | 14 ++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 4935adbc75a..28893a54a3d 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -463,6 +463,13 @@ void WebContents::FindReply(content::WebContents* web_contents, } } +bool WebContents::CheckMediaAccessPermission( + content::WebContents* web_contents, + const GURL& security_origin, + content::MediaStreamType type) { + return true; +} + void WebContents::RequestMediaAccessPermission( content::WebContents* web_contents, const content::MediaStreamRequest& request, diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index b4f29090dbd..a785e1c070d 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -202,6 +202,10 @@ class WebContents : public mate::TrackableObject, const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update) override; + bool CheckMediaAccessPermission( + content::WebContents* web_contents, + const GURL& security_origin, + content::MediaStreamType type) override; void RequestMediaAccessPermission( content::WebContents* web_contents, const content::MediaStreamRequest& request, diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index e4444f55b11..8477aea776a 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -87,6 +87,20 @@ describe('chromium feature', function() { }); }); + describe('navigator.mediaDevices', function() { + if (process.env.TRAVIS === 'true') { + return; + } + + it('can return labels of enumerated devices', function(done) { + navigator.mediaDevices.enumerateDevices().then((devices) => { + const result = devices.some((device) => !!device.label); + if (result) + done(); + }); + }); + }); + describe('navigator.language', function() { it('should not be empty', function() { assert.notEqual(navigator.language, ''); From 070772b4b984e0bc03cea28388dffaa63b14d0d0 Mon Sep 17 00:00:00 2001 From: gellert Date: Sat, 6 Feb 2016 22:33:21 +0100 Subject: [PATCH 173/173] Added special key identifiers for OSX and Windows --- atom/common/keyboard_util.cc | 10 ++++++++++ docs/api/web-contents.md | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/atom/common/keyboard_util.cc b/atom/common/keyboard_util.cc index e5dedd84ded..1884246d233 100644 --- a/atom/common/keyboard_util.cc +++ b/atom/common/keyboard_util.cc @@ -80,6 +80,16 @@ ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& chr) { if (chr == "tab") return ui::VKEY_TAB; if (chr == "escape") return ui::VKEY_ESCAPE; if (chr == "control") return ui::VKEY_CONTROL; +#if defined(OS_MACOSX) + if (chr == "command" + || chr == "cmd" + || chr == "meta") return ui::VKEY_COMMAND; + if (chr == "option") return ui::VKEY_MENU; +#endif +#if defined(OS_WIN) + if (chr == "meta") return ui::VKEY_LWIN; + if (chr == "altgr") return ui::VKEY_ALTGR; +#endif if (chr == "alt") return ui::VKEY_MENU; if (chr == "shift") return ui::VKEY_SHIFT; if (chr == "end") return ui::VKEY_END; diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index dde701d7f48..31c55801aab 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -769,8 +769,10 @@ For keyboard events, the `event` object also have following properties: * `keyCode` Char or String (**required**) - The character that will be sent as the keyboard event. Can be a single UTF-8 character, or the name of the key that generates the event. Accepted key names are `enter`, `backspace`, - `delete`, `tab`, `escape`, `control`, `alt`, `shift`, `end`, `home`, `insert`, - `left`, `up`, `right`, `down`, `pageUp`, `pageDown`, `printScreen` + `delete`, `tab`, `escape`, `control`, `alt`, `altgr` (Windows only), `shift`, + `end`, `home`, `insert`, `left`, `up`, `right`, `down`, `pageUp`, `pageDown`, + `printScreen`, `meta`, `cmd` (OSX only), `command` (OSX only), `option` + (OSX only) For mouse events, the `event` object also have following properties: