From 621178f5588d36336dd7adb0fbda70b2e8b62ec5 Mon Sep 17 00:00:00 2001 From: Patrick Detlefsen Date: Mon, 15 Jun 2015 20:28:47 +0200 Subject: [PATCH 001/738] initial idea --- atom/browser/api/lib/auto-updater.coffee | 7 ++- .../lib/auto-updater/auto-updater-win.coffee | 60 +++++++++++++++++++ .../auto-updater/squirrel-update-win.coffee | 42 +++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 atom/browser/api/lib/auto-updater/auto-updater-win.coffee create mode 100644 atom/browser/api/lib/auto-updater/squirrel-update-win.coffee diff --git a/atom/browser/api/lib/auto-updater.coffee b/atom/browser/api/lib/auto-updater.coffee index 8b6f7ffd0d30..7d7feea7ac95 100644 --- a/atom/browser/api/lib/auto-updater.coffee +++ b/atom/browser/api/lib/auto-updater.coffee @@ -1,4 +1,9 @@ -autoUpdater = process.atomBinding('auto_updater').autoUpdater +switch process.platform + when 'darwin' + autoUpdater = process.atomBinding('auto_updater').autoUpdater + when 'win32' + autoUpdater = require('./auto-updater-win') + EventEmitter = require('events').EventEmitter autoUpdater.__proto__ = EventEmitter.prototype diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee new file mode 100644 index 000000000000..043d4c7c419f --- /dev/null +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee @@ -0,0 +1,60 @@ +{EventEmitter} = require 'events' +SquirrelUpdate = require './auto-updater/squirrel-update-win' + +class AutoUpdater + @__proto__ = EventEmitter.prototype + + quitAndInstall: -> + # TODO + + setFeedUrl: (@updateUrl) -> + + checkForUpdates: -> + throw new Error('Update URL is not set') unless @updateUrl + + @emit 'checking-for-update' + + unless SquirrelUpdate.existsSync() + @emit 'update-not-available' + return + + @downloadUpdate (error, update) => + if error? + @emit 'update-not-available' + return + + unless update? + @emit 'update-not-available' + return + + @emit 'update-available' + + @installUpdate (error) => + if error? + @emit 'update-not-available' + return + + @emit 'update-downloaded', {}, update.releaseNotes, update.version, new Date(), @updateUrl, => @quitAndInstall() + + downloadUpdate: (callback) -> + SquirrelUpdate.spawn ['--download', @updateUrl], (error, stdout) -> + return callback(error) if error? + + try + # Last line of output is the JSON details about the releases + json = stdout.trim().split('\n').pop() + update = JSON.parse(json)?.releasesToApply?.pop?() + catch error + error.stdout = stdout + return callback(error) + + callback(null, update) + + installUpdate: (callback) -> + SquirrelUpdate.spawn(['--update', @updateUrl], callback) + + supportsUpdates: -> + SquirrelUpdate.existsSync() + + +module.exports = new AutoUpdater() diff --git a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee new file mode 100644 index 000000000000..faaa907f679f --- /dev/null +++ b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee @@ -0,0 +1,42 @@ +ChildProcess = require 'child_process' +fs = require 'fs' +path = require 'path' + +appFolder = path.resolve(process.execPath, '..') # i.e. my-app/app-0.1.13/ +rootApplicationFolder = path.resolve(appFolder, '..') # i.e. my-app/ +updateDotExe = path.join(rootApplicationFolder, 'Update.exe') +exeName = path.basename(process.execPath) + +# Spawn a command and invoke the callback when it completes with an error +# and the output from standard out. +spawn = (command, args, callback) -> + stdout = '' + + try + spawnedProcess = ChildProcess.spawn(command, args) + catch error + # Spawn can throw an error + process.nextTick -> callback?(error, stdout) + return + + spawnedProcess.stdout.on 'data', (data) -> stdout += data + + error = null + spawnedProcess.on 'error', (processError) -> error ?= processError + spawnedProcess.on 'close', (code, signal) -> + error ?= new Error("Command failed: #{signal ? code}") if code isnt 0 + error?.code ?= code + error?.stdout ?= stdout + callback?(error, stdout) + +# Spawn the Update.exe with the given arguments and invoke the callback when +# the command completes. +spawnUpdate = (args, callback) -> + spawn(updateDotExe, args, callback) + +# Exports +exports.spawn = spawnUpdate + +# Is the Update.exe installed with Atom? +exports.existsSync = -> + fs.accessSync(updateDotExe, fs.R_OK) From 99f352228c62100069df90146536faea82edd981 Mon Sep 17 00:00:00 2001 From: Patrick Detlefsen Date: Tue, 16 Jun 2015 11:04:37 +0200 Subject: [PATCH 002/738] addresses suggestions from pull-request --- atom/browser/api/lib/auto-updater.coffee | 7 ++++--- atom/browser/api/lib/auto-updater/auto-updater-win.coffee | 5 ++++- .../api/lib/auto-updater/squirrel-update-win.coffee | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/atom/browser/api/lib/auto-updater.coffee b/atom/browser/api/lib/auto-updater.coffee index 7d7feea7ac95..0b7e84ba7efe 100644 --- a/atom/browser/api/lib/auto-updater.coffee +++ b/atom/browser/api/lib/auto-updater.coffee @@ -1,8 +1,9 @@ switch process.platform - when 'darwin' - autoUpdater = process.atomBinding('auto_updater').autoUpdater when 'win32' - autoUpdater = require('./auto-updater-win') + autoUpdater = require('./auto-updater/auto-updater-win') + default + # take the default binding for the current platform + autoUpdater = process.atomBinding('auto_updater').autoUpdater EventEmitter = require('events').EventEmitter diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee index 043d4c7c419f..556b86cbc95e 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee @@ -7,7 +7,10 @@ class AutoUpdater quitAndInstall: -> # TODO - setFeedUrl: (@updateUrl) -> + setFeedUrl: (updateUrl) -> + # set feed URL only when it hasn't been set before + unless @updateUrl + @updateUrl = updateUrl checkForUpdates: -> throw new Error('Update URL is not set') unless @updateUrl diff --git a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee index faaa907f679f..d57a0130784e 100644 --- a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee +++ b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee @@ -2,8 +2,8 @@ ChildProcess = require 'child_process' fs = require 'fs' path = require 'path' -appFolder = path.resolve(process.execPath, '..') # i.e. my-app/app-0.1.13/ -rootApplicationFolder = path.resolve(appFolder, '..') # i.e. my-app/ +appFolder = path.dirname(process.execPath) # i.e. my-app/app-0.1.13/ +rootApplicationFolder = path.resolve(appFolder, '..') # i.e. my-app/ updateDotExe = path.join(rootApplicationFolder, 'Update.exe') exeName = path.basename(process.execPath) From 7aa60baafb0749075ac33ff77dc183f2e0bc91cc Mon Sep 17 00:00:00 2001 From: Patrick Detlefsen Date: Tue, 16 Jun 2015 11:48:39 +0200 Subject: [PATCH 003/738] switch statement coffee else instead of default --- atom/browser/api/lib/auto-updater.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/api/lib/auto-updater.coffee b/atom/browser/api/lib/auto-updater.coffee index 0b7e84ba7efe..1b6c935f34b6 100644 --- a/atom/browser/api/lib/auto-updater.coffee +++ b/atom/browser/api/lib/auto-updater.coffee @@ -1,7 +1,7 @@ switch process.platform when 'win32' autoUpdater = require('./auto-updater/auto-updater-win') - default + else # take the default binding for the current platform autoUpdater = process.atomBinding('auto_updater').autoUpdater From a8469fc79d4f5c87c7d6f2b1e1b877fccd9c2500 Mon Sep 17 00:00:00 2001 From: Patrick Detlefsen Date: Tue, 16 Jun 2015 12:31:55 +0200 Subject: [PATCH 004/738] auto-updater extends event-emitter --- atom/browser/api/lib/auto-updater/auto-updater-win.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee index 556b86cbc95e..1f9fcd185fc1 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee @@ -1,8 +1,7 @@ {EventEmitter} = require 'events' SquirrelUpdate = require './auto-updater/squirrel-update-win' -class AutoUpdater - @__proto__ = EventEmitter.prototype +class AutoUpdater extends EventEmitter quitAndInstall: -> # TODO From 62882fe49e6910710b17cb186192fdf67df5544d Mon Sep 17 00:00:00 2001 From: Patrick Detlefsen Date: Tue, 16 Jun 2015 16:13:23 +0200 Subject: [PATCH 005/738] auto updater win is an EventEmitter already --- atom/browser/api/lib/auto-updater.coffee | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/lib/auto-updater.coffee b/atom/browser/api/lib/auto-updater.coffee index 1b6c935f34b6..a479f5fccfe5 100644 --- a/atom/browser/api/lib/auto-updater.coffee +++ b/atom/browser/api/lib/auto-updater.coffee @@ -3,11 +3,9 @@ switch process.platform autoUpdater = require('./auto-updater/auto-updater-win') else # take the default binding for the current platform - autoUpdater = process.atomBinding('auto_updater').autoUpdater - -EventEmitter = require('events').EventEmitter - -autoUpdater.__proto__ = EventEmitter.prototype + autoUpdater = process.atomBinding('auto_updater').autoUpdater + EventEmitter = require('events').EventEmitter + autoUpdater.__proto__ = EventEmitter.prototype autoUpdater.on 'update-downloaded-raw', (args...) -> args[3] = new Date(args[3]) # releaseDate From ae5411c37b9c712e0a6b973eaf729753cd21e7c1 Mon Sep 17 00:00:00 2001 From: Patrick Detlefsen Date: Mon, 22 Jun 2015 15:16:50 +0200 Subject: [PATCH 006/738] move squirrel bahaviour into proper place --- .../lib/auto-updater/auto-updater-win.coffee | 23 ++++-------- .../auto-updater/squirrel-update-win.coffee | 35 +++++++++++++------ 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee index 1f9fcd185fc1..a3fbd8822ada 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee @@ -1,10 +1,12 @@ {EventEmitter} = require 'events' SquirrelUpdate = require './auto-updater/squirrel-update-win' +app = require('app') class AutoUpdater extends EventEmitter quitAndInstall: -> - # TODO + SquirrelUpdate.processStart -> + app.quit() setFeedUrl: (updateUrl) -> # set feed URL only when it hasn't been set before @@ -36,27 +38,16 @@ class AutoUpdater extends EventEmitter @emit 'update-not-available' return + # info about the newly installed version and a function any of the event listeners can call to restart the application @emit 'update-downloaded', {}, update.releaseNotes, update.version, new Date(), @updateUrl, => @quitAndInstall() downloadUpdate: (callback) -> - SquirrelUpdate.spawn ['--download', @updateUrl], (error, stdout) -> - return callback(error) if error? - - try - # Last line of output is the JSON details about the releases - json = stdout.trim().split('\n').pop() - update = JSON.parse(json)?.releasesToApply?.pop?() - catch error - error.stdout = stdout - return callback(error) - - callback(null, update) + SquirrelUpdate.download(callback) installUpdate: (callback) -> - SquirrelUpdate.spawn(['--update', @updateUrl], callback) + SquirrelUpdate.update(@updateUrl, callback) supportsUpdates: -> - SquirrelUpdate.existsSync() - + SquirrelUpdate.supported() module.exports = new AutoUpdater() diff --git a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee index d57a0130784e..f07584f4c54d 100644 --- a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee +++ b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee @@ -9,11 +9,11 @@ exeName = path.basename(process.execPath) # Spawn a command and invoke the callback when it completes with an error # and the output from standard out. -spawn = (command, args, callback) -> +spawnUpdate = (args, callback) -> stdout = '' try - spawnedProcess = ChildProcess.spawn(command, args) + spawnedProcess = ChildProcess.spawn(updateDotExe, args) catch error # Spawn can throw an error process.nextTick -> callback?(error, stdout) @@ -29,14 +29,29 @@ spawn = (command, args, callback) -> error?.stdout ?= stdout callback?(error, stdout) -# Spawn the Update.exe with the given arguments and invoke the callback when -# the command completes. -spawnUpdate = (args, callback) -> - spawn(updateDotExe, args, callback) +processStart = (callback) -> + spawnUpdate(['--processStart', exeName], callback) -# Exports -exports.spawn = spawnUpdate +download = (callback) -> + spawnUpdate ['--download', @updateUrl], (error, stdout) -> + return callback(error) if error? -# Is the Update.exe installed with Atom? -exports.existsSync = -> + try + # Last line of output is the JSON details about the releases + json = stdout.trim().split('\n').pop() + update = JSON.parse(json)?.releasesToApply?.pop?() + catch error + error.stdout = stdout + return callback(error) + + callback(null, update) + +update = (updateUrl, callback) -> + spawnUpdate ['--update', updateUrl], callback + +# Is the Update.exe installed with the current application? +exports.supported = -> fs.accessSync(updateDotExe, fs.R_OK) +exports.processStart = processStart +exports.download = download +exports.update = update From 154ca8575ca450405307958004e5c862a7cdda10 Mon Sep 17 00:00:00 2001 From: Patrick Detlefsen Date: Mon, 22 Jun 2015 15:33:08 +0200 Subject: [PATCH 007/738] limit the auto-updater-win api to very few methods --- .../api/lib/auto-updater/auto-updater-win.coffee | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee index a3fbd8822ada..2da37ddb035e 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee @@ -18,11 +18,11 @@ class AutoUpdater extends EventEmitter @emit 'checking-for-update' - unless SquirrelUpdate.existsSync() + unless SquirrelUpdate.supported() @emit 'update-not-available' return - @downloadUpdate (error, update) => + SquirrelUpdate.download (error, update) => if error? @emit 'update-not-available' return @@ -33,7 +33,7 @@ class AutoUpdater extends EventEmitter @emit 'update-available' - @installUpdate (error) => + SquirrelUpdate.update @updateUrl, (error) => if error? @emit 'update-not-available' return @@ -41,13 +41,4 @@ class AutoUpdater extends EventEmitter # info about the newly installed version and a function any of the event listeners can call to restart the application @emit 'update-downloaded', {}, update.releaseNotes, update.version, new Date(), @updateUrl, => @quitAndInstall() - downloadUpdate: (callback) -> - SquirrelUpdate.download(callback) - - installUpdate: (callback) -> - SquirrelUpdate.update(@updateUrl, callback) - - supportsUpdates: -> - SquirrelUpdate.supported() - module.exports = new AutoUpdater() From 6c4016af462d9f449b7f823ba80eb19f4511ef5e Mon Sep 17 00:00:00 2001 From: Patrick Detlefsen Date: Mon, 22 Jun 2015 15:51:47 +0200 Subject: [PATCH 008/738] make sure the query params are stripped from the updateUrl --- .../api/lib/auto-updater/auto-updater-win.coffee | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee index 2da37ddb035e..9a2431577e0b 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee @@ -1,6 +1,7 @@ {EventEmitter} = require 'events' SquirrelUpdate = require './auto-updater/squirrel-update-win' app = require('app') +url = require('url') class AutoUpdater extends EventEmitter @@ -11,7 +12,14 @@ class AutoUpdater extends EventEmitter setFeedUrl: (updateUrl) -> # set feed URL only when it hasn't been set before unless @updateUrl - @updateUrl = updateUrl + # See https://github.com/Squirrel/Squirrel.Windows/issues/132 + # This way the Mac and Windows Update URL can be the same, even when + # the Mac version is sending additional data in the query string. + parsedUrl = url.parse(updateUrl) + delete parsedUrl.search + delete parsedUrl.query + + @updateUrl = url.format(parsedUrl) checkForUpdates: -> throw new Error('Update URL is not set') unless @updateUrl From 01f06431423195891f6f6f63f3135d83ec8eca20 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 25 Sep 2015 09:34:04 +0800 Subject: [PATCH 009/738] Fix inconsistent docs: downloadItem.getURL() => downloadItem.getUrl() --- docs/api/download-item.md | 2 +- docs/api/session.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/download-item.md b/docs/api/download-item.md index 722dc5d8cf78..5097fde83f5c 100644 --- a/docs/api/download-item.md +++ b/docs/api/download-item.md @@ -66,7 +66,7 @@ Resumes the download that has been paused. Cancels the download operation. -### `downloadItem.getURL()` +### `downloadItem.getUrl()` Returns a `String` represents the origin url where the item is downloaded from. diff --git a/docs/api/session.md b/docs/api/session.md index ae0aacf4657f..64991ab7530c 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -28,7 +28,7 @@ Calling `event.preventDefault()` will cancel the download. ```javascript session.on('will-download', function(event, item, webContents) { event.preventDefault(); - require('request')(item.getURL(), function(data) { + require('request')(item.getUrl(), function(data) { require('fs').writeFileSync('/somewhere', data); }); }); From 109d8352e1f0970c3382a89ff72289065a04af49 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Sep 2015 12:52:16 +0800 Subject: [PATCH 010/738] Update node, fixes #2894 --- vendor/node | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/node b/vendor/node index d64246490d69..558bfc048294 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit d64246490d697f387b888391b1aba65032703a0f +Subproject commit 558bfc048294acb57f702f1a802eddd01ebf2794 From 004d3ced5323f55fb094c400365d21edcf4e109c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Sep 2015 13:04:54 +0800 Subject: [PATCH 011/738] Update node to fix building on Windows --- vendor/node | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/node b/vendor/node index 558bfc048294..ac25693ad1d4 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 558bfc048294acb57f702f1a802eddd01ebf2794 +Subproject commit ac25693ad1d4c248e69a89147fd3995c3bf6c946 From 4a64d1d9467e00748f4e157af664a51aed564e38 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 25 Sep 2015 13:13:11 +0800 Subject: [PATCH 012/738] :memo: fix a typo interrputed => interrupted --- atom/browser/api/atom_api_download_item.cc | 2 +- docs/api/download-item.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index 6b3dfbf3f7db..ec4dcd84b285 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -30,7 +30,7 @@ struct Converter { download_state = "cancelled"; break; case content::DownloadItem::INTERRUPTED: - download_state = "interrputed"; + download_state = "interrupted"; break; default: break; diff --git a/docs/api/download-item.md b/docs/api/download-item.md index 5097fde83f5c..53cd56cca9e5 100644 --- a/docs/api/download-item.md +++ b/docs/api/download-item.md @@ -39,7 +39,7 @@ Emits when the `downloadItem` gets updated. * `interrupted` - An error broke the connection with the file server. Emits when the download is in a terminal state. This includes a completed -download, a cancelled download(via `downloadItem.cancel()`), and interrputed +download, a cancelled download(via `downloadItem.cancel()`), and interrupted download that can't be resumed. ## Methods From 6f944ad49b85b772166fb14951c9a4c8ce4b963d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Sep 2015 16:21:08 +0800 Subject: [PATCH 013/738] Clean up code --- atom/browser/native_window_mac.mm | 36 ++++++++++++++----------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 6a99f1cf4227..c87e4b2dca1e 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -351,21 +351,19 @@ NativeWindowMac::NativeWindowMac( bool useStandardWindow = true; options.Get(switches::kStandardWindow, &useStandardWindow); + // New title bar styles are available in Yosemite or newer + std::string titleBarStyle; + if (base::mac::IsOSYosemiteOrLater()) + options.Get(switches::kTitleBarStyle, &titleBarStyle); + NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask; if (!useStandardWindow || transparent() || !has_frame()) { styleMask |= NSTexturedBackgroundWindowMask; } - - std::string titleBarStyle = "default"; - options.Get(switches::kTitleBarStyle, &titleBarStyle); - - if (base::mac::IsOSYosemiteOrLater()) { - // New title bar styles are available in Yosemite or newer - if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { - styleMask |= NSFullSizeContentViewWindowMask; - styleMask |= NSUnifiedTitleAndToolbarWindowMask; - } + if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { + styleMask |= NSFullSizeContentViewWindowMask; + styleMask |= NSUnifiedTitleAndToolbarWindowMask; } window_.reset([[AtomNSWindow alloc] @@ -394,16 +392,14 @@ NativeWindowMac::NativeWindowMac( [window_ setReleasedWhenClosed:NO]; // Configure title bar look on Yosemite or newer - if (base::mac::IsOSYosemiteOrLater()) { - if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { - [window_ setTitlebarAppearsTransparent:YES]; - [window_ setTitleVisibility:NSWindowTitleHidden]; - if (titleBarStyle == "hidden-inset") { - NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]; - toolbar.showsBaselineSeparator = NO; - [window_ setToolbar:toolbar]; - [toolbar release]; - } + if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { + [window_ setTitlebarAppearsTransparent:YES]; + [window_ setTitleVisibility:NSWindowTitleHidden]; + if (titleBarStyle == "hidden-inset") { + base::scoped_nsobject toolbar( + [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]); + [toolbar setShowsBaselineSeparator:NO]; + [window_ setToolbar:toolbar]; } } From 7884a2319c5fb65c262435efc274c0f362c4f87e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Sep 2015 16:38:36 +0800 Subject: [PATCH 014/738] osx: Make draggable region work for window with hidden titlebar --- atom/browser/native_window.cc | 3 ++- atom/browser/native_window.h | 10 ++++++++++ atom/browser/native_window_mac.mm | 9 ++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index e06633d7b7ca..c3620bba7052 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -68,6 +68,7 @@ NativeWindow::NativeWindow( const mate::Dictionary& options) : content::WebContentsObserver(inspectable_web_contents->GetWebContents()), has_frame_(true), + force_using_draggable_region_(false), transparent_(false), enable_larger_than_screen_(false), is_closed_(false), @@ -473,7 +474,7 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) { void NativeWindow::UpdateDraggableRegions( const std::vector& regions) { // Draggable region is not supported for non-frameless window. - if (has_frame_) + if (has_frame_ && !force_using_draggable_region_) return; draggable_region_ = DraggableRegionsToSkRegion(regions); } diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index e9a2b9433d13..5c8d8c73b0fe 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -219,6 +219,13 @@ class NativeWindow : public content::WebContentsObserver, bool enable_larger_than_screen() const { return enable_larger_than_screen_; } gfx::ImageSkia icon() const { return icon_; } + bool force_using_draggable_region() const { + return force_using_draggable_region_; + } + void set_force_using_draggable_region(bool force) { + force_using_draggable_region_ = true; + } + void set_has_dialog_attached(bool has_dialog_attached) { has_dialog_attached_ = has_dialog_attached; } @@ -257,6 +264,9 @@ class NativeWindow : public content::WebContentsObserver, // Whether window has standard frame. bool has_frame_; + // Force the window to be aware of draggable regions. + bool force_using_draggable_region_; + // Whether window is transparent. bool transparent_; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index c87e4b2dca1e..f0a685e4d952 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -391,7 +391,7 @@ NativeWindowMac::NativeWindowMac( // We will manage window's lifetime ourselves. [window_ setReleasedWhenClosed:NO]; - // Configure title bar look on Yosemite or newer + // Hide the title bar. if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { [window_ setTitlebarAppearsTransparent:YES]; [window_ setTitleVisibility:NSWindowTitleHidden]; @@ -401,6 +401,8 @@ NativeWindowMac::NativeWindowMac( [toolbar setShowsBaselineSeparator:NO]; [window_ setToolbar:toolbar]; } + // We should be aware of draggable regions when using hidden titlebar. + set_force_using_draggable_region(true); } // On OS X the initial window size doesn't include window frame. @@ -432,6 +434,11 @@ NativeWindowMac::NativeWindowMac( [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; InstallView(); + + // Install the DraggableRegionView if it is forced to use draggable regions + // for normal window. + if (has_frame() && force_using_draggable_region()) + InstallDraggableRegionView(); } NativeWindowMac::~NativeWindowMac() { From c0528c5049dc42ab191367b0a463274f72f46818 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Sep 2015 17:50:53 +0800 Subject: [PATCH 015/738] Bump v0.33.2 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 2 +- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/atom.gyp b/atom.gyp index 3a46f242a238..41d671d7a293 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.1', + 'version%': '0.33.2', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 6260173b8258..745b12520c2b 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,7 +17,7 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.1 + 0.33.2 LSMinimumSystemVersion 10.8.0 NSMainNibFile diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 0583c2df3be9..e0b9fa5cfe82 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,33,1,0 - PRODUCTVERSION 0,33,1,0 + FILEVERSION 0,33,2,0 + PRODUCTVERSION 0,33,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.1" + VALUE "FileVersion", "0.33.2" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.33.1" + VALUE "ProductVersion", "0.33.2" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 5f9d0f3ca0bb..56dcd67fb0fb 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 33 -#define ATOM_PATCH_VERSION 1 +#define ATOM_PATCH_VERSION 2 #define ATOM_VERSION_IS_RELEASE 1 From bb102717b4576c8daf5e75ccc564b471c0bd1d70 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Fri, 25 Sep 2015 13:01:52 +0200 Subject: [PATCH 016/738] Adding option to specify the button of WebMouseEvent. --- .../native_mate_converters/blink_converter.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/atom/common/native_mate_converters/blink_converter.cc b/atom/common/native_mate_converters/blink_converter.cc index 67c7e7e95fd8..beb60737e73f 100644 --- a/atom/common/native_mate_converters/blink_converter.cc +++ b/atom/common/native_mate_converters/blink_converter.cc @@ -77,6 +77,21 @@ struct Converter { } }; +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Handle val, + blink::WebMouseEvent::Button* out) { + std::string button = base::StringToLowerASCII(V8ToString(val)); + if (button == "left") + *out = blink::WebMouseEvent::Button::ButtonLeft; + else if (button == "middle") + *out = blink::WebMouseEvent::Button::ButtonMiddle; + else if (button == "right") + *out = blink::WebMouseEvent::Button::ButtonRight; + return true; + } +}; + template<> struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Handle val, @@ -176,6 +191,7 @@ bool Converter::FromV8( return false; if (!dict.Get("x", &out->x) || !dict.Get("y", &out->y)) return false; + dict.Get("button", &out->button); dict.Get("globalX", &out->globalX); dict.Get("globalY", &out->globalY); dict.Get("movementX", &out->movementX); From 775c90b7337bcb74a3d5d21f803f4a7034c6ff24 Mon Sep 17 00:00:00 2001 From: Josh Abernathy Date: Fri, 25 Sep 2015 11:37:30 -0400 Subject: [PATCH 017/738] Use 0.8.0. This picks up the fix for https://github.com/atom/atom/issues/7061. --- script/update-external-binaries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/update-external-binaries.py b/script/update-external-binaries.py index 49e73435ab51..fae268ea8cb7 100755 --- a/script/update-external-binaries.py +++ b/script/update-external-binaries.py @@ -8,7 +8,7 @@ from lib.config import get_target_arch from lib.util import safe_mkdir, rm_rf, extract_zip, tempdir, download -VERSION = 'v0.7.0' +VERSION = 'v0.8.0' SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) FRAMEWORKS_URL = 'http://github.com/atom/atom-shell-frameworks/releases' \ '/download/' + VERSION From 56520159f73ba6fbc3faa41a6c0977e923c4e088 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sat, 26 Sep 2015 10:36:26 +0900 Subject: [PATCH 018/738] Update as upstream, fix small typo --- docs-translations/ko-KR/api/session.md | 8 ++---- .../ko-KR/tutorial/quick-start.md | 1 + .../tutorial/using-native-node-modules.md | 27 ++++++++++--------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index cb912aabb100..4c6ead1647ff 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -17,11 +17,7 @@ var session = win.webContents.session ### Event: 'will-download' * `event` Event -* `item` Object - * `url` String - * `filename` String - * `mimeType` String - * `hasUserGesture` Boolean +* `item` [DownloadItem](download-item.md) * `webContents` [WebContents](web-contents.md) Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이벤트입니다. @@ -31,7 +27,7 @@ Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이 ```javascript session.on('will-download', function(event, item, webContents) { event.preventDefault(); - require('request')(item.url, function(data) { + require('request')(item.getUrl(), function(data) { require('fs').writeFileSync('/somewhere', data); }); }); diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 8c2e043061ec..4a6ce6d22523 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -111,6 +111,7 @@ app.on('ready', function() { + 헬로 월드! diff --git a/docs-translations/ko-KR/tutorial/using-native-node-modules.md b/docs-translations/ko-KR/tutorial/using-native-node-modules.md index 913c300be881..ed64abb492f7 100644 --- a/docs-translations/ko-KR/tutorial/using-native-node-modules.md +++ b/docs-translations/ko-KR/tutorial/using-native-node-modules.md @@ -29,7 +29,20 @@ npm install --save-dev electron-rebuild node ./node_modules/.bin/electron-rebuild ``` -### node-gyp을 이용한 방법 +### `npm`을 이용한 방법 + +또한 `npm`을 통해 설치할 수도 있습니다. +환경변수가 필요한 것을 제외하고 일반 Node 모듈을 설치하는 방법과 완전히 똑같습니다: + +```bash +export npm_config_disturl=https://atom.io/download/atom-shell +export npm_config_target=0.33.1 +export npm_config_arch=x64 +export npm_config_runtime=electron +HOME=~/.electron-gyp npm install module-name +``` + +### `node-gyp`를 이용한 방법 Node 모듈을 `node-gyp`를 사용하여 Electron을 타겟으로 빌드할 때는 `node-gyp`에 헤더 다운로드 주소와 버전을 알려주어야 합니다: @@ -40,15 +53,3 @@ $ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=ht `HOME=~/.electron-gyp`은 변경할 헤더의 위치를 찾습니다. `--target=0.29.1`은 Electron의 버전입니다. `--dist-url=...`은 헤더를 다운로드 하는 주소입니다. `--arch=x64`는 64비트 시스템을 타겟으로 빌드 한다는 것을 `node-gyp`에게 알려줍니다. - -### npm을 이용한 방법 - -또한 `npm`을 통해 설치할 수도 있습니다. -환경변수가 필요한 것을 제외하고 일반 Node 모듈을 설치하는 방법과 완전히 똑같습니다: - -```bash -export npm_config_disturl=https://atom.io/download/atom-shell -export npm_config_target=0.29.1 -export npm_config_arch=x64 -HOME=~/.electron-gyp npm install module-name -``` From 690f859a78cb1928b299fc126b8f8720044cdc33 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 26 Sep 2015 22:06:01 +0800 Subject: [PATCH 019/738] Bump v0.33.3 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 2 +- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/atom.gyp b/atom.gyp index 41d671d7a293..42069ea84621 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.2', + 'version%': '0.33.3', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 745b12520c2b..eb39cb35f947 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,7 +17,7 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.2 + 0.33.3 LSMinimumSystemVersion 10.8.0 NSMainNibFile diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index e0b9fa5cfe82..6fba6cf80676 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,33,2,0 - PRODUCTVERSION 0,33,2,0 + FILEVERSION 0,33,3,0 + PRODUCTVERSION 0,33,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.2" + VALUE "FileVersion", "0.33.3" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.33.2" + VALUE "ProductVersion", "0.33.3" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 56dcd67fb0fb..4f240347540e 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 33 -#define ATOM_PATCH_VERSION 2 +#define ATOM_PATCH_VERSION 3 #define ATOM_VERSION_IS_RELEASE 1 From 9f30e5f52635c797f633fbbc1c4417f1fad5664b Mon Sep 17 00:00:00 2001 From: Gohy Leandre Date: Sat, 26 Sep 2015 17:23:34 +0200 Subject: [PATCH 020/738] Add ability to preload modules (--require, -r) --- atom/browser/default_app/main.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index 4d854dc35cbc..1b92685d13a2 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -13,8 +13,8 @@ app.on('window-all-closed', function() { // Parse command line options. var argv = process.argv.slice(1); -var option = { file: null, help: null, version: null, webdriver: null }; -for (var i in argv) { +var option = { file: null, help: null, version: null, webdriver: null, modules: [] }; +for (var i = 0; i < argv.length; i++) { if (argv[i] == '--version' || argv[i] == '-v') { option.version = true; break; @@ -23,6 +23,9 @@ for (var i in argv) { break; } else if (argv[i] == '--test-type=webdriver') { option.webdriver = true; + } else if (argv[i] == '--require' || argv[i] == '-r') { + option.modules.push(argv[++i]); + continue; } else if (argv[i][0] == '-') { continue; } else { @@ -212,6 +215,10 @@ app.once('ready', function() { Menu.setApplicationMenu(menu); }); +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) { @@ -253,6 +260,7 @@ if (option.file && !option.webdriver) { 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 += " -r, --require Module to preload (option can be repeated)"; helpMessage += " -h, --help Print this usage message.\n"; helpMessage += " -v, --version Print the version."; console.log(helpMessage); From 457147365af2bbd3b69a0bf35cac8ce78110b76c Mon Sep 17 00:00:00 2001 From: fscherwi Date: Sun, 27 Sep 2015 14:44:28 +0200 Subject: [PATCH 021/738] standardize package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 101fdeee257a..a125d13b68ef 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "electron", "devDependencies": { - "asar": "0.8.x", + "asar": "^0.8.0", "coffee-script": "^1.9.2", "coffeelint": "^1.9.4", "request": "*", - "runas": "3.x" + "runas": "^3.0.0" }, "private": true, "scripts": { From 397fbeae28db234b042baf144aa61f952e43d3b5 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sun, 27 Sep 2015 22:20:35 +0900 Subject: [PATCH 022/738] Update example variable name prefix (atom to electron) * Update variable name prefix as `atom` to `electron` --- docs-translations/ko-KR/api/screen.md | 10 +++++----- docs/api/screen.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs-translations/ko-KR/api/screen.md b/docs-translations/ko-KR/api/screen.md index 26975cbb1e27..5e0805749f30 100644 --- a/docs-translations/ko-KR/api/screen.md +++ b/docs-translations/ko-KR/api/screen.md @@ -6,7 +6,7 @@ `screen`은 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속 받았습니다. **참고:** 랜더러 / DevTools에선 이미 DOM 속성이 `window.screen`을 가지고 있으므로 `screen = require('screen')` 형식으로 모듈을 사용할 수 없습니다. -밑의 예제와 같이 `atomScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다. +밑의 예제와 같이 `electronScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다. 다음 예제는 화면 전체를 채우는 윈도우 창을 생성합니다: @@ -17,8 +17,8 @@ var BrowserWindow = require('browser-window'); var mainWindow; app.on('ready', function() { - var atomScreen = require('screen'); - var size = atomScreen.getPrimaryDisplay().workAreaSize; + var electronScreen = require('screen'); + var size = electronScreen.getPrimaryDisplay().workAreaSize; mainWindow = new BrowserWindow({ width: size.width, height: size.height }); }); ``` @@ -32,8 +32,8 @@ var BrowserWindow = require('browser-window'); var mainWindow; app.on('ready', function() { - var atomScreen = require('screen'); - var displays = atomScreen.getAllDisplays(); + var electronScreen = require('screen'); + var displays = electronScreen.getAllDisplays(); var externalDisplay = null; for (var i in displays) { if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) { diff --git a/docs/api/screen.md b/docs/api/screen.md index 934e3eaf5a70..da15c7326f17 100644 --- a/docs/api/screen.md +++ b/docs/api/screen.md @@ -8,7 +8,7 @@ position, etc. You should not use this module until the `ready` event of the **Note:** In the renderer / DevTools, `window.screen` is a reserved DOM property, so writing `var screen = require('screen')` will not work. In our -examples below, we use `atomScreen` as the variable name instead. +examples below, we use `electronScreen` as the variable name instead. An example of creating a window that fills the whole screen: @@ -19,8 +19,8 @@ var BrowserWindow = require('browser-window'); var mainWindow; app.on('ready', function() { - var atomScreen = require('screen'); - var size = atomScreen.getPrimaryDisplay().workAreaSize; + var electronScreen = require('screen'); + var size = electronScreen.getPrimaryDisplay().workAreaSize; mainWindow = new BrowserWindow({ width: size.width, height: size.height }); }); ``` @@ -34,8 +34,8 @@ var BrowserWindow = require('browser-window'); var mainWindow; app.on('ready', function() { - var atomScreen = require('screen'); - var displays = atomScreen.getAllDisplays(); + var electronScreen = require('screen'); + var displays = electronScreen.getAllDisplays(); var externalDisplay = null; for (var i in displays) { if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) { From fc7f4ae24be37e7414887a7540f16d4167dd3762 Mon Sep 17 00:00:00 2001 From: Robo Date: Sun, 27 Sep 2015 18:49:52 +0530 Subject: [PATCH 023/738] session: api to emulate network conditions --- atom/browser/api/atom_api_session.cc | 41 ++++++++++++++++++++++++++++ atom/browser/api/atom_api_session.h | 3 ++ docs/api/session.md | 15 ++++++++++ 3 files changed, 59 insertions(+) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 7d5f75cac09c..7bc1a2153e3f 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -19,6 +19,8 @@ #include "base/prefs/pref_service.h" #include "base/strings/string_util.h" #include "base/thread_task_runner_handle.h" +#include "brightray/browser/net/devtools_network_conditions.h" +#include "brightray/browser/net/devtools_network_controller.h" #include "chrome/common/pref_names.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" @@ -294,6 +296,43 @@ void Session::SetDownloadPath(const base::FilePath& path) { prefs::kDownloadDefaultDirectory, path); } +void Session::EnableNetworkEmulation(const mate::Dictionary& options) { + scoped_ptr conditions; + bool offline = false; + double latency, download_throughput, upload_throughput; + if (options.Get("offline", &offline) && offline) { + conditions.reset(new brightray::DevToolsNetworkConditions(offline)); + } else { + options.Get("latency", &latency); + options.Get("downloadThroughput", &download_throughput); + options.Get("uploadThroughput", &upload_throughput); + conditions.reset( + new brightray::DevToolsNetworkConditions(false, + latency, + download_throughput, + upload_throughput)); + } + auto controller = browser_context_->GetDevToolsNetworkController(); + + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&brightray::DevToolsNetworkController::SetNetworkState, + base::Unretained(controller), + std::string(), + base::Passed(&conditions))); +} + +void Session::DisableNetworkEmulation() { + scoped_ptr conditions( + new brightray::DevToolsNetworkConditions(false)); + auto controller = browser_context_->GetDevToolsNetworkController(); + + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&brightray::DevToolsNetworkController::SetNetworkState, + base::Unretained(controller), + std::string(), + base::Passed(&conditions))); +} + v8::Local Session::Cookies(v8::Isolate* isolate) { if (cookies_.IsEmpty()) { auto handle = atom::api::Cookies::Create(isolate, browser_context()); @@ -310,6 +349,8 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( .SetMethod("clearStorageData", &Session::ClearStorageData) .SetMethod("setProxy", &Session::SetProxy) .SetMethod("setDownloadPath", &Session::SetDownloadPath) + .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation) + .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation) .SetProperty("cookies", &Session::Cookies); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 14406e57af5b..68ee3634e6c4 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -20,6 +20,7 @@ class FilePath; namespace mate { class Arguments; +class Dictionary; } namespace atom { @@ -65,6 +66,8 @@ class Session: public mate::TrackableObject, void ClearStorageData(mate::Arguments* args); void SetProxy(const std::string& proxy, const base::Closure& callback); void SetDownloadPath(const base::FilePath& path); + void EnableNetworkEmulation(const mate::Dictionary& options); + void DisableNetworkEmulation(); v8::Local Cookies(v8::Isolate* isolate); // Cached object for cookies API. diff --git a/docs/api/session.md b/docs/api/session.md index 64991ab7530c..36a92f296e7f 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -191,3 +191,18 @@ proxy-uri = ["://"][":"] Sets download saving directory. By default, the download directory will be the `Downloads` under the respective app folder. + +### `session.enableNetworkEmulation(options)` + +* `options` Object + * `offline` Boolean - Whether to emulate network outage. + * `latency` Double - RTT in ms + * `downloadThroughput` Double - Download rate in Bps + * `uploadThroughput` Double - Upload rate in Bps + +Emulates network with the given configuration for the `session`. + +### `session.disableNetworkEmulation` + +Disables any network emulation already active for the `session`. Resets to +the original network configuration. From 6dcc752f6742d150ce909ffffae270355234c608 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Mon, 28 Sep 2015 02:12:47 +0300 Subject: [PATCH 024/738] Set default extension in Windows file dialog On Windows when you open the save dialog and switch the filter, the extension is supposed to change accordingly. It didn't happen with the existing code, since the existing code didn't set the default extension (should be set to the first filter). This resolves #2915. --- atom/browser/ui/file_dialog_win.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/atom/browser/ui/file_dialog_win.cc b/atom/browser/ui/file_dialog_win.cc index b169471c6e99..da00dc54e2fc 100644 --- a/atom/browser/ui/file_dialog_win.cc +++ b/atom/browser/ui/file_dialog_win.cc @@ -79,6 +79,9 @@ class FileDialog { if (!title.empty()) GetPtr()->SetTitle(base::UTF8ToUTF16(title).c_str()); + if (!filterspec.empty()) + GetPtr()->SetDefaultExtension(filterspec.front().pszSpec); + SetDefaultFolder(default_path); } From 70bdfedabf5f9e5bfb1acd89f23d1818e9538016 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Mon, 28 Sep 2015 02:41:06 +0200 Subject: [PATCH 025/738] Added text and unmodifiedtext setting when sending char type keyboard events, and made the type of the character read char16, so I can simulate char events from non-english origins. --- .../native_mate_converters/blink_converter.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/atom/common/native_mate_converters/blink_converter.cc b/atom/common/native_mate_converters/blink_converter.cc index beb60737e73f..f1fc1983de5f 100644 --- a/atom/common/native_mate_converters/blink_converter.cc +++ b/atom/common/native_mate_converters/blink_converter.cc @@ -9,6 +9,7 @@ #include "atom/common/keyboad_util.h" #include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "content/public/browser/native_web_keyboard_event.h" #include "native_mate/dictionary.h" #include "third_party/WebKit/public/web/WebDeviceEmulationParams.h" @@ -29,10 +30,10 @@ int VectorToBitArray(const std::vector& vec) { namespace mate { template<> -struct Converter { +struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Handle val, - char* out) { - std::string code = base::StringToLowerASCII(V8ToString(val)); + base::char16* out) { + base::string16 code = base::UTF8ToUTF16(V8ToString(val)); if (code.length() != 1) return false; *out = code[0]; @@ -157,16 +158,18 @@ bool Converter::FromV8( return false; if (!ConvertFromV8(isolate, val, static_cast(out))) return false; - char code; + base::char16 code; if (!dict.Get("keyCode", &code)) return false; bool shifted = false; out->windowsKeyCode = atom::KeyboardCodeFromCharCode(code, &shifted); - if (out->windowsKeyCode == ui::VKEY_UNKNOWN) - return false; if (shifted) out->modifiers |= blink::WebInputEvent::ShiftKey; out->setKeyIdentifierFromWindowsKeyCode(); + if (out->type == blink::WebInputEvent::Char || out->type == blink::WebInputEvent::RawKeyDown) { + out->text[0] = code; + out->unmodifiedText[0] = code; + } return true; } From 21cd4c14316b3a25053d1b45e8754f668a016774 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Mon, 28 Sep 2015 02:52:16 +0200 Subject: [PATCH 026/738] Added documentation about the changes --- docs/api/web-contents.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index c2dccc3a876c..b2e924e5d083 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -534,13 +534,13 @@ Sends an input `event` to the page. For keyboard events, the `event` object also have following properties: * `keyCode` String (**required**) - A single character that will be sent as - keyboard event. Can be any ASCII character on the keyboard, like `a`, `1` - and `=`. + keyboard event. Can be any UTF-8 character. For mouse events, the `event` object also have following properties: * `x` Integer (**required**) * `y` Integer (**required**) +* `button` String - The button pressed, can be `left`, `middle`, `right` * `globalX` Integer * `globalY` Integer * `movementX` Integer From 44ee74a9b13db7e0e97248dcd1c4c1291f1fe878 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Mon, 28 Sep 2015 03:05:08 +0200 Subject: [PATCH 027/738] Style fix --- atom/common/native_mate_converters/blink_converter.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/common/native_mate_converters/blink_converter.cc b/atom/common/native_mate_converters/blink_converter.cc index f1fc1983de5f..a723df1ea940 100644 --- a/atom/common/native_mate_converters/blink_converter.cc +++ b/atom/common/native_mate_converters/blink_converter.cc @@ -166,7 +166,8 @@ bool Converter::FromV8( if (shifted) out->modifiers |= blink::WebInputEvent::ShiftKey; out->setKeyIdentifierFromWindowsKeyCode(); - if (out->type == blink::WebInputEvent::Char || out->type == blink::WebInputEvent::RawKeyDown) { + if (out->type == blink::WebInputEvent::Char + || out->type == blink::WebInputEvent::RawKeyDown) { out->text[0] = code; out->unmodifiedText[0] = code; } From 82bb7905300f6bd906279df81bfe61a82d35e2da Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 28 Sep 2015 12:48:33 +0800 Subject: [PATCH 028/738] Style fix for #2918 --- atom/common/native_mate_converters/blink_converter.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/common/native_mate_converters/blink_converter.cc b/atom/common/native_mate_converters/blink_converter.cc index a723df1ea940..0a599bfdf015 100644 --- a/atom/common/native_mate_converters/blink_converter.cc +++ b/atom/common/native_mate_converters/blink_converter.cc @@ -166,8 +166,8 @@ bool Converter::FromV8( if (shifted) out->modifiers |= blink::WebInputEvent::ShiftKey; out->setKeyIdentifierFromWindowsKeyCode(); - if (out->type == blink::WebInputEvent::Char - || out->type == blink::WebInputEvent::RawKeyDown) { + if (out->type == blink::WebInputEvent::Char || + out->type == blink::WebInputEvent::RawKeyDown) { out->text[0] = code; out->unmodifiedText[0] = code; } From 442c79abe0a36d38961177e738d0ffa35cbb81d7 Mon Sep 17 00:00:00 2001 From: Robo Date: Mon, 28 Sep 2015 12:39:55 +0530 Subject: [PATCH 029/738] update brightray --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 8e443520e695..75f7d3fd88ae 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 8e443520e695674fd26585cfa24a0ec0b6140c27 +Subproject commit 75f7d3fd88ae60026a0717b93e3bf7182f827dc3 From db0732b35be691081ced67c219cb783e9ab2330a Mon Sep 17 00:00:00 2001 From: Robo Date: Mon, 28 Sep 2015 12:52:50 +0530 Subject: [PATCH 030/738] add examples --- docs/api/session.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/api/session.md b/docs/api/session.md index 36a92f296e7f..392b6826414d 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -202,6 +202,18 @@ Sets download saving directory. By default, the download directory will be the Emulates network with the given configuration for the `session`. +```javascript +// To emulate a GPRS connection with 50kbps throughput and 500 ms latency. +window.webContents.session.enableNetworkEmulation({ + latency: 500, + downloadThroughput: 6400, + uploadThroughput: 6400 +}); + +// To emulate a network outage. +window.webContents.session.enableNetworkEmulation({offline: true}); +``` + ### `session.disableNetworkEmulation` Disables any network emulation already active for the `session`. Resets to From 1b18a4dfad30a2437f72706ccee1c17a09b3683f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 28 Sep 2015 15:34:52 +0800 Subject: [PATCH 031/738] Update node, fixes #2916 --- vendor/node | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/node b/vendor/node index ac25693ad1d4..f4243f5c84a3 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit ac25693ad1d4c248e69a89147fd3995c3bf6c946 +Subproject commit f4243f5c84a371632d8d72a1a2210a0e994afdcc From 8734395358951f18d01e1e55c6915221f9f99c2b Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Mon, 28 Sep 2015 22:33:43 +0200 Subject: [PATCH 032/738] Detalied documentation about frameBuffer's format. --- docs/api/web-contents.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index b2e924e5d083..7cbf8d93ba2c 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -565,8 +565,11 @@ For the `mouseWheel` event, the `event` object also have following properties: Begin subscribing for presentation events and captured frames, the `callback` will be called with `callback(frameBuffer)` when there is a presentation event. -The `frameBuffer` is a `Buffer` that contains raw pixel data, in the format of -32bit ARGB. +The `frameBuffer` is a `Buffer` that contains raw pixel data. On most machines, +the pixel data is effectively stored in 32bit BGRA format, but the actual +representation depends on the endianness of the processor (most modern +processors are little-endian, on machines with big-endian processors the data +is in 32bit ARGB format). ### `webContents.endFrameSubscription()` From fa95d32475e30120e8d93e2dcf3a4d91f416e06c Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Tue, 29 Sep 2015 05:35:33 +0900 Subject: [PATCH 033/738] Update as upstream, small changes --- docs-translations/ko-KR/api/screen.md | 2 +- docs-translations/ko-KR/api/session.md | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/screen.md b/docs-translations/ko-KR/api/screen.md index 5e0805749f30..2d3c02f85412 100644 --- a/docs-translations/ko-KR/api/screen.md +++ b/docs-translations/ko-KR/api/screen.md @@ -6,7 +6,7 @@ `screen`은 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속 받았습니다. **참고:** 랜더러 / DevTools에선 이미 DOM 속성이 `window.screen`을 가지고 있으므로 `screen = require('screen')` 형식으로 모듈을 사용할 수 없습니다. -밑의 예제와 같이 `electronScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다. +아래의 예제와 같이 `electronScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다. 다음 예제는 화면 전체를 채우는 윈도우 창을 생성합니다: diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index 4c6ead1647ff..96d38dda5d62 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -181,3 +181,29 @@ proxy-uri = ["://"][":"] * `path` String - 다운로드 위치 다운로드 저장 위치를 지정합니다. 기본 다운로드 위치는 각 어플리케이션 데이터 디렉터리의 `Downloads` 폴더입니다. + +### `session.enableNetworkEmulation(options)` + +* `options` Object + * `offline` Boolean - 네트워크의 오프라인 상태 여부 + * `latency` Double - 밀리세컨드 단위의 RTT + * `downloadThroughput` Double - Bps 단위의 다운로드 주기 + * `uploadThroughput` Double - Bps 단위의 업로드 주기 + +제공된 설정으로 `session`의 네트워크를 에뮬레이트합니다. + +```javascript +// 50kbps의 처리량과 함께 500ms의 레이턴시로 GPRS 연결을 에뮬레이트합니다. +window.webContents.session.enableNetworkEmulation({ + latency: 500, + downloadThroughput: 6400, + uploadThroughput: 6400 +}); + +// 네트워크가 끊긴 상태를 에뮬레이트합니다. +window.webContents.session.enableNetworkEmulation({offline: true}); +``` + +### `session.disableNetworkEmulation` + +활성화된 `session`의 에뮬레이션을 비활성화합니다. 기본 네트워크 설정으로 돌아갑니다. From ee0f0f6cfcd41f3f70399922bec08d1f109317ed Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Tue, 29 Sep 2015 02:20:09 +0300 Subject: [PATCH 034/738] Fix window state events on Windows This commit fixes the issue we had with window state events not firing when triggered through Aero Snap. Instead of listening to command from the system menu (SC_MAXIMIZE etc.), we use the WM_SIZE event. This resolves #1381. --- atom/browser/native_window_views.cc | 99 ++++++++++++++++++++--------- atom/browser/native_window_views.h | 8 ++- 2 files changed, 73 insertions(+), 34 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 70707219f3f2..34c2f6226319 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -169,9 +169,6 @@ NativeWindowViews::NativeWindowViews( menu_bar_autohide_(false), menu_bar_visible_(false), menu_bar_alt_pressed_(false), -#if defined(OS_WIN) - is_minimized_(false), -#endif keyboard_event_handler_(new views::UnhandledKeyboardEventHandler), use_content_size_(false), resizable_(true) { @@ -228,6 +225,9 @@ NativeWindowViews::NativeWindowViews( window_->Init(params); + bool fullscreen = false; + options.Get(switches::kFullscreen, &fullscreen); + #if defined(USE_X11) // Start monitoring window states. window_state_watcher_.reset(new WindowStateWatcher(this)); @@ -253,8 +253,7 @@ NativeWindowViews::NativeWindowViews( } // Before the window is mapped, there is no SHOW_FULLSCREEN_STATE. - bool fullscreen = false; - if (options.Get(switches::kFullscreen, & fullscreen) && fullscreen) { + if (fullscreen) { state_atom_list.push_back(GetAtom("_NET_WM_STATE_FULLSCREEN")); } @@ -278,6 +277,12 @@ NativeWindowViews::NativeWindowViews( bounds = ContentBoundsToWindowBounds(bounds); #if defined(OS_WIN) + // Save initial window state. + if (fullscreen) + last_window_state_ = ui::SHOW_STATE_FULLSCREEN; + else + last_window_state_ = ui::SHOW_STATE_NORMAL; + if (!has_frame()) { // Set Window style so that we get a minimize and maximize animation when // frameless. @@ -391,11 +396,16 @@ bool NativeWindowViews::IsMinimized() { void NativeWindowViews::SetFullScreen(bool fullscreen) { #if defined(OS_WIN) // There is no native fullscreen state on Windows. - window_->SetFullscreen(fullscreen); - if (fullscreen) + if (fullscreen) { + last_window_state_ = ui::SHOW_STATE_FULLSCREEN; NotifyWindowEnterFullScreen(); - else + } else { + last_window_state_ = ui::SHOW_STATE_NORMAL; NotifyWindowLeaveFullScreen(); + } + // We set the new value after notifying, so we can handle the size event + // correctly. + window_->SetFullscreen(fullscreen); #else if (IsVisible()) window_->SetFullscreen(fullscreen); @@ -807,24 +817,8 @@ void NativeWindowViews::OnWidgetMove() { #if defined(OS_WIN) bool NativeWindowViews::ExecuteWindowsCommand(int command_id) { - // Windows uses the 4 lower order bits of |command_id| for type-specific - // information so we must exclude this when comparing. - static const int sc_mask = 0xFFF0; - if ((command_id & sc_mask) == SC_MINIMIZE) { - NotifyWindowMinimize(); - is_minimized_ = true; - } else if ((command_id & sc_mask) == SC_RESTORE) { - if (is_minimized_) - NotifyWindowRestore(); - else - NotifyWindowUnmaximize(); - is_minimized_ = false; - } else if ((command_id & sc_mask) == SC_MAXIMIZE) { - NotifyWindowMaximize(); - } else { - std::string command = AppCommandToString(command_id); - NotifyWindowExecuteWindowsCommand(command); - } + std::string command = AppCommandToString(command_id); + NotifyWindowExecuteWindowsCommand(command); return false; } #endif @@ -844,11 +838,54 @@ void NativeWindowViews::GetDevToolsWindowWMClass( #if defined(OS_WIN) bool NativeWindowViews::PreHandleMSG( UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) { - // Handle thumbar button click message. - if (message == WM_COMMAND && HIWORD(w_param) == THBN_CLICKED) - return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param)); - else - return false; + switch (message) { + case WM_COMMAND: + // Handle thumbar button click message. + if (HIWORD(w_param) == THBN_CLICKED) + return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param)); + return false; + case WM_SIZE: + // Handle window state change. + HandleSizeEvent(w_param, l_param); + return false; + default: + return false; + } +} + +void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) { + // Here we handle the WM_SIZE event in order to figure out what is the current + // window state and notify the user accordingly. + switch (w_param) { + case SIZE_MAXIMIZED: + last_window_state_ = ui::SHOW_STATE_MAXIMIZED; + NotifyWindowMaximize(); + break; + case SIZE_MINIMIZED: + last_window_state_ = ui::SHOW_STATE_MINIMIZED; + NotifyWindowMinimize(); + break; + case SIZE_RESTORED: + if (last_window_state_ == ui::SHOW_STATE_NORMAL) + return; + + switch (last_window_state_) { + case ui::SHOW_STATE_MAXIMIZED: + last_window_state_ = ui::SHOW_STATE_NORMAL; + NotifyWindowUnmaximize(); + break; + case ui::SHOW_STATE_MINIMIZED: + if (IsFullscreen()) { + last_window_state_ = ui::SHOW_STATE_FULLSCREEN; + NotifyWindowEnterFullScreen(); + } else { + last_window_state_ = ui::SHOW_STATE_NORMAL; + NotifyWindowRestore(); + } + break; + } + break; + } } #endif diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 355f5bd38ef3..70c722c7d9cc 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -142,6 +142,8 @@ class NativeWindowViews : public NativeWindow, // MessageHandlerDelegate: bool PreHandleMSG( UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) override; + + void HandleSizeEvent(WPARAM w_param, LPARAM l_param); #endif // NativeWindow: @@ -178,9 +180,9 @@ class NativeWindowViews : public NativeWindow, #elif defined(OS_WIN) // Weak ref. AtomDesktopWindowTreeHostWin* atom_desktop_window_tree_host_win_; - // Records window was whether restored from minimized state or maximized - // state. - bool is_minimized_; + + ui::WindowShowState last_window_state_; + // In charge of running taskbar related APIs. TaskbarHost taskbar_host_; #endif From a0dcfc57b29ec241f7da2053fc8bf3b99383c0da Mon Sep 17 00:00:00 2001 From: My-khael Pierce Date: Mon, 28 Sep 2015 23:09:13 -0400 Subject: [PATCH 035/738] Update quick-start.md --- docs/tutorial/quick-start.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index 4ce65a1dc1ae..94368df09c1c 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -143,8 +143,8 @@ working as expected. ### electron-prebuilt -If you've installed `electron-prebuilt` globally with `npm`, then you need only -run the following in your app's source directory: +If you've installed `electron-prebuilt` globally with `npm`, then you will only need +to run the following in your app's source directory: ```bash electron . @@ -158,7 +158,7 @@ If you've installed it locally, then run: ### Manually Downloaded Electron Binary -If you downloaded Electron manually, you can also just use the included +If you downloaded Electron manually, you can also use the included binary to execute your app directly. #### Windows From 464134a31ab439535fe406e90428ccca6f911de9 Mon Sep 17 00:00:00 2001 From: Robo Date: Tue, 29 Sep 2015 17:47:26 +0530 Subject: [PATCH 036/738] protocol: allowing default clients to handle external unhandled protocols --- atom/browser/atom_browser_client.cc | 9 ++++ atom/browser/atom_browser_client.h | 6 +++ ...owser_resource_dispatcher_host_delegate.cc | 54 +++++++++++++++++++ ...rowser_resource_dispatcher_host_delegate.h | 29 ++++++++++ filenames.gypi | 2 + 5 files changed, 100 insertions(+) create mode 100644 atom/browser/atom_browser_resource_dispatcher_host_delegate.cc create mode 100644 atom/browser/atom_browser_resource_dispatcher_host_delegate.h diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index e45caceab01e..dface840d721 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -11,6 +11,7 @@ #include "atom/browser/atom_access_token_store.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" +#include "atom/browser/atom_browser_resource_dispatcher_host_delegate.h" #include "atom/browser/atom_quota_permission_context.h" #include "atom/browser/atom_speech_recognition_manager_delegate.h" #include "atom/browser/browser.h" @@ -30,6 +31,7 @@ #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" +#include "content/public/browser/resource_dispatcher_host.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" #include "content/public/common/web_preferences.h" @@ -226,6 +228,13 @@ void AtomBrowserClient::SelectClientCertificate( delegate.Pass()); } +void AtomBrowserClient::ResourceDispatcherHostCreated() { + resource_dispatcher_host_delegate_.reset( + new AtomResourceDispatcherHostDelegate); + content::ResourceDispatcherHost::Get()->SetDelegate( + resource_dispatcher_host_delegate_.get()); +} + brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts( const content::MainFunctionParams&) { v8::V8::Initialize(); // Init V8 before creating main parts. diff --git a/atom/browser/atom_browser_client.h b/atom/browser/atom_browser_client.h index a0217efede9f..ee4700456cc6 100644 --- a/atom/browser/atom_browser_client.h +++ b/atom/browser/atom_browser_client.h @@ -23,6 +23,8 @@ class SSLCertRequestInfo; namespace atom { +class AtomResourceDispatcherHostDelegate; + class AtomBrowserClient : public brightray::BrowserClient, public content::RenderProcessHostObserver { public: @@ -56,6 +58,7 @@ class AtomBrowserClient : public brightray::BrowserClient, content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, scoped_ptr delegate) override; + void ResourceDispatcherHostCreated() override; // brightray::BrowserClient: brightray::BrowserMainParts* OverrideCreateBrowserMainParts( @@ -68,6 +71,9 @@ class AtomBrowserClient : public brightray::BrowserClient, // pending_render_process => current_render_process. std::map pending_processes_; + scoped_ptr + resource_dispatcher_host_delegate_; + DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient); }; diff --git a/atom/browser/atom_browser_resource_dispatcher_host_delegate.cc b/atom/browser/atom_browser_resource_dispatcher_host_delegate.cc new file mode 100644 index 000000000000..9e02f7cc8129 --- /dev/null +++ b/atom/browser/atom_browser_resource_dispatcher_host_delegate.cc @@ -0,0 +1,54 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/atom_browser_resource_dispatcher_host_delegate.h" + +#include "atom/common/platform_util.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/render_view_host.h" +#include "net/base/escape.h" + +using content::BrowserThread; + +namespace atom { + +namespace { + +void HandleExternalProtocolInUI(const GURL& url, + int render_process_id, + int render_view_id) { + auto web_contents = content::WebContents::FromRenderViewHost( + content::RenderViewHost::FromID(render_process_id, render_view_id)); + if (!web_contents) + return; + + GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); + platform_util::OpenExternal(escaped_url); +} + +} // namespace + +AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() { +} + +AtomResourceDispatcherHostDelegate::~AtomResourceDispatcherHostDelegate() { +} + +bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( + const GURL& url, + int render_process_id, + int render_view_id, + bool is_main_frame, + ui::PageTransition transition, + bool has_user_gesture) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&HandleExternalProtocolInUI, + url, + render_process_id, + render_view_id)); + return true; +} + +} // namespace atom diff --git a/atom/browser/atom_browser_resource_dispatcher_host_delegate.h b/atom/browser/atom_browser_resource_dispatcher_host_delegate.h new file mode 100644 index 000000000000..21155024c800 --- /dev/null +++ b/atom/browser/atom_browser_resource_dispatcher_host_delegate.h @@ -0,0 +1,29 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_ATOM_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ +#define ATOM_BROWSER_ATOM_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ + +#include "content/public/browser/resource_dispatcher_host_delegate.h" + +namespace atom { + +class AtomResourceDispatcherHostDelegate + : public content::ResourceDispatcherHostDelegate { + public: + AtomResourceDispatcherHostDelegate(); + ~AtomResourceDispatcherHostDelegate(); + + // content::ResourceDispatcherHostDelegate: + bool HandleExternalProtocol(const GURL& url, + int render_process_id, + int render_view_id, + bool is_main_frame, + ui::PageTransition transition, + bool has_user_gesture) override; +}; + +} // namespace atom + +#endif // ATOM_BROWSER_ATOM_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ diff --git a/filenames.gypi b/filenames.gypi index cb6a2273eae3..a571ed1caf58 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -125,6 +125,8 @@ 'atom/browser/atom_browser_main_parts.h', 'atom/browser/atom_browser_main_parts_linux.cc', 'atom/browser/atom_browser_main_parts_mac.mm', + 'atom/browser/atom_browser_resource_dispatcher_host_delegate.cc', + 'atom/browser/atom_browser_resource_dispatcher_host_delegate.h', 'atom/browser/atom_javascript_dialog_manager.cc', 'atom/browser/atom_javascript_dialog_manager.h', 'atom/browser/atom_quota_permission_context.cc', From 93f58925aa2b6e0bef2143f2ca2b8122c31f17bc Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 30 Sep 2015 10:54:18 +0900 Subject: [PATCH 037/738] Improve grammar --- docs-translations/ko-KR/tutorial/quick-start.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 4a6ce6d22523..3edf13cc4736 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -127,31 +127,31 @@ app.on('ready', function() { 앱을 작성한 후 [어플리케이션 배포](application-distribution.md) 가이드를 따라 앱을 패키징 하고 패키징한 앱을 실행할 수 있습니다. 또한 Electron 실행파일을 다운로드 받아 바로 실행해 볼 수도 있습니다. -### electron-prebuilt +### electron-prebuilt 사용 `npm`을 통해 `electron-prebuilt` 패키지를 전역에 설치하면 간단한 명령으로 앱을 실행할 수 있습니다. -앱 디렉터리 내에서 이렇게 실행합니다: +앱 디렉터리 내에서 다음 명령으로 실행할 수 있습니다: ```bash electron . ``` -또는 앱 디렉터리 밖에서 앱 디렉터리를 입력해도 됩니다: +또는 앱 디렉터리 밖에서 앱을 실행할 수도 있습니다: ```bash electron app ``` -npm 모듈을 로컬에 설치했다면 이렇게 실행할 수 있습니다: +npm 모듈을 로컬에 설치했다면 다음 명령으로 실행할 수 있습니다: ```bash ./node_modules/.bin/electron . ``` -### 임의로 다운로드 받은 Electron +### 다운로드 받은 Electron 바이너리 사용 -만약 Electron 바이너리를 임의로 다운로드 받았다면 다음과 같이 앱 디렉터리에 놓고 실행하면 됩니다. +따로 Electron 바이너리를 다운로드 받았다면 다음 예시와 같이 실행하면 됩니다. #### Windows From 21f7316a18dd62a6753b99953ca97fdc9106faea Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 30 Sep 2015 10:56:42 +0800 Subject: [PATCH 038/738] Code cleanup --- atom/browser/atom_browser_client.cc | 2 +- ...owser_resource_dispatcher_host_delegate.cc | 54 ------------------- .../atom_resource_dispatcher_host_delegate.cc | 32 +++++++++++ ... atom_resource_dispatcher_host_delegate.h} | 7 ++- filenames.gypi | 4 +- 5 files changed, 38 insertions(+), 61 deletions(-) delete mode 100644 atom/browser/atom_browser_resource_dispatcher_host_delegate.cc create mode 100644 atom/browser/atom_resource_dispatcher_host_delegate.cc rename atom/browser/{atom_browser_resource_dispatcher_host_delegate.h => atom_resource_dispatcher_host_delegate.h} (74%) diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index dface840d721..4969ce47a679 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -11,8 +11,8 @@ #include "atom/browser/atom_access_token_store.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" -#include "atom/browser/atom_browser_resource_dispatcher_host_delegate.h" #include "atom/browser/atom_quota_permission_context.h" +#include "atom/browser/atom_resource_dispatcher_host_delegate.h" #include "atom/browser/atom_speech_recognition_manager_delegate.h" #include "atom/browser/browser.h" #include "atom/browser/native_window.h" diff --git a/atom/browser/atom_browser_resource_dispatcher_host_delegate.cc b/atom/browser/atom_browser_resource_dispatcher_host_delegate.cc deleted file mode 100644 index 9e02f7cc8129..000000000000 --- a/atom/browser/atom_browser_resource_dispatcher_host_delegate.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2015 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/browser/atom_browser_resource_dispatcher_host_delegate.h" - -#include "atom/common/platform_util.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/render_view_host.h" -#include "net/base/escape.h" - -using content::BrowserThread; - -namespace atom { - -namespace { - -void HandleExternalProtocolInUI(const GURL& url, - int render_process_id, - int render_view_id) { - auto web_contents = content::WebContents::FromRenderViewHost( - content::RenderViewHost::FromID(render_process_id, render_view_id)); - if (!web_contents) - return; - - GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); - platform_util::OpenExternal(escaped_url); -} - -} // namespace - -AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() { -} - -AtomResourceDispatcherHostDelegate::~AtomResourceDispatcherHostDelegate() { -} - -bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( - const GURL& url, - int render_process_id, - int render_view_id, - bool is_main_frame, - ui::PageTransition transition, - bool has_user_gesture) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&HandleExternalProtocolInUI, - url, - render_process_id, - render_view_id)); - return true; -} - -} // namespace atom diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc new file mode 100644 index 000000000000..46904d2ff99d --- /dev/null +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -0,0 +1,32 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/atom_resource_dispatcher_host_delegate.h" + +#include "atom/common/platform_util.h" +#include "content/public/browser/browser_thread.h" +#include "net/base/escape.h" +#include "url/gurl.h" + +using content::BrowserThread; + +namespace atom { + +AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() { +} + +bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( + const GURL& url, + int render_process_id, + int render_view_id, + bool is_main_frame, + ui::PageTransition transition, + 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)); + return true; +} + +} // namespace atom diff --git a/atom/browser/atom_browser_resource_dispatcher_host_delegate.h b/atom/browser/atom_resource_dispatcher_host_delegate.h similarity index 74% rename from atom/browser/atom_browser_resource_dispatcher_host_delegate.h rename to atom/browser/atom_resource_dispatcher_host_delegate.h index 21155024c800..876554f0f964 100644 --- a/atom/browser/atom_browser_resource_dispatcher_host_delegate.h +++ b/atom/browser/atom_resource_dispatcher_host_delegate.h @@ -2,8 +2,8 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#ifndef ATOM_BROWSER_ATOM_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ -#define ATOM_BROWSER_ATOM_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ +#ifndef ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ +#define ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ #include "content/public/browser/resource_dispatcher_host_delegate.h" @@ -13,7 +13,6 @@ class AtomResourceDispatcherHostDelegate : public content::ResourceDispatcherHostDelegate { public: AtomResourceDispatcherHostDelegate(); - ~AtomResourceDispatcherHostDelegate(); // content::ResourceDispatcherHostDelegate: bool HandleExternalProtocol(const GURL& url, @@ -26,4 +25,4 @@ class AtomResourceDispatcherHostDelegate } // namespace atom -#endif // ATOM_BROWSER_ATOM_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ +#endif // ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ diff --git a/filenames.gypi b/filenames.gypi index a571ed1caf58..0e7010d7a4cf 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -125,12 +125,12 @@ 'atom/browser/atom_browser_main_parts.h', 'atom/browser/atom_browser_main_parts_linux.cc', 'atom/browser/atom_browser_main_parts_mac.mm', - 'atom/browser/atom_browser_resource_dispatcher_host_delegate.cc', - 'atom/browser/atom_browser_resource_dispatcher_host_delegate.h', 'atom/browser/atom_javascript_dialog_manager.cc', 'atom/browser/atom_javascript_dialog_manager.h', 'atom/browser/atom_quota_permission_context.cc', 'atom/browser/atom_quota_permission_context.h', + 'atom/browser/atom_resource_dispatcher_host_delegate.cc', + 'atom/browser/atom_resource_dispatcher_host_delegate.h', 'atom/browser/atom_speech_recognition_manager_delegate.cc', 'atom/browser/atom_speech_recognition_manager_delegate.h', 'atom/browser/atom_ssl_config_service.cc', From 4fdf6ceb5170c8146a1eb37559bf7a766d803ec3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 30 Sep 2015 16:58:37 +0800 Subject: [PATCH 039/738] Cache remote WebContents object of webview --- atom/renderer/lib/web-view/web-view.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 65e4501975fe..3a563101f003 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -46,6 +46,7 @@ class WebViewImpl # that we don't end up allocating a second guest. if @guestInstanceId guestViewInternal.destroyGuest @guestInstanceId + @webContents = null @guestInstanceId = undefined @beforeFirstNavigation = true @attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId = true @@ -188,6 +189,7 @@ class WebViewImpl attachWindow: (guestInstanceId) -> @guestInstanceId = guestInstanceId + @webContents = remote.getGuestWebContents @guestInstanceId return true unless @internalInstanceId guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildParams() @@ -299,7 +301,7 @@ registerWebViewElement = -> createHandler = (m) -> (args...) -> internal = v8Util.getHiddenValue this, 'internal' - remote.getGuestWebContents(internal.guestInstanceId)[m] args... + internal.webContents[m] args... proto[m] = createHandler m for m in methods window.WebView = webFrame.registerEmbedderCustomElement 'webview', From 8c3116851dcdc2eee5be766a1f889d48a88ddab2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 30 Sep 2015 17:29:38 +0800 Subject: [PATCH 040/738] Exit the process when unable to find a valid app Fixes #2583. --- atom/browser/lib/init.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index 1299364d2fa6..454baf0b8ac5 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -64,7 +64,9 @@ for packagePath in searchPaths catch e continue -throw new Error("Unable to find a valid app") unless packageJson? +unless packageJson? + process.nextTick -> process.exit 1 + throw new Error("Unable to find a valid app") # Set application's version. app.setVersion packageJson.version if packageJson.version? From d5f81357b60092edee2694975cb646651f695220 Mon Sep 17 00:00:00 2001 From: Alexander Rusakov Date: Wed, 30 Sep 2015 17:13:20 +0300 Subject: [PATCH 041/738] remove required width and height BrowserWindowOptions --- docs/api/browser-window.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index a1870bc66afd..c71cb610fc18 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -24,14 +24,13 @@ You can also create a window without chrome by using [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter). It creates a new `BrowserWindow` with native properties as set by the `options`. -Properties `width` and `height` are required. ### `new BrowserWindow(options)` `options` Object, properties: -* `width` Integer (**required**) - Window's width. -* `height` Integer (**required**) - Window's height. +* `width` Integer - Window's width. +* `height` Integer - Window's height. * `x` Integer - Window's left offset from screen. * `y` Integer - Window's top offset from screen. * `use-content-size` Boolean - The `width` and `height` would be used as web From 0fb68e8130841282d7e605d165c9d1ced84ff103 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 30 Sep 2015 23:41:23 +0800 Subject: [PATCH 042/738] Make Menu.popup accept no parameter --- atom/browser/api/lib/menu.coffee | 6 +++++- docs/api/menu.md | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/lib/menu.coffee b/atom/browser/api/lib/menu.coffee index 3595ba1fe7db..f66c1568c003 100644 --- a/atom/browser/api/lib/menu.coffee +++ b/atom/browser/api/lib/menu.coffee @@ -79,7 +79,11 @@ Menu::_init = -> v8Util.setHiddenValue group[0], 'checked', true unless checked Menu::popup = (window, x, y) -> - throw new TypeError('Invalid window') unless window?.constructor is BrowserWindow + unless window?.constructor is BrowserWindow + # Shift. + y = x + x = window + window = BrowserWindow.getFocusedWindow() if x? and y? @_popupAt(window, x, y) else diff --git a/docs/api/menu.md b/docs/api/menu.md index f48b07e7e40a..cabd04ca8550 100644 --- a/docs/api/menu.md +++ b/docs/api/menu.md @@ -237,9 +237,9 @@ Generally, the `template` is just an array of `options` for constructing a You can also attach other fields to the element of the `template` and they will become properties of the constructed menu items. -### `Menu.popup(browserWindow[, x, y])` +### `Menu.popup([browserWindow, x, y])` -* `browserWindow` BrowserWindow +* `browserWindow` BrowserWindow (optional) * `x` Number (optional) * `y` Number (**required** if `x` is used) From 83c514001ef3b7fb0cd82f7ddcef8ad704e717c7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 1 Oct 2015 11:14:19 +0800 Subject: [PATCH 043/738] Move devtools API to WebContents --- atom/browser/api/atom_api_web_contents.cc | 44 +++++++++++++++++--- atom/browser/api/atom_api_web_contents.h | 11 ++++- atom/browser/api/atom_api_window.cc | 32 +------------- atom/browser/api/atom_api_window.h | 5 --- atom/browser/api/lib/browser-window.coffee | 9 ++++ atom/browser/common_web_contents_delegate.cc | 25 +++++++++++ atom/browser/common_web_contents_delegate.h | 13 +++++- atom/browser/native_window.cc | 14 ------- atom/browser/native_window.h | 9 +--- atom/browser/native_window_observer.h | 5 --- atom/browser/native_window_views.cc | 12 ------ atom/browser/native_window_views.h | 7 ---- 12 files changed, 97 insertions(+), 89 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index bdeb4ed4f873..90c5a5146c3b 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -26,6 +26,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "brightray/browser/inspectable_web_contents.h" +#include "brightray/browser/inspectable_web_contents_view.h" #include "chrome/browser/printing/print_view_manager_basic.h" #include "chrome/browser/printing/print_preview_message_handler.h" #include "content/common/view_messages.h" @@ -228,6 +229,8 @@ WebContents::WebContents(v8::Isolate* isolate, AttachAsUserData(web_contents); InitWithWebContents(web_contents); + managed_web_contents()->GetView()->SetDelegate(this); + // Save the preferences in C++. base::DictionaryValue web_preferences; mate::ConvertFromV8(isolate, options.GetHandle(), &web_preferences); @@ -491,6 +494,28 @@ void WebContents::DidUpdateFaviconURL( Emit("page-favicon-updated", unique_urls); } +void WebContents::DevToolsFocused() { + Emit("devtools-focused"); +} + +void WebContents::DevToolsOpened() { + v8::Locker locker(isolate()); + v8::HandleScope handle_scope(isolate()); + auto handle = WebContents::CreateFrom( + isolate(), managed_web_contents()->GetDevToolsWebContents()); + devtools_web_contents_.Reset(isolate(), handle.ToV8()); + + Emit("devtools-opened"); +} + +void WebContents::DevToolsClosed() { + v8::Locker locker(isolate()); + v8::HandleScope handle_scope(isolate()); + devtools_web_contents_.Reset(); + + Emit("devtools-closed"); +} + bool WebContents::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(WebContents, message) @@ -698,10 +723,6 @@ void WebContents::InspectServiceWorker() { } } -v8::Local WebContents::Session(v8::Isolate* isolate) { - return v8::Local::New(isolate, session_); -} - void WebContents::HasServiceWorker( const base::Callback& callback) { auto context = GetServiceWorkerContext(web_contents()); @@ -893,6 +914,17 @@ v8::Local WebContents::GetWebPreferences(v8::Isolate* isolate) { return mate::ConvertToV8(isolate, *web_preferences->web_preferences()); } +v8::Local WebContents::Session(v8::Isolate* isolate) { + return v8::Local::New(isolate, session_); +} + +v8::Local WebContents::DevToolsWebContents(v8::Isolate* isolate) { + if (devtools_web_contents_.IsEmpty()) + return v8::Null(isolate); + else + return v8::Local::New(isolate, devtools_web_contents_); +} + mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( v8::Isolate* isolate) { if (template_.IsEmpty()) @@ -957,7 +989,9 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("_printToPDF", &WebContents::PrintToPDF) .SetMethod("addWorkSpace", &WebContents::AddWorkSpace) .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace) - .SetProperty("session", &WebContents::Session) + .SetProperty("session", &WebContents::Session, true) + .SetProperty("devToolsWebContents", + &WebContents::DevToolsWebContents, true) .Build()); return mate::ObjectTemplateBuilder( diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 91750ac6136c..fa32d812e684 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -83,7 +83,6 @@ class WebContents : public mate::TrackableObject, void DisableDeviceEmulation(); void InspectElement(int x, int y); void InspectServiceWorker(); - v8::Local Session(v8::Isolate* isolate); void HasServiceWorker(const base::Callback&); void UnregisterServiceWorker(const base::Callback&); void SetAudioMuted(bool muted); @@ -135,6 +134,10 @@ class WebContents : public mate::TrackableObject, // Returns the web preferences of current WebContents. v8::Local GetWebPreferences(v8::Isolate* isolate); + // Properties. + v8::Local Session(v8::Isolate* isolate); + v8::Local DevToolsWebContents(v8::Isolate* isolate); + protected: explicit WebContents(content::WebContents* web_contents); WebContents(v8::Isolate* isolate, const mate::Dictionary& options); @@ -218,6 +221,11 @@ class WebContents : public mate::TrackableObject, void PluginCrashed(const base::FilePath& plugin_path, base::ProcessId plugin_pid) override; + // brightray::InspectableWebContentsViewDelegate: + void DevToolsFocused() override; + void DevToolsOpened() override; + void DevToolsClosed() override; + private: enum Type { BROWSER_WINDOW, // Used by BrowserWindow. @@ -237,6 +245,7 @@ class WebContents : public mate::TrackableObject, IPC::Message* message); v8::Global session_; + v8::Global devtools_web_contents_; scoped_ptr guest_delegate_; diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 4d866d18503c..7536c708768a 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -184,28 +184,6 @@ void Window::OnRendererResponsive() { Emit("responsive"); } -void Window::OnDevToolsFocus() { - Emit("devtools-focused"); -} - -void Window::OnDevToolsOpened() { - v8::Locker locker(isolate()); - v8::HandleScope handle_scope(isolate()); - auto handle = WebContents::CreateFrom( - isolate(), api_web_contents_->GetDevToolsWebContents()); - devtools_web_contents_.Reset(isolate(), handle.ToV8()); - - Emit("devtools-opened"); -} - -void Window::OnDevToolsClosed() { - v8::Locker locker(isolate()); - v8::HandleScope handle_scope(isolate()); - devtools_web_contents_.Reset(); - - Emit("devtools-closed"); -} - void Window::OnExecuteWindowsCommand(const std::string& command_name) { Emit("app-command", command_name); } @@ -540,13 +518,6 @@ v8::Local Window::WebContents(v8::Isolate* isolate) { return v8::Local::New(isolate, web_contents_); } -v8::Local Window::DevToolsWebContents(v8::Isolate* isolate) { - if (devtools_web_contents_.IsEmpty()) - return v8::Null(isolate); - else - return v8::Local::New(isolate, devtools_web_contents_); -} - // static void Window::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { @@ -618,8 +589,7 @@ void Window::BuildPrototype(v8::Isolate* isolate, &Window::ShowDefinitionForSelection) #endif .SetProperty("id", &Window::ID, true) - .SetProperty("webContents", &Window::WebContents, true) - .SetProperty("devToolsWebContents", &Window::DevToolsWebContents, true); + .SetProperty("webContents", &Window::WebContents, true); } } // namespace api diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index d60bf0d87ea0..8cf26fe58e8a 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -69,9 +69,6 @@ class Window : public mate::TrackableObject, void OnWindowLeaveHtmlFullScreen() override; void OnRendererUnresponsive() override; void OnRendererResponsive() override; - void OnDevToolsFocus() override; - void OnDevToolsOpened() override; - void OnDevToolsClosed() override; void OnExecuteWindowsCommand(const std::string& command_name) override; // mate::Wrappable: @@ -150,10 +147,8 @@ class Window : public mate::TrackableObject, int32_t ID() const; v8::Local WebContents(v8::Isolate* isolate); - v8::Local DevToolsWebContents(v8::Isolate* isolate); v8::Global web_contents_; - v8::Global devtools_web_contents_; v8::Global menu_; api::WebContents* api_web_contents_; diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 2a92cfc55f88..6ffba50d34cb 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -48,6 +48,15 @@ BrowserWindow::_init = -> # Notify the creation of the window. app.emit 'browser-window-created', {}, this + # Be compatible with old APIs. + @webContents.on 'devtools-focused', => @emit 'devtools-focused' + @webContents.on 'devtools-opened', => @emit 'devtools-opened' + @webContents.on 'devtools-closed', => @emit 'devtools-closed' + Object.defineProperty this, 'devToolsWebContents', + enumerable: true, + configurable: false, + get: -> @webContents.devToolsWebContents + BrowserWindow.getFocusedWindow = -> windows = BrowserWindow.getAllWindows() return window for window in windows when window.isFocused() diff --git a/atom/browser/common_web_contents_delegate.cc b/atom/browser/common_web_contents_delegate.cc index 3cef7c6d68cc..518d4f650a63 100644 --- a/atom/browser/common_web_contents_delegate.cc +++ b/atom/browser/common_web_contents_delegate.cc @@ -21,6 +21,14 @@ #include "content/public/browser/render_view_host.h" #include "storage/browser/fileapi/isolated_context.h" +#if defined(TOOLKIT_VIEWS) +#include "atom/browser/native_window_views.h" +#endif + +#if defined(USE_X11) +#include "atom/browser/browser.h" +#endif + using content::BrowserThread; namespace atom { @@ -355,6 +363,23 @@ void CommonWebContentsDelegate::OnDevToolsAppendToFile( "DevToolsAPI.appendedToURL", &url_value, nullptr, nullptr); } +#if defined(TOOLKIT_VIEWS) +gfx::ImageSkia CommonWebContentsDelegate::GetDevToolsWindowIcon() { + if (!owner_window()) + return gfx::ImageSkia(); + return static_cast(static_cast( + owner_window()))->GetWindowAppIcon(); +} +#endif + +#if defined(USE_X11) +void CommonWebContentsDelegate::GetDevToolsWindowWMClass( + std::string* name, std::string* class_name) { + *class_name = Browser::Get()->GetName(); + *name = base::StringToLowerASCII(*class_name); +} +#endif + void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) { // Window is already in fullscreen mode, save the state. if (enter_fullscreen && owner_window_->IsFullscreen()) { diff --git a/atom/browser/common_web_contents_delegate.h b/atom/browser/common_web_contents_delegate.h index 495b5501a0d1..3a5be180dcc1 100644 --- a/atom/browser/common_web_contents_delegate.h +++ b/atom/browser/common_web_contents_delegate.h @@ -12,6 +12,7 @@ #include "brightray/browser/default_web_contents_delegate.h" #include "brightray/browser/inspectable_web_contents_impl.h" #include "brightray/browser/inspectable_web_contents_delegate.h" +#include "brightray/browser/inspectable_web_contents_view_delegate.h" namespace atom { @@ -21,7 +22,8 @@ class WebDialogHelper; class CommonWebContentsDelegate : public brightray::DefaultWebContentsDelegate, - public brightray::InspectableWebContentsDelegate { + public brightray::InspectableWebContentsDelegate, + public brightray::InspectableWebContentsViewDelegate { public: CommonWebContentsDelegate(); virtual ~CommonWebContentsDelegate(); @@ -86,6 +88,15 @@ class CommonWebContentsDelegate void DevToolsRemoveFileSystem( const base::FilePath& file_system_path) override; + // brightray::InspectableWebContentsViewDelegate: +#if defined(TOOLKIT_VIEWS) + gfx::ImageSkia GetDevToolsWindowIcon() override; +#endif +#if defined(USE_X11) + void GetDevToolsWindowWMClass( + std::string* name, std::string* class_name) override; +#endif + private: // Callback for when DevToolsSaveToFile has completed. void OnDevToolsSaveToFile(const std::string& url); diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index c3620bba7052..b3ac71d210cf 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -76,8 +76,6 @@ NativeWindow::NativeWindow( aspect_ratio_(0.0), inspectable_web_contents_(inspectable_web_contents), weak_factory_(this) { - inspectable_web_contents->GetView()->SetDelegate(this); - options.Get(switches::kFrame, &has_frame_); options.Get(switches::kTransparent, &transparent_); options.Get(switches::kEnableLargerThanScreen, &enable_larger_than_screen_); @@ -418,18 +416,6 @@ void NativeWindow::NotifyWindowExecuteWindowsCommand( OnExecuteWindowsCommand(command)); } -void NativeWindow::DevToolsFocused() { - FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus()); -} - -void NativeWindow::DevToolsOpened() { - FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened()); -} - -void NativeWindow::DevToolsClosed() { - FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed()); -} - void NativeWindow::RenderViewCreated( content::RenderViewHost* render_view_host) { if (!transparent_) diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 5c8d8c73b0fe..6350ad247c12 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -15,7 +15,6 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "brightray/browser/inspectable_web_contents_view_delegate.h" #include "content/public/browser/readback_types.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -50,8 +49,7 @@ namespace atom { struct DraggableRegion; -class NativeWindow : public content::WebContentsObserver, - public brightray::InspectableWebContentsViewDelegate { +class NativeWindow : public content::WebContentsObserver { public: using CapturePageCallback = base::Callback; @@ -234,11 +232,6 @@ class NativeWindow : public content::WebContentsObserver, NativeWindow(brightray::InspectableWebContents* inspectable_web_contents, const mate::Dictionary& options); - // brightray::InspectableWebContentsViewDelegate: - void DevToolsFocused() override; - void DevToolsOpened() override; - void DevToolsClosed() override; - // content::WebContentsObserver: void RenderViewCreated(content::RenderViewHost* render_view_host) override; void BeforeUnloadDialogCancelled() override; diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 5b0a0c56b3de..33ab1ecb6b3d 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -55,11 +55,6 @@ class NativeWindowObserver { virtual void OnWindowEnterHtmlFullScreen() {} virtual void OnWindowLeaveHtmlFullScreen() {} - // Redirect devtools events. - virtual void OnDevToolsFocus() {} - virtual void OnDevToolsOpened() {} - virtual void OnDevToolsClosed() {} - // Called when renderer is hung. virtual void OnRendererUnresponsive() {} diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 34c2f6226319..0fa2a99c27fc 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -823,18 +823,6 @@ bool NativeWindowViews::ExecuteWindowsCommand(int command_id) { } #endif -gfx::ImageSkia NativeWindowViews::GetDevToolsWindowIcon() { - return GetWindowAppIcon(); -} - -#if defined(USE_X11) -void NativeWindowViews::GetDevToolsWindowWMClass( - std::string* name, std::string* class_name) { - *class_name = Browser::Get()->GetName(); - *name = base::StringToLowerASCII(*class_name); -} -#endif - #if defined(OS_WIN) bool NativeWindowViews::PreHandleMSG( UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) { diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 70c722c7d9cc..71e122d3814f 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -131,13 +131,6 @@ class NativeWindowViews : public NativeWindow, bool ExecuteWindowsCommand(int command_id) override; #endif - // brightray::InspectableWebContentsViewDelegate: - gfx::ImageSkia GetDevToolsWindowIcon() override; -#if defined(USE_X11) - void GetDevToolsWindowWMClass( - std::string* name, std::string* class_name) override; -#endif - #if defined(OS_WIN) // MessageHandlerDelegate: bool PreHandleMSG( From f2c7943d42eb83ca81c73c619ac9e727744b8967 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 1 Oct 2015 13:45:59 +0800 Subject: [PATCH 044/738] Add WebContents.getOwnerBrowserWindow --- atom/browser/api/atom_api_web_contents.cc | 9 +++++++++ atom/browser/api/atom_api_web_contents.h | 3 +++ atom/browser/api/atom_api_window.cc | 11 +++++++++++ atom/browser/api/atom_api_window.h | 4 ++++ atom/browser/native_window.h | 4 +++- 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 90c5a5146c3b..bbe244da7e88 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -7,6 +7,7 @@ #include #include "atom/browser/api/atom_api_session.h" +#include "atom/browser/api/atom_api_window.h" #include "atom/browser/atom_browser_client.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" @@ -914,6 +915,13 @@ v8::Local WebContents::GetWebPreferences(v8::Isolate* isolate) { return mate::ConvertToV8(isolate, *web_preferences->web_preferences()); } +v8::Local WebContents::GetOwnerBrowserWindow() { + if (owner_window()) + return Window::From(isolate(), owner_window()); + else + return v8::Null(isolate()); +} + v8::Local WebContents::Session(v8::Isolate* isolate) { return v8::Local::New(isolate, session_); } @@ -981,6 +989,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency) .SetMethod("isGuest", &WebContents::IsGuest) .SetMethod("getWebPreferences", &WebContents::GetWebPreferences) + .SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow) .SetMethod("hasServiceWorker", &WebContents::HasServiceWorker) .SetMethod("unregisterServiceWorker", &WebContents::UnregisterServiceWorker) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index fa32d812e684..bbf331848c55 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -134,6 +134,9 @@ class WebContents : public mate::TrackableObject, // Returns the web preferences of current WebContents. v8::Local GetWebPreferences(v8::Isolate* isolate); + // Returns the owner window. + v8::Local GetOwnerBrowserWindow(); + // Properties. v8::Local Session(v8::Isolate* isolate); v8::Local DevToolsWebContents(v8::Isolate* isolate); diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 7536c708768a..c4beaace6728 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -92,6 +92,7 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) { web_contents->SetOwnerWindow(window_.get()); window_->InitFromOptions(options); window_->AddObserver(this); + AttachAsUserData(window_.get()); } Window::~Window() { @@ -592,6 +593,16 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetProperty("webContents", &Window::WebContents, true); } +// static +v8::Local Window::From(v8::Isolate* isolate, + NativeWindow* native_window) { + auto existing = TrackableObject::FromWrappedClass(isolate, native_window); + if (existing) + return existing->GetWrapper(isolate); + else + return v8::Null(isolate); +} + } // namespace api } // namespace atom diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 8cf26fe58e8a..d2886b5fac94 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -43,6 +43,10 @@ class Window : public mate::TrackableObject, static void BuildPrototype(v8::Isolate* isolate, v8::Local prototype); + // Returns the BrowserWindow object from |native_window|. + static v8::Local From(v8::Isolate* isolate, + NativeWindow* native_window); + NativeWindow* window() const { return window_.get(); } protected: diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 6350ad247c12..751644e4595c 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -15,6 +15,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "base/supports_user_data.h" #include "content/public/browser/readback_types.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -49,7 +50,8 @@ namespace atom { struct DraggableRegion; -class NativeWindow : public content::WebContentsObserver { +class NativeWindow : public base::SupportsUserData, + public content::WebContentsObserver { public: using CapturePageCallback = base::Callback; From 1045bbc861186a566f0d9ed2b4768a7fda23be3f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 1 Oct 2015 14:08:33 +0800 Subject: [PATCH 045/738] Do not enumerate windows in remote.getCurrentWindow --- atom/browser/lib/rpc-server.coffee | 11 ++--------- atom/renderer/api/lib/remote.coffee | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 0a28d350e8a9..149b208b409d 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -106,16 +106,9 @@ ipc.on 'ATOM_BROWSER_GLOBAL', (event, name) -> catch e event.returnValue = errorToMeta e -ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event, guestInstanceId) -> +ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event) -> try - BrowserWindow = require 'browser-window' - if guestInstanceId? - guestViewManager = require './guest-view-manager' - window = BrowserWindow.fromWebContents guestViewManager.getEmbedder(guestInstanceId) - else - window = BrowserWindow.fromWebContents event.sender - window = BrowserWindow.fromDevToolsWebContents event.sender unless window? - event.returnValue = valueToMeta event.sender, window + event.returnValue = valueToMeta event.sender, event.sender.getOwnerBrowserWindow() catch e event.returnValue = errorToMeta e diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index 00d22ab8cf6d..1f17cf340020 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -130,7 +130,7 @@ exports.require = (module) -> windowCache = null exports.getCurrentWindow = -> return windowCache if windowCache? - meta = ipc.sendSync 'ATOM_BROWSER_CURRENT_WINDOW', process.guestInstanceId + meta = ipc.sendSync 'ATOM_BROWSER_CURRENT_WINDOW' windowCache = metaToValue meta # Get current WebContents object. From ca40ea8e2fc179668b8d9c8b429a94cb0f740781 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 1 Oct 2015 14:41:01 +0800 Subject: [PATCH 046/738] Inherit owner window in devtools --- atom/browser/api/atom_api_web_contents.cc | 5 +++++ atom/browser/common_web_contents_delegate.cc | 6 +++++- atom/browser/common_web_contents_delegate.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index bbe244da7e88..f6433ca635cd 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -506,6 +506,11 @@ void WebContents::DevToolsOpened() { isolate(), managed_web_contents()->GetDevToolsWebContents()); devtools_web_contents_.Reset(isolate(), handle.ToV8()); + // Inherit owner window in devtools. + if (owner_window()) + handle->SetOwnerWindow(managed_web_contents()->GetDevToolsWebContents(), + owner_window()); + Emit("devtools-opened"); } diff --git a/atom/browser/common_web_contents_delegate.cc b/atom/browser/common_web_contents_delegate.cc index 518d4f650a63..8b7a159dd7d6 100644 --- a/atom/browser/common_web_contents_delegate.cc +++ b/atom/browser/common_web_contents_delegate.cc @@ -136,7 +136,11 @@ void CommonWebContentsDelegate::InitWithWebContents( } void CommonWebContentsDelegate::SetOwnerWindow(NativeWindow* owner_window) { - content::WebContents* web_contents = GetWebContents(); + SetOwnerWindow(GetWebContents(), owner_window); +} + +void CommonWebContentsDelegate::SetOwnerWindow( + content::WebContents* web_contents, NativeWindow* owner_window) { owner_window_ = owner_window->GetWeakPtr(); NativeWindowRelay* relay = new NativeWindowRelay(owner_window_); web_contents->SetUserData(relay->key, relay); diff --git a/atom/browser/common_web_contents_delegate.h b/atom/browser/common_web_contents_delegate.h index 3a5be180dcc1..ee18f36660ee 100644 --- a/atom/browser/common_web_contents_delegate.h +++ b/atom/browser/common_web_contents_delegate.h @@ -34,6 +34,8 @@ class CommonWebContentsDelegate // Set the window as owner window. void SetOwnerWindow(NativeWindow* owner_window); + void SetOwnerWindow(content::WebContents* web_contents, + NativeWindow* owner_window); // Destroy the managed InspectableWebContents object. void DestroyWebContents(); From ef4014e14b9344204eb0f9636cbcf0af0c284cc2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 1 Oct 2015 14:46:33 +0800 Subject: [PATCH 047/738] Don't show open dialog as sheet in devtools --- atom/renderer/lib/inspector.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/renderer/lib/inspector.coffee b/atom/renderer/lib/inspector.coffee index 126f68f9608e..5f08a2acf8d8 100644 --- a/atom/renderer/lib/inspector.coffee +++ b/atom/renderer/lib/inspector.coffee @@ -44,7 +44,7 @@ createMenu = (x, y, items, document) -> showFileChooserDialog = (callback) -> remote = require 'remote' dialog = remote.require 'dialog' - files = dialog.showOpenDialog remote.getCurrentWindow(), null + files = dialog.showOpenDialog {} callback pathToHtml5FileObject files[0] if files? pathToHtml5FileObject = (path) -> From af971a46bd125ac778faa27e2a6a6eb52d1f77a1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 1 Oct 2015 16:30:31 +0800 Subject: [PATCH 048/738] docs: Move devtools methods to WebContents --- docs/api/browser-window.md | 57 -------------------------------------- docs/api/web-contents.md | 57 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index c71cb610fc18..1a2870f205ae 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -231,18 +231,6 @@ Emitted when the window enters full screen state triggered by html api. Emitted when the window leaves full screen state triggered by html api. -### Event: 'devtools-opened' - -Emitted when DevTools is opened. - -### Event: 'devtools-closed' - -Emitted when DevTools is closed. - -### Event: 'devtools-focused' - -Emitted when DevTools is focused / opened. - ### Event: 'app-command': Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) @@ -317,16 +305,6 @@ operations will be done via it. See the [`webContents` documentation](web-contents.md) for its methods and events. -**Note:** Users should never store this object because it may become `null` -when the renderer process (web page) has crashed. - -### `win.devToolsWebContents` - -Get the `WebContents` of DevTools for this window. - -**Note:** Users should never store this object because it may become `null` -when the DevTools has been closed. - ### `win.id` The unique ID of this window. @@ -595,41 +573,6 @@ bar will become grey when set to `true`. Whether the window's document has been edited. -### `win.openDevTools([options])` - -* `options` Object (optional). Properties: - * `detach` Boolean - opens DevTools in a new window - -Opens the developer tools. - -### `win.closeDevTools()` - -Closes the developer tools. - -### `win.isDevToolsOpened()` - -Returns whether the developer tools are opened. - -### `win.toggleDevTools()` - -Toggles the developer tools. - -### `win.isDevToolsFocused()` - -Returns whether the developer tools is focused. - -### `win.inspectElement(x, y)` - -* `x` Integer -* `y` Integer - -Starts inspecting element at position (`x`, `y`). - -### `win.inspectServiceWorker()` - -Opens the developer tools for the service worker context present in the web -contents. - ### `win.focusOnWebView()` ### `win.blurWebView()` diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 7cbf8d93ba2c..08670bad9df7 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -154,6 +154,18 @@ Emitted when a plugin process has crashed. Emitted when `webContents` is destroyed. +### Event: 'devtools-opened' + +Emitted when DevTools is opened. + +### Event: 'devtools-closed' + +Emitted when DevTools is closed. + +### Event: 'devtools-focused' + +Emitted when DevTools is focused / opened. + ## Instance Methods The `webContents` object has the following instance methods: @@ -441,6 +453,40 @@ Adds the specified path to DevTools workspace. Removes the specified path from DevTools workspace. +### `webContents.openDevTools([options])` + +* `options` Object (optional). Properties: + * `detach` Boolean - opens DevTools in a new window + +Opens the developer tools. + +### `webContents.closeDevTools()` + +Closes the developer tools. + +### `webContents.isDevToolsOpened()` + +Returns whether the developer tools are opened. + +### `webContents.toggleDevTools()` + +Toggles the developer tools. + +### `webContents.isDevToolsFocused()` + +Returns whether the developer tools is focused. + +### `webContents.inspectElement(x, y)` + +* `x` Integer +* `y` Integer + +Starts inspecting element at position (`x`, `y`). + +### `webContents.inspectServiceWorker()` + +Opens the developer tools for the service worker context. + ### `webContents.send(channel[, args...])` * `channel` String @@ -574,3 +620,14 @@ is in 32bit ARGB format). ### `webContents.endFrameSubscription()` End subscribing for frame presentation events. + +## Instance Properties + +`WebContents` objects also have the following properties: + +### `webContents.devToolsWebContents` + +Get the `WebContents` of DevTools for this `WebContents`. + +**Note:** Users should never store this object because it may become `null` +when the DevTools has been closed. From 6082b83a6522cd68ca5934f4bd50e69461cd1838 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 1 Oct 2015 17:03:45 +0800 Subject: [PATCH 049/738] Update brightray for #2851 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 75f7d3fd88ae..6cbb4ad4d173 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 75f7d3fd88ae60026a0717b93e3bf7182f827dc3 +Subproject commit 6cbb4ad4d173d25b66eecf675c2b25ee64196429 From 63c065299a61a4133f801d08dfd2c0f3381d92c4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 1 Oct 2015 17:31:44 +0800 Subject: [PATCH 050/738] Update brightray for atom/brightray#147 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 6cbb4ad4d173..a4b793cf32ff 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 6cbb4ad4d173d25b66eecf675c2b25ee64196429 +Subproject commit a4b793cf32ff550f7fff87148464d4d02afa880b From 8d61531f4e344a9244305e5d0832d8cf536bbfb2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 1 Oct 2015 17:46:11 +0800 Subject: [PATCH 051/738] Revert #2879 --- atom/browser/native_window.cc | 7 +------ atom/browser/native_window_mac.mm | 4 ---- atom/browser/native_window_views.cc | 3 --- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index b3ac71d210cf..80a7d1347f3e 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -158,13 +158,8 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { // Then show it. bool show = true; options.Get(switches::kShow, &show); - if (show) { + if (show) Show(); - } else { - // When RenderView is created it sets to visible, this is to prevent - // breaking the visibility API. - web_contents()->WasHidden(); - } } void NativeWindow::SetSize(const gfx::Size& size) { diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index f0a685e4d952..3e8dab2133c9 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -470,8 +470,6 @@ bool NativeWindowMac::IsFocused() { } void NativeWindowMac::Show() { - web_contents()->WasShown(); - // This method is supposed to put focus on window, however if the app does not // have focus then "makeKeyAndOrderFront" will only show the window. [NSApp activateIgnoringOtherApps:YES]; @@ -480,13 +478,11 @@ void NativeWindowMac::Show() { } void NativeWindowMac::ShowInactive() { - web_contents()->WasShown(); [window_ orderFrontRegardless]; } void NativeWindowMac::Hide() { [window_ orderOut:nil]; - web_contents()->WasHidden(); } bool NativeWindowMac::IsVisible() { diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 0fa2a99c27fc..e9db97e195d1 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -343,17 +343,14 @@ bool NativeWindowViews::IsFocused() { } void NativeWindowViews::Show() { - web_contents()->WasShown(); window_->native_widget_private()->ShowWithWindowState(GetRestoredState()); } void NativeWindowViews::ShowInactive() { - web_contents()->WasShown(); window_->ShowInactive(); } void NativeWindowViews::Hide() { - window_->Hide(); web_contents()->WasHidden(); } From 5d9e4fc8fd98360e22ce4725174c07592e5e3ad0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 1 Oct 2015 18:39:35 +0800 Subject: [PATCH 052/738] Override document.hidden --- atom/renderer/lib/override.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/atom/renderer/lib/override.coffee b/atom/renderer/lib/override.coffee index 5cffdd486d9c..93cf8b8357e8 100644 --- a/atom/renderer/lib/override.coffee +++ b/atom/renderer/lib/override.coffee @@ -122,3 +122,7 @@ window.history.go = (offset) -> sendHistoryOperation 'goToOffset', offset Object.defineProperty window.history, 'length', get: -> getHistoryOperation 'length' + +# Make document.hidden return the correct value. +Object.defineProperty document, 'hidden', + get: -> !remote.getCurrentWindow().isVisible() From c1fba9b4a5c90a7afe001a02629be703c4d6a1c1 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 2 Oct 2015 12:46:42 +0900 Subject: [PATCH 053/738] Update as upstream --- docs-translations/ko-KR/api/menu.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs-translations/ko-KR/api/menu.md b/docs-translations/ko-KR/api/menu.md index a8ac499f5768..56b7f4a198e5 100644 --- a/docs-translations/ko-KR/api/menu.md +++ b/docs-translations/ko-KR/api/menu.md @@ -229,11 +229,11 @@ Menu.setApplicationMenu(menu); 또한 `template`에는 다른 속성도 추가할 수 있으며 메뉴가 만들어질 때 해당 메뉴 아이템의 프로퍼티로 변환됩니다. -### `Menu.popup(browserWindow[, x, y])` +### `Menu.popup([browserWindow, x, y])` -* `browserWindow` BrowserWindow +* `browserWindow` BrowserWindow (optional) * `x` Number (optional) -* `y` Number (만약 `x`를 지정했을 경우 `y`도 필수로 지정해야 합니다) +* `y` Number (만약 `x`를 지정했을 경우 반드시 `y`도 지정해야 합니다) 메뉴를 `browserWindow` 내부 팝업으로 표시합니다. 옵션으로 메뉴를 표시할 `(x,y)` 좌표를 지정할 수 있습니다. From 9eb7c3ac2d6653834803f91ad3f643f30df9eab5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 2 Oct 2015 13:41:50 +0800 Subject: [PATCH 054/738] Bump v0.33.4 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 2 +- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- vendor/brightray | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/atom.gyp b/atom.gyp index 42069ea84621..b3c9e117a505 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.3', + 'version%': '0.33.4', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index eb39cb35f947..b1b905a43332 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,7 +17,7 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.3 + 0.33.4 LSMinimumSystemVersion 10.8.0 NSMainNibFile diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 6fba6cf80676..6d900b0ea017 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,33,3,0 - PRODUCTVERSION 0,33,3,0 + FILEVERSION 0,33,4,0 + PRODUCTVERSION 0,33,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.3" + VALUE "FileVersion", "0.33.4" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.33.3" + VALUE "ProductVersion", "0.33.4" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 4f240347540e..998e43088122 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 33 -#define ATOM_PATCH_VERSION 3 +#define ATOM_PATCH_VERSION 4 #define ATOM_VERSION_IS_RELEASE 1 diff --git a/vendor/brightray b/vendor/brightray index a4b793cf32ff..6cbb4ad4d173 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit a4b793cf32ff550f7fff87148464d4d02afa880b +Subproject commit 6cbb4ad4d173d25b66eecf675c2b25ee64196429 From 0ecf077590ef64e88a31fff81fe50590a8c42c82 Mon Sep 17 00:00:00 2001 From: Jhen Date: Fri, 2 Oct 2015 21:53:55 +0800 Subject: [PATCH 055/738] Fix typo for docs/api/menu-item.md --- docs/api/menu-item.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/menu-item.md b/docs/api/menu-item.md index 89524d9f2352..37079233fc0c 100644 --- a/docs/api/menu-item.md +++ b/docs/api/menu-item.md @@ -1,6 +1,6 @@ # MenuItem -The `menu-item` module allows you to add items to an application or content +The `menu-item` module allows you to add items to an application or context [`menu`](menu.md). See [`menu`](menu.md) for examples. From 64640afc20bba0e6474a3bb2b61c0d72a379185c Mon Sep 17 00:00:00 2001 From: Raphael Date: Fri, 2 Oct 2015 17:41:57 -0700 Subject: [PATCH 056/738] supported operating system list Proposed fix for issue #2964 --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 0bf29fbc3e31..ccfc9cf2009c 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,12 @@ npm install electron-prebuilt --save-dev - [China](https://npm.taobao.org/mirrors/electron) +## Supported Operating Systems + +- Ubuntu: 14.04 and higher +- Mac: OS X 10.8.0 and higher +- Windows: Win7 or higher + ## Documentation Guides and the API reference are located in the @@ -53,6 +59,7 @@ contains documents describing how to build and contribute to Electron. - [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN) - [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW) + ## Community You can ask questions and interact with the community in the following From 651009a1dc4cfe901a24ca829413719e906fb00e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 3 Oct 2015 13:42:34 +0800 Subject: [PATCH 057/738] docs: Add "Supported Platforms" --- README.md | 15 ++++----------- docs/README.md | 1 + docs/tutorial/supported-platforms.md | 23 +++++++++++++++++++++++ 3 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 docs/tutorial/supported-platforms.md diff --git a/README.md b/README.md index ccfc9cf2009c..fa122c9b6c6f 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important announcements. This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0). -By participating, you are expected to uphold this code. Please report +By participating, you are expected to uphold this code. Please report unacceptable behavior to atom@github.com. ## Downloads @@ -38,12 +38,6 @@ npm install electron-prebuilt --save-dev - [China](https://npm.taobao.org/mirrors/electron) -## Supported Operating Systems - -- Ubuntu: 14.04 and higher -- Mac: OS X 10.8.0 and higher -- Windows: Win7 or higher - ## Documentation Guides and the API reference are located in the @@ -59,15 +53,14 @@ contains documents describing how to build and contribute to Electron. - [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN) - [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW) - ## Community -You can ask questions and interact with the community in the following +You can ask questions and interact with the community in the following locations: -- [`electron`](http://discuss.atom.io/category/electron) category on the Atom +- [`electron`](http://discuss.atom.io/category/electron) category on the Atom forums - `#atom-shell` channel on Freenode - [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack -Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron) +Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron) for a community maintained list of useful example apps, tools and resources. diff --git a/docs/README.md b/docs/README.md index b2f95fe4b579..eb6e9d6e36f0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,5 +1,6 @@ ## Guides +* [Supported Platforms](tutorial/supported-platforms.md) * [Application Distribution](tutorial/application-distribution.md) * [Application Packaging](tutorial/application-packaging.md) * [Using Native Node Modules](tutorial/using-native-node-modules.md) diff --git a/docs/tutorial/supported-platforms.md b/docs/tutorial/supported-platforms.md new file mode 100644 index 000000000000..8b795769a878 --- /dev/null +++ b/docs/tutorial/supported-platforms.md @@ -0,0 +1,23 @@ +# Supported Platforms + +Following platforms are supported by Electron: + +### OS X + +Only 64bit binaries are provided for OS X, and the minimum OS X version supported is OS X 10.8. + +### Windows + +Windows 7 and later are supported, Electron should be able to run on Windows Vista, but there is no testing done on it. + +Both `x86` and `x64` binaries are provided for Windows, and `ARM` version of Windows is not supported for now. + +### Linux + +The prebuilt `ia32`(`i686`) and `x64`(`amd64`) binaries of Electron are built on Ubuntu 12.04, the `arm` binary is built against ARM v7 with hard-float ABI and NEON for Debian Wheezy. + +Whether the prebuilt binary can run on a distribution depends on whether the distribution includes the libraries that Electron is linked to on the building platform, so only Ubuntu 12.04 is guaranteed to work, but following platforms are also verified to be able to run the prebuilt binaries of Electron: + +* Ubuntu 12.04 and later +* Fedora 21 +* Debian 8 From 0f9f8e62fc801b724278b45a61a5c7f6828ca204 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 3 Oct 2015 13:53:52 +0800 Subject: [PATCH 058/738] docs: No leading slash in --url-base Fixes #2968. --- 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 ebc6d2fa7801..b87f8f11dac9 100644 --- a/docs/tutorial/using-selenium-and-webdriver.md +++ b/docs/tutorial/using-selenium-and-webdriver.md @@ -74,7 +74,7 @@ driver. First you need to download the `chromedriver` binary, and run it: ```bash -$ chromedriver --url-base=/wd/hub --port=9515 +$ chromedriver --url-base=wd/hub --port=9515 Starting ChromeDriver (v2.10.291558) on port 9515 Only local connections are allowed. ``` From 3503b62ff290f7897ca1f0cf304dbc6b630152c0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 3 Oct 2015 15:33:55 +0800 Subject: [PATCH 059/738] Disable logging unless --enable-logging is specified --- atom/app/atom_main_delegate.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 3c7d6b2e7034..fe3c0e09ae33 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -27,10 +27,10 @@ AtomMainDelegate::~AtomMainDelegate() { } bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { - // Disable logging out to debug.log on Windows logging::LoggingSettings settings; #if defined(OS_WIN) #if defined(DEBUG) + // Print logging to debug.log on Windows settings.logging_dest = logging::LOG_TO_ALL; settings.log_file = L"debug.log"; settings.lock_log = logging::LOCK_LOG_FILE; @@ -41,6 +41,12 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { #else // defined(OS_WIN) settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; #endif // !defined(OS_WIN) + + // Only enable logging when --enable-logging is specified. + auto command_line = base::CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(switches::kEnableLogging)) + settings.logging_dest = logging::LOG_NONE; + logging::InitLogging(settings); // Logging with pid and timestamp. From 55acdcb1ad3e999f9f0ac5cd115203216ed25989 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 3 Oct 2015 15:43:26 +0800 Subject: [PATCH 060/738] docs: --enable-logging --- docs/api/chrome-command-line-switches.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index cd633fc0460c..c2a39126f63e 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -89,15 +89,21 @@ Enables net log events to be saved and writes them to `path`. ## --ssl-version-fallback-min=`version` -Set the minimum SSL/TLS version ("tls1", "tls1.1" or "tls1.2") that TLS +Sets the minimum SSL/TLS version ("tls1", "tls1.1" or "tls1.2") that TLS fallback will accept. +## --enable-logging + +Prints Chromium's logging into console. + +This switch can not be used in `app.commandLine.appendSwitch` since it is parsed earlier than user's app is loaded. + ## --v=`log_level` Gives the default maximal active V-logging level; 0 is the default. Normally positive values are used for V-logging levels. -Passing `--v=-1` will disable logging. +This switch only works when `--enable-logging` is also passed. ## --vmodule=`pattern` @@ -109,10 +115,4 @@ Any pattern containing a forward or backward slash will be tested against the whole pathname and not just the module. E.g. `*/foo/bar/*=2` would change the logging level for all code in the source files under a `foo/bar` directory. -To disable all chromium related logs and only enable your application logs you -can do: - -```javascript -app.commandLine.appendSwitch('v', -1); -app.commandLine.appendSwitch('vmodule', 'console=0'); -``` +This switch only works when `--enable-logging` is also passed. From b78bb8442406cd6df63966b851ab59928dd92b3a Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sat, 3 Oct 2015 17:54:05 +0900 Subject: [PATCH 061/738] Update as upstream --- docs-translations/ko-KR/README.md | 1 + .../ko-KR/api/chrome-command-line-switches.md | 18 ++++++------- docs-translations/ko-KR/api/menu-item.md | 2 +- .../ko-KR/tutorial/supported-platforms.md | 26 +++++++++++++++++++ .../tutorial/using-selenium-and-webdriver.md | 2 +- 5 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 docs-translations/ko-KR/tutorial/supported-platforms.md diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index 1e0ba63e7b6d..9b88aa6e1780 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -1,5 +1,6 @@ ## 개발 가이드 +* [지원하는 플랫폼](tutorial/supported-platforms.md) * [어플리케이션 배포](tutorial/application-distribution.md) * [어플리케이션 패키징](tutorial/application-packaging.md) * [네이티브 Node 모듈 사용하기](tutorial/using-native-node-modules.md) diff --git a/docs-translations/ko-KR/api/chrome-command-line-switches.md b/docs-translations/ko-KR/api/chrome-command-line-switches.md index 2d9158fcc2f4..777ce4612d17 100644 --- a/docs-translations/ko-KR/api/chrome-command-line-switches.md +++ b/docs-translations/ko-KR/api/chrome-command-line-switches.md @@ -84,13 +84,19 @@ Net log 이벤트를 활성화하고 `path`에 로그를 기록합니다. ## --ssl-version-fallback-min=`version` -Fallback SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", "tls1.2") +TLS fallback에서 사용할 SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", "tls1.2") + +## --enable-logging + +Chromium의 로그를 콘솔에 출력합니다. + +이 스위치는 어플리케이션이 로드되기 전에 파싱 되므로 `app.commandLine.appendSwitch`에서 사용할 수 없습니다. ## --v=`log_level` 기본 V-logging 최대 활성화 레벨을 지정합니다. 기본값은 0입니다. 기본적으로 양수를 레벨로 사용합니다. -`--v=-1`를 사용하면 로깅이 비활성화 됩니다. +이 스위치는 `--enable-logging` 스위치를 같이 지정해야 작동합니다. ## --vmodule=`pattern` @@ -100,10 +106,4 @@ Fallback SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", "tls1.2") 또한 슬래시(`/`) 또는 백슬래시(`\`)를 포함하는 패턴은 지정한 경로에 대해 패턴을 테스트 합니다. 예를 들어 `*/foo/bar/*=2` 표현식은 `foo/bar` 디렉터리 안의 모든 소스 코드의 로깅 레벨을 2로 지정합니다. -모든 크로미움과 관련된 로그를 비활성화하고 어플리케이션의 로그만 활성화 하려면 다음과 같이 코드를 작성하면 됩니다: - - -```javascript -app.commandLine.appendSwitch('v', -1); -app.commandLine.appendSwitch('vmodule', 'console=0'); -``` +이 스위치는 `--enable-logging` 스위치를 같이 지정해야 작동합니다. diff --git a/docs-translations/ko-KR/api/menu-item.md b/docs-translations/ko-KR/api/menu-item.md index 8f1021009954..e4c5c677676d 100644 --- a/docs-translations/ko-KR/api/menu-item.md +++ b/docs-translations/ko-KR/api/menu-item.md @@ -1,6 +1,6 @@ # MenuItem -`menu-item` 모듈은 어플리케이션 또는 컨텐츠 [`menu`](menu.md)에 아이템을 추가할 수 있도록 관련 클래스를 제공합니다. +`menu-item` 모듈은 어플리케이션 또는 컨텍스트 [`menu`](menu.md)에 아이템을 추가할 수 있도록 관련 클래스를 제공합니다. [`menu`](menu.md)에서 예제를 확인할 수 있습니다. diff --git a/docs-translations/ko-KR/tutorial/supported-platforms.md b/docs-translations/ko-KR/tutorial/supported-platforms.md new file mode 100644 index 000000000000..7a35da0c129a --- /dev/null +++ b/docs-translations/ko-KR/tutorial/supported-platforms.md @@ -0,0 +1,26 @@ +# 지원하는 플랫폼 + +Electron에선 다음과 같은 플랫폼을 지원합니다: + +### OS X + +OS X는 64비트 바이너리만 제공됩니다. 그리고 최소 OS X 지원 버전은 10.8입니다. + +### Windows + +Windows 7 이후 버전만 지원됩니다. Windows Vista에서도 작동할 수 있지만 아직 모든 작동 테스트가 완료되지 않았습니다. + +윈도우용 바이너리는 `x86`과 `x64` 모두 제공됩니다. 그리고 `ARM` 버전 윈도우는 아직 지원하지 않습니다. (역주: 추후 지원할 가능성이 있습니다) + +### Linux + +Ubuntu 12.04 버전에서 빌드된 `ia32`(`i686`), `x64`(`amd64`) 바이너리가 제공됩니다. +그리고 `arm` 버전 바이너리는 ARM v7 hard-float ABI와 Debian Wheezy용 NEON에 맞춰 제공됩니다. + +미리 빌드된 바이너리가 배포판에서 작동할 수 있는지 여부는 Electron이 빌드된 플랫폼에서 링크된 라이브러리에 따라 달라집니다. +그래서 현재 Linux 바이너리는 Ubuntu 12.04 버전만 정상적인 작동이 보장됩니다. +하지만 다음 플랫폼들은 미리 빌드된 Electron 바이너리가 정상적으로 작동하는 것을 확인했습니다: + +* Ubuntu 12.04 이후 버전 +* Fedora 21 +* Debian 8 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 33dc6311ce35..a9fd84a68bc2 100644 --- a/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md +++ b/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md @@ -71,7 +71,7 @@ driver.quit(); 먼저, `chromedriver` 바이너리를 다운로드 받고 실행합니다: ```bash -$ chromedriver --url-base=/wd/hub --port=9515 +$ chromedriver --url-base=wd/hub --port=9515 Starting ChromeDriver (v2.10.291558) on port 9515 Only local connections are allowed. ``` From 021ee20400ea4636090fb41213f3dcfd1770edf6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 3 Oct 2015 17:52:46 +0800 Subject: [PATCH 062/738] No need to add "app" to search paths --- atom/renderer/lib/init.coffee | 3 --- 1 file changed, 3 deletions(-) diff --git a/atom/renderer/lib/init.coffee b/atom/renderer/lib/init.coffee index 274c50ec5f39..ff9b12ecbf3c 100644 --- a/atom/renderer/lib/init.coffee +++ b/atom/renderer/lib/init.coffee @@ -11,9 +11,6 @@ process.argv.splice 1, 1 # of Atom's built-in libraries. globalPaths = Module.globalPaths globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') -# And also app. -globalPaths.push path.join(process.resourcesPath, 'app') -globalPaths.push path.join(process.resourcesPath, 'app.asar') # Import common settings. require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') From 9fe326ebeb43ffb2c955945ca8b4a2135efb08c2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 3 Oct 2015 19:55:59 +0800 Subject: [PATCH 063/738] Clear node's global search paths --- atom/browser/lib/init.coffee | 6 +++--- atom/common/lib/init.coffee | 13 ++----------- atom/renderer/lib/init.coffee | 6 +++--- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index 454baf0b8ac5..44ae29522ebf 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -7,14 +7,14 @@ Module = require 'module' # we need to restore it here. process.argv.splice 1, 1 +# Import common settings. +require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') + # Add browser/api/lib to module search paths, which contains javascript part of # Electron's built-in libraries. globalPaths = Module.globalPaths globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') -# Import common settings. -require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') - if process.platform is 'win32' # Redirect node's console to use our own implementations, since node can not # handle console output when running as GUI program. diff --git a/atom/common/lib/init.coffee b/atom/common/lib/init.coffee index acb635edeaa4..2bfea3d72afa 100644 --- a/atom/common/lib/init.coffee +++ b/atom/common/lib/init.coffee @@ -9,18 +9,9 @@ process.atomBinding = (name) -> catch e process.binding "atom_common_#{name}" if /No such module/.test e.message -# Global module search paths. +# Clear node's global search paths. globalPaths = Module.globalPaths - -# Don't lookup modules in user-defined search paths, see http://git.io/vf8sF. -homeDir = - if process.platform is 'win32' - process.env.USERPROFILE - else - process.env.HOME -if homeDir # Node only add user-defined search paths when $HOME is defined. - userModulePath = path.resolve homeDir, '.node_modules' - globalPaths.splice globalPaths.indexOf(userModulePath), 2 +globalPaths.length = 0 # Add common/api/lib to module search paths. globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') diff --git a/atom/renderer/lib/init.coffee b/atom/renderer/lib/init.coffee index ff9b12ecbf3c..e5173fcd1ec8 100644 --- a/atom/renderer/lib/init.coffee +++ b/atom/renderer/lib/init.coffee @@ -7,14 +7,14 @@ Module = require 'module' # atom-renderer.js, we need to restore it here. process.argv.splice 1, 1 +# Import common settings. +require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') + # Add renderer/api/lib to require's search paths, which contains javascript part # of Atom's built-in libraries. globalPaths = Module.globalPaths globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') -# Import common settings. -require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') - # The global variable will be used by ipc for event dispatching v8Util = process.atomBinding 'v8_util' v8Util.setHiddenValue global, 'ipc', new events.EventEmitter From 01d2765e4b566df853cd583006ebc7993d48cd38 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 3 Oct 2015 20:38:39 +0800 Subject: [PATCH 064/738] Prevent Node from adding paths outside this app to search paths --- atom/browser/lib/init.coffee | 3 +++ atom/common/lib/init.coffee | 6 +---- atom/common/lib/reset-search-paths.coffee | 29 +++++++++++++++++++++++ atom/renderer/lib/init.coffee | 3 +++ filenames.gypi | 1 + 5 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 atom/common/lib/reset-search-paths.coffee diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index 44ae29522ebf..b394c0fecc28 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -7,6 +7,9 @@ Module = require 'module' # we need to restore it here. process.argv.splice 1, 1 +# Clear search paths. +require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths') + # Import common settings. require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') diff --git a/atom/common/lib/init.coffee b/atom/common/lib/init.coffee index 2bfea3d72afa..1c80e6171a4d 100644 --- a/atom/common/lib/init.coffee +++ b/atom/common/lib/init.coffee @@ -9,12 +9,8 @@ process.atomBinding = (name) -> catch e process.binding "atom_common_#{name}" if /No such module/.test e.message -# Clear node's global search paths. -globalPaths = Module.globalPaths -globalPaths.length = 0 - # Add common/api/lib to module search paths. -globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') +Module.globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') # setImmediate and process.nextTick makes use of uv_check and uv_prepare to # run the callbacks, however since we only run uv loop on requests, the diff --git a/atom/common/lib/reset-search-paths.coffee b/atom/common/lib/reset-search-paths.coffee new file mode 100644 index 000000000000..7061103306aa --- /dev/null +++ b/atom/common/lib/reset-search-paths.coffee @@ -0,0 +1,29 @@ +path = require 'path' +Module = require 'module' + +# Clear Node's global search paths. +Module.globalPaths.length = 0 + +# Clear current and parent(init.coffee)'s search paths. +module.paths = [] +module.parent.paths = [] + +# Prevent Node from adding paths outside this app to search paths. +Module._nodeModulePaths = (from) -> + from = path.resolve from + + # If "from" is outside the app then we do nothing. + skipOutsidePaths = from.startsWith process.resourcesPath + + # Following logoic is copied from module.js. + splitRe = if process.platform is 'win32' then /[\/\\]/ else /\// + paths = [] + + parts = from.split splitRe + for part, tip in parts by -1 + continue if part is 'node_modules' + dir = parts.slice(0, tip + 1).join path.sep + break if skipOutsidePaths and not dir.startsWith process.resourcesPath + paths.push path.join(dir, 'node_modules') + + paths diff --git a/atom/renderer/lib/init.coffee b/atom/renderer/lib/init.coffee index e5173fcd1ec8..b7224b39aeed 100644 --- a/atom/renderer/lib/init.coffee +++ b/atom/renderer/lib/init.coffee @@ -7,6 +7,9 @@ Module = require 'module' # atom-renderer.js, we need to restore it here. process.argv.splice 1, 1 +# Clear search paths. +require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths') + # Import common settings. require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') diff --git a/filenames.gypi b/filenames.gypi index 0e7010d7a4cf..000633fb96b1 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -37,6 +37,7 @@ 'atom/common/api/lib/native-image.coffee', 'atom/common/api/lib/shell.coffee', 'atom/common/lib/init.coffee', + 'atom/common/lib/reset-search-paths.coffee', 'atom/renderer/lib/chrome-api.coffee', 'atom/renderer/lib/init.coffee', 'atom/renderer/lib/inspector.coffee', From bb938b02d8f3b32079c4d555e50df6b9647df43b Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Sat, 3 Oct 2015 09:02:50 -0700 Subject: [PATCH 065/738] Remove Vista as possibly working Vista crashes on startup because Win7 touch APIs aren't present - this is fine, but we want to tell people out of the gate that it won't work --- docs/tutorial/supported-platforms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/supported-platforms.md b/docs/tutorial/supported-platforms.md index 8b795769a878..f74ccf2ec258 100644 --- a/docs/tutorial/supported-platforms.md +++ b/docs/tutorial/supported-platforms.md @@ -8,9 +8,9 @@ Only 64bit binaries are provided for OS X, and the minimum OS X version supporte ### Windows -Windows 7 and later are supported, Electron should be able to run on Windows Vista, but there is no testing done on it. +Windows 7 and later are supported, older operating systems are not supported (and do not work). -Both `x86` and `x64` binaries are provided for Windows, and `ARM` version of Windows is not supported for now. +Both `x86` and `amd64` (x64) binaries are provided for Windows, and `ARM` version of Windows is not supported for now. ### Linux From b4ec7c5aaf09d7125124658f269954cacc1765c0 Mon Sep 17 00:00:00 2001 From: chriswmercer Date: Sat, 3 Oct 2015 18:03:49 +0100 Subject: [PATCH 066/738] Minor grammar correction --- docs/tutorial/supported-platforms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/supported-platforms.md b/docs/tutorial/supported-platforms.md index 8b795769a878..ec0f3ef6a11c 100644 --- a/docs/tutorial/supported-platforms.md +++ b/docs/tutorial/supported-platforms.md @@ -10,7 +10,7 @@ Only 64bit binaries are provided for OS X, and the minimum OS X version supporte Windows 7 and later are supported, Electron should be able to run on Windows Vista, but there is no testing done on it. -Both `x86` and `x64` binaries are provided for Windows, and `ARM` version of Windows is not supported for now. +Both `x86` and `x64` binaries are provided for Windows. Please note, the `ARM` version of Windows is not supported for now. ### Linux From aea1f8aebb8faf71c2c54c815b72ad9a8c21a88e Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 3 Oct 2015 22:09:57 +0300 Subject: [PATCH 067/738] Fix calculating min/max size in frameless views The minimum and maximum size that frameless windows had used, was incorrect. It included the border, so when it was called it actually added that to the size, so window increased in size. The fix makes sure that the view will use the frameless size. This fixes #2945 and partially fixes #1806 (it also refers to some other issues with hidpi which might still exist). --- atom/browser/native_window_views.cc | 29 +++++++++++++++++++++++-- atom/browser/native_window_views.h | 2 ++ atom/browser/ui/views/frameless_view.cc | 8 +++++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index e9db97e195d1..40d702e35aa4 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -818,9 +818,7 @@ bool NativeWindowViews::ExecuteWindowsCommand(int command_id) { NotifyWindowExecuteWindowsCommand(command); return false; } -#endif -#if defined(OS_WIN) bool NativeWindowViews::PreHandleMSG( UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) { switch (message) { @@ -874,6 +872,33 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) { } #endif +gfx::Size NativeWindowViews::WindowSizeToFramelessSize( + const gfx::Size& size) { + if (size.width() == 0 && size.height() == 0) + return size; + + gfx::Rect window_bounds = gfx::Rect(size); + if (use_content_size_) { + if (menu_bar_ && menu_bar_visible_) { + window_bounds.set_height(window_bounds.height() + kMenuBarHeight); + } + } else if (has_frame()) { +#if defined(OS_WIN) + gfx::Size frame_size = gfx::win::ScreenToDIPRect( + window_->non_client_view()->GetWindowBoundsForClientBounds( + gfx::Rect())).size(); +#else + gfx::Size frame_size = + window_->non_client_view()->GetWindowBoundsForClientBounds( + gfx::Rect()).size(); +#endif + window_bounds.set_height(window_bounds.height() - frame_size.height()); + window_bounds.set_width(window_bounds.width() - frame_size.width()); + } + + return window_bounds.size(); +} + void NativeWindowViews::HandleKeyboardEvent( content::WebContents*, const content::NativeWebKeyboardEvent& event) { diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 71e122d3814f..790e532f84a0 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -94,6 +94,8 @@ class NativeWindowViews : public NativeWindow, gfx::AcceleratedWidget GetAcceleratedWidget(); + gfx::Size WindowSizeToFramelessSize(const gfx::Size& size); + views::Widget* widget() const { return window_.get(); } #if defined(OS_WIN) diff --git a/atom/browser/ui/views/frameless_view.cc b/atom/browser/ui/views/frameless_view.cc index 03a31e082874..e8d351ec8281 100644 --- a/atom/browser/ui/views/frameless_view.cc +++ b/atom/browser/ui/views/frameless_view.cc @@ -104,11 +104,15 @@ gfx::Size FramelessView::GetPreferredSize() const { } gfx::Size FramelessView::GetMinimumSize() const { - return window_->GetMinimumSize(); + gfx::Size size = window_->WindowSizeToFramelessSize( + window_->GetMinimumSize()); + return size; } gfx::Size FramelessView::GetMaximumSize() const { - return window_->GetMaximumSize(); + gfx::Size size = window_->WindowSizeToFramelessSize( + window_->GetMaximumSize()); + return size; } const char* FramelessView::GetClassName() const { From 5d7cfa1b3ac5b3f578ceca6ceb94dcbddedd4dcf Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Oct 2015 15:53:09 +0800 Subject: [PATCH 068/738] Update brightray for atom/brightray#149 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 6cbb4ad4d173..361d99dd05a8 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 6cbb4ad4d173d25b66eecf675c2b25ee64196429 +Subproject commit 361d99dd05a8368faee20bc39a6ffaedbc67c383 From 791f988aba568921c940713231da1811b6a1cdd3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Oct 2015 16:32:08 +0800 Subject: [PATCH 069/738] linux: Fix pressing Alt not showing menubar --- atom/browser/native_window_views.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index e9db97e195d1..4282b0eda96f 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -905,9 +905,6 @@ void NativeWindowViews::HandleKeyboardEvent( // When a single Alt is pressed: menu_bar_alt_pressed_ = true; } else if (event.type == blink::WebInputEvent::KeyUp && IsAltKey(event) && -#if defined(USE_X11) - event.modifiers == 0 && -#endif menu_bar_alt_pressed_) { // When a single Alt is released right after a Alt is pressed: menu_bar_alt_pressed_ = false; From add9c380230ae61316156025ef8c9fec85d23f84 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Oct 2015 16:33:03 +0800 Subject: [PATCH 070/738] linux: Enable force showing menubar This is for debugging purpose. --- atom/browser/ui/x/x_window_utils.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/atom/browser/ui/x/x_window_utils.cc b/atom/browser/ui/x/x_window_utils.cc index e57122839cd8..f5c3f54ec123 100644 --- a/atom/browser/ui/x/x_window_utils.cc +++ b/atom/browser/ui/x/x_window_utils.cc @@ -6,6 +6,7 @@ #include +#include "base/environment.h" #include "base/strings/string_util.h" #include "dbus/bus.h" #include "dbus/object_proxy.h" @@ -50,6 +51,10 @@ void SetWindowType(::Window xwindow, const std::string& type) { } bool ShouldUseGlobalMenuBar() { + scoped_ptr env(base::Environment::Create()); + if (env->HasVar("ELECTRON_FORCE_WINDOW_MENU_BAR")) + return false; + dbus::Bus::Options options; scoped_refptr bus(new dbus::Bus(options)); From 74b76102a84740a618ff3288f27dfad1197d32a2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Oct 2015 16:53:20 +0800 Subject: [PATCH 071/738] linux: No longer needs to manually read DPI settings It is now done in brightray by reading the value from GTK+. --- atom/browser/atom_browser_main_parts.cc | 4 - atom/browser/atom_browser_main_parts.h | 4 - atom/browser/atom_browser_main_parts_linux.cc | 73 ------------------- filenames.gypi | 1 - vendor/brightray | 2 +- 5 files changed, 1 insertion(+), 83 deletions(-) delete mode 100644 atom/browser/atom_browser_main_parts_linux.cc diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index a1a1192b2768..1b46247c4918 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -55,10 +55,6 @@ void AtomBrowserMainParts::RegisterDestructionCallback( void AtomBrowserMainParts::PostEarlyInitialization() { brightray::BrowserMainParts::PostEarlyInitialization(); -#if defined(USE_X11) - SetDPIFromGSettings(); -#endif - { // Temporary set the bridge_task_runner_ as current thread's task runner, // so we can fool gin::PerIsolateData to use it as its task runner, instead diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index bcebc86f16ca..9fefa486a1dc 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -48,10 +48,6 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { #endif private: -#if defined(USE_X11) - void SetDPIFromGSettings(); -#endif - // A fake BrowserProcess object that used to feed the source code from chrome. scoped_ptr fake_browser_process_; diff --git a/atom/browser/atom_browser_main_parts_linux.cc b/atom/browser/atom_browser_main_parts_linux.cc deleted file mode 100644 index 278e49ac1f1e..000000000000 --- a/atom/browser/atom_browser_main_parts_linux.cc +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/browser/atom_browser_main_parts.h" - -#include - -#include "base/command_line.h" -#include "base/strings/string_number_conversions.h" -#include "ui/gfx/switches.h" - -namespace atom { - -namespace { - -const char* kInterfaceSchema = "org.gnome.desktop.interface"; -const char* kScaleFactor = "scaling-factor"; - -bool SchemaExists(const char* schema_name) { - const gchar* const* schemas = g_settings_list_schemas(); - while (*schemas) { - if (strcmp(schema_name, static_cast(*schemas)) == 0) - return true; - schemas++; - } - return false; -} - -bool KeyExists(GSettings* client, const char* key) { - gchar** keys = g_settings_list_keys(client); - if (!keys) - return false; - - gchar** iter = keys; - while (*iter) { - if (strcmp(*iter, key) == 0) - break; - iter++; - } - - bool exists = *iter != NULL; - g_strfreev(keys); - return exists; -} - -void GetDPIFromGSettings(guint* scale_factor) { - GSettings* client = nullptr; - if (!SchemaExists(kInterfaceSchema) || - !(client = g_settings_new(kInterfaceSchema))) { - VLOG(1) << "Cannot create gsettings client."; - return; - } - - if (KeyExists(client, kScaleFactor)) - *scale_factor = g_settings_get_uint(client, kScaleFactor); - - g_object_unref(client); -} - -} // namespace - -void AtomBrowserMainParts::SetDPIFromGSettings() { - guint scale_factor = 1; - GetDPIFromGSettings(&scale_factor); - if (scale_factor == 0) - scale_factor = 1; - - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - switches::kForceDeviceScaleFactor, base::UintToString(scale_factor)); -} - -} // namespace atom diff --git a/filenames.gypi b/filenames.gypi index 000633fb96b1..eb94973e018c 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -124,7 +124,6 @@ 'atom/browser/atom_download_manager_delegate.h', 'atom/browser/atom_browser_main_parts.cc', 'atom/browser/atom_browser_main_parts.h', - 'atom/browser/atom_browser_main_parts_linux.cc', 'atom/browser/atom_browser_main_parts_mac.mm', 'atom/browser/atom_javascript_dialog_manager.cc', 'atom/browser/atom_javascript_dialog_manager.h', diff --git a/vendor/brightray b/vendor/brightray index 361d99dd05a8..bbb9287337f8 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 361d99dd05a8368faee20bc39a6ffaedbc67c383 +Subproject commit bbb9287337f8b7958b001be35b993c21cd573109 From bdd2f919137546a560ce808fd386994823628c57 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Oct 2015 19:20:52 +0800 Subject: [PATCH 072/738] Make Browser::Quit more robust --- atom/browser/browser.cc | 15 +++++++++++++-- atom/browser/browser.h | 3 +++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 9d2a9fc1effb..d8bb94103cd9 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -16,7 +16,8 @@ namespace atom { Browser::Browser() : is_quiting_(false), - is_ready_(false) { + is_ready_(false), + is_shutdown_(false) { WindowList::AddObserver(this); } @@ -30,6 +31,9 @@ Browser* Browser::Get() { } void Browser::Quit() { + if (is_quiting_) + return; + is_quiting_ = HandleBeforeQuit(); if (!is_quiting_) return; @@ -42,9 +46,13 @@ void Browser::Quit() { } void Browser::Shutdown() { - FOR_EACH_OBSERVER(BrowserObserver, observers_, OnQuit()); + if (is_shutdown_) + return; + is_shutdown_ = true; is_quiting_ = true; + + FOR_EACH_OBSERVER(BrowserObserver, observers_, OnQuit()); base::MessageLoop::current()->PostTask( FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); } @@ -121,6 +129,9 @@ void Browser::ClientCertificateSelector( } void Browser::NotifyAndShutdown() { + if (is_shutdown_) + return; + bool prevent_default = false; FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWillQuit(&prevent_default)); diff --git a/atom/browser/browser.h b/atom/browser/browser.h index d135556b8760..3c5abd2f0405 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -159,6 +159,9 @@ class Browser : public WindowListObserver { // Whether "ready" event has been emitted. bool is_ready_; + // The browse is being shutdown. + bool is_shutdown_; + std::string version_override_; std::string name_override_; From 0e131f760b63ad199c5fffa13b2d422cf3bb5e26 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Oct 2015 19:21:36 +0800 Subject: [PATCH 073/738] Quit gracefully when Ctrl-C is pressed --- atom/browser/atom_browser_main_parts.cc | 12 + atom/browser/atom_browser_main_parts.h | 8 + atom/browser/atom_browser_main_parts_posix.cc | 225 ++++++++++++++++++ filenames.gypi | 1 + 4 files changed, 246 insertions(+) create mode 100644 atom/browser/atom_browser_main_parts_posix.cc diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 1b46247c4918..e70d42fc768a 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -52,6 +52,12 @@ void AtomBrowserMainParts::RegisterDestructionCallback( destruction_callbacks_.push_back(callback); } +void AtomBrowserMainParts::PreEarlyInitialization() { +#if defined(OS_POSIX) + HandleSIGCHLD(); +#endif +} + void AtomBrowserMainParts::PostEarlyInitialization() { brightray::BrowserMainParts::PostEarlyInitialization(); @@ -112,6 +118,12 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() { #endif } +void AtomBrowserMainParts::PostMainMessageLoopStart() { +#if defined(OS_POSIX) + HandleShutdownSignals(); +#endif +} + void AtomBrowserMainParts::PostMainMessageLoopRun() { brightray::BrowserMainParts::PostMainMessageLoopRun(); diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index 9fefa486a1dc..65b142157dc1 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -39,8 +39,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { protected: // content::BrowserMainParts: + void PreEarlyInitialization() override; void PostEarlyInitialization() override; void PreMainMessageLoopRun() override; + void PostMainMessageLoopStart() override; void PostMainMessageLoopRun() override; #if defined(OS_MACOSX) void PreMainMessageLoopStart() override; @@ -48,6 +50,12 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { #endif private: +#if defined(OS_POSIX) + // Set signal handlers. + void HandleSIGCHLD(); + void HandleShutdownSignals(); +#endif + // A fake BrowserProcess object that used to feed the source code from chrome. scoped_ptr fake_browser_process_; diff --git a/atom/browser/atom_browser_main_parts_posix.cc b/atom/browser/atom_browser_main_parts_posix.cc new file mode 100644 index 000000000000..ea0f87b171d4 --- /dev/null +++ b/atom/browser/atom_browser_main_parts_posix.cc @@ -0,0 +1,225 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +// Most code came from: chrome/browser/chrome_browser_main_posix.cc. + +#include "atom/browser/atom_browser_main_parts.h" + +#include +#include +#include +#include +#include +#include + +#include "atom/browser/browser.h" +#include "base/posix/eintr_wrapper.h" +#include "content/public/browser/browser_thread.h" + +using content::BrowserThread; + +namespace atom { + +namespace { + +// See comment in |PreEarlyInitialization()|, where sigaction is called. +void SIGCHLDHandler(int signal) { +} + +// The OSX fork() implementation can crash in the child process before +// fork() returns. In that case, the shutdown pipe will still be +// shared with the parent process. To prevent child crashes from +// causing parent shutdowns, |g_pipe_pid| is the pid for the process +// which registered |g_shutdown_pipe_write_fd|. +// See . +pid_t g_pipe_pid = -1; +int g_shutdown_pipe_write_fd = -1; +int g_shutdown_pipe_read_fd = -1; + +// Common code between SIG{HUP, INT, TERM}Handler. +void GracefulShutdownHandler(int signal) { + // Reinstall the default handler. We had one shot at graceful shutdown. + struct sigaction action; + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_DFL; + RAW_CHECK(sigaction(signal, &action, NULL) == 0); + + RAW_CHECK(g_pipe_pid == getpid()); + RAW_CHECK(g_shutdown_pipe_write_fd != -1); + RAW_CHECK(g_shutdown_pipe_read_fd != -1); + size_t bytes_written = 0; + do { + int rv = HANDLE_EINTR( + write(g_shutdown_pipe_write_fd, + reinterpret_cast(&signal) + bytes_written, + sizeof(signal) - bytes_written)); + RAW_CHECK(rv >= 0); + bytes_written += rv; + } while (bytes_written < sizeof(signal)); +} + +// See comment in |PostMainMessageLoopStart()|, where sigaction is called. +void SIGHUPHandler(int signal) { + RAW_CHECK(signal == SIGHUP); + GracefulShutdownHandler(signal); +} + +// See comment in |PostMainMessageLoopStart()|, where sigaction is called. +void SIGINTHandler(int signal) { + RAW_CHECK(signal == SIGINT); + GracefulShutdownHandler(signal); +} + +// See comment in |PostMainMessageLoopStart()|, where sigaction is called. +void SIGTERMHandler(int signal) { + RAW_CHECK(signal == SIGTERM); + GracefulShutdownHandler(signal); +} + +class ShutdownDetector : public base::PlatformThread::Delegate { + public: + explicit ShutdownDetector(int shutdown_fd); + + void ThreadMain() override; + + private: + const int shutdown_fd_; + + DISALLOW_COPY_AND_ASSIGN(ShutdownDetector); +}; + +ShutdownDetector::ShutdownDetector(int shutdown_fd) + : shutdown_fd_(shutdown_fd) { + CHECK_NE(shutdown_fd_, -1); +} + +// These functions are used to help us diagnose crash dumps that happen +// during the shutdown process. +NOINLINE void ShutdownFDReadError() { + // Ensure function isn't optimized away. + asm(""); + sleep(UINT_MAX); +} + +NOINLINE void ShutdownFDClosedError() { + // Ensure function isn't optimized away. + asm(""); + sleep(UINT_MAX); +} + +NOINLINE void ExitPosted() { + // Ensure function isn't optimized away. + asm(""); + sleep(UINT_MAX); +} + +void ShutdownDetector::ThreadMain() { + base::PlatformThread::SetName("CrShutdownDetector"); + + int signal; + size_t bytes_read = 0; + ssize_t ret; + do { + ret = HANDLE_EINTR( + read(shutdown_fd_, + reinterpret_cast(&signal) + bytes_read, + sizeof(signal) - bytes_read)); + if (ret < 0) { + NOTREACHED() << "Unexpected error: " << strerror(errno); + ShutdownFDReadError(); + break; + } else if (ret == 0) { + NOTREACHED() << "Unexpected closure of shutdown pipe."; + ShutdownFDClosedError(); + break; + } + bytes_read += ret; + } while (bytes_read < sizeof(signal)); + VLOG(1) << "Handling shutdown for signal " << signal << "."; + base::Closure task = + base::Bind(&Browser::Quit, base::Unretained(Browser::Get())); + + if (!BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task)) { + // Without a UI thread to post the exit task to, there aren't many + // options. Raise the signal again. The default handler will pick it up + // and cause an ungraceful exit. + RAW_LOG(WARNING, "No UI thread, exiting ungracefully."); + kill(getpid(), signal); + + // The signal may be handled on another thread. Give that a chance to + // happen. + sleep(3); + + // We really should be dead by now. For whatever reason, we're not. Exit + // immediately, with the exit status set to the signal number with bit 8 + // set. On the systems that we care about, this exit status is what is + // normally used to indicate an exit by this signal's default handler. + // This mechanism isn't a de jure standard, but even in the worst case, it + // should at least result in an immediate exit. + RAW_LOG(WARNING, "Still here, exiting really ungracefully."); + _exit(signal | (1 << 7)); + } + ExitPosted(); +} + +} // namespace + +void AtomBrowserMainParts::HandleSIGCHLD() { + // We need to accept SIGCHLD, even though our handler is a no-op because + // otherwise we cannot wait on children. (According to POSIX 2001.) + struct sigaction action; + memset(&action, 0, sizeof(action)); + action.sa_handler = SIGCHLDHandler; + CHECK(sigaction(SIGCHLD, &action, NULL) == 0); +} + +void AtomBrowserMainParts::HandleShutdownSignals() { + int pipefd[2]; + int ret = pipe(pipefd); + if (ret < 0) { + PLOG(DFATAL) << "Failed to create pipe"; + } else { + g_pipe_pid = getpid(); + g_shutdown_pipe_read_fd = pipefd[0]; + g_shutdown_pipe_write_fd = pipefd[1]; +#if !defined(ADDRESS_SANITIZER) && !defined(KEEP_SHADOW_STACKS) + const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2; +#else + // ASan instrumentation and -finstrument-functions (used for keeping the + // shadow stacks) bloat the stack frames, so we need to increase the stack + // size to avoid hitting the guard page. + const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4; +#endif + // TODO(viettrungluu,willchan): crbug.com/29675 - This currently leaks, so + // if you change this, you'll probably need to change the suppression. + if (!base::PlatformThread::CreateNonJoinable( + kShutdownDetectorThreadStackSize, + new ShutdownDetector(g_shutdown_pipe_read_fd))) { + LOG(DFATAL) << "Failed to create shutdown detector task."; + } + } + // Setup signal handlers for shutdown AFTER shutdown pipe is setup because + // it may be called right away after handler is set. + + // If adding to this list of signal handlers, note the new signal probably + // needs to be reset in child processes. See + // base/process_util_posix.cc:LaunchProcess. + + // We need to handle SIGTERM, because that is how many POSIX-based distros ask + // processes to quit gracefully at shutdown time. + struct sigaction action; + memset(&action, 0, sizeof(action)); + action.sa_handler = SIGTERMHandler; + CHECK(sigaction(SIGTERM, &action, NULL) == 0); + // Also handle SIGINT - when the user terminates the browser via Ctrl+C. If + // the browser process is being debugged, GDB will catch the SIGINT first. + action.sa_handler = SIGINTHandler; + CHECK(sigaction(SIGINT, &action, NULL) == 0); + // And SIGHUP, for when the terminal disappears. On shutdown, many Linux + // distros send SIGHUP, SIGTERM, and then SIGKILL. + action.sa_handler = SIGHUPHandler; + CHECK(sigaction(SIGHUP, &action, NULL) == 0); +} + +} // namespace atom diff --git a/filenames.gypi b/filenames.gypi index eb94973e018c..04b82992bc33 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -125,6 +125,7 @@ 'atom/browser/atom_browser_main_parts.cc', 'atom/browser/atom_browser_main_parts.h', 'atom/browser/atom_browser_main_parts_mac.mm', + 'atom/browser/atom_browser_main_parts_posix.cc', 'atom/browser/atom_javascript_dialog_manager.cc', 'atom/browser/atom_javascript_dialog_manager.h', 'atom/browser/atom_quota_permission_context.cc', From a2a4970f5f6601c6e8b713e6fe342ea63d78b022 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Oct 2015 19:36:41 +0800 Subject: [PATCH 074/738] Fix cpplint warnings --- atom/browser/atom_browser_main_parts_posix.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/atom/browser/atom_browser_main_parts_posix.cc b/atom/browser/atom_browser_main_parts_posix.cc index ea0f87b171d4..2a0dddc47483 100644 --- a/atom/browser/atom_browser_main_parts_posix.cc +++ b/atom/browser/atom_browser_main_parts_posix.cc @@ -171,7 +171,7 @@ void AtomBrowserMainParts::HandleSIGCHLD() { struct sigaction action; memset(&action, 0, sizeof(action)); action.sa_handler = SIGCHLDHandler; - CHECK(sigaction(SIGCHLD, &action, NULL) == 0); + CHECK_EQ(sigaction(SIGCHLD, &action, NULL), 0); } void AtomBrowserMainParts::HandleShutdownSignals() { @@ -211,15 +211,15 @@ void AtomBrowserMainParts::HandleShutdownSignals() { struct sigaction action; memset(&action, 0, sizeof(action)); action.sa_handler = SIGTERMHandler; - CHECK(sigaction(SIGTERM, &action, NULL) == 0); + CHECK_EQ(sigaction(SIGTERM, &action, NULL), 0); // Also handle SIGINT - when the user terminates the browser via Ctrl+C. If // the browser process is being debugged, GDB will catch the SIGINT first. action.sa_handler = SIGINTHandler; - CHECK(sigaction(SIGINT, &action, NULL) == 0); + CHECK_EQ(sigaction(SIGINT, &action, NULL), 0); // And SIGHUP, for when the terminal disappears. On shutdown, many Linux // distros send SIGHUP, SIGTERM, and then SIGKILL. action.sa_handler = SIGHUPHandler; - CHECK(sigaction(SIGHUP, &action, NULL) == 0); + CHECK_EQ(sigaction(SIGHUP, &action, NULL), 0); } } // namespace atom From d4bfeff6ad1686feb4a815096bb7890230a73a01 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Oct 2015 20:08:19 +0800 Subject: [PATCH 075/738] Fix crashing on Linux --- atom/browser/atom_browser_main_parts.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index e70d42fc768a..4c11176997ca 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -53,6 +53,7 @@ void AtomBrowserMainParts::RegisterDestructionCallback( } void AtomBrowserMainParts::PreEarlyInitialization() { + brightray::BrowserMainParts::PreEarlyInitialization(); #if defined(OS_POSIX) HandleSIGCHLD(); #endif @@ -119,6 +120,7 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() { } void AtomBrowserMainParts::PostMainMessageLoopStart() { + brightray::BrowserMainParts::PostMainMessageLoopStart(); #if defined(OS_POSIX) HandleShutdownSignals(); #endif From 3d4318e15e757cf26377637ee1240d5b87cde39c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Oct 2015 21:19:44 +0800 Subject: [PATCH 076/738] docs: Remove `cache` and `userCache` dir Closes #1404. --- docs/api/app.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/api/app.md b/docs/api/app.md index e4a8d561e2f5..0b5780aab7bf 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -197,12 +197,6 @@ You can request the following paths by the name: * `~/Library/Application Support` on OS X * `userData` The directory for storing your app's configuration files, which by default it is the `appData` directory appended with your app's name. -* `cache` Per-user application cache directory, which by default points to: - * `%APPDATA%` on Windows (which doesn't have a universal cache location) - * `$XDG_CACHE_HOME` or `~/.cache` on Linux - * `~/Library/Caches` on OS X -* `userCache` The directory for placing your app's caches, by default it is the - `cache` directory appended with your app's name. * `temp` Temporary directory. * `userDesktop` The current user's Desktop directory. * `exe` The current executable file. From ca6f6880139670e560157ebaa812cdf73afdeb0a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 4 Oct 2015 22:19:05 +0800 Subject: [PATCH 077/738] Update brightray for #877 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index bbb9287337f8..c44f99278bc4 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit bbb9287337f8b7958b001be35b993c21cd573109 +Subproject commit c44f99278bc4f6823f81b6f3a8d75881d697fd01 From 4d02fc58fa183c13273888cc30a874abaee52238 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Mon, 5 Oct 2015 03:29:02 +0300 Subject: [PATCH 078/738] Fix restore/unmaximize wrong window size This resolves #2498. --- atom/browser/native_window_views.cc | 46 +++++++++++++++++++---------- atom/browser/native_window_views.h | 6 ++++ 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index e9db97e195d1..7117142cf006 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -283,6 +283,8 @@ NativeWindowViews::NativeWindowViews( else last_window_state_ = ui::SHOW_STATE_NORMAL; + last_normal_size_ = gfx::Size(widget_size_); + if (!has_frame()) { // Set Window style so that we get a minimize and maximize animation when // frameless. @@ -851,23 +853,35 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) { NotifyWindowMinimize(); break; case SIZE_RESTORED: - if (last_window_state_ == ui::SHOW_STATE_NORMAL) - return; - - switch (last_window_state_) { - case ui::SHOW_STATE_MAXIMIZED: - last_window_state_ = ui::SHOW_STATE_NORMAL; - NotifyWindowUnmaximize(); - break; - case ui::SHOW_STATE_MINIMIZED: - if (IsFullscreen()) { - last_window_state_ = ui::SHOW_STATE_FULLSCREEN; - NotifyWindowEnterFullScreen(); - } else { + if (last_window_state_ == ui::SHOW_STATE_NORMAL) { + // Window was resized so we save it's new size. + last_normal_size_ = GetSize(); + } else { + switch (last_window_state_) { + case ui::SHOW_STATE_MAXIMIZED: last_window_state_ = ui::SHOW_STATE_NORMAL; - NotifyWindowRestore(); - } - break; + + // When the window is restored we resize it to the previous known + // normal size. + NativeWindow::SetSize(last_normal_size_); + + NotifyWindowUnmaximize(); + break; + case ui::SHOW_STATE_MINIMIZED: + if (IsFullscreen()) { + last_window_state_ = ui::SHOW_STATE_FULLSCREEN; + NotifyWindowEnterFullScreen(); + } else { + last_window_state_ = ui::SHOW_STATE_NORMAL; + + // When the window is restored we resize it to the previous known + // normal size. + NativeWindow::SetSize(last_normal_size_); + + NotifyWindowRestore(); + } + break; + } } break; } diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 71e122d3814f..f93a9e2f7f9a 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -176,6 +176,12 @@ class NativeWindowViews : public NativeWindow, ui::WindowShowState last_window_state_; + // There's an issue with restore on Windows, that sometimes causes the Window + // to receive the wrong size (#2498). To circumvent that, we keep tabs on the + // size of the window while in the normal state (not maximized, minimized or + // fullscreen), so we restore it correctly. + gfx::Size last_normal_size_; + // In charge of running taskbar related APIs. TaskbarHost taskbar_host_; #endif From c34c123b338df7a8a72cc14f0b032eae223800ac Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Mon, 5 Oct 2015 04:01:25 +0300 Subject: [PATCH 079/738] Make it work only on Windows Limiting the solution to Windows only. --- atom/browser/ui/views/frameless_view.cc | 8 ++------ atom/browser/ui/views/win_frame_view.cc | 6 ++++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/atom/browser/ui/views/frameless_view.cc b/atom/browser/ui/views/frameless_view.cc index e8d351ec8281..03a31e082874 100644 --- a/atom/browser/ui/views/frameless_view.cc +++ b/atom/browser/ui/views/frameless_view.cc @@ -104,15 +104,11 @@ gfx::Size FramelessView::GetPreferredSize() const { } gfx::Size FramelessView::GetMinimumSize() const { - gfx::Size size = window_->WindowSizeToFramelessSize( - window_->GetMinimumSize()); - return size; + return window_->GetMinimumSize(); } gfx::Size FramelessView::GetMaximumSize() const { - gfx::Size size = window_->WindowSizeToFramelessSize( - window_->GetMaximumSize()); - return size; + return window_->GetMaximumSize(); } const char* FramelessView::GetClassName() const { diff --git a/atom/browser/ui/views/win_frame_view.cc b/atom/browser/ui/views/win_frame_view.cc index db74661932b7..d0338af19d9a 100644 --- a/atom/browser/ui/views/win_frame_view.cc +++ b/atom/browser/ui/views/win_frame_view.cc @@ -40,12 +40,14 @@ int WinFrameView::NonClientHitTest(const gfx::Point& point) { } gfx::Size WinFrameView::GetMinimumSize() const { - gfx::Size size = FramelessView::GetMinimumSize(); + gfx::Size size = window_->WindowSizeToFramelessSize( + window_->GetMinimumSize()); return gfx::win::DIPToScreenSize(size); } gfx::Size WinFrameView::GetMaximumSize() const { - gfx::Size size = FramelessView::GetMaximumSize(); + gfx::Size size = window_->WindowSizeToFramelessSize( + window_->GetMaximumSize()); return gfx::win::DIPToScreenSize(size); } From 69140af0835d2d7aea8bbce632ae7fe9faa70bad Mon Sep 17 00:00:00 2001 From: hansrwindhoff Date: Sun, 4 Oct 2015 20:14:52 -0600 Subject: [PATCH 080/738] example code didn't run --- docs/api/screen.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/api/screen.md b/docs/api/screen.md index da15c7326f17..9afbf02170e1 100644 --- a/docs/api/screen.md +++ b/docs/api/screen.md @@ -37,8 +37,8 @@ app.on('ready', function() { var electronScreen = require('screen'); var displays = electronScreen.getAllDisplays(); var externalDisplay = null; - for (var i in displays) { - if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) { + for (var i =0; i< displays.length; i++) { + if (displays[i].bounds.x !==0 || displays[i].bounds.y !== 0) { externalDisplay = displays[i]; break; } @@ -48,6 +48,8 @@ app.on('ready', function() { mainWindow = new BrowserWindow({ x: externalDisplay.bounds.x + 50, y: externalDisplay.bounds.y + 50, + width: 900, + height:600 }); } }); From 46c69cc3e5f76aee329a1b79847ac0f65818e5ee Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 11:41:06 +0800 Subject: [PATCH 081/738] docs: Removed unneeded changes from PR --- docs/api/screen.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/api/screen.md b/docs/api/screen.md index 9afbf02170e1..3b6c276daf34 100644 --- a/docs/api/screen.md +++ b/docs/api/screen.md @@ -37,8 +37,8 @@ app.on('ready', function() { var electronScreen = require('screen'); var displays = electronScreen.getAllDisplays(); var externalDisplay = null; - for (var i =0; i< displays.length; i++) { - if (displays[i].bounds.x !==0 || displays[i].bounds.y !== 0) { + for (var i in displays) { + if (displays[i].bounds.x != 0 || displays[i].bounds.y != 0) { externalDisplay = displays[i]; break; } @@ -48,8 +48,6 @@ app.on('ready', function() { mainWindow = new BrowserWindow({ x: externalDisplay.bounds.x + 50, y: externalDisplay.bounds.y + 50, - width: 900, - height:600 }); } }); From ad8e727ba251b559e48625680a50cc014f26b0e5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 11:41:36 +0800 Subject: [PATCH 082/738] docs: "loaded" event of "process" --- docs/api/process.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/api/process.md b/docs/api/process.md index abd3c4fe574c..4e0fa4d602ef 100644 --- a/docs/api/process.md +++ b/docs/api/process.md @@ -9,7 +9,25 @@ upstream node: * `process.versions['chrome']` String - Version of Chromium. * `process.resourcesPath` String - Path to JavaScript source code. -# Methods +## Events + +### Event: 'loaded' + +Emitted when Electron has loaded its internal initialization script and is +beginning to load the web page or the main script. + +It can be used by the preload script to add removed Node global symbols back to +the global scope when node integration is turned off: + +```js +// preload.js +process.once('loaded', function() { + global.setImmediate = setImmediate; + global.clearImmediate = clearImmediate; +}); +``` + +## Methods The `process` object has the following method: @@ -17,7 +35,7 @@ The `process` object has the following method: Causes the main thread of the current process hang. -## process.setFdLimit(maxDescriptors) _OS X_ _Linux_ +### process.setFdLimit(maxDescriptors) _OS X_ _Linux_ * `maxDescriptors` Integer From ec0a8a13219a18989623878ed063449742a42bd6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 11:42:43 +0800 Subject: [PATCH 083/738] Bump v0.33.5 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 2 +- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/atom.gyp b/atom.gyp index b3c9e117a505..637e1c4795cf 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.4', + 'version%': '0.33.5', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index b1b905a43332..12934e6ef855 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,7 +17,7 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.4 + 0.33.5 LSMinimumSystemVersion 10.8.0 NSMainNibFile diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 6d900b0ea017..7a36dcdf35e5 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,33,4,0 - PRODUCTVERSION 0,33,4,0 + FILEVERSION 0,33,5,0 + PRODUCTVERSION 0,33,5,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.4" + VALUE "FileVersion", "0.33.5" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.33.4" + VALUE "ProductVersion", "0.33.5" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 998e43088122..42610f196e12 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 33 -#define ATOM_PATCH_VERSION 4 +#define ATOM_PATCH_VERSION 5 #define ATOM_VERSION_IS_RELEASE 1 From 7de3aa3cc1eef66a84df8d474954d4e2d81a1adb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 19:57:14 +0800 Subject: [PATCH 084/738] Fix typo, closes #2990 --- atom/browser/native_window_views.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 4282b0eda96f..689626fc5f48 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -351,7 +351,7 @@ void NativeWindowViews::ShowInactive() { } void NativeWindowViews::Hide() { - web_contents()->WasHidden(); + window_->Hide(); } bool NativeWindowViews::IsVisible() { From 2d676770b12975daf1bbf67d0c758be04e03844f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 19:57:30 +0800 Subject: [PATCH 085/738] Bump v0.33.6 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 2 +- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/atom.gyp b/atom.gyp index 637e1c4795cf..f06a0c8251be 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.5', + 'version%': '0.33.6', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 12934e6ef855..50e019c1c77e 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,7 +17,7 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.5 + 0.33.6 LSMinimumSystemVersion 10.8.0 NSMainNibFile diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 7a36dcdf35e5..b1aba451dcf6 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,33,5,0 - PRODUCTVERSION 0,33,5,0 + FILEVERSION 0,33,6,0 + PRODUCTVERSION 0,33,6,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.5" + VALUE "FileVersion", "0.33.6" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.33.5" + VALUE "ProductVersion", "0.33.6" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 42610f196e12..8078551b90ed 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 33 -#define ATOM_PATCH_VERSION 5 +#define ATOM_PATCH_VERSION 6 #define ATOM_VERSION_IS_RELEASE 1 From 8577f2b52f42335747101123b4fe9e5fa77f1bd8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 16:19:01 +0800 Subject: [PATCH 086/738] osx: Add NativeWindow::SetSizeConstraints --- atom/browser/native_window.cc | 69 +++++++++++++++ atom/browser/native_window.h | 26 ++++-- atom/browser/native_window_mac.h | 12 +-- atom/browser/native_window_mac.mm | 77 +++++++---------- atom/browser/native_window_views.cc | 16 ++++ atom/browser/native_window_views.h | 6 ++ .../browser/app_window/size_constraints.cc | 83 +++++++++++++++++++ .../browser/app_window/size_constraints.h | 57 +++++++++++++ filenames.gypi | 2 + 9 files changed, 287 insertions(+), 61 deletions(-) create mode 100644 chromium_src/extensions/browser/app_window/size_constraints.cc create mode 100644 chromium_src/extensions/browser/app_window/size_constraints.h diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 80a7d1347f3e..cad6942d2e99 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -162,6 +162,14 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { Show(); } +gfx::Size NativeWindow::ContentSizeToWindowSize(const gfx::Size& size) { + return size; +} + +gfx::Size NativeWindow::WindowSizeToContentSize(const gfx::Size& size) { + return size; +} + void NativeWindow::SetSize(const gfx::Size& size) { SetBounds(gfx::Rect(GetPosition(), size)); } @@ -178,6 +186,67 @@ gfx::Point NativeWindow::GetPosition() { return GetBounds().origin(); } +void NativeWindow::SetContentSize(const gfx::Size& size) { + SetSize(ContentSizeToWindowSize(size)); +} + +gfx::Size NativeWindow::GetContentSize() { + return WindowSizeToContentSize(GetSize()); +} + +void NativeWindow::SetSizeConstraints( + const extensions::SizeConstraints& window_constraints) { + extensions::SizeConstraints content_constraints; + if (window_constraints.HasMaximumSize()) + content_constraints.set_maximum_size( + WindowSizeToContentSize(window_constraints.GetMaximumSize())); + if (window_constraints.HasMinimumSize()) + content_constraints.set_minimum_size( + WindowSizeToContentSize(window_constraints.GetMinimumSize())); + SetContentSizeConstraints(content_constraints); +} + +extensions::SizeConstraints NativeWindow::GetSizeConstraints() { + extensions::SizeConstraints content_constraints = GetContentSizeConstraints(); + extensions::SizeConstraints window_constraints; + if (content_constraints.HasMaximumSize()) + window_constraints.set_maximum_size( + ContentSizeToWindowSize(content_constraints.GetMaximumSize())); + if (content_constraints.HasMinimumSize()) + window_constraints.set_minimum_size( + ContentSizeToWindowSize(content_constraints.GetMinimumSize())); + return window_constraints; +} + +void NativeWindow::SetContentSizeConstraints( + const extensions::SizeConstraints& size_constraints) { + size_constraints_ = size_constraints; +} + +extensions::SizeConstraints NativeWindow::GetContentSizeConstraints() { + return size_constraints_; +} + +void NativeWindow::SetMinimumSize(const gfx::Size& size) { + extensions::SizeConstraints size_constraints; + size_constraints.set_minimum_size(size); + SetSizeConstraints(size_constraints); +} + +gfx::Size NativeWindow::GetMinimumSize() { + return GetSizeConstraints().GetMinimumSize(); +} + +void NativeWindow::SetMaximumSize(const gfx::Size& size) { + extensions::SizeConstraints size_constraints; + size_constraints.set_maximum_size(size); + SetSizeConstraints(size_constraints); +} + +gfx::Size NativeWindow::GetMaximumSize() { + return GetSizeConstraints().GetMaximumSize(); +} + void NativeWindow::SetRepresentedFilename(const std::string& filename) { } diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 751644e4595c..538783306464 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -19,6 +19,7 @@ #include "content/public/browser/readback_types.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" +#include "extensions/browser/app_window/size_constraints.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" @@ -110,12 +111,18 @@ class NativeWindow : public base::SupportsUserData, virtual gfx::Size GetSize(); virtual void SetPosition(const gfx::Point& position); virtual gfx::Point GetPosition(); - virtual void SetContentSize(const gfx::Size& size) = 0; - virtual gfx::Size GetContentSize() = 0; - virtual void SetMinimumSize(const gfx::Size& size) = 0; - virtual gfx::Size GetMinimumSize() = 0; - virtual void SetMaximumSize(const gfx::Size& size) = 0; - virtual gfx::Size GetMaximumSize() = 0; + virtual void SetContentSize(const gfx::Size& size); + virtual gfx::Size GetContentSize(); + virtual void SetSizeConstraints( + const extensions::SizeConstraints& size_constraints); + virtual extensions::SizeConstraints GetSizeConstraints(); + virtual void SetContentSizeConstraints( + const extensions::SizeConstraints& size_constraints); + virtual extensions::SizeConstraints GetContentSizeConstraints(); + virtual void SetMinimumSize(const gfx::Size& size); + virtual gfx::Size GetMinimumSize(); + virtual void SetMaximumSize(const gfx::Size& size); + virtual gfx::Size GetMaximumSize(); virtual void SetResizable(bool resizable) = 0; virtual bool IsResizable() = 0; virtual void SetAlwaysOnTop(bool top) = 0; @@ -234,6 +241,10 @@ class NativeWindow : public base::SupportsUserData, NativeWindow(brightray::InspectableWebContents* inspectable_web_contents, const mate::Dictionary& options); + // Converts between content size to window size. + virtual gfx::Size ContentSizeToWindowSize(const gfx::Size& size); + virtual gfx::Size WindowSizeToContentSize(const gfx::Size& size); + // content::WebContentsObserver: void RenderViewCreated(content::RenderViewHost* render_view_host) override; void BeforeUnloadDialogCancelled() override; @@ -269,6 +280,9 @@ class NativeWindow : public base::SupportsUserData, // has to been explicitly provided. scoped_ptr draggable_region_; // used in custom drag. + // Minimum and maximum size, stored as content size. + extensions::SizeConstraints size_constraints_; + // Whether window can be resized larger than screen. bool enable_larger_than_screen_; diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 20ad60531498..60581a2d977b 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -44,12 +44,8 @@ class NativeWindowMac : public NativeWindow { bool IsFullscreen() const override; void SetBounds(const gfx::Rect& bounds) override; gfx::Rect GetBounds() override; - void SetContentSize(const gfx::Size& size) override; - gfx::Size GetContentSize() override; - void SetMinimumSize(const gfx::Size& size) override; - gfx::Size GetMinimumSize() override; - void SetMaximumSize(const gfx::Size& size) override; - gfx::Size GetMaximumSize() override; + void SetContentSizeConstraints( + const extensions::SizeConstraints& size_constraints) override; void SetResizable(bool resizable) override; bool IsResizable() override; void SetAlwaysOnTop(bool top) override; @@ -89,6 +85,10 @@ class NativeWindowMac : public NativeWindow { const content::NativeWebKeyboardEvent&) override; private: + // NativeWindow: + gfx::Size ContentSizeToWindowSize(const gfx::Size& size) override; + gfx::Size WindowSizeToContentSize(const gfx::Size& size) override; + void InstallView(); void UninstallView(); diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 3e8dab2133c9..76f9b0d0de07 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -22,6 +22,11 @@ namespace { +// Converts gfx::Size to NSSize. +inline NSSize ToNSSize(const gfx::Size& size) { + return NSMakeSize(size.width(), size.height()); +} + // Prevents window from resizing during the scope. class ScopedDisableResize { public: @@ -549,56 +554,18 @@ gfx::Rect NativeWindowMac::GetBounds() { return bounds; } -void NativeWindowMac::SetContentSize(const gfx::Size& size) { - if (!has_frame()) { - SetSize(size); - return; +void NativeWindowMac::SetContentSizeConstraints( + const extensions::SizeConstraints& size_constraints) { + NSView* content = [window_ contentView]; + if (size_constraints.HasMinimumSize()) { + NSSize min_size = ToNSSize(size_constraints.GetMinimumSize()); + [window_ setMinSize:[content convertSize:min_size toView:nil]]; } - - NSRect frame_nsrect = [window_ frame]; - NSSize frame = frame_nsrect.size; - NSSize content = [window_ contentRectForFrameRect:frame_nsrect].size; - - int width = size.width() + frame.width - content.width; - int height = size.height() + frame.height - content.height; - frame_nsrect.origin.y -= height - frame_nsrect.size.height; - frame_nsrect.size.width = width; - frame_nsrect.size.height = height; - [window_ setFrame:frame_nsrect display:YES]; -} - -gfx::Size NativeWindowMac::GetContentSize() { - if (!has_frame()) - return GetSize(); - - NSRect bounds = [[window_ contentView] bounds]; - return gfx::Size(bounds.size.width, bounds.size.height); -} - -void NativeWindowMac::SetMinimumSize(const gfx::Size& size) { - NSSize min_size = NSMakeSize(size.width(), size.height()); - NSView* content = [window_ contentView]; - [window_ setContentMinSize:[content convertSize:min_size toView:nil]]; -} - -gfx::Size NativeWindowMac::GetMinimumSize() { - NSView* content = [window_ contentView]; - NSSize min_size = [content convertSize:[window_ contentMinSize] - fromView:nil]; - return gfx::Size(min_size.width, min_size.height); -} - -void NativeWindowMac::SetMaximumSize(const gfx::Size& size) { - NSSize max_size = NSMakeSize(size.width(), size.height()); - NSView* content = [window_ contentView]; - [window_ setContentMaxSize:[content convertSize:max_size toView:nil]]; -} - -gfx::Size NativeWindowMac::GetMaximumSize() { - NSView* content = [window_ contentView]; - NSSize max_size = [content convertSize:[window_ contentMaxSize] - fromView:nil]; - return gfx::Size(max_size.width, max_size.height); + if (size_constraints.HasMaximumSize()) { + NSSize max_size = ToNSSize(size_constraints.GetMaximumSize()); + [window_ setMaxSize:[content convertSize:max_size toView:nil]]; + } + NativeWindow::SetContentSizeConstraints(size_constraints); } void NativeWindowMac::SetResizable(bool resizable) { @@ -821,6 +788,18 @@ void NativeWindowMac::HandleKeyboardEvent( } } +gfx::Size NativeWindowMac::ContentSizeToWindowSize(const gfx::Size& size) { + NSRect content = NSMakeRect(0, 0, size.width(), size.height()); + NSRect frame = [window_ frameRectForContentRect:content]; + return gfx::Size(frame.size); +} + +gfx::Size NativeWindowMac::WindowSizeToContentSize(const gfx::Size& size) { + NSRect frame = NSMakeRect(0, 0, size.width(), size.height()); + NSRect content = [window_ contentRectForFrameRect:frame]; + return gfx::Size(content.size); +} + void NativeWindowMac::InstallView() { // Make sure the bottom corner is rounded: http://crbug.com/396264. [[window_ contentView] setWantsLayer:YES]; diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index f9e2089a4efa..1c7546854ee2 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -440,6 +440,22 @@ gfx::Rect NativeWindowViews::GetBounds() { return window_->GetWindowBoundsInScreen(); } +void NativeWindowViews::SetSizeConstraints( + const extensions::SizeConstraints& size_constraints) { +} + +extensions::SizeConstraints NativeWindowViews::GetSizeConstraints() { + return extensions::SizeConstraints(); +} + +void NativeWindowViews::SetContentSizeConstraints( + const extensions::SizeConstraints& size_constraints) { +} + +extensions::SizeConstraints NativeWindowViews::GetContentSizeConstraints() { + return extensions::SizeConstraints(); +} + void NativeWindowViews::SetContentSize(const gfx::Size& size) { if (!has_frame()) { NativeWindow::SetSize(size); diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 2b2322f1959e..5a90e6a22139 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -63,6 +63,12 @@ class NativeWindowViews : public NativeWindow, bool IsFullscreen() const override; void SetBounds(const gfx::Rect& bounds) override; gfx::Rect GetBounds() override; + void SetSizeConstraints( + const extensions::SizeConstraints& size_constraints) override; + extensions::SizeConstraints GetSizeConstraints() override; + void SetContentSizeConstraints( + const extensions::SizeConstraints& size_constraints) override; + extensions::SizeConstraints GetContentSizeConstraints() override; void SetContentSize(const gfx::Size& size) override; gfx::Size GetContentSize() override; void SetMinimumSize(const gfx::Size& size) override; diff --git a/chromium_src/extensions/browser/app_window/size_constraints.cc b/chromium_src/extensions/browser/app_window/size_constraints.cc new file mode 100644 index 000000000000..6d248c16017a --- /dev/null +++ b/chromium_src/extensions/browser/app_window/size_constraints.cc @@ -0,0 +1,83 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/browser/app_window/size_constraints.h" + +#include + +#include "ui/gfx/geometry/insets.h" + +namespace extensions { + +SizeConstraints::SizeConstraints() + : maximum_size_(kUnboundedSize, kUnboundedSize) {} + +SizeConstraints::SizeConstraints(const gfx::Size& min_size, + const gfx::Size& max_size) + : minimum_size_(min_size), maximum_size_(max_size) {} + +SizeConstraints::~SizeConstraints() {} + +// static +gfx::Size SizeConstraints::AddFrameToConstraints( + const gfx::Size& size_constraints, + const gfx::Insets& frame_insets) { + return gfx::Size( + size_constraints.width() == kUnboundedSize + ? kUnboundedSize + : size_constraints.width() + frame_insets.width(), + size_constraints.height() == kUnboundedSize + ? kUnboundedSize + : size_constraints.height() + frame_insets.height()); +} + +gfx::Size SizeConstraints::ClampSize(gfx::Size size) const { + const gfx::Size max_size = GetMaximumSize(); + if (max_size.width() != kUnboundedSize) + size.set_width(std::min(size.width(), max_size.width())); + if (max_size.height() != kUnboundedSize) + size.set_height(std::min(size.height(), max_size.height())); + size.SetToMax(GetMinimumSize()); + return size; +} + +bool SizeConstraints::HasMinimumSize() const { + const gfx::Size min_size = GetMinimumSize(); + return min_size.width() != kUnboundedSize || + min_size.height() != kUnboundedSize; +} + +bool SizeConstraints::HasMaximumSize() const { + const gfx::Size max_size = GetMaximumSize(); + return max_size.width() != kUnboundedSize || + max_size.height() != kUnboundedSize; +} + +bool SizeConstraints::HasFixedSize() const { + return !GetMinimumSize().IsEmpty() && GetMinimumSize() == GetMaximumSize(); +} + +gfx::Size SizeConstraints::GetMinimumSize() const { + return minimum_size_; +} + +gfx::Size SizeConstraints::GetMaximumSize() const { + return gfx::Size( + maximum_size_.width() == kUnboundedSize + ? kUnboundedSize + : std::max(maximum_size_.width(), minimum_size_.width()), + maximum_size_.height() == kUnboundedSize + ? kUnboundedSize + : std::max(maximum_size_.height(), minimum_size_.height())); +} + +void SizeConstraints::set_minimum_size(const gfx::Size& min_size) { + minimum_size_ = min_size; +} + +void SizeConstraints::set_maximum_size(const gfx::Size& max_size) { + maximum_size_ = max_size; +} + +} // namespace extensions diff --git a/chromium_src/extensions/browser/app_window/size_constraints.h b/chromium_src/extensions/browser/app_window/size_constraints.h new file mode 100644 index 000000000000..ecacf1e5eb13 --- /dev/null +++ b/chromium_src/extensions/browser/app_window/size_constraints.h @@ -0,0 +1,57 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_BROWSER_APP_WINDOW_SIZE_CONSTRAINTS_H_ +#define EXTENSIONS_BROWSER_APP_WINDOW_SIZE_CONSTRAINTS_H_ + +#include "ui/gfx/geometry/size.h" + +namespace gfx { +class Insets; +} + +namespace extensions { + +class SizeConstraints { + public: + // The value SizeConstraints uses to represent an unbounded width or height. + // This is an enum so that it can be declared inline here. + enum { kUnboundedSize = 0 }; + + SizeConstraints(); + SizeConstraints(const gfx::Size& min_size, const gfx::Size& max_size); + ~SizeConstraints(); + + // Adds frame insets to a size constraint. + static gfx::Size AddFrameToConstraints(const gfx::Size& size_constraints, + const gfx::Insets& frame_insets); + + // Returns the bounds with its size clamped to the min/max size. + gfx::Size ClampSize(gfx::Size size) const; + + // When gfx::Size is used as a min/max size, a zero represents an unbounded + // component. This method checks whether either component is specified. + // Note we can't use gfx::Size::IsEmpty as it returns true if either width + // or height is zero. + bool HasMinimumSize() const; + bool HasMaximumSize() const; + + // This returns true if all components are specified, and min and max are + // equal. + bool HasFixedSize() const; + + gfx::Size GetMaximumSize() const; + gfx::Size GetMinimumSize() const; + + void set_minimum_size(const gfx::Size& min_size); + void set_maximum_size(const gfx::Size& max_size); + + private: + gfx::Size minimum_size_; + gfx::Size maximum_size_; +}; + +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_APP_WINDOW_SIZE_CONSTRAINTS_H_ diff --git a/filenames.gypi b/filenames.gypi index 04b82992bc33..a6e799cd67c1 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -429,6 +429,8 @@ 'chromium_src/chrome/renderer/tts_dispatcher.cc', 'chromium_src/chrome/renderer/tts_dispatcher.h', 'chromium_src/chrome/utility/utility_message_handler.h', + 'chromium_src/extensions/browser/app_window/size_constraints.cc', + 'chromium_src/extensions/browser/app_window/size_constraints.h', 'chromium_src/library_loaders/libspeechd_loader.cc', 'chromium_src/library_loaders/libspeechd.h', 'chromium_src/net/test/embedded_test_server/stream_listen_socket.cc', From a76ea00249286b791a3308230ea7179516ef38d0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 19:05:59 +0800 Subject: [PATCH 087/738] views: Implement NativeWindow::SetSizeConstraints --- atom/browser/native_window_views.cc | 139 +++++++++------------ atom/browser/native_window_views.h | 22 +--- atom/browser/ui/views/frameless_view.cc | 4 +- atom/browser/ui/views/native_frame_view.cc | 5 +- atom/browser/ui/views/native_frame_view.h | 6 +- atom/browser/ui/views/win_frame_view.cc | 4 +- 6 files changed, 71 insertions(+), 109 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 1c7546854ee2..fdcbe42205bf 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -186,7 +186,8 @@ NativeWindowViews::NativeWindowViews( // will not allow us to resize the window larger than scree. // Setting directly to INT_MAX somehow doesn't work, so we just devide // by 10, which should still be large enough. - maximum_size_.SetSize(INT_MAX / 10, INT_MAX / 10); + SetContentSizeConstraints(extensions::SizeConstraints( + gfx::Size(), gfx::Size(INT_MAX / 10, INT_MAX / 10))); int width = 800, height = 600; options.Get(switches::kWidth, &width); @@ -271,11 +272,6 @@ NativeWindowViews::NativeWindowViews( set_background(views::Background::CreateStandardPanelBackground()); AddChildView(web_view_); - if (has_frame() && - options.Get(switches::kUseContentSize, &use_content_size_) && - use_content_size_) - bounds = ContentBoundsToWindowBounds(bounds); - #if defined(OS_WIN) // Save initial window state. if (fullscreen) @@ -316,8 +312,14 @@ NativeWindowViews::NativeWindowViews( if (transparent() && !has_frame()) wm::SetShadowType(GetNativeWindow(), wm::SHADOW_TYPE_NONE); + gfx::Size size = bounds.size(); + if (has_frame() && + options.Get(switches::kUseContentSize, &use_content_size_) && + use_content_size_) + size = ContentSizeToWindowSize(size); + window_->UpdateWindowIcon(); - window_->CenterWindow(bounds.size()); + window_->CenterWindow(size); Layout(); } @@ -440,60 +442,6 @@ gfx::Rect NativeWindowViews::GetBounds() { return window_->GetWindowBoundsInScreen(); } -void NativeWindowViews::SetSizeConstraints( - const extensions::SizeConstraints& size_constraints) { -} - -extensions::SizeConstraints NativeWindowViews::GetSizeConstraints() { - return extensions::SizeConstraints(); -} - -void NativeWindowViews::SetContentSizeConstraints( - const extensions::SizeConstraints& size_constraints) { -} - -extensions::SizeConstraints NativeWindowViews::GetContentSizeConstraints() { - return extensions::SizeConstraints(); -} - -void NativeWindowViews::SetContentSize(const gfx::Size& size) { - if (!has_frame()) { - NativeWindow::SetSize(size); - return; - } - - gfx::Rect bounds = window_->GetWindowBoundsInScreen(); - bounds.set_size(size); - SetBounds(ContentBoundsToWindowBounds(bounds)); -} - -gfx::Size NativeWindowViews::GetContentSize() { - if (!has_frame()) - return GetSize(); - - gfx::Size content_size = - window_->non_client_view()->frame_view()->GetBoundsForClientView().size(); - if (menu_bar_ && menu_bar_visible_) - content_size.set_height(content_size.height() - kMenuBarHeight); - return content_size; -} - -void NativeWindowViews::SetMinimumSize(const gfx::Size& size) { - minimum_size_ = size; -} - -gfx::Size NativeWindowViews::GetMinimumSize() { - return minimum_size_; -} - -void NativeWindowViews::SetMaximumSize(const gfx::Size& size) { - maximum_size_ = size; -} - -gfx::Size NativeWindowViews::GetMaximumSize() { - return maximum_size_; -} - void NativeWindowViews::SetResizable(bool resizable) { #if defined(OS_WIN) // WS_MAXIMIZEBOX => Maximize button @@ -929,6 +877,47 @@ gfx::Size NativeWindowViews::WindowSizeToFramelessSize( return window_bounds.size(); } +gfx::Size NativeWindowViews::ContentSizeToWindowSize(const gfx::Size& size) { + if (!has_frame()) + return size; + + gfx::Size window_size(size); +#if defined(OS_WIN) + gfx::Rect dpi_bounds = + gfx::Rect(gfx::Point(), gfx::win::DIPToScreenSize(size)); + gfx::Rect window_bounds = gfx::win::ScreenToDIPRect( + window_->non_client_view()->GetWindowBoundsForClientBounds(dpi_bounds)); + window_size = window_bounds.size(); +#endif + + if (menu_bar_ && menu_bar_visible_) + window_size.set_height(window_size.height() + kMenuBarHeight); + return window_size; +} + +gfx::Size NativeWindowViews::WindowSizeToContentSize(const gfx::Size& size) { + if (!has_frame()) + return size; + + gfx::Size content_size(size); +#if defined(OS_WIN) + content_size = gfx::win::DIPToScreenSize(content_size); + RECT rect; + SetRectEmpty(&rect); + HWND hwnd = GetAcceleratedWidget(); + DWORD style = ::GetWindowLong(hwnd, GWL_STYLE); + DWORD ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE); + AdjustWindowRectEx(&rect, style, FALSE, ex_style); + content_size.set_width(content_size.width() - (rect.right - rect.left)); + content_size.set_height(content_size.height() - (rect.bottom - rect.top)); + content_size = gfx::win::ScreenToDIPSize(content_size); +#endif + + if (menu_bar_ && menu_bar_visible_) + content_size.set_height(content_size.height() - kMenuBarHeight); + return content_size; +} + void NativeWindowViews::HandleKeyboardEvent( content::WebContents*, const content::NativeWebKeyboardEvent& event) { @@ -970,6 +959,14 @@ void NativeWindowViews::HandleKeyboardEvent( } } +gfx::Size NativeWindowViews::GetMinimumSize() { + return NativeWindow::GetMinimumSize(); +} + +gfx::Size NativeWindowViews::GetMaximumSize() { + return NativeWindow::GetMaximumSize(); +} + bool NativeWindowViews::AcceleratorPressed(const ui::Accelerator& accelerator) { return accelerator_util::TriggerAcceleratorTableCommand( &accelerator_table_, accelerator); @@ -992,26 +989,6 @@ void NativeWindowViews::RegisterAccelerators(ui::MenuModel* menu_model) { } } -gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds( - const gfx::Rect& bounds) { - gfx::Point origin = bounds.origin(); -#if defined(OS_WIN) - gfx::Rect dpi_bounds = gfx::win::DIPToScreenRect(bounds); - gfx::Rect window_bounds = gfx::win::ScreenToDIPRect( - window_->non_client_view()->GetWindowBoundsForClientBounds(dpi_bounds)); -#else - gfx::Rect window_bounds = - window_->non_client_view()->GetWindowBoundsForClientBounds(bounds); -#endif - // The window's position would also be changed, but we only want to change - // the size. - window_bounds.set_origin(origin); - - if (menu_bar_ && menu_bar_visible_) - window_bounds.set_height(window_bounds.height() + kMenuBarHeight); - return window_bounds; -} - ui::WindowShowState NativeWindowViews::GetRestoredState() { if (IsMaximized()) return ui::SHOW_STATE_MAXIMIZED; diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 5a90e6a22139..0e74410868e1 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -63,18 +63,6 @@ class NativeWindowViews : public NativeWindow, bool IsFullscreen() const override; void SetBounds(const gfx::Rect& bounds) override; gfx::Rect GetBounds() override; - void SetSizeConstraints( - const extensions::SizeConstraints& size_constraints) override; - extensions::SizeConstraints GetSizeConstraints() override; - void SetContentSizeConstraints( - const extensions::SizeConstraints& size_constraints) override; - extensions::SizeConstraints GetContentSizeConstraints() override; - void SetContentSize(const gfx::Size& size) override; - gfx::Size GetContentSize() override; - void SetMinimumSize(const gfx::Size& size) override; - gfx::Size GetMinimumSize() override; - void SetMaximumSize(const gfx::Size& size) override; - gfx::Size GetMaximumSize() override; void SetResizable(bool resizable) override; bool IsResizable() override; void SetAlwaysOnTop(bool top) override; @@ -148,20 +136,20 @@ class NativeWindowViews : public NativeWindow, #endif // NativeWindow: + gfx::Size ContentSizeToWindowSize(const gfx::Size& size) override; + gfx::Size WindowSizeToContentSize(const gfx::Size& size) override; void HandleKeyboardEvent( content::WebContents*, const content::NativeWebKeyboardEvent& event) override; // views::View: + gfx::Size GetMinimumSize() override; + gfx::Size GetMaximumSize() override; bool AcceleratorPressed(const ui::Accelerator& accelerator) override; // Register accelerators supported by the menu model. void RegisterAccelerators(ui::MenuModel* menu_model); - // Converts between client area and window area, since we include the menu bar - // in client area we need to substract/add menu bar's height in convertions. - gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& content_bounds); - // Returns the restore state for the window. ui::WindowShowState GetRestoredState(); @@ -203,8 +191,6 @@ class NativeWindowViews : public NativeWindow, bool use_content_size_; bool resizable_; std::string title_; - gfx::Size minimum_size_; - gfx::Size maximum_size_; gfx::Size widget_size_; DISALLOW_COPY_AND_ASSIGN(NativeWindowViews); diff --git a/atom/browser/ui/views/frameless_view.cc b/atom/browser/ui/views/frameless_view.cc index 03a31e082874..f5e28025e9bf 100644 --- a/atom/browser/ui/views/frameless_view.cc +++ b/atom/browser/ui/views/frameless_view.cc @@ -104,11 +104,11 @@ gfx::Size FramelessView::GetPreferredSize() const { } gfx::Size FramelessView::GetMinimumSize() const { - return window_->GetMinimumSize(); + return static_cast(window_)->GetMinimumSize(); } gfx::Size FramelessView::GetMaximumSize() const { - return window_->GetMaximumSize(); + return static_cast(window_)->GetMaximumSize(); } const char* FramelessView::GetClassName() const { diff --git a/atom/browser/ui/views/native_frame_view.cc b/atom/browser/ui/views/native_frame_view.cc index a434fb434961..134255f48458 100644 --- a/atom/browser/ui/views/native_frame_view.cc +++ b/atom/browser/ui/views/native_frame_view.cc @@ -4,7 +4,7 @@ #include "atom/browser/ui/views/native_frame_view.h" -#include "atom/browser/native_window_views.h" +#include "atom/browser/native_window.h" namespace atom { @@ -14,8 +14,7 @@ const char kViewClassName[] = "AtomNativeFrameView"; } // namespace -NativeFrameView::NativeFrameView(NativeWindowViews* window, - views::Widget* widget) +NativeFrameView::NativeFrameView(NativeWindow* window, views::Widget* widget) : views::NativeFrameView(widget), window_(window) { } diff --git a/atom/browser/ui/views/native_frame_view.h b/atom/browser/ui/views/native_frame_view.h index acbe9cddc8dc..670459f1cbd0 100644 --- a/atom/browser/ui/views/native_frame_view.h +++ b/atom/browser/ui/views/native_frame_view.h @@ -9,13 +9,13 @@ namespace atom { -class NativeWindowViews; +class NativeWindow; // Like the views::NativeFrameView, but returns the min/max size from the // NativeWindowViews. class NativeFrameView : public views::NativeFrameView { public: - NativeFrameView(NativeWindowViews* window, views::Widget* widget); + NativeFrameView(NativeWindow* window, views::Widget* widget); protected: // views::View: @@ -24,7 +24,7 @@ class NativeFrameView : public views::NativeFrameView { const char* GetClassName() const override; private: - NativeWindowViews* window_; // weak ref. + NativeWindow* window_; // weak ref. DISALLOW_COPY_AND_ASSIGN(NativeFrameView); }; diff --git a/atom/browser/ui/views/win_frame_view.cc b/atom/browser/ui/views/win_frame_view.cc index d0338af19d9a..7106d8f759cf 100644 --- a/atom/browser/ui/views/win_frame_view.cc +++ b/atom/browser/ui/views/win_frame_view.cc @@ -41,13 +41,13 @@ int WinFrameView::NonClientHitTest(const gfx::Point& point) { gfx::Size WinFrameView::GetMinimumSize() const { gfx::Size size = window_->WindowSizeToFramelessSize( - window_->GetMinimumSize()); + FramelessView::GetMinimumSize()); return gfx::win::DIPToScreenSize(size); } gfx::Size WinFrameView::GetMaximumSize() const { gfx::Size size = window_->WindowSizeToFramelessSize( - window_->GetMaximumSize()); + FramelessView::GetMaximumSize()); return gfx::win::DIPToScreenSize(size); } From 279407f7a300e0914b5fdc6b0b6cb0fb3b23a2f8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 19:32:23 +0800 Subject: [PATCH 088/738] osx: Fix converting size for frameless window --- atom/browser/native_window_mac.mm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 76f9b0d0de07..70c3cfc0cc7b 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -789,12 +789,18 @@ void NativeWindowMac::HandleKeyboardEvent( } gfx::Size NativeWindowMac::ContentSizeToWindowSize(const gfx::Size& size) { + if (!has_frame()) + return size; + NSRect content = NSMakeRect(0, 0, size.width(), size.height()); NSRect frame = [window_ frameRectForContentRect:content]; return gfx::Size(frame.size); } gfx::Size NativeWindowMac::WindowSizeToContentSize(const gfx::Size& size) { + if (!has_frame()) + return size; + NSRect frame = NSMakeRect(0, 0, size.width(), size.height()); NSRect content = [window_ contentRectForFrameRect:frame]; return gfx::Size(content.size); From a9b0111c3e312d5797d1d4e5e64447f50e856467 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 20:03:43 +0800 Subject: [PATCH 089/738] views: Use the quicker way of return content size Converting content size to window size on high DPI systems will lose percise and have 1px offset sometimes. --- atom/browser/native_window_views.cc | 4 ++++ atom/browser/native_window_views.h | 1 + 2 files changed, 5 insertions(+) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index fdcbe42205bf..0264ac59e1a7 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -442,6 +442,10 @@ gfx::Rect NativeWindowViews::GetBounds() { return window_->GetWindowBoundsInScreen(); } +gfx::Size NativeWindowViews::GetContentSize() { + return web_view_->size(); +} + void NativeWindowViews::SetResizable(bool resizable) { #if defined(OS_WIN) // WS_MAXIMIZEBOX => Maximize button diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 0e74410868e1..1ba02e89a3af 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -63,6 +63,7 @@ class NativeWindowViews : public NativeWindow, bool IsFullscreen() const override; void SetBounds(const gfx::Rect& bounds) override; gfx::Rect GetBounds() override; + gfx::Size GetContentSize() override; void SetResizable(bool resizable) override; bool IsResizable() override; void SetAlwaysOnTop(bool top) override; From d19ead1907acbbf60b069f25709562d66cf6aad8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 20:09:29 +0800 Subject: [PATCH 090/738] osx: Call setContentMinSize in SetContentSizeConstraints --- atom/browser/native_window_mac.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 70c3cfc0cc7b..bb00a82451c1 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -559,11 +559,11 @@ void NativeWindowMac::SetContentSizeConstraints( NSView* content = [window_ contentView]; if (size_constraints.HasMinimumSize()) { NSSize min_size = ToNSSize(size_constraints.GetMinimumSize()); - [window_ setMinSize:[content convertSize:min_size toView:nil]]; + [window_ setContentMinSize:[content convertSize:min_size toView:nil]]; } if (size_constraints.HasMaximumSize()) { NSSize max_size = ToNSSize(size_constraints.GetMaximumSize()); - [window_ setMaxSize:[content convertSize:max_size toView:nil]]; + [window_ setContentMaxSize:[content convertSize:max_size toView:nil]]; } NativeWindow::SetContentSizeConstraints(size_constraints); } From e675407552c808a43dea74ad8796cd0fa9d8c05e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 20:36:28 +0800 Subject: [PATCH 091/738] Make min/max size respect use-content-size --- atom/browser/native_window.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index cad6942d2e99..f8023222fb79 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -119,15 +119,23 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { } else if (options.Get(switches::kCenter, ¢er) && center) { Center(); } + extensions::SizeConstraints size_constraints; int min_height = 0, min_width = 0; if (options.Get(switches::kMinHeight, &min_height) | options.Get(switches::kMinWidth, &min_width)) { - SetMinimumSize(gfx::Size(min_width, min_height)); + size_constraints.set_minimum_size(gfx::Size(min_width, min_height)); } int max_height = INT_MAX, max_width = INT_MAX; if (options.Get(switches::kMaxHeight, &max_height) | options.Get(switches::kMaxWidth, &max_width)) { - SetMaximumSize(gfx::Size(max_width, max_height)); + size_constraints.set_maximum_size(gfx::Size(max_width, max_height)); + } + bool use_content_size = false; + options.Get(switches::kUseContentSize, &use_content_size); + if (use_content_size) { + SetContentSizeConstraints(size_constraints); + } else { + SetSizeConstraints(size_constraints); } bool resizable; if (options.Get(switches::kResizable, &resizable)) { From 3b1ee994e21f5afc361c830913bce175a37a6217 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 20:37:08 +0800 Subject: [PATCH 092/738] views: Remove hack on setting min/max size for frameless window --- atom/browser/native_window_views.cc | 27 ------------------------- atom/browser/native_window_views.h | 2 -- atom/browser/ui/views/frameless_view.cc | 4 ++-- atom/browser/ui/views/win_frame_view.cc | 13 ------------ atom/browser/ui/views/win_frame_view.h | 2 -- 5 files changed, 2 insertions(+), 46 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 0264ac59e1a7..5cd99dbdefb2 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -854,33 +854,6 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) { } #endif -gfx::Size NativeWindowViews::WindowSizeToFramelessSize( - const gfx::Size& size) { - if (size.width() == 0 && size.height() == 0) - return size; - - gfx::Rect window_bounds = gfx::Rect(size); - if (use_content_size_) { - if (menu_bar_ && menu_bar_visible_) { - window_bounds.set_height(window_bounds.height() + kMenuBarHeight); - } - } else if (has_frame()) { -#if defined(OS_WIN) - gfx::Size frame_size = gfx::win::ScreenToDIPRect( - window_->non_client_view()->GetWindowBoundsForClientBounds( - gfx::Rect())).size(); -#else - gfx::Size frame_size = - window_->non_client_view()->GetWindowBoundsForClientBounds( - gfx::Rect()).size(); -#endif - window_bounds.set_height(window_bounds.height() - frame_size.height()); - window_bounds.set_width(window_bounds.width() - frame_size.width()); - } - - return window_bounds.size(); -} - gfx::Size NativeWindowViews::ContentSizeToWindowSize(const gfx::Size& size) { if (!has_frame()) return size; diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 1ba02e89a3af..35ca7b63e25c 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -89,8 +89,6 @@ class NativeWindowViews : public NativeWindow, gfx::AcceleratedWidget GetAcceleratedWidget(); - gfx::Size WindowSizeToFramelessSize(const gfx::Size& size); - views::Widget* widget() const { return window_.get(); } #if defined(OS_WIN) diff --git a/atom/browser/ui/views/frameless_view.cc b/atom/browser/ui/views/frameless_view.cc index f5e28025e9bf..2ec4459f6b45 100644 --- a/atom/browser/ui/views/frameless_view.cc +++ b/atom/browser/ui/views/frameless_view.cc @@ -104,11 +104,11 @@ gfx::Size FramelessView::GetPreferredSize() const { } gfx::Size FramelessView::GetMinimumSize() const { - return static_cast(window_)->GetMinimumSize(); + return window_->GetContentSizeConstraints().GetMinimumSize(); } gfx::Size FramelessView::GetMaximumSize() const { - return static_cast(window_)->GetMaximumSize(); + return window_->GetContentSizeConstraints().GetMaximumSize(); } const char* FramelessView::GetClassName() const { diff --git a/atom/browser/ui/views/win_frame_view.cc b/atom/browser/ui/views/win_frame_view.cc index 7106d8f759cf..fca7cb23347c 100644 --- a/atom/browser/ui/views/win_frame_view.cc +++ b/atom/browser/ui/views/win_frame_view.cc @@ -5,7 +5,6 @@ #include "atom/browser/ui/views/win_frame_view.h" #include "atom/browser/native_window_views.h" -#include "ui/gfx/win/dpi.h" #include "ui/views/widget/widget.h" #include "ui/views/win/hwnd_util.h" @@ -39,18 +38,6 @@ int WinFrameView::NonClientHitTest(const gfx::Point& point) { return FramelessView::NonClientHitTest(point); } -gfx::Size WinFrameView::GetMinimumSize() const { - gfx::Size size = window_->WindowSizeToFramelessSize( - FramelessView::GetMinimumSize()); - return gfx::win::DIPToScreenSize(size); -} - -gfx::Size WinFrameView::GetMaximumSize() const { - gfx::Size size = window_->WindowSizeToFramelessSize( - FramelessView::GetMaximumSize()); - return gfx::win::DIPToScreenSize(size); -} - const char* WinFrameView::GetClassName() const { return kViewClassName; } diff --git a/atom/browser/ui/views/win_frame_view.h b/atom/browser/ui/views/win_frame_view.h index 825677bff310..b2c1ef3a15de 100644 --- a/atom/browser/ui/views/win_frame_view.h +++ b/atom/browser/ui/views/win_frame_view.h @@ -20,8 +20,6 @@ class WinFrameView : public FramelessView { int NonClientHitTest(const gfx::Point& point) override; // views::View: - gfx::Size GetMinimumSize() const override; - gfx::Size GetMaximumSize() const override; const char* GetClassName() const override; private: From 857acd25741969d390dec96a23ad65a01fdd93a1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 5 Oct 2015 21:06:57 +0800 Subject: [PATCH 093/738] win: Fix GetContentSize for minimized window --- atom/browser/native_window_views.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 5cd99dbdefb2..d7d6cf8addae 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -443,6 +443,11 @@ gfx::Rect NativeWindowViews::GetBounds() { } gfx::Size NativeWindowViews::GetContentSize() { +#if defined(OS_WIN) + if (IsMinimized()) + return NativeWindow::GetContentSize(); +#endif + return web_view_->size(); } From 239b97cde16896e127d1f814549e26ee474a4abf Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Mon, 5 Oct 2015 16:51:49 +0300 Subject: [PATCH 094/738] Update process.md Fixed the `loaded` example according to [this](https://github.com/atom/electron/issues/2984#issuecomment-145465907) comment. --- docs/api/process.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/api/process.md b/docs/api/process.md index 4e0fa4d602ef..a2157886bc61 100644 --- a/docs/api/process.md +++ b/docs/api/process.md @@ -21,9 +21,11 @@ the global scope when node integration is turned off: ```js // preload.js +var _setImmediate = setImmediate; +var _clearImmediate = clearImmediate; process.once('loaded', function() { - global.setImmediate = setImmediate; - global.clearImmediate = clearImmediate; + global.setImmediate = _setImmediate; + global.clearImmediate = _clearImmediate; }); ``` From ea3e84e7ff38393449c70e447019342766836e2d Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Mon, 5 Oct 2015 16:56:36 +0300 Subject: [PATCH 095/738] Update screen.md Removed a trailing comma. --- docs/api/screen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/screen.md b/docs/api/screen.md index 3b6c276daf34..42468da16005 100644 --- a/docs/api/screen.md +++ b/docs/api/screen.md @@ -47,7 +47,7 @@ app.on('ready', function() { if (externalDisplay) { mainWindow = new BrowserWindow({ x: externalDisplay.bounds.x + 50, - y: externalDisplay.bounds.y + 50, + y: externalDisplay.bounds.y + 50 }); } }); From 87e0c812e9de44c96b33a65432decbd012c2d17a Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Mon, 5 Oct 2015 17:48:48 +0300 Subject: [PATCH 096/738] Update native modules doc --- docs/tutorial/using-native-node-modules.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/tutorial/using-native-node-modules.md b/docs/tutorial/using-native-node-modules.md index 0e6477fc4c04..491415b900ac 100644 --- a/docs/tutorial/using-native-node-modules.md +++ b/docs/tutorial/using-native-node-modules.md @@ -6,16 +6,17 @@ the location of Electron's headers when building native modules. ## Native Node Module Compatibility -Since Node v0.11.x there were vital changes in the V8 API. So generally all -native modules written for Node v0.10.x won't work for newer Node or io.js -versions. And because Electron internally uses __io.js v3.1.0__, it has the -same problem. +Native modules might break when Node starts using a new version of V8. +To make sure the module you're interested in will work with Electron, you should +check if it supports the internal Node version used by Electron. +You can check what version of Node is used in Electron by looking it up in +the [releases](https://github.com/atom/electron/releases) page or by using +`process.version` (see [Quick Start](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md) +for example). -To solve this, you should use modules that support Node v0.11.x or later, -[many modules](https://www.npmjs.org/browse/depended/nan) do support both now. -For old modules that only support Node v0.10.x, you should use the -[nan](https://github.com/rvagg/nan) module to port it to v0.11.x or later -versions of Node or io.js. +Consider using [NAN](https://github.com/nodejs/nan/) for your own modules, since +it makes it easier to support multiple versions of Node. It's also helpful for +porting old modules to newer versions of Node so they can work with Electron. ## How to Install Native Modules From bb4951514582b366a91b4367158e710f5cc1eee0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 00:13:57 +0800 Subject: [PATCH 097/738] Separate Windows specific code of NativeWindow to another file --- atom/browser/native_window_views.cc | 136 ---------------------- atom/browser/native_window_views_win.cc | 145 ++++++++++++++++++++++++ filenames.gypi | 1 + 3 files changed, 146 insertions(+), 136 deletions(-) create mode 100644 atom/browser/native_window_views_win.cc diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index d7d6cf8addae..308e8ee3dcc0 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -77,70 +77,6 @@ bool IsAltModifier(const content::NativeWebKeyboardEvent& event) { (modifiers == (Modifiers::AltKey | Modifiers::IsRight)); } -#if defined(OS_WIN) -// Convert Win32 WM_APPCOMMANDS to strings. -const char* AppCommandToString(int command_id) { - switch (command_id) { - case APPCOMMAND_BROWSER_BACKWARD : return "browser-backward"; - case APPCOMMAND_BROWSER_FORWARD : return "browser-forward"; - case APPCOMMAND_BROWSER_REFRESH : return "browser-refresh"; - case APPCOMMAND_BROWSER_STOP : return "browser-stop"; - case APPCOMMAND_BROWSER_SEARCH : return "browser-search"; - case APPCOMMAND_BROWSER_FAVORITES : return "browser-favorites"; - case APPCOMMAND_BROWSER_HOME : return "browser-home"; - case APPCOMMAND_VOLUME_MUTE : return "volume-mute"; - case APPCOMMAND_VOLUME_DOWN : return "volume-down"; - case APPCOMMAND_VOLUME_UP : return "volume-up"; - case APPCOMMAND_MEDIA_NEXTTRACK : return "media-nexttrack"; - case APPCOMMAND_MEDIA_PREVIOUSTRACK : return "media-previoustrack"; - case APPCOMMAND_MEDIA_STOP : return "media-stop"; - case APPCOMMAND_MEDIA_PLAY_PAUSE : return "media-play_pause"; - case APPCOMMAND_LAUNCH_MAIL : return "launch-mail"; - case APPCOMMAND_LAUNCH_MEDIA_SELECT : return "launch-media-select"; - case APPCOMMAND_LAUNCH_APP1 : return "launch-app1"; - case APPCOMMAND_LAUNCH_APP2 : return "launch-app2"; - case APPCOMMAND_BASS_DOWN : return "bass-down"; - case APPCOMMAND_BASS_BOOST : return "bass-boost"; - case APPCOMMAND_BASS_UP : return "bass-up"; - case APPCOMMAND_TREBLE_DOWN : return "treble-down"; - case APPCOMMAND_TREBLE_UP : return "treble-up"; - case APPCOMMAND_MICROPHONE_VOLUME_MUTE : return "microphone-volume-mute"; - case APPCOMMAND_MICROPHONE_VOLUME_DOWN : return "microphone-volume-down"; - case APPCOMMAND_MICROPHONE_VOLUME_UP : return "microphone-volume-up"; - case APPCOMMAND_HELP : return "help"; - case APPCOMMAND_FIND : return "find"; - case APPCOMMAND_NEW : return "new"; - case APPCOMMAND_OPEN : return "open"; - case APPCOMMAND_CLOSE : return "close"; - case APPCOMMAND_SAVE : return "save"; - case APPCOMMAND_PRINT : return "print"; - case APPCOMMAND_UNDO : return "undo"; - case APPCOMMAND_REDO : return "redo"; - case APPCOMMAND_COPY : return "copy"; - case APPCOMMAND_CUT : return "cut"; - case APPCOMMAND_PASTE : return "paste"; - case APPCOMMAND_REPLY_TO_MAIL : return "reply-to-mail"; - case APPCOMMAND_FORWARD_MAIL : return "forward-mail"; - case APPCOMMAND_SEND_MAIL : return "send-mail"; - case APPCOMMAND_SPELL_CHECK : return "spell-check"; - case APPCOMMAND_MIC_ON_OFF_TOGGLE : return "mic-on-off-toggle"; - case APPCOMMAND_CORRECTION_LIST : return "correction-list"; - case APPCOMMAND_MEDIA_PLAY : return "media-play"; - case APPCOMMAND_MEDIA_PAUSE : return "media-pause"; - case APPCOMMAND_MEDIA_RECORD : return "media-record"; - case APPCOMMAND_MEDIA_FAST_FORWARD : return "media-fast-forward"; - case APPCOMMAND_MEDIA_REWIND : return "media-rewind"; - case APPCOMMAND_MEDIA_CHANNEL_UP : return "media-channel-up"; - case APPCOMMAND_MEDIA_CHANNEL_DOWN : return "media-channel-down"; - case APPCOMMAND_DELETE : return "delete"; - case APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE: - return "dictate-or-command-control-toggle"; - default: - return "unknown"; - } -} -#endif - class NativeWindowClientView : public views::ClientView { public: NativeWindowClientView(views::Widget* widget, @@ -787,78 +723,6 @@ void NativeWindowViews::OnWidgetMove() { NotifyWindowMove(); } -#if defined(OS_WIN) -bool NativeWindowViews::ExecuteWindowsCommand(int command_id) { - std::string command = AppCommandToString(command_id); - NotifyWindowExecuteWindowsCommand(command); - return false; -} - -bool NativeWindowViews::PreHandleMSG( - UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) { - switch (message) { - case WM_COMMAND: - // Handle thumbar button click message. - if (HIWORD(w_param) == THBN_CLICKED) - return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param)); - return false; - case WM_SIZE: - // Handle window state change. - HandleSizeEvent(w_param, l_param); - return false; - default: - return false; - } -} - -void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) { - // Here we handle the WM_SIZE event in order to figure out what is the current - // window state and notify the user accordingly. - switch (w_param) { - case SIZE_MAXIMIZED: - last_window_state_ = ui::SHOW_STATE_MAXIMIZED; - NotifyWindowMaximize(); - break; - case SIZE_MINIMIZED: - last_window_state_ = ui::SHOW_STATE_MINIMIZED; - NotifyWindowMinimize(); - break; - case SIZE_RESTORED: - if (last_window_state_ == ui::SHOW_STATE_NORMAL) { - // Window was resized so we save it's new size. - last_normal_size_ = GetSize(); - } else { - switch (last_window_state_) { - case ui::SHOW_STATE_MAXIMIZED: - last_window_state_ = ui::SHOW_STATE_NORMAL; - - // When the window is restored we resize it to the previous known - // normal size. - NativeWindow::SetSize(last_normal_size_); - - NotifyWindowUnmaximize(); - break; - case ui::SHOW_STATE_MINIMIZED: - if (IsFullscreen()) { - last_window_state_ = ui::SHOW_STATE_FULLSCREEN; - NotifyWindowEnterFullScreen(); - } else { - last_window_state_ = ui::SHOW_STATE_NORMAL; - - // When the window is restored we resize it to the previous known - // normal size. - NativeWindow::SetSize(last_normal_size_); - - NotifyWindowRestore(); - } - break; - } - } - break; - } -} -#endif - gfx::Size NativeWindowViews::ContentSizeToWindowSize(const gfx::Size& size) { if (!has_frame()) return size; diff --git a/atom/browser/native_window_views_win.cc b/atom/browser/native_window_views_win.cc new file mode 100644 index 000000000000..79c512894377 --- /dev/null +++ b/atom/browser/native_window_views_win.cc @@ -0,0 +1,145 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/native_window_views.h" + +namespace atom { + +namespace { + +// Convert Win32 WM_APPCOMMANDS to strings. +const char* AppCommandToString(int command_id) { + switch (command_id) { + case APPCOMMAND_BROWSER_BACKWARD : return "browser-backward"; + case APPCOMMAND_BROWSER_FORWARD : return "browser-forward"; + case APPCOMMAND_BROWSER_REFRESH : return "browser-refresh"; + case APPCOMMAND_BROWSER_STOP : return "browser-stop"; + case APPCOMMAND_BROWSER_SEARCH : return "browser-search"; + case APPCOMMAND_BROWSER_FAVORITES : return "browser-favorites"; + case APPCOMMAND_BROWSER_HOME : return "browser-home"; + case APPCOMMAND_VOLUME_MUTE : return "volume-mute"; + case APPCOMMAND_VOLUME_DOWN : return "volume-down"; + case APPCOMMAND_VOLUME_UP : return "volume-up"; + case APPCOMMAND_MEDIA_NEXTTRACK : return "media-nexttrack"; + case APPCOMMAND_MEDIA_PREVIOUSTRACK : return "media-previoustrack"; + case APPCOMMAND_MEDIA_STOP : return "media-stop"; + case APPCOMMAND_MEDIA_PLAY_PAUSE : return "media-play_pause"; + case APPCOMMAND_LAUNCH_MAIL : return "launch-mail"; + case APPCOMMAND_LAUNCH_MEDIA_SELECT : return "launch-media-select"; + case APPCOMMAND_LAUNCH_APP1 : return "launch-app1"; + case APPCOMMAND_LAUNCH_APP2 : return "launch-app2"; + case APPCOMMAND_BASS_DOWN : return "bass-down"; + case APPCOMMAND_BASS_BOOST : return "bass-boost"; + case APPCOMMAND_BASS_UP : return "bass-up"; + case APPCOMMAND_TREBLE_DOWN : return "treble-down"; + case APPCOMMAND_TREBLE_UP : return "treble-up"; + case APPCOMMAND_MICROPHONE_VOLUME_MUTE : return "microphone-volume-mute"; + case APPCOMMAND_MICROPHONE_VOLUME_DOWN : return "microphone-volume-down"; + case APPCOMMAND_MICROPHONE_VOLUME_UP : return "microphone-volume-up"; + case APPCOMMAND_HELP : return "help"; + case APPCOMMAND_FIND : return "find"; + case APPCOMMAND_NEW : return "new"; + case APPCOMMAND_OPEN : return "open"; + case APPCOMMAND_CLOSE : return "close"; + case APPCOMMAND_SAVE : return "save"; + case APPCOMMAND_PRINT : return "print"; + case APPCOMMAND_UNDO : return "undo"; + case APPCOMMAND_REDO : return "redo"; + case APPCOMMAND_COPY : return "copy"; + case APPCOMMAND_CUT : return "cut"; + case APPCOMMAND_PASTE : return "paste"; + case APPCOMMAND_REPLY_TO_MAIL : return "reply-to-mail"; + case APPCOMMAND_FORWARD_MAIL : return "forward-mail"; + case APPCOMMAND_SEND_MAIL : return "send-mail"; + case APPCOMMAND_SPELL_CHECK : return "spell-check"; + case APPCOMMAND_MIC_ON_OFF_TOGGLE : return "mic-on-off-toggle"; + case APPCOMMAND_CORRECTION_LIST : return "correction-list"; + case APPCOMMAND_MEDIA_PLAY : return "media-play"; + case APPCOMMAND_MEDIA_PAUSE : return "media-pause"; + case APPCOMMAND_MEDIA_RECORD : return "media-record"; + case APPCOMMAND_MEDIA_FAST_FORWARD : return "media-fast-forward"; + case APPCOMMAND_MEDIA_REWIND : return "media-rewind"; + case APPCOMMAND_MEDIA_CHANNEL_UP : return "media-channel-up"; + case APPCOMMAND_MEDIA_CHANNEL_DOWN : return "media-channel-down"; + case APPCOMMAND_DELETE : return "delete"; + case APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE: + return "dictate-or-command-control-toggle"; + default: + return "unknown"; + } +} + +} // namespace + +bool NativeWindowViews::ExecuteWindowsCommand(int command_id) { + std::string command = AppCommandToString(command_id); + NotifyWindowExecuteWindowsCommand(command); + return false; +} + +bool NativeWindowViews::PreHandleMSG( + UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) { + switch (message) { + case WM_COMMAND: + // Handle thumbar button click message. + if (HIWORD(w_param) == THBN_CLICKED) + return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param)); + return false; + case WM_SIZE: + // Handle window state change. + HandleSizeEvent(w_param, l_param); + return false; + default: + return false; + } +} + +void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) { + // Here we handle the WM_SIZE event in order to figure out what is the current + // window state and notify the user accordingly. + switch (w_param) { + case SIZE_MAXIMIZED: + last_window_state_ = ui::SHOW_STATE_MAXIMIZED; + NotifyWindowMaximize(); + break; + case SIZE_MINIMIZED: + last_window_state_ = ui::SHOW_STATE_MINIMIZED; + NotifyWindowMinimize(); + break; + case SIZE_RESTORED: + if (last_window_state_ == ui::SHOW_STATE_NORMAL) { + // Window was resized so we save it's new size. + last_normal_size_ = GetSize(); + } else { + switch (last_window_state_) { + case ui::SHOW_STATE_MAXIMIZED: + last_window_state_ = ui::SHOW_STATE_NORMAL; + + // When the window is restored we resize it to the previous known + // normal size. + SetSize(last_normal_size_); + + NotifyWindowUnmaximize(); + break; + case ui::SHOW_STATE_MINIMIZED: + if (IsFullscreen()) { + last_window_state_ = ui::SHOW_STATE_FULLSCREEN; + NotifyWindowEnterFullScreen(); + } else { + last_window_state_ = ui::SHOW_STATE_NORMAL; + + // When the window is restored we resize it to the previous known + // normal size. + SetSize(last_normal_size_); + + NotifyWindowRestore(); + } + break; + } + } + break; + } +} + +} // namespace atom diff --git a/filenames.gypi b/filenames.gypi index a6e799cd67c1..6418ba287214 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -154,6 +154,7 @@ 'atom/browser/mac/atom_application_delegate.mm', 'atom/browser/native_window.cc', 'atom/browser/native_window.h', + 'atom/browser/native_window_views_win.cc', 'atom/browser/native_window_views.cc', 'atom/browser/native_window_views.h', 'atom/browser/native_window_mac.h', From 60fb406c614af764b21df19ff1cc654ee2c1edda Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 00:15:10 +0800 Subject: [PATCH 098/738] views: Fix content size constraints in window with menubar --- atom/browser/native_window_views.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 308e8ee3dcc0..0e04414b6a47 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -519,8 +519,24 @@ void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) { if (!menu_bar_autohide_) { SetMenuBarVisibility(true); - if (use_content_size_) + if (use_content_size_) { + // Enlarge the size constraints for the menu. + extensions::SizeConstraints constraints = GetContentSizeConstraints(); + if (constraints.HasMinimumSize()) { + gfx::Size min_size = constraints.GetMinimumSize(); + min_size.set_height(min_size.height() + kMenuBarHeight); + constraints.set_minimum_size(min_size); + } + if (constraints.HasMaximumSize()) { + gfx::Size max_size = constraints.GetMaximumSize(); + max_size.set_height(max_size.height() + kMenuBarHeight); + constraints.set_maximum_size(max_size); + } + SetContentSizeConstraints(constraints); + + // Resize the window to make sure content size is not changed. SetContentSize(content_size); + } } } From c8723238f8fc6abb68ad42a3f9411760e1fcd048 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 00:21:37 +0800 Subject: [PATCH 099/738] win: Fix building on Windows --- atom/browser/native_window_views_win.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/native_window_views_win.cc b/atom/browser/native_window_views_win.cc index 79c512894377..6092a2242ac0 100644 --- a/atom/browser/native_window_views_win.cc +++ b/atom/browser/native_window_views_win.cc @@ -118,7 +118,7 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) { // When the window is restored we resize it to the previous known // normal size. - SetSize(last_normal_size_); + NativeWindow::SetSize(last_normal_size_); NotifyWindowUnmaximize(); break; @@ -131,7 +131,7 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) { // When the window is restored we resize it to the previous known // normal size. - SetSize(last_normal_size_); + NativeWindow::SetSize(last_normal_size_); NotifyWindowRestore(); } From b70e7c6a4cc51548769075f3f9925430e2435746 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 00:39:16 +0800 Subject: [PATCH 100/738] Remove default definition of ContentSizeToWindowSize --- atom/browser/native_window.cc | 8 -------- atom/browser/native_window.h | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index f8023222fb79..641bdd3757a1 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -170,14 +170,6 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { Show(); } -gfx::Size NativeWindow::ContentSizeToWindowSize(const gfx::Size& size) { - return size; -} - -gfx::Size NativeWindow::WindowSizeToContentSize(const gfx::Size& size) { - return size; -} - void NativeWindow::SetSize(const gfx::Size& size) { SetBounds(gfx::Rect(GetPosition(), size)); } diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 538783306464..379c23837b19 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -242,8 +242,8 @@ class NativeWindow : public base::SupportsUserData, const mate::Dictionary& options); // Converts between content size to window size. - virtual gfx::Size ContentSizeToWindowSize(const gfx::Size& size); - virtual gfx::Size WindowSizeToContentSize(const gfx::Size& size); + virtual gfx::Size ContentSizeToWindowSize(const gfx::Size& size) = 0; + virtual gfx::Size WindowSizeToContentSize(const gfx::Size& size) = 0; // content::WebContentsObserver: void RenderViewCreated(content::RenderViewHost* render_view_host) override; From ccf4ed907a2ad95bcbb35925ec9ddf59195605a6 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Mon, 5 Oct 2015 19:11:20 +0200 Subject: [PATCH 101/738] Fix some minor bugs related to KeyboardEvent sending --- atom/common/keyboad_util.cc | 7 ++++--- atom/common/native_mate_converters/blink_converter.cc | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/atom/common/keyboad_util.cc b/atom/common/keyboad_util.cc index 1baa829ff74a..29d1a800c859 100644 --- a/atom/common/keyboad_util.cc +++ b/atom/common/keyboad_util.cc @@ -10,9 +10,10 @@ namespace atom { ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted) { *shifted = false; switch (c) { - case 8: case 0x7F: return ui::VKEY_BACK; - case 9: return ui::VKEY_TAB; - case 0xD: case 3: return ui::VKEY_RETURN; + case 0x08: return ui::VKEY_BACK; + case 0x7F: return ui::VKEY_DELETE; + case 0x09: return ui::VKEY_TAB; + case 0x0D: return ui::VKEY_RETURN; case 0x1B: return ui::VKEY_ESCAPE; case ' ': return ui::VKEY_SPACE; diff --git a/atom/common/native_mate_converters/blink_converter.cc b/atom/common/native_mate_converters/blink_converter.cc index 0a599bfdf015..fcfc8905b3e2 100644 --- a/atom/common/native_mate_converters/blink_converter.cc +++ b/atom/common/native_mate_converters/blink_converter.cc @@ -61,7 +61,7 @@ struct Converter { else if (type == "mousewheel") *out = blink::WebInputEvent::MouseWheel; else if (type == "keydown") - *out = blink::WebInputEvent::KeyDown; + *out = blink::WebInputEvent::RawKeyDown; else if (type == "keyup") *out = blink::WebInputEvent::KeyUp; else if (type == "char") From c3cd438d34a265074c2896a688811d5f71f6d60a Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Mon, 5 Oct 2015 21:12:29 +0300 Subject: [PATCH 102/738] Replace io.js references with node.js references --- README.md | 2 +- docs/api/native-image.md | 2 +- docs/tutorial/quick-start.md | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fa122c9b6c6f..94d4c09982be 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ :zap: *Formerly known as Atom Shell* :zap: The Electron framework lets you write cross-platform desktop applications -using JavaScript, HTML and CSS. It is based on [io.js](http://iojs.org) and +using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org) and [Chromium](http://www.chromium.org) and is used in the [Atom editor](https://github.com/atom/atom). diff --git a/docs/api/native-image.md b/docs/api/native-image.md index df2bb96ff9da..097a8130c243 100644 --- a/docs/api/native-image.md +++ b/docs/api/native-image.md @@ -142,7 +142,7 @@ Returns a boolean whether the image is empty. Returns the size of the image. -[buffer]: https://iojs.org/api/buffer.html#buffer_class_buffer +[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer ### `image.setTemplateImage(option)` diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index 94368df09c1c..5300d754a69b 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -2,7 +2,7 @@ Electron enables you to create desktop applications with pure JavaScript by providing a runtime with rich native (operating system) APIs. You could see it -as a variant of the io.js runtime that is focused on desktop applications +as a variant of the Node.js runtime that is focused on desktop applications instead of web servers. This doesn't mean Electron is a JavaScript binding to graphical user interface @@ -22,8 +22,9 @@ multi-process architecture is also used. Each web page in Electron runs in its own process, which is called __the renderer process__. In normal browsers, web pages usually run in a sandboxed environment and are not -allowed access to native resources. Electron users, however, have the power to use -io.js APIs in web pages allowing lower level operating system interactions. +allowed access to native resources. Electron users, however, have the power to +use Node.js APIs in web pages allowing lower level operating system +interactions. ### Differences Between Main Process and Renderer Process @@ -129,7 +130,7 @@ Finally the `index.html` is the web page you want to show:

Hello World!

- We are using io.js + We are using Node.js and Electron . From db46c1b92561a7145ff1920de1b49c085cc2d380 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Tue, 6 Oct 2015 13:48:39 +0900 Subject: [PATCH 103/738] Update as upstream --- docs-translations/ko-KR/api/process.md | 16 ++++++++++++++++ docs-translations/ko-KR/api/screen.md | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/process.md b/docs-translations/ko-KR/api/process.md index f557f8cc6be5..57ba0fa768a9 100644 --- a/docs-translations/ko-KR/api/process.md +++ b/docs-translations/ko-KR/api/process.md @@ -7,6 +7,22 @@ Electron의 `process` 객체는 기존의 node와는 달리 약간의 차이점 * `process.versions['chrome']` String - Chromium의 버전. * `process.resourcesPath` String - JavaScript 소스코드의 경로. +## Events + +### Event: 'loaded' + +Electron 내부 초기화 스크립트의 로드가 완료되고, 웹 페이지나 메인 스크립트를 로드하기 시작할 때 발생하는 이벤트입니다. + +이 이벤트는 preload 스크립트를 통해 node 통합이 꺼져있는 전역 스코프에 node의 전역 심볼들을 다시 추가할 때 사용할 수 있습니다: + +```javascript +// preload.js +process.once('loaded', function() { + global.setImmediate = setImmediate; + global.clearImmediate = clearImmediate; +}); +``` + ## Methods `process` 객체는 다음과 같은 메서드를 가지고 있습니다: diff --git a/docs-translations/ko-KR/api/screen.md b/docs-translations/ko-KR/api/screen.md index 2d3c02f85412..de2d8baf4e35 100644 --- a/docs-translations/ko-KR/api/screen.md +++ b/docs-translations/ko-KR/api/screen.md @@ -36,7 +36,7 @@ app.on('ready', function() { var displays = electronScreen.getAllDisplays(); var externalDisplay = null; for (var i in displays) { - if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) { + if (displays[i].bounds.x != 0 || displays[i].bounds.y != 0) { externalDisplay = displays[i]; break; } From 428c5b6d01fb0cc7aaa465ca98832d395e16e2b2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 14:50:18 +0800 Subject: [PATCH 104/738] Setting "x" and "y" should not change window size --- atom/browser/native_window.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 641bdd3757a1..981804cb22c9 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -112,10 +112,7 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { int x = -1, y = -1; bool center; if (options.Get(switches::kX, &x) && options.Get(switches::kY, &y)) { - int width = -1, height = -1; - options.Get(switches::kWidth, &width); - options.Get(switches::kHeight, &height); - SetBounds(gfx::Rect(x, y, width, height)); + SetPosition(gfx::Point(x, y)); } else if (options.Get(switches::kCenter, ¢er) && center) { Center(); } From 6fea6cf58acbc00a66837628d3a20d5bd1938fa1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 15:15:23 +0800 Subject: [PATCH 105/738] osx: Fix setting size constraints for frameless window --- atom/browser/native_window_mac.mm | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index bb00a82451c1..5f867d9b1a6c 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -22,11 +22,6 @@ namespace { -// Converts gfx::Size to NSSize. -inline NSSize ToNSSize(const gfx::Size& size) { - return NSMakeSize(size.width(), size.height()); -} - // Prevents window from resizing during the scope. class ScopedDisableResize { public: @@ -556,13 +551,25 @@ gfx::Rect NativeWindowMac::GetBounds() { void NativeWindowMac::SetContentSizeConstraints( const extensions::SizeConstraints& size_constraints) { + auto convertSize = [this](const gfx::Size& size) { + // Our frameless window still has titlebar attached, so setting contentSize + // will result in actual content size being larger. + if (!has_frame()) { + NSRect frame = NSMakeRect(0, 0, size.width(), size.height()); + NSRect content = [window_ contentRectForFrameRect:frame]; + return content.size; + } else { + return NSMakeSize(size.width(), size.height()); + } + }; + NSView* content = [window_ contentView]; if (size_constraints.HasMinimumSize()) { - NSSize min_size = ToNSSize(size_constraints.GetMinimumSize()); + NSSize min_size = convertSize(size_constraints.GetMinimumSize()); [window_ setContentMinSize:[content convertSize:min_size toView:nil]]; } if (size_constraints.HasMaximumSize()) { - NSSize max_size = ToNSSize(size_constraints.GetMaximumSize()); + NSSize max_size = convertSize(size_constraints.GetMaximumSize()); [window_ setContentMaxSize:[content convertSize:max_size toView:nil]]; } NativeWindow::SetContentSizeConstraints(size_constraints); From 898db4d6bd5838b2461174726d022054f19f123e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 15:23:23 +0800 Subject: [PATCH 106/738] osx: Set resizable flag when creating window Setting resizable for frameless window before it is shown will change its size. --- atom/browser/native_window.cc | 2 ++ atom/browser/native_window_mac.mm | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 981804cb22c9..dd4694b3bd6b 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -134,10 +134,12 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { } else { SetSizeConstraints(size_constraints); } +#if defined(OS_WIN) || defined(USE_X11) bool resizable; if (options.Get(switches::kResizable, &resizable)) { SetResizable(resizable); } +#endif bool top; if (options.Get(switches::kAlwaysOnTop, &top) && top) { SetAlwaysOnTop(true); diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 5f867d9b1a6c..6420345da9b6 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -350,6 +350,8 @@ NativeWindowMac::NativeWindowMac( bool useStandardWindow = true; options.Get(switches::kStandardWindow, &useStandardWindow); + bool resizable = true; + options.Get(switches::kResizable, &resizable); // New title bar styles are available in Yosemite or newer std::string titleBarStyle; @@ -357,10 +359,13 @@ NativeWindowMac::NativeWindowMac( options.Get(switches::kTitleBarStyle, &titleBarStyle); NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | NSResizableWindowMask; + NSMiniaturizableWindowMask; if (!useStandardWindow || transparent() || !has_frame()) { styleMask |= NSTexturedBackgroundWindowMask; } + if (resizable) { + styleMask |= NSResizableWindowMask; + } if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { styleMask |= NSFullSizeContentViewWindowMask; styleMask |= NSUnifiedTitleAndToolbarWindowMask; From 8e4094793890cc060912fffb30849e7f7322cdec Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 15:43:36 +0800 Subject: [PATCH 107/738] spec: Make window.open specs more reliable --- spec/chromium-spec.coffee | 41 ++++++++++++-------------- spec/fixtures/pages/window-opener.html | 5 +++- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/spec/chromium-spec.coffee b/spec/chromium-spec.coffee index a782079026a7..2c4853a0d635 100644 --- a/spec/chromium-spec.coffee +++ b/spec/chromium-spec.coffee @@ -4,10 +4,17 @@ https = require 'https' path = require 'path' ws = require 'ws' remote = require 'remote' +BrowserWindow = remote.require 'browser-window' describe 'chromium feature', -> fixtures = path.resolve __dirname, 'fixtures' + listener = null + afterEach -> + if listener? + window.removeEventListener 'message', listener + listener = null + xdescribe 'heap snapshot', -> it 'does not crash', -> process.atomBinding('v8_util').takeHeapSnapshot() @@ -24,20 +31,17 @@ describe 'chromium feature', -> $.get "http://127.0.0.1:#{port}" describe 'document.hidden', -> - BrowserWindow = remote.require 'browser-window' - ipc = remote.require 'ipc' url = "file://#{fixtures}/pages/document-hidden.html" w = null afterEach -> w?.destroy() - ipc.removeAllListeners 'hidden' it 'is set correctly when window is not shown', (done) -> - ipc.once 'hidden', (event, hidden) -> - assert hidden - done() w = new BrowserWindow(show:false) + w.webContents.on 'ipc-message', (event, args) -> + assert.deepEqual args, ['hidden', true] + done() w.loadUrl url describe 'navigator.webkitGetUserMedia', -> @@ -52,8 +56,6 @@ describe 'chromium feature', -> assert.notEqual navigator.language, '' describe 'window.open', -> - @timeout 10000 - it 'returns a BrowserWindowProxy object', -> b = window.open 'about:blank', '', 'show=no' assert.equal b.closed, false @@ -62,46 +64,41 @@ describe 'chromium feature', -> it 'accepts "node-integration" as feature', (done) -> listener = (event) -> - window.removeEventListener 'message', listener - b.close() assert.equal event.data, 'undefined' + b.close() done() window.addEventListener 'message', listener b = window.open "file://#{fixtures}/pages/window-opener-node.html", '', 'node-integration=no,show=no' it 'inherit options of parent window', (done) -> listener = (event) -> - window.removeEventListener 'message', listener - b.close() size = remote.getCurrentWindow().getSize() assert.equal event.data, "size: #{size.width} #{size.height}" + b.close() done() window.addEventListener 'message', listener b = window.open "file://#{fixtures}/pages/window-open-size.html", '', 'show=no' describe 'window.opener', -> - @timeout 10000 - - ipc = remote.require 'ipc' url = "file://#{fixtures}/pages/window-opener.html" w = null afterEach -> w?.destroy() - ipc.removeAllListeners 'opener' it 'is null for main window', (done) -> - ipc.once 'opener', (event, opener) -> - assert.equal opener, null - done() - BrowserWindow = remote.require 'browser-window' w = new BrowserWindow(show: false) + w.webContents.on 'ipc-message', (event, args) -> + assert.deepEqual args, ['opener', null] + done() w.loadUrl url it 'is not null for window opened by window.open', (done) -> - ipc.once 'opener', (event, opener) -> + listener = (event) -> + assert.equal event.data, 'object' b.close() - done(if opener isnt null then undefined else opener) + done() + window.addEventListener 'message', listener b = window.open url, '', 'show=no' describe 'window.opener.postMessage', -> diff --git a/spec/fixtures/pages/window-opener.html b/spec/fixtures/pages/window-opener.html index 0b5ecd556c9b..226b57dbd709 100644 --- a/spec/fixtures/pages/window-opener.html +++ b/spec/fixtures/pages/window-opener.html @@ -1,7 +1,10 @@ From f6327de7f748fe92de91aa6cc99db9df64c6fe09 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 16:08:32 +0800 Subject: [PATCH 108/738] spec: Increase timeout for window.open specs --- spec/chromium-spec.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/chromium-spec.coffee b/spec/chromium-spec.coffee index 2c4853a0d635..a034f9378235 100644 --- a/spec/chromium-spec.coffee +++ b/spec/chromium-spec.coffee @@ -56,6 +56,8 @@ describe 'chromium feature', -> assert.notEqual navigator.language, '' describe 'window.open', -> + @timeout 10000 + it 'returns a BrowserWindowProxy object', -> b = window.open 'about:blank', '', 'show=no' assert.equal b.closed, false @@ -80,6 +82,8 @@ describe 'chromium feature', -> b = window.open "file://#{fixtures}/pages/window-open-size.html", '', 'show=no' describe 'window.opener', -> + @timeout 10000 + url = "file://#{fixtures}/pages/window-opener.html" w = null From e06778178a1f5369c93530d678e6af059f59995b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 16:06:39 +0800 Subject: [PATCH 109/738] linux: Restore size constraints when became sizable --- atom/browser/native_window_views.cc | 19 +++++++++++++++---- atom/browser/native_window_views.h | 7 +++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 0e04414b6a47..6d89ee1d06e3 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -387,6 +387,15 @@ gfx::Size NativeWindowViews::GetContentSize() { return web_view_->size(); } +void NativeWindowViews::SetContentSizeConstraints( + const extensions::SizeConstraints& size_constraints) { + NativeWindow::SetContentSizeConstraints(size_constraints); +#if defined(USE_X11) + if (resizable_) + old_size_constraints_ = size_constraints; +#endif +} + void NativeWindowViews::SetResizable(bool resizable) { #if defined(OS_WIN) // WS_MAXIMIZEBOX => Maximize button @@ -403,11 +412,13 @@ void NativeWindowViews::SetResizable(bool resizable) { // On Linux there is no "resizable" property of a window, we have to set // both the minimum and maximum size to the window size to achieve it. if (resizable) { - SetMaximumSize(gfx::Size()); - SetMinimumSize(gfx::Size()); + SetContentSizeConstraints(old_size_constraints_); } else { - SetMaximumSize(GetSize()); - SetMinimumSize(GetSize()); + old_size_constraints_ = GetContentSizeConstraints(); + resizable_ = false; + gfx::Size content_size = GetContentSize(); + SetContentSizeConstraints( + extensions::SizeConstraints(content_size, content_size)); } } #endif diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 35ca7b63e25c..0014acd073c1 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -64,6 +64,8 @@ class NativeWindowViews : public NativeWindow, void SetBounds(const gfx::Rect& bounds) override; gfx::Rect GetBounds() override; gfx::Size GetContentSize() override; + void SetContentSizeConstraints( + const extensions::SizeConstraints& size_constraints) override; void SetResizable(bool resizable) override; bool IsResizable() override; void SetAlwaysOnTop(bool top) override; @@ -165,6 +167,11 @@ class NativeWindowViews : public NativeWindow, // Handles window state events. scoped_ptr window_state_watcher_; + + // The "resizable" flag on Linux is implemented by setting size constraints, + // we need to make sure size constraints are restored when window becomes + // resizable again. + extensions::SizeConstraints old_size_constraints_; #elif defined(OS_WIN) // Weak ref. AtomDesktopWindowTreeHostWin* atom_desktop_window_tree_host_win_; From f607e81facac1dd27665ef4a81469ff1ea4bdd82 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 16:16:02 +0800 Subject: [PATCH 110/738] views: Make size constraints work immediately after set --- atom/browser/native_window_views.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 6d89ee1d06e3..4c8d014b1ec9 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -390,6 +390,7 @@ gfx::Size NativeWindowViews::GetContentSize() { void NativeWindowViews::SetContentSizeConstraints( const extensions::SizeConstraints& size_constraints) { NativeWindow::SetContentSizeConstraints(size_constraints); + window_->OnSizeConstraintsChanged(); #if defined(USE_X11) if (resizable_) old_size_constraints_ = size_constraints; From c6d5a92d349bb376c4c6f78ed618b970d343258b Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Tue, 6 Oct 2015 19:53:35 +0900 Subject: [PATCH 111/738] Update as upstream --- README-ko.md | 2 +- docs-translations/ko-KR/api/native-image.md | 2 +- docs-translations/ko-KR/api/process.md | 6 ++++-- docs-translations/ko-KR/api/screen.md | 2 +- docs-translations/ko-KR/tutorial/quick-start.md | 6 +++--- .../ko-KR/tutorial/using-native-node-modules.md | 14 ++++++++------ 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/README-ko.md b/README-ko.md index 1481e7ce3dc5..c722243eb589 100644 --- a/README-ko.md +++ b/README-ko.md @@ -8,7 +8,7 @@ :zap: *프레임워크 이름이 Atom Shell에서 Electron으로 변경되었습니다* :zap: -Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. 이 프레임워크는 [io.js](http://iojs.org) 와 +Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. 이 프레임워크는 [Node.js](https://nodejs.org) 와 [Chromium](http://www.chromium.org)을 기반으로 만들어 졌으며 [Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다. Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서 [@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요. diff --git a/docs-translations/ko-KR/api/native-image.md b/docs-translations/ko-KR/api/native-image.md index 423cedb98300..485ab7bc71d4 100644 --- a/docs-translations/ko-KR/api/native-image.md +++ b/docs-translations/ko-KR/api/native-image.md @@ -142,4 +142,4 @@ var image = NativeImage.createFromPath('/Users/somebody/images/icon.png'); 이미지가 템플릿 이미지인지 확인합니다. -[buffer]: https://iojs.org/api/buffer.html#buffer_class_buffer +[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer diff --git a/docs-translations/ko-KR/api/process.md b/docs-translations/ko-KR/api/process.md index 57ba0fa768a9..a35c8b4e93d8 100644 --- a/docs-translations/ko-KR/api/process.md +++ b/docs-translations/ko-KR/api/process.md @@ -17,9 +17,11 @@ Electron 내부 초기화 스크립트의 로드가 완료되고, 웹 페이지 ```javascript // preload.js +var _setImmediate = setImmediate; +var _clearImmediate = clearImmediate; process.once('loaded', function() { - global.setImmediate = setImmediate; - global.clearImmediate = clearImmediate; + global.setImmediate = _setImmediate; + global.clearImmediate = _clearImmediate; }); ``` diff --git a/docs-translations/ko-KR/api/screen.md b/docs-translations/ko-KR/api/screen.md index de2d8baf4e35..c65540eba228 100644 --- a/docs-translations/ko-KR/api/screen.md +++ b/docs-translations/ko-KR/api/screen.md @@ -45,7 +45,7 @@ app.on('ready', function() { if (externalDisplay) { mainWindow = new BrowserWindow({ x: externalDisplay.bounds.x + 50, - y: externalDisplay.bounds.y + 50, + y: externalDisplay.bounds.y + 50 }); } }); diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 3edf13cc4736..6eaad7476958 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -3,7 +3,7 @@ ## 소개 Electron은 자바스크립트와 함께 제공된 풍부한 네이티브 API를 사용하여 멋진 데스크탑 어플리케이션을 만들 수 있도록 해주는 프레임워크입니다. -이 프레임워크의 io.js(node.js)는 웹 서버 개발이 아닌 데스크탑 어플리케이션 개발에 초점을 맞췄습니다. +이 프레임워크의 Node.js는 웹 서버 개발이 아닌 데스크탑 어플리케이션 개발에 초점을 맞췄습니다. 이 말은 Electron이 GUI 라이브러리의 자바스크립트 바인딩이라는 뜻이 아닙니다. 대신, Electron은 웹 페이지의 GUI를 사용합니다. 쉽게 말해 Electron은 자바스크립트를 사용하여 조작하는 작은 Chromium 브라우저로 볼 수 있습니다. @@ -19,7 +19,7 @@ Electron이 웹페이지를 보여줄 때 Chromium의 multi-processes 구조도 Electron 프로세스 내에서 작동하는 웹 페이지를 __랜더러 프로세스__ 라고 불립니다. 보통 일반 브라우저의 웹 페이지들은 샌드박스가 적용된 환경에서 작동하며 네이티브 리소스에는 접근할 수 없도록 되어 있습니다. -하지만 Electron은 웹 페이지 내에서 io.js(node.js) API를 사용하여 low-level 수준으로 운영체제와 상호작용할 수 있습니다. +하지만 Electron은 웹 페이지 내에서 Node.js API를 사용하여 low-level 수준으로 운영체제와 상호작용할 수 있습니다. ### 메인 프로세스와 랜더러 프로세스의 차이점 @@ -116,7 +116,7 @@ app.on('ready', function() {

헬로 월드!

- 이 어플리케이션은 io.js 과 + 이 어플리케이션은 Node.js 과 Electron 을 사용합니다. diff --git a/docs-translations/ko-KR/tutorial/using-native-node-modules.md b/docs-translations/ko-KR/tutorial/using-native-node-modules.md index ed64abb492f7..6a0c67770b0b 100644 --- a/docs-translations/ko-KR/tutorial/using-native-node-modules.md +++ b/docs-translations/ko-KR/tutorial/using-native-node-modules.md @@ -5,14 +5,16 @@ Electron에선 node.js 네이티브 모듈이 지원됩니다. 하지만 Electro ## 네이티브 node 모듈 호환성 -Node v0.11.x 버전부터는 V8 API의 중대한 변경이 있었습니다. 하지만 대부분의 네이티브 모듈은 Node v0.10.x 버전을 타겟으로 작성 되었기 때문에 -새로운 Node 또는 io.js 버전에서 작동하지 않을 수 있습니다. Electron은 내부적으로 __io.js v3.1.0__ 버전을 사용하기 때문에 호환성 문제가 발생할 수 있습니다. +네이티브 모듈은 node.js가 새로운 V8 버전을 사용함으로 인해 작동하지 않을 수 있습니다. +사용하는 네이티브 모듈이 Electron에 맞춰 작동할 수 있도록 하려면 Electron에서 사용하는 node.js의 버전을 확인할 필요가 있습니다. +Electron에서 사용하는 node 버전은 [releases](https://github.com/atom/electron/releases)에서 확인할 수 있으며 +`process.version`을 출력하여 버전을 확인할 수도 있습니다. ([시작하기](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md)의 예제를 참고하세요) -이 문제를 해결하기 위해선 모듈이 v0.11.x 또는 최신 버전을 지원할 수 있도록 변경해야 합니다. -현재 [많은 모듈들](https://www.npmjs.org/browse/depended/nan)이 안정적으로 두 버전 모두 지원하고 있지만 오래된 모듈의 경우 여전히 Node v0.10.x 버전만을 지원하고 있습니다. -예를 들어 [nan](https://github.com/rvagg/nan) 모듈을 사용해야 한다면 Node v0.11.x 또는 최신 버전의 Node와 io.js로 포팅 할 필요가 있습니다. +혹시 직접 만든 네이티브 모듈이 있다면 [NAN](https://github.com/nodejs/nan/) 모듈을 사용하는 것을 고려해보는 것이 좋습니다. +이 모듈은 다중 버전의 node.js를 지원하기 쉽게 해줍니다. 이를 통해 오래된 모듈을 새 버전의 node.js에 맞게 포팅할 수 있습니다. +Electron도 이 모듈을 통해 포팅된 네이티브 모듈을 사용할 수 있습니다. -## 네이티브 모듈 설치하는 방법 +## 네이티브 모듈을 설치하는 방법 네이티브 모듈을 설치하는 방법은 세 가지 종류가 있습니다. From c916baa93968c6d874a94696a0f44868bbc18f11 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 21:40:08 +0800 Subject: [PATCH 112/738] Update brightray, fix #2315 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index c44f99278bc4..9e97c2b5bf5a 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit c44f99278bc4f6823f81b6f3a8d75881d697fd01 +Subproject commit 9e97c2b5bf5aa455f863bb29f99a219bdda4d29d From 927c3f34c3759e29948a1ffaa76a4985d38a1d69 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 22:25:55 +0800 Subject: [PATCH 113/738] Guard against undefined, fix #2995 In theory this should never happen, seems like some object is garbage collected after the JavaScript context has been destroyed. --- atom/browser/lib/objects-registry.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/atom/browser/lib/objects-registry.coffee b/atom/browser/lib/objects-registry.coffee index ccfe2dbe0ad2..667adbc24e9e 100644 --- a/atom/browser/lib/objects-registry.coffee +++ b/atom/browser/lib/objects-registry.coffee @@ -34,6 +34,7 @@ class ObjectsRegistry extends EventEmitter @dereference id, 1 # Also reduce the count in owner. pointer = @owners[webContentsId] + return unless pointer? --pointer[id] delete pointer[id] if pointer[id] is 0 @@ -57,6 +58,7 @@ class ObjectsRegistry extends EventEmitter # Private: Dereference the object from store. dereference: (id, count) -> pointer = @storage[id] + return unless pointer? pointer.count -= count if pointer.count is 0 v8Util.deleteHiddenValue pointer.object, 'atomId' From 5bdc077b486885e5769230b40c4ae7f54b29aea9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 6 Oct 2015 22:45:00 +0800 Subject: [PATCH 114/738] Update brightray for #2855 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 9e97c2b5bf5a..c25b9b27845a 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 9e97c2b5bf5aa455f863bb29f99a219bdda4d29d +Subproject commit c25b9b27845a308e6a6a5966dad057d721b1f3d1 From cab466f999f507b6f535ce5db298868a3cf3ae5b Mon Sep 17 00:00:00 2001 From: joshaber Date: Tue, 6 Oct 2015 16:14:44 -0400 Subject: [PATCH 115/738] ++crashpad --- vendor/crashpad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/crashpad b/vendor/crashpad index e6a0d433b0ee..cdc8d01d7df1 160000 --- a/vendor/crashpad +++ b/vendor/crashpad @@ -1 +1 @@ -Subproject commit e6a0d433b0ee399eecce2bef671794771052ffdb +Subproject commit cdc8d01d7df15d7139729747bff23b96baa28017 From 74be1d5b25cb5b8ceac975f13be7042951e7994d Mon Sep 17 00:00:00 2001 From: joshaber Date: Tue, 6 Oct 2015 16:14:49 -0400 Subject: [PATCH 116/738] ++brightray --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index c25b9b27845a..57bcb55bd483 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit c25b9b27845a308e6a6a5966dad057d721b1f3d1 +Subproject commit 57bcb55bd4830386d1d499f24064ea8078976167 From 4c3fd3877438dcdd57c83a9d17915e4093fb9d80 Mon Sep 17 00:00:00 2001 From: joshaber Date: Tue, 6 Oct 2015 16:15:03 -0400 Subject: [PATCH 117/738] This now has to be non-nil. --- atom/common/platform_util_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/common/platform_util_mac.mm b/atom/common/platform_util_mac.mm index 1aa75effd35b..2f9e2b764236 100644 --- a/atom/common/platform_util_mac.mm +++ b/atom/common/platform_util_mac.mm @@ -20,7 +20,7 @@ void ShowItemInFolder(const base::FilePath& full_path) { DCHECK([NSThread isMainThread]); NSString* path_string = base::SysUTF8ToNSString(full_path.value()); if (!path_string || ![[NSWorkspace sharedWorkspace] selectFile:path_string - inFileViewerRootedAtPath:nil]) + inFileViewerRootedAtPath:@""]) LOG(WARNING) << "NSWorkspace failed to select file " << full_path.value(); } From 326af3cbe36fa444e7a6f7ae5bdbbd237b163574 Mon Sep 17 00:00:00 2001 From: joshaber Date: Tue, 6 Oct 2015 16:34:20 -0400 Subject: [PATCH 118/738] Use Xcode 7. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4d4cd5dde9f0..8b4343138994 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ os: - osx env: - TARGET_ARCH=x64 +osx_image: xcode7 matrix: include: From 871571c65ed7f32034f6fb9fab42d4fd0ddaf707 Mon Sep 17 00:00:00 2001 From: Meyito Date: Tue, 6 Oct 2015 22:09:57 -0500 Subject: [PATCH 119/738] Translations of some of the Electron docs API in Spanish --- docs-translations/es/README.md | 12 +- .../es/api/chrome-command-line-switches.md | 119 ++++++++++++++++++ docs-translations/es/api/process.md | 47 +++++++ docs-translations/es/api/synopsis.md | 47 +++++++ 4 files changed, 219 insertions(+), 6 deletions(-) create mode 100644 docs-translations/es/api/chrome-command-line-switches.md create mode 100644 docs-translations/es/api/process.md create mode 100644 docs-translations/es/api/synopsis.md diff --git a/docs-translations/es/README.md b/docs-translations/es/README.md index 497cc4e05ccf..10c1b9fe991a 100644 --- a/docs-translations/es/README.md +++ b/docs-translations/es/README.md @@ -10,15 +10,15 @@ ## Tutoriales -* [Introducción](../../docs/tutorial/quick-start.md) -* [Integración con el entorno de escritorio](../../docs/tutorial/desktop-environment-integration.md) -* [Detección del evento en línea/fuera de línea](../../docs/tutorial/online-offline-events.md) +* [Introducción](tutorial/quick-start.md) +* [Integración con el entorno de escritorio](tutorial/desktop-environment-integration.md) +* [Detección del evento en línea/fuera de línea](tutorial/online-offline-events.md) ## API -* [Sinopsis](../../docs/api/synopsis.md) -* [Proceso](../../docs/api/process.md) -* [Parámetros CLI soportados (Chrome)](../../docs/api/chrome-command-line-switches.md) +* [Sinopsis](api/synopsis.md) +* [Proceso](api/process.md) +* [Parámetros CLI soportados (Chrome)](api/chrome-command-line-switches.md) Elementos DOM customizados: diff --git a/docs-translations/es/api/chrome-command-line-switches.md b/docs-translations/es/api/chrome-command-line-switches.md new file mode 100644 index 000000000000..c063869adf95 --- /dev/null +++ b/docs-translations/es/api/chrome-command-line-switches.md @@ -0,0 +1,119 @@ +# Parámetros CLI soportados (Chrome) + +Esta página lista las líneas de comandos usadas por el navegador Chrome que también son +soportadas por Electron. Puedes usar [app.commandLine.appendSwitch][append-switch] para +anexarlas en el script principal de tu aplicación antes de que el evento [ready][ready] del +modulo [app][app] sea emitido: + +```javascript +var app = require('app'); +app.commandLine.appendSwitch('remote-debugging-port', '8315'); +app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1'); + +app.on('ready', function() { + // Your code here +}); +``` + +## --client-certificate=`path` + +Establece el `path` del archivo de certificado del cliente. + +## --ignore-connections-limit=`domains` + +Ignora el límite de conexiones para la lista de `domains` separados por `,`. + +## --disable-http-cache + +Deshabilita la cacheé del disco para las peticiones HTTP. + +## --remote-debugging-port=`port` + +Habilita la depuración remota a través de HTTP en el puerto especificado. + +## --proxy-server=`address:port` + +Usa un servidor proxy especificado, que sobreescribe la configuración del sistema. +Este cambio solo afecta peticiones HTTP y HTTPS. + +## --proxy-pac-url=`url` + +Utiliza el script PAC en la `url` especificada. + +## --no-proxy-server + +No usa un servidor proxy y siempre establece conexiones directas. Anula cualquier +otra bandera de servidor proxy bandera que se pase. + +## --host-rules=`rules` + +Una lista separada por comas de `rules` (reglas) que controlan cómo se asignan los +nombres de host. + +Por ejemplo: + +* `MAP * 127.0.0.1` Obliga a todos los nombres de host a ser asignados a 127.0.0.1 +* `MAP *.google.com proxy` Obliga todos los subdominios google.com a resolverse con + "proxy". +* `MAP test.com [::1]:77` Obliga a resolver "test.com" con un bucle invertido de IPv6. + También obligará a que el puerto de la dirección respuesta sea 77. +* `MAP * baz, EXCLUDE www.google.com` Reasigna todo a "baz", excepto a "www.google.com". + +Estas asignaciones especifican el host final en una petición de red (Anfitrión de la conexión TCP +y de resolución de conexión directa, y el `CONNECT` en una conexión proxy HTTP, y el host final de +la conexión proxy `SOCKS`). + +## --host-resolver-rules=`rules` + +Como `--host-rules` pero estas `rules` solo se aplican al solucionador. + +[app]: app.md +[append-switch]: app.md#appcommandlineappendswitchswitch-value +[ready]: app.md#event-ready + +## --ignore-certificate-errors + +Ignora errores de certificado relacionados. + +## --ppapi-flash-path=`path` + +Asigna la ruta `path` del pepper flash plugin. + +## --ppapi-flash-version=`version` + +Asigna la versión `version` del pepper flash plugin. + +## --log-net-log=`path` + +Permite guardar y escribir eventos de registros de red en `path`. + +## --ssl-version-fallback-min=`version` + +Establece la versión mínima de SSL/TLS ("tls1", "tls1.1" o "tls1.2") que +el repliegue de TLC aceptará. + +## --enable-logging + +Imprime el registro de Chromium en consola. + +Este cambio no puede ser usado en `app.commandLine.appendSwitch` ya que se analiza antes de que la +aplicación del usuario este cargada. + +## --v=`log_level` + +Da el maximo nivel activo de V-logging por defecto; 0 es el predeterminado. Valores positivos +son normalmente usados para los niveles de V-logging. + +Este modificador sólo funciona cuando también se pasa `--enable-logging`. + +## --vmodule=`pattern` + +Da los niveles máximos de V-logging por módulo para sobreescribir el valor dado por +`--v`. Ej. `my_module=2,foo*=3` cambiaria el nivel de registro para todo el código +el archivos de origen `my_module.*` y `foo*.*`. + +Cualquier patron que contiene un slash o un slash invertido será probado contra toda la ruta +y no sólo con el módulo. Ej. `*/foo/bar/*=2` cambiaría el nivel de registro para todo el código +en los archivos origen bajo un directorio `foo/bar`. + +Este modificador sólo funciona cuando también se pasa `--enable-logging`. diff --git a/docs-translations/es/api/process.md b/docs-translations/es/api/process.md new file mode 100644 index 000000000000..e03ef5fa1c36 --- /dev/null +++ b/docs-translations/es/api/process.md @@ -0,0 +1,47 @@ +# process + +El objeto `process` en Electron tiene las siguientes diferencias con respecto +al node convencional: + +* `process.type` String - El tipo del proceso puede ser `browser` (ej. proceso + principal) o `renderer`. +* `process.versions['electron']` String - Versión de Electron. +* `process.versions['chrome']` String - Versión de Chromium. +* `process.resourcesPath` String - Ruta al código fuente JavaScript. + +## Events + +### Event: 'loaded' + +Se emite cuando Electron ha cargado su script de inicialización interna y +está comenzando a cargar la página web o el script principal. + +Puede ser usado por el script precargado para añadir de nuevo los símbolos globales +de Node eliminados, al alcance global cuando la integración de Node está apagada: + +```js +// preload.js +var _setImmediate = setImmediate; +var _clearImmediate = clearImmediate; +process.once('loaded', function() { + global.setImmediate = _setImmediate; + global.clearImmediate = _clearImmediate; +}); +``` + +## Methods + +El objeto `process` tiene los siguientes métodos: + +### `process.hang` + +Interrumpe el hilo principal del proceso actual. + + +### process.setFdLimit(maxDescriptors) _OS X_ _Linux_ + +* `maxDescriptors` Integer + +Establece el límite dinámico del descriptor del archivo en `maxDescriptors` +o en el límite estricto del Sistema Operativo, el que sea menor para el +proceso actual. diff --git a/docs-translations/es/api/synopsis.md b/docs-translations/es/api/synopsis.md new file mode 100644 index 000000000000..0da368dea459 --- /dev/null +++ b/docs-translations/es/api/synopsis.md @@ -0,0 +1,47 @@ +# Synopsis + +Todos los [Módulos integrados de Node.js](http://nodejs.org/api/) se encuentran +disponibles en Electron y módulos de terceros son támbien totalmente compatibles +(incluyendo los [módulos nativos](../tutorial/using-native-node-modules.md)). + +Electron también provee algunos módulos integrados adicionales para desarrollar +aplicaciones nativas de escritorio. Algunos módulos sólo se encuentran disponibles +en el proceso principal, algunos sólo en el proceso renderer (pagina web), y +algunos pueden ser usados en ambos procesos. + +La regla básica es: Si un módulo es +[GUI](https://es.wikipedia.org/wiki/Interfaz_gráfica_de_usuario) o de bajo nivel, +entonces solo estará disponible en el proceso principal. Necesitas familiarizarte +con el concepto de [scripts para proceso principal vs scripts para proceso renderer] +(../tutorial/quick-start.md#the-main-process) para ser capaz de usar esos módulos. + +El script del proceso principal es como un script normal de Node.js: + +```javascript +var app = require('app'); +var BrowserWindow = require('browser-window'); + +var window = null; + +app.on('ready', function() { + window = new BrowserWindow({width: 800, height: 600}); + window.loadUrl('https://github.com'); +}); +``` + +El proceso renderer no es diferente de una página web normal, excepto por la +capacidad extra de utilizar módulos de node: + +```html + + + + + + +``` + +Para ejecutar tu aplicación, lee [Ejecutar la aplicación](../tutorial/quick-start.md#run-your-app). \ No newline at end of file From 821005e6b4d38062fe9c2cd4a6a1eb54d4c3efa2 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 7 Oct 2015 12:15:48 +0800 Subject: [PATCH 120/738] Fix a wrong usage of switch commandline. We should not always save switch path as ascii string, which will not be handled well on Windows. --- atom/app/atom_content_client.cc | 4 ++-- atom/browser/api/atom_api_app.cc | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/atom/app/atom_content_client.cc b/atom/app/atom_content_client.cc index e760c01453d4..0931a1b55a41 100644 --- a/atom/app/atom_content_client.cc +++ b/atom/app/atom_content_client.cc @@ -99,7 +99,7 @@ void AtomContentClient::AddAdditionalSchemes( void AtomContentClient::AddPepperPlugins( std::vector* plugins) { auto command_line = base::CommandLine::ForCurrentProcess(); - auto flash_path = command_line->GetSwitchValueNative( + auto flash_path = command_line->GetSwitchValuePath( switches::kPpapiFlashPath); if (flash_path.empty()) return; @@ -108,7 +108,7 @@ void AtomContentClient::AddPepperPlugins( switches::kPpapiFlashVersion); plugins->push_back( - CreatePepperFlashInfo(base::FilePath(flash_path), flash_version)); + CreatePepperFlashInfo(flash_path, flash_version)); } } // namespace atom diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 2e7596971f48..70595856c494 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -20,6 +20,7 @@ #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/node_includes.h" +#include "atom/common/options_switches.h" #include "base/command_line.h" #include "base/environment.h" #include "base/files/file_path.h" @@ -27,6 +28,7 @@ #include "brightray/browser/brightray_paths.h" #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/gpu_data_manager.h" +#include "content/public/common/content_switches.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" #include "net/ssl/ssl_cert_request_info.h" @@ -301,6 +303,16 @@ namespace { void AppendSwitch(const std::string& switch_string, mate::Arguments* args) { auto command_line = base::CommandLine::ForCurrentProcess(); + + if (switch_string == atom::switches::kPpapiFlashPath || + switch_string == atom::switches::kClientCertificate || + switch_string == switches::kLogNetLog) { + base::FilePath path; + args->GetNext(&path); + command_line->AppendSwitchPath(switch_string, path); + return; + } + std::string value; if (args->GetNext(&value)) command_line->AppendSwitchASCII(switch_string, value); From 579f253340e83ef11f580d28b25f85388e3da743 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 7 Oct 2015 20:19:37 +0900 Subject: [PATCH 121/738] Fix small typo --- docs-translations/ko-KR/api/auto-updater.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/auto-updater.md b/docs-translations/ko-KR/api/auto-updater.md index 23f881c32ba8..4588b4ff9caa 100644 --- a/docs-translations/ko-KR/api/auto-updater.md +++ b/docs-translations/ko-KR/api/auto-updater.md @@ -30,7 +30,7 @@ Squirrel의 인스톨러는 오류에 관대하게 설계되었습니다. 그리 Squirrel은 업데이트 확인을 위해 클라이언트 어플리케이션의 요청은 무시합니다. Squirrel은 응답을 분석해야 할 책임이 있기 때문에 `Accept: application/json`이 요청 헤더에 추가됩니다. -업데이트 응답과 본문 포맷에 대한 요구 사항은 [Server Support](#server-support)를 참고하세요. +업데이트 응답과 본문 포맷에 대한 요구 사항은 [서버 지원](#server-support)를 참고하세요. 업데이트 요청에는 서버가 해당 어플리케이션이 어떤 버전을 사용해야 하는지 판단하기 위해 *반드시* 버전 식별자를 포함시켜야 합니다. 추가로 OS 버전, 사용자 이름 같은 다른 식별 기준을 포함하여 서버에서 적합한 어플리케이션을 제공할 수 있도록 할 수 있습니다. From 3966441d21bf16f4735bdd93bdeabf72f154d0b1 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 7 Oct 2015 20:20:34 +0900 Subject: [PATCH 122/738] Fix small typos --- docs-translations/ko-KR/api/auto-updater.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs-translations/ko-KR/api/auto-updater.md b/docs-translations/ko-KR/api/auto-updater.md index 4588b4ff9caa..a91181a1885f 100644 --- a/docs-translations/ko-KR/api/auto-updater.md +++ b/docs-translations/ko-KR/api/auto-updater.md @@ -21,7 +21,7 @@ Squirrel은 사용자에게 어플리케이션의 업데이트를 알릴 필요 서버에선 이러한 요청을 분류 처리하여 적당한 업데이트를 제공할 수 있습니다. Squirrel JSON 업데이트 요청시 처리는 반드시 어떤 업데이트가 필요한지 요청의 기준에 맞춰 동적으로 생성되어야 합니다. -Squirrel은 사용해야 하는 업데이트 선택하는 과정을 서버에 의존합니다. [서버 지원](#server-support)을 참고하세요. +Squirrel은 사용해야 하는 업데이트 선택하는 과정을 서버에 의존합니다. [서버 지원](#서버-지원)을 참고하세요. Squirrel의 인스톨러는 오류에 관대하게 설계되었습니다. 그리고 업데이트가 유효한지 확인합니다. @@ -30,7 +30,7 @@ Squirrel의 인스톨러는 오류에 관대하게 설계되었습니다. 그리 Squirrel은 업데이트 확인을 위해 클라이언트 어플리케이션의 요청은 무시합니다. Squirrel은 응답을 분석해야 할 책임이 있기 때문에 `Accept: application/json`이 요청 헤더에 추가됩니다. -업데이트 응답과 본문 포맷에 대한 요구 사항은 [서버 지원](#server-support)를 참고하세요. +업데이트 응답과 본문 포맷에 대한 요구 사항은 [서버 지원](#서버-지원)를 참고하세요. 업데이트 요청에는 서버가 해당 어플리케이션이 어떤 버전을 사용해야 하는지 판단하기 위해 *반드시* 버전 식별자를 포함시켜야 합니다. 추가로 OS 버전, 사용자 이름 같은 다른 식별 기준을 포함하여 서버에서 적합한 어플리케이션을 제공할 수 있도록 할 수 있습니다. From 63c1fdd22a2ec048f5de1833e3d28d4379dfe39d Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 7 Oct 2015 20:46:57 +0900 Subject: [PATCH 123/738] Improve grammar * Improve the `auto-updater.md` content grammar. --- docs-translations/ko-KR/api/auto-updater.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs-translations/ko-KR/api/auto-updater.md b/docs-translations/ko-KR/api/auto-updater.md index a91181a1885f..98bd65dd0a86 100644 --- a/docs-translations/ko-KR/api/auto-updater.md +++ b/docs-translations/ko-KR/api/auto-updater.md @@ -2,9 +2,9 @@ **이 모듈은 현재 OS X에서만 사용할 수 있습니다.** -Windows 어플리케이션 인스톨러를 생성하려면 [atom/grunt-electron-installer](https://github.com/atom/grunt-electron-installer)를 참고하세요. +Windows 인스톨러를 생성하려면 [atom/grunt-electron-installer](https://github.com/atom/grunt-electron-installer)를 참고하세요. -`auto-updater` 모듈은 [Squirrel.Mac](https://github.com/Squirrel/Squirrel.Mac) 프레임워크의 간단한 Wrapper입니다. +`auto-updater` 모듈은 [Squirrel.Mac](https://github.com/Squirrel/Squirrel.Mac) 프레임워크의 간단한 wrapper 입니다. Squirrel.Mac은 업데이트 설치를 위해 `.app` 폴더에 [codesign](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/codesign.1.html) @@ -14,11 +14,11 @@ Squirrel.Mac은 업데이트 설치를 위해 `.app` 폴더에 Squirrel은 어플리케이션이 **안전하고 투명한 업데이트**를 제공할 수 있도록 하는데 초점이 맞춰진 OS X 프레임워크입니다. -Squirrel은 사용자에게 어플리케이션의 업데이트를 알릴 필요 없이 서버가 지시하는 버전을 받아온 후 자동으로 업데이트합니다. -이 기능을 사용하면 Squirrel을 통해 클라이언트의 어플리케이션을 지능적으로 업데이트 할 수 있습니다. +Squirrel은 사용자에게 어플리케이션의 업데이트를 알릴 필요 없이 자동으로 서버가 지시하는 버전을 받아 어플리케이션을 업데이트합니다. +지능적으로 클라이언트 어플리케이션을 업데이트 할 수 있습니다. -또한 요청시 커스텀 헤더 또는 요청 본문에 인증 정보를 포함시킬 수 있습니다. -서버에선 이러한 요청을 분류 처리하여 적당한 업데이트를 제공할 수 있습니다. +업데이트 요청은 커스텀 헤더 또는 요청 본문에 인증 정보를 포함시킬 수 있습니다. +이에 따라 서버에선 이러한 요청을 분석 처리하여 사용자에게 적당한 업데이트를 제공할 수 있습니다. Squirrel JSON 업데이트 요청시 처리는 반드시 어떤 업데이트가 필요한지 요청의 기준에 맞춰 동적으로 생성되어야 합니다. Squirrel은 사용해야 하는 업데이트 선택하는 과정을 서버에 의존합니다. [서버 지원](#서버-지원)을 참고하세요. @@ -27,8 +27,8 @@ Squirrel의 인스톨러는 오류에 관대하게 설계되었습니다. 그리 ## 업데이트 요청 -Squirrel은 업데이트 확인을 위해 클라이언트 어플리케이션의 요청은 무시합니다. -Squirrel은 응답을 분석해야 할 책임이 있기 때문에 `Accept: application/json`이 요청 헤더에 추가됩니다. +Squirrel은 클라이언트 어플리케이션이 업데이트 확인을 위해 제공하는 요청을 무시합니다. +Squirrel이 응답을 분석할 수 있어야하기 때문에 요청 헤더에 `Accept: application/json` 헤더가 추가됩니다. 업데이트 응답과 본문 포맷에 대한 요구 사항은 [서버 지원](#서버-지원)를 참고하세요. @@ -46,7 +46,7 @@ autoUpdater.setFeedUrl('http://mycompany.com/myapp/latest?version=' + app.getVer ## 서버 지원 -업데이트를 제공하는 서버는 반드시 클라이언트로부터 받은 [Update Request](#update-requests)를 기반으로 업데이트를 처리할 수 있어야 합니다. +업데이트를 제공하는 서버는 반드시 클라이언트로부터 받은 [업데이트 요청](#업데이트-요청)을 기반으로 업데이트를 처리할 수 있어야 합니다. 만약 업데이트 요청이 들어오면 서버는 반드시 [200 OK](http://tools.ietf.org/html/rfc2616#section-10.2.1) 상태 코드를 포함한 [업데이트 JSON](#update-json-format)을 본문으로 보내야 합니다. From 6f61832a342dce60205df47a0b410ed932192f60 Mon Sep 17 00:00:00 2001 From: Steve Kinney Date: Wed, 7 Oct 2015 09:03:11 -0700 Subject: [PATCH 124/738] :lipstick: Add semicolon to global-shortcut code example This keeps this line consistent with the rest of the documentation. --- docs/api/global-shortcut.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/global-shortcut.md b/docs/api/global-shortcut.md index adba06e1adcf..fe69881f396e 100644 --- a/docs/api/global-shortcut.md +++ b/docs/api/global-shortcut.md @@ -16,7 +16,7 @@ app.on('ready', function() { // Register a 'ctrl+x' shortcut listener. var ret = globalShortcut.register('ctrl+x', function() { console.log('ctrl+x is pressed'); - }) + }); if (!ret) { console.log('registration failed'); From 2978beaeb7fad9a05ffec71ef8256f23ec371f21 Mon Sep 17 00:00:00 2001 From: Steve Kinney Date: Wed, 7 Oct 2015 09:03:46 -0700 Subject: [PATCH 125/738] :lipstick: Add preposition to globalShortcut.unregisterAll() --- docs/api/global-shortcut.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/global-shortcut.md b/docs/api/global-shortcut.md index fe69881f396e..c9dfb194529a 100644 --- a/docs/api/global-shortcut.md +++ b/docs/api/global-shortcut.md @@ -62,4 +62,4 @@ Unregisters the global shortcut of `accelerator`. ### `globalShortcut.unregisterAll()` -Unregisters all the global shortcuts. +Unregisters all of the global shortcuts. From 05f0b5a8a4c7f40cc0b84f27c5f06ce40f0081e2 Mon Sep 17 00:00:00 2001 From: Renato Alencar Date: Wed, 7 Oct 2015 14:11:58 -0300 Subject: [PATCH 126/738] add quick-start guide pt-BR translation --- .../pt-BR/tutorial/quick-start.md | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 docs-translations/pt-BR/tutorial/quick-start.md diff --git a/docs-translations/pt-BR/tutorial/quick-start.md b/docs-translations/pt-BR/tutorial/quick-start.md new file mode 100644 index 000000000000..294faaca0e9d --- /dev/null +++ b/docs-translations/pt-BR/tutorial/quick-start.md @@ -0,0 +1,192 @@ +# Introdução + +Electron permite criar aplicações desktop com puro JavaScript através de +um runtime APIs ricas e nativas. Você pode ver isso como uma variação do +runtime do io.js que é focado em aplicações desktop em vez de web servers. + +Isso não significa que o Electron é uma ligação em JavaScript para blibliotécas +de interface gráfica (GUI). Em vez disso, Electron usa páginas web como +interface gráfica, então você pode ver isso também como um navegador Chromium +mínimo, controlado por JavaScript. + +### Processo Principal + +No Electron, o processo que executa o script principal (main) do `package.json` +é chamado __processo principal__. O script que roda no processo principal pode +mostrar uma GUI criando páginas web. + +### Processo Renderizador + +Desde que o Electron usa o Chromium para mostrar as páginas web, a arquitetura +multi-processo do Chromium também é usada. Cada página web no Electron roda em +seu próprio processo, o que é chamado de __processo renderizador__. + +Em navegadores comuns, as páginas web normalmente rodam em um ambiente em sandbox +e não tem permissão de acesso para recursos nativos. Usuários Electron, entretanto, +tem o poder de usar as APIs do io.js nas páginas web, permitindo interações de baixo +nível no sistema operacional. + +### Diferenças Entre o Processo Principal e o Processo Renderizador + +O processo principal cria as páginas web criando instâncias de `BrowserWindow`. +Cada instância de `BrowserWindow` roda a página web em seu próprio processo renderizador. +Quando uma instância de `BrowserWindow` é destruída, o processo renderizador +correspondente também é finalizado. + +O processo principal gerência todas as páginas web de seus processos renderizadores +correspondentes. Cada processo renderizador é isolado e toma conta de sua +respectiva página web. + +Nas páginas web, chamar APIs nativas relacionadas à GUI não é permitido porque +gerênciar recursos de GUI em páginas web é muito perigoso e o fazamento de recursos +se torna fácil. Se você quer realizar operações com GUI em páginas web, o processo +renderizador da página web deve se comunicar com o processo principal para requisitar +que o processo principal realize estas operações. + +No Electron, nós fornecemos o módulo [ipc](../../../docs/api/ipc-renderer.md) para +comunicação entre o processo principal e o processo renderizador. Isso também um +módulo [remoto](../../../docs/api/remote.md) para comunicação RPC. + +## Crie seu Primeiro App Electron + +Geralmente, um app Electron é estruturado assim: + +```text +your-app/ +├── package.json +├── main.js +└── index.html +``` + +O formato de `package.json` é exatamente o mesmo que os dos módulos do Node, e +e o script especificado pelo campo `main` é o script de inicialização do seu app, +que irá executar o processo principal. Um exemplo do seu `package.json` deve parecer +como isso: + +```json +{ + "name" : "your-app", + "version" : "0.1.0", + "main" : "main.js" +} +``` + +__Nota__: Se o campo `main` não estiver presente no `package.jso`, o Electron irá +tentar carregar um `index.js` + +O `main.js` deve criar as janelas e os manipuladores de eventos do sistema, um típico +exemplo: + +```javascript +var app = require('app'); // Módulo para controlar o ciclo de vida do app. +var BrowserWindow = require('browser-window'); // Módulo para criar uma janela nativa do browser. + +// Relate falhas para nossos servidores. +require('crash-reporter').start(); + +// Mantenha uma referência global para o objeto window, se você não o fizer, +// a janela será fechada automaticamente quando o objeto JavaScript for +// coletado pelo garbage collector. +var mainWindow = null; + +// Sair quando todas as janelas estiverem fechadas. +app.on('window-all-closed', function() { + // No OS X é comum para as aplicações na barra de menu + // continuarem ativas até que o usuário saia explicitamente + // com Cmd + Q + if (process.platform != 'darwin') { + app.quit(); + } +}); + +// Esse método irá ser chamado quando o Electron finalizar +// a inicialização e estiver pronto para criar janelas do browser. +app.on('ready', function() { + // Criar a janela do navegador. + mainWindow = new BrowserWindow({width: 800, height: 600}); + + // e carrega o index.html do app. + mainWindow.loadUrl('file://' + __dirname + '/index.html'); + + // Abre os DevTools. + mainWindow.openDevTools(); + + // Emitido quando a janela é fechada. + mainWindow.on('closed', function() { + // Desfaz a referência para o objeto window, normalmente você deverá + // guardar as janelas em um array se seu app suportar várias janelas, + // essa é a hora que você deverá deletar o elemento correspondente. + mainWindow = null; + }); +}); +``` + +Finalmente o `index.html` é a página web que você quer mostrar: + +```html + + + + + Hello World! + + +

Hello World!

+ Nós estamos usando io.js + e Electron . + + +``` + +## Execute seu App + +Uma vez que você criou seus arquivos `main.js`, `index.html, e `package.json` iniciais, +você provavelmente vai querer tentar executar seu app localmente para testa-lo a ter +certeza que funciona como você espera. + +### electron-prebuilt + +Se você instalou `electron-prebuilt` globalmente com `npm`, então você irá precisar apenas +rodar o seguinte comando no diretório fonte do seu app: + +```bash +electron . +``` + +Se você o instalou localmente, então execute: + +```bash +./node_modules/.bin/electron . +``` + +### Binário do Electron Baixado Manualmente + +Se você baixou o Electron manualmente, você pode também usar o binário incluído para +executar seu app diretamente. + +#### Windows + +```bash +$ .\electron\electron.exe your-app\ +``` + +#### Linux + +```bash +$ ./electron/electron your-app/ +``` + +#### OS X + +```bash +$ ./Electron.app/Contents/MacOS/Electron your-app/ +``` + +`Electron.app` aqui é uma parte do pacote de lançamento do Electron, você pode baixa-lo +[aqui](https://github.com/atom/electron/releases). + +### Executar como umas distribuição + +Depois de terminar seu app, você pode criar uma distribuição seguindo o guia +[Application Distribution](./application-distribution.md) e então executar o app +empacotado. From b1ae60a63909d5b700171fd35b2ba0b33e26c7af Mon Sep 17 00:00:00 2001 From: Renato Alencar Date: Wed, 7 Oct 2015 14:24:09 -0300 Subject: [PATCH 127/738] grammar corrections --- docs-translations/pt-BR/tutorial/quick-start.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs-translations/pt-BR/tutorial/quick-start.md b/docs-translations/pt-BR/tutorial/quick-start.md index 294faaca0e9d..16c66e9a85d2 100644 --- a/docs-translations/pt-BR/tutorial/quick-start.md +++ b/docs-translations/pt-BR/tutorial/quick-start.md @@ -1,7 +1,7 @@ # Introdução Electron permite criar aplicações desktop com puro JavaScript através de -um runtime APIs ricas e nativas. Você pode ver isso como uma variação do +um runtime com APIs ricas e nativas. Você pode ver isso como uma variação do runtime do io.js que é focado em aplicações desktop em vez de web servers. Isso não significa que o Electron é uma ligação em JavaScript para blibliotécas @@ -38,13 +38,13 @@ correspondentes. Cada processo renderizador é isolado e toma conta de sua respectiva página web. Nas páginas web, chamar APIs nativas relacionadas à GUI não é permitido porque -gerênciar recursos de GUI em páginas web é muito perigoso e o fazamento de recursos -se torna fácil. Se você quer realizar operações com GUI em páginas web, o processo +gerênciar recursos de GUI em páginas web é muito perigoso e torna fácil o vazamento de +recursos. Se você quer realizar operações com GUI em páginas web, o processo renderizador da página web deve se comunicar com o processo principal para requisitar que o processo principal realize estas operações. No Electron, nós fornecemos o módulo [ipc](../../../docs/api/ipc-renderer.md) para -comunicação entre o processo principal e o processo renderizador. Isso também um +comunicação entre o processo principal e o processo renderizador. Que é também um módulo [remoto](../../../docs/api/remote.md) para comunicação RPC. ## Crie seu Primeiro App Electron @@ -61,7 +61,7 @@ your-app/ O formato de `package.json` é exatamente o mesmo que os dos módulos do Node, e e o script especificado pelo campo `main` é o script de inicialização do seu app, que irá executar o processo principal. Um exemplo do seu `package.json` deve parecer -como isso: +com isso: ```json { From c7dc901607b2320cdbe2cb6119e6d84a5765a606 Mon Sep 17 00:00:00 2001 From: Jan Wiemers Date: Wed, 7 Oct 2015 23:14:49 +0200 Subject: [PATCH 128/738] add --app parameter and update the example usage in the default_app #1877 --- atom/browser/default_app/index.html | 2 +- atom/browser/default_app/main.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/atom/browser/default_app/index.html b/atom/browser/default_app/index.html index 96e45806d5dd..b9bdfffc659f 100644 --- a/atom/browser/default_app/index.html +++ b/atom/browser/default_app/index.html @@ -58,7 +58,7 @@ + + +``` + +There may be instances where you want to respond to these events in the +main process as well. The main process however does not have a +`navigator` object and thus cannot detect these events directly. Using +Electron's inter-process communication utilities, the events can be forwarded +to the main process and handled as needed, as shown in the following example. + +_main.js_ + +```javascript +var app = require('app'); +var ipc = require('ipc'); +var BrowserWindow = require('browser-window'); +var onlineStatusWindow; + +app.on('ready', function() { + onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); + onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); +}); + +ipc.on('online-status-changed', function(event, status) { + console.log(status); +}); +``` + +_online-status.html_ + +```html + + + + + + +``` From c71efc8ca54b1f7f4de799eca8c0e49bb558c2e7 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 10 Oct 2015 08:13:27 +0300 Subject: [PATCH 153/738] Fix `process.std*.write` - Support printing Buffer - Don't add '\n' at the end the chunk --- atom/browser/lib/init.coffee | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index 2b6b1bb3c239..9f92d700c73a 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -21,10 +21,15 @@ globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') if process.platform is 'win32' # Redirect node's console to use our own implementations, since node can not # handle console output when running as GUI program. - print = (args...) -> + consoleLog = (args...) -> process.log util.format(args...) + "\n" - console.log = console.error = console.warn = print - process.stdout.write = process.stderr.write = print + streamWrite = (chunk, encoding, callback) -> + chunk = chunk.toString(encoding) if Buffer.isBuffer chunk + process.log chunk + callback() if callback + true + console.log = console.error = console.warn = consoleLog + process.stdout.write = process.stderr.write = streamWrite # Always returns EOF for stdin stream. Readable = require('stream').Readable From b5b6e30c8bed97dc8b079e34db0ef8aa2e03091a Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sat, 10 Oct 2015 15:10:34 +0900 Subject: [PATCH 154/738] Update as upstream --- docs-translations/ko-KR/api/global-shortcut.md | 6 ++++-- docs-translations/ko-KR/styleguide.md | 10 +++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docs-translations/ko-KR/api/global-shortcut.md b/docs-translations/ko-KR/api/global-shortcut.md index 84c1c70798d7..f000a3bdb6a4 100644 --- a/docs-translations/ko-KR/api/global-shortcut.md +++ b/docs-translations/ko-KR/api/global-shortcut.md @@ -12,7 +12,9 @@ var globalShortcut = require('global-shortcut'); app.on('ready', function() { // 'ctrl+x' 단축키를 리스너에 등록합니다. - var ret = globalShortcut.register('ctrl+x', function() { console.log('ctrl+x is pressed'); }) + var ret = globalShortcut.register('ctrl+x', function() { + console.log('ctrl+x is pressed'); + }); if (!ret) { console.log('registration failed'); @@ -56,4 +58,4 @@ app.on('will-quit', function() { ### `globalShortcut.unregisterAll()` -모든 전역 단축키 등록을 해제합니다. +모든 전역 단축키의 등록을 해제합니다. diff --git a/docs-translations/ko-KR/styleguide.md b/docs-translations/ko-KR/styleguide.md index aaa9274cd0b7..92b68e345505 100644 --- a/docs-translations/ko-KR/styleguide.md +++ b/docs-translations/ko-KR/styleguide.md @@ -56,9 +56,13 @@ Electron 문서 구조를 이해하는 데 참고할 수 있는 유용한 도움 메서드 이름은 인수가 무엇을 받는지에 따라 결정됩니다. 선택적 인수는 브라켓([, ])으로 묶어 이 인수가 다른 인수뒤에서 선택적으로 사용될 수 있다는 것을 표시합니다. -메서드의 밑에선 각 인수에 대해 자세한 설명을 합니다. 인수의 타입은 일반적인 타입 중 하나를 받거나: -[`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) -Electron의 [`webContent`](api/web-content.md)같은 커스텀 타입을 받습니다. +메서드 이름 하단에선 각 인수에 대해 자세한 설명을 합니다. +인수의 타입은 일반적인 타입 중 하나를 받거나: +[`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) +와 같은 일반적으로 쓰이는 타입 중 하나를 받거나 Electron의 [`webContent`](api/web-content.md)같은 커스텀 타입을 받습니다. ### Events From df12f181a4311a4ffd08079c4a302bdebf00a5ac Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 10 Oct 2015 17:43:38 +0800 Subject: [PATCH 155/738] Can not print string16 in wcout on POSIX --- atom/common/api/atom_bindings.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/common/api/atom_bindings.cc b/atom/common/api/atom_bindings.cc index 1a44d1af0a0b..8fb2efd3a3f9 100644 --- a/atom/common/api/atom_bindings.cc +++ b/atom/common/api/atom_bindings.cc @@ -41,7 +41,7 @@ void FatalErrorCallback(const char* location, const char* message) { } void Log(const base::string16& message) { - std::wcout << message; + std::cout << message; } } // namespace From 6d20d37101f6db3579452df2a63d6a257a1f881b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 10 Oct 2015 17:37:25 +0800 Subject: [PATCH 156/738] Bump v0.33.7 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 2 +- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/atom.gyp b/atom.gyp index f06a0c8251be..f5933b8631ec 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.6', + 'version%': '0.33.7', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 50e019c1c77e..77a5502de1eb 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,7 +17,7 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.6 + 0.33.7 LSMinimumSystemVersion 10.8.0 NSMainNibFile diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index b1aba451dcf6..39085d2ed8a1 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,33,6,0 - PRODUCTVERSION 0,33,6,0 + FILEVERSION 0,33,7,0 + PRODUCTVERSION 0,33,7,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.6" + VALUE "FileVersion", "0.33.7" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.33.6" + VALUE "ProductVersion", "0.33.7" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 8078551b90ed..995a6f916b1d 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 33 -#define ATOM_PATCH_VERSION 6 +#define ATOM_PATCH_VERSION 7 #define ATOM_VERSION_IS_RELEASE 1 From 0cd1195eea926a0650dcc77c4141acd5a0b88c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Guimar=C3=A3es?= Date: Sat, 10 Oct 2015 13:41:32 -0300 Subject: [PATCH 157/738] online-offline-events.md translated to pt-BR --- .../pt-BR/tutorial/online-offline-events.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs-translations/pt-BR/tutorial/online-offline-events.md b/docs-translations/pt-BR/tutorial/online-offline-events.md index 88f9a32f2ec6..36b45dc00ffd 100644 --- a/docs-translations/pt-BR/tutorial/online-offline-events.md +++ b/docs-translations/pt-BR/tutorial/online-offline-events.md @@ -1,7 +1,8 @@ # Online/Offline Event Detection -Online and offline event detection can be implemented in the renderer process -using standard HTML5 APIs, as shown in the following example. +Os eventos de detecão Online e Offile podem ser implementados no processo +de renderização utilizando a API padrão do HTML, como é mostrado no exemplo +a seguir. _main.js_ @@ -36,11 +37,11 @@ _online-status.html_ ``` -There may be instances where you want to respond to these events in the -main process as well. The main process however does not have a -`navigator` object and thus cannot detect these events directly. Using -Electron's inter-process communication utilities, the events can be forwarded -to the main process and handled as needed, as shown in the following example. +Pode haver casos onde você também deseja responder a estes eventos no processo principal. +Mas o processo principal não consegue detectar esses eventos diretamente, pois não possui +um objeto `navigator`. Utilizando a ferramentas para comunicação entre processos, os eventos +podem ser direcionados para o processo principal e manipulados quando necessário. Você +pode ser isto no exemplo abaixo. _main.js_ From 692816f9d257e4ae82902fc68827a64e288ac555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Guimar=C3=A3es?= Date: Sat, 10 Oct 2015 14:01:55 -0300 Subject: [PATCH 158/738] online-offline-events.md translated to pt-BR --- docs-translations/pt-BR/README.md | 2 +- .../tutorial/desktop-environment-integration.md | 12 ++++++------ .../pt-BR/tutorial/online-offline-events.md | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs-translations/pt-BR/README.md b/docs-translations/pt-BR/README.md index 767a9e72d6f5..74923a411c5d 100644 --- a/docs-translations/pt-BR/README.md +++ b/docs-translations/pt-BR/README.md @@ -12,7 +12,7 @@ * [Introdução](tutorial/quick-start.md) * [A integração com o ambiente de desenvolvimento](tutorial/desktop-environment-integration.md) -* [Evento de detecção on-line/off-line](../../docs/tutorial/online-offline-events.md) +* [Evento de detecção on-line/off-line](tutorial/online-offline-events.md) ## API - Referencias diff --git a/docs-translations/pt-BR/tutorial/desktop-environment-integration.md b/docs-translations/pt-BR/tutorial/desktop-environment-integration.md index 9c56cabda2a0..20a78d32d537 100644 --- a/docs-translations/pt-BR/tutorial/desktop-environment-integration.md +++ b/docs-translations/pt-BR/tutorial/desktop-environment-integration.md @@ -39,7 +39,7 @@ app.clearRecentDocuments(); ### Notas para Windows A fim de ser possível usar estas funcionalidades no Windows, sua aplicação deve -estar registrada como um handler daquele tipo de documento, caso contrário o +estar registrada como um handler daquele tipo de documento, caso contrário, o arquivo não será exibido no JumpList mesmo depois de você ter adicionado isto. Você pode encontrar qualquer coisa sobre o registro da aplicacão em [Application Registration][app-registration]. @@ -51,7 +51,7 @@ linha de comando. ### Notas para OS X Quando um arquivo for requisitado pelo menu de documentos recentes, o evento `open-file` -do módulo `app` deve ser emitido. +do módulo `app` irá ser emitido. ## Dock Menu customizado (OS X) @@ -82,7 +82,7 @@ app.dock.setMenu(dockMenu); ## Tarefas do Usuário (Windows) -No Windows você pode especificar ações customizadas na categoria `Tasks` do JumpList, +No Windows você pode especificar ações customizadas na categoria `Tarefas` do JumpList, esse texto foi copiado do MSDN: > Applications define tasks based on both the program's features and the key @@ -142,7 +142,7 @@ até sua aplicação ser desinstalada. No Windows você pode adicionar uma miniatura na barra de ferramentas com botões específicos para a janela e barra de tarefas para aplicação. Isso provê ao usuário -uma forma de acessar um comando específico da janela sem ser necessário restaurar +uma forma de acessar um comando específico para janela sem ser necessário restaurar ou ativar a janela. Isto é ilustrado no MSDN: @@ -229,8 +229,8 @@ window.setProgressBar(0.5); ## Representação do arquivo na janela (OS X) No OS X, uma janela pode possuir a representação de um arquivo na barra de título, -para que o ícone do arquivo possa ser exibido na barra de título e uma janela seja -exibida quando o usuário usar um Command-Click ou Control-Click no título. +permitindo que ao usuário acionar um Command-Click ou Control-Click sobre o título da janela, +uma pop-up de navegação entre arquivos é exibida. Você também pode inserir um estado de edição na janela para que o ícone do arquivo possa indicar se o documento nesta janela foi modificado. diff --git a/docs-translations/pt-BR/tutorial/online-offline-events.md b/docs-translations/pt-BR/tutorial/online-offline-events.md index 36b45dc00ffd..294a62e7a81c 100644 --- a/docs-translations/pt-BR/tutorial/online-offline-events.md +++ b/docs-translations/pt-BR/tutorial/online-offline-events.md @@ -41,7 +41,7 @@ Pode haver casos onde você também deseja responder a estes eventos no processo Mas o processo principal não consegue detectar esses eventos diretamente, pois não possui um objeto `navigator`. Utilizando a ferramentas para comunicação entre processos, os eventos podem ser direcionados para o processo principal e manipulados quando necessário. Você -pode ser isto no exemplo abaixo. +pode ver isto no exemplo abaixo. _main.js_ From 4e8db2c3be8f3c9a172fb87ad8739493ab3dfbb1 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 10 Oct 2015 20:17:08 +0300 Subject: [PATCH 159/738] Go back to using node's console.* and std*.write It seems that whatever issues we had with using the original implementation of node for `console.*` calls and for `process.std*.write` on Windows were solved. So I removed the patch. Tested it with cmd, cygwin and used spawn and exec and everything seems to work (except for colors/ansi escape codes, but that didn't work before anyway). --- atom/browser/lib/init.coffee | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index 9f92d700c73a..67630a1bd6fa 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -18,25 +18,6 @@ require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') globalPaths = Module.globalPaths globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') -if process.platform is 'win32' - # Redirect node's console to use our own implementations, since node can not - # handle console output when running as GUI program. - consoleLog = (args...) -> - process.log util.format(args...) + "\n" - streamWrite = (chunk, encoding, callback) -> - chunk = chunk.toString(encoding) if Buffer.isBuffer chunk - process.log chunk - callback() if callback - true - console.log = console.error = console.warn = consoleLog - process.stdout.write = process.stderr.write = streamWrite - - # Always returns EOF for stdin stream. - Readable = require('stream').Readable - stdin = new Readable - stdin.push null - process.__defineGetter__ 'stdin', -> stdin - # Don't quit on fatal error. process.on 'uncaughtException', (error) -> # Do nothing if the user has a custom uncaught exception handler. From cb903a09c0cd281f2cb934afe981b7a4f37d8bc3 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 10 Oct 2015 20:44:22 +0300 Subject: [PATCH 160/738] Block all internal logs when running without `--enable-logging` --- atom/app/atom_main_delegate.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 6ba1b89837c6..639340bcf091 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -48,8 +48,10 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { // Only enable logging when --enable-logging is specified. auto command_line = base::CommandLine::ForCurrentProcess(); - if (!command_line->HasSwitch(switches::kEnableLogging)) + if (!command_line->HasSwitch(switches::kEnableLogging)) { settings.logging_dest = logging::LOG_NONE; + logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES); + } logging::InitLogging(settings); From 6ec184a2ce700489d1dbe3cb87c3c1e59b3f1039 Mon Sep 17 00:00:00 2001 From: "jinhai.wang" Date: Sun, 11 Oct 2015 13:52:06 +0800 Subject: [PATCH 161/738] add new file: ipc-main-process.md --- .../zh-CN/api/ipc-main-process.md | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 docs-translations/zh-CN/api/ipc-main-process.md diff --git a/docs-translations/zh-CN/api/ipc-main-process.md b/docs-translations/zh-CN/api/ipc-main-process.md new file mode 100644 index 000000000000..1655a1aa5b1d --- /dev/null +++ b/docs-translations/zh-CN/api/ipc-main-process.md @@ -0,0 +1,68 @@ +# ipc (主进程) + +在主进程使用`ipc`模块时,`ipc`负责捕获从渲染进程(网页)发送的同步或者是异步消息. + +## 发送消息 + +主进程也可以向渲染进程发送信息,具体可以看[WebContents.send](web-contents.md#webcontentssendchannel-args). + +- 当发送消息的时候,事件名字为'channel'. +- 回复一个同步消息的时候,你需要使用`event.returnValue` +- 回复一个异步消息的时候,使用`event.sender.send(...)` + +下面是一个主进程和渲染进程的通信例子. + +```javascript +// 在主进程中. +var ipc = require('ipc'); +ipc.on('asynchronous-message', function(event, arg) { + console.log(arg); // 打印 "ping" + event.sender.send('asynchronous-reply', 'pong'); +}); + +ipc.on('synchronous-message', function(event, arg) { + console.log(arg); // 打印 "ping" + event.returnValue = 'pong'; +}); +``` + +```javascript +// 在渲染进程(网页). +var ipc = require('ipc'); +console.log(ipc.sendSync('synchronous-message', 'ping')); // 打印 "pong" + +ipc.on('asynchronous-reply', function(arg) { + console.log(arg); // 打印 "pong" +}); +ipc.send('asynchronous-message', 'ping'); +``` + +## 监听消息 + +`ipc`模块有下列几种方法来监听事件. + +### `ipc.on(channel, callback)` + +* `channel` - 事件名称. +* `callback` - 回调函数. + +当事件发生的时候,会传入`callback` `event`和`arg`参数. + +## IPC 事件 + +传入`callback`的`event`对象含有下列方法. + +### `Event.returnValue` + +在同步消息中,设置这个值将会被返回. + +### `Event.sender` + +返回一个可以发送消息的`WebContents`. + +### `Event.sender.send(channel[.arg1][,arg2][,...])` + +* `channel` - 事件名称. +* `arg` (选用) + +这个可以发送一个可带参数的异步消息回渲染进程. From bd95be23f3a8f29208e757564fce880a0f2129f6 Mon Sep 17 00:00:00 2001 From: "jinhai.wang" Date: Sun, 11 Oct 2015 14:56:23 +0800 Subject: [PATCH 162/738] fix docs-translations/zh-CN/api ipc-main-process.md '' -> bug --- docs-translations/zh-CN/api/ipc-main-process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/zh-CN/api/ipc-main-process.md b/docs-translations/zh-CN/api/ipc-main-process.md index 1655a1aa5b1d..75d5785b2e5f 100644 --- a/docs-translations/zh-CN/api/ipc-main-process.md +++ b/docs-translations/zh-CN/api/ipc-main-process.md @@ -6,7 +6,7 @@ 主进程也可以向渲染进程发送信息,具体可以看[WebContents.send](web-contents.md#webcontentssendchannel-args). -- 当发送消息的时候,事件名字为'channel'. +- 当发送消息的时候,事件名字为`channel`. - 回复一个同步消息的时候,你需要使用`event.returnValue` - 回复一个异步消息的时候,使用`event.sender.send(...)` From 36bbf5d51fe249fd02ceef359eb9eeac5d730c62 Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Sun, 11 Oct 2015 15:18:27 +0200 Subject: [PATCH 163/738] fixed devtools instructions --- docs/tutorial/devtools-extension.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/tutorial/devtools-extension.md b/docs/tutorial/devtools-extension.md index e9466f14b648..20ba7031d8ad 100644 --- a/docs/tutorial/devtools-extension.md +++ b/docs/tutorial/devtools-extension.md @@ -16,11 +16,13 @@ $ cd /some-directory $ git clone --recursive https://github.com/facebook/react-devtools.git ``` +Follow the instructions in [`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md) to build the extension. + Then you can load the extension in Electron by opening DevTools in any window, and running the following code in the DevTools console: ```javascript -require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools'); +require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools/shells/chrome'); ``` To unload the extension, you can call the `BrowserWindow.removeDevToolsExtension` From 9419a2ec2c3a6d8e43e5d7c309c6925438a4cf37 Mon Sep 17 00:00:00 2001 From: kokdemo Date: Sun, 11 Oct 2015 22:26:14 +0800 Subject: [PATCH 164/738] translate the application-distrubution.md --- .../tutorial/application-distribution.md | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 docs-translations/zh-CN/tutorial/application-distribution.md diff --git a/docs-translations/zh-CN/tutorial/application-distribution.md b/docs-translations/zh-CN/tutorial/application-distribution.md new file mode 100644 index 000000000000..c1fddce15ea4 --- /dev/null +++ b/docs-translations/zh-CN/tutorial/application-distribution.md @@ -0,0 +1,109 @@ +# 应用部署 + +为了使用Electron部署你的应用程序,你存放应用程序的文件夹需要叫做 `app` 并且需要放在 Electron 的资源文件夹下(在 OS X 中是指 `Electron.app/Contents/Resources/`,在 Linux 和 Windows 中是指 `resources/`) +就像这样: + +在 OS X 中: + +```text +electron/Electron.app/Contents/Resources/app/ +├── package.json +├── main.js +└── index.html +``` + +在 Windows 和 Linux 中: + +```text +electron/resources/app +├── package.json +├── main.js +└── index.html +``` + +然后运行 `Electron.app` (或者 Linux 中的 `electron`,Windows 中的 `electron.exe`), +接着 Electron 就会以你的应用程序的方式启动。`electron` 文件夹将被部署并可以分发给最终的使用者。 + +## 将你的应用程序打包成一个文件 + +除了通过拷贝所有的资源文件来分发你的应用程序之外,你可以可以通过打包你的应用程序为一个 [asar](https://github.com/atom/asar) 库文件以避免暴露你的源代码。 + +为了使用一个 `asar` 库文件代替 `app` 文件夹,你需要修改这个库文件的名字为 `app.asar` , +然后将其放到 Electron 的资源文件夹下,然后 Electron 就会试图读取这个库文件并从中启动。 +如下所示: + +在 OS X 中: + +```text +electron/Electron.app/Contents/Resources/ +└── app.asar +``` + +在 Windows 和 Linux 中: + +```text +electron/resources/ +└── app.asar +``` + +更多的细节请见 [Application packaging](application-packaging.md). + +## 更换名称与下载二进制文件 + +在使用 Electron 打包你的应用程序之后,你可能需要在分发给用户之前修改打包的名字。 + +### Windows + +你可以将 `electron.exe` 改成任意你喜欢的名字,然后可以使用像 +[rcedit](https://github.com/atom/rcedit) 或者[ResEdit](http://www.resedit.net) +编辑它的icon和其他信息。 + +### OS X + +你可以将 `Electron.app` 改成任意你喜欢的名字,然后你也需要修改这些文件中的 +`CFBundleDisplayName`, `CFBundleIdentifier` 以及 `CFBundleName` 字段。 +这些文件如下: + +* `Electron.app/Contents/Info.plist` +* `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist` + +你也可以重命名帮助应用程序以避免在应用程序监视器中显示 `Electron Helper`, +但是请确保你已经修改了帮助应用的可执行文件的名字。 + +一个改过名字的应用程序的构造可能是这样的: + +``` +MyApp.app/Contents +├── Info.plist +├── MacOS/ +│   └── MyApp +└── Frameworks/ + ├── MyApp Helper EH.app + | ├── Info.plist + | └── MacOS/ + |    └── MyApp Helper EH + ├── MyApp Helper NP.app + | ├── Info.plist + | └── MacOS/ + |    └── MyApp Helper NP + └── MyApp Helper.app + ├── Info.plist + └── MacOS/ +    └── MyApp Helper +``` + +### Linux + +你可以将 `electron` 改成任意你喜欢的名字。 + +## 通过重编译源代码来更换名称 + +通过修改产品名称并重编译源代码来更换 Electron 的名称也是可行的。 +你需要修改 `atom.gyp` 文件并彻底重编译一次。 + +### grunt打包脚本 + +手动的检查 Electron 代码并重编译是很复杂晦涩的,因此有一个 Grunt任务可以自动自动的处理 +这些内容 [grunt-build-atom-shell](https://github.com/paulcbetts/grunt-build-atom-shell). + +这个任务会自动的处理编辑 `.gyp` 文件,从源代码进行编译,然后重编译你的应用程序的本地 Node 模块以匹配这个新的可执行文件的名称。 From 799748cc5d1cfd95182625ea4585daf1d35773d3 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Mon, 12 Oct 2015 08:19:44 +0900 Subject: [PATCH 165/738] Update as upstream, improve grammar --- .../ko-KR/tutorial/devtools-extension.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs-translations/ko-KR/tutorial/devtools-extension.md b/docs-translations/ko-KR/tutorial/devtools-extension.md index e6a9b559c35f..ebfdc8ec0b4d 100644 --- a/docs-translations/ko-KR/tutorial/devtools-extension.md +++ b/docs-translations/ko-KR/tutorial/devtools-extension.md @@ -14,13 +14,13 @@ $ cd /some-directory $ git clone --recursive https://github.com/facebook/react-devtools.git ``` -그리고 개발자 콘솔이 열린 창에서 다음의 코드를 콘솔에 입력하면 확장 기능을 로드할 수 있습니다: +그리고 개발자 콘솔에서 다음 코드를 입력하면 확장 기능을 로드할 수 있습니다: ```javascript -require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools'); +require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools/shells/chrome'); ``` -확장 기능을 unload 하고 콘솔을 다시 열 때 해당 확장 기능이 로드되지 않도록 하려면 `BrowserWindow.removeDevToolsExtension` API를 사용하면 됩니다: +확장 기능을 언로드 하고 콘솔을 다시 열 때 해당 확장 기능이 로드되지 않도록 하려면 `BrowserWindow.removeDevToolsExtension` API를 사용하면 됩니다: ```javascript require('remote').require('browser-window').removeDevToolsExtension('React Developer Tools'); @@ -29,13 +29,13 @@ require('remote').require('browser-window').removeDevToolsExtension('React Devel ## 개발자 콘솔 확장 기능의 구성 형식 모든 개발자 콘솔 확장은 완벽히 Chrome 브라우저를 위해 작성되었기 때문에 Electron에서도 로드할 수 있습니다. -하지만 반드시 확장 기능은 소스코드 그대로의 디렉터리(폴더) 형태여야 합니다. 그래서 `crx` 등의 포맷으로 패키징된 확장 기능의 경우 -사용자가 직접 해당 패키지의 압축을 풀어서 로드하지 않는 이상은 Electron에서 해당 확장 기능의 압축을 풀 방법이 없습니다. +하지만 반드시 확장 기능은 소스 코드 디렉터리(폴더) 형태여야 합니다. 그래서 `crx` 등의 포맷으로 패키징된 확장 기능의 경우 +사용자가 직접 해당 패키지의 압축을 풀어서 로드하지 않는 이상 Electron에서 해당 확장 기능의 압축을 풀 방법이 없습니다. ## 백그라운드 페이지 현재 Electron은 Chrome에서 지원하는 백그라운드 페이지(background pages)를 지원하지 않습니다. -몇몇 확장 기능은 이 기능에 의존하는 경우가 있는데 이 경우 해당 확장 기능은 Electron에서 작동하지 않을 수 있습니다. +몇몇 확장 기능은 이 기능에 의존하는 경우가 있는데, 이 때 해당 확장 기능은 Electron에서 작동하지 않을 수 있습니다. ## `chrome.*` API From 9de9d2ecc1ee28c5b2aaa98f00ff742b1c978659 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Mon, 12 Oct 2015 08:23:30 +0900 Subject: [PATCH 166/738] Add missing paragraphs --- docs-translations/ko-KR/tutorial/devtools-extension.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs-translations/ko-KR/tutorial/devtools-extension.md b/docs-translations/ko-KR/tutorial/devtools-extension.md index ebfdc8ec0b4d..966431dd72b8 100644 --- a/docs-translations/ko-KR/tutorial/devtools-extension.md +++ b/docs-translations/ko-KR/tutorial/devtools-extension.md @@ -14,6 +14,10 @@ $ cd /some-directory $ git clone --recursive https://github.com/facebook/react-devtools.git ``` +[`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md) +가이드를 통해 확장 기능을 개발하는 방법을 알아볼 수 있습니다. + + 그리고 개발자 콘솔에서 다음 코드를 입력하면 확장 기능을 로드할 수 있습니다: ```javascript From 5ff97c686ab3ef380d0ed02cf6d9f3835cc20335 Mon Sep 17 00:00:00 2001 From: Robo Date: Tue, 13 Oct 2015 01:13:59 +0530 Subject: [PATCH 167/738] nativemate: handle binary types in v8 value conversion --- .../native_mate_converters/v8_value_converter.cc | 11 +++++++++++ .../native_mate_converters/v8_value_converter.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/atom/common/native_mate_converters/v8_value_converter.cc b/atom/common/native_mate_converters/v8_value_converter.cc index a91e614fc6dd..7d3a1277cb8b 100644 --- a/atom/common/native_mate_converters/v8_value_converter.cc +++ b/atom/common/native_mate_converters/v8_value_converter.cc @@ -152,6 +152,10 @@ v8::Local V8ValueConverter::ToV8ValueImpl( return ToV8Object(isolate, static_cast(value)); + case base::Value::TYPE_BINARY: + return ToArrayBuffer(isolate, + static_cast(value)); + default: LOG(ERROR) << "Unexpected value type: " << value->GetType(); return v8::Null(isolate); @@ -200,6 +204,13 @@ v8::Local V8ValueConverter::ToV8Object( return result.GetHandle(); } +v8::Local V8ValueConverter::ToArrayBuffer( + v8::Isolate* isolate, const base::BinaryValue* value) const { + return node::Buffer::Copy(isolate, + value->GetBuffer(), + value->GetSize()).ToLocalChecked(); +} + base::Value* V8ValueConverter::FromV8ValueImpl( FromV8ValueState* state, v8::Local val, diff --git a/atom/common/native_mate_converters/v8_value_converter.h b/atom/common/native_mate_converters/v8_value_converter.h index db108ad9b043..2b695b43747b 100644 --- a/atom/common/native_mate_converters/v8_value_converter.h +++ b/atom/common/native_mate_converters/v8_value_converter.h @@ -41,6 +41,9 @@ class V8ValueConverter { v8::Local ToV8Object( v8::Isolate* isolate, const base::DictionaryValue* dictionary) const; + v8::Local ToArrayBuffer( + v8::Isolate* isolate, + const base::BinaryValue* value) const; base::Value* FromV8ValueImpl(FromV8ValueState* state, v8::Local value, From b9d838975d0baf4f65ef93ca0efec1305e431ed7 Mon Sep 17 00:00:00 2001 From: Alex Sherwin Date: Mon, 12 Oct 2015 20:17:06 -0400 Subject: [PATCH 168/738] Fixing "tile" -> "title" typo --- docs/tutorial/desktop-environment-integration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/desktop-environment-integration.md b/docs/tutorial/desktop-environment-integration.md index 3132edffcc27..78067f3d8a12 100644 --- a/docs/tutorial/desktop-environment-integration.md +++ b/docs/tutorial/desktop-environment-integration.md @@ -223,7 +223,7 @@ window.setProgressBar(0.5); ## Represented File of Window (OS X) On OS X a window can set its represented file, so the file's icon can show in -the title bar and when users Command-Click or Control-Click on the tile a path +the title bar and when users Command-Click or Control-Click on the title a path popup will show. You can also set the edited state of a window so that the file icon can indicate From b9b25180f83ea512fe51533637fb4e2497d11ed0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 13 Oct 2015 09:04:10 +0800 Subject: [PATCH 169/738] Update brightray for #2903 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 375436a777a7..e3fa861368e5 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 375436a777a793f4815f38c13a5226fcd82de567 +Subproject commit e3fa861368e5fca1e8680e0206fe7b19288dc473 From af8049941e434332b149d9bf4d942d7748ed6e7a Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Tue, 13 Oct 2015 20:53:04 +0900 Subject: [PATCH 170/738] Update as upstream --- .../ko-KR/tutorial/desktop-environment-integration.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md index 94f0ffa013a7..8e73d5940f7c 100644 --- a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md +++ b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md @@ -194,10 +194,10 @@ var window = new BrowserWindow({...}); window.setProgressBar(0.5); ``` -## 윈도우 대표 파일 제시 (OS X) +## 대표 파일 제시 (OS X) -OS X는 윈도우에서 대표 파일을 설정할 수 있습니다. 쉽게 말해 타이틀바에서 파일 아이콘을 볼 수 있을 때 사용자가 Command-Click 또는 Control-Click 할 경우 파일 경로 팝업이 보여집니다. -또한 윈도우의 상태도 지정할 수 있습니다. 쉽게 말해 로드된 문서의 수정여부를 타이틀바 파일 아이콘에 표시할 수 있습니다. +OS X는 창에서 대표 파일을 설정할 수 있습니다. 타이틀바에서 파일 아이콘이 있고, 사용자가 Command-Click 또는 Control-Click 키를 누를 경우 파일 경로 팝업이 보여집니다. +또한 창의 상태도 지정할 수 있습니다. 쉽게 말해 로드된 문서의 수정여부를 타이틀바 파일 아이콘에 표시할 수 있습니다. __대표 파일 팝업 메뉴:__ From d152b25fb638533560da6da3cb9670bc6ab37f23 Mon Sep 17 00:00:00 2001 From: kokdemo Date: Wed, 14 Oct 2015 00:27:17 +0800 Subject: [PATCH 171/738] translate the supported-platforms.md and update the README.md --- .../zh-CN/tutorial/supported-platforms.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs-translations/zh-CN/tutorial/supported-platforms.md diff --git a/docs-translations/zh-CN/tutorial/supported-platforms.md b/docs-translations/zh-CN/tutorial/supported-platforms.md new file mode 100644 index 000000000000..a819e3a0817c --- /dev/null +++ b/docs-translations/zh-CN/tutorial/supported-platforms.md @@ -0,0 +1,27 @@ +# 支持的平台 + +以下的平台是 Electron 目前支持的: + +### OS X + +对于 OS X 系统仅有64位的二进制文档,支持的最低版本是 OS X 10.8。 + +### Windows + +仅支持 Windows 7 及其以后的版本,之前的版本中是不能工作的。 + +对于 Windows 提供 `x86` 和 `amd64` (x64) 版本的二进制文件。需要注意的是 +`ARM` 版本的 Windows 目前尚不支持. + +### Linux + +预编译的 `ia32`(`i686`) 和 `x64`(`amd64`) 版本 Electron 二进制文件都是在 +Ubuntu 12.04 下编译的,`arm` 版的二进制文件是在 ARM v7(硬浮点 ABI 与 +Debian Wheezy 版本的 NEON)下完成的。 + +预编译二进制文件是否能够运行,取决于其中是否包括了编译平台链接的库,所以只有 Ubuntu 12.04 +可以保证正常工作,但是以下的平台也被正事可以运行 Electron的预编译版本: + +* Ubuntu 12.04 及更新 +* Fedora 21 +* Debian 8 From 644af0800c4024c7e533351ce89587e7260cfd36 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 14 Oct 2015 09:47:46 +0800 Subject: [PATCH 172/738] Update brightray for atom/brightray#156 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index e3fa861368e5..d5ca8556a65e 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit e3fa861368e5fca1e8680e0206fe7b19288dc473 +Subproject commit d5ca8556a65e37575fc39e2b394fa62401b996c5 From a9f5667899b64ad1af5b571c5ad2ea4b68410fd3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 28 Sep 2015 14:52:55 +0800 Subject: [PATCH 173/738] mac: Disable crash reporter for MAS build --- atom.gyp | 31 +++++++++++++++----- atom/common/crash_reporter/crash_reporter.cc | 19 ++++++++++++ atom/common/crash_reporter/crash_reporter.h | 4 +-- script/update.py | 6 ++++ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/atom.gyp b/atom.gyp index f5933b8631ec..9838edf54a54 100644 --- a/atom.gyp +++ b/atom.gyp @@ -285,12 +285,21 @@ 'vendor/breakpad/breakpad.gyp:breakpad_sender', ], }], # OS=="win" - ['OS=="mac"', { + ['OS=="mac" and mas_build==0', { 'dependencies': [ 'vendor/crashpad/client/client.gyp:crashpad_client', 'vendor/crashpad/handler/handler.gyp:crashpad_handler', ], - }], # OS=="mac" + }], # OS=="mac" and mas_build==0 + ['OS=="mac" and mas_build==1', { + 'defines': [ + 'MAS_BUILD', + ], + 'sources!': [ + 'atom/common/crash_reporter/crash_reporter_mac.h', + 'atom/common/crash_reporter/crash_reporter_mac.mm', + ], + }], # OS=="mac" and mas_build==1 ['OS=="linux"', { 'link_settings': { 'ldflags': [ @@ -439,12 +448,6 @@ '<@(copied_libraries)', ], }, - { - 'destination': '<(PRODUCT_DIR)/<(product_name) Framework.framework/Versions/A/Resources', - 'files': [ - '<(PRODUCT_DIR)/crashpad_handler', - ], - }, ], 'postbuilds': [ { @@ -476,6 +479,18 @@ ], }, ], + 'conditions': [ + ['mas_build==0', { + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/<(product_name) Framework.framework/Versions/A/Resources', + 'files': [ + '<(PRODUCT_DIR)/crashpad_handler', + ], + }, + ], + }], + ], }, # target framework { 'target_name': '<(project_name)_helper', diff --git a/atom/common/crash_reporter/crash_reporter.cc b/atom/common/crash_reporter/crash_reporter.cc index 59b7fd51e45e..3658931ec188 100644 --- a/atom/common/crash_reporter/crash_reporter.cc +++ b/atom/common/crash_reporter/crash_reporter.cc @@ -64,4 +64,23 @@ CrashReporter::GetUploadedReports(const std::string& path) { return result; } +#if defined(OS_MACOSX) && defined(MAS_BUILD) +void CrashReporter::InitBreakpad(const std::string& product_name, + const std::string& version, + const std::string& company_name, + const std::string& submit_url, + bool auto_submit, + bool skip_system_crash_handler) { +} + +void CrashReporter::SetUploadParameters() { +} + +// static +CrashReporter* CrashReporter::GetInstance() { + static CrashReporter crash_reporter; + return &crash_reporter; +} +#endif + } // namespace crash_reporter diff --git a/atom/common/crash_reporter/crash_reporter.h b/atom/common/crash_reporter/crash_reporter.h index c7d58ca3aa76..98832fea45de 100644 --- a/atom/common/crash_reporter/crash_reporter.h +++ b/atom/common/crash_reporter/crash_reporter.h @@ -40,8 +40,8 @@ class CrashReporter { const std::string& company_name, const std::string& submit_url, bool auto_submit, - bool skip_system_crash_handler) = 0; - virtual void SetUploadParameters() = 0; + bool skip_system_crash_handler); + virtual void SetUploadParameters(); StringMap upload_parameters_; bool is_browser_; diff --git a/script/update.py b/script/update.py index abb3756ca365..e91e8401cbff 100755 --- a/script/update.py +++ b/script/update.py @@ -55,11 +55,17 @@ def run_gyp(target_arch, component): # Avoid using the old gyp lib in system. env['PYTHONPATH'] = os.path.pathsep.join([gyp_pylib, env.get('PYTHONPATH', '')]) + # Whether to build for Mac App Store. + if os.environ.has_key('MAS_BUILD'): + mas_build = 1 + else: + mas_build = 0 defines = [ '-Dlibchromiumcontent_component={0}'.format(component), '-Dtarget_arch={0}'.format(target_arch), '-Dhost_arch={0}'.format(get_host_arch()), '-Dlibrary=static_library', + '-Dmas_build={0}'.format(mas_build), ] return subprocess.call([python, gyp, '-f', 'ninja', '--depth', '.', 'atom.gyp', '-Icommon.gypi'] + defines, env=env) From b62e3554dc695d45eb789ce89e23d3afd32aec34 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 28 Sep 2015 15:02:36 +0800 Subject: [PATCH 174/738] mac: Disable auto updater in MAS build --- atom.gyp | 30 +++++++++++++++++++++++------- atom/browser/auto_updater.cc | 8 ++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/atom.gyp b/atom.gyp index 9838edf54a54..bf655c1cbb4a 100644 --- a/atom.gyp +++ b/atom.gyp @@ -64,9 +64,6 @@ 'files': [ '<(PRODUCT_DIR)/<(product_name) Helper.app', '<(PRODUCT_DIR)/<(product_name) Framework.framework', - 'external_binaries/Squirrel.framework', - 'external_binaries/ReactiveCocoa.framework', - 'external_binaries/Mantle.framework', ], }, { @@ -109,7 +106,21 @@ '<@(locale_dirs)', ], }, - ] + ], + 'conditions': [ + ['mas_build==0', { + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/<(product_name).app/Contents/Frameworks', + 'files': [ + 'external_binaries/Squirrel.framework', + 'external_binaries/ReactiveCocoa.framework', + 'external_binaries/Mantle.framework', + ], + }, + ], + }], + ], }, { # OS=="mac" 'dependencies': [ 'make_locale_paks', @@ -296,6 +307,7 @@ 'MAS_BUILD', ], 'sources!': [ + 'atom/browser/auto_updater_mac.mm', 'atom/common/crash_reporter/crash_reporter_mac.h', 'atom/common/crash_reporter/crash_reporter_mac.mm', ], @@ -402,9 +414,6 @@ 'libraries': [ '$(SDKROOT)/System/Library/Frameworks/Carbon.framework', '$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework', - 'external_binaries/Squirrel.framework', - 'external_binaries/ReactiveCocoa.framework', - 'external_binaries/Mantle.framework', ], }, 'mac_bundle': 1, @@ -481,6 +490,13 @@ ], 'conditions': [ ['mas_build==0', { + 'link_settings': { + 'libraries': [ + 'external_binaries/Squirrel.framework', + 'external_binaries/ReactiveCocoa.framework', + 'external_binaries/Mantle.framework', + ], + }, 'copies': [ { 'destination': '<(PRODUCT_DIR)/<(product_name) Framework.framework/Versions/A/Resources', diff --git a/atom/browser/auto_updater.cc b/atom/browser/auto_updater.cc index fd3d412f9bb0..7ebae510e9f8 100644 --- a/atom/browser/auto_updater.cc +++ b/atom/browser/auto_updater.cc @@ -16,4 +16,12 @@ void AutoUpdater::SetDelegate(AutoUpdaterDelegate* delegate) { delegate_ = delegate; } +#if defined(OS_MACOSX) && defined(MAS_BUILD) +void AutoUpdater::SetFeedURL(const std::string& url) { +} + +void AutoUpdater::CheckForUpdates() { +} +#endif + } // namespace auto_updater From 7b57a945f84c6585ff5dc4658e7da8be6ed9273b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 28 Sep 2015 15:07:49 +0800 Subject: [PATCH 175/738] mac: Set process.mas to true for MAS build --- atom/common/api/atom_bindings.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/atom/common/api/atom_bindings.cc b/atom/common/api/atom_bindings.cc index 8fb2efd3a3f9..06fc30e7e3cd 100644 --- a/atom/common/api/atom_bindings.cc +++ b/atom/common/api/atom_bindings.cc @@ -72,6 +72,10 @@ void AtomBindings::BindTo(v8::Isolate* isolate, // Do not warn about deprecated APIs. dict.Set("noDeprecation", true); +#if defined(MAS_BUILD) + dict.Set("mas", true); +#endif + mate::Dictionary versions; if (dict.Get("versions", &versions)) { versions.Set(ATOM_PROJECT_NAME, ATOM_VERSION_STRING); From 3afc9c4ebef721a64ac7bb26226d2e380b260458 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 28 Sep 2015 15:08:27 +0800 Subject: [PATCH 176/738] spec: Disable crash reporter test for MAS build --- spec/api-crash-reporter-spec.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/api-crash-reporter-spec.coffee b/spec/api-crash-reporter-spec.coffee index 60b630bc2ffc..ef60e6ab9ffb 100644 --- a/spec/api-crash-reporter-spec.coffee +++ b/spec/api-crash-reporter-spec.coffee @@ -18,6 +18,9 @@ describe 'crash-reporter module', -> # It is not working on 64bit Windows. return if process.platform is 'win32' and process.arch is 'x64' + # It is not working for mas build. + return if process.mas + # The crash-reporter test is not reliable on CI machine. isCI = remote.process.argv[2] == '--ci' return if isCI From df7a9b80b1b6012a1f457e9a28a5c0f6bcff9348 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 28 Sep 2015 16:45:53 +0800 Subject: [PATCH 177/738] Fix linking error --- atom/common/crash_reporter/crash_reporter.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/common/crash_reporter/crash_reporter.cc b/atom/common/crash_reporter/crash_reporter.cc index 3658931ec188..b87ce54acd51 100644 --- a/atom/common/crash_reporter/crash_reporter.cc +++ b/atom/common/crash_reporter/crash_reporter.cc @@ -64,7 +64,6 @@ CrashReporter::GetUploadedReports(const std::string& path) { return result; } -#if defined(OS_MACOSX) && defined(MAS_BUILD) void CrashReporter::InitBreakpad(const std::string& product_name, const std::string& version, const std::string& company_name, @@ -76,6 +75,7 @@ void CrashReporter::InitBreakpad(const std::string& product_name, void CrashReporter::SetUploadParameters() { } +#if defined(OS_MACOSX) && defined(MAS_BUILD) // static CrashReporter* CrashReporter::GetInstance() { static CrashReporter crash_reporter; From 48faf74f7fc8cd719d4ea8d1381cd03ab6533691 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 29 Sep 2015 10:59:52 +0800 Subject: [PATCH 178/738] mas: Use mas as platform name in dist --- script/create-dist.py | 10 ++++++---- script/lib/config.py | 7 +++++++ script/upload.py | 11 ++++++----- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/script/create-dist.py b/script/create-dist.py index ca7e21642872..5f47b2d358f0 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -8,7 +8,8 @@ import sys import stat from lib.config import LIBCHROMIUMCONTENT_COMMIT, BASE_URL, PLATFORM, \ - get_target_arch, get_chromedriver_version + get_target_arch, get_chromedriver_version, \ + get_platform_key from lib.util import scoped_cwd, rm_rf, get_atom_shell_version, make_zip, \ execute, atom_gyp @@ -170,7 +171,8 @@ def create_symbols(): def create_dist_zip(): dist_name = '{0}-{1}-{2}-{3}.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION, - PLATFORM, get_target_arch()) + get_platform_key(), + get_target_arch()) zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name) with scoped_cwd(DIST_DIR): @@ -182,7 +184,7 @@ def create_dist_zip(): def create_chrome_binary_zip(binary, version): - dist_name = '{0}-{1}-{2}-{3}.zip'.format(binary, version, PLATFORM, + dist_name = '{0}-{1}-{2}-{3}.zip'.format(binary, version, get_platform_key(), get_target_arch()) zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name) @@ -198,7 +200,7 @@ def create_chrome_binary_zip(binary, version): def create_symbols_zip(): dist_name = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION, - PLATFORM, + get_platform_key(), get_target_arch()) zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name) diff --git a/script/lib/config.py b/script/lib/config.py index 68f216785d60..30eedc13e968 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -20,6 +20,13 @@ PLATFORM = { verbose_mode = False +def get_platform_key(): + if os.environ.has_key('MAS_BUILD'): + return 'mas' + else: + return PLATFORM + + def get_target_arch(): try: target_arch_path = os.path.join(__file__, '..', '..', '..', 'vendor', diff --git a/script/upload.py b/script/upload.py index 6fc421e6b7a2..318bbb594a11 100755 --- a/script/upload.py +++ b/script/upload.py @@ -7,7 +7,8 @@ import subprocess import sys import tempfile -from lib.config import PLATFORM, get_target_arch, get_chromedriver_version +from lib.config import PLATFORM, get_target_arch, get_chromedriver_version, \ + get_platform_key from lib.util import atom_gyp, execute, get_atom_shell_version, parse_version, \ scoped_cwd from lib.github import GitHub @@ -24,14 +25,14 @@ OUT_DIR = os.path.join(SOURCE_ROOT, 'out', 'R') DIST_DIR = os.path.join(SOURCE_ROOT, 'dist') DIST_NAME = '{0}-{1}-{2}-{3}.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION, - PLATFORM, + get_platform_key(), get_target_arch()) SYMBOLS_NAME = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION, - PLATFORM, + get_platform_key(), get_target_arch()) MKSNAPSHOT_NAME = 'mksnapshot-{0}-{1}-{2}.zip'.format(ATOM_SHELL_VERSION, - PLATFORM, + get_platform_key(), get_target_arch()) @@ -85,7 +86,7 @@ def main(): # 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(), PLATFORM, get_target_arch()) + 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)) From 9e51ff2b4b573d11f77b81026163156903c7f06f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 29 Sep 2015 13:25:51 +0800 Subject: [PATCH 179/738] mac: Set CFBundleShortVersionString in Info.plist --- atom/browser/resources/mac/Info.plist | 2 ++ script/bump-version.py | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 77a5502de1eb..cfd6440bf258 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -18,6 +18,8 @@ atom.icns CFBundleVersion 0.33.7 + CFBundleShortVersionString + 0.33.7 LSMinimumSystemVersion 10.8.0 NSMainNibFile diff --git a/script/bump-version.py b/script/bump-version.py index f910ae3ef95f..3ee0b23df3b8 100755 --- a/script/bump-version.py +++ b/script/bump-version.py @@ -106,10 +106,11 @@ def update_info_plist(version): line = lines[i] if 'CFBundleVersion' in line: lines[i + 1] = ' {0}\n'.format(version) + if 'CFBundleShortVersionString' in line: + lines[i + 1] = ' {0}\n'.format(version) - with open(info_plist, 'w') as f: - f.write(''.join(lines)) - return + with open(info_plist, 'w') as f: + f.write(''.join(lines)) def tag_version(version): From 96c15f19e39bbf5f5b1c8d24826c99e2d6996a5e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 29 Sep 2015 13:27:50 +0800 Subject: [PATCH 180/738] mac: Set LSApplicationCategoryType in Info.plist --- atom/browser/resources/mac/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index cfd6440bf258..e35eaea77133 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -20,6 +20,8 @@ 0.33.7 CFBundleShortVersionString 0.33.7 + LSApplicationCategoryType + public.app-category.developer-tools LSMinimumSystemVersion 10.8.0 NSMainNibFile From d6842751bbd636e63db9d436bc12dfff2286036e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 29 Sep 2015 13:32:53 +0800 Subject: [PATCH 181/738] mac: Don't specify CFBundleExecutable in framework --- atom/common/resources/mac/Info.plist | 2 -- 1 file changed, 2 deletions(-) diff --git a/atom/common/resources/mac/Info.plist b/atom/common/resources/mac/Info.plist index 332babe979e6..7f4d818c1bd9 100644 --- a/atom/common/resources/mac/Info.plist +++ b/atom/common/resources/mac/Info.plist @@ -2,8 +2,6 @@ - CFBundleExecutable - ${PRODUCT_NAME} Framework CFBundleIdentifier ${ATOM_BUNDLE_ID} CFBundleName From 51335934c1eba0eb5b4ebd3ea1508a696b5f9b53 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 9 Oct 2015 16:16:35 +0800 Subject: [PATCH 182/738] mac: Set CFBundleExecutable for Electron Framework --- atom/common/resources/mac/Info.plist | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atom/common/resources/mac/Info.plist b/atom/common/resources/mac/Info.plist index 7f4d818c1bd9..7b56a46470ea 100644 --- a/atom/common/resources/mac/Info.plist +++ b/atom/common/resources/mac/Info.plist @@ -5,7 +5,9 @@ CFBundleIdentifier ${ATOM_BUNDLE_ID} CFBundleName - ${PRODUCT_NAME} Framework + ${PRODUCT_NAME} + CFBundleExecutable + ${PRODUCT_NAME} CFBundlePackageType FMWK NSSupportsAutomaticGraphicsSwitching From b47076231ce5e013a5b0a5378af1ff44beb60ed4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 9 Oct 2015 21:30:41 +0800 Subject: [PATCH 183/738] mas: Do not link with QTKit for mas build --- atom.gyp | 6 ++++++ vendor/brightray | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/atom.gyp b/atom.gyp index bf655c1cbb4a..3d9b7f59f395 100644 --- a/atom.gyp +++ b/atom.gyp @@ -301,6 +301,12 @@ 'vendor/crashpad/client/client.gyp:crashpad_client', 'vendor/crashpad/handler/handler.gyp:crashpad_handler', ], + 'link_settings': { + # Do not link with QTKit for mas build. + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/QTKit.framework', + ], + }, }], # OS=="mac" and mas_build==0 ['OS=="mac" and mas_build==1', { 'defines': [ diff --git a/vendor/brightray b/vendor/brightray index d5ca8556a65e..fe2dd437c9ef 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit d5ca8556a65e37575fc39e2b394fa62401b996c5 +Subproject commit fe2dd437c9ef7877bf9d454db8ae401965cd7cb0 From 74d389b2b0a96b30f6d7bf69205cbd18762f62a8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 14 Oct 2015 12:36:03 +0800 Subject: [PATCH 184/738] Bump v0.33.8 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/atom.gyp b/atom.gyp index 3d9b7f59f395..c768289f744b 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.7', + 'version%': '0.33.8', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index e35eaea77133..f4725715526b 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.7 + 0.33.8 CFBundleShortVersionString - 0.33.7 + 0.33.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 39085d2ed8a1..08af14987eee 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,33,7,0 - PRODUCTVERSION 0,33,7,0 + FILEVERSION 0,33,8,0 + PRODUCTVERSION 0,33,8,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.7" + VALUE "FileVersion", "0.33.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.33.7" + VALUE "ProductVersion", "0.33.8" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 995a6f916b1d..205d512b2b52 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 33 -#define ATOM_PATCH_VERSION 7 +#define ATOM_PATCH_VERSION 8 #define ATOM_VERSION_IS_RELEASE 1 From 95c4847d601f350dab5b4f64cc7dca2db55801e2 Mon Sep 17 00:00:00 2001 From: Nicholas Arcuri Date: Wed, 14 Oct 2015 06:28:27 -0400 Subject: [PATCH 185/738] Update application-distribution.md Fix typo on line 38 --- docs/tutorial/application-distribution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/application-distribution.md b/docs/tutorial/application-distribution.md index 4f1f5202a008..d65bc08ca87f 100644 --- a/docs/tutorial/application-distribution.md +++ b/docs/tutorial/application-distribution.md @@ -35,7 +35,7 @@ exposing your app's source code to users. To use an `asar` archive to replace the `app` folder, you need to rename the archive to `app.asar`, and put it under Electron's resources directory like -below, and Electron will then try read the archive and start from it. +below, and Electron will then try to read the archive and start from it. On OS X: From 4270eba43896536390a5d3fd454bed4607fcbee6 Mon Sep 17 00:00:00 2001 From: kokdemo Date: Thu, 15 Oct 2015 00:00:52 +0800 Subject: [PATCH 186/738] translate the debugging-main-process.md --- docs-translations/zh-CN/README.md | 1 + .../zh-CN/tutorial/debugging-main-process.md | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 docs-translations/zh-CN/tutorial/debugging-main-process.md diff --git a/docs-translations/zh-CN/README.md b/docs-translations/zh-CN/README.md index 124d030c46ee..6085cbfb2c65 100644 --- a/docs-translations/zh-CN/README.md +++ b/docs-translations/zh-CN/README.md @@ -1,5 +1,6 @@ ## 向导 +* [支持平台](tutorial/supported-platforms.md) * [应用部署](tutorial/application-distribution.md) * [应用打包](tutorial/application-packaging.md) * [使用原生模块](tutorial/using-native-node-modules.md) diff --git a/docs-translations/zh-CN/tutorial/debugging-main-process.md b/docs-translations/zh-CN/tutorial/debugging-main-process.md new file mode 100644 index 000000000000..48f3579394e7 --- /dev/null +++ b/docs-translations/zh-CN/tutorial/debugging-main-process.md @@ -0,0 +1,48 @@ +# 主进程调试 + +浏览器窗口的开发工具仅能调试渲染器的进程脚本(比如web 页面)。为了提供一个可以调试主进程 +的方法,Electron 提供了 `--debug` 和 `--debug-brk` 开关。 + +## 命令行开关 + +使用如下的命令行开关来调试 Electron 的主进程: + +### `--debug=[port]` + +当这个开关用于 Electron 时,它将会监听 V8 引擎中有关 `port` 的调试器协议信息。 +默认的 `port` 是 `5858`。 + +### `--debug-brk=[port]` + +就像 `--debug` 一样,但是会在第一行暂停脚本运行。 + +## 使用 node-inspector 来调试 + +__备注:__ Electron 使用 node v0.11.13 版本,目前对 node-inspector支持的不是特别好, +如果你通过 node-inspector 的 console 来检查 `process` 对象,主进程就会崩溃。 + +### 1. 开始 [node-inspector][node-inspector] 服务 + +```bash +$ node-inspector +``` + +### 2. 打开 Electron 的调试模式 + +你也可以用调试参数来运行 Electron : + +```bash +$ electron --debug=5858 your/app +``` + +或者,在第一行暂停你的脚本: + +```bash +$ electron --debug-brk=5858 your/app +``` + +### 3. 加载调试器界面 + +在 Chrome 中打开 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858 + +[node-inspector]: https://github.com/node-inspector/node-inspector From 79311af8eb6fc1d6764751fde572ac566c140988 Mon Sep 17 00:00:00 2001 From: Yegun Kim Date: Thu, 15 Oct 2015 16:26:24 -0500 Subject: [PATCH 187/738] translate "/docs-translations/ko-KR/api/app.md" --- docs-translations/ko-KR/api/app.md | 342 +++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 docs-translations/ko-KR/api/app.md diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md new file mode 100644 index 000000000000..2fa04368ec36 --- /dev/null +++ b/docs-translations/ko-KR/api/app.md @@ -0,0 +1,342 @@ +# app + +앱 모듈은 어플리케이션의 생명주기(?) 제어를 책임집니다. + +밑의 예제는 마지막 윈도우가 종료되었을 때, 어떻게 어플리케이션을 종료하는지 설명합니다. + +```javascript +var app = require('app'); +app.on('window-all-closed', function() { + app.quit(); +}); +``` + +## Events + +앱 객체는 밑의 이벤트들을 발현(?)시킵니다. + +### Event: 'will-finish-launching' + +'will-finish-launching' 이벤트는 어플리케이션이 기본적인 시동준비(?)를 마치면 발현(?)됩니다. + 윈도우 운영체제와 리눅스 운영체제 안에서, 'will-finish-launching' 이벤트는 'ready' 이벤트와 동일합니다. +OS X 운영체제 안에서는, 이 이벤트는 'NSApplication'의 'applicationWillFinishLaunching' 알림으로 표현됩니다. +유저는 대개 'open-file'과 'open-url' 이벤트를 위한 listeners을 세팅합니다. +그리고, crash reporter와 auto updater를 시작합니다. + +대부분의 경우, 유저는 모든 것을 'ready' 이벤트 handler로 해결합니다. + +### Event: 'ready' + +Electron이 초기화를 끝냈을 때, 이벤트가 발현합니다. + +### Event: 'window-all-closed' + +모든 윈도우창이 종료되었을 때, 이벤트가 발현합니다. + +이 이벤트는 어플리케이션이 정상 종료되지 않았을 때만 발현됩니다. +만약 유저가 'Cmd + Q' 또는 개발자가 'app.quit()'를 호출했다면, Electron은 먼저 모든 윈도우창 종료를 시도합니다. +그 다음에, 'will-quit' 이벤트를 발현시킵니다. +그리고, 'will-quit'가 발현된 경우에는 'window-all-closed' 이벤트는 발현되지 않습니다. + +### Event: 'before-quit' + +Returns: + +* `event` Event + +어플리케이션이 어플리케이션의 윈도우 종료를 시작하기 전에, 발현됩니다. +'event.preventDefault()' 호출은 어플리케이션의 강제종료 행위를 방지합니다. + +### Event: 'will-quit' + +Returns: + +* `event` Event + +모든 윈도우창이 종료되고 어플리케이션이 종료하고자 할 때, 이벤트가 발현됩니다. +'event.preventDefault()'의 호출은 어플리케이션 종료를 방지합니다. +'will-quit' 이벤트와 'window-all-closed' 이벤트와의 차이점을 확인하려면, +'window-all-close' 이벤트의 설명을 참조합시다. + +### Event: 'quit' + +어플리케이션이 종료될 때, 발현됩니다. + +### Event: 'open-file' + +Returns: + +* `event` Event +* `path` String + +어플리케이션을 이용하여 파일을 열고자 할 때, 발현됩니다. + +'open-file' 이벤트는 보통 어플리케이션이 열려 있을 때와, +파일을 열기 위해 OS가 어플리케이션을 재사용할 때 발현됩니다. +'open-file'은 파일이 dock에 추가될 때와 어플리케이션이 실행하기 전에도 발현됩니다. +위의 케이스를 처리하기 위해서는, 'ready' 이벤트가 발현되기도 전에, 어플리케이션 시작 초기 시 +'open-file' 이벤트에 linsten을 걸어 놨는지 반드시 확인해야 합니다. + +이 이벤트를 처리하기 위한다면, 유저는 'even.preventDefault()'를 호출해야 합니다. + +### Event: 'open-url' + +Returns: + +* `event` Event +* `url` String + +유저가 어플리케이션을 이용하여 URL을 열고자 할 경우, 발현됩니다. +어플리케이션을 통해 열기 위해서는 URL 구조가 반드시 등록되어 있어야 합니다. +이 이벤트를 처리하기 위해선, 유저가 'event.preventDefault()'을 호출해야 합니다. + +### Event: 'activate' _OS X_ + +Returns: + +* `event` Event +* `hasVisibleWindows` Bool + +어플리케이션이 활성화 되었을 때 발현됩니다. +(어플리케이션은 dock 아이콘을 click했을 때 주로 활성화됩니다.) + +### Event: 'browser-window-blur' + +Returns: + +* `event` Event +* `window` BrowserWindow + +[browserWindow](browser-window.md)가 흐려졌을 때, 호출됩니다. + +### Event: 'browser-window-focus' + +Returns: + +* `event` Event +* `window` BrowserWindow + +[browserWindow](browser-window.md)을 포커싱했을 때, 호출됩니다. +(포커싱이란? 클릭 또는 활성화했을 때를 의미) + +### Event: 'browser-window-created' + +Returns: + +* `event` Event +* `window` BrowserWindow + +새로운 [browserWindow](browser-window.md)가 생성될 때 발현됩니다. + +### Event: 'select-certificate' + +유저인증이 요청되었을 때 발현됩니다. + +Returns: + +* `event` Event +* `webContents` [WebContents](browser-window.md#class-webcontents) +* `url` String +* `certificateList` [Objects] + * `data` PEM encoded data + * `issuerName` Issuer's Common Name +* `callback` Function + +```javascript +app.on('select-certificate', function(event, host, url, list, callback) { + event.preventDefault(); + callback(list[0]); +}) +``` + +'url' 유저인증 요청의 탐색 항목에 대응합니다. +그리고, 'callback' 는 리스트로 필터링된 항목과 함께 호출될 필요가 있습니다. + +'event.preventDefault()' 호출은 기록소로부터 처음인증된 정보를 사용하는 +어플리케이션을 막습니다. + +### Event: 'gpu-process-crashed' + +GPU가 충돌을 일으켰을 때, 발현됩니다. + +## Methods + +'app' 객체는 밑의 함수를 포함하고 있습니다: + +**Note:** 어떤 함수들은 표시된 특정한 운영체제에서만 사용가능합니다. + +### `app.quit()` + +모든 윈도우창 종료를 시도합니다. 'before-quit' 이벤트가 먼저 발현됩니다. +모든 윈도우창이 성공적으로 종료되었다면, 'will-quit' 이벤트가 발현하고, +디폴트설정으로 어플리케이션이 종료됩니다. + +이 함수는 모든 'beforeunload'과 'unload' 이벤트 처리기가 제대로 실행되었음을 보장합니다. +(즉, 'beforeunload'와 'unload'가 정상 실행되었을 때, 실행가능합니다.) + +'beforeunload' 이벤트 처리기가 'false'를 반환하였을 경우, 윈도우 창 종료가 취소 될 수 있습니다. + + +### `app.getAppPath()` + +현재 어플리케이션의 디렉토리를 반환합니다. + +### `app.getPath(name)` + +* `name` String + +특정한 디렉토리의 경로나 'name' 파일의 경로를 찾아 반환합니다. +실패할 경우, 'Error'를 반환합니다. + +유저는 다음과 같은 이름으로 경로를 요쳥할 수 있습니다: + +* `home` = 유저의 홈 디렉토리. +* `appData` = 유저의 어플리케이션 데이터 디렉토리, 디폴트설정으로: + * `%APPDATA%` = on Windows + * `$XDG_CONFIG_HOME` 또는 `~/.config` = on Linux + * `~/Library/Application Support` = on OS X +* `userData` = 유저 app의 설정파일을 저장하는 디렉토리, +디폴트설정으로 'appData' 디렉토리에 유저 app의 이름을 추가한 형식. +* `temp` = 임시 디렉토리. +* `userDesktop` = 현재 로그인한 유저의 데스트탑 디렉토리. +* `exe` = 현재 실행가능한 파일. +* `module` = `libchromiumcontent` 라이브러리. + +### `app.setPath(name, path)` + +* `name` String +* `path` String + +특정한 디렉토리나 파일이름이 'name'인 'path'를 재정의합니다. +만약 지정된 디렉토리의 경로가 존재하지 않는다면, 디렉토리가 새로 생성됩니다. +실패시, 'Error'를 반환합니다. + +유저는 'app.getPath'에 정의되어 있는 'name' 경로만 재정의할 수 있습니다. + +디폴트설정으로, 웹페이지의 쿠키와 캐시는 'userData' 디렉토리 밑에 저장됩니다. + +만약 유저가 이 위치를 변경하고자 한다면, 'app' 모듈의 'ready' 이벤트가 발현되기 전, +유저는 반드시 'userData' 경로를 재정의해야 합니다. + +### `app.getVersion()` + +로드된 어플리케이션의 버전을 반환합니다. + +만약 'package.json' 파일에서 어플리케이션의 버전을 찾지 못한다면, +현재 번들 또는 실행 파일의 버전이 반환됩니다. + +### `app.getName()` + +응용프로그램(=어플리케이션)의 'package.json' 파일에 있는 +현재 응용프로그램의 이름을 반환합니다. + +NPM 모듈 스펙에 따라, 대부분 'package.json'의 'name' 필드는 소문자 이름입니다. +유저는 'productName'의 필드를 지정해야 합니다. +'productName'는 응용프로그램의 대문자 이름입니다. +'productName'는 Electron에서 선호하는 'name' 입니다. + +### `app.getLocale()` + +현재 응용프로그램의 locale을 반환합니다. + +### `app.resolveProxy(url, callback)` + +* `url` URL +* `callback` Function + +'url'을 위해 프록시 정보를 해석합니다. +'callback'은 'callback(proxy)' 요청이 수행될 때, +호출됩니다. + +### `app.addRecentDocument(path)` + +* `path` String + +최근 문서 목록에 'path'를 추가합니다. + +목록은 운영체제에 의해 관리됩니다. +Windows 운영체제에서는, 작업표시줄에서 참조할 수 있습니다. +OS X 운영체제에서는, dock 메뉴에서 참조할 수 있습니다. + +### `app.clearRecentDocuments()` + +최근 문서 목록을 모두 지웁니다. + +### `app.setUserTasks(tasks)` _Windows_ + +* `tasks` Array - 'Task' 객체의 배열 + +Windows 운영체제에서 JumpList의 [Tasks][tasks] 카테고리로 'tasks'를 추가합니다. + +'tasks'는 밑의 형식을 따르는 'Task' 객체의 배열입니다: + +`Task` Object +* `program` String - 프로그램을 실행할 경로, 대부분 유저는 현재 프로그램을 여는 'process.execPath'를 지정합니다. +* `arguments` String - 'program'이 실행될 때의 명령문 인자. +* `title` String - JumpList에 표시할 문장. +* `description` String - 이 task 객체에 대한 설명. +* `iconPath` String - 아이콘을 포함한 임의의 리소스 파일이며, JumpList에 표시될 아이콘의 절대 경로. +유저는 대부분 프로그램의 아이콘을 표시하기 위해 'process.execPath'를 지정합니다. +* `iconIndex` Integer - 아이콘 파일안의 아이콘 색인(index). 만약, 아이콘 파일 안에 두 개 이상의 아이콘이 있을 경우, + 아이콘을 특정하기 위해 이 값을 설정합니다. 단, 하나의 아이콘만 있을 경우는 0 값을 가집니다. + +### `app.commandLine.appendSwitch(switch[, value])` + +Append a switch (with optional `value`) to Chromium's command line. +Chromium의 명령문에 (선택적으로, 'value'와 함께) switch를 추가합니다. + +**Note:** 이 함수는 'process.argv'에 영향을 주지 않습니다. +그리고, 보통 이 함수는 개발자들이 하드웨어 수준의 Chrominum의 행동을 제어하기 위해 주로 사용됩니다. + +### `app.commandLine.appendArgument(value)` + +Chromium의 명령문에 인자를 추가합니다. 인자는 올바르게 인용될 것입니다. + +**Note:** 'process.argv'에 영향을 주지는 않습니다. + +### `app.dock.bounce([type])` _OS X_ + +* `type` String (optional) - 'critical'이나 'informational'. 디폴트 설정은 'informational' + +'critical'이 input으로 전달되면, dock 아이콘은 응용프로그램이 활성화되거나, 요청이 취소될 때까지 +계속 bounce합니다. + +'informational'이 input으로 전달되면, dock 아이콘은 1초만 bounce합니다. +그러나, 응용프로그램이 활성화되거나 요청이 취소될 때까지 요청은 계속 활성화되어 있습니다. + +요청을 대표하는 ID를 반환합니다. + +### `app.dock.cancelBounce(id)` _OS X_ + +* `id` Integer + +'id'의 반송을 취소합니다. + + +### `app.dock.setBadge(text)` _OS X_ + +* `text` String + +dock의 badge 구역에 표현될 문장을 설정합니다. + +### `app.dock.getBadge()` _OS X_ + +dock의 badge 라인을 반환합니다. + + +### `app.dock.hide()` _OS X_ + +dock 아이콘을 숨깁니다. + +### `app.dock.show()` _OS X_ + +dock 아이콘을 보여줍니다. + +### `app.dock.setMenu(menu)` _OS X_ + +* `menu` Menu + +어플리케이션의 [dock menu][dock-menu]을 결정합니다. + +[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 From f52c4af605e343c3131327041a21b0b8b882c191 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 15 Oct 2015 12:44:55 +0800 Subject: [PATCH 188/738] win: Don't output newline except for main process --- atom/app/atom_main_delegate.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 639340bcf091..44f2048c091f 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -21,6 +21,15 @@ namespace atom { +namespace { + +bool IsBrowserProcess(base::CommandLine* cmd) { + std::string process_type = cmd->GetSwitchValueASCII(switches::kProcessType); + return process_type.empty(); +} + +} // namespace + AtomMainDelegate::AtomMainDelegate() { } @@ -28,11 +37,14 @@ AtomMainDelegate::~AtomMainDelegate() { } bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { + auto command_line = base::CommandLine::ForCurrentProcess(); + logging::LoggingSettings settings; #if defined(OS_WIN) // On Windows the terminal returns immediately, so we add a new line to // prevent output in the same line as the prompt. - std::wcout << std::endl; + if (IsBrowserProcess(command_line)) + std::wcout << std::endl; #if defined(DEBUG) // Print logging to debug.log on Windows settings.logging_dest = logging::LOG_TO_ALL; @@ -47,7 +59,6 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { #endif // !defined(OS_WIN) // Only enable logging when --enable-logging is specified. - auto command_line = base::CommandLine::ForCurrentProcess(); if (!command_line->HasSwitch(switches::kEnableLogging)) { settings.logging_dest = logging::LOG_NONE; logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES); @@ -83,7 +94,7 @@ void AtomMainDelegate::PreSandboxStartup() { } // Only append arguments for browser process. - if (!process_type.empty()) + if (!IsBrowserProcess(command_line)) return; #if defined(OS_WIN) From 6aec8b092cf6c249649414d1c0a85f2a878bdd69 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 15 Oct 2015 16:19:45 +0800 Subject: [PATCH 189/738] views: Fix crash when setSizeConstrains is called early --- atom/browser/native_window_views.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 4c8d014b1ec9..e3688235bd4e 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -390,7 +390,10 @@ gfx::Size NativeWindowViews::GetContentSize() { void NativeWindowViews::SetContentSizeConstraints( const extensions::SizeConstraints& size_constraints) { NativeWindow::SetContentSizeConstraints(size_constraints); - window_->OnSizeConstraintsChanged(); + // widget_delegate() is only available after Init() is called, we make use of + // this to determine whether native widget has initialized. + if (window_ && window_->widget_delegate()) + window_->OnSizeConstraintsChanged(); #if defined(USE_X11) if (resizable_) old_size_constraints_ = size_constraints; From 11a49bba35005c3c91beaaa6e2523c5a9f9751a5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 15 Oct 2015 16:35:50 +0800 Subject: [PATCH 190/738] win: Fix "enable-larger-than-screen" option spec --- atom/browser/native_window.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index dd4694b3bd6b..7f30aa00389f 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -116,7 +116,8 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { } else if (options.Get(switches::kCenter, ¢er) && center) { Center(); } - extensions::SizeConstraints size_constraints; + // On Linux and Window we may already have maximum size defined. + extensions::SizeConstraints size_constraints(GetContentSizeConstraints()); int min_height = 0, min_width = 0; if (options.Get(switches::kMinHeight, &min_height) | options.Get(switches::kMinWidth, &min_width)) { From 55d5660ddb9650ea2ced673aee51805f449e7841 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 15 Oct 2015 13:16:24 +0800 Subject: [PATCH 191/738] win: Make the event in crash service signaled by default Otherwise it seems to block the crash client on some machines. Fix #2769. --- atom/common/crash_reporter/win/crash_service.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/common/crash_reporter/win/crash_service.cc b/atom/common/crash_reporter/win/crash_service.cc index d315b0b9419e..9b6ba7e03a65 100644 --- a/atom/common/crash_reporter/win/crash_service.cc +++ b/atom/common/crash_reporter/win/crash_service.cc @@ -311,7 +311,7 @@ bool CrashService::Initialize(const base::string16& application_name, // service is initialized. base::string16 wait_name = ReplaceStringPlaceholders( kWaitEventFormat, application_name, NULL); - HANDLE wait_event = ::CreateEventW(NULL, TRUE, FALSE, wait_name.c_str()); + HANDLE wait_event = ::CreateEventW(NULL, TRUE, TRUE, wait_name.c_str()); ::SetEvent(wait_event); return true; From d90b598125322ebc191dd09a3a606cb6426dbbce Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 15 Oct 2015 14:16:27 +0800 Subject: [PATCH 192/738] win: Hook up V8 to breakpad This fixes the crashes happens from V8 not caught by the crash reporter, for more context, see http://code.google.com/p/v8/issues/detail?id=3597. Fix #2365. --- atom/app/atom_main_delegate.cc | 8 ++ .../crash_reporter/crash_reporter_win.cc | 124 +++++++++++++++++- .../crash_reporter/crash_reporter_win.h | 6 + 3 files changed, 135 insertions(+), 3 deletions(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 44f2048c091f..1c35bced3e6c 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -19,6 +19,10 @@ #include "content/public/common/content_switches.h" #include "ui/base/resource/resource_bundle.h" +#if defined(OS_WIN) +#include "atom/common/crash_reporter/crash_reporter_win.h" +#endif + namespace atom { namespace { @@ -69,6 +73,10 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { // Logging with pid and timestamp. logging::SetLogItems(true, false, true, false); +#if defined(OS_WIN) + crash_reporter::SetupV8CodeRangeHook(); +#endif + #if defined(DEBUG) && defined(OS_LINUX) // Enable convient stack printing. base::debug::EnableInProcessStackDumping(); diff --git a/atom/common/crash_reporter/crash_reporter_win.cc b/atom/common/crash_reporter/crash_reporter_win.cc index be096da80e2c..8ea5b6689cfb 100644 --- a/atom/common/crash_reporter/crash_reporter_win.cc +++ b/atom/common/crash_reporter/crash_reporter_win.cc @@ -11,6 +11,25 @@ #include "base/memory/singleton.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "content/public/common/result_codes.h" +#include "gin/public/debug.h" +#include "sandbox/win/src/nt_internals.h" + +#pragma intrinsic(_AddressOfReturnAddress) +#pragma intrinsic(_ReturnAddress) + +#ifdef _WIN64 +// See http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx +typedef struct _UNWIND_INFO { + unsigned char Version : 3; + unsigned char Flags : 5; + unsigned char SizeOfProlog; + unsigned char CountOfCodes; + unsigned char FrameRegister : 4; + unsigned char FrameOffset : 4; + ULONG ExceptionHandler; +} UNWIND_INFO, *PUNWIND_INFO; +#endif namespace crash_reporter { @@ -24,8 +43,101 @@ const MINIDUMP_TYPE kSmallDumpType = static_cast( const wchar_t kWaitEventFormat[] = L"$1CrashServiceWaitEvent"; const wchar_t kPipeNameFormat[] = L"\\\\.\\pipe\\$1 Crash Service"; +typedef NTSTATUS (WINAPI* NtTerminateProcessPtr)(HANDLE ProcessHandle, + NTSTATUS ExitStatus); +char* g_real_terminate_process_stub = NULL; + +void TerminateProcessWithoutDump() { + // Patched stub exists based on conditions (See InitCrashReporter). + // As a side note this function also gets called from + // WindowProcExceptionFilter. + if (g_real_terminate_process_stub == NULL) { + ::TerminateProcess(::GetCurrentProcess(), content::RESULT_CODE_KILLED); + } else { + NtTerminateProcessPtr real_terminate_proc = + reinterpret_cast( + static_cast(g_real_terminate_process_stub)); + real_terminate_proc(::GetCurrentProcess(), content::RESULT_CODE_KILLED); + } +} + +#ifdef _WIN64 +int CrashForExceptionInNonABICompliantCodeRange( + PEXCEPTION_RECORD ExceptionRecord, + ULONG64 EstablisherFrame, + PCONTEXT ContextRecord, + PDISPATCHER_CONTEXT DispatcherContext) { + EXCEPTION_POINTERS info = { ExceptionRecord, ContextRecord }; + if (!CrashReporter::GetInstance()) + return EXCEPTION_CONTINUE_SEARCH; + return static_cast(CrashReporter::GetInstance())-> + CrashForException(&info); +} + +struct ExceptionHandlerRecord { + RUNTIME_FUNCTION runtime_function; + UNWIND_INFO unwind_info; + unsigned char thunk[12]; +}; + +void RegisterNonABICompliantCodeRange(void* start, size_t size_in_bytes) { + ExceptionHandlerRecord* record = + reinterpret_cast(start); + + // We assume that the first page of the code range is executable and + // committed and reserved for breakpad. What could possibly go wrong? + + // All addresses are 32bit relative offsets to start. + record->runtime_function.BeginAddress = 0; + record->runtime_function.EndAddress = + base::checked_cast(size_in_bytes); + record->runtime_function.UnwindData = + offsetof(ExceptionHandlerRecord, unwind_info); + + // Create unwind info that only specifies an exception handler. + record->unwind_info.Version = 1; + record->unwind_info.Flags = UNW_FLAG_EHANDLER; + record->unwind_info.SizeOfProlog = 0; + record->unwind_info.CountOfCodes = 0; + record->unwind_info.FrameRegister = 0; + record->unwind_info.FrameOffset = 0; + record->unwind_info.ExceptionHandler = + offsetof(ExceptionHandlerRecord, thunk); + + // Hardcoded thunk. + // mov imm64, rax + record->thunk[0] = 0x48; + record->thunk[1] = 0xb8; + void* handler = &CrashForExceptionInNonABICompliantCodeRange; + memcpy(&record->thunk[2], &handler, 8); + + // jmp rax + record->thunk[10] = 0xff; + record->thunk[11] = 0xe0; + + // Protect reserved page against modifications. + DWORD old_protect; + CHECK(VirtualProtect( + start, sizeof(ExceptionHandlerRecord), PAGE_EXECUTE_READ, &old_protect)); + CHECK(RtlAddFunctionTable( + &record->runtime_function, 1, reinterpret_cast(start))); +} + +void UnregisterNonABICompliantCodeRange(void* start) { + ExceptionHandlerRecord* record = + reinterpret_cast(start); + + CHECK(RtlDeleteFunctionTable(&record->runtime_function)); +} +#endif // _WIN64 + } // namespace +void SetupV8CodeRangeHook() { + gin::Debug::SetCodeRangeCreatedCallback(RegisterNonABICompliantCodeRange); + gin::Debug::SetCodeRangeDeletedCallback(UnregisterNonABICompliantCodeRange); +} + CrashReporterWin::CrashReporterWin() { } @@ -63,14 +175,12 @@ void CrashReporterWin::InitBreakpad(const std::string& product_name, // to allow any previous handler to detach in the correct order. breakpad_.reset(); - int handler_types = google_breakpad::ExceptionHandler::HANDLER_EXCEPTION | - google_breakpad::ExceptionHandler::HANDLER_PURECALL; breakpad_.reset(new google_breakpad::ExceptionHandler( temp_dir.value(), FilterCallback, MinidumpCallback, this, - handler_types, + google_breakpad::ExceptionHandler::HANDLER_ALL, kSmallDumpType, pipe_name.c_str(), GetCustomInfo(product_name, version, company_name))); @@ -83,6 +193,14 @@ void CrashReporterWin::SetUploadParameters() { upload_parameters_["platform"] = "win32"; } +int CrashReporterWin::CrashForException(EXCEPTION_POINTERS* info) { + if (breakpad_) { + breakpad_->WriteMinidumpForException(info); + TerminateProcessWithoutDump(); + } + return EXCEPTION_CONTINUE_SEARCH; +} + // static bool CrashReporterWin::FilterCallback(void* context, EXCEPTION_POINTERS* exinfo, diff --git a/atom/common/crash_reporter/crash_reporter_win.h b/atom/common/crash_reporter/crash_reporter_win.h index 72b9411d2191..1725ca328310 100644 --- a/atom/common/crash_reporter/crash_reporter_win.h +++ b/atom/common/crash_reporter/crash_reporter_win.h @@ -17,6 +17,9 @@ template struct DefaultSingletonTraits; namespace crash_reporter { +// Hook up V8 to breakpad. +void SetupV8CodeRangeHook(); + class CrashReporterWin : public CrashReporter { public: static CrashReporterWin* GetInstance(); @@ -29,6 +32,9 @@ class CrashReporterWin : public CrashReporter { bool skip_system_crash_handler) override; void SetUploadParameters() override; + // Crashes the process after generating a dump for the provided exception. + int CrashForException(EXCEPTION_POINTERS* info); + private: friend struct DefaultSingletonTraits; From f5c25d6277ffe025f3f0e5e621feafc06f1390d8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 15 Oct 2015 18:25:07 +0800 Subject: [PATCH 193/738] win: Only install breakpad hook when crash-reporter is used --- atom/app/atom_main_delegate.cc | 8 -------- .../crash_reporter/crash_reporter_win.cc | 19 ++++++++++++++----- .../crash_reporter/crash_reporter_win.h | 3 --- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 1c35bced3e6c..44f2048c091f 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -19,10 +19,6 @@ #include "content/public/common/content_switches.h" #include "ui/base/resource/resource_bundle.h" -#if defined(OS_WIN) -#include "atom/common/crash_reporter/crash_reporter_win.h" -#endif - namespace atom { namespace { @@ -73,10 +69,6 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { // Logging with pid and timestamp. logging::SetLogItems(true, false, true, false); -#if defined(OS_WIN) - crash_reporter::SetupV8CodeRangeHook(); -#endif - #if defined(DEBUG) && defined(OS_LINUX) // Enable convient stack printing. base::debug::EnableInProcessStackDumping(); diff --git a/atom/common/crash_reporter/crash_reporter_win.cc b/atom/common/crash_reporter/crash_reporter_win.cc index 8ea5b6689cfb..78bd196f6cce 100644 --- a/atom/common/crash_reporter/crash_reporter_win.cc +++ b/atom/common/crash_reporter/crash_reporter_win.cc @@ -133,11 +133,6 @@ void UnregisterNonABICompliantCodeRange(void* start) { } // namespace -void SetupV8CodeRangeHook() { - gin::Debug::SetCodeRangeCreatedCallback(RegisterNonABICompliantCodeRange); - gin::Debug::SetCodeRangeDeletedCallback(UnregisterNonABICompliantCodeRange); -} - CrashReporterWin::CrashReporterWin() { } @@ -187,6 +182,20 @@ void CrashReporterWin::InitBreakpad(const std::string& product_name, if (!breakpad_->IsOutOfProcess()) LOG(ERROR) << "Cannot initialize out-of-process crash handler"; + +#ifdef _WIN64 + // Hook up V8 to breakpad. + { + // gin::Debug::SetCodeRangeCreatedCallback only runs the callback when + // Isolate is just created, so we have to manually run following code here. + void* code_range = nullptr; + size_t size = 0; + v8::Isolate::GetCurrent()->GetCodeRange(&code_range, &size); + if (code_range && size) + RegisterNonABICompliantCodeRange(code_range, size); + } + gin::Debug::SetCodeRangeDeletedCallback(UnregisterNonABICompliantCodeRange); +#endif } void CrashReporterWin::SetUploadParameters() { diff --git a/atom/common/crash_reporter/crash_reporter_win.h b/atom/common/crash_reporter/crash_reporter_win.h index 1725ca328310..09c7ff4eaad6 100644 --- a/atom/common/crash_reporter/crash_reporter_win.h +++ b/atom/common/crash_reporter/crash_reporter_win.h @@ -17,9 +17,6 @@ template struct DefaultSingletonTraits; namespace crash_reporter { -// Hook up V8 to breakpad. -void SetupV8CodeRangeHook(); - class CrashReporterWin : public CrashReporter { public: static CrashReporterWin* GetInstance(); From 909779babf4bafe88d826bf61b3e2b6bf23a2949 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 15 Oct 2015 18:25:34 +0800 Subject: [PATCH 194/738] spec: Bring back crash-reporter spec on x64 Windows --- spec/api-crash-reporter-spec.coffee | 3 --- 1 file changed, 3 deletions(-) diff --git a/spec/api-crash-reporter-spec.coffee b/spec/api-crash-reporter-spec.coffee index ef60e6ab9ffb..9aedb0c8ea1e 100644 --- a/spec/api-crash-reporter-spec.coffee +++ b/spec/api-crash-reporter-spec.coffee @@ -15,9 +15,6 @@ describe 'crash-reporter module', -> beforeEach -> w = new BrowserWindow(show: false) afterEach -> w.destroy() - # It is not working on 64bit Windows. - return if process.platform is 'win32' and process.arch is 'x64' - # It is not working for mas build. return if process.mas From 904f3c256420d2efd79c1dc411b3a7028e18985e Mon Sep 17 00:00:00 2001 From: Lucas Pugliesi Date: Thu, 15 Oct 2015 10:52:30 -0300 Subject: [PATCH 195/738] Translation of using-native-node-modules to pt-br. --- docs-translations/pt-BR/README.md | 4 +- .../tutorial/using-native-node-modules.md | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 docs-translations/pt-BR/tutorial/using-native-node-modules.md diff --git a/docs-translations/pt-BR/README.md b/docs-translations/pt-BR/README.md index 74923a411c5d..b142c861597b 100644 --- a/docs-translations/pt-BR/README.md +++ b/docs-translations/pt-BR/README.md @@ -1,8 +1,8 @@ ## Guias -* [Distribuir Aplicação](tutorial/application-distribution.md) +* [Distribuição de Aplicações](tutorial/application-distribution.md) * [Empacotamento da aplicação](tutorial/application-packaging.md) -* [Usando módulos nativos](../../docs/tutorial/using-native-node-modules.md) +* [Usando módulos nativos](tutorial/using-native-node-modules.md) * [Depuração do processo principal](../../docs/tutorial/debugging-main-process.md) * [Usando Selenium e WebDriver](../../docs/tutorial/using-selenium-and-webdriver.md) * [Extensão DevTools](../../docs/tutorial/devtools-extension.md) diff --git a/docs-translations/pt-BR/tutorial/using-native-node-modules.md b/docs-translations/pt-BR/tutorial/using-native-node-modules.md new file mode 100644 index 000000000000..c5e9eeddd61e --- /dev/null +++ b/docs-translations/pt-BR/tutorial/using-native-node-modules.md @@ -0,0 +1,68 @@ +# Usando Módulos Nativos do Node + +Os módulos nativos do Node são suportados pelo Electron, desde que o Electron +esteja usando uma versão diferente da oficial V8 do Node, você tem de +especificar manualmente a localização das headers do Electron quando compilar os +módulos nativos. + +## Compatibilidade de Módulos Nativos do Node + +Módulos nativos podem quebrar quando utilizar a nova versão do Node, V8. +Para ter certeza que o módulo que você está interessado em trabalhar com o +Electron, você deve checar se a versão do Node utilizada é compatível com a +usada pelo Electron. +Você pode verificar qual versão do Node foi utilizada no Electron olhando na +página [releases](https://github.com/atom/electron/releases) ou usando +`process.version` (veja [Quick Start](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md) +por exemplo). + +Considere usar [NAN](https://github.com/nodejs/nan/) para seus próprios +módulos, caso isso facilite o suporte da múltiplas versões do Node. Isso é +também de grande ajuda para fazer a portabilidade dos módulos antigos para as +versões mais novas do Node, assim podendo trabalhar com o Electron. + +## Como Instalar os Módulos Nativos + +Existem três maneiras de instalar os módulos nativos: + +### O Modo Fácil + +O modo mais direto para recompilar os módulos é pelo pacote +[`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild), +o que lida com passos manuais para baixar as headers e construir os módulos +nativos: + +```sh +npm install --save-dev electron-rebuild + +# Sempre que rodar npm install, execute também: +node ./node_modules/.bin/electron-rebuild +``` + +### Via npm + +Você pode usar também `npm` para instalar os módulos. Os passos são exatamente +os mesmos com os módulos Node, exceto que você precisa configurar algumas +variáveis da ambiente: + +```bash +export npm_config_disturl=https://atom.io/download/atom-shell +export npm_config_target=0.33.1 +export npm_config_arch=x64 +export npm_config_runtime=electron +HOME=~/.electron-gyp npm install module-name +``` + +### O modo node-gyp + +Para compilar os módulos do Node com as headers do Electron, você precisa dizer +ao `node-gyp` onde baixar as headers e qual versão usar: + +```bash +$ cd /path-to-module/ +$ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=https://atom.io/download/atom-shell +``` + +A tag `HOME=~/.electron-gyp` altera onde encontrar as headers de desenvolvimento. +A tag `--target=0.29.1` é a versão do Electron. A tag `--dist-url=...` especifica +onde baixar as headers. A tag `--arch=x64` diz ao módulo que é feito em 64bit. From 3dba56c335f977f0ffed7626f664f09e4d21693c Mon Sep 17 00:00:00 2001 From: Lucas Pugliesi Date: Thu, 15 Oct 2015 17:16:48 -0300 Subject: [PATCH 196/738] Translation of using-pepper-flash-plugin to pt-br. --- docs-translations/pt-BR/README.md | 2 +- .../tutorial/using-pepper-flash-plugin.md | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md diff --git a/docs-translations/pt-BR/README.md b/docs-translations/pt-BR/README.md index b142c861597b..3db45bb7e2af 100644 --- a/docs-translations/pt-BR/README.md +++ b/docs-translations/pt-BR/README.md @@ -6,7 +6,7 @@ * [Depuração do processo principal](../../docs/tutorial/debugging-main-process.md) * [Usando Selenium e WebDriver](../../docs/tutorial/using-selenium-and-webdriver.md) * [Extensão DevTools](../../docs/tutorial/devtools-extension.md) -* [Usando o plugin papper flash](../../docs/tutorial/using-pepper-flash-plugin.md) +* [Usando o plugin papper flash](tutorial/using-pepper-flash-plugin.md) ## Tutoriais diff --git a/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md b/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md new file mode 100644 index 000000000000..a92f61c78e28 --- /dev/null +++ b/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md @@ -0,0 +1,68 @@ +# Usando o Plugin Pepper Flash + +Electron atualmente suporta o plugin Pepper Flash. Para usá-lo no Electron, +você deve especificar manualmente a localização do plugin e então ele será +habilitado em sua aplicação. + +## Prepare uma cópia do plugin Flash + +Tanto no OS X como no Linux, os detalhes do plugin Pepper Flash podem ser +encontrados navegando por `chrome://plugins` no navegador Chrome. Essa +localização e versão são úteis para o suporte do plugin Electron's Pepper Flash. +Você pode também copiar para outra localização. + +## Adicionando a opçao Electron + +Você pode adicionar diretamente `--ppapi-flash-path` e `ppapi-flash-version` +para a linha de comando do Electron ou usando o método +`app.commandLine.appendSwitch` após o evento pronto. Também, adicione a opção +`plugins` em `browser-window`. +Por exemplo: + +```javascript +var app = require('app'); +var BrowserWindow = require('browser-window'); + +// Informa os erros ao ao servidor. +require('crash-reporter').start(); + +// Mantém uma referência global da janela, se não manter, a janela irá fechar +// automaticamente quando o objeto javascript for GCed. +var mainWindow = null; + +// Sai assim que todas as janelas forem fechadas. +app.on('window-all-closed', function() { + if (process.platform != 'darwin') { + app.quit(); + } +}); + +// Epecifica o caminho do flash. +// No Windows, deve ser /path/to/pepflashplayer.dll +// No Mac, /path/to/PepperFlashPlayer.plugin +// No Linux, /path/to/libpepflashplayer.so +app.commandLine.appendSwitch('ppapi-flash-path', '/path/to/libpepflashplayer.so'); + +// Especifica a versão do flash, por exemplo, v17.0.0.169 +app.commandLine.appendSwitch('ppapi-flash-version', '17.0.0.169'); + +app.on('ready', function() { + mainWindow = new BrowserWindow({ + 'width': 800, + 'height': 600, + 'web-preferences': { + 'plugins': true + } + }); + mainWindow.loadUrl('file://' + __dirname + '/index.html'); + // Algo mais +}); +``` + +## Ative o plugin Flash na tag `` + +Adicione o atributo `plugins` na tag ``. + +```html + +``` From facd0fbc0858a917eb77cd3416e89ec618b67f2f Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 14 Oct 2015 12:41:31 +0800 Subject: [PATCH 197/738] Implement webContents.savePage API. --- atom/browser/api/atom_api_session.cc | 3 + atom/browser/api/atom_api_web_contents.cc | 28 ++++++++ atom/browser/api/atom_api_web_contents.h | 4 ++ atom/browser/api/save_page_handler.cc | 78 +++++++++++++++++++++++ atom/browser/api/save_page_handler.h | 60 +++++++++++++++++ docs/api/web-contents.md | 23 +++++++ filenames.gypi | 2 + spec/api-browser-window-spec.coffee | 12 ++++ 8 files changed, 210 insertions(+) create mode 100644 atom/browser/api/save_page_handler.cc create mode 100644 atom/browser/api/save_page_handler.h diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 7bc1a2153e3f..3c92266be33c 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -11,6 +11,7 @@ #include "atom/browser/api/atom_api_download_item.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/api/atom_api_web_contents.h" +#include "atom/browser/api/save_page_handler.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" @@ -237,6 +238,8 @@ Session::~Session() { void Session::OnDownloadCreated(content::DownloadManager* manager, content::DownloadItem* item) { auto web_contents = item->GetWebContents(); + if (SavePageHandler::IsSavePageTypes(item->GetMimeType())) + return; bool prevent_default = Emit( "will-download", DownloadItem::Create(isolate(), item), diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 0b8a9882cd1b..5b3ef2f4aa7b 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -162,6 +162,26 @@ struct Converter { } }; +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + content::SavePageType* out) { + std::string save_type; + if (!ConvertFromV8(isolate, val, &save_type)) + return false; + if (save_type == "HTMLOnly") { + *out = content::SAVE_PAGE_TYPE_AS_ONLY_HTML; + } else if (save_type == "HTMLComplete") { + *out = content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML; + } else if (save_type == "MHTML") { + *out = content::SAVE_PAGE_TYPE_AS_MHTML; + } else { + return false; + } + return true; + } +}; + } // namespace mate @@ -665,6 +685,13 @@ void WebContents::InsertCSS(const std::string& css) { web_contents()->InsertCSS(css); } +bool WebContents::SavePage(const base::FilePath& full_file_path, + const content::SavePageType& save_type, + const SavePageHandler::SavePageCallback& callback) { + auto handler = new SavePageHandler(web_contents(), callback); + return handler->Handle(full_file_path, save_type); +} + void WebContents::ExecuteJavaScript(const base::string16& code, bool has_user_gesture) { Send(new AtomViewMsg_ExecuteJavaScript(routing_id(), code, has_user_gesture)); @@ -976,6 +1003,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("setUserAgent", &WebContents::SetUserAgent) .SetMethod("getUserAgent", &WebContents::GetUserAgent) .SetMethod("insertCSS", &WebContents::InsertCSS) + .SetMethod("savePage", &WebContents::SavePage) .SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript) .SetMethod("openDevTools", &WebContents::OpenDevTools) .SetMethod("closeDevTools", &WebContents::CloseDevTools) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 01075c450a53..7fa8951106b2 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -9,6 +9,7 @@ #include #include "atom/browser/api/frame_subscriber.h" +#include "atom/browser/api/save_page_handler.h" #include "atom/browser/api/trackable_object.h" #include "atom/browser/common_web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" @@ -73,6 +74,9 @@ class WebContents : public mate::TrackableObject, void SetUserAgent(const std::string& user_agent); std::string GetUserAgent(); void InsertCSS(const std::string& css); + bool SavePage(const base::FilePath& full_file_path, + const content::SavePageType& save_type, + const SavePageHandler::SavePageCallback& callback); void ExecuteJavaScript(const base::string16& code, bool has_user_gesture); void OpenDevTools(mate::Arguments* args); diff --git a/atom/browser/api/save_page_handler.cc b/atom/browser/api/save_page_handler.cc new file mode 100644 index 000000000000..42b93befddf6 --- /dev/null +++ b/atom/browser/api/save_page_handler.cc @@ -0,0 +1,78 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/api/save_page_handler.h" + +#include + +#include "atom/browser/atom_browser_context.h" +#include "base/callback.h" +#include "base/files/file_path.h" +#include "content/public/browser/web_contents.h" + +namespace atom { + +namespace api { + +SavePageHandler::SavePageHandler(content::WebContents* web_contents, + const SavePageCallback& callback) + : web_contents_(web_contents), + callback_(callback) { +} + +SavePageHandler::~SavePageHandler() { +} + +void SavePageHandler::OnDownloadCreated(content::DownloadManager* manager, + content::DownloadItem* item) { + // OnDownloadCreated is invoked during WebContents::SavePage, so the |item| + // here is the one stated by WebContents::SavePage. + item->AddObserver(this); +} + +bool SavePageHandler::Handle(const base::FilePath& full_path, + const content::SavePageType& save_type) { + auto download_manager = content::BrowserContext::GetDownloadManager( + web_contents_->GetBrowserContext()); + download_manager->AddObserver(this); + bool result = web_contents_->SavePage(full_path, + full_path.DirName(), + save_type); + download_manager->RemoveObserver(this); + // If initialization fails which means fail to create |DownloadItem|, we need + // to delete the |SavePageHandler| instance to avoid memory-leak. + if (!result) + delete this; + return result; +} + +void SavePageHandler::OnDownloadUpdated(content::DownloadItem* item) { + if (item->IsDone()) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Locker locker(isolate); + v8::HandleScope handle_scope(isolate); + if (item->GetState() == content::DownloadItem::COMPLETE) { + callback_.Run(v8::Null(isolate)); + } else { + v8::Local error_message = v8::String::NewFromUtf8( + isolate, "Fail to save page"); + callback_.Run(v8::Exception::Error(error_message)); + } + Destroy(item); + } +} + +void SavePageHandler::Destroy(content::DownloadItem* item) { + item->RemoveObserver(this); + delete this; +} + +// static +bool SavePageHandler::IsSavePageTypes(const std::string& type) { + return type == "multipart/related" || type == "text/html"; +} + +} // namespace api + +} // namespace atom diff --git a/atom/browser/api/save_page_handler.h b/atom/browser/api/save_page_handler.h new file mode 100644 index 000000000000..dd1692a8badc --- /dev/null +++ b/atom/browser/api/save_page_handler.h @@ -0,0 +1,60 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_API_SAVE_PAGE_HANDLER_H_ +#define ATOM_BROWSER_API_SAVE_PAGE_HANDLER_H_ + +#include + +#include "content/public/browser/download_item.h" +#include "content/public/browser/download_manager.h" +#include "content/public/browser/save_page_type.h" +#include "v8/include/v8.h" + +namespace base { +class FilePath; +} + +namespace content { +class WebContents; +} + +namespace atom { + +namespace api { + +// A self-destroyed class for handling save page request. +class SavePageHandler : public content::DownloadManager::Observer, + public content::DownloadItem::Observer { + public: + using SavePageCallback = base::Callback)>; + + SavePageHandler(content::WebContents* web_contents, + const SavePageCallback& callback); + ~SavePageHandler(); + + bool Handle(const base::FilePath& full_path, + const content::SavePageType& save_type); + + static bool IsSavePageTypes(const std::string& type); + + private: + void Destroy(content::DownloadItem* item); + + // content::DownloadManager::Observer: + void OnDownloadCreated(content::DownloadManager* manager, + content::DownloadItem* item) override; + + // content::DownloadItem::Observer: + void OnDownloadUpdated(content::DownloadItem* item) override; + + content::WebContents* web_contents_; // weak + SavePageCallback callback_; +}; + +} // namespace api + +} // namespace atom + +#endif // ATOM_BROWSER_API_SAVE_PAGE_HANDLER_H_ diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 08670bad9df7..006d7e3934b9 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -631,3 +631,26 @@ Get the `WebContents` of DevTools for this `WebContents`. **Note:** Users should never store this object because it may become `null` when the DevTools has been closed. + +### `webContents.savePage(fullPath, saveType, callback)` + +* `fullPath` String - The full file path. +* `saveType` String - Specify the save type. + * `HTMLOnly` - Save only the HTML of the page. + * `HTMLComplete` - Save complete-html page. + * `MHTML` - Save complete-html page as MHTML. +* `callback` Function - `function(error) {}`. + * `error` Error + +Returns true if the process of saving page has been initiated successfully. + +```javascript +win.loadUrl('https://github.com'); + +win.webContents.on('did-finish-load', function() { + win.webContents.savePage('/tmp/test.html', 'HTMLComplete', function(error) { + if (!error) + console.log("Save page successfully"); + }); +}); +``` diff --git a/filenames.gypi b/filenames.gypi index 6418ba287214..aadc1a092f6b 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -108,6 +108,8 @@ 'atom/browser/api/trackable_object.h', 'atom/browser/api/frame_subscriber.cc', 'atom/browser/api/frame_subscriber.h', + 'atom/browser/api/save_page_handler.cc', + 'atom/browser/api/save_page_handler.h', 'atom/browser/auto_updater.cc', 'atom/browser/auto_updater.h', 'atom/browser/auto_updater_delegate.h', diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 2e4a66b92b9a..0f9b376784fc 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -301,3 +301,15 @@ describe 'browser-window module', -> assert.notEqual data.length, 0 w.webContents.endFrameSubscription() done() + + describe 'save page', -> + savePagePath = path.join fixtures, 'save_page.html' + it 'should save page', (done) -> + w.webContents.on 'did-finish-load', -> + w.webContents.savePage savePagePath, 'HTMLComplete', (error) -> + assert.equal error, null + assert fs.existsSync savePagePath + fs.unlinkSync savePagePath + done() + + w.loadUrl "file://#{fixtures}/api/blank.html" From aeb24b784d00e55dbc9e3a708f6cb0e6b7cddf00 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Thu, 15 Oct 2015 18:36:02 -0700 Subject: [PATCH 198/738] Allow "released callback" errors to be traced to remote calls --- atom/browser/lib/rpc-server.coffee | 4 +++- atom/common/api/lib/callbacks-registry.coffee | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 149b208b409d..7bbc019b6d72 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -69,7 +69,9 @@ unwrapArgs = (sender, args) -> rendererReleased = true ret = -> - throw new Error('Calling a callback of released renderer view') if rendererReleased + if rendererReleased + throw new Error("Attempting to call a function in a renderer window + that has been closed or released. Function provided here: #{meta.id}.") sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments) v8Util.setDestructor ret, -> return if rendererReleased diff --git a/atom/common/api/lib/callbacks-registry.coffee b/atom/common/api/lib/callbacks-registry.coffee index 8f5eb62916c0..a9e9c7b1228f 100644 --- a/atom/common/api/lib/callbacks-registry.coffee +++ b/atom/common/api/lib/callbacks-registry.coffee @@ -11,6 +11,20 @@ class CallbacksRegistry add: (callback) -> id = Math.random().toString() + + # Capture the location of the function and put it in the ID string, + # so that release errors can be tracked down easily. + regexp = /at (.*)/gi + stackString = (new Error).stack + + while (match = regexp.exec(stackString)) isnt null + [x, location] = match + continue if location.indexOf('(native)') isnt -1 + continue if location.indexOf('atom.asar') isnt -1 + [x, filenameAndLine] = /([^/^\)]*)\)?$/gi.exec(location) + id = "#{filenameAndLine} (#{id})" + break + @callbacks[id] = callback id From fb99e7248441353ab1e4a271102ba269b331c6b8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 16 Oct 2015 14:59:00 +0800 Subject: [PATCH 199/738] Update libchromiumcontent to have mas build --- script/lib/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/lib/config.py b/script/lib/config.py index 30eedc13e968..83468f819946 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -7,8 +7,8 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ - 'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '04523758cda2a96d2454f9056fb1fb9a1c1f95f1' + 'http://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' +LIBCHROMIUMCONTENT_COMMIT = '78e54bc39a04b758ed5167cd980cc4d9951bd629' PLATFORM = { 'cygwin': 'win32', From 7bdbe45c91d8a04558afa03b6c855e0fa825f47f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 16 Oct 2015 15:00:26 +0800 Subject: [PATCH 200/738] subpixel-font-scaling option is removed --- atom/browser/web_contents_preferences.cc | 1 - atom/common/options_switches.cc | 1 - atom/common/options_switches.h | 1 - atom/renderer/atom_renderer_client.cc | 2 -- docs/api/browser-window.md | 1 - 5 files changed, 6 deletions(-) diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 2856598c0bc0..14e32353af65 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -26,7 +26,6 @@ namespace { const char* kWebRuntimeFeatures[] = { switches::kExperimentalFeatures, switches::kExperimentalCanvasFeatures, - switches::kSubpixelFontScaling, switches::kOverlayScrollbars, switches::kOverlayFullscreenVideo, switches::kSharedWorker, diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 46687becf84a..e05768b52303 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -99,7 +99,6 @@ const char kClientCertificate[] = "client-certificate"; // Web runtime features. const char kExperimentalFeatures[] = "experimental-features"; const char kExperimentalCanvasFeatures[] = "experimental-canvas-features"; -const char kSubpixelFontScaling[] = "subpixel-font-scaling"; const char kOverlayScrollbars[] = "overlay-scrollbars"; const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video"; const char kSharedWorker[] = "shared-worker"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 16046d19c822..c568804c4dfb 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -51,7 +51,6 @@ extern const char kClientCertificate[]; extern const char kExperimentalFeatures[]; extern const char kExperimentalCanvasFeatures[]; -extern const char kSubpixelFontScaling[]; extern const char kOverlayScrollbars[]; extern const char kOverlayFullscreenVideo[]; extern const char kSharedWorker[]; diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index eeadabcba737..10dd2541b9cf 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -234,8 +234,6 @@ void AtomRendererClient::EnableWebRuntimeFeatures() { blink::WebRuntimeFeatures::enableExperimentalFeatures(b); if (IsSwitchEnabled(command_line, switches::kExperimentalCanvasFeatures, &b)) blink::WebRuntimeFeatures::enableExperimentalCanvasFeatures(b); - if (IsSwitchEnabled(command_line, switches::kSubpixelFontScaling, &b)) - blink::WebRuntimeFeatures::enableSubpixelFontScaling(b); if (IsSwitchEnabled(command_line, switches::kOverlayScrollbars, &b)) blink::WebRuntimeFeatures::enableOverlayScrollbars(b); if (IsSwitchEnabled(command_line, switches::kOverlayFullscreenVideo, &b)) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 1a2870f205ae..fd25f8cdc982 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -111,7 +111,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `plugins` Boolean - Whether plugins should be enabled. * `experimental-features` Boolean * `experimental-canvas-features` Boolean - * `subpixel-font-scaling` Boolean * `overlay-scrollbars` Boolean * `overlay-fullscreen-video` Boolean * `shared-worker` Boolean From 18fd126c64a8d2afb5c8f7f837aa1cca34e0b070 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 16 Oct 2015 17:15:23 +0800 Subject: [PATCH 201/738] docs: Mac App Store Submission Guide --- docs/README.md | 1 + docs/api/process.md | 4 +- .../mac-app-store-submission-guide.md | 119 ++++++++++++++++++ 3 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 docs/tutorial/mac-app-store-submission-guide.md diff --git a/docs/README.md b/docs/README.md index eb6e9d6e36f0..a0d91a5459ce 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,6 +2,7 @@ * [Supported Platforms](tutorial/supported-platforms.md) * [Application Distribution](tutorial/application-distribution.md) +* [Mac App Store Submission Guide](tutorial/mac-app-store-submission-guide.md) * [Application Packaging](tutorial/application-packaging.md) * [Using Native Node Modules](tutorial/using-native-node-modules.md) * [Debugging Main Process](tutorial/debugging-main-process.md) diff --git a/docs/api/process.md b/docs/api/process.md index a2157886bc61..22fe452b0cad 100644 --- a/docs/api/process.md +++ b/docs/api/process.md @@ -8,6 +8,8 @@ upstream node: * `process.versions['electron']` String - Version of Electron. * `process.versions['chrome']` String - Version of Chromium. * `process.resourcesPath` String - Path to JavaScript source code. +* `process.mas` Boolean - For Mac App Store build, this value is `true`, for + other builds it is `undefined`. ## Events @@ -37,7 +39,7 @@ The `process` object has the following method: Causes the main thread of the current process hang. -### process.setFdLimit(maxDescriptors) _OS X_ _Linux_ +### `process.setFdLimit(maxDescriptors)` _OS X_ _Linux_ * `maxDescriptors` Integer diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md new file mode 100644 index 000000000000..696a7d9321ae --- /dev/null +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -0,0 +1,119 @@ +# Mac App Store Submission Guide + +Since v0.34.0, Electron allows submitting packaged apps to Mac App Store (MAS), +this guide provides information on how to submit your app, and the limitations +of the MAS build. + +## How to submit your app + +Following steps introduces a simple way submit your app to Mac App Store, but +it doesn't make sure your app gets approved by Apple, you still have to read +apple's [Submitting Your App][submitting-your-app] guide on how to meet Mac +App Store's requirements. + +### Get certificate + +To submit your app to Mac App Store, you have to get a certificate from Apple +first, you can follow existing guides on web: + +* "First steps" of [Mac App Store (MAS) Submission Guideline][nwjs-guide] +* "Step 2" of [Distributing an app on Mac OS X without Xcode][dist-no-xcode] + +### Sign your app + +After getting the certificate, you can package your app by following +[Application Distribution](application-distribution.md), and then sign your app. +The step is basically the same with other programs, the key is to sign every +dependency of Electron one by one. + +First you need to prepare two entitlements files. + +`child.plist`: + +```xml + + + + + com.apple.security.app-sandbox + + com.apple.security.inherit + + + +``` + +`parent.plist`: + +```xml + + + + + com.apple.security.app-sandbox + + + +``` + +And then sign your app with following script: + +```bash +#!/bin/bash + +# Name of your app. +APP="YourApp" +# The path of you app to sign. +APP_PATH="/path/to/YouApp.app" +# The path to the location you want to put the signed package. +RESULT_PATH="~/Desktop/$APP.pkg" +# The name of certificates you requested. +APP_KEY="3rd Party Mac Developer Application: Company Name (APPIDENTITY)" +INSTALLER_KEY="3rd Party Mac Developer Installer: Company Name (APPIDENTITY)" + +FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks" + +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Framework.framework/Libraries/libnode.dylib" +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Framework.framework/$APP Framework" +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Framework.framework/" +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper.app/" +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper EH.app/" +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper NP.app/" +codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" +productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$APP_PATH" +``` + +If you are new to app sandboxing of OS X, you should also go through Apple's +[Enabling App Sandbox][enable-app-sandbox] to have a basic idea, and add keys +for the permissions needed by your app to the entitlements files. + +### Upload your app and submit for review + +After signing your app you can use Application Loader to upload it to iTunes +Connect for processing, make sure you have [created a record][create-record] +before uploading. Then you can [submit your app for review][submit-for-review]. + +## Limitations of MAS build + +In order to satisfy requirements for app sandboxing, following modules have been +disabled in MAS build: + +* `crash-reporter` +* `auto-updater` + +and following behaviors have been changed: + +* Video capture may not work for some machines. +* Certain accessibility features may not work. +* Apps will not be aware of DNS changes. + +Also due to the usage of app sandboxing, the resources can be accessed by the +app is strictly limited, you can read [App Sandboxing][app-sandboxing] for more. + +[submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html +[nwjs-guide]: https://github.com/nwjs/nw.js/wiki/Mac-App-Store-%28MAS%29-Submission-Guideline#first-steps +[dist-no-xcode]: https://devreboot.wordpress.com/2014/07/04/distributing-an-app-on-mac-os-x-without-xcode-outside-the-mac-app-store/ +[enable-app-sandbox]: https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html +[create-record]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/CreatingiTunesConnectRecord.html +[submit-for-review]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/SubmittingTheApp.html +[app-sandboxing]: https://developer.apple.com/app-sandboxing/ From 16b9f8995df5fe0097bca3eea31aae2e2b3749a4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 16 Oct 2015 17:38:11 +0800 Subject: [PATCH 202/738] Revert "Go back to using node's console.* and std*.write" This reverts commit 4e8db2c3be8f3c9a172fb87ad8739493ab3dfbb1. It seems that we still have problems with Node.js's console.* calls, I'm reverting this for now unitl we get a solution. Fixes #3100. --- atom/browser/lib/init.coffee | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index 67630a1bd6fa..9f92d700c73a 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -18,6 +18,25 @@ require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') globalPaths = Module.globalPaths globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') +if process.platform is 'win32' + # Redirect node's console to use our own implementations, since node can not + # handle console output when running as GUI program. + consoleLog = (args...) -> + process.log util.format(args...) + "\n" + streamWrite = (chunk, encoding, callback) -> + chunk = chunk.toString(encoding) if Buffer.isBuffer chunk + process.log chunk + callback() if callback + true + console.log = console.error = console.warn = consoleLog + process.stdout.write = process.stderr.write = streamWrite + + # Always returns EOF for stdin stream. + Readable = require('stream').Readable + stdin = new Readable + stdin.push null + process.__defineGetter__ 'stdin', -> stdin + # Don't quit on fatal error. process.on 'uncaughtException', (error) -> # Do nothing if the user has a custom uncaught exception handler. From 776077c8de551053ddf9a6d6de810796721b7eed Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 16 Oct 2015 17:42:55 +0800 Subject: [PATCH 203/738] Bump v0.33.9 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/atom.gyp b/atom.gyp index c768289f744b..03d71d18ab0b 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.8', + 'version%': '0.33.9', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index f4725715526b..7979a38bcb87 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.8 + 0.33.9 CFBundleShortVersionString - 0.33.8 + 0.33.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 08af14987eee..c981414b102d 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,33,8,0 - PRODUCTVERSION 0,33,8,0 + FILEVERSION 0,33,9,0 + PRODUCTVERSION 0,33,9,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.8" + VALUE "FileVersion", "0.33.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.33.8" + VALUE "ProductVersion", "0.33.9" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 205d512b2b52..3d87c4f46d50 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 33 -#define ATOM_PATCH_VERSION 8 +#define ATOM_PATCH_VERSION 9 #define ATOM_VERSION_IS_RELEASE 1 From 22e9c2f4ebbf3f4990afd27cea650cc652e0d1b8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 16 Oct 2015 18:53:25 +0800 Subject: [PATCH 204/738] Bump v0.34.0 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/atom.gyp b/atom.gyp index 03d71d18ab0b..d6d9e2e2268e 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.9', + 'version%': '0.34.0', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 7979a38bcb87..01c4bc7e6281 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.9 + 0.34.0 CFBundleShortVersionString - 0.33.9 + 0.34.0 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index c981414b102d..5a25256831cc 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,33,9,0 - PRODUCTVERSION 0,33,9,0 + FILEVERSION 0,34,0,0 + PRODUCTVERSION 0,34,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.9" + VALUE "FileVersion", "0.34.0" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.33.9" + VALUE "ProductVersion", "0.34.0" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 3d87c4f46d50..8351fff18ca2 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -6,8 +6,8 @@ #define ATOM_VERSION_H #define ATOM_MAJOR_VERSION 0 -#define ATOM_MINOR_VERSION 33 -#define ATOM_PATCH_VERSION 9 +#define ATOM_MINOR_VERSION 34 +#define ATOM_PATCH_VERSION 0 #define ATOM_VERSION_IS_RELEASE 1 From 5e5caf2e8649ea87ad27a91ce7ac23be976d5346 Mon Sep 17 00:00:00 2001 From: Lucas Pugliesi Date: Fri, 16 Oct 2015 09:09:24 -0300 Subject: [PATCH 205/738] Translation of debugging-main-process to pt-br. --- .../pt-BR/tutorial/debugging-main-process.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 docs-translations/pt-BR/tutorial/debugging-main-process.md diff --git a/docs-translations/pt-BR/tutorial/debugging-main-process.md b/docs-translations/pt-BR/tutorial/debugging-main-process.md new file mode 100644 index 000000000000..ee79a523e928 --- /dev/null +++ b/docs-translations/pt-BR/tutorial/debugging-main-process.md @@ -0,0 +1,53 @@ +# Depurando o Processo Principal + +A janela do navegador, DevTools, pode somente depurar o processo de renderização +de scripts (por exemplo, as páginas da web). Para providenciar um modo de +depurar os scripts através do processo principal, o Electron criou as opções +`--debug` e `--debug-brk`. + +## Opções da Linha de Comando + +Use a seguinte opção na linha de comando para depurar o processo principal do +Electron: + +### `--debug=[porta]` + +Quando este comando é usado, o Electron irá executar o protocolo de depuração +V8 mandando as mensagens na `porta`. A `porta` padrão é `5858`. + +### `--debug-brk=[porta]` + +Semelhante ao `--debug`, porém pausa o script na primeira linha. + +## Usando node-inspector para depurar + +__Nota:__ O Electron usa a versão v0.11.13 do Node, a qual, atualmenta não +funciona muito bem com node-inspector, e o processo principal irá quebrar se +você inspecionar o objeto `process` pelo console do node-inspector. + +### 1. Inicie o servidor [node-inspector][node-inspector] + +```bash +$ node-inspector +``` + +### 2. Habilite o modo de depuração para o Electron + +Você pode também iniciar o Electron com um ponto de depuração, desta maneira: + +```bash +$ electron --debug=5858 sua/aplicacao +``` + +ou para pausar o script na primeira linha: + +```bash +$ electron --debug-brk=5858 sua/aplicacao +``` + +### 3. Carregue o debugger UI + +Abra este endereço http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858 +usando o Chrome. + +[node-inspector]: https://github.com/node-inspector/node-inspector From 2725068a0c52c8ad2fbaecc6ab1d1044d73101fe Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 16 Oct 2015 09:11:30 -0300 Subject: [PATCH 206/738] Updating README.md --- docs-translations/pt-BR/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/pt-BR/README.md b/docs-translations/pt-BR/README.md index 3db45bb7e2af..db88edaf77eb 100644 --- a/docs-translations/pt-BR/README.md +++ b/docs-translations/pt-BR/README.md @@ -3,7 +3,7 @@ * [Distribuição de Aplicações](tutorial/application-distribution.md) * [Empacotamento da aplicação](tutorial/application-packaging.md) * [Usando módulos nativos](tutorial/using-native-node-modules.md) -* [Depuração do processo principal](../../docs/tutorial/debugging-main-process.md) +* [Depuração do processo principal](tutorial/debugging-main-process.md) * [Usando Selenium e WebDriver](../../docs/tutorial/using-selenium-and-webdriver.md) * [Extensão DevTools](../../docs/tutorial/devtools-extension.md) * [Usando o plugin papper flash](tutorial/using-pepper-flash-plugin.md) From 115bb31ab468faa2958b9c7888ebdbeec6d1a651 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 16 Oct 2015 20:21:06 +0800 Subject: [PATCH 207/738] docs: Small fix on mas guide --- docs/tutorial/mac-app-store-submission-guide.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md index 696a7d9321ae..ccd0ead8584e 100644 --- a/docs/tutorial/mac-app-store-submission-guide.md +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -6,7 +6,7 @@ of the MAS build. ## How to submit your app -Following steps introduces a simple way submit your app to Mac App Store, but +Following steps introduces a simple way to submit your app to Mac App Store, but it doesn't make sure your app gets approved by Apple, you still have to read apple's [Submitting Your App][submitting-your-app] guide on how to meet Mac App Store's requirements. @@ -14,10 +14,7 @@ App Store's requirements. ### Get certificate To submit your app to Mac App Store, you have to get a certificate from Apple -first, you can follow existing guides on web: - -* "First steps" of [Mac App Store (MAS) Submission Guideline][nwjs-guide] -* "Step 2" of [Distributing an app on Mac OS X without Xcode][dist-no-xcode] +first, you can follow [existing guides][nwjs-guide] on web. ### Sign your app @@ -73,9 +70,9 @@ INSTALLER_KEY="3rd Party Mac Developer Installer: Company Name (APPIDENTITY)" FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks" -codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Framework.framework/Libraries/libnode.dylib" -codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Framework.framework/$APP Framework" -codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Framework.framework/" +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Libraries/libnode.dylib" +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Electron Framework" +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/" codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper.app/" codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper EH.app/" codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper NP.app/" @@ -112,7 +109,6 @@ app is strictly limited, you can read [App Sandboxing][app-sandboxing] for more. [submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html [nwjs-guide]: https://github.com/nwjs/nw.js/wiki/Mac-App-Store-%28MAS%29-Submission-Guideline#first-steps -[dist-no-xcode]: https://devreboot.wordpress.com/2014/07/04/distributing-an-app-on-mac-os-x-without-xcode-outside-the-mac-app-store/ [enable-app-sandbox]: https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html [create-record]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/CreatingiTunesConnectRecord.html [submit-for-review]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/SubmittingTheApp.html From 94f64c755d894b2248f8b6e376640d29be83baa1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 16 Oct 2015 19:58:20 +0800 Subject: [PATCH 208/738] spec: Load url after event listener is set up --- spec/asar-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/asar-spec.coffee b/spec/asar-spec.coffee index 1e6ee6910369..75f0cec63adb 100644 --- a/spec/asar-spec.coffee +++ b/spec/asar-spec.coffee @@ -450,10 +450,10 @@ describe 'asar package', -> w = new BrowserWindow(show: false, width: 400, height: 400) p = path.resolve fixtures, 'asar', 'web.asar', 'index.html' u = url.format protocol: 'file', slashed: true, pathname: p - w.loadUrl u ipc.once 'dirname', (event, dirname) -> assert.equal dirname, path.dirname(p) done() + w.loadUrl u it 'loads script tag in html', (done) -> after -> From d9fdfb711f445b161b08038a7041d1bc47c595be Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 16 Oct 2015 20:25:30 +0800 Subject: [PATCH 209/738] Clean up CallbackRegistry There were some ancient code there. --- atom/browser/lib/rpc-server.coffee | 2 +- atom/common/api/lib/callbacks-registry.coffee | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 7bbc019b6d72..a1e159a16a7f 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -71,7 +71,7 @@ unwrapArgs = (sender, args) -> ret = -> if rendererReleased throw new Error("Attempting to call a function in a renderer window - that has been closed or released. Function provided here: #{meta.id}.") + that has been closed or released. Function provided here: #{meta.id}.") sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments) v8Util.setDestructor ret, -> return if rendererReleased diff --git a/atom/common/api/lib/callbacks-registry.coffee b/atom/common/api/lib/callbacks-registry.coffee index a9e9c7b1228f..d4c37f087b1e 100644 --- a/atom/common/api/lib/callbacks-registry.coffee +++ b/atom/common/api/lib/callbacks-registry.coffee @@ -1,16 +1,11 @@ -savedGlobal = global # the "global.global" might be deleted later - module.exports = class CallbacksRegistry constructor: -> - @emptyFunc = -> throw new Error "Browser trying to call a non-exist callback - in renderer, this usually happens when renderer code forgot to release - a callback installed on objects in browser when renderer was going to be - unloaded or released." + @nextId = 0 @callbacks = {} add: (callback) -> - id = Math.random().toString() + id = ++@nextId # Capture the location of the function and put it in the ID string, # so that release errors can be tracked down easily. @@ -32,10 +27,10 @@ class CallbacksRegistry @callbacks[id] ? -> call: (id, args...) -> - @get(id).call savedGlobal, args... + @get(id).call global, args... apply: (id, args...) -> - @get(id).apply savedGlobal, args... + @get(id).apply global, args... remove: (id) -> delete @callbacks[id] From f05fc3c0ea5f12a0eb764f17f32443de74aa5e5d Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 16 Oct 2015 22:23:31 +0900 Subject: [PATCH 210/738] Improve grammar, some fixes * Improve grammar * Fix typos * Fix some mistranslations * Fix quotes (' to `) --- docs-translations/ko-KR/api/app.md | 248 ++++++++++++++--------------- 1 file changed, 121 insertions(+), 127 deletions(-) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index 2fa04368ec36..18354a70bd7a 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -1,8 +1,8 @@ # app -앱 모듈은 어플리케이션의 생명주기(?) 제어를 책임집니다. +`app` 모듈은 어플리케이션의 생명주기 제어를 책임집니다. -밑의 예제는 마지막 윈도우가 종료되었을 때, 어떻게 어플리케이션을 종료하는지 설명합니다. +밑의 예제는 마지막 윈도우창가 종료되었을 때, 어플리케이션을 종료시키는 예제입니다: ```javascript var app = require('app'); @@ -13,30 +13,32 @@ app.on('window-all-closed', function() { ## Events -앱 객체는 밑의 이벤트들을 발현(?)시킵니다. +`app` 객체는 다음과 같은 이벤트를 가지고 있습니다: ### Event: 'will-finish-launching' -'will-finish-launching' 이벤트는 어플리케이션이 기본적인 시동준비(?)를 마치면 발현(?)됩니다. - 윈도우 운영체제와 리눅스 운영체제 안에서, 'will-finish-launching' 이벤트는 'ready' 이벤트와 동일합니다. -OS X 운영체제 안에서는, 이 이벤트는 'NSApplication'의 'applicationWillFinishLaunching' 알림으로 표현됩니다. -유저는 대개 'open-file'과 'open-url' 이벤트를 위한 listeners을 세팅합니다. -그리고, crash reporter와 auto updater를 시작합니다. +어플리케이션이 기본적인 시작 준비를 마치면 발생하는 이벤트입니다. +Windows, Linux 운영체제에서의 `will-finish-launching` 이벤트는 `ready` 이벤트와 동일합니다. +OS X에서의 이벤트는 `NSApplication`의 `applicationWillFinishLaunching`에 대한 알림으로 표현됩니다. +대개 이곳에서 `open-file`과 `open-url` 이벤트 리스너를 설정하고 crash reporter와 auto updater를 시작합니다. -대부분의 경우, 유저는 모든 것을 'ready' 이벤트 handler로 해결합니다. +대부분의 경우, 모든 것을 `ready` 이벤트 핸들러로 해결해야 합니다. ### Event: 'ready' -Electron이 초기화를 끝냈을 때, 이벤트가 발현합니다. +Electron이 초기화를 끝냈을 때 발생하는 이벤트입니다. ### Event: 'window-all-closed' -모든 윈도우창이 종료되었을 때, 이벤트가 발현합니다. +모든 윈도우창이 종료되었을 때 발생하는 이벤트입니다. -이 이벤트는 어플리케이션이 정상 종료되지 않았을 때만 발현됩니다. -만약 유저가 'Cmd + Q' 또는 개발자가 'app.quit()'를 호출했다면, Electron은 먼저 모든 윈도우창 종료를 시도합니다. -그 다음에, 'will-quit' 이벤트를 발현시킵니다. -그리고, 'will-quit'가 발현된 경우에는 'window-all-closed' 이벤트는 발현되지 않습니다. +이 이벤트는 어플리케이션이 완전히 종료되지 않았을 때만 발생합니다. +만약 사용자가 `Cmd + Q`를 입력했거나 개발자가 `app.quit()`를 호출했다면, +Electron은 먼저 모든 윈도우창의 종료를 시도하고 `will-quit` 이벤트를 발생시킵니다. +그리고 `will-quit` 이벤트가 발생했을 땐 `window-all-closed` 이벤트가 발생하지 않습니다. + +**역주:** 이 이벤트는 말 그대로 현재 어플리케이션에서 윈도우창만 완전히 종료됬을 때 발생하는 이벤트 입니다. + 따라서 어플리케이션을 완전히 종료하려면 이 이벤트에서 `app.quit()`를 호출해 주어야 합니다. ### Event: 'before-quit' @@ -44,8 +46,9 @@ Returns: * `event` Event -어플리케이션이 어플리케이션의 윈도우 종료를 시작하기 전에, 발현됩니다. -'event.preventDefault()' 호출은 어플리케이션의 강제종료 행위를 방지합니다. +어플리케이션 윈도우창들이 닫히기 시작할 때 발생하는 이벤트입니다. +`event.preventDefault()` 호출은 이벤트의 기본 동작을 방지하기 때문에 +이를 통해 어플리케이션의 종료를 방지할 수 있습니다. ### Event: 'will-quit' @@ -53,14 +56,14 @@ Returns: * `event` Event -모든 윈도우창이 종료되고 어플리케이션이 종료하고자 할 때, 이벤트가 발현됩니다. -'event.preventDefault()'의 호출은 어플리케이션 종료를 방지합니다. -'will-quit' 이벤트와 'window-all-closed' 이벤트와의 차이점을 확인하려면, -'window-all-close' 이벤트의 설명을 참조합시다. +모든 윈도우창들이 종료되고 어플리케이션이 종료되기 시작할 때 발생하는 이벤트 입니다. +`event.preventDefault()` 호출을 통해 어플리케이션의 종료를 방지할 수 있습니다. + +`will-quit` 와 `window-all-closed` 이벤트의 차이점을 확인하려면 `window-all-close` 이벤트의 설명을 참고하세요. ### Event: 'quit' -어플리케이션이 종료될 때, 발현됩니다. +어플리케이션이 종료될 때 발생하는 이벤트입니다. ### Event: 'open-file' @@ -69,15 +72,13 @@ Returns: * `event` Event * `path` String -어플리케이션을 이용하여 파일을 열고자 할 때, 발현됩니다. +사용자가 어플리케이션을 통해 파일을 열고자 할 때 발생하는 이벤트입니다. -'open-file' 이벤트는 보통 어플리케이션이 열려 있을 때와, -파일을 열기 위해 OS가 어플리케이션을 재사용할 때 발현됩니다. -'open-file'은 파일이 dock에 추가될 때와 어플리케이션이 실행하기 전에도 발현됩니다. -위의 케이스를 처리하기 위해서는, 'ready' 이벤트가 발현되기도 전에, 어플리케이션 시작 초기 시 -'open-file' 이벤트에 linsten을 걸어 놨는지 반드시 확인해야 합니다. +`open-file` 이벤트는 보통 어플리케이션이 열려 있을 때와 OS가 파일을 열기 위해 어플리케이션을 재사용할 때 발생합니다. +`open-file` 이벤트는 파일을 dock에 떨어트릴 때와 어플리케이션이 실행되기 전에도 발생합니다. +이 경우엔 확실히 `open-file` 이벤트 리스너를 어플리케이션이 시작하기 전에 설정해 놓았는지 확인해야 합니다. (`ready` 이벤트가 발생하기 전에) -이 이벤트를 처리하기 위한다면, 유저는 'even.preventDefault()'를 호출해야 합니다. +이 이벤트를 처리하려면 반드시 `event.preventDefault()`를 호출해야 합니다. ### Event: 'open-url' @@ -86,9 +87,11 @@ Returns: * `event` Event * `url` String -유저가 어플리케이션을 이용하여 URL을 열고자 할 경우, 발현됩니다. -어플리케이션을 통해 열기 위해서는 URL 구조가 반드시 등록되어 있어야 합니다. -이 이벤트를 처리하기 위해선, 유저가 'event.preventDefault()'을 호출해야 합니다. +유저가 어플리케이션을 통해 URL을 열고자 할 때 발생하는 이벤트입니다. + +어플리케이션에서 URL을 열기 위해선 반드시 URL 스킴이 등록되어 있어야 합니다. + +이 이벤트를 처리하려면 반드시 `event.preventDefault()`를 호출해야 합니다. ### Event: 'activate' _OS X_ @@ -97,8 +100,8 @@ Returns: * `event` Event * `hasVisibleWindows` Bool -어플리케이션이 활성화 되었을 때 발현됩니다. -(어플리케이션은 dock 아이콘을 click했을 때 주로 활성화됩니다.) +어플리케이션이 활성화 되었을 때 발생하는 이벤트 입니다. +이 이벤트는 어플리케이션의 dock 아이콘을 클릭했을 때 주로 발생합니다. ### Event: 'browser-window-blur' @@ -107,7 +110,7 @@ Returns: * `event` Event * `window` BrowserWindow -[browserWindow](browser-window.md)가 흐려졌을 때, 호출됩니다. +[browserWindow](browser-window.md)에 대한 포커스가 사라졌을 때 발생하는 이벤트 입니다. ### Event: 'browser-window-focus' @@ -116,8 +119,9 @@ Returns: * `event` Event * `window` BrowserWindow -[browserWindow](browser-window.md)을 포커싱했을 때, 호출됩니다. -(포커싱이란? 클릭 또는 활성화했을 때를 의미) +[browserWindow](browser-window.md)에 대한 포커스가 발생했을 때 발생하는 이벤트 입니다. + +**역주:** _포커스_는 창을 클릭해서 활성화 시켰을 때를 말합니다. ### Event: 'browser-window-created' @@ -126,11 +130,11 @@ Returns: * `event` Event * `window` BrowserWindow -새로운 [browserWindow](browser-window.md)가 생성될 때 발현됩니다. +새로운 [browserWindow](browser-window.md)가 생성되었을 때 발생하는 이벤트 입니다. ### Event: 'select-certificate' -유저인증이 요청되었을 때 발현됩니다. +사용자 인증이 요청되었을 때 발생하는 이벤트 입니다. Returns: @@ -138,8 +142,8 @@ Returns: * `webContents` [WebContents](browser-window.md#class-webcontents) * `url` String * `certificateList` [Objects] - * `data` PEM encoded data - * `issuerName` Issuer's Common Name + * `data` PEM으로 인코딩된 데이터 + * `issuerName` 발급자의 공통 이름 * `callback` Function ```javascript @@ -149,180 +153,170 @@ app.on('select-certificate', function(event, host, url, list, callback) { }) ``` -'url' 유저인증 요청의 탐색 항목에 대응합니다. -그리고, 'callback' 는 리스트로 필터링된 항목과 함께 호출될 필요가 있습니다. +`url`에 대한 -'event.preventDefault()' 호출은 기록소로부터 처음인증된 정보를 사용하는 -어플리케이션을 막습니다. +`url`은 클라이언트 인증서를 요청하는 탐색 항목에 해당합니다. +그리고 `callback`은 목록에서 필터링된 항목과 함께 호출될 필요가 있습니다. + +이 이벤트에서의 `event.preventDefault()` 호출은 초기 인증에 사용한 저장된 데이터를 사용하는 것을 막습니다. ### Event: 'gpu-process-crashed' -GPU가 충돌을 일으켰을 때, 발현됩니다. +GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입니다. ## Methods -'app' 객체는 밑의 함수를 포함하고 있습니다: +`app` 객체는 다음과 같은 메서드를 가지고 있습니다: -**Note:** 어떤 함수들은 표시된 특정한 운영체제에서만 사용가능합니다. +**참고:** 몇몇 메서드는 특정 플랫폼에서만 작동합니다. ### `app.quit()` -모든 윈도우창 종료를 시도합니다. 'before-quit' 이벤트가 먼저 발현됩니다. -모든 윈도우창이 성공적으로 종료되었다면, 'will-quit' 이벤트가 발현하고, -디폴트설정으로 어플리케이션이 종료됩니다. - -이 함수는 모든 'beforeunload'과 'unload' 이벤트 처리기가 제대로 실행되었음을 보장합니다. -(즉, 'beforeunload'와 'unload'가 정상 실행되었을 때, 실행가능합니다.) - -'beforeunload' 이벤트 처리기가 'false'를 반환하였을 경우, 윈도우 창 종료가 취소 될 수 있습니다. +모든 윈도우창 종료를 시도합니다. `before-quit` 이벤트가 먼저 발생합니다. +모든 윈도우창이 성공적으로 종료되면 `will-quit` 이벤트가 발생하고 기본 동작에 따라 어플리케이션이 종료됩니다. +이 함수는 모든 `beforeunload`와 `unload` 이벤트 핸들러가 제대로 실행됨을 보장합니다. +`beforeunload` 이벤트 핸들러에서 `false`를 반환했을 때 윈도우창 종료가 취소 될 수 있습니다. ### `app.getAppPath()` -현재 어플리케이션의 디렉토리를 반환합니다. +현재 어플리케이션의 디렉터리를 반환합니다. ### `app.getPath(name)` * `name` String -특정한 디렉토리의 경로나 'name' 파일의 경로를 찾아 반환합니다. -실패할 경우, 'Error'를 반환합니다. +`name`에 관련한 특정 디렉터리 또는 파일의 경로를 반환합니다. +경로를 가져오는 데 실패할 경우 `Error`를 반환합니다. -유저는 다음과 같은 이름으로 경로를 요쳥할 수 있습니다: +**역주:** 이 메서드는 운영체제에서 지정한 특수 디렉터리를 가져오는데 사용할 수 있습니다. -* `home` = 유저의 홈 디렉토리. -* `appData` = 유저의 어플리케이션 데이터 디렉토리, 디폴트설정으로: - * `%APPDATA%` = on Windows - * `$XDG_CONFIG_HOME` 또는 `~/.config` = on Linux - * `~/Library/Application Support` = on OS X -* `userData` = 유저 app의 설정파일을 저장하는 디렉토리, -디폴트설정으로 'appData' 디렉토리에 유저 app의 이름을 추가한 형식. -* `temp` = 임시 디렉토리. -* `userDesktop` = 현재 로그인한 유저의 데스트탑 디렉토리. -* `exe` = 현재 실행가능한 파일. -* `module` = `libchromiumcontent` 라이브러리. +`name`은 다음 목록에 있는 경로 중 하나를 선택해 사용할 수 있습니다: + +* `home` - 사용자의 홈 디렉터리. +* `appData` - 각 사용자의 어플리케이션 데이터 디렉터리. 기본 경로는 다음과 같습니다: + * `%APPDATA%` - Windows + * `$XDG_CONFIG_HOME` 또는 `~/.config` - Linux + * `~/Library/Application Support` - OS X +* `userData` - 어플리케이션의 설정을 저장하는 디렉터리. + 이 디렉터리는 기본적으로 `appData`에 어플리케이션 이름으로 생성된 폴더가 지정됩니다. +* `temp` - 임시 폴더 디렉터리. +* `userDesktop` - 현재 사용자의 데스트탑 디렉터리. +* `exe` - 현재 실행중인 Electron 바이너리 파일. +* `module` - `libchromiumcontent` 라이브러리. ### `app.setPath(name, path)` * `name` String * `path` String -특정한 디렉토리나 파일이름이 'name'인 'path'를 재정의합니다. -만약 지정된 디렉토리의 경로가 존재하지 않는다면, 디렉토리가 새로 생성됩니다. -실패시, 'Error'를 반환합니다. +`name`에 대한 특정 디렉터리나 파일의 경로인 `path`를 재정의합니다. +만약 지정한 디렉터리의 경로가 존재하지 않으면 디렉터리가 이 메서드를 통해 새로 생성됩니다. +재정의에 실패했을 땐 `Error`를 반환합니다. -유저는 'app.getPath'에 정의되어 있는 'name' 경로만 재정의할 수 있습니다. +이 메서드는 `app.getPath`에 정의되어 있는 `name`의 경로만 재정의할 수 있습니다. -디폴트설정으로, 웹페이지의 쿠키와 캐시는 'userData' 디렉토리 밑에 저장됩니다. - -만약 유저가 이 위치를 변경하고자 한다면, 'app' 모듈의 'ready' 이벤트가 발현되기 전, -유저는 반드시 'userData' 경로를 재정의해야 합니다. +기본적으로, 웹 페이지의 쿠키와 캐시는 `userData` 디렉터리에 저장됩니다. +만약 이 위치를 변경하고자 한다면, 반드시 `app` 모듈의 `ready` 이벤트가 발생하기 전에 `userData` 경로를 재정의해야 합니다. ### `app.getVersion()` 로드된 어플리케이션의 버전을 반환합니다. -만약 'package.json' 파일에서 어플리케이션의 버전을 찾지 못한다면, -현재 번들 또는 실행 파일의 버전이 반환됩니다. +만약 `package.json` 파일에서 어플리케이션의 버전을 찾을 수 없는 경우, 현재 번들 또는 실행 파일의 버전을 반환합니다. ### `app.getName()` -응용프로그램(=어플리케이션)의 'package.json' 파일에 있는 -현재 응용프로그램의 이름을 반환합니다. +`package.json`에서 기술된 현재 어플리케이션의 이름을 반환합니다. -NPM 모듈 스펙에 따라, 대부분 'package.json'의 'name' 필드는 소문자 이름입니다. -유저는 'productName'의 필드를 지정해야 합니다. -'productName'는 응용프로그램의 대문자 이름입니다. -'productName'는 Electron에서 선호하는 'name' 입니다. +npm 모듈 규칙에 따라 대부분의 경우 `package.json`의 `name` 필드는 소문자 이름을 사용합니다. +하지만 Electron은 `name`대신 `productName` 필드를 주로 사용하기 때문에 반드시 이 필드도 같이 지정해야 합니다. +이 필드는 맨 앞글자가 대문자인 어플리케이션 전체 이름을 지정해야 합니다. ### `app.getLocale()` -현재 응용프로그램의 locale을 반환합니다. +현재 어플리케이션의 [로케일](https://ko.wikipedia.org/wiki/%EB%A1%9C%EC%BC%80%EC%9D%BC)을 반환합니다. ### `app.resolveProxy(url, callback)` * `url` URL * `callback` Function -'url'을 위해 프록시 정보를 해석합니다. -'callback'은 'callback(proxy)' 요청이 수행될 때, -호출됩니다. +`url`의 프록시 정보를 해석합니다. +`callback`은 요청이 수행되었을 때 `callback(proxy)` 형태로 호출됩니다. ### `app.addRecentDocument(path)` * `path` String -최근 문서 목록에 'path'를 추가합니다. +최근 문서 목록에 `path`를 추가합니다. -목록은 운영체제에 의해 관리됩니다. -Windows 운영체제에서는, 작업표시줄에서 참조할 수 있습니다. -OS X 운영체제에서는, dock 메뉴에서 참조할 수 있습니다. +이 목록은 OS에 의해 관리됩니다. +최근 문서 목록은 Windows의 경우 작업 표시줄에서 찾을 수 있고, OS X의 경우 dock 메뉴에서 찾을 수 있습니다. ### `app.clearRecentDocuments()` -최근 문서 목록을 모두 지웁니다. +최근 문서 목록을 모두 비웁니다. ### `app.setUserTasks(tasks)` _Windows_ -* `tasks` Array - 'Task' 객체의 배열 +* `tasks` Array - `Task` 객체의 배열 -Windows 운영체제에서 JumpList의 [Tasks][tasks] 카테고리로 'tasks'를 추가합니다. +Windows에서 사용할 수 있는 JumpList의 [Tasks][tasks] 카테고리에 `task`를 추가합니다. -'tasks'는 밑의 형식을 따르는 'Task' 객체의 배열입니다: +`tasks`는 다음과 같은 구조를 가지는 `Task` 객체의 배열입니다: `Task` Object -* `program` String - 프로그램을 실행할 경로, 대부분 유저는 현재 프로그램을 여는 'process.execPath'를 지정합니다. -* `arguments` String - 'program'이 실행될 때의 명령문 인자. -* `title` String - JumpList에 표시할 문장. -* `description` String - 이 task 객체에 대한 설명. -* `iconPath` String - 아이콘을 포함한 임의의 리소스 파일이며, JumpList에 표시될 아이콘의 절대 경로. -유저는 대부분 프로그램의 아이콘을 표시하기 위해 'process.execPath'를 지정합니다. -* `iconIndex` Integer - 아이콘 파일안의 아이콘 색인(index). 만약, 아이콘 파일 안에 두 개 이상의 아이콘이 있을 경우, - 아이콘을 특정하기 위해 이 값을 설정합니다. 단, 하나의 아이콘만 있을 경우는 0 값을 가집니다. - +* `program` String - 실행할 프로그램의 경로. + 보통 현재 작동중인 어플리케이션의 경로인 `process.execPath`를 지정합니다. +* `arguments` String - `program`이 실행될 때 사용될 명령줄 인자. +* `title` String - JumpList에 표시할 문자열. +* `description` String - 이 작업에 대한 설명. +* `iconPath` String - JumpList에 표시될 아이콘의 절대 경로. + 아이콘을 포함하고 있는 임의의 리소스 파일을 사용할 수 있습니다. + 보통 어플리케이션의 아이콘을 그대로 사용하기 위해 `process.execPath`를 지정합니다. +* `iconIndex` Integer - 아이콘 파일의 인덱스. 만약 아이콘 파일이 두 개 이상의 아이콘을 가지고 있을 경우, + 사용할 아이콘의 인덱스를 이 옵션으로 지정해 주어야 합니다. 단, 아이콘을 하나만 포함하고 있는 경우 0을 지정하면 됩니다. + ### `app.commandLine.appendSwitch(switch[, value])` -Append a switch (with optional `value`) to Chromium's command line. -Chromium의 명령문에 (선택적으로, 'value'와 함께) switch를 추가합니다. +Chrominum의 명령줄에 스위치를 추가합니다. `value`는 추가적인 값을 뜻하며 옵션입니다. -**Note:** 이 함수는 'process.argv'에 영향을 주지 않습니다. -그리고, 보통 이 함수는 개발자들이 하드웨어 수준의 Chrominum의 행동을 제어하기 위해 주로 사용됩니다. +**참고:** 이 메서드는 `process.argv`에 영향을 주지 않습니다. + 개발자들은 보통 Chrominum의 로우 레벨 수준의 동작을 제어하기 위해 주로 사용합니다. ### `app.commandLine.appendArgument(value)` -Chromium의 명령문에 인자를 추가합니다. 인자는 올바르게 인용될 것입니다. +Chrominum의 명령줄에 인자를 추가합니다. 인자는 올바르게 인용됩니다. -**Note:** 'process.argv'에 영향을 주지는 않습니다. +**참고:** 이 메서드는 `process.argv`에 영향을 주지 않습니다. ### `app.dock.bounce([type])` _OS X_ -* `type` String (optional) - 'critical'이나 'informational'. 디폴트 설정은 'informational' +* `type` String (optional) - `critical` 또는 `informational`을 지정할 수 있습니다. 기본값은 `informational` 입니다. -'critical'이 input으로 전달되면, dock 아이콘은 응용프로그램이 활성화되거나, 요청이 취소될 때까지 -계속 bounce합니다. +`critical`이 전달되면 dock 아이콘이 어플리케이션이 활성화되거나 요청이 중지되기 전까지 통통 튑니다. -'informational'이 input으로 전달되면, dock 아이콘은 1초만 bounce합니다. -그러나, 응용프로그램이 활성화되거나 요청이 취소될 때까지 요청은 계속 활성화되어 있습니다. +`informational`이 전달되면 dock 아이콘이 1초만 통통 튑니다. +하지만 어플리케이션이 활성화되거나 요청이 중지되기 전까지 요청은 계속 활성화로 유지 됩니다. -요청을 대표하는 ID를 반환합니다. +또한 요청을 취소할 때 사용할 수 있는 ID를 반환합니다. ### `app.dock.cancelBounce(id)` _OS X_ * `id` Integer -'id'의 반송을 취소합니다. - +`app.dock.bounce([type])` 메서드에서 반환한 `id`의 통통 튀는 효과를 취소합니다. ### `app.dock.setBadge(text)` _OS X_ * `text` String -dock의 badge 구역에 표현될 문장을 설정합니다. +dock의 badge에 표시할 문자열을 설정합니다. ### `app.dock.getBadge()` _OS X_ -dock의 badge 라인을 반환합니다. - +dock의 badge에 설정된 문자열을 반환합니다. ### `app.dock.hide()` _OS X_ @@ -330,13 +324,13 @@ dock 아이콘을 숨깁니다. ### `app.dock.show()` _OS X_ -dock 아이콘을 보여줍니다. +dock 아이콘을 표시합니다. ### `app.dock.setMenu(menu)` _OS X_ * `menu` Menu -어플리케이션의 [dock menu][dock-menu]을 결정합니다. +어플리케이션의 [dock menu][dock-menu]를 설정합니다. [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 From edd6032ed0b869d0c17cce114475dccd13ce50fd Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 16 Oct 2015 22:26:27 +0900 Subject: [PATCH 211/738] Improve grammar for more readability --- docs-translations/ko-KR/README.md | 2 +- docs-translations/ko-KR/api/chrome-command-line-switches.md | 4 ++-- docs-translations/ko-KR/api/process.md | 2 +- docs-translations/ko-KR/api/tray.md | 2 +- .../ko-KR/tutorial/desktop-environment-integration.md | 4 ++-- docs-translations/ko-KR/tutorial/quick-start.md | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index 9b88aa6e1780..e77ee9b6936e 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -19,7 +19,7 @@ * [개요](api/synopsis.md) * [Process 객체](api/process.md) -* [크롬 Command Line 스위치 지원](api/chrome-command-line-switches.md) +* [크롬 명령줄 스위치 지원](api/chrome-command-line-switches.md) ### 커스텀 DOM elements: diff --git a/docs-translations/ko-KR/api/chrome-command-line-switches.md b/docs-translations/ko-KR/api/chrome-command-line-switches.md index 777ce4612d17..41517e08cabb 100644 --- a/docs-translations/ko-KR/api/chrome-command-line-switches.md +++ b/docs-translations/ko-KR/api/chrome-command-line-switches.md @@ -1,6 +1,6 @@ -# 크롬 Command-Line 스위치 지원 +# 크롬 명령줄 스위치 지원 -크롬 Command-Line 스위치는 크롬 브라우저에서 제공되는 추가 옵션이며 Electron에서도 지원합니다. +크롬 명령줄(Command-Line) 스위치는 크롬 브라우저에서 제공되는 추가 옵션이며 Electron에서도 지원합니다. [app][app]의 [ready][ready]이벤트가 작동하기 전에 [app.commandLine.appendSwitch][append-switch] API를 사용하면 어플리케이션 내부에서 스위치들을 추가할 수 있습니다: diff --git a/docs-translations/ko-KR/api/process.md b/docs-translations/ko-KR/api/process.md index a35c8b4e93d8..109c443c4907 100644 --- a/docs-translations/ko-KR/api/process.md +++ b/docs-translations/ko-KR/api/process.md @@ -37,4 +37,4 @@ process.once('loaded', function() { * `maxDescriptors` Integer -`maxDescriptors`에 file descriptor 소프트 리미트를 설정하거나 OS 하드 리미트를 설정합니다. 값은 현재 프로세스에 대해 낮은 값이어야 합니다. +현재 프로세스의 파일 기술자의 제한 값을 소프트 제한 `maxDescriptors`의 값이나 OS 하드 제한 중 낮은 값으로 설정합니다. diff --git a/docs-translations/ko-KR/api/tray.md b/docs-translations/ko-KR/api/tray.md index beccf6d8b34a..cd821f581b32 100644 --- a/docs-translations/ko-KR/api/tray.md +++ b/docs-translations/ko-KR/api/tray.md @@ -118,7 +118,7 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다. `Tray` 모듈은 다음과 같은 메서드를 가지고 있습니다: -**참고:** 몇가지 메서드는 특정한 플랫폼에서만 작동합니다. +**참고:** 몇몇 메서드는 특정 플랫폼에서만 작동합니다. ### `Tray.destroy()` diff --git a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md index 8e73d5940f7c..b721f5a4a358 100644 --- a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md +++ b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md @@ -1,7 +1,7 @@ # 데스크톱 환경 통합 -어플리케이션을 배포할 서로 다른 운영체제 시스템의 환경과 기능에 맞춰 사용 환경을 통합할 수 있습니다. -예를 들어 Windows에선 태스크바의 JumpList에 바로가기를 추가할 수 있고 Mac(OS X)에선 dock menu에 커스텀 메뉴를 추가할 수 있습니다. +어플리케이션 배포의 대상이 되는 서로 다른 운영체제 시스템의 환경에 맞춰 어플리케이션의 기능을 통합할 수 있습니다. +예를 들어 Windows에선 태스크바의 JumpList에 바로가기를 추가할 수 있고 Mac(OS X)에선 dock 메뉴에 커스텀 메뉴를 추가할 수 있습니다. 이 가이드는 Electron API를 이용하여 각 운영체제 시스템의 기능을 활용하는 방법을 설명합니다. diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 6eaad7476958..3a0c38f04b92 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -71,7 +71,7 @@ var BrowserWindow = require('browser-window'); // 네이티브 브라우저 창 require('crash-reporter').start(); // 윈도우 객체를 전역에 유지합니다. 만약 이렇게 하지 않으면 -// 자바스크립트 GC가 일어날 때 창이 자동으로 닫혀버립니다. +// 자바스크립트 GC가 일어날 때 창이 멋대로 닫혀버립니다. var mainWindow = null; // 모든 창이 닫히면 어플리케이션 종료. From 32523ae352b7735b0bcac52accbc0800dc0d8546 Mon Sep 17 00:00:00 2001 From: Roman Klauke Date: Fri, 16 Oct 2015 22:03:47 +0200 Subject: [PATCH 212/738] replace Mac with OS X Commit 691d8dd replaced "Mac" with "OS X". This commit replaces some other occurrences. --- docs/README.md | 2 +- docs/api/frameless-window.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index a0d91a5459ce..754048f5e3f3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -66,7 +66,7 @@ * [Source Code Directory Structure](development/source-code-directory-structure.md) * [Technical Differences to NW.js (formerly node-webkit)](development/atom-shell-vs-node-webkit.md) * [Build System Overview](development/build-system-overview.md) -* [Build Instructions (Mac)](development/build-instructions-osx.md) +* [Build Instructions (OS X)](development/build-instructions-osx.md) * [Build Instructions (Windows)](development/build-instructions-windows.md) * [Build Instructions (Linux)](development/build-instructions-linux.md) * [Setting Up Symbol Server in debugger](development/setting-up-symbol-server.md) diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index 8d64a6fcd7c8..bc37aafca882 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -13,7 +13,7 @@ var BrowserWindow = require('browser-window'); var win = new BrowserWindow({ width: 800, height: 600, frame: false }); ``` -### Alternatives on Mac +### Alternatives on OS X On Mac OS X 10.10 Yosemite and newer, there's an alternative way to specify a chromeless window. Instead of setting `frame` to `false` which disables From b5478eaef76063f65bda41da65461f03017d989d Mon Sep 17 00:00:00 2001 From: Greg Gamel Date: Fri, 16 Oct 2015 17:50:41 -0500 Subject: [PATCH 213/738] Update MAS tutorial to improve readability Adjusted tutorial body copy and headings to improve readability, clarify sentences, and fix some (minor) grammatical missteps. --- .../mac-app-store-submission-guide.md | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md index ccd0ead8584e..b67e6ff54d38 100644 --- a/docs/tutorial/mac-app-store-submission-guide.md +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -1,29 +1,28 @@ # Mac App Store Submission Guide -Since v0.34.0, Electron allows submitting packaged apps to Mac App Store (MAS), -this guide provides information on how to submit your app, and the limitations +Since v0.34.0, Electron allows submitting packaged apps to the Mac App Store (MAS). +This guide provides information on: how to submit your app & the limitations of the MAS build. -## How to submit your app +## How to Submit Your App -Following steps introduces a simple way to submit your app to Mac App Store, but -it doesn't make sure your app gets approved by Apple, you still have to read -apple's [Submitting Your App][submitting-your-app] guide on how to meet Mac -App Store's requirements. +The following steps introduce a simple way to submit your app to Mac App Store. However, these steps +do not ensure sure your app will be approved by Apple; you still need to read +Apple's [Submitting Your App][submitting-your-app] guide on how to meet the Mac +App Store requirements. -### Get certificate +### Get Certificate -To submit your app to Mac App Store, you have to get a certificate from Apple -first, you can follow [existing guides][nwjs-guide] on web. +To submit your app to the Mac App Store, you first must get a certificate from Apple. You can follow these [existing guides][nwjs-guide] on web. -### Sign your app +### Sign Your App -After getting the certificate, you can package your app by following -[Application Distribution](application-distribution.md), and then sign your app. -The step is basically the same with other programs, the key is to sign every +After getting the certificate from Apple, you can package your app by following +[Application Distribution](application-distribution.md), and then proceed to signing your app. +This step is basically the same with other programs, but the key is to sign every dependency of Electron one by one. -First you need to prepare two entitlements files. +First, you need to prepare two entitlements files. `child.plist`: @@ -53,7 +52,7 @@ First you need to prepare two entitlements files. ``` -And then sign your app with following script: +...and then sign your app with the following script: ```bash #!/bin/bash @@ -80,32 +79,32 @@ codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$APP_PATH" ``` -If you are new to app sandboxing of OS X, you should also go through Apple's -[Enabling App Sandbox][enable-app-sandbox] to have a basic idea, and add keys +If you are new to app sandboxing under OS X, you should also read through Apple's +[Enabling App Sandbox][enable-app-sandbox] to have a basic idea, then add keys for the permissions needed by your app to the entitlements files. -### Upload your app and submit for review +### Upload Your App and Submit for Review -After signing your app you can use Application Loader to upload it to iTunes -Connect for processing, make sure you have [created a record][create-record] +After signing your app, you can use Application Loader to upload it to iTunes +Connect for processing, making sure you have [created a record][create-record] before uploading. Then you can [submit your app for review][submit-for-review]. -## Limitations of MAS build +## Limitations of MAS Build -In order to satisfy requirements for app sandboxing, following modules have been -disabled in MAS build: +In order to satisfy all requirements for app sandboxing, the following modules have been +disabled in the MAS build: * `crash-reporter` * `auto-updater` -and following behaviors have been changed: +and the following behaviors have been changed: * Video capture may not work for some machines. * Certain accessibility features may not work. * Apps will not be aware of DNS changes. -Also due to the usage of app sandboxing, the resources can be accessed by the -app is strictly limited, you can read [App Sandboxing][app-sandboxing] for more. +Also, due to the usage of app sandboxing, the resources which can be accessed by the +app are strictly limited; you can read [App Sandboxing][app-sandboxing] for more information. [submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html [nwjs-guide]: https://github.com/nwjs/nw.js/wiki/Mac-App-Store-%28MAS%29-Submission-Guideline#first-steps From 72078f7b027088b004895e9582d204a23f80a03a Mon Sep 17 00:00:00 2001 From: max_devjs Date: Fri, 16 Oct 2015 19:56:45 -0300 Subject: [PATCH 214/738] [truly humble correction of a misspelling] Substituting webp with web in frameless-window.md . --- docs/api/frameless-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index bc37aafca882..707a928f9db6 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -1,6 +1,6 @@ # Frameless Window -A frameless window is a window that has no [chrome](https://developer.mozilla.org/en-US/docs/Glossary/Chrome), the parts of the window, like toolbars, that are not a part of the webp page. These are options on the [`BrowserWindow`](browser-window.md) class. +A frameless window is a window that has no [chrome](https://developer.mozilla.org/en-US/docs/Glossary/Chrome), the parts of the window, like toolbars, that are not a part of the web page. These are options on the [`BrowserWindow`](browser-window.md) class. ## Create a frameless window From 5e7a30deeab7639e9f76458690d488ca9c6d93f2 Mon Sep 17 00:00:00 2001 From: Greg Gamel Date: Fri, 16 Oct 2015 18:25:30 -0500 Subject: [PATCH 215/738] Additional updates to adhere to styleguide Per @jlord's recommendations. --- .../mac-app-store-submission-guide.md | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md index b67e6ff54d38..fb04a5573b12 100644 --- a/docs/tutorial/mac-app-store-submission-guide.md +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -1,26 +1,27 @@ # Mac App Store Submission Guide -Since v0.34.0, Electron allows submitting packaged apps to the Mac App Store (MAS). -This guide provides information on: how to submit your app & the limitations -of the MAS build. +Since v0.34.0, Electron allows submitting packaged apps to the Mac App Store +(MAS). This guide provides information on: how to submit your app and the +limitations of the MAS build. ## How to Submit Your App -The following steps introduce a simple way to submit your app to Mac App Store. However, these steps -do not ensure sure your app will be approved by Apple; you still need to read -Apple's [Submitting Your App][submitting-your-app] guide on how to meet the Mac -App Store requirements. +The following steps introduce a simple way to submit your app to Mac App Store. +However, these steps do not ensure sure your app will be approved by Apple; you +still need to read Apple's [Submitting Your App][submitting-your-app] guide on +how to meet the Mac App Store requirements. ### Get Certificate -To submit your app to the Mac App Store, you first must get a certificate from Apple. You can follow these [existing guides][nwjs-guide] on web. +To submit your app to the Mac App Store, you first must get a certificate from +Apple. You can follow these [existing guides][nwjs-guide] on web. ### Sign Your App After getting the certificate from Apple, you can package your app by following -[Application Distribution](application-distribution.md), and then proceed to signing your app. -This step is basically the same with other programs, but the key is to sign every -dependency of Electron one by one. +[Application Distribution](application-distribution.md), and then proceed to +signing your app. This step is basically the same with other programs, but the +key is to sign every dependency of Electron one by one. First, you need to prepare two entitlements files. @@ -52,7 +53,7 @@ First, you need to prepare two entitlements files. ``` -...and then sign your app with the following script: +And then sign your app with the following script: ```bash #!/bin/bash @@ -78,10 +79,10 @@ codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$APP_PATH" ``` - -If you are new to app sandboxing under OS X, you should also read through Apple's -[Enabling App Sandbox][enable-app-sandbox] to have a basic idea, then add keys -for the permissions needed by your app to the entitlements files. +a +If you are new to app sandboxing under OS X, you should also read through +Apple's [Enabling App Sandbox][enable-app-sandbox] to have a basic idea, then +add keys for the permissions needed by your app to the entitlements files. ### Upload Your App and Submit for Review @@ -91,8 +92,8 @@ before uploading. Then you can [submit your app for review][submit-for-review]. ## Limitations of MAS Build -In order to satisfy all requirements for app sandboxing, the following modules have been -disabled in the MAS build: +In order to satisfy all requirements for app sandboxing, the following modules +have been disabled in the MAS build: * `crash-reporter` * `auto-updater` @@ -103,8 +104,9 @@ and the following behaviors have been changed: * Certain accessibility features may not work. * Apps will not be aware of DNS changes. -Also, due to the usage of app sandboxing, the resources which can be accessed by the -app are strictly limited; you can read [App Sandboxing][app-sandboxing] for more information. +Also, due to the usage of app sandboxing, the resources which can be accessed by + the app are strictly limited; you can read [App Sandboxing][app-sandboxing] for + more information. [submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html [nwjs-guide]: https://github.com/nwjs/nw.js/wiki/Mac-App-Store-%28MAS%29-Submission-Guideline#first-steps From 7ac643d5f85028b126b52ad956c67af78f3417af Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Fri, 16 Oct 2015 16:45:54 -0700 Subject: [PATCH 216/738] Create a new method on App to override URL Security Manager's decisions wrt NTLM --- atom/browser/api/atom_api_app.cc | 6 ++++++ atom/browser/api/atom_api_app.h | 2 ++ vendor/brightray | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 70595856c494..47c3b1dd4672 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -251,6 +251,12 @@ void App::SetAppUserModelId(const std::string& app_id) { #endif } +void App::AllowNTLMCredentialsForAllDomains(bool should_allow) { + auto browser_context = static_cast( + AtomBrowserMainParts::Get()->browser_context()); + browser_context->AllowNTLMCredentialsForAllDomains(should_allow); +} + std::string App::GetLocale() { return l10n_util::GetApplicationLocale(""); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 4896a5f066a1..75889d24543f 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -65,6 +65,8 @@ class App : public mate::EventEmitter, void SetDesktopName(const std::string& desktop_name); void SetAppUserModelId(const std::string& app_id); + void AllowNTLMCredentialsForAllDomains(bool should_allow); + std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); diff --git a/vendor/brightray b/vendor/brightray index fe2dd437c9ef..2fc67433d18f 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit fe2dd437c9ef7877bf9d454db8ae401965cd7cb0 +Subproject commit 2fc67433d18fa336c2f76e94c1a04177360cb126 From 5ae6bd2ef4e3892b84121f6d92b3de6a2f89fdf1 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Fri, 16 Oct 2015 16:46:05 -0700 Subject: [PATCH 217/738] Wire it up --- atom/browser/api/atom_api_app.cc | 1 + atom/browser/api/atom_api_app.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 47c3b1dd4672..158dd6ae3488 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -291,6 +291,7 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( .SetMethod("getPath", &App::GetPath) .SetMethod("setDesktopName", &App::SetDesktopName) .SetMethod("setAppUserModelId", &App::SetAppUserModelId) + .SetMethod("allowNTLMCredentialsForAllDomains", &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) .SetProperty("defaultSession", &App::DefaultSession); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 75889d24543f..52f134169fcd 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -66,7 +66,7 @@ class App : public mate::EventEmitter, void SetDesktopName(const std::string& desktop_name); void SetAppUserModelId(const std::string& app_id); void AllowNTLMCredentialsForAllDomains(bool should_allow); - + std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); From a3fc25110eed8e61bbf37c6935350c3747b5aea7 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Fri, 16 Oct 2015 16:55:28 -0700 Subject: [PATCH 218/738] Linter fixes --- atom/browser/api/atom_api_app.cc | 3 ++- atom/browser/api/atom_api_app.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 158dd6ae3488..f124b00e8089 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -291,7 +291,8 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( .SetMethod("getPath", &App::GetPath) .SetMethod("setDesktopName", &App::SetDesktopName) .SetMethod("setAppUserModelId", &App::SetAppUserModelId) - .SetMethod("allowNTLMCredentialsForAllDomains", &App::AllowNTLMCredentialsForAllDomains) + .SetMethod("allowNTLMCredentialsForAllDomains", + &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) .SetProperty("defaultSession", &App::DefaultSession); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 52f134169fcd..75889d24543f 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -66,7 +66,7 @@ class App : public mate::EventEmitter, void SetDesktopName(const std::string& desktop_name); void SetAppUserModelId(const std::string& app_id); void AllowNTLMCredentialsForAllDomains(bool should_allow); - + std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); From b958982d9921712732c9db056a55674133626b15 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Fri, 16 Oct 2015 17:00:31 -0700 Subject: [PATCH 219/738] Rollback submodule change --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 2fc67433d18f..fe2dd437c9ef 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 2fc67433d18fa336c2f76e94c1a04177360cb126 +Subproject commit fe2dd437c9ef7877bf9d454db8ae401965cd7cb0 From c46ed897dd5714322e7fe0ed151deb289fa2df6e Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sun, 18 Oct 2015 03:22:35 +0900 Subject: [PATCH 220/738] Update translation progress in README.md --- docs-translations/ko-KR/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index e77ee9b6936e..9df89ead5088 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -29,7 +29,7 @@ ### 메인 프로세스에서 사용할 수 있는 모듈: -* [app (0% 번역됨)](api/app.md) +* [app](api/app.md) * [auto-updater](api/auto-updater.md) * [browser-window (0% 번역됨)](api/browser-window.md) * [content-tracing](api/content-tracing.md) From 82e6058607fa0b1ca24b83a5084392422fec12f9 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sun, 18 Oct 2015 03:30:37 +0900 Subject: [PATCH 221/738] Update as upstream --- docs-translations/ko-KR/README.md | 3 ++- docs-translations/ko-KR/api/frameless-window.md | 2 +- docs-translations/ko-KR/api/process.md | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index 9df89ead5088..bfe08e5e1032 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -2,6 +2,7 @@ * [지원하는 플랫폼](tutorial/supported-platforms.md) * [어플리케이션 배포](tutorial/application-distribution.md) +* [맥 앱스토어 제출 가이드 (0% 번역됨)](tutorial/mac-app-store-submission-guide.md) * [어플리케이션 패키징](tutorial/application-packaging.md) * [네이티브 Node 모듈 사용하기](tutorial/using-native-node-modules.md) * [메인 프로세스 디버깅하기](tutorial/debugging-main-process.md) @@ -65,7 +66,7 @@ * [소스 코드 디렉터리 구조](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-osx.md) +* [빌드 설명서 (OS X)](development/build-instructions-osx.md) * [빌드 설명서 (Windows)](development/build-instructions-windows.md) * [빌드 설명서 (Linux)](development/build-instructions-linux.md) * [디버거에서 디버그 심볼 서버 설정](development/setting-up-symbol-server.md) diff --git a/docs-translations/ko-KR/api/frameless-window.md b/docs-translations/ko-KR/api/frameless-window.md index 64422460775f..28662c311ba2 100644 --- a/docs-translations/ko-KR/api/frameless-window.md +++ b/docs-translations/ko-KR/api/frameless-window.md @@ -13,7 +13,7 @@ var BrowserWindow = require('browser-window'); var win = new BrowserWindow({ width: 800, height: 600, frame: false }); ``` -### 최신 Mac에서 사용할 수 있는 대안 +### 최신 OS X에서 사용할 수 있는 대안 OS X 10.10 Yosemite 이후의 최신 버전부터는 테두리가 없는 창을 만들 때 새로운 방법을 사용할 수 있습니다. `frame` 옵션을 `false`로 지정하여 제목과 창 구성 요소를 모두 비활성화하는 대신 새로운 `title-bar-style` diff --git a/docs-translations/ko-KR/api/process.md b/docs-translations/ko-KR/api/process.md index 109c443c4907..c66eb84cfeae 100644 --- a/docs-translations/ko-KR/api/process.md +++ b/docs-translations/ko-KR/api/process.md @@ -5,7 +5,8 @@ Electron의 `process` 객체는 기존의 node와는 달리 약간의 차이점 * `process.type` String - 프로세스의 타입, `browser` (메인 프로세스) 또는 `renderer`가 됩니다. * `process.versions['electron']` String - Electron의 버전. * `process.versions['chrome']` String - Chromium의 버전. -* `process.resourcesPath` String - JavaScript 소스코드의 경로. +* `process.resourcesPath` String - JavaScript 소스 코드의 경로. +* `process.mas` Boolean - Mac 앱 스토어용 빌드일 때 `true`로 지정됩니다. 다른 빌드일 땐 `undefined`로 지정됩니다. ## Events From 49d25d00697047faed54e0e8080520d73cce629e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Sun, 18 Oct 2015 11:28:05 +0800 Subject: [PATCH 222/738] Fix: savePage API saves external resources in a wrong directory. --- atom/browser/api/save_page_handler.cc | 7 ++++++- spec/api-browser-window-spec.coffee | 19 ++++++++++++++----- spec/fixtures/pages/save_page/index.html | 6 ++++++ spec/fixtures/pages/save_page/test.css | 1 + spec/fixtures/pages/save_page/test.js | 1 + 5 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 spec/fixtures/pages/save_page/index.html create mode 100644 spec/fixtures/pages/save_page/test.css create mode 100644 spec/fixtures/pages/save_page/test.js diff --git a/atom/browser/api/save_page_handler.cc b/atom/browser/api/save_page_handler.cc index 42b93befddf6..1e5bc094cf63 100644 --- a/atom/browser/api/save_page_handler.cc +++ b/atom/browser/api/save_page_handler.cc @@ -36,8 +36,13 @@ bool SavePageHandler::Handle(const base::FilePath& full_path, auto download_manager = content::BrowserContext::GetDownloadManager( web_contents_->GetBrowserContext()); download_manager->AddObserver(this); + // Chromium will create a 'foo_files' directory under the directory of saving + // page 'foo.html' for holding other resource files of 'foo.html'. + base::FilePath saved_main_directory_path = full_path.DirName().Append( + full_path.RemoveExtension().BaseName().value() + + FILE_PATH_LITERAL("_files")); bool result = web_contents_->SavePage(full_path, - full_path.DirName(), + saved_main_directory_path, save_type); download_manager->RemoveObserver(this); // If initialization fails which means fail to create |DownloadItem|, we need diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 0f9b376784fc..1218d27b7fd7 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -303,13 +303,22 @@ describe 'browser-window module', -> done() describe 'save page', -> - savePagePath = path.join fixtures, 'save_page.html' + savePageDir = path.join fixtures, 'save_page' + savePageHtmlPath = path.join savePageDir, 'save_page.html' + savePageJsPath = path.join savePageDir, 'save_page_files', 'test.js' + savePageCssPath = path.join savePageDir, 'save_page_files', 'test.css' it 'should save page', (done) -> w.webContents.on 'did-finish-load', -> - w.webContents.savePage savePagePath, 'HTMLComplete', (error) -> + w.webContents.savePage savePageHtmlPath, 'HTMLComplete', (error) -> assert.equal error, null - assert fs.existsSync savePagePath - fs.unlinkSync savePagePath + assert fs.existsSync savePageHtmlPath + assert fs.existsSync savePageJsPath + assert fs.existsSync savePageCssPath + fs.unlinkSync savePageCssPath + fs.unlinkSync savePageJsPath + fs.unlinkSync savePageHtmlPath + fs.rmdirSync path.join savePageDir, 'save_page_files' + fs.rmdirSync savePageDir done() - w.loadUrl "file://#{fixtures}/api/blank.html" + w.loadUrl "file://#{fixtures}/pages/save_page/index.html" diff --git a/spec/fixtures/pages/save_page/index.html b/spec/fixtures/pages/save_page/index.html new file mode 100644 index 000000000000..829233bb86fb --- /dev/null +++ b/spec/fixtures/pages/save_page/index.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/spec/fixtures/pages/save_page/test.css b/spec/fixtures/pages/save_page/test.css new file mode 100644 index 000000000000..f7df9d4fdadb --- /dev/null +++ b/spec/fixtures/pages/save_page/test.css @@ -0,0 +1 @@ +h1 { } diff --git a/spec/fixtures/pages/save_page/test.js b/spec/fixtures/pages/save_page/test.js new file mode 100644 index 000000000000..3d79457383f5 --- /dev/null +++ b/spec/fixtures/pages/save_page/test.js @@ -0,0 +1 @@ +console.log('save_page'); From 60b14d03e98dcbcc73098b36c337cb0ad47c828e Mon Sep 17 00:00:00 2001 From: Brandon Cash Date: Sun, 18 Oct 2015 00:32:13 -0500 Subject: [PATCH 223/738] Fix: tray NotfiyDropFiles typo --- atom/browser/ui/tray_icon.cc | 2 +- atom/browser/ui/tray_icon.h | 2 +- atom/browser/ui/tray_icon_cocoa.mm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/atom/browser/ui/tray_icon.cc b/atom/browser/ui/tray_icon.cc index 12c6be2ea74e..d2c6bc1b2597 100644 --- a/atom/browser/ui/tray_icon.cc +++ b/atom/browser/ui/tray_icon.cc @@ -55,7 +55,7 @@ void TrayIcon::NotifyRightClicked(const gfx::Rect& bounds, int modifiers) { OnRightClicked(bounds, modifiers)); } -void TrayIcon::NotfiyDropFiles(const std::vector& files) { +void TrayIcon::NotifyDropFiles(const std::vector& files) { FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDropFiles(files)); } diff --git a/atom/browser/ui/tray_icon.h b/atom/browser/ui/tray_icon.h index af774ddbfb42..539fe04f4bb6 100644 --- a/atom/browser/ui/tray_icon.h +++ b/atom/browser/ui/tray_icon.h @@ -61,7 +61,7 @@ class TrayIcon { void NotifyBalloonClosed(); void NotifyRightClicked(const gfx::Rect& bounds = gfx::Rect(), int modifiers = 0); - void NotfiyDropFiles(const std::vector& files); + void NotifyDropFiles(const std::vector& files); protected: TrayIcon(); diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index ec6a6a3e1964..34ca4e9a9112 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -265,7 +265,7 @@ const CGFloat kVerticalTitleMargin = 2; NSArray* files = [pboard propertyListForType:NSFilenamesPboardType]; for (NSString* file in files) dropFiles.push_back(base::SysNSStringToUTF8(file)); - trayIcon_->NotfiyDropFiles(dropFiles); + trayIcon_->NotifyDropFiles(dropFiles); return YES; } return NO; From 0aefa98e5ad545761f14c28bc57d957e317b6dd2 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Mon, 19 Oct 2015 11:34:13 +0900 Subject: [PATCH 224/738] Small fix in README --- README-ko.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-ko.md b/README-ko.md index c722243eb589..4432c96f827d 100644 --- a/README-ko.md +++ b/README-ko.md @@ -49,7 +49,7 @@ Electron을 빌드 하는 방법과 프로젝트에 기여하는 방법도 문 ## 커뮤니티 -다음 링크를 통해 커뮤니티에 질문을 올리거나 토론을 나누실 수 있습니다: +다음 링크를 통해 커뮤니티에 질문을 올리거나 토론을 나눌 수 있습니다: - Atom 포럼의 [`electron`](http://discuss.atom.io/category/electron) 카테고리 - Freenode 채팅의 `#atom-shell` 채널 From 810af2f95d34632b82d9a26dad833ce854272627 Mon Sep 17 00:00:00 2001 From: Prince J Wesley Date: Mon, 19 Oct 2015 08:33:22 +0530 Subject: [PATCH 225/738] :bug: Honor fs.readFileSync contract for empty packed asar file --- atom/common/lib/asar.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atom/common/lib/asar.coffee b/atom/common/lib/asar.coffee index 22d0e70b34fa..d2a7799fa694 100644 --- a/atom/common/lib/asar.coffee +++ b/atom/common/lib/asar.coffee @@ -263,7 +263,9 @@ exports.wrapFsWithAsar = (fs) -> info = archive.getFileInfo filePath notFoundError asarPath, filePath unless info - return new Buffer(0) if info.size is 0 + + if info.size is 0 + return if options then '' else new Buffer(0) if info.unpacked realPath = archive.copyFileOut filePath From d9c7401d0b7e5e8aa73ee5d315d0b09d191c0f63 Mon Sep 17 00:00:00 2001 From: Jhen Date: Mon, 19 Oct 2015 21:29:10 +0800 Subject: [PATCH 226/738] Replace io.js with node.js for zh-TW docs translation --- docs-translations/zh-TW/tutorial/quick-start.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs-translations/zh-TW/tutorial/quick-start.md b/docs-translations/zh-TW/tutorial/quick-start.md index aee2baa713bf..4655549167c1 100644 --- a/docs-translations/zh-TW/tutorial/quick-start.md +++ b/docs-translations/zh-TW/tutorial/quick-start.md @@ -3,7 +3,7 @@ ## 簡介 Electron 可以讓你使用純 JavaScript 提供豐富的原生的 APIs 來創造桌面應用程式。 -你可以把它視為一個 io.js 的變體,專注於桌面應用程式而不是 web 伺服器。 +你可以把它視為一個 Node.js 的變體,專注於桌面應用程式而不是 web 伺服器。 這不表示 Electron 是一個用 JavaScript 去綁定 GUI 函式庫。取而代之的,Electron 是使用網頁介面來作為它的 GUI , 所以你可以把它看作是一個被 JavaScript 所控制且精簡化的 Chromium 瀏覽器。 @@ -19,7 +19,7 @@ Electron 可以讓你使用純 JavaScript 提供豐富的原生的 APIs 來創 每一個網頁在 Electron 裏執行各自的行程,被稱為 __渲染行程__。 在一般瀏覽器中,網頁通常會在沙盒環境下運行,並且不允許存取原生資源。然而, -Electron 的用戶擁有在網頁中呼叫 io.js APIs 的能力,允許低級別操作與作業系統的交互作用。 +Electron 的用戶擁有在網頁中呼叫 Node.js APIs 的能力,允許低級別操作與作業系統的交互作用。 ## 主行程與渲染行程的區別 @@ -110,7 +110,7 @@ app.on('ready', function() {           

Hello World!

-    We are using io.js +    We are using Node.js     and Electron .    From 09ee24514e0a19b22a66e2b0e34a9fe51b88181d Mon Sep 17 00:00:00 2001 From: Jhen Date: Mon, 19 Oct 2015 21:49:57 +0800 Subject: [PATCH 227/738] Replace Mac with OS X for zh-TW docs translation --- docs-translations/zh-TW/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/zh-TW/README.md b/docs-translations/zh-TW/README.md index cc75ba51c144..bf2fc3386799 100644 --- a/docs-translations/zh-TW/README.md +++ b/docs-translations/zh-TW/README.md @@ -64,7 +64,7 @@ * [源碼目錄結構](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) +* [構建步驟 (OS X)](development/build-instructions-osx.md) * [構建步驟 (Windows)](development/build-instructions-windows.md) * [構建步驟 (Linux)](development/build-instructions-linux.md) * [在 debugger 中使用 symbol server](development/setting-up-symbol-server.md) From 7f15d63552bc9de71535246b64bddf267f4f5a31 Mon Sep 17 00:00:00 2001 From: Jhen Date: Mon, 19 Oct 2015 21:54:29 +0800 Subject: [PATCH 228/738] Update README.md for zh-TW docs-translations --- docs-translations/zh-TW/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs-translations/zh-TW/README.md b/docs-translations/zh-TW/README.md index bf2fc3386799..1e69c9744387 100644 --- a/docs-translations/zh-TW/README.md +++ b/docs-translations/zh-TW/README.md @@ -1,7 +1,9 @@ ## 導引 +* [支援平台](tutorial/supported-platforms.md) * [應用程式發布](tutorial/application-distribution.md) * [應用程式打包](tutorial/application-packaging.md) +* [Mac App Store 上架指引](tutorial/mac-app-store-submission-guide.md) * [使用原生 node 模組](tutorial/using-native-node-modules.md) * [主行程 Debug](tutorial/debugging-main-process.md) * [使用 Selenium 和 WebDriver](tutorial/using-selenium-and-webdriver.md) From 489090fcf82bf3f7f3bf5a65326b7e176e37340d Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 13:03:20 -0700 Subject: [PATCH 229/738] Set up our browser context to use new delegate-based API --- atom/browser/atom_browser_context.cc | 10 ++++++++-- atom/browser/atom_browser_context.h | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index 6823fbaee90c..13be18ce9bd6 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -60,8 +60,8 @@ std::string RemoveWhitespace(const std::string& str) { AtomBrowserContext::AtomBrowserContext(const std::string& partition, bool in_memory) : brightray::BrowserContext(partition, in_memory), - job_factory_(new AtomURLRequestJobFactory) { -} + job_factory_(new AtomURLRequestJobFactory), + allow_ntlm_everywhere_(false) : { } AtomBrowserContext::~AtomBrowserContext() { } @@ -168,6 +168,12 @@ void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) { base::FilePath()); } + +bool AtomBrowserContext::AllowNTLMCredentialsForDomain(const GURL& auth_origin) { + if (allow_ntlm_everywhere_) return true; + return brightray::URLRequestContextGetter::Delegate::AllowNTLMCredentialsForDomain(auth_origin); +} + } // namespace atom namespace brightray { diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index 839359c1ef50..9ec3928272b3 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -28,6 +28,7 @@ class AtomBrowserContext : public brightray::BrowserContext { net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory( const base::FilePath& base_path) override; net::SSLConfigService* CreateSSLConfigService() override; + bool AllowNTLMCredentialsForDomain(const GURL& auth_origin) override; // content::BrowserContext: content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; @@ -44,6 +45,8 @@ class AtomBrowserContext : public brightray::BrowserContext { // Managed by brightray::BrowserContext. AtomURLRequestJobFactory* job_factory_; + + bool allow_ntlm_everywhere_; DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext); }; From b3c7e2bf337fe1a013b46acd625ae16e733004d3 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 13:07:14 -0700 Subject: [PATCH 230/738] Plumb the method back --- atom/browser/atom_browser_context.cc | 8 +++++++- atom/browser/atom_browser_context.h | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index 13be18ce9bd6..75742f8c8e6f 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -61,7 +61,8 @@ AtomBrowserContext::AtomBrowserContext(const std::string& partition, bool in_memory) : brightray::BrowserContext(partition, in_memory), job_factory_(new AtomURLRequestJobFactory), - allow_ntlm_everywhere_(false) : { } + allow_ntlm_everywhere_(false) { +} AtomBrowserContext::~AtomBrowserContext() { } @@ -174,6 +175,11 @@ bool AtomBrowserContext::AllowNTLMCredentialsForDomain(const GURL& auth_origin) return brightray::URLRequestContextGetter::Delegate::AllowNTLMCredentialsForDomain(auth_origin); } + +void AtomBrowserContext::AllowNTLMCredentialsForAllDomains(bool should_allow) { + allow_ntlm_everywhere_ = should_allow; +} + } // namespace atom namespace brightray { diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index 9ec3928272b3..d4b7d724b428 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -19,7 +19,7 @@ class AtomBrowserContext : public brightray::BrowserContext { public: AtomBrowserContext(const std::string& partition, bool in_memory); ~AtomBrowserContext() override; - + // brightray::URLRequestContextGetter::Delegate: std::string GetUserAgent() override; net::URLRequestJobFactory* CreateURLRequestJobFactory( @@ -36,6 +36,8 @@ class AtomBrowserContext : public brightray::BrowserContext { // brightray::BrowserContext: void RegisterPrefs(PrefRegistrySimple* pref_registry) override; + + void AllowNTLMCredentialsForAllDomains(bool should_allow); AtomURLRequestJobFactory* job_factory() const { return job_factory_; } From e3535d664b49bcc0a88b9d73dd297840e66d4f61 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 13:12:17 -0700 Subject: [PATCH 231/738] Fixed linter issues but now the code looks awful --- atom/browser/atom_browser_context.cc | 8 +++++--- atom/browser/atom_browser_context.h | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index 75742f8c8e6f..b0a9897352e1 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -61,7 +61,7 @@ AtomBrowserContext::AtomBrowserContext(const std::string& partition, bool in_memory) : brightray::BrowserContext(partition, in_memory), job_factory_(new AtomURLRequestJobFactory), - allow_ntlm_everywhere_(false) { + allow_ntlm_everywhere_(false) { } AtomBrowserContext::~AtomBrowserContext() { @@ -170,9 +170,11 @@ void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) { } -bool AtomBrowserContext::AllowNTLMCredentialsForDomain(const GURL& auth_origin) { +bool AtomBrowserContext::AllowNTLMCredentialsForDomain + (const GURL& auth_origin) { if (allow_ntlm_everywhere_) return true; - return brightray::URLRequestContextGetter::Delegate::AllowNTLMCredentialsForDomain(auth_origin); + return brightray::URLRequestContextGetter + ::Delegate::AllowNTLMCredentialsForDomain(auth_origin); } diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index d4b7d724b428..aafa092442bc 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -19,7 +19,7 @@ class AtomBrowserContext : public brightray::BrowserContext { public: AtomBrowserContext(const std::string& partition, bool in_memory); ~AtomBrowserContext() override; - + // brightray::URLRequestContextGetter::Delegate: std::string GetUserAgent() override; net::URLRequestJobFactory* CreateURLRequestJobFactory( @@ -36,7 +36,7 @@ class AtomBrowserContext : public brightray::BrowserContext { // brightray::BrowserContext: void RegisterPrefs(PrefRegistrySimple* pref_registry) override; - + void AllowNTLMCredentialsForAllDomains(bool should_allow); AtomURLRequestJobFactory* job_factory() const { return job_factory_; } @@ -47,7 +47,7 @@ class AtomBrowserContext : public brightray::BrowserContext { // Managed by brightray::BrowserContext. AtomURLRequestJobFactory* job_factory_; - + bool allow_ntlm_everywhere_; DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext); From 9f8479e9d8e56c82871c663f0114bc8044d44a9f Mon Sep 17 00:00:00 2001 From: Robo Date: Tue, 20 Oct 2015 02:26:01 +0530 Subject: [PATCH 232/738] browser: flag to diable specified cipher suites --- atom/browser/atom_ssl_config_service.cc | 27 ++++++++++++++++++++++++ atom/common/options_switches.cc | 3 +++ atom/common/options_switches.h | 1 + docs/api/chrome-command-line-switches.md | 4 ++++ 4 files changed, 35 insertions(+) diff --git a/atom/browser/atom_ssl_config_service.cc b/atom/browser/atom_ssl_config_service.cc index f19dbacf7dd3..0a47067b0a68 100644 --- a/atom/browser/atom_ssl_config_service.cc +++ b/atom/browser/atom_ssl_config_service.cc @@ -5,11 +5,14 @@ #include "atom/browser/atom_ssl_config_service.h" #include +#include #include "base/command_line.h" +#include "base/strings/string_split.h" #include "atom/common/options_switches.h" #include "content/public/browser/browser_thread.h" #include "net/socket/ssl_client_socket.h" +#include "net/ssl/ssl_cipher_suite_names.h" namespace atom { @@ -26,6 +29,23 @@ uint16 GetSSLProtocolVersion(const std::string& version_string) { return version; } +std::vector ParseCipherSuites( + const std::vector& cipher_strings) { + std::vector cipher_suites; + cipher_suites.reserve(cipher_strings.size()); + + for (auto& cipher_string : cipher_strings) { + uint16 cipher_suite = 0; + if (!net::ParseSSLCipherString(cipher_string, &cipher_suite)) { + LOG(ERROR) << "Ignoring unrecognised cipher suite : " + << cipher_string; + continue; + } + cipher_suites.push_back(cipher_suite); + } + return cipher_suites; +} + } // namespace AtomSSLConfigService::AtomSSLConfigService() { @@ -35,6 +55,13 @@ AtomSSLConfigService::AtomSSLConfigService() { cmd_line->GetSwitchValueASCII(switches::kSSLVersionFallbackMin); config_.version_fallback_min = GetSSLProtocolVersion(version_string); } + + if (cmd_line->HasSwitch(switches::kCipherSuiteBlacklist)) { + auto cipher_strings = base::SplitString( + cmd_line->GetSwitchValueASCII(switches::kCipherSuiteBlacklist), + ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + config_.disabled_cipher_suites = ParseCipherSuites(cipher_strings); + } } AtomSSLConfigService::~AtomSSLConfigService() { diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 46687becf84a..84d63c29a0a7 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -117,6 +117,9 @@ const char kRegisterStandardSchemes[] = "register-standard-schemes"; // TLS fallback will accept. const char kSSLVersionFallbackMin[] = "ssl-version-fallback-min"; +// Comma-separated list of SSL cipher suites to disable. +const char kCipherSuiteBlacklist[] = "cipher-suite-blacklist"; + // The browser process app model ID const char kAppUserModelId[] = "app-user-model-id"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 16046d19c822..73312d028d34 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -60,6 +60,7 @@ extern const char kPageVisibility[]; extern const char kDisableHttpCache[]; extern const char kRegisterStandardSchemes[]; extern const char kSSLVersionFallbackMin[]; +extern const char kCipherSuiteBlacklist[]; extern const char kAppUserModelId[]; diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index c2a39126f63e..abf8726b684d 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -92,6 +92,10 @@ Enables net log events to be saved and writes them to `path`. Sets the minimum SSL/TLS version ("tls1", "tls1.1" or "tls1.2") that TLS fallback will accept. +## --cipher-suite-blacklist=`cipher_suites` + +Specify comma-separated list of SSL cipher suites to disable. + ## --enable-logging Prints Chromium's logging into console. From bc7c7da799eb7ce1d066b48db7819702084868da Mon Sep 17 00:00:00 2001 From: Jessica Lord Date: Mon, 19 Oct 2015 15:52:02 -0700 Subject: [PATCH 233/738] Add links to electron-quick-start --- README.md | 5 +++++ docs/tutorial/quick-start.md | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/README.md b/README.md index 94d4c09982be..dd03f7099e10 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,11 @@ contains documents describing how to build and contribute to Electron. - [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN) - [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW) +## Quick Start + +Clone and run the [`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) +repository to see a minimal Electron app in action. + ## Community You can ask questions and interact with the community in the following diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index 5300d754a69b..40988d92df66 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -188,3 +188,19 @@ it from [here](https://github.com/atom/electron/releases). After you're done writing your app, you can create a distribution by following the [Application Distribution](./application-distribution.md) guide and then executing the packaged app. + +### Try this Example + +Clone and run the code in this tutorial by using the [`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) +repository. + +**Note**: Running this requires [Git](https://git-scm.com) and [Node.js](https://nodejs.org/en/download/) (which includes [npm](https://npmjs.org)) on your system. + +```bash +# Clone the repository +$ git clone https://github.com/atom/electron-quick-start +# Go into the repository +$ cd electron-quick-start +# Install dependencies and run the app +$ npm install && npm start +``` From d09b09b744ac65c649106add357ab69dac72ae40 Mon Sep 17 00:00:00 2001 From: Jessica Lord Date: Mon, 19 Oct 2015 16:37:18 -0700 Subject: [PATCH 234/738] Match the electron-quick-start repo --- docs/tutorial/quick-start.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index 5300d754a69b..9ad477d0c7f0 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -130,8 +130,9 @@ Finally the `index.html` is the web page you want to show:

Hello World!

- We are using Node.js - and Electron . + We are using node , + Chrome , + and Electron . ``` From 5a46147e9b3f8a7a8c7d07570891d9b9a2339d06 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 20 Oct 2015 10:34:33 +0800 Subject: [PATCH 235/738] Update brightray for atom/brightray#158 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index fe2dd437c9ef..c3c6c3b311be 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit fe2dd437c9ef7877bf9d454db8ae401965cd7cb0 +Subproject commit c3c6c3b311be326611a4018af9feadf6fb5e03e8 From 2c4a24d26b8b2353c13fb3bc1ccc963c1107d377 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 20 Oct 2015 13:00:28 +0800 Subject: [PATCH 236/738] Add ELECTRON_ENABLE_LOGGING env It is the same with --enable-logging. --- atom/app/atom_main_delegate.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 44f2048c091f..392e4dcb3601 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -59,7 +59,9 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { #endif // !defined(OS_WIN) // Only enable logging when --enable-logging is specified. - if (!command_line->HasSwitch(switches::kEnableLogging)) { + scoped_ptr env(base::Environment::Create()); + if (!command_line->HasSwitch(switches::kEnableLogging) && + !env->HasVar("ELECTRON_ENABLE_LOGGING")) { settings.logging_dest = logging::LOG_NONE; logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES); } From fb8ca33d5d88ff09713dd6dde65930a9051cb58a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 20 Oct 2015 13:02:48 +0800 Subject: [PATCH 237/738] Add ELECTRON_ENABLE_STACK_DUMPING env It enables in-process stack dumping, which is convenient for debugging. --- atom/app/atom_main_delegate.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 392e4dcb3601..e4ac7cfc0a99 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -71,10 +71,13 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { // Logging with pid and timestamp. logging::SetLogItems(true, false, true, false); -#if defined(DEBUG) && defined(OS_LINUX) // Enable convient stack printing. - base::debug::EnableInProcessStackDumping(); + bool enable_stack_dumping = env->HasVar("ELECTRON_ENABLE_STACK_DUMPING"); +#if defined(DEBUG) && defined(OS_LINUX) + enable_stack_dumping = true; #endif + if (enable_stack_dumping) + base::debug::EnableInProcessStackDumping(); return brightray::MainDelegate::BasicStartupComplete(exit_code); } From be36a17dbf6ce69a3341077d6c955c09c1244e57 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 20 Oct 2015 13:06:41 +0800 Subject: [PATCH 238/738] docs: Mention the ELECTRON_ENABLE_LOGGING env --- docs/api/chrome-command-line-switches.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index abf8726b684d..69e785f79e72 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -100,7 +100,9 @@ Specify comma-separated list of SSL cipher suites to disable. Prints Chromium's logging into console. -This switch can not be used in `app.commandLine.appendSwitch` since it is parsed earlier than user's app is loaded. +This switch can not be used in `app.commandLine.appendSwitch` since it is parsed +earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING` +environment variable to achieve the same effect. ## --v=`log_level` From 14e2bbe4c76f86b4e8b6822eaf463216cb3bdd8a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 20 Oct 2015 13:50:19 +0800 Subject: [PATCH 239/738] Update brightray for #3120 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index c3c6c3b311be..f1cbfd1d457f 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit c3c6c3b311be326611a4018af9feadf6fb5e03e8 +Subproject commit f1cbfd1d457f9b40bca23a2f30948a093d6048a9 From a7a399dcd8ba60ff7aaf4c5c8de14009de69657f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 20 Oct 2015 13:52:39 +0800 Subject: [PATCH 240/738] Code cleanup --- atom/browser/atom_browser_context.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index b0a9897352e1..6cfb160489fc 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -169,15 +169,12 @@ void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) { base::FilePath()); } - -bool AtomBrowserContext::AllowNTLMCredentialsForDomain - (const GURL& auth_origin) { - if (allow_ntlm_everywhere_) return true; - return brightray::URLRequestContextGetter - ::Delegate::AllowNTLMCredentialsForDomain(auth_origin); +bool AtomBrowserContext::AllowNTLMCredentialsForDomain(const GURL& origin) { + if (allow_ntlm_everywhere_) + return true; + return Delegate::AllowNTLMCredentialsForDomain(origin); } - void AtomBrowserContext::AllowNTLMCredentialsForAllDomains(bool should_allow) { allow_ntlm_everywhere_ = should_allow; } From c92889462789b540f6f3f583a10ddd80af8e95b7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 20 Oct 2015 13:56:31 +0800 Subject: [PATCH 241/738] docs: app.allowNTLMCredentialsForAllDomains --- docs/api/app.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/api/app.md b/docs/api/app.md index 0b5780aab7bf..bd49919ce79b 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -99,7 +99,7 @@ You should call `event.preventDefault()` if you want to handle this event. Returns: * `event` Event -* `hasVisibleWindows` Bool +* `hasVisibleWindows` Boolean Emitted when the application is activated, which usually happens when clicks on the applications's dock icon. @@ -280,6 +280,13 @@ Adds `tasks` to the [Tasks][tasks] category of the JumpList on Windows. consists of two or more icons, set this value to identify the icon. If an icon file consists of one icon, this value is 0. +### `app.allowNTLMCredentialsForAllDomains(allow)` + +* `allow` Boolean + +Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate +authentication. + ### `app.commandLine.appendSwitch(switch[, value])` Append a switch (with optional `value`) to Chromium's command line. From 7a0db35d914928c759667b99d2a8813dc3b00356 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 21 Oct 2015 00:25:24 +0900 Subject: [PATCH 242/738] Update as upstream --- README-ko.md | 4 ++++ docs-translations/ko-KR/api/app.md | 10 ++++++-- .../ko-KR/api/chrome-command-line-switches.md | 9 +++++-- .../ko-KR/tutorial/quick-start.md | 24 ++++++++++++++++--- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/README-ko.md b/README-ko.md index 4432c96f827d..c8a3e6c59fb7 100644 --- a/README-ko.md +++ b/README-ko.md @@ -47,6 +47,10 @@ Electron을 빌드 하는 방법과 프로젝트에 기여하는 방법도 문 - [중국어 간체](https://github.com/atom/electron/tree/master/docs-translations/zh-CN) - [중국어 번체](https://github.com/atom/electron/tree/master/docs-translations/zh-TW) +## 시작하기 + +[`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) 저장소를 클론하여 Electron을 간단히 접해볼 수 있습니다. + ## 커뮤니티 다음 링크를 통해 커뮤니티에 질문을 올리거나 토론을 나눌 수 있습니다: diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index 18354a70bd7a..c364d9dc606e 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -98,7 +98,7 @@ Returns: Returns: * `event` Event -* `hasVisibleWindows` Bool +* `hasVisibleWindows` Boolean 어플리케이션이 활성화 되었을 때 발생하는 이벤트 입니다. 이 이벤트는 어플리케이션의 dock 아이콘을 클릭했을 때 주로 발생합니다. @@ -277,7 +277,13 @@ Windows에서 사용할 수 있는 JumpList의 [Tasks][tasks] 카테고리에 `t 보통 어플리케이션의 아이콘을 그대로 사용하기 위해 `process.execPath`를 지정합니다. * `iconIndex` Integer - 아이콘 파일의 인덱스. 만약 아이콘 파일이 두 개 이상의 아이콘을 가지고 있을 경우, 사용할 아이콘의 인덱스를 이 옵션으로 지정해 주어야 합니다. 단, 아이콘을 하나만 포함하고 있는 경우 0을 지정하면 됩니다. - + +### `app.allowNTLMCredentialsForAllDomains(allow)` + +* `allow` Boolean + +항상 동적으로 HTTP NTLM 또는 Negotiate 인증에 자격 증명을 보낼 것인지 설정합니다. + ### `app.commandLine.appendSwitch(switch[, value])` Chrominum의 명령줄에 스위치를 추가합니다. `value`는 추가적인 값을 뜻하며 옵션입니다. diff --git a/docs-translations/ko-KR/api/chrome-command-line-switches.md b/docs-translations/ko-KR/api/chrome-command-line-switches.md index 41517e08cabb..c3ef6ee33b7a 100644 --- a/docs-translations/ko-KR/api/chrome-command-line-switches.md +++ b/docs-translations/ko-KR/api/chrome-command-line-switches.md @@ -44,7 +44,7 @@ HTTP 요청 캐시를 비활성화 합니다. ## --host-rules=`rules` -Hostname 맵핑 규칙을 설정합니다. (`,`로 분리) +Hostname 맵핑 규칙을 설정합니다. (`,`로 구분) 예시: @@ -86,11 +86,16 @@ Net log 이벤트를 활성화하고 `path`에 로그를 기록합니다. TLS fallback에서 사용할 SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", "tls1.2") +## --cipher-suite-blacklist=`cipher_suites` + +SSL 암호화를 비활성화할 대상 목록을 지정합니다. (`,`로 구분) + ## --enable-logging Chromium의 로그를 콘솔에 출력합니다. -이 스위치는 어플리케이션이 로드되기 전에 파싱 되므로 `app.commandLine.appendSwitch`에서 사용할 수 없습니다. +이 스위치는 어플리케이션이 로드되기 전에 인식 되므로 `app.commandLine.appendSwitch` 메서드에선 사용할 수 없습니다. +하지만 `ELECTRON_ENABLE_LOGGING` 환경 변수를 설정하면 본 스위치와 같은 효과를 낼 수 있습니다. ## --v=`log_level` diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 3a0c38f04b92..ce3c7e29e0e8 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -116,7 +116,8 @@ app.on('ready', function() {

헬로 월드!

- 이 어플리케이션은 Node.js 과 + 이 어플리케이션은 node , + Chrome , Electron 을 사용합니다. @@ -174,6 +175,23 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/ 어플리케이션 실행파일은 `Electron`의 release 패키지에 포함되어 있습니다. [여기](https://github.com/atom/electron/releases)에서 다운로드 받을 수 있습니다. -### 배포용 파일 만들기 +### 배포용 실행 파일 만들기 -어플리케이션 작성을 완료했다면 [어플리케이션 배포](application-distribution.md) 가이드를 통해 제작한 앱을 본격적으로 배포할 수 있습니다. \ No newline at end of file +어플리케이션 작성을 모두 끝냈다면 [어플리케이션 배포](application-distribution.md) 가이드를 통해 제작한 앱을 패키징하고 배포할 수 있습니다. + +### 미리 작성된 앱 실행하기 + +[`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) 저장소를 클론하면 이 가이드에서 작성한 예제 앱을 바로 실행해 볼 수 있습니다. + +**참고**: 이 예제를 실행시키려면 [Git](https://git-scm.com)과 [Node.js](https://nodejs.org/en/download/)가 필요합니다. (CLI에서 실행 가능한 [npm](https://npmjs.org)이 있어야 합니다) + +**역주**: `npm`은 보통 Node.js를 설치하면 자동으로 같이 설치됩니다. + +```bash +# 저장소를 클론합니다 +$ git clone https://github.com/atom/electron-quick-start +# 저장소 안으로 들어갑니다 +$ cd electron-quick-start +# 어플리케이션의 종속성 모듈을 설치한 후 실행합니다 +$ npm install && npm start +``` \ No newline at end of file From 1ad979f9bda5b7f1e7977ddf35319d58221b1fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionic=C4=83=20Biz=C4=83u?= Date: Tue, 20 Oct 2015 19:44:01 +0300 Subject: [PATCH 243/738] Add some missing words ("be" and "the") --- docs/api/app.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/app.md b/docs/api/app.md index bd49919ce79b..d59e0e40d053 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -169,7 +169,7 @@ The `app` object has the following methods: ### `app.quit()` -Try to close all windows. The `before-quit` event will emitted first. If all +Try to close all windows. The `before-quit` event will be emitted first. If all windows are successfully closed, the `will-quit` event will be emitted and by default the application will terminate. @@ -213,7 +213,7 @@ created by this method. On failure an `Error` is thrown. You can only override paths of a `name` defined in `app.getPath`. -By default, web pages's cookies and caches will be stored under the `userData` +By default, web pages' cookies and caches will be stored under the `userData` directory. If you want to change this location, you have to override the `userData` path before the `ready` event of the `app` module is emitted. @@ -264,7 +264,7 @@ Clears the recent documents list. Adds `tasks` to the [Tasks][tasks] category of the JumpList on Windows. -`tasks` is an array of `Task` objects in following format: +`tasks` is an array of `Task` objects in the following format: `Task` Object * `program` String - Path of the program to execute, usually you should From db3bc289379840b466517abb0f16a8d2e349073f Mon Sep 17 00:00:00 2001 From: Patrick Detlefsen Date: Tue, 20 Oct 2015 19:25:03 +0200 Subject: [PATCH 244/738] PR feedback adressed --- atom/browser/api/lib/auto-updater.coffee | 2 +- .../api/lib/auto-updater/auto-updater-win.coffee | 13 +++---------- .../api/lib/auto-updater/squirrel-update-win.coffee | 8 ++++---- filenames.gypi | 2 ++ 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/atom/browser/api/lib/auto-updater.coffee b/atom/browser/api/lib/auto-updater.coffee index a479f5fccfe5..c039bd12dc46 100644 --- a/atom/browser/api/lib/auto-updater.coffee +++ b/atom/browser/api/lib/auto-updater.coffee @@ -1,6 +1,6 @@ switch process.platform when 'win32' - autoUpdater = require('./auto-updater/auto-updater-win') + autoUpdater = require './auto-updater/auto-updater-win' else # take the default binding for the current platform autoUpdater = process.atomBinding('auto_updater').autoUpdater diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee index 9a2431577e0b..764f76a2253f 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee @@ -1,7 +1,7 @@ {EventEmitter} = require 'events' SquirrelUpdate = require './auto-updater/squirrel-update-win' -app = require('app') -url = require('url') +app = require 'app' +url = require 'url' class AutoUpdater extends EventEmitter @@ -12,14 +12,7 @@ class AutoUpdater extends EventEmitter setFeedUrl: (updateUrl) -> # set feed URL only when it hasn't been set before unless @updateUrl - # See https://github.com/Squirrel/Squirrel.Windows/issues/132 - # This way the Mac and Windows Update URL can be the same, even when - # the Mac version is sending additional data in the query string. - parsedUrl = url.parse(updateUrl) - delete parsedUrl.search - delete parsedUrl.query - - @updateUrl = url.format(parsedUrl) + @updateUrl = updateUrl checkForUpdates: -> throw new Error('Update URL is not set') unless @updateUrl diff --git a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee index f07584f4c54d..95d9e1465d8a 100644 --- a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee +++ b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee @@ -2,10 +2,10 @@ ChildProcess = require 'child_process' fs = require 'fs' path = require 'path' -appFolder = path.dirname(process.execPath) # i.e. my-app/app-0.1.13/ -rootApplicationFolder = path.resolve(appFolder, '..') # i.e. my-app/ -updateDotExe = path.join(rootApplicationFolder, 'Update.exe') -exeName = path.basename(process.execPath) +appFolder = path.dirname process.execPath # i.e. my-app/app-0.1.13/ +rootApplicationFolder = path.resolve appFolder, '..' # i.e. my-app/ +updateDotExe = path.join rootApplicationFolder, 'Update.exe' +exeName = path.basename process.execPath # Spawn a command and invoke the callback when it completes with an error # and the output from standard out. diff --git a/filenames.gypi b/filenames.gypi index ebd1fb41aaf2..35139dbdfcd5 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -11,6 +11,8 @@ 'atom/browser/api/lib/app.coffee', 'atom/browser/api/lib/atom-delegate.coffee', 'atom/browser/api/lib/auto-updater.coffee', + 'atom/browser/api/lib/auto-updater/auto-updater-win.coffee', + 'atom/browser/api/lib/auto-updater/squirrel-update-win.coffee', 'atom/browser/api/lib/browser-window.coffee', 'atom/browser/api/lib/content-tracing.coffee', 'atom/browser/api/lib/dialog.coffee', From da7161d5a7fcc3c7804eb22f51a705444d114f22 Mon Sep 17 00:00:00 2001 From: Nate Goldman Date: Tue, 20 Oct 2015 10:44:02 -0700 Subject: [PATCH 245/738] use webContents.openDevTools https://github.com/atom/electron/issues/3125#issuecomment-148975593 --- docs/tutorial/quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index 052da3d91be8..b023deccda52 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -107,7 +107,7 @@ app.on('ready', function() { mainWindow.loadUrl('file://' + __dirname + '/index.html'); // Open the DevTools. - mainWindow.openDevTools(); + mainWindow.webContents.openDevTools(); // Emitted when the window is closed. mainWindow.on('closed', function() { From 285a4789b30feaa905ac61a642e309a7408e3d2c Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 12:35:56 -0700 Subject: [PATCH 246/738] Update app.md --- docs/api/app.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/api/app.md b/docs/api/app.md index d59e0e40d053..41098d4279c9 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -285,7 +285,10 @@ Adds `tasks` to the [Tasks][tasks] category of the JumpList on Windows. * `allow` Boolean Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate -authentication. +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. ### `app.commandLine.appendSwitch(switch[, value])` From 27fa5d880a7183e61c954014d637be82128e40f0 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 11:16:51 -0700 Subject: [PATCH 247/738] Copy some relevant files over from Chromium --- atom/browser/process_singleton.h | 183 +++ atom/browser/process_singleton_posix.cc | 1062 +++++++++++++++++ .../browser/process_singleton_startup_lock.cc | 53 + atom/browser/process_singleton_startup_lock.h | 57 + atom/browser/process_singleton_win.cc | 441 +++++++ 5 files changed, 1796 insertions(+) create mode 100644 atom/browser/process_singleton.h create mode 100644 atom/browser/process_singleton_posix.cc create mode 100644 atom/browser/process_singleton_startup_lock.cc create mode 100644 atom/browser/process_singleton_startup_lock.h create mode 100644 atom/browser/process_singleton_win.cc diff --git a/atom/browser/process_singleton.h b/atom/browser/process_singleton.h new file mode 100644 index 000000000000..3260c4ef240c --- /dev/null +++ b/atom/browser/process_singleton.h @@ -0,0 +1,183 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PROCESS_SINGLETON_H_ +#define CHROME_BROWSER_PROCESS_SINGLETON_H_ + +#include "build/build_config.h" + +#if defined(OS_WIN) +#include +#endif // defined(OS_WIN) + +#include +#include + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/process/process.h" +#include "base/threading/non_thread_safe.h" +#include "ui/gfx/native_widget_types.h" + +#if defined(OS_POSIX) && !defined(OS_ANDROID) +#include "base/files/scoped_temp_dir.h" +#endif + +#if defined(OS_WIN) +#include "base/win/message_window.h" +#endif // defined(OS_WIN) + +namespace base { +class CommandLine; +} + +// ProcessSingleton ---------------------------------------------------------- +// +// This class allows different browser processes to communicate with +// each other. It is named according to the user data directory, so +// we can be sure that no more than one copy of the application can be +// running at once with a given data directory. +// +// Implementation notes: +// - the Windows implementation uses an invisible global message window; +// - the Linux implementation uses a Unix domain socket in the user data dir. + +class ProcessSingleton : public base::NonThreadSafe { + public: + enum NotifyResult { + PROCESS_NONE, + PROCESS_NOTIFIED, + PROFILE_IN_USE, + LOCK_ERROR, + }; + + // Implement this callback to handle notifications from other processes. The + // callback will receive the command line and directory with which the other + // Chrome process was launched. Return true if the command line will be + // handled within the current browser instance or false if the remote process + // should handle it (i.e., because the current process is shutting down). + using NotificationCallback = + base::Callback; + + ProcessSingleton(const base::FilePath& user_data_dir, + const NotificationCallback& notification_callback); + ~ProcessSingleton(); + + // Notify another process, if available. Otherwise sets ourselves as the + // singleton instance. Returns PROCESS_NONE if we became the singleton + // instance. Callers are guaranteed to either have notified an existing + // process or have grabbed the singleton (unless the profile is locked by an + // unreachable process). + // TODO(brettw): Make the implementation of this method non-platform-specific + // by making Linux re-use the Windows implementation. + NotifyResult NotifyOtherProcessOrCreate(); + + // Sets ourself up as the singleton instance. Returns true on success. If + // false is returned, we are not the singleton instance and the caller must + // exit. + // NOTE: Most callers should generally prefer NotifyOtherProcessOrCreate() to + // this method, only callers for whom failure is preferred to notifying + // another process should call this directly. + bool Create(); + + // Clear any lock state during shutdown. + void Cleanup(); + +#if defined(OS_POSIX) && !defined(OS_ANDROID) + static void DisablePromptForTesting(); +#endif +#if defined(OS_WIN) + // Called to query whether to kill a hung browser process that has visible + // windows. Return true to allow killing the hung process. + using ShouldKillRemoteProcessCallback = base::Callback; + void OverrideShouldKillRemoteProcessCallbackForTesting( + const ShouldKillRemoteProcessCallback& display_dialog_callback); +#endif + + protected: + // Notify another process, if available. + // Returns true if another process was found and notified, false if we should + // continue with the current process. + // On Windows, Create() has to be called before this. + NotifyResult NotifyOtherProcess(); + +#if defined(OS_POSIX) && !defined(OS_ANDROID) + // Exposed for testing. We use a timeout on Linux, and in tests we want + // this timeout to be short. + NotifyResult NotifyOtherProcessWithTimeout( + const base::CommandLine& command_line, + int retry_attempts, + const base::TimeDelta& timeout, + bool kill_unresponsive); + NotifyResult NotifyOtherProcessWithTimeoutOrCreate( + const base::CommandLine& command_line, + int retry_attempts, + const base::TimeDelta& timeout); + void OverrideCurrentPidForTesting(base::ProcessId pid); + void OverrideKillCallbackForTesting( + const base::Callback& callback); +#endif + + private: + NotificationCallback notification_callback_; // Handler for notifications. + +#if defined(OS_WIN) + bool EscapeVirtualization(const base::FilePath& user_data_dir); + + HWND remote_window_; // The HWND_MESSAGE of another browser. + base::win::MessageWindow window_; // The message-only window. + bool is_virtualized_; // Stuck inside Microsoft Softricity VM environment. + HANDLE lock_file_; + base::FilePath user_data_dir_; + ShouldKillRemoteProcessCallback should_kill_remote_process_callback_; +#elif defined(OS_POSIX) && !defined(OS_ANDROID) + // Return true if the given pid is one of our child processes. + // Assumes that the current pid is the root of all pids of the current + // instance. + bool IsSameChromeInstance(pid_t pid); + + // Extract the process's pid from a symbol link path and if it is on + // the same host, kill the process, unlink the lock file and return true. + // If the process is part of the same chrome instance, unlink the lock file + // and return true without killing it. + // If the process is on a different host, return false. + bool KillProcessByLockPath(); + + // Default function to kill a process, overridable by tests. + void KillProcess(int pid); + + // Allow overriding for tests. + base::ProcessId current_pid_; + + // Function to call when the other process is hung and needs to be killed. + // Allows overriding for tests. + base::Callback kill_callback_; + + // Path in file system to the socket. + base::FilePath socket_path_; + + // Path in file system to the lock. + base::FilePath lock_path_; + + // Path in file system to the cookie file. + base::FilePath cookie_path_; + + // Temporary directory to hold the socket. + base::ScopedTempDir socket_dir_; + + // Helper class for linux specific messages. LinuxWatcher is ref counted + // because it posts messages between threads. + class LinuxWatcher; + scoped_refptr watcher_; +#endif + + DISALLOW_COPY_AND_ASSIGN(ProcessSingleton); +}; + +#endif // CHROME_BROWSER_PROCESS_SINGLETON_H_ diff --git a/atom/browser/process_singleton_posix.cc b/atom/browser/process_singleton_posix.cc new file mode 100644 index 000000000000..81a5c5fec355 --- /dev/null +++ b/atom/browser/process_singleton_posix.cc @@ -0,0 +1,1062 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// On Linux, when the user tries to launch a second copy of chrome, we check +// for a socket in the user's profile directory. If the socket file is open we +// send a message to the first chrome browser process with the current +// directory and second process command line flags. The second process then +// exits. +// +// Because many networked filesystem implementations do not support unix domain +// sockets, we create the socket in a temporary directory and create a symlink +// in the profile. This temporary directory is no longer bound to the profile, +// and may disappear across a reboot or login to a separate session. To bind +// them, we store a unique cookie in the profile directory, which must also be +// present in the remote directory to connect. The cookie is checked both before +// and after the connection. /tmp is sticky, and different Chrome sessions use +// different cookies. Thus, a matching cookie before and after means the +// connection was to a directory with a valid cookie. +// +// We also have a lock file, which is a symlink to a non-existent destination. +// The destination is a string containing the hostname and process id of +// chrome's browser process, eg. "SingletonLock -> example.com-9156". When the +// first copy of chrome exits it will delete the lock file on shutdown, so that +// a different instance on a different host may then use the profile directory. +// +// If writing to the socket fails, the hostname in the lock is checked to see if +// another instance is running a different host using a shared filesystem (nfs, +// etc.) If the hostname differs an error is displayed and the second process +// exits. Otherwise the first process (if any) is killed and the second process +// starts as normal. +// +// When the second process sends the current directory and command line flags to +// the first process, it waits for an ACK message back from the first process +// for a certain time. If there is no ACK message back in time, then the first +// process will be considered as hung for some reason. The second process then +// retrieves the process id from the symbol link and kills it by sending +// SIGKILL. Then the second process starts as normal. + +#include "chrome/browser/process_singleton.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "base/base_paths.h" +#include "base/basictypes.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/path_service.h" +#include "base/posix/eintr_wrapper.h" +#include "base/posix/safe_strerror.h" +#include "base/rand_util.h" +#include "base/sequenced_task_runner_helpers.h" +#include "base/single_thread_task_runner.h" +#include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/threading/platform_thread.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/grit/chromium_strings.h" +#include "chrome/grit/generated_resources.h" +#include "content/public/browser/browser_thread.h" +#include "net/base/net_util.h" +#include "ui/base/l10n/l10n_util.h" + +#if defined(OS_LINUX) +#include "chrome/browser/ui/process_singleton_dialog_linux.h" +#endif + +#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) +#include "ui/views/linux_ui/linux_ui.h" +#endif + +using content::BrowserThread; + +namespace { + +// Timeout for the current browser process to respond. 20 seconds should be +// enough. +const int kTimeoutInSeconds = 20; +// Number of retries to notify the browser. 20 retries over 20 seconds = 1 try +// per second. +const int kRetryAttempts = 20; +static bool g_disable_prompt; +const char kStartToken[] = "START"; +const char kACKToken[] = "ACK"; +const char kShutdownToken[] = "SHUTDOWN"; +const char kTokenDelimiter = '\0'; +const int kMaxMessageLength = 32 * 1024; +const int kMaxACKMessageLength = arraysize(kShutdownToken) - 1; + +const char kLockDelimiter = '-'; + +// Set the close-on-exec bit on a file descriptor. +// Returns 0 on success, -1 on failure. +int SetCloseOnExec(int fd) { + int flags = fcntl(fd, F_GETFD, 0); + if (-1 == flags) + return flags; + if (flags & FD_CLOEXEC) + return 0; + return fcntl(fd, F_SETFD, flags | FD_CLOEXEC); +} + +// Close a socket and check return value. +void CloseSocket(int fd) { + int rv = IGNORE_EINTR(close(fd)); + DCHECK_EQ(0, rv) << "Error closing socket: " << base::safe_strerror(errno); +} + +// Write a message to a socket fd. +bool WriteToSocket(int fd, const char *message, size_t length) { + DCHECK(message); + DCHECK(length); + size_t bytes_written = 0; + do { + ssize_t rv = HANDLE_EINTR( + write(fd, message + bytes_written, length - bytes_written)); + if (rv < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // The socket shouldn't block, we're sending so little data. Just give + // up here, since NotifyOtherProcess() doesn't have an asynchronous api. + LOG(ERROR) << "ProcessSingleton would block on write(), so it gave up."; + return false; + } + PLOG(ERROR) << "write() failed"; + return false; + } + bytes_written += rv; + } while (bytes_written < length); + + return true; +} + +struct timeval TimeDeltaToTimeVal(const base::TimeDelta& delta) { + struct timeval result; + result.tv_sec = delta.InSeconds(); + result.tv_usec = delta.InMicroseconds() % base::Time::kMicrosecondsPerSecond; + return result; +} + +// Wait a socket for read for a certain timeout. +// Returns -1 if error occurred, 0 if timeout reached, > 0 if the socket is +// ready for read. +int WaitSocketForRead(int fd, const base::TimeDelta& timeout) { + fd_set read_fds; + struct timeval tv = TimeDeltaToTimeVal(timeout); + + FD_ZERO(&read_fds); + FD_SET(fd, &read_fds); + + return HANDLE_EINTR(select(fd + 1, &read_fds, NULL, NULL, &tv)); +} + +// Read a message from a socket fd, with an optional timeout. +// If |timeout| <= 0 then read immediately. +// Return number of bytes actually read, or -1 on error. +ssize_t ReadFromSocket(int fd, + char* buf, + size_t bufsize, + const base::TimeDelta& timeout) { + if (timeout > base::TimeDelta()) { + int rv = WaitSocketForRead(fd, timeout); + if (rv <= 0) + return rv; + } + + size_t bytes_read = 0; + do { + ssize_t rv = HANDLE_EINTR(read(fd, buf + bytes_read, bufsize - bytes_read)); + if (rv < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + PLOG(ERROR) << "read() failed"; + return rv; + } else { + // It would block, so we just return what has been read. + return bytes_read; + } + } else if (!rv) { + // No more data to read. + return bytes_read; + } else { + bytes_read += rv; + } + } while (bytes_read < bufsize); + + return bytes_read; +} + +// Set up a sockaddr appropriate for messaging. +void SetupSockAddr(const std::string& path, struct sockaddr_un* addr) { + addr->sun_family = AF_UNIX; + CHECK(path.length() < arraysize(addr->sun_path)) + << "Socket path too long: " << path; + base::strlcpy(addr->sun_path, path.c_str(), arraysize(addr->sun_path)); +} + +// Set up a socket appropriate for messaging. +int SetupSocketOnly() { + int sock = socket(PF_UNIX, SOCK_STREAM, 0); + PCHECK(sock >= 0) << "socket() failed"; + + int rv = net::SetNonBlocking(sock); + DCHECK_EQ(0, rv) << "Failed to make non-blocking socket."; + rv = SetCloseOnExec(sock); + DCHECK_EQ(0, rv) << "Failed to set CLOEXEC on socket."; + + return sock; +} + +// Set up a socket and sockaddr appropriate for messaging. +void SetupSocket(const std::string& path, int* sock, struct sockaddr_un* addr) { + *sock = SetupSocketOnly(); + SetupSockAddr(path, addr); +} + +// Read a symbolic link, return empty string if given path is not a symbol link. +base::FilePath ReadLink(const base::FilePath& path) { + base::FilePath target; + if (!base::ReadSymbolicLink(path, &target)) { + // The only errno that should occur is ENOENT. + if (errno != 0 && errno != ENOENT) + PLOG(ERROR) << "readlink(" << path.value() << ") failed"; + } + return target; +} + +// Unlink a path. Return true on success. +bool UnlinkPath(const base::FilePath& path) { + int rv = unlink(path.value().c_str()); + if (rv < 0 && errno != ENOENT) + PLOG(ERROR) << "Failed to unlink " << path.value(); + + return rv == 0; +} + +// Create a symlink. Returns true on success. +bool SymlinkPath(const base::FilePath& target, const base::FilePath& path) { + if (!base::CreateSymbolicLink(target, path)) { + // Double check the value in case symlink suceeded but we got an incorrect + // failure due to NFS packet loss & retry. + int saved_errno = errno; + if (ReadLink(path) != target) { + // If we failed to create the lock, most likely another instance won the + // startup race. + errno = saved_errno; + PLOG(ERROR) << "Failed to create " << path.value(); + return false; + } + } + return true; +} + +// Extract the hostname and pid from the lock symlink. +// Returns true if the lock existed. +bool ParseLockPath(const base::FilePath& path, + std::string* hostname, + int* pid) { + std::string real_path = ReadLink(path).value(); + if (real_path.empty()) + return false; + + std::string::size_type pos = real_path.rfind(kLockDelimiter); + + // If the path is not a symbolic link, or doesn't contain what we expect, + // bail. + if (pos == std::string::npos) { + *hostname = ""; + *pid = -1; + return true; + } + + *hostname = real_path.substr(0, pos); + + const std::string& pid_str = real_path.substr(pos + 1); + if (!base::StringToInt(pid_str, pid)) + *pid = -1; + + return true; +} + +// Returns true if the user opted to unlock the profile. +bool DisplayProfileInUseError(const base::FilePath& lock_path, + const std::string& hostname, + int pid) { + base::string16 error = l10n_util::GetStringFUTF16( + IDS_PROFILE_IN_USE_POSIX, + base::IntToString16(pid), + base::ASCIIToUTF16(hostname)); + LOG(ERROR) << error; + + if (g_disable_prompt) + return false; + +#if defined(OS_LINUX) + base::string16 relaunch_button_text = l10n_util::GetStringUTF16( + IDS_PROFILE_IN_USE_LINUX_RELAUNCH); + return ShowProcessSingletonDialog(error, relaunch_button_text); +#elif defined(OS_MACOSX) + // On Mac, always usurp the lock. + return true; +#endif + + NOTREACHED(); + return false; +} + +bool IsChromeProcess(pid_t pid) { + base::FilePath other_chrome_path(base::GetProcessExecutablePath(pid)); + return (!other_chrome_path.empty() && + other_chrome_path.BaseName() == + base::FilePath(chrome::kBrowserProcessExecutableName)); +} + +// A helper class to hold onto a socket. +class ScopedSocket { + public: + ScopedSocket() : fd_(-1) { Reset(); } + ~ScopedSocket() { Close(); } + int fd() { return fd_; } + void Reset() { + Close(); + fd_ = SetupSocketOnly(); + } + void Close() { + if (fd_ >= 0) + CloseSocket(fd_); + fd_ = -1; + } + private: + int fd_; +}; + +// Returns a random string for uniquifying profile connections. +std::string GenerateCookie() { + return base::Uint64ToString(base::RandUint64()); +} + +bool CheckCookie(const base::FilePath& path, const base::FilePath& cookie) { + return (cookie == ReadLink(path)); +} + +bool ConnectSocket(ScopedSocket* socket, + const base::FilePath& socket_path, + const base::FilePath& cookie_path) { + base::FilePath socket_target; + if (base::ReadSymbolicLink(socket_path, &socket_target)) { + // It's a symlink. Read the cookie. + base::FilePath cookie = ReadLink(cookie_path); + if (cookie.empty()) + return false; + base::FilePath remote_cookie = socket_target.DirName(). + Append(chrome::kSingletonCookieFilename); + // Verify the cookie before connecting. + if (!CheckCookie(remote_cookie, cookie)) + return false; + // Now we know the directory was (at that point) created by the profile + // owner. Try to connect. + sockaddr_un addr; + SetupSockAddr(socket_target.value(), &addr); + int ret = HANDLE_EINTR(connect(socket->fd(), + reinterpret_cast(&addr), + sizeof(addr))); + if (ret != 0) + return false; + // Check the cookie again. We only link in /tmp, which is sticky, so, if the + // directory is still correct, it must have been correct in-between when we + // connected. POSIX, sadly, lacks a connectat(). + if (!CheckCookie(remote_cookie, cookie)) { + socket->Reset(); + return false; + } + // Success! + return true; + } else if (errno == EINVAL) { + // It exists, but is not a symlink (or some other error we detect + // later). Just connect to it directly; this is an older version of Chrome. + sockaddr_un addr; + SetupSockAddr(socket_path.value(), &addr); + int ret = HANDLE_EINTR(connect(socket->fd(), + reinterpret_cast(&addr), + sizeof(addr))); + return (ret == 0); + } else { + // File is missing, or other error. + if (errno != ENOENT) + PLOG(ERROR) << "readlink failed"; + return false; + } +} + +#if defined(OS_MACOSX) +bool ReplaceOldSingletonLock(const base::FilePath& symlink_content, + const base::FilePath& lock_path) { + // Try taking an flock(2) on the file. Failure means the lock is taken so we + // should quit. + base::ScopedFD lock_fd(HANDLE_EINTR( + open(lock_path.value().c_str(), O_RDWR | O_CREAT | O_SYMLINK, 0644))); + if (!lock_fd.is_valid()) { + PLOG(ERROR) << "Could not open singleton lock"; + return false; + } + + int rc = HANDLE_EINTR(flock(lock_fd.get(), LOCK_EX | LOCK_NB)); + if (rc == -1) { + if (errno == EWOULDBLOCK) { + LOG(ERROR) << "Singleton lock held by old process."; + } else { + PLOG(ERROR) << "Error locking singleton lock"; + } + return false; + } + + // Successfully taking the lock means we can replace it with the a new symlink + // lock. We never flock() the lock file from now on. I.e. we assume that an + // old version of Chrome will not run with the same user data dir after this + // version has run. + if (!base::DeleteFile(lock_path, false)) { + PLOG(ERROR) << "Could not delete old singleton lock."; + return false; + } + + return SymlinkPath(symlink_content, lock_path); +} +#endif // defined(OS_MACOSX) + +} // namespace + +/////////////////////////////////////////////////////////////////////////////// +// ProcessSingleton::LinuxWatcher +// A helper class for a Linux specific implementation of the process singleton. +// This class sets up a listener on the singleton socket and handles parsing +// messages that come in on the singleton socket. +class ProcessSingleton::LinuxWatcher + : public base::MessageLoopForIO::Watcher, + public base::MessageLoop::DestructionObserver, + public base::RefCountedThreadSafe { + public: + // A helper class to read message from an established socket. + class SocketReader : public base::MessageLoopForIO::Watcher { + public: + SocketReader(ProcessSingleton::LinuxWatcher* parent, + base::MessageLoop* ui_message_loop, + int fd) + : parent_(parent), + ui_message_loop_(ui_message_loop), + fd_(fd), + bytes_read_(0) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + // Wait for reads. + base::MessageLoopForIO::current()->WatchFileDescriptor( + fd, true, base::MessageLoopForIO::WATCH_READ, &fd_reader_, this); + // If we haven't completed in a reasonable amount of time, give up. + timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kTimeoutInSeconds), + this, &SocketReader::CleanupAndDeleteSelf); + } + + ~SocketReader() override { CloseSocket(fd_); } + + // MessageLoopForIO::Watcher impl. + void OnFileCanReadWithoutBlocking(int fd) override; + void OnFileCanWriteWithoutBlocking(int fd) override { + // SocketReader only watches for accept (read) events. + NOTREACHED(); + } + + // Finish handling the incoming message by optionally sending back an ACK + // message and removing this SocketReader. + void FinishWithACK(const char *message, size_t length); + + private: + void CleanupAndDeleteSelf() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + parent_->RemoveSocketReader(this); + // We're deleted beyond this point. + } + + base::MessageLoopForIO::FileDescriptorWatcher fd_reader_; + + // The ProcessSingleton::LinuxWatcher that owns us. + ProcessSingleton::LinuxWatcher* const parent_; + + // A reference to the UI message loop. + base::MessageLoop* const ui_message_loop_; + + // The file descriptor we're reading. + const int fd_; + + // Store the message in this buffer. + char buf_[kMaxMessageLength]; + + // Tracks the number of bytes we've read in case we're getting partial + // reads. + size_t bytes_read_; + + base::OneShotTimer timer_; + + DISALLOW_COPY_AND_ASSIGN(SocketReader); + }; + + // We expect to only be constructed on the UI thread. + explicit LinuxWatcher(ProcessSingleton* parent) + : ui_message_loop_(base::MessageLoop::current()), + parent_(parent) { + } + + // Start listening for connections on the socket. This method should be + // called from the IO thread. + void StartListening(int socket); + + // This method determines if we should use the same process and if we should, + // opens a new browser tab. This runs on the UI thread. + // |reader| is for sending back ACK message. + void HandleMessage(const std::string& current_dir, + const std::vector& argv, + SocketReader* reader); + + // MessageLoopForIO::Watcher impl. These run on the IO thread. + void OnFileCanReadWithoutBlocking(int fd) override; + void OnFileCanWriteWithoutBlocking(int fd) override { + // ProcessSingleton only watches for accept (read) events. + NOTREACHED(); + } + + // MessageLoop::DestructionObserver + void WillDestroyCurrentMessageLoop() override { + fd_watcher_.StopWatchingFileDescriptor(); + } + + private: + friend struct BrowserThread::DeleteOnThread; + friend class base::DeleteHelper; + + ~LinuxWatcher() override { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + STLDeleteElements(&readers_); + + base::MessageLoopForIO* ml = base::MessageLoopForIO::current(); + ml->RemoveDestructionObserver(this); + } + + // Removes and deletes the SocketReader. + void RemoveSocketReader(SocketReader* reader); + + base::MessageLoopForIO::FileDescriptorWatcher fd_watcher_; + + // A reference to the UI message loop (i.e., the message loop we were + // constructed on). + base::MessageLoop* ui_message_loop_; + + // The ProcessSingleton that owns us. + ProcessSingleton* const parent_; + + std::set readers_; + + DISALLOW_COPY_AND_ASSIGN(LinuxWatcher); +}; + +void ProcessSingleton::LinuxWatcher::OnFileCanReadWithoutBlocking(int fd) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + // Accepting incoming client. + sockaddr_un from; + socklen_t from_len = sizeof(from); + int connection_socket = HANDLE_EINTR(accept( + fd, reinterpret_cast(&from), &from_len)); + if (-1 == connection_socket) { + PLOG(ERROR) << "accept() failed"; + return; + } + int rv = net::SetNonBlocking(connection_socket); + DCHECK_EQ(0, rv) << "Failed to make non-blocking socket."; + SocketReader* reader = new SocketReader(this, + ui_message_loop_, + connection_socket); + readers_.insert(reader); +} + +void ProcessSingleton::LinuxWatcher::StartListening(int socket) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + // Watch for client connections on this socket. + base::MessageLoopForIO* ml = base::MessageLoopForIO::current(); + ml->AddDestructionObserver(this); + ml->WatchFileDescriptor(socket, true, base::MessageLoopForIO::WATCH_READ, + &fd_watcher_, this); +} + +void ProcessSingleton::LinuxWatcher::HandleMessage( + const std::string& current_dir, const std::vector& argv, + SocketReader* reader) { + DCHECK(ui_message_loop_ == base::MessageLoop::current()); + DCHECK(reader); + + if (parent_->notification_callback_.Run(base::CommandLine(argv), + base::FilePath(current_dir))) { + // Send back "ACK" message to prevent the client process from starting up. + reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1); + } else { + LOG(WARNING) << "Not handling interprocess notification as browser" + " is shutting down"; + // Send back "SHUTDOWN" message, so that the client process can start up + // without killing this process. + reader->FinishWithACK(kShutdownToken, arraysize(kShutdownToken) - 1); + return; + } +} + +void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(reader); + readers_.erase(reader); + delete reader; +} + +/////////////////////////////////////////////////////////////////////////////// +// ProcessSingleton::LinuxWatcher::SocketReader +// + +void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking( + int fd) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_EQ(fd, fd_); + while (bytes_read_ < sizeof(buf_)) { + ssize_t rv = HANDLE_EINTR( + read(fd, buf_ + bytes_read_, sizeof(buf_) - bytes_read_)); + if (rv < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + PLOG(ERROR) << "read() failed"; + CloseSocket(fd); + return; + } else { + // It would block, so we just return and continue to watch for the next + // opportunity to read. + return; + } + } else if (!rv) { + // No more data to read. It's time to process the message. + break; + } else { + bytes_read_ += rv; + } + } + + // Validate the message. The shortest message is kStartToken\0x\0x + const size_t kMinMessageLength = arraysize(kStartToken) + 4; + if (bytes_read_ < kMinMessageLength) { + buf_[bytes_read_] = 0; + LOG(ERROR) << "Invalid socket message (wrong length):" << buf_; + CleanupAndDeleteSelf(); + return; + } + + std::string str(buf_, bytes_read_); + std::vector tokens = base::SplitString( + str, std::string(1, kTokenDelimiter), + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + + if (tokens.size() < 3 || tokens[0] != kStartToken) { + LOG(ERROR) << "Wrong message format: " << str; + CleanupAndDeleteSelf(); + return; + } + + // Stop the expiration timer to prevent this SocketReader object from being + // terminated unexpectly. + timer_.Stop(); + + std::string current_dir = tokens[1]; + // Remove the first two tokens. The remaining tokens should be the command + // line argv array. + tokens.erase(tokens.begin()); + tokens.erase(tokens.begin()); + + // Return to the UI thread to handle opening a new browser tab. + ui_message_loop_->task_runner()->PostTask( + FROM_HERE, base::Bind(&ProcessSingleton::LinuxWatcher::HandleMessage, + parent_, current_dir, tokens, this)); + fd_reader_.StopWatchingFileDescriptor(); + + // LinuxWatcher::HandleMessage() is in charge of destroying this SocketReader + // object by invoking SocketReader::FinishWithACK(). +} + +void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK( + const char *message, size_t length) { + if (message && length) { + // Not necessary to care about the return value. + WriteToSocket(fd_, message, length); + } + + if (shutdown(fd_, SHUT_WR) < 0) + PLOG(ERROR) << "shutdown() failed"; + + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&ProcessSingleton::LinuxWatcher::RemoveSocketReader, + parent_, + this)); + // We will be deleted once the posted RemoveSocketReader task runs. +} + +/////////////////////////////////////////////////////////////////////////////// +// ProcessSingleton +// +ProcessSingleton::ProcessSingleton( + const base::FilePath& user_data_dir, + const NotificationCallback& notification_callback) + : notification_callback_(notification_callback), + current_pid_(base::GetCurrentProcId()), + watcher_(new LinuxWatcher(this)) { + socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename); + lock_path_ = user_data_dir.Append(chrome::kSingletonLockFilename); + cookie_path_ = user_data_dir.Append(chrome::kSingletonCookieFilename); + + kill_callback_ = base::Bind(&ProcessSingleton::KillProcess, + base::Unretained(this)); +} + +ProcessSingleton::~ProcessSingleton() { +} + +ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { + return NotifyOtherProcessWithTimeout( + *base::CommandLine::ForCurrentProcess(), kRetryAttempts, + base::TimeDelta::FromSeconds(kTimeoutInSeconds), true); +} + +ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( + const base::CommandLine& cmd_line, + int retry_attempts, + const base::TimeDelta& timeout, + bool kill_unresponsive) { + DCHECK_GE(retry_attempts, 0); + DCHECK_GE(timeout.InMicroseconds(), 0); + + base::TimeDelta sleep_interval = timeout / retry_attempts; + + ScopedSocket socket; + for (int retries = 0; retries <= retry_attempts; ++retries) { + // Try to connect to the socket. + if (ConnectSocket(&socket, socket_path_, cookie_path_)) + break; + + // If we're in a race with another process, they may be in Create() and have + // created the lock but not attached to the socket. So we check if the + // process with the pid from the lockfile is currently running and is a + // chrome browser. If so, we loop and try again for |timeout|. + + std::string hostname; + int pid; + if (!ParseLockPath(lock_path_, &hostname, &pid)) { + // No lockfile exists. + return PROCESS_NONE; + } + + if (hostname.empty()) { + // Invalid lockfile. + UnlinkPath(lock_path_); + return PROCESS_NONE; + } + + if (hostname != net::GetHostName() && !IsChromeProcess(pid)) { + // Locked by process on another host. If the user selected to unlock + // the profile, try to continue; otherwise quit. + if (DisplayProfileInUseError(lock_path_, hostname, pid)) { + UnlinkPath(lock_path_); + return PROCESS_NONE; + } + return PROFILE_IN_USE; + } + + if (!IsChromeProcess(pid)) { + // Orphaned lockfile (no process with pid, or non-chrome process.) + UnlinkPath(lock_path_); + return PROCESS_NONE; + } + + if (IsSameChromeInstance(pid)) { + // Orphaned lockfile (pid is part of same chrome instance we are, even + // though we haven't tried to create a lockfile yet). + UnlinkPath(lock_path_); + return PROCESS_NONE; + } + + if (retries == retry_attempts) { + // Retries failed. Kill the unresponsive chrome process and continue. + if (!kill_unresponsive || !KillProcessByLockPath()) + return PROFILE_IN_USE; + return PROCESS_NONE; + } + + base::PlatformThread::Sleep(sleep_interval); + } + + timeval socket_timeout = TimeDeltaToTimeVal(timeout); + setsockopt(socket.fd(), + SOL_SOCKET, + SO_SNDTIMEO, + &socket_timeout, + sizeof(socket_timeout)); + + // Found another process, prepare our command line + // format is "START\0\0\0...\0". + std::string to_send(kStartToken); + to_send.push_back(kTokenDelimiter); + + base::FilePath current_dir; + if (!PathService::Get(base::DIR_CURRENT, ¤t_dir)) + return PROCESS_NONE; + to_send.append(current_dir.value()); + + const std::vector& argv = cmd_line.argv(); + for (std::vector::const_iterator it = argv.begin(); + it != argv.end(); ++it) { + to_send.push_back(kTokenDelimiter); + to_send.append(*it); + } + + // Send the message + if (!WriteToSocket(socket.fd(), to_send.data(), to_send.length())) { + // Try to kill the other process, because it might have been dead. + if (!kill_unresponsive || !KillProcessByLockPath()) + return PROFILE_IN_USE; + return PROCESS_NONE; + } + + if (shutdown(socket.fd(), SHUT_WR) < 0) + PLOG(ERROR) << "shutdown() failed"; + + // Read ACK message from the other process. It might be blocked for a certain + // timeout, to make sure the other process has enough time to return ACK. + char buf[kMaxACKMessageLength + 1]; + ssize_t len = ReadFromSocket(socket.fd(), buf, kMaxACKMessageLength, timeout); + + // Failed to read ACK, the other process might have been frozen. + if (len <= 0) { + if (!kill_unresponsive || !KillProcessByLockPath()) + return PROFILE_IN_USE; + return PROCESS_NONE; + } + + buf[len] = '\0'; + if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) { + // The other process is shutting down, it's safe to start a new process. + return PROCESS_NONE; + } else if (strncmp(buf, kACKToken, arraysize(kACKToken) - 1) == 0) { +#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) + // Likely NULL in unit tests. + views::LinuxUI* linux_ui = views::LinuxUI::instance(); + if (linux_ui) + linux_ui->NotifyWindowManagerStartupComplete(); +#endif + + // Assume the other process is handling the request. + return PROCESS_NOTIFIED; + } + + NOTREACHED() << "The other process returned unknown message: " << buf; + return PROCESS_NOTIFIED; +} + +ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate() { + return NotifyOtherProcessWithTimeoutOrCreate( + *base::CommandLine::ForCurrentProcess(), kRetryAttempts, + base::TimeDelta::FromSeconds(kTimeoutInSeconds)); +} + +ProcessSingleton::NotifyResult +ProcessSingleton::NotifyOtherProcessWithTimeoutOrCreate( + const base::CommandLine& command_line, + int retry_attempts, + const base::TimeDelta& timeout) { + NotifyResult result = NotifyOtherProcessWithTimeout( + command_line, retry_attempts, timeout, true); + if (result != PROCESS_NONE) + return result; + if (Create()) + return PROCESS_NONE; + // If the Create() failed, try again to notify. (It could be that another + // instance was starting at the same time and managed to grab the lock before + // we did.) + // This time, we don't want to kill anything if we aren't successful, since we + // aren't going to try to take over the lock ourselves. + result = NotifyOtherProcessWithTimeout( + command_line, retry_attempts, timeout, false); + if (result != PROCESS_NONE) + return result; + + return LOCK_ERROR; +} + +void ProcessSingleton::OverrideCurrentPidForTesting(base::ProcessId pid) { + current_pid_ = pid; +} + +void ProcessSingleton::OverrideKillCallbackForTesting( + const base::Callback& callback) { + kill_callback_ = callback; +} + +void ProcessSingleton::DisablePromptForTesting() { + g_disable_prompt = true; +} + +bool ProcessSingleton::Create() { + int sock; + sockaddr_un addr; + + // The symlink lock is pointed to the hostname and process id, so other + // processes can find it out. + base::FilePath symlink_content(base::StringPrintf( + "%s%c%u", + net::GetHostName().c_str(), + kLockDelimiter, + current_pid_)); + + // Create symbol link before binding the socket, to ensure only one instance + // can have the socket open. + if (!SymlinkPath(symlink_content, lock_path_)) { + // TODO(jackhou): Remove this case once this code is stable on Mac. + // http://crbug.com/367612 +#if defined(OS_MACOSX) + // On Mac, an existing non-symlink lock file means the lock could be held by + // the old process singleton code. If we can successfully replace the lock, + // continue as normal. + if (base::IsLink(lock_path_) || + !ReplaceOldSingletonLock(symlink_content, lock_path_)) { + return false; + } +#else + // If we failed to create the lock, most likely another instance won the + // startup race. + return false; +#endif + } + + // Create the socket file somewhere in /tmp which is usually mounted as a + // normal filesystem. Some network filesystems (notably AFS) are screwy and + // do not support Unix domain sockets. + if (!socket_dir_.CreateUniqueTempDir()) { + LOG(ERROR) << "Failed to create socket directory."; + return false; + } + + // Check that the directory was created with the correct permissions. + int dir_mode = 0; + CHECK(base::GetPosixFilePermissions(socket_dir_.path(), &dir_mode) && + dir_mode == base::FILE_PERMISSION_USER_MASK) + << "Temp directory mode is not 700: " << std::oct << dir_mode; + + // Setup the socket symlink and the two cookies. + base::FilePath socket_target_path = + socket_dir_.path().Append(chrome::kSingletonSocketFilename); + base::FilePath cookie(GenerateCookie()); + base::FilePath remote_cookie_path = + socket_dir_.path().Append(chrome::kSingletonCookieFilename); + UnlinkPath(socket_path_); + UnlinkPath(cookie_path_); + if (!SymlinkPath(socket_target_path, socket_path_) || + !SymlinkPath(cookie, cookie_path_) || + !SymlinkPath(cookie, remote_cookie_path)) { + // We've already locked things, so we can't have lost the startup race, + // but something doesn't like us. + LOG(ERROR) << "Failed to create symlinks."; + if (!socket_dir_.Delete()) + LOG(ERROR) << "Encountered a problem when deleting socket directory."; + return false; + } + + SetupSocket(socket_target_path.value(), &sock, &addr); + + if (bind(sock, reinterpret_cast(&addr), sizeof(addr)) < 0) { + PLOG(ERROR) << "Failed to bind() " << socket_target_path.value(); + CloseSocket(sock); + return false; + } + + if (listen(sock, 5) < 0) + NOTREACHED() << "listen failed: " << base::safe_strerror(errno); + + DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO)); + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&ProcessSingleton::LinuxWatcher::StartListening, + watcher_.get(), + sock)); + + return true; +} + +void ProcessSingleton::Cleanup() { + UnlinkPath(socket_path_); + UnlinkPath(cookie_path_); + UnlinkPath(lock_path_); +} + +bool ProcessSingleton::IsSameChromeInstance(pid_t pid) { + pid_t cur_pid = current_pid_; + while (pid != cur_pid) { + pid = base::GetParentProcessId(pid); + if (pid < 0) + return false; + if (!IsChromeProcess(pid)) + return false; + } + return true; +} + +bool ProcessSingleton::KillProcessByLockPath() { + std::string hostname; + int pid; + ParseLockPath(lock_path_, &hostname, &pid); + + if (!hostname.empty() && hostname != net::GetHostName()) { + return DisplayProfileInUseError(lock_path_, hostname, pid); + } + UnlinkPath(lock_path_); + + if (IsSameChromeInstance(pid)) + return true; + + if (pid > 0) { + kill_callback_.Run(pid); + return true; + } + + LOG(ERROR) << "Failed to extract pid from path: " << lock_path_.value(); + return true; +} + +void ProcessSingleton::KillProcess(int pid) { + // TODO(james.su@gmail.com): Is SIGKILL ok? + int rv = kill(static_cast(pid), SIGKILL); + // ESRCH = No Such Process (can happen if the other process is already in + // progress of shutting down and finishes before we try to kill it). + DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " + << base::safe_strerror(errno); +} diff --git a/atom/browser/process_singleton_startup_lock.cc b/atom/browser/process_singleton_startup_lock.cc new file mode 100644 index 000000000000..f564de7dca4d --- /dev/null +++ b/atom/browser/process_singleton_startup_lock.cc @@ -0,0 +1,53 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/process_singleton_startup_lock.h" + +#include "base/bind.h" +#include "base/logging.h" + +ProcessSingletonStartupLock::ProcessSingletonStartupLock( + const ProcessSingleton::NotificationCallback& original_callback) + : locked_(true), + original_callback_(original_callback) {} + +ProcessSingletonStartupLock::~ProcessSingletonStartupLock() {} + +ProcessSingleton::NotificationCallback +ProcessSingletonStartupLock::AsNotificationCallback() { + return base::Bind(&ProcessSingletonStartupLock::NotificationCallbackImpl, + base::Unretained(this)); +} + +void ProcessSingletonStartupLock::Unlock() { + DCHECK(CalledOnValidThread()); + locked_ = false; + + // Replay the command lines of the messages which were received while the + // ProcessSingleton was locked. Only replay each message once. + std::set replayed_messages; + for (std::vector::const_iterator it = + saved_startup_messages_.begin(); + it != saved_startup_messages_.end(); ++it) { + if (replayed_messages.find(*it) != replayed_messages.end()) + continue; + original_callback_.Run(base::CommandLine(it->first), it->second); + replayed_messages.insert(*it); + } + saved_startup_messages_.clear(); +} + +bool ProcessSingletonStartupLock::NotificationCallbackImpl( + const base::CommandLine& command_line, + const base::FilePath& current_directory) { + if (locked_) { + // If locked, it means we are not ready to process this message because + // we are probably in a first run critical phase. + saved_startup_messages_.push_back( + std::make_pair(command_line.argv(), current_directory)); + return true; + } else { + return original_callback_.Run(command_line, current_directory); + } +} diff --git a/atom/browser/process_singleton_startup_lock.h b/atom/browser/process_singleton_startup_lock.h new file mode 100644 index 000000000000..187dd35bce3d --- /dev/null +++ b/atom/browser/process_singleton_startup_lock.h @@ -0,0 +1,57 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ +#define CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ + +#include +#include +#include + +#include "base/basictypes.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/threading/non_thread_safe.h" +#include "chrome/browser/process_singleton.h" + +// Provides a ProcessSingleton::NotificationCallback that can queue up +// command-line invocations during startup and execute them when startup +// completes. +// +// The object starts in a locked state. |Unlock()| must be called +// when the process is prepared to handle command-line invocations. +// +// Once unlocked, notifications are forwarded to a wrapped NotificationCallback. +class ProcessSingletonStartupLock : public base::NonThreadSafe { + public: + explicit ProcessSingletonStartupLock( + const ProcessSingleton::NotificationCallback& original_callback); + ~ProcessSingletonStartupLock(); + + // Returns the ProcessSingleton::NotificationCallback. + // The callback is only valid during the lifetime of the + // ProcessSingletonStartupLock instance. + ProcessSingleton::NotificationCallback AsNotificationCallback(); + + // Executes previously queued command-line invocations and allows future + // invocations to be executed immediately. + void Unlock(); + + bool locked() { return locked_; } + + private: + typedef std::pair + DelayedStartupMessage; + + bool NotificationCallbackImpl(const base::CommandLine& command_line, + const base::FilePath& current_directory); + + bool locked_; + std::vector saved_startup_messages_; + ProcessSingleton::NotificationCallback original_callback_; + + DISALLOW_COPY_AND_ASSIGN(ProcessSingletonStartupLock); +}; + +#endif // CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ diff --git a/atom/browser/process_singleton_win.cc b/atom/browser/process_singleton_win.cc new file mode 100644 index 000000000000..623aa7f42f7f --- /dev/null +++ b/atom/browser/process_singleton_win.cc @@ -0,0 +1,441 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/process_singleton.h" + +#include + +#include "base/base_paths.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/process/process.h" +#include "base/process/process_info.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" +#include "base/win/metro.h" +#include "base/win/registry.h" +#include "base/win/scoped_handle.h" +#include "base/win/windows_version.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part.h" +#include "chrome/browser/chrome_process_finder_win.h" +#include "chrome/browser/metro_utils/metro_chrome_win.h" +#include "chrome/browser/shell_integration.h" +#include "chrome/browser/ui/simple_message_box.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_paths_internal.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/grit/chromium_strings.h" +#include "chrome/installer/util/wmi.h" +#include "content/public/common/result_codes.h" +#include "net/base/escape.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/win/hwnd_util.h" + +namespace { + +const char kLockfile[] = "lockfile"; + +const int kMetroChromeActivationTimeoutMs = 3000; + +// A helper class that acquires the given |mutex| while the AutoLockMutex is in +// scope. +class AutoLockMutex { + public: + explicit AutoLockMutex(HANDLE mutex) : mutex_(mutex) { + DWORD result = ::WaitForSingleObject(mutex_, INFINITE); + DPCHECK(result == WAIT_OBJECT_0) << "Result = " << result; + } + + ~AutoLockMutex() { + BOOL released = ::ReleaseMutex(mutex_); + DPCHECK(released); + } + + private: + HANDLE mutex_; + DISALLOW_COPY_AND_ASSIGN(AutoLockMutex); +}; + +// A helper class that releases the given |mutex| while the AutoUnlockMutex is +// in scope and immediately re-acquires it when going out of scope. +class AutoUnlockMutex { + public: + explicit AutoUnlockMutex(HANDLE mutex) : mutex_(mutex) { + BOOL released = ::ReleaseMutex(mutex_); + DPCHECK(released); + } + + ~AutoUnlockMutex() { + DWORD result = ::WaitForSingleObject(mutex_, INFINITE); + DPCHECK(result == WAIT_OBJECT_0) << "Result = " << result; + } + + private: + HANDLE mutex_; + DISALLOW_COPY_AND_ASSIGN(AutoUnlockMutex); +}; + +// Checks the visibility of the enumerated window and signals once a visible +// window has been found. +BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) { + bool* result = reinterpret_cast(param); + *result = ::IsWindowVisible(window) != 0; + // Stops enumeration if a visible window has been found. + return !*result; +} + +bool ParseCommandLine(const COPYDATASTRUCT* cds, + base::CommandLine* parsed_command_line, + base::FilePath* current_directory) { + // We should have enough room for the shortest command (min_message_size) + // and also be a multiple of wchar_t bytes. The shortest command + // possible is L"START\0\0" (empty current directory and command line). + static const int min_message_size = 7; + if (cds->cbData < min_message_size * sizeof(wchar_t) || + cds->cbData % sizeof(wchar_t) != 0) { + LOG(WARNING) << "Invalid WM_COPYDATA, length = " << cds->cbData; + return false; + } + + // We split the string into 4 parts on NULLs. + DCHECK(cds->lpData); + const std::wstring msg(static_cast(cds->lpData), + cds->cbData / sizeof(wchar_t)); + const std::wstring::size_type first_null = msg.find_first_of(L'\0'); + if (first_null == 0 || first_null == std::wstring::npos) { + // no NULL byte, don't know what to do + LOG(WARNING) << "Invalid WM_COPYDATA, length = " << msg.length() << + ", first null = " << first_null; + return false; + } + + // Decode the command, which is everything until the first NULL. + if (msg.substr(0, first_null) == L"START") { + // Another instance is starting parse the command line & do what it would + // have done. + VLOG(1) << "Handling STARTUP request from another process"; + const std::wstring::size_type second_null = + msg.find_first_of(L'\0', first_null + 1); + if (second_null == std::wstring::npos || + first_null == msg.length() - 1 || second_null == msg.length()) { + LOG(WARNING) << "Invalid format for start command, we need a string in 4 " + "parts separated by NULLs"; + return false; + } + + // Get current directory. + *current_directory = base::FilePath(msg.substr(first_null + 1, + second_null - first_null)); + + const std::wstring::size_type third_null = + msg.find_first_of(L'\0', second_null + 1); + if (third_null == std::wstring::npos || + third_null == msg.length()) { + LOG(WARNING) << "Invalid format for start command, we need a string in 4 " + "parts separated by NULLs"; + } + + // Get command line. + const std::wstring cmd_line = + msg.substr(second_null + 1, third_null - second_null); + *parsed_command_line = base::CommandLine::FromString(cmd_line); + return true; + } + return false; +} + +bool ProcessLaunchNotification( + const ProcessSingleton::NotificationCallback& notification_callback, + UINT message, + WPARAM wparam, + LPARAM lparam, + LRESULT* result) { + if (message != WM_COPYDATA) + return false; + + // Handle the WM_COPYDATA message from another process. + const COPYDATASTRUCT* cds = reinterpret_cast(lparam); + + base::CommandLine parsed_command_line(base::CommandLine::NO_PROGRAM); + base::FilePath current_directory; + if (!ParseCommandLine(cds, &parsed_command_line, ¤t_directory)) { + *result = TRUE; + return true; + } + + *result = notification_callback.Run(parsed_command_line, current_directory) ? + TRUE : FALSE; + return true; +} + +// Returns true if Chrome needs to be relaunched into Windows 8 immersive mode. +// Following conditions apply:- +// 1. Windows 8 or greater. +// 2. Not in Windows 8 immersive mode. +// 3. Chrome is default browser. +// 4. Process integrity level is not high. +// 5. The profile data directory is the default directory. +// 6. Last used mode was immersive/machine is a tablet. +// TODO(ananta) +// Move this function to a common place as the Windows 8 delegate_execute +// handler can possibly use this. +bool ShouldLaunchInWindows8ImmersiveMode(const base::FilePath& user_data_dir) { + // Returning false from this function doesn't mean we don't launch immersive + // mode in Aura. This function is specifically called in case when we need + // to relaunch desktop launched chrome into immersive mode through 'relaunch' + // menu. In case of Aura, we will use delegate_execute to do the relaunch. + return false; +} + +bool DisplayShouldKillMessageBox() { + return chrome::ShowMessageBox( + NULL, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), + l10n_util::GetStringUTF16(IDS_BROWSER_HUNGBROWSER_MESSAGE), + chrome::MESSAGE_BOX_TYPE_QUESTION) != + chrome::MESSAGE_BOX_RESULT_NO; +} + +} // namespace + +// Microsoft's Softricity virtualization breaks the sandbox processes. +// So, if we detect the Softricity DLL we use WMI Win32_Process.Create to +// break out of the virtualization environment. +// http://code.google.com/p/chromium/issues/detail?id=43650 +bool ProcessSingleton::EscapeVirtualization( + const base::FilePath& user_data_dir) { + if (::GetModuleHandle(L"sftldr_wow64.dll") || + ::GetModuleHandle(L"sftldr.dll")) { + int process_id; + if (!installer::WMIProcess::Launch(::GetCommandLineW(), &process_id)) + return false; + is_virtualized_ = true; + // The new window was spawned from WMI, and won't be in the foreground. + // So, first we sleep while the new chrome.exe instance starts (because + // WaitForInputIdle doesn't work here). Then we poll for up to two more + // seconds and make the window foreground if we find it (or we give up). + HWND hwnd = 0; + ::Sleep(90); + for (int tries = 200; tries; --tries) { + hwnd = chrome::FindRunningChromeWindow(user_data_dir); + if (hwnd) { + ::SetForegroundWindow(hwnd); + break; + } + ::Sleep(10); + } + return true; + } + return false; +} + +ProcessSingleton::ProcessSingleton( + const base::FilePath& user_data_dir, + const NotificationCallback& notification_callback) + : notification_callback_(notification_callback), + is_virtualized_(false), + lock_file_(INVALID_HANDLE_VALUE), + user_data_dir_(user_data_dir), + should_kill_remote_process_callback_( + base::Bind(&DisplayShouldKillMessageBox)) { +} + +ProcessSingleton::~ProcessSingleton() { + if (lock_file_ != INVALID_HANDLE_VALUE) + ::CloseHandle(lock_file_); +} + +// Code roughly based on Mozilla. +ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { + if (is_virtualized_) + return PROCESS_NOTIFIED; // We already spawned the process in this case. + if (lock_file_ == INVALID_HANDLE_VALUE && !remote_window_) { + return LOCK_ERROR; + } else if (!remote_window_) { + return PROCESS_NONE; + } + + switch (chrome::AttemptToNotifyRunningChrome(remote_window_, false)) { + case chrome::NOTIFY_SUCCESS: + return PROCESS_NOTIFIED; + case chrome::NOTIFY_FAILED: + remote_window_ = NULL; + return PROCESS_NONE; + case chrome::NOTIFY_WINDOW_HUNG: + // Fall through and potentially terminate the hung browser. + break; + } + + DWORD process_id = 0; + DWORD thread_id = ::GetWindowThreadProcessId(remote_window_, &process_id); + if (!thread_id || !process_id) { + remote_window_ = NULL; + return PROCESS_NONE; + } + base::Process process = base::Process::Open(process_id); + + // The window is hung. Scan for every window to find a visible one. + bool visible_window = false; + ::EnumThreadWindows(thread_id, + &BrowserWindowEnumeration, + reinterpret_cast(&visible_window)); + + // If there is a visible browser window, ask the user before killing it. + if (visible_window && !should_kill_remote_process_callback_.Run()) { + // The user denied. Quit silently. + return PROCESS_NOTIFIED; + } + + // Time to take action. Kill the browser process. + process.Terminate(content::RESULT_CODE_HUNG, true); + remote_window_ = NULL; + return PROCESS_NONE; +} + +ProcessSingleton::NotifyResult +ProcessSingleton::NotifyOtherProcessOrCreate() { + ProcessSingleton::NotifyResult result = PROCESS_NONE; + if (!Create()) { + result = NotifyOtherProcess(); + if (result == PROCESS_NONE) + result = PROFILE_IN_USE; + } else { + g_browser_process->platform_part()->PlatformSpecificCommandLineProcessing( + *base::CommandLine::ForCurrentProcess()); + } + return result; +} + +// Look for a Chrome instance that uses the same profile directory. If there +// isn't one, create a message window with its title set to the profile +// directory path. +bool ProcessSingleton::Create() { + static const wchar_t kMutexName[] = L"Local\\ChromeProcessSingletonStartup!"; + static const wchar_t kMetroActivationEventName[] = + L"Local\\ChromeProcessSingletonStartupMetroActivation!"; + + remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); + if (!remote_window_ && !EscapeVirtualization(user_data_dir_)) { + // Make sure we will be the one and only process creating the window. + // We use a named Mutex since we are protecting against multi-process + // access. As documented, it's clearer to NOT request ownership on creation + // since it isn't guaranteed we will get it. It is better to create it + // without ownership and explicitly get the ownership afterward. + base::win::ScopedHandle only_me(::CreateMutex(NULL, FALSE, kMutexName)); + if (!only_me.IsValid()) { + DPLOG(FATAL) << "CreateMutex failed"; + return false; + } + + AutoLockMutex auto_lock_only_me(only_me.Get()); + + // We now own the mutex so we are the only process that can create the + // window at this time, but we must still check if someone created it + // between the time where we looked for it above and the time the mutex + // was given to us. + remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); + + + // In Win8+, a new Chrome process launched in Desktop mode may need to be + // transmuted into Metro Chrome (see ShouldLaunchInWindows8ImmersiveMode for + // heuristics). To accomplish this, the current Chrome activates Metro + // Chrome, releases the startup mutex, and waits for metro Chrome to take + // the singleton. From that point onward, the command line for this Chrome + // process will be sent to Metro Chrome by the usual channels. + if (!remote_window_ && base::win::GetVersion() >= base::win::VERSION_WIN8 && + !base::win::IsMetroProcess()) { + // |metro_activation_event| is created right before activating a Metro + // Chrome (note that there can only be one Metro Chrome process; by OS + // design); all following Desktop processes will then wait for this event + // to be signaled by Metro Chrome which will do so as soon as it grabs + // this singleton (should any of the waiting processes timeout waiting for + // the signal they will try to grab the singleton for themselves which + // will result in a forced Desktop Chrome launch in the worst case). + base::win::ScopedHandle metro_activation_event( + ::OpenEvent(SYNCHRONIZE, FALSE, kMetroActivationEventName)); + if (!metro_activation_event.IsValid() && + ShouldLaunchInWindows8ImmersiveMode(user_data_dir_)) { + // No Metro activation is under way, but the desire is to launch in + // Metro mode: activate and rendez-vous with the activated process. + metro_activation_event.Set( + ::CreateEvent(NULL, TRUE, FALSE, kMetroActivationEventName)); + if (!chrome::ActivateMetroChrome()) { + // Failed to launch immersive Chrome, default to launching on Desktop. + LOG(ERROR) << "Failed to launch immersive chrome"; + metro_activation_event.Close(); + } + } + + if (metro_activation_event.IsValid()) { + // Release |only_me| (to let Metro Chrome grab this singleton) and wait + // until the event is signaled (i.e. Metro Chrome was successfully + // activated). Ignore timeout waiting for |metro_activation_event|. + { + AutoUnlockMutex auto_unlock_only_me(only_me.Get()); + + DWORD result = ::WaitForSingleObject(metro_activation_event.Get(), + kMetroChromeActivationTimeoutMs); + DPCHECK(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT) + << "Result = " << result; + } + + // Check if this singleton was successfully grabbed by another process + // (hopefully Metro Chrome). Failing to do so, this process will grab + // the singleton and launch in Desktop mode. + remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); + } + } + + if (!remote_window_) { + // We have to make sure there is no Chrome instance running on another + // machine that uses the same profile. + base::FilePath lock_file_path = user_data_dir_.AppendASCII(kLockfile); + lock_file_ = ::CreateFile(lock_file_path.value().c_str(), + GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | + FILE_FLAG_DELETE_ON_CLOSE, + NULL); + DWORD error = ::GetLastError(); + LOG_IF(WARNING, lock_file_ != INVALID_HANDLE_VALUE && + error == ERROR_ALREADY_EXISTS) << "Lock file exists but is writable."; + LOG_IF(ERROR, lock_file_ == INVALID_HANDLE_VALUE) + << "Lock file can not be created! Error code: " << error; + + if (lock_file_ != INVALID_HANDLE_VALUE) { + // Set the window's title to the path of our user data directory so + // other Chrome instances can decide if they should forward to us. + bool result = window_.CreateNamed( + base::Bind(&ProcessLaunchNotification, notification_callback_), + user_data_dir_.value()); + CHECK(result && window_.hwnd()); + } + + if (base::win::GetVersion() >= base::win::VERSION_WIN8) { + // Make sure no one is still waiting on Metro activation whether it + // succeeded (i.e., this is the Metro process) or failed. + base::win::ScopedHandle metro_activation_event( + ::OpenEvent(EVENT_MODIFY_STATE, FALSE, kMetroActivationEventName)); + if (metro_activation_event.IsValid()) + ::SetEvent(metro_activation_event.Get()); + } + } + } + + return window_.hwnd() != NULL; +} + +void ProcessSingleton::Cleanup() { +} + +void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting( + const ShouldKillRemoteProcessCallback& display_dialog_callback) { + should_kill_remote_process_callback_ = display_dialog_callback; +} From 90b997ef084284907164ccbd17235d5aa38ce567 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 11:21:24 -0700 Subject: [PATCH 248/738] Add the files to filenames.gypi --- filenames.gypi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/filenames.gypi b/filenames.gypi index aadc1a092f6b..17d1b3597c41 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -182,6 +182,9 @@ 'atom/browser/net/url_request_fetch_job.h', 'atom/browser/node_debugger.cc', 'atom/browser/node_debugger.h', + 'atom/browser/process_singleton_posix.cc', + 'atom/browser/process_singleton_startup_lock.cc', + 'atom/browser/process_singleton_win.cc', 'atom/browser/ui/accelerator_util.cc', 'atom/browser/ui/accelerator_util.h', 'atom/browser/ui/accelerator_util_mac.mm', From ff2d9759d5829c1332e8df205a763f290ccede04 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 11:28:29 -0700 Subject: [PATCH 249/738] Start to remove / rearrange some header files --- atom/browser/process_singleton.h | 2 -- atom/browser/process_singleton_posix.cc | 13 +------------ atom/browser/process_singleton_startup_lock.cc | 2 +- atom/browser/process_singleton_startup_lock.h | 2 +- atom/browser/process_singleton_win.cc | 18 +++++------------- 5 files changed, 8 insertions(+), 29 deletions(-) diff --git a/atom/browser/process_singleton.h b/atom/browser/process_singleton.h index 3260c4ef240c..451414613eb1 100644 --- a/atom/browser/process_singleton.h +++ b/atom/browser/process_singleton.h @@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_PROCESS_SINGLETON_H_ #define CHROME_BROWSER_PROCESS_SINGLETON_H_ -#include "build/build_config.h" - #if defined(OS_WIN) #include #endif // defined(OS_WIN) diff --git a/atom/browser/process_singleton_posix.cc b/atom/browser/process_singleton_posix.cc index 81a5c5fec355..b7ebd2de58b5 100644 --- a/atom/browser/process_singleton_posix.cc +++ b/atom/browser/process_singleton_posix.cc @@ -37,7 +37,7 @@ // retrieves the process id from the symbol link and kills it by sending // SIGKILL. Then the second process starts as normal. -#include "chrome/browser/process_singleton.h" +#include "process_singleton.h" #include #include @@ -77,21 +77,10 @@ #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/grit/chromium_strings.h" -#include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_thread.h" #include "net/base/net_util.h" #include "ui/base/l10n/l10n_util.h" -#if defined(OS_LINUX) -#include "chrome/browser/ui/process_singleton_dialog_linux.h" -#endif - -#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) -#include "ui/views/linux_ui/linux_ui.h" -#endif - using content::BrowserThread; namespace { diff --git a/atom/browser/process_singleton_startup_lock.cc b/atom/browser/process_singleton_startup_lock.cc index f564de7dca4d..58d0fd1231ca 100644 --- a/atom/browser/process_singleton_startup_lock.cc +++ b/atom/browser/process_singleton_startup_lock.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/process_singleton_startup_lock.h" +#include "process_singleton_startup_lock.h" #include "base/bind.h" #include "base/logging.h" diff --git a/atom/browser/process_singleton_startup_lock.h b/atom/browser/process_singleton_startup_lock.h index 187dd35bce3d..2e8c9754997d 100644 --- a/atom/browser/process_singleton_startup_lock.h +++ b/atom/browser/process_singleton_startup_lock.h @@ -13,7 +13,7 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/threading/non_thread_safe.h" -#include "chrome/browser/process_singleton.h" +#include "process_singleton.h" // Provides a ProcessSingleton::NotificationCallback that can queue up // command-line invocations during startup and execute them when startup diff --git a/atom/browser/process_singleton_win.cc b/atom/browser/process_singleton_win.cc index 623aa7f42f7f..95a5b7d9bb05 100644 --- a/atom/browser/process_singleton_win.cc +++ b/atom/browser/process_singleton_win.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/process_singleton.h" +#include "process_singleton.h" #include @@ -20,18 +20,10 @@ #include "base/win/registry.h" #include "base/win/scoped_handle.h" #include "base/win/windows_version.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_process_platform_part.h" -#include "chrome/browser/chrome_process_finder_win.h" -#include "chrome/browser/metro_utils/metro_chrome_win.h" -#include "chrome/browser/shell_integration.h" -#include "chrome/browser/ui/simple_message_box.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_paths_internal.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/grit/chromium_strings.h" -#include "chrome/installer/util/wmi.h" +//#include "chrome/browser/browser_process.h" +//#include "chrome/browser/browser_process_platform_part.h" +#include "chrome_process_finder_win.h" // TODO: Pull this in +//#include "chrome/browser/shell_integration.h" // TODO: Maybe pull this in? #include "content/public/common/result_codes.h" #include "net/base/escape.h" #include "ui/base/l10n/l10n_util.h" From 05b22b9372ddacea832c3c13e917ef5fd0842d52 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 11:43:45 -0700 Subject: [PATCH 250/738] Import process_finder verbatim --- atom/browser/chrome_process_finder_win.cc | 97 +++++++++++++++++++++++ atom/browser/chrome_process_finder_win.h | 39 +++++++++ 2 files changed, 136 insertions(+) create mode 100644 atom/browser/chrome_process_finder_win.cc create mode 100644 atom/browser/chrome_process_finder_win.h diff --git a/atom/browser/chrome_process_finder_win.cc b/atom/browser/chrome_process_finder_win.cc new file mode 100644 index 000000000000..13c4a0eb5a56 --- /dev/null +++ b/atom/browser/chrome_process_finder_win.cc @@ -0,0 +1,97 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chrome_process_finder_win.h" + +#include +#include + +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/process/process.h" +#include "base/process/process_info.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/win/message_window.h" +#include "base/win/scoped_handle.h" +#include "base/win/win_util.h" +#include "base/win/windows_version.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" + + +namespace { + +int timeout_in_milliseconds = 20 * 1000; + +} // namespace + +namespace chrome { + +HWND FindRunningChromeWindow(const base::FilePath& user_data_dir) { + return base::win::MessageWindow::FindWindow(user_data_dir.value()); +} + +NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window, + bool fast_start) { + DCHECK(remote_window); + DWORD process_id = 0; + DWORD thread_id = GetWindowThreadProcessId(remote_window, &process_id); + if (!thread_id || !process_id) + return NOTIFY_FAILED; + + base::CommandLine command_line(*base::CommandLine::ForCurrentProcess()); + command_line.AppendSwitchASCII( + switches::kOriginalProcessStartTime, + base::Int64ToString( + base::CurrentProcessInfo::CreationTime().ToInternalValue())); + + if (fast_start) + command_line.AppendSwitch(switches::kFastStart); + + // Send the command line to the remote chrome window. + // Format is "START\0<<>>\0<<>>". + std::wstring to_send(L"START\0", 6); // want the NULL in the string. + base::FilePath cur_dir; + if (!base::GetCurrentDirectory(&cur_dir)) + return NOTIFY_FAILED; + to_send.append(cur_dir.value()); + to_send.append(L"\0", 1); // Null separator. + to_send.append(command_line.GetCommandLineString()); + to_send.append(L"\0", 1); // Null separator. + + // Allow the current running browser window to make itself the foreground + // window (otherwise it will just flash in the taskbar). + ::AllowSetForegroundWindow(process_id); + + COPYDATASTRUCT cds; + cds.dwData = 0; + cds.cbData = static_cast((to_send.length() + 1) * sizeof(wchar_t)); + cds.lpData = const_cast(to_send.c_str()); + DWORD_PTR result = 0; + if (::SendMessageTimeout(remote_window, WM_COPYDATA, NULL, + reinterpret_cast(&cds), SMTO_ABORTIFHUNG, + timeout_in_milliseconds, &result)) { + return result ? NOTIFY_SUCCESS : NOTIFY_FAILED; + } + + // It is possible that the process owning this window may have died by now. + if (!::IsWindow(remote_window)) + return NOTIFY_FAILED; + + // If the window couldn't be notified but still exists, assume it is hung. + return NOTIFY_WINDOW_HUNG; +} + +base::TimeDelta SetNotificationTimeoutForTesting(base::TimeDelta new_timeout) { + base::TimeDelta old_timeout = + base::TimeDelta::FromMilliseconds(timeout_in_milliseconds); + timeout_in_milliseconds = new_timeout.InMilliseconds(); + return old_timeout; +} + +} // namespace chrome diff --git a/atom/browser/chrome_process_finder_win.h b/atom/browser/chrome_process_finder_win.h new file mode 100644 index 000000000000..a66429de5e74 --- /dev/null +++ b/atom/browser/chrome_process_finder_win.h @@ -0,0 +1,39 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROME_PROCESS_FINDER_WIN_H_ +#define CHROME_BROWSER_CHROME_PROCESS_FINDER_WIN_H_ + +#include + +#include "base/time/time.h" + +namespace base { +class FilePath; +} + +namespace chrome { + +enum NotifyChromeResult { + NOTIFY_SUCCESS, + NOTIFY_FAILED, + NOTIFY_WINDOW_HUNG, +}; + +// Finds an already running Chrome window if it exists. +HWND FindRunningChromeWindow(const base::FilePath& user_data_dir); + +// Attempts to send the current command line to an already running instance of +// Chrome via a WM_COPYDATA message. +// Returns true if a running Chrome is found and successfully notified. +// |fast_start| is true when this is being called on the window fast start path. +NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window, + bool fast_start); + +// Changes the notification timeout to |new_timeout|, returns the old timeout. +base::TimeDelta SetNotificationTimeoutForTesting(base::TimeDelta new_timeout); + +} // namespace chrome + +#endif // CHROME_BROWSER_CHROME_PROCESS_FINDER_WIN_H_ From d3b23a2032cc44345fef4d565c08933d7c28c204 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 11:47:38 -0700 Subject: [PATCH 251/738] Renames to avoid confusion, add file --- ...cess_finder_win.cc => atom_process_finder_win.cc} | 12 +++++------- ...rocess_finder_win.h => atom_process_finder_win.h} | 12 ++++++------ filenames.gypi | 1 + 3 files changed, 12 insertions(+), 13 deletions(-) rename atom/browser/{chrome_process_finder_win.cc => atom_process_finder_win.cc} (89%) rename atom/browser/{chrome_process_finder_win.h => atom_process_finder_win.h} (74%) diff --git a/atom/browser/chrome_process_finder_win.cc b/atom/browser/atom_process_finder_win.cc similarity index 89% rename from atom/browser/chrome_process_finder_win.cc rename to atom/browser/atom_process_finder_win.cc index 13c4a0eb5a56..df2d736d3e63 100644 --- a/atom/browser/chrome_process_finder_win.cc +++ b/atom/browser/atom_process_finder_win.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/chrome_process_finder_win.h" +#include "atom/browser/atom_process_finder_win.h" #include #include @@ -20,8 +20,6 @@ #include "base/win/scoped_handle.h" #include "base/win/win_util.h" #include "base/win/windows_version.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_switches.h" namespace { @@ -30,14 +28,14 @@ int timeout_in_milliseconds = 20 * 1000; } // namespace -namespace chrome { +namespace atom { -HWND FindRunningChromeWindow(const base::FilePath& user_data_dir) { +HWND FindRunningAtomWindow(const base::FilePath& user_data_dir) { return base::win::MessageWindow::FindWindow(user_data_dir.value()); } -NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window, - bool fast_start) { +NotifyChromeResult AttemptToNotifyRunningAtom(HWND remote_window, + bool fast_start) { DCHECK(remote_window); DWORD process_id = 0; DWORD thread_id = GetWindowThreadProcessId(remote_window, &process_id); diff --git a/atom/browser/chrome_process_finder_win.h b/atom/browser/atom_process_finder_win.h similarity index 74% rename from atom/browser/chrome_process_finder_win.h rename to atom/browser/atom_process_finder_win.h index a66429de5e74..f8aa72fdd956 100644 --- a/atom/browser/chrome_process_finder_win.h +++ b/atom/browser/atom_process_finder_win.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CHROME_PROCESS_FINDER_WIN_H_ -#define CHROME_BROWSER_CHROME_PROCESS_FINDER_WIN_H_ +#ifndef ATOM_BROWSER_ATOM_PROCESS_FINDER_WIN_H_ +#define ATOM_BROWSER_ATOM_PROCESS_FINDER_WIN_H_ #include @@ -13,7 +13,7 @@ namespace base { class FilePath; } -namespace chrome { +namespace atom { enum NotifyChromeResult { NOTIFY_SUCCESS, @@ -22,13 +22,13 @@ enum NotifyChromeResult { }; // Finds an already running Chrome window if it exists. -HWND FindRunningChromeWindow(const base::FilePath& user_data_dir); +HWND FindRunningAtomWindow(const base::FilePath& user_data_dir); // Attempts to send the current command line to an already running instance of // Chrome via a WM_COPYDATA message. // Returns true if a running Chrome is found and successfully notified. // |fast_start| is true when this is being called on the window fast start path. -NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window, +NotifyChromeResult AttemptToNotifyRunningAtom(HWND remote_window, bool fast_start); // Changes the notification timeout to |new_timeout|, returns the old timeout. @@ -36,4 +36,4 @@ base::TimeDelta SetNotificationTimeoutForTesting(base::TimeDelta new_timeout); } // namespace chrome -#endif // CHROME_BROWSER_CHROME_PROCESS_FINDER_WIN_H_ +#endif // ATOM_BROWSER_ATOM_PROCESS_FINDER_WIN_H_ diff --git a/filenames.gypi b/filenames.gypi index 17d1b3597c41..0dce079b5ec6 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -128,6 +128,7 @@ 'atom/browser/atom_browser_main_parts.h', 'atom/browser/atom_browser_main_parts_mac.mm', 'atom/browser/atom_browser_main_parts_posix.cc', + 'atom/browser/atom_process_finder_win.cc', 'atom/browser/atom_javascript_dialog_manager.cc', 'atom/browser/atom_javascript_dialog_manager.h', 'atom/browser/atom_quota_permission_context.cc', From daa65a138bc8dff4e576bbda53ab0145a734e7b3 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 12:16:37 -0700 Subject: [PATCH 252/738] Come Correct with headers --- atom/browser/process_singleton_posix.cc | 2 +- atom/browser/process_singleton_startup_lock.cc | 2 +- atom/browser/process_singleton_startup_lock.h | 6 +++--- atom/browser/process_singleton_win.cc | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/atom/browser/process_singleton_posix.cc b/atom/browser/process_singleton_posix.cc index b7ebd2de58b5..119b18e11ab8 100644 --- a/atom/browser/process_singleton_posix.cc +++ b/atom/browser/process_singleton_posix.cc @@ -37,7 +37,7 @@ // retrieves the process id from the symbol link and kills it by sending // SIGKILL. Then the second process starts as normal. -#include "process_singleton.h" +#include "atom/browser/process_singleton.h" #include #include diff --git a/atom/browser/process_singleton_startup_lock.cc b/atom/browser/process_singleton_startup_lock.cc index 58d0fd1231ca..fa53284f0514 100644 --- a/atom/browser/process_singleton_startup_lock.cc +++ b/atom/browser/process_singleton_startup_lock.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "process_singleton_startup_lock.h" +#include "atom/browser/process_singleton_startup_lock.h" #include "base/bind.h" #include "base/logging.h" diff --git a/atom/browser/process_singleton_startup_lock.h b/atom/browser/process_singleton_startup_lock.h index 2e8c9754997d..aecff8414e14 100644 --- a/atom/browser/process_singleton_startup_lock.h +++ b/atom/browser/process_singleton_startup_lock.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ -#define CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ +#ifndef ATOM_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ +#define ATOM_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ #include #include @@ -13,7 +13,7 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/threading/non_thread_safe.h" -#include "process_singleton.h" +#include "atom/browser/process_singleton.h" // Provides a ProcessSingleton::NotificationCallback that can queue up // command-line invocations during startup and execute them when startup diff --git a/atom/browser/process_singleton_win.cc b/atom/browser/process_singleton_win.cc index 95a5b7d9bb05..902a4530d95a 100644 --- a/atom/browser/process_singleton_win.cc +++ b/atom/browser/process_singleton_win.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "process_singleton.h" +#include "atom/browser/process_singleton.h" #include @@ -22,7 +22,7 @@ #include "base/win/windows_version.h" //#include "chrome/browser/browser_process.h" //#include "chrome/browser/browser_process_platform_part.h" -#include "chrome_process_finder_win.h" // TODO: Pull this in +#include "atom/browser/atom_process_finder_win.h" //#include "chrome/browser/shell_integration.h" // TODO: Maybe pull this in? #include "content/public/common/result_codes.h" #include "net/base/escape.h" From 1b3363c8114bcacabddcc928ff340b21ada440e9 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 12:17:14 -0700 Subject: [PATCH 253/738] Get process finder working --- atom/browser/atom_process_finder_win.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/atom/browser/atom_process_finder_win.cc b/atom/browser/atom_process_finder_win.cc index df2d736d3e63..a658b7163b3c 100644 --- a/atom/browser/atom_process_finder_win.cc +++ b/atom/browser/atom_process_finder_win.cc @@ -43,13 +43,6 @@ NotifyChromeResult AttemptToNotifyRunningAtom(HWND remote_window, return NOTIFY_FAILED; base::CommandLine command_line(*base::CommandLine::ForCurrentProcess()); - command_line.AppendSwitchASCII( - switches::kOriginalProcessStartTime, - base::Int64ToString( - base::CurrentProcessInfo::CreationTime().ToInternalValue())); - - if (fast_start) - command_line.AppendSwitch(switches::kFastStart); // Send the command line to the remote chrome window. // Format is "START\0<<>>\0<<>>". From c46579b1acadf1270cd389f827e25bff4013eadf Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 12:28:06 -0700 Subject: [PATCH 254/738] Remove a bunch of stuff we don't need in process_singleton_win --- atom/browser/process_singleton_win.cc | 146 +++----------------------- 1 file changed, 15 insertions(+), 131 deletions(-) diff --git a/atom/browser/process_singleton_win.cc b/atom/browser/process_singleton_win.cc index 902a4530d95a..cf667f11e443 100644 --- a/atom/browser/process_singleton_win.cc +++ b/atom/browser/process_singleton_win.cc @@ -33,8 +33,6 @@ namespace { const char kLockfile[] = "lockfile"; -const int kMetroChromeActivationTimeoutMs = 3000; - // A helper class that acquires the given |mutex| while the AutoLockMutex is in // scope. class AutoLockMutex { @@ -166,66 +164,14 @@ bool ProcessLaunchNotification( return true; } -// Returns true if Chrome needs to be relaunched into Windows 8 immersive mode. -// Following conditions apply:- -// 1. Windows 8 or greater. -// 2. Not in Windows 8 immersive mode. -// 3. Chrome is default browser. -// 4. Process integrity level is not high. -// 5. The profile data directory is the default directory. -// 6. Last used mode was immersive/machine is a tablet. -// TODO(ananta) -// Move this function to a common place as the Windows 8 delegate_execute -// handler can possibly use this. -bool ShouldLaunchInWindows8ImmersiveMode(const base::FilePath& user_data_dir) { - // Returning false from this function doesn't mean we don't launch immersive - // mode in Aura. This function is specifically called in case when we need - // to relaunch desktop launched chrome into immersive mode through 'relaunch' - // menu. In case of Aura, we will use delegate_execute to do the relaunch. +bool TerminateAppWithError() { + // TODO: This is called when the secondary process can't ping the primary + // process. Need to find out what to do here. return false; } -bool DisplayShouldKillMessageBox() { - return chrome::ShowMessageBox( - NULL, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), - l10n_util::GetStringUTF16(IDS_BROWSER_HUNGBROWSER_MESSAGE), - chrome::MESSAGE_BOX_TYPE_QUESTION) != - chrome::MESSAGE_BOX_RESULT_NO; -} - } // namespace -// Microsoft's Softricity virtualization breaks the sandbox processes. -// So, if we detect the Softricity DLL we use WMI Win32_Process.Create to -// break out of the virtualization environment. -// http://code.google.com/p/chromium/issues/detail?id=43650 -bool ProcessSingleton::EscapeVirtualization( - const base::FilePath& user_data_dir) { - if (::GetModuleHandle(L"sftldr_wow64.dll") || - ::GetModuleHandle(L"sftldr.dll")) { - int process_id; - if (!installer::WMIProcess::Launch(::GetCommandLineW(), &process_id)) - return false; - is_virtualized_ = true; - // The new window was spawned from WMI, and won't be in the foreground. - // So, first we sleep while the new chrome.exe instance starts (because - // WaitForInputIdle doesn't work here). Then we poll for up to two more - // seconds and make the window foreground if we find it (or we give up). - HWND hwnd = 0; - ::Sleep(90); - for (int tries = 200; tries; --tries) { - hwnd = chrome::FindRunningChromeWindow(user_data_dir); - if (hwnd) { - ::SetForegroundWindow(hwnd); - break; - } - ::Sleep(10); - } - return true; - } - return false; -} - ProcessSingleton::ProcessSingleton( const base::FilePath& user_data_dir, const NotificationCallback& notification_callback) @@ -234,7 +180,7 @@ ProcessSingleton::ProcessSingleton( lock_file_(INVALID_HANDLE_VALUE), user_data_dir_(user_data_dir), should_kill_remote_process_callback_( - base::Bind(&DisplayShouldKillMessageBox)) { + base::Bind(&TerminateAppWithError)) { } ProcessSingleton::~ProcessSingleton() { @@ -252,13 +198,13 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { return PROCESS_NONE; } - switch (chrome::AttemptToNotifyRunningChrome(remote_window_, false)) { - case chrome::NOTIFY_SUCCESS: + switch (atom::AttemptToNotifyRunningAtom(remote_window_, false)) { + case atom::NOTIFY_SUCCESS: return PROCESS_NOTIFIED; - case chrome::NOTIFY_FAILED: + case atom::NOTIFY_FAILED: remote_window_ = NULL; return PROCESS_NONE; - case chrome::NOTIFY_WINDOW_HUNG: + case atom::NOTIFY_WINDOW_HUNG: // Fall through and potentially terminate the hung browser. break; } @@ -297,8 +243,9 @@ ProcessSingleton::NotifyOtherProcessOrCreate() { if (result == PROCESS_NONE) result = PROFILE_IN_USE; } else { - g_browser_process->platform_part()->PlatformSpecificCommandLineProcessing( - *base::CommandLine::ForCurrentProcess()); + // TODO: Figure out how to implement this + //g_browser_process->platform_part()->PlatformSpecificCommandLineProcessing( + // *base::CommandLine::ForCurrentProcess()); } return result; } @@ -307,12 +254,10 @@ ProcessSingleton::NotifyOtherProcessOrCreate() { // isn't one, create a message window with its title set to the profile // directory path. bool ProcessSingleton::Create() { - static const wchar_t kMutexName[] = L"Local\\ChromeProcessSingletonStartup!"; - static const wchar_t kMetroActivationEventName[] = - L"Local\\ChromeProcessSingletonStartupMetroActivation!"; + static const wchar_t kMutexName[] = L"Local\\AtomProcessSingletonStartup!"; - remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); - if (!remote_window_ && !EscapeVirtualization(user_data_dir_)) { + remote_window_ = atom::FindRunningAtomWindow(user_data_dir_); + if (!remote_window_) { // Make sure we will be the one and only process creating the window. // We use a named Mutex since we are protecting against multi-process // access. As documented, it's clearer to NOT request ownership on creation @@ -330,59 +275,7 @@ bool ProcessSingleton::Create() { // window at this time, but we must still check if someone created it // between the time where we looked for it above and the time the mutex // was given to us. - remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); - - - // In Win8+, a new Chrome process launched in Desktop mode may need to be - // transmuted into Metro Chrome (see ShouldLaunchInWindows8ImmersiveMode for - // heuristics). To accomplish this, the current Chrome activates Metro - // Chrome, releases the startup mutex, and waits for metro Chrome to take - // the singleton. From that point onward, the command line for this Chrome - // process will be sent to Metro Chrome by the usual channels. - if (!remote_window_ && base::win::GetVersion() >= base::win::VERSION_WIN8 && - !base::win::IsMetroProcess()) { - // |metro_activation_event| is created right before activating a Metro - // Chrome (note that there can only be one Metro Chrome process; by OS - // design); all following Desktop processes will then wait for this event - // to be signaled by Metro Chrome which will do so as soon as it grabs - // this singleton (should any of the waiting processes timeout waiting for - // the signal they will try to grab the singleton for themselves which - // will result in a forced Desktop Chrome launch in the worst case). - base::win::ScopedHandle metro_activation_event( - ::OpenEvent(SYNCHRONIZE, FALSE, kMetroActivationEventName)); - if (!metro_activation_event.IsValid() && - ShouldLaunchInWindows8ImmersiveMode(user_data_dir_)) { - // No Metro activation is under way, but the desire is to launch in - // Metro mode: activate and rendez-vous with the activated process. - metro_activation_event.Set( - ::CreateEvent(NULL, TRUE, FALSE, kMetroActivationEventName)); - if (!chrome::ActivateMetroChrome()) { - // Failed to launch immersive Chrome, default to launching on Desktop. - LOG(ERROR) << "Failed to launch immersive chrome"; - metro_activation_event.Close(); - } - } - - if (metro_activation_event.IsValid()) { - // Release |only_me| (to let Metro Chrome grab this singleton) and wait - // until the event is signaled (i.e. Metro Chrome was successfully - // activated). Ignore timeout waiting for |metro_activation_event|. - { - AutoUnlockMutex auto_unlock_only_me(only_me.Get()); - - DWORD result = ::WaitForSingleObject(metro_activation_event.Get(), - kMetroChromeActivationTimeoutMs); - DPCHECK(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT) - << "Result = " << result; - } - - // Check if this singleton was successfully grabbed by another process - // (hopefully Metro Chrome). Failing to do so, this process will grab - // the singleton and launch in Desktop mode. - remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); - } - } - + remote_window_ = atom::FindRunningAtomWindow(user_data_dir_); if (!remote_window_) { // We have to make sure there is no Chrome instance running on another // machine that uses the same profile. @@ -409,15 +302,6 @@ bool ProcessSingleton::Create() { user_data_dir_.value()); CHECK(result && window_.hwnd()); } - - if (base::win::GetVersion() >= base::win::VERSION_WIN8) { - // Make sure no one is still waiting on Metro activation whether it - // succeeded (i.e., this is the Metro process) or failed. - base::win::ScopedHandle metro_activation_event( - ::OpenEvent(EVENT_MODIFY_STATE, FALSE, kMetroActivationEventName)); - if (metro_activation_event.IsValid()) - ::SetEvent(metro_activation_event.Get()); - } } } From 88dd1480cc7601cf6f96923018eeaffdcbeef9c9 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 13:51:27 -0700 Subject: [PATCH 255/738] Get POSIX mostly compiling --- atom/browser/process_singleton_posix.cc | 50 ++++++++++++------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/atom/browser/process_singleton_posix.cc b/atom/browser/process_singleton_posix.cc index 119b18e11ab8..2df9da631bee 100644 --- a/atom/browser/process_singleton_posix.cc +++ b/atom/browser/process_singleton_posix.cc @@ -81,6 +81,10 @@ #include "net/base/net_util.h" #include "ui/base/l10n/l10n_util.h" +#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) +#include "ui/views/linux_ui/linux_ui.h" +#endif + using content::BrowserThread; namespace { @@ -101,6 +105,13 @@ const int kMaxACKMessageLength = arraysize(kShutdownToken) - 1; const char kLockDelimiter = '-'; +const base::FilePath::CharType kSingletonCookieFilename[] = + FILE_PATH_LITERAL("SingletonCookie"); + +const base::FilePath::CharType kSingletonLockFilename[] = FILE_PATH_LITERAL("SingletonLock"); +const base::FilePath::CharType kSingletonSocketFilename[] = + FILE_PATH_LITERAL("SingletonSocket"); + // Set the close-on-exec bit on a file descriptor. // Returns 0 on success, -1 on failure. int SetCloseOnExec(int fd) { @@ -293,33 +304,20 @@ bool ParseLockPath(const base::FilePath& path, bool DisplayProfileInUseError(const base::FilePath& lock_path, const std::string& hostname, int pid) { - base::string16 error = l10n_util::GetStringFUTF16( - IDS_PROFILE_IN_USE_POSIX, - base::IntToString16(pid), - base::ASCIIToUTF16(hostname)); - LOG(ERROR) << error; - - if (g_disable_prompt) - return false; - -#if defined(OS_LINUX) - base::string16 relaunch_button_text = l10n_util::GetStringUTF16( - IDS_PROFILE_IN_USE_LINUX_RELAUNCH); - return ShowProcessSingletonDialog(error, relaunch_button_text); -#elif defined(OS_MACOSX) - // On Mac, always usurp the lock. + // TODO: yolo return true; -#endif - - NOTREACHED(); - return false; } bool IsChromeProcess(pid_t pid) { base::FilePath other_chrome_path(base::GetProcessExecutablePath(pid)); + + auto command_line = base::CommandLine::ForCurrentProcess(); + base::FilePath exec_path(command_line->GetProgram()); + PathService::Get(base::FILE_EXE, &exec_path); + return (!other_chrome_path.empty() && other_chrome_path.BaseName() == - base::FilePath(chrome::kBrowserProcessExecutableName)); + exec_path.BaseName()); } // A helper class to hold onto a socket. @@ -360,7 +358,7 @@ bool ConnectSocket(ScopedSocket* socket, if (cookie.empty()) return false; base::FilePath remote_cookie = socket_target.DirName(). - Append(chrome::kSingletonCookieFilename); + Append(kSingletonCookieFilename); // Verify the cookie before connecting. if (!CheckCookie(remote_cookie, cookie)) return false; @@ -720,9 +718,9 @@ ProcessSingleton::ProcessSingleton( : notification_callback_(notification_callback), current_pid_(base::GetCurrentProcId()), watcher_(new LinuxWatcher(this)) { - socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename); - lock_path_ = user_data_dir.Append(chrome::kSingletonLockFilename); - cookie_path_ = user_data_dir.Append(chrome::kSingletonCookieFilename); + socket_path_ = user_data_dir.Append(kSingletonSocketFilename); + lock_path_ = user_data_dir.Append(kSingletonLockFilename); + cookie_path_ = user_data_dir.Append(kSingletonCookieFilename); kill_callback_ = base::Bind(&ProcessSingleton::KillProcess, base::Unretained(this)); @@ -962,10 +960,10 @@ bool ProcessSingleton::Create() { // Setup the socket symlink and the two cookies. base::FilePath socket_target_path = - socket_dir_.path().Append(chrome::kSingletonSocketFilename); + socket_dir_.path().Append(kSingletonSocketFilename); base::FilePath cookie(GenerateCookie()); base::FilePath remote_cookie_path = - socket_dir_.path().Append(chrome::kSingletonCookieFilename); + socket_dir_.path().Append(kSingletonCookieFilename); UnlinkPath(socket_path_); UnlinkPath(cookie_path_); if (!SymlinkPath(socket_target_path, socket_path_) || From 8288a224587a5634a7057dbbbeafe838d012a4a4 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 14:07:23 -0700 Subject: [PATCH 256/738] Fix build against old OneShotTimer --- atom/browser/process_singleton_posix.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/process_singleton_posix.cc b/atom/browser/process_singleton_posix.cc index 2df9da631bee..5810af2a2a55 100644 --- a/atom/browser/process_singleton_posix.cc +++ b/atom/browser/process_singleton_posix.cc @@ -503,7 +503,7 @@ class ProcessSingleton::LinuxWatcher // reads. size_t bytes_read_; - base::OneShotTimer timer_; + base::OneShotTimer timer_; DISALLOW_COPY_AND_ASSIGN(SocketReader); }; From 717aba9631583d160db6062b0fb424bf90d40c3d Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 14:43:04 -0700 Subject: [PATCH 257/738] Create a dummy method in app that we'll twerk --- atom/browser/api/atom_api_app.cc | 5 +++++ atom/browser/api/atom_api_app.h | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index f124b00e8089..27cc137d2274 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -268,6 +268,10 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { return v8::Local::New(isolate, default_session_); } +bool App::MakeSingleInstance(const SingleInstanceCallback& callback) { + return false; +} + mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( v8::Isolate* isolate) { auto browser = base::Unretained(Browser::Get()); @@ -294,6 +298,7 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( .SetMethod("allowNTLMCredentialsForAllDomains", &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) + .SetMethod("MakeSingleInstance", &App::MakeSingleInstance) .SetProperty("defaultSession", &App::DefaultSession); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 75889d24543f..ae79abe8f21d 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -9,6 +9,7 @@ #include "atom/browser/api/event_emitter.h" #include "atom/browser/browser_observer.h" +#include "atom/common/native_mate_converters/callback.h" #include "content/public/browser/gpu_data_manager_observer.h" #include "native_mate/handle.h" @@ -24,6 +25,8 @@ namespace atom { namespace api { +using SingleInstanceCallback = base::Callback; + class App : public mate::EventEmitter, public BrowserObserver, public content::GpuDataManagerObserver { @@ -65,7 +68,10 @@ class App : public mate::EventEmitter, void SetDesktopName(const std::string& desktop_name); void SetAppUserModelId(const std::string& app_id); + void AllowNTLMCredentialsForAllDomains(bool should_allow); + + bool MakeSingleInstance(const SingleInstanceCallback& callback); std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); From 4d5495a0a0460eb6838031a39b9ee958e13b30cf Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 14:50:18 -0700 Subject: [PATCH 258/738] Bring in chrome_process_singleton but nuke the active dialog bits --- atom/browser/atom_process_singleton.cc | 29 ++++++++++++++ atom/browser/atom_process_singleton.h | 52 ++++++++++++++++++++++++++ filenames.gypi | 1 + 3 files changed, 82 insertions(+) create mode 100644 atom/browser/atom_process_singleton.cc create mode 100644 atom/browser/atom_process_singleton.h diff --git a/atom/browser/atom_process_singleton.cc b/atom/browser/atom_process_singleton.cc new file mode 100644 index 000000000000..e9e4dc727bf7 --- /dev/null +++ b/atom/browser/atom_process_singleton.cc @@ -0,0 +1,29 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "atom/browser/atom_process_singleton.h" + +AtomProcessSingleton::AtomProcessSingleton( + const base::FilePath& user_data_dir, + const ProcessSingleton::NotificationCallback& notification_callback) + : startup_lock_(notification_callback), + process_singleton_(user_data_dir, + startup_lock_.AsNotificationCallback()) { +} + +AtomProcessSingleton::~AtomProcessSingleton() { +} + +ProcessSingleton::NotifyResult + AtomProcessSingleton::NotifyOtherProcessOrCreate() { + return process_singleton_.NotifyOtherProcessOrCreate(); +} + +void AtomProcessSingleton::Cleanup() { + process_singleton_.Cleanup(); +} + +void AtomProcessSingleton::Unlock() { + startup_lock_.Unlock(); +} diff --git a/atom/browser/atom_process_singleton.h b/atom/browser/atom_process_singleton.h new file mode 100644 index 000000000000..de4e2463a080 --- /dev/null +++ b/atom/browser/atom_process_singleton.h @@ -0,0 +1,52 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_ATOM_PROCESS_SINGLETON_H_ +#define ATOM_BROWSER_ATOM_PROCESS_SINGLETON_H_ + +#include "base/basictypes.h" +#include "base/files/file_path.h" +#include "atom/browser/process_singleton.h" +#include "atom/browser/process_singleton_startup_lock.h" + +// Composes a basic ProcessSingleton with ProcessSingletonStartupLock +class AtomProcessSingleton { + public: + AtomProcessSingleton( + const base::FilePath& user_data_dir, + const ProcessSingleton::NotificationCallback& notification_callback); + + ~AtomProcessSingleton(); + + // Notify another process, if available. Otherwise sets ourselves as the + // singleton instance. Returns PROCESS_NONE if we became the singleton + // instance. Callers are guaranteed to either have notified an existing + // process or have grabbed the singleton (unless the profile is locked by an + // unreachable process). + ProcessSingleton::NotifyResult NotifyOtherProcessOrCreate(); + + // Clear any lock state during shutdown. + void Cleanup(); + + // Executes previously queued command-line invocations and allows future + // invocations to be executed immediately. + // This only has an effect the first time it is called. + void Unlock(); + + private: + // We compose these two locks with the client-supplied notification callback. + // First |modal_dialog_lock_| will discard any notifications that arrive while + // a modal dialog is active. Otherwise, it will pass the notification to + // |startup_lock_|, which will queue notifications until |Unlock()| is called. + // Notifications passing through both locks are finally delivered to our + // client. + ProcessSingletonStartupLock startup_lock_; + + // The basic ProcessSingleton + ProcessSingleton process_singleton_; + + DISALLOW_COPY_AND_ASSIGN(AtomProcessSingleton); +}; + +#endif // ATOM_BROWSER_ATOM_PROCESS_SINGLETON_H_ diff --git a/filenames.gypi b/filenames.gypi index 0dce079b5ec6..54fedb9f4130 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -129,6 +129,7 @@ 'atom/browser/atom_browser_main_parts_mac.mm', 'atom/browser/atom_browser_main_parts_posix.cc', 'atom/browser/atom_process_finder_win.cc', + 'atom/browser/atom_process_singleton.cc', 'atom/browser/atom_javascript_dialog_manager.cc', 'atom/browser/atom_javascript_dialog_manager.h', 'atom/browser/atom_quota_permission_context.cc', From 7491ae40007018acc7953c1757fae99d342e61f4 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 16:00:30 -0700 Subject: [PATCH 259/738] Set up Browser to create the process singleton --- atom/browser/browser.cc | 37 +++++++++++++++++++++++++++++++++++-- atom/browser/browser.h | 13 +++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index d8bb94103cd9..10d6cc8330eb 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -9,6 +9,8 @@ #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/window_list.h" #include "base/message_loop/message_loop.h" +#include "base/path_service.h" +#include "brightray/browser/brightray_paths.h" #include "content/public/browser/client_certificate_delegate.h" #include "net/ssl/ssl_cert_request_info.h" @@ -17,7 +19,18 @@ namespace atom { Browser::Browser() : is_quiting_(false), is_ready_(false), - is_shutdown_(false) { + is_shutdown_(false), + process_notify_callback_(NULL) { + base::FilePath userDir; + PathService::Get(brightray::DIR_USER_DATA, &userDir); + + auto no_refcount_this = base::Unretained(this); + process_singleton_.reset(new AtomProcessSingleton( + userDir, + base::Bind(&Browser::OnProcessSingletonNotification, no_refcount_this))); + + process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); + WindowList::AddObserver(this); } @@ -114,6 +127,7 @@ void Browser::WillFinishLaunching() { void Browser::DidFinishLaunching() { is_ready_ = true; + process_singleton_->Unlock() ; FOR_EACH_OBSERVER(BrowserObserver, observers_, OnFinishLaunching()); } @@ -139,7 +153,8 @@ void Browser::NotifyAndShutdown() { is_quiting_ = false; return; } - + + process_singleton_->Cleanup(); Shutdown(); } @@ -152,6 +167,14 @@ bool Browser::HandleBeforeQuit() { return !prevent_default; } +ProcessSingleton::NotifyResult Browser::GetSingleInstanceResult() { + return process_notify_result_; +} + +void Browser::SetSingleInstanceCallback(ProcessSingleton::NotificationCallback* callback) { + process_notify_callback_ = callback; +} + void Browser::OnWindowCloseCancelled(NativeWindow* window) { if (is_quiting_) // Once a beforeunload handler has prevented the closing, we think the quit @@ -166,4 +189,14 @@ void Browser::OnWindowAllClosed() { FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWindowAllClosed()); } +bool Browser::OnProcessSingletonNotification( + const base::CommandLine& command_line, + const base::FilePath& current_directory) { + if (process_notify_callback_) { + return (*process_notify_callback_).Run(command_line, current_directory); + } else { + return true; // We'll handle this, not a different process + } +} + } // namespace atom diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 3c5abd2f0405..4dffeb093fab 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -9,8 +9,10 @@ #include #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "base/compiler_specific.h" #include "base/observer_list.h" +#include "atom/browser/atom_process_singleton.h" #include "atom/browser/browser_observer.h" #include "atom/browser/window_list_observer.h" @@ -63,6 +65,9 @@ class Browser : public WindowListObserver { // Clear the recent documents list. void ClearRecentDocuments(); + + ProcessSingleton::NotifyResult GetSingleInstanceResult(); + void SetSingleInstanceCallback(ProcessSingleton::NotificationCallback* callback); #if defined(OS_MACOSX) // Bounce the dock icon. @@ -152,6 +157,10 @@ class Browser : public WindowListObserver { // WindowListObserver implementations: void OnWindowCloseCancelled(NativeWindow* window) override; void OnWindowAllClosed() override; + + bool OnProcessSingletonNotification( + const base::CommandLine& command_line, + const base::FilePath& current_directory); // Observers of the browser. base::ObserverList observers_; @@ -164,6 +173,10 @@ class Browser : public WindowListObserver { std::string version_override_; std::string name_override_; + + scoped_ptr process_singleton_; + ProcessSingleton::NotifyResult process_notify_result_; + ProcessSingleton::NotificationCallback* process_notify_callback_; #if defined(OS_WIN) base::string16 app_user_model_id_; From c38f2fcf759f84fc1b0c5e1946270fbcea9f38ff Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 16:20:51 -0700 Subject: [PATCH 260/738] Add a native mate converter for command lines --- .../command_line_converter.h | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 atom/common/native_mate_converters/command_line_converter.h diff --git a/atom/common/native_mate_converters/command_line_converter.h b/atom/common/native_mate_converters/command_line_converter.h new file mode 100644 index 000000000000..7941c9a0968b --- /dev/null +++ b/atom/common/native_mate_converters/command_line_converter.h @@ -0,0 +1,37 @@ +// Copyright (c) 2014 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_COMMAND_LINE_CONVERTER_H_ +#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_COMMAND_LINE_CONVERTER_H_ + +#include + +#include "atom/common/native_mate_converters/string16_converter.h" +#include "base/command_line.h" + +namespace mate { + +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + const base::CommandLine& val) { + return Converter::ToV8(isolate, val.GetCommandLineString()); + } + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + base::CommandLine* out) { + base::FilePath::StringType path; + + if (Converter::FromV8(isolate, val, &path)) { + *out = base::CommandLine(base::FilePath(path)); + return true; + } else { + return false; + } + } +}; + +} // namespace mate + +#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_FILE_PATH_CONVERTER_H_ From cdd51fa96db2aa274d53486d740016ddd9cbbb30 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 16:21:03 -0700 Subject: [PATCH 261/738] Wire everything up --- atom/browser/api/atom_api_app.cc | 15 ++++++++++++++- atom/browser/api/atom_api_app.h | 7 +++---- atom/browser/browser.cc | 2 +- atom/browser/browser.h | 4 ++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 27cc137d2274..3c858c2f3463 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -19,6 +19,7 @@ #include "atom/browser/api/atom_api_web_contents.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/file_path_converter.h" +#include "atom/common/native_mate_converters/command_line_converter.h" #include "atom/common/node_includes.h" #include "atom/common/options_switches.h" #include "base/command_line.h" @@ -268,7 +269,19 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { return v8::Local::New(isolate, default_session_); } -bool App::MakeSingleInstance(const SingleInstanceCallback& callback) { +bool App::MakeSingleInstance(const ProcessSingleton::NotificationCallback& callback) { + auto browser = Browser::Get(); + browser->SetSingleInstanceCallback(&callback); + + switch(browser->GetSingleInstanceResult()) { + case ProcessSingleton::NotifyResult::PROCESS_NONE: + return false; + case ProcessSingleton::NotifyResult::LOCK_ERROR: + case ProcessSingleton::NotifyResult::PROFILE_IN_USE: + case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: + return true; + } + return false; } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index ae79abe8f21d..10d4edf117f1 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -9,6 +9,7 @@ #include "atom/browser/api/event_emitter.h" #include "atom/browser/browser_observer.h" +#include "atom/browser/process_singleton.h" #include "atom/common/native_mate_converters/callback.h" #include "content/public/browser/gpu_data_manager_observer.h" #include "native_mate/handle.h" @@ -25,8 +26,6 @@ namespace atom { namespace api { -using SingleInstanceCallback = base::Callback; - class App : public mate::EventEmitter, public BrowserObserver, public content::GpuDataManagerObserver { @@ -70,8 +69,8 @@ class App : public mate::EventEmitter, void SetAppUserModelId(const std::string& app_id); void AllowNTLMCredentialsForAllDomains(bool should_allow); - - bool MakeSingleInstance(const SingleInstanceCallback& callback); + + bool MakeSingleInstance(const ProcessSingleton::NotificationCallback& callback); std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 10d6cc8330eb..3c55be68824c 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -171,7 +171,7 @@ ProcessSingleton::NotifyResult Browser::GetSingleInstanceResult() { return process_notify_result_; } -void Browser::SetSingleInstanceCallback(ProcessSingleton::NotificationCallback* callback) { +void Browser::SetSingleInstanceCallback(const ProcessSingleton::NotificationCallback* callback) { process_notify_callback_ = callback; } diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 4dffeb093fab..f14062232ca7 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -67,7 +67,7 @@ class Browser : public WindowListObserver { void ClearRecentDocuments(); ProcessSingleton::NotifyResult GetSingleInstanceResult(); - void SetSingleInstanceCallback(ProcessSingleton::NotificationCallback* callback); + void SetSingleInstanceCallback(const ProcessSingleton::NotificationCallback* callback); #if defined(OS_MACOSX) // Bounce the dock icon. @@ -176,7 +176,7 @@ class Browser : public WindowListObserver { scoped_ptr process_singleton_; ProcessSingleton::NotifyResult process_notify_result_; - ProcessSingleton::NotificationCallback* process_notify_callback_; + const ProcessSingleton::NotificationCallback* process_notify_callback_; #if defined(OS_WIN) base::string16 app_user_model_id_; From b02f89e63be64ec122dd6c933d174366f16c41fd Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 17:36:21 -0700 Subject: [PATCH 262/738] Typo --- atom/browser/api/atom_api_app.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 3c858c2f3463..2b60d2db965d 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -311,7 +311,7 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( .SetMethod("allowNTLMCredentialsForAllDomains", &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) - .SetMethod("MakeSingleInstance", &App::MakeSingleInstance) + .SetMethod("makeSingleInstance", &App::MakeSingleInstance) .SetProperty("defaultSession", &App::DefaultSession); } From 50fab0733bbfcb6c504e9230347971c00c27acec Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 17:37:26 -0700 Subject: [PATCH 263/738] At Browser ctor time, DIR_USER_DATA is unset, wait --- atom/browser/browser.cc | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 3c55be68824c..39c348bcd6d2 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -21,16 +21,6 @@ Browser::Browser() is_ready_(false), is_shutdown_(false), process_notify_callback_(NULL) { - base::FilePath userDir; - PathService::Get(brightray::DIR_USER_DATA, &userDir); - - auto no_refcount_this = base::Unretained(this); - process_singleton_.reset(new AtomProcessSingleton( - userDir, - base::Bind(&Browser::OnProcessSingletonNotification, no_refcount_this))); - - process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); - WindowList::AddObserver(this); } @@ -122,6 +112,17 @@ void Browser::Activate(bool has_visible_windows) { } void Browser::WillFinishLaunching() { + base::FilePath userDir; + PathService::Get(brightray::DIR_USER_DATA, &userDir); + + auto no_refcount_this = base::Unretained(this); + process_singleton_.reset(new AtomProcessSingleton( + userDir, + base::Bind(&Browser::OnProcessSingletonNotification, no_refcount_this))); + + LOG(ERROR) << "Setting up Process Singleton: " << userDir.value(); + process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); + FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWillFinishLaunching()); } From 4a4b829cfc91ff50534b9679e3ef3f2c192cdce2 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 18:02:54 -0700 Subject: [PATCH 264/738] Fix callback handle usage --- atom/browser/api/atom_api_app.cc | 17 ++++++++++++++--- atom/browser/api/atom_api_app.h | 7 ++++++- atom/browser/browser.cc | 12 +++++++----- atom/browser/browser.h | 9 +++++---- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 2b60d2db965d..7792fa6bc3a5 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -269,10 +269,21 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { return v8::Local::New(isolate, default_session_); } -bool App::MakeSingleInstance(const ProcessSingleton::NotificationCallback& callback) { +bool App::OnProcessSingletonNotification( + const base::CommandLine& command_line, + const base::FilePath& current_directory) { + return true; +} + +bool App::MakeSingleInstance(v8::Local callback) { + single_instance_callback_ = callback; + auto browser = Browser::Get(); - browser->SetSingleInstanceCallback(&callback); - + + auto no_refcount_this = base::Unretained(this); + browser->SetSingleInstanceCallback( + base::Bind(&App::OnProcessSingletonNotification, no_refcount_this)); + switch(browser->GetSingleInstanceResult()) { case ProcessSingleton::NotifyResult::PROCESS_NONE: return false; diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 10d4edf117f1..2d6a9f7f66b9 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -70,11 +70,16 @@ class App : public mate::EventEmitter, void AllowNTLMCredentialsForAllDomains(bool should_allow); - bool MakeSingleInstance(const ProcessSingleton::NotificationCallback& callback); + bool MakeSingleInstance(v8::Local callback); + + bool OnProcessSingletonNotification( + const base::CommandLine& command_line, + const base::FilePath& current_directory); std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); + v8::Local single_instance_callback_; v8::Global default_session_; DISALLOW_COPY_AND_ASSIGN(App); diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 39c348bcd6d2..f2ee8b42350a 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -20,7 +20,7 @@ Browser::Browser() : is_quiting_(false), is_ready_(false), is_shutdown_(false), - process_notify_callback_(NULL) { + process_notify_callback_set_(false) { WindowList::AddObserver(this); } @@ -169,11 +169,13 @@ bool Browser::HandleBeforeQuit() { } ProcessSingleton::NotifyResult Browser::GetSingleInstanceResult() { + LOG(ERROR) << "Process Notify Result: " << process_notify_result_; return process_notify_result_; } - -void Browser::SetSingleInstanceCallback(const ProcessSingleton::NotificationCallback* callback) { + +void Browser::SetSingleInstanceCallback(const ProcessSingleton::NotificationCallback& callback) { process_notify_callback_ = callback; + process_notify_callback_set_ = true; } void Browser::OnWindowCloseCancelled(NativeWindow* window) { @@ -193,8 +195,8 @@ void Browser::OnWindowAllClosed() { bool Browser::OnProcessSingletonNotification( const base::CommandLine& command_line, const base::FilePath& current_directory) { - if (process_notify_callback_) { - return (*process_notify_callback_).Run(command_line, current_directory); + if (process_notify_callback_set_) { + return process_notify_callback_.Run(command_line, current_directory); } else { return true; // We'll handle this, not a different process } diff --git a/atom/browser/browser.h b/atom/browser/browser.h index f14062232ca7..b84e220d27eb 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -65,9 +65,9 @@ class Browser : public WindowListObserver { // Clear the recent documents list. void ClearRecentDocuments(); - + ProcessSingleton::NotifyResult GetSingleInstanceResult(); - void SetSingleInstanceCallback(const ProcessSingleton::NotificationCallback* callback); + void SetSingleInstanceCallback(const ProcessSingleton::NotificationCallback& callback); #if defined(OS_MACOSX) // Bounce the dock icon. @@ -173,10 +173,11 @@ class Browser : public WindowListObserver { std::string version_override_; std::string name_override_; - + scoped_ptr process_singleton_; ProcessSingleton::NotifyResult process_notify_result_; - const ProcessSingleton::NotificationCallback* process_notify_callback_; + const ProcessSingleton::NotificationCallback process_notify_callback_; + bool process_notify_callback_set_; #if defined(OS_WIN) base::string16 app_user_model_id_; From 63417bc975317e0b9c16e2f8c5a50847ac73bcbc Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 18:23:13 -0700 Subject: [PATCH 265/738] I am not good at C++ at all --- atom/browser/api/atom_api_app.h | 2 +- atom/browser/browser.cc | 2 +- atom/browser/browser.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 2d6a9f7f66b9..6654046e8286 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -21,7 +21,7 @@ class FilePath; namespace mate { class Arguments; } - + namespace atom { namespace api { diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index f2ee8b42350a..84b149330a65 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -173,7 +173,7 @@ ProcessSingleton::NotifyResult Browser::GetSingleInstanceResult() { return process_notify_result_; } -void Browser::SetSingleInstanceCallback(const ProcessSingleton::NotificationCallback& callback) { +void Browser::SetSingleInstanceCallback(ProcessSingleton::NotificationCallback callback) { process_notify_callback_ = callback; process_notify_callback_set_ = true; } diff --git a/atom/browser/browser.h b/atom/browser/browser.h index b84e220d27eb..b3de4d169ac9 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -67,7 +67,7 @@ class Browser : public WindowListObserver { void ClearRecentDocuments(); ProcessSingleton::NotifyResult GetSingleInstanceResult(); - void SetSingleInstanceCallback(const ProcessSingleton::NotificationCallback& callback); + void SetSingleInstanceCallback(ProcessSingleton::NotificationCallback callback); #if defined(OS_MACOSX) // Bounce the dock icon. @@ -176,7 +176,7 @@ class Browser : public WindowListObserver { scoped_ptr process_singleton_; ProcessSingleton::NotifyResult process_notify_result_; - const ProcessSingleton::NotificationCallback process_notify_callback_; + ProcessSingleton::NotificationCallback process_notify_callback_; bool process_notify_callback_set_; #if defined(OS_WIN) From a2eedcc027f5f58a2069c1cc12c40ed2086f2157 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 19 Oct 2015 18:42:31 -0700 Subject: [PATCH 266/738] Wire up the final callback to JS --- atom/browser/api/atom_api_app.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 7792fa6bc3a5..072686dd8d12 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -272,7 +272,10 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { bool App::OnProcessSingletonNotification( const base::CommandLine& command_line, const base::FilePath& current_directory) { - return true; + ProcessSingleton::NotificationCallback cb; + mate::Converter::FromV8(isolate(), single_instance_callback_, &cb); + + return cb.Run(command_line, current_directory); } bool App::MakeSingleInstance(v8::Local callback) { From 5d4c29a1e32fe58221e98be534f73da3902f054a Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 13:27:34 -0700 Subject: [PATCH 267/738] Ditch double-callback, just use mate directly --- atom/browser/api/atom_api_app.cc | 19 +++++-------------- atom/browser/api/atom_api_app.h | 8 ++------ 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 072686dd8d12..24c8063bc8da 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -269,23 +269,14 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { return v8::Local::New(isolate, default_session_); } -bool App::OnProcessSingletonNotification( - const base::CommandLine& command_line, - const base::FilePath& current_directory) { - ProcessSingleton::NotificationCallback cb; - mate::Converter::FromV8(isolate(), single_instance_callback_, &cb); - - return cb.Run(command_line, current_directory); -} - bool App::MakeSingleInstance(v8::Local callback) { single_instance_callback_ = callback; - auto browser = Browser::Get(); + ProcessSingleton::NotificationCallback cb; + mate::Converter::FromV8(isolate(), single_instance_callback_, &cb); - auto no_refcount_this = base::Unretained(this); - browser->SetSingleInstanceCallback( - base::Bind(&App::OnProcessSingletonNotification, no_refcount_this)); + auto browser = Browser::Get(); + browser->SetSingleInstanceCallback(cb); switch(browser->GetSingleInstanceResult()) { case ProcessSingleton::NotifyResult::PROCESS_NONE: @@ -295,7 +286,7 @@ bool App::MakeSingleInstance(v8::Local callback) { case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: return true; } - + return false; } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 6654046e8286..b8285553b497 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -21,7 +21,7 @@ class FilePath; namespace mate { class Arguments; } - + namespace atom { namespace api { @@ -71,11 +71,7 @@ class App : public mate::EventEmitter, void AllowNTLMCredentialsForAllDomains(bool should_allow); bool MakeSingleInstance(v8::Local callback); - - bool OnProcessSingletonNotification( - const base::CommandLine& command_line, - const base::FilePath& current_directory); - + std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); From b6f1729acda0172bc86b6d21a6a31020113504dc Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 13:38:57 -0700 Subject: [PATCH 268/738] Move initialization of Single Instance into MakeSingleInstance call --- atom/browser/api/atom_api_app.cc | 4 +++- atom/browser/browser.cc | 25 +++++++++++++------------ atom/browser/browser.h | 3 ++- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 24c8063bc8da..f3955d2d03ab 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -270,12 +270,14 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { } bool App::MakeSingleInstance(v8::Local callback) { + auto browser = Browser::Get(); single_instance_callback_ = callback; + browser->InitializeSingleInstance(); + ProcessSingleton::NotificationCallback cb; mate::Converter::FromV8(isolate(), single_instance_callback_, &cb); - auto browser = Browser::Get(); browser->SetSingleInstanceCallback(cb); switch(browser->GetSingleInstanceResult()) { diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 84b149330a65..5c12a0d338f8 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -112,17 +112,6 @@ void Browser::Activate(bool has_visible_windows) { } void Browser::WillFinishLaunching() { - base::FilePath userDir; - PathService::Get(brightray::DIR_USER_DATA, &userDir); - - auto no_refcount_this = base::Unretained(this); - process_singleton_.reset(new AtomProcessSingleton( - userDir, - base::Bind(&Browser::OnProcessSingletonNotification, no_refcount_this))); - - LOG(ERROR) << "Setting up Process Singleton: " << userDir.value(); - process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); - FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWillFinishLaunching()); } @@ -154,7 +143,7 @@ void Browser::NotifyAndShutdown() { is_quiting_ = false; return; } - + process_singleton_->Cleanup(); Shutdown(); } @@ -168,6 +157,18 @@ bool Browser::HandleBeforeQuit() { return !prevent_default; } +void Browser::InitializeSingleInstance() { + base::FilePath userDir; + PathService::Get(brightray::DIR_USER_DATA, &userDir); + + auto no_refcount_this = base::Unretained(this); + process_singleton_.reset(new AtomProcessSingleton( + userDir, + base::Bind(&Browser::OnProcessSingletonNotification, no_refcount_this))); + + process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); +} + ProcessSingleton::NotifyResult Browser::GetSingleInstanceResult() { LOG(ERROR) << "Process Notify Result: " << process_notify_result_; return process_notify_result_; diff --git a/atom/browser/browser.h b/atom/browser/browser.h index b3de4d169ac9..9113c58dd12d 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -66,6 +66,7 @@ class Browser : public WindowListObserver { // Clear the recent documents list. void ClearRecentDocuments(); + void InitializeSingleInstance(); ProcessSingleton::NotifyResult GetSingleInstanceResult(); void SetSingleInstanceCallback(ProcessSingleton::NotificationCallback callback); @@ -157,7 +158,7 @@ class Browser : public WindowListObserver { // WindowListObserver implementations: void OnWindowCloseCancelled(NativeWindow* window) override; void OnWindowAllClosed() override; - + bool OnProcessSingletonNotification( const base::CommandLine& command_line, const base::FilePath& current_directory); From 7491d5cfb5a680afa03c09561315f17279a45c87 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 14:05:07 -0700 Subject: [PATCH 269/738] Copy back the original versions of Chromium files in --- .../browser/chrome_process_finder_win.cc | 97 ++ .../browser/chrome_process_finder_win.h | 39 + .../chrome/browser/process_singleton.h | 183 +++ .../chrome/browser/process_singleton_posix.cc | 1062 +++++++++++++++++ .../browser/process_singleton_startup_lock.cc | 53 + .../browser/process_singleton_startup_lock.h | 57 + .../chrome/browser/process_singleton_win.cc | 441 +++++++ 7 files changed, 1932 insertions(+) create mode 100644 chromium_src/chrome/browser/chrome_process_finder_win.cc create mode 100644 chromium_src/chrome/browser/chrome_process_finder_win.h create mode 100644 chromium_src/chrome/browser/process_singleton.h create mode 100644 chromium_src/chrome/browser/process_singleton_posix.cc create mode 100644 chromium_src/chrome/browser/process_singleton_startup_lock.cc create mode 100644 chromium_src/chrome/browser/process_singleton_startup_lock.h create mode 100644 chromium_src/chrome/browser/process_singleton_win.cc diff --git a/chromium_src/chrome/browser/chrome_process_finder_win.cc b/chromium_src/chrome/browser/chrome_process_finder_win.cc new file mode 100644 index 000000000000..13c4a0eb5a56 --- /dev/null +++ b/chromium_src/chrome/browser/chrome_process_finder_win.cc @@ -0,0 +1,97 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chrome_process_finder_win.h" + +#include +#include + +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/process/process.h" +#include "base/process/process_info.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/win/message_window.h" +#include "base/win/scoped_handle.h" +#include "base/win/win_util.h" +#include "base/win/windows_version.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" + + +namespace { + +int timeout_in_milliseconds = 20 * 1000; + +} // namespace + +namespace chrome { + +HWND FindRunningChromeWindow(const base::FilePath& user_data_dir) { + return base::win::MessageWindow::FindWindow(user_data_dir.value()); +} + +NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window, + bool fast_start) { + DCHECK(remote_window); + DWORD process_id = 0; + DWORD thread_id = GetWindowThreadProcessId(remote_window, &process_id); + if (!thread_id || !process_id) + return NOTIFY_FAILED; + + base::CommandLine command_line(*base::CommandLine::ForCurrentProcess()); + command_line.AppendSwitchASCII( + switches::kOriginalProcessStartTime, + base::Int64ToString( + base::CurrentProcessInfo::CreationTime().ToInternalValue())); + + if (fast_start) + command_line.AppendSwitch(switches::kFastStart); + + // Send the command line to the remote chrome window. + // Format is "START\0<<>>\0<<>>". + std::wstring to_send(L"START\0", 6); // want the NULL in the string. + base::FilePath cur_dir; + if (!base::GetCurrentDirectory(&cur_dir)) + return NOTIFY_FAILED; + to_send.append(cur_dir.value()); + to_send.append(L"\0", 1); // Null separator. + to_send.append(command_line.GetCommandLineString()); + to_send.append(L"\0", 1); // Null separator. + + // Allow the current running browser window to make itself the foreground + // window (otherwise it will just flash in the taskbar). + ::AllowSetForegroundWindow(process_id); + + COPYDATASTRUCT cds; + cds.dwData = 0; + cds.cbData = static_cast((to_send.length() + 1) * sizeof(wchar_t)); + cds.lpData = const_cast(to_send.c_str()); + DWORD_PTR result = 0; + if (::SendMessageTimeout(remote_window, WM_COPYDATA, NULL, + reinterpret_cast(&cds), SMTO_ABORTIFHUNG, + timeout_in_milliseconds, &result)) { + return result ? NOTIFY_SUCCESS : NOTIFY_FAILED; + } + + // It is possible that the process owning this window may have died by now. + if (!::IsWindow(remote_window)) + return NOTIFY_FAILED; + + // If the window couldn't be notified but still exists, assume it is hung. + return NOTIFY_WINDOW_HUNG; +} + +base::TimeDelta SetNotificationTimeoutForTesting(base::TimeDelta new_timeout) { + base::TimeDelta old_timeout = + base::TimeDelta::FromMilliseconds(timeout_in_milliseconds); + timeout_in_milliseconds = new_timeout.InMilliseconds(); + return old_timeout; +} + +} // namespace chrome diff --git a/chromium_src/chrome/browser/chrome_process_finder_win.h b/chromium_src/chrome/browser/chrome_process_finder_win.h new file mode 100644 index 000000000000..a66429de5e74 --- /dev/null +++ b/chromium_src/chrome/browser/chrome_process_finder_win.h @@ -0,0 +1,39 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROME_PROCESS_FINDER_WIN_H_ +#define CHROME_BROWSER_CHROME_PROCESS_FINDER_WIN_H_ + +#include + +#include "base/time/time.h" + +namespace base { +class FilePath; +} + +namespace chrome { + +enum NotifyChromeResult { + NOTIFY_SUCCESS, + NOTIFY_FAILED, + NOTIFY_WINDOW_HUNG, +}; + +// Finds an already running Chrome window if it exists. +HWND FindRunningChromeWindow(const base::FilePath& user_data_dir); + +// Attempts to send the current command line to an already running instance of +// Chrome via a WM_COPYDATA message. +// Returns true if a running Chrome is found and successfully notified. +// |fast_start| is true when this is being called on the window fast start path. +NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window, + bool fast_start); + +// Changes the notification timeout to |new_timeout|, returns the old timeout. +base::TimeDelta SetNotificationTimeoutForTesting(base::TimeDelta new_timeout); + +} // namespace chrome + +#endif // CHROME_BROWSER_CHROME_PROCESS_FINDER_WIN_H_ diff --git a/chromium_src/chrome/browser/process_singleton.h b/chromium_src/chrome/browser/process_singleton.h new file mode 100644 index 000000000000..9d99b02b9f4c --- /dev/null +++ b/chromium_src/chrome/browser/process_singleton.h @@ -0,0 +1,183 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PROCESS_SINGLETON_H_ +#define CHROME_BROWSER_PROCESS_SINGLETON_H_ + +#include "build/build_config.h" + +#if defined(OS_WIN) +#include +#endif // defined(OS_WIN) + +#include +#include + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/process/process.h" +#include "base/threading/non_thread_safe.h" +#include "ui/gfx/native_widget_types.h" + +#if defined(OS_POSIX) && !defined(OS_ANDROID) +#include "base/files/scoped_temp_dir.h" +#endif + +#if defined(OS_WIN) +#include "base/win/message_window.h" +#endif // defined(OS_WIN) + +namespace base { +class CommandLine; +} + +// ProcessSingleton ---------------------------------------------------------- +// +// This class allows different browser processes to communicate with +// each other. It is named according to the user data directory, so +// we can be sure that no more than one copy of the application can be +// running at once with a given data directory. +// +// Implementation notes: +// - the Windows implementation uses an invisible global message window; +// - the Linux implementation uses a Unix domain socket in the user data dir. + +class ProcessSingleton : public base::NonThreadSafe { + public: + enum NotifyResult { + PROCESS_NONE, + PROCESS_NOTIFIED, + PROFILE_IN_USE, + LOCK_ERROR, + }; + + // Implement this callback to handle notifications from other processes. The + // callback will receive the command line and directory with which the other + // Chrome process was launched. Return true if the command line will be + // handled within the current browser instance or false if the remote process + // should handle it (i.e., because the current process is shutting down). + using NotificationCallback = + base::Callback; + + ProcessSingleton(const base::FilePath& user_data_dir, + const NotificationCallback& notification_callback); + ~ProcessSingleton(); + + // Notify another process, if available. Otherwise sets ourselves as the + // singleton instance. Returns PROCESS_NONE if we became the singleton + // instance. Callers are guaranteed to either have notified an existing + // process or have grabbed the singleton (unless the profile is locked by an + // unreachable process). + // TODO(brettw): Make the implementation of this method non-platform-specific + // by making Linux re-use the Windows implementation. + NotifyResult NotifyOtherProcessOrCreate(); + + // Sets ourself up as the singleton instance. Returns true on success. If + // false is returned, we are not the singleton instance and the caller must + // exit. + // NOTE: Most callers should generally prefer NotifyOtherProcessOrCreate() to + // this method, only callers for whom failure is preferred to notifying + // another process should call this directly. + bool Create(); + + // Clear any lock state during shutdown. + void Cleanup(); + +#if defined(OS_POSIX) && !defined(OS_ANDROID) + static void DisablePromptForTesting(); +#endif +#if defined(OS_WIN) + // Called to query whether to kill a hung browser process that has visible + // windows. Return true to allow killing the hung process. + using ShouldKillRemoteProcessCallback = base::Callback; + void OverrideShouldKillRemoteProcessCallbackForTesting( + const ShouldKillRemoteProcessCallback& display_dialog_callback); +#endif + + protected: + // Notify another process, if available. + // Returns true if another process was found and notified, false if we should + // continue with the current process. + // On Windows, Create() has to be called before this. + NotifyResult NotifyOtherProcess(); + +#if defined(OS_POSIX) && !defined(OS_ANDROID) + // Exposed for testing. We use a timeout on Linux, and in tests we want + // this timeout to be short. + NotifyResult NotifyOtherProcessWithTimeout( + const base::CommandLine& command_line, + int retry_attempts, + const base::TimeDelta& timeout, + bool kill_unresponsive); + NotifyResult NotifyOtherProcessWithTimeoutOrCreate( + const base::CommandLine& command_line, + int retry_attempts, + const base::TimeDelta& timeout); + void OverrideCurrentPidForTesting(base::ProcessId pid); + void OverrideKillCallbackForTesting( + const base::Callback& callback); +#endif + + private: + NotificationCallback notification_callback_; // Handler for notifications. + +#if defined(OS_WIN) + bool EscapeVirtualization(const base::FilePath& user_data_dir); + + HWND remote_window_; // The HWND_MESSAGE of another browser. + base::win::MessageWindow window_; // The message-only window. + bool is_virtualized_; // Stuck inside Microsoft Softricity VM environment. + HANDLE lock_file_; + base::FilePath user_data_dir_; + ShouldKillRemoteProcessCallback should_kill_remote_process_callback_; +#elif defined(OS_POSIX) && !defined(OS_ANDROID) + // Return true if the given pid is one of our child processes. + // Assumes that the current pid is the root of all pids of the current + // instance. + bool IsSameChromeInstance(pid_t pid); + + // Extract the process's pid from a symbol link path and if it is on + // the same host, kill the process, unlink the lock file and return true. + // If the process is part of the same chrome instance, unlink the lock file + // and return true without killing it. + // If the process is on a different host, return false. + bool KillProcessByLockPath(); + + // Default function to kill a process, overridable by tests. + void KillProcess(int pid); + + // Allow overriding for tests. + base::ProcessId current_pid_; + + // Function to call when the other process is hung and needs to be killed. + // Allows overriding for tests. + base::Callback kill_callback_; + + // Path in file system to the socket. + base::FilePath socket_path_; + + // Path in file system to the lock. + base::FilePath lock_path_; + + // Path in file system to the cookie file. + base::FilePath cookie_path_; + + // Temporary directory to hold the socket. + base::ScopedTempDir socket_dir_; + + // Helper class for linux specific messages. LinuxWatcher is ref counted + // because it posts messages between threads. + class LinuxWatcher; + scoped_refptr watcher_; +#endif + + DISALLOW_COPY_AND_ASSIGN(ProcessSingleton); +}; + +#endif // CHROME_BROWSER_PROCESS_SINGLETON_H_ \ No newline at end of file diff --git a/chromium_src/chrome/browser/process_singleton_posix.cc b/chromium_src/chrome/browser/process_singleton_posix.cc new file mode 100644 index 000000000000..e855207ea77b --- /dev/null +++ b/chromium_src/chrome/browser/process_singleton_posix.cc @@ -0,0 +1,1062 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// On Linux, when the user tries to launch a second copy of chrome, we check +// for a socket in the user's profile directory. If the socket file is open we +// send a message to the first chrome browser process with the current +// directory and second process command line flags. The second process then +// exits. +// +// Because many networked filesystem implementations do not support unix domain +// sockets, we create the socket in a temporary directory and create a symlink +// in the profile. This temporary directory is no longer bound to the profile, +// and may disappear across a reboot or login to a separate session. To bind +// them, we store a unique cookie in the profile directory, which must also be +// present in the remote directory to connect. The cookie is checked both before +// and after the connection. /tmp is sticky, and different Chrome sessions use +// different cookies. Thus, a matching cookie before and after means the +// connection was to a directory with a valid cookie. +// +// We also have a lock file, which is a symlink to a non-existent destination. +// The destination is a string containing the hostname and process id of +// chrome's browser process, eg. "SingletonLock -> example.com-9156". When the +// first copy of chrome exits it will delete the lock file on shutdown, so that +// a different instance on a different host may then use the profile directory. +// +// If writing to the socket fails, the hostname in the lock is checked to see if +// another instance is running a different host using a shared filesystem (nfs, +// etc.) If the hostname differs an error is displayed and the second process +// exits. Otherwise the first process (if any) is killed and the second process +// starts as normal. +// +// When the second process sends the current directory and command line flags to +// the first process, it waits for an ACK message back from the first process +// for a certain time. If there is no ACK message back in time, then the first +// process will be considered as hung for some reason. The second process then +// retrieves the process id from the symbol link and kills it by sending +// SIGKILL. Then the second process starts as normal. + +#include "chrome/browser/process_singleton.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "base/base_paths.h" +#include "base/basictypes.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/path_service.h" +#include "base/posix/eintr_wrapper.h" +#include "base/posix/safe_strerror.h" +#include "base/rand_util.h" +#include "base/sequenced_task_runner_helpers.h" +#include "base/single_thread_task_runner.h" +#include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/threading/platform_thread.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/grit/chromium_strings.h" +#include "chrome/grit/generated_resources.h" +#include "content/public/browser/browser_thread.h" +#include "net/base/net_util.h" +#include "ui/base/l10n/l10n_util.h" + +#if defined(OS_LINUX) +#include "chrome/browser/ui/process_singleton_dialog_linux.h" +#endif + +#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) +#include "ui/views/linux_ui/linux_ui.h" +#endif + +using content::BrowserThread; + +namespace { + +// Timeout for the current browser process to respond. 20 seconds should be +// enough. +const int kTimeoutInSeconds = 20; +// Number of retries to notify the browser. 20 retries over 20 seconds = 1 try +// per second. +const int kRetryAttempts = 20; +static bool g_disable_prompt; +const char kStartToken[] = "START"; +const char kACKToken[] = "ACK"; +const char kShutdownToken[] = "SHUTDOWN"; +const char kTokenDelimiter = '\0'; +const int kMaxMessageLength = 32 * 1024; +const int kMaxACKMessageLength = arraysize(kShutdownToken) - 1; + +const char kLockDelimiter = '-'; + +// Set the close-on-exec bit on a file descriptor. +// Returns 0 on success, -1 on failure. +int SetCloseOnExec(int fd) { + int flags = fcntl(fd, F_GETFD, 0); + if (-1 == flags) + return flags; + if (flags & FD_CLOEXEC) + return 0; + return fcntl(fd, F_SETFD, flags | FD_CLOEXEC); +} + +// Close a socket and check return value. +void CloseSocket(int fd) { + int rv = IGNORE_EINTR(close(fd)); + DCHECK_EQ(0, rv) << "Error closing socket: " << base::safe_strerror(errno); +} + +// Write a message to a socket fd. +bool WriteToSocket(int fd, const char *message, size_t length) { + DCHECK(message); + DCHECK(length); + size_t bytes_written = 0; + do { + ssize_t rv = HANDLE_EINTR( + write(fd, message + bytes_written, length - bytes_written)); + if (rv < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // The socket shouldn't block, we're sending so little data. Just give + // up here, since NotifyOtherProcess() doesn't have an asynchronous api. + LOG(ERROR) << "ProcessSingleton would block on write(), so it gave up."; + return false; + } + PLOG(ERROR) << "write() failed"; + return false; + } + bytes_written += rv; + } while (bytes_written < length); + + return true; +} + +struct timeval TimeDeltaToTimeVal(const base::TimeDelta& delta) { + struct timeval result; + result.tv_sec = delta.InSeconds(); + result.tv_usec = delta.InMicroseconds() % base::Time::kMicrosecondsPerSecond; + return result; +} + +// Wait a socket for read for a certain timeout. +// Returns -1 if error occurred, 0 if timeout reached, > 0 if the socket is +// ready for read. +int WaitSocketForRead(int fd, const base::TimeDelta& timeout) { + fd_set read_fds; + struct timeval tv = TimeDeltaToTimeVal(timeout); + + FD_ZERO(&read_fds); + FD_SET(fd, &read_fds); + + return HANDLE_EINTR(select(fd + 1, &read_fds, NULL, NULL, &tv)); +} + +// Read a message from a socket fd, with an optional timeout. +// If |timeout| <= 0 then read immediately. +// Return number of bytes actually read, or -1 on error. +ssize_t ReadFromSocket(int fd, + char* buf, + size_t bufsize, + const base::TimeDelta& timeout) { + if (timeout > base::TimeDelta()) { + int rv = WaitSocketForRead(fd, timeout); + if (rv <= 0) + return rv; + } + + size_t bytes_read = 0; + do { + ssize_t rv = HANDLE_EINTR(read(fd, buf + bytes_read, bufsize - bytes_read)); + if (rv < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + PLOG(ERROR) << "read() failed"; + return rv; + } else { + // It would block, so we just return what has been read. + return bytes_read; + } + } else if (!rv) { + // No more data to read. + return bytes_read; + } else { + bytes_read += rv; + } + } while (bytes_read < bufsize); + + return bytes_read; +} + +// Set up a sockaddr appropriate for messaging. +void SetupSockAddr(const std::string& path, struct sockaddr_un* addr) { + addr->sun_family = AF_UNIX; + CHECK(path.length() < arraysize(addr->sun_path)) + << "Socket path too long: " << path; + base::strlcpy(addr->sun_path, path.c_str(), arraysize(addr->sun_path)); +} + +// Set up a socket appropriate for messaging. +int SetupSocketOnly() { + int sock = socket(PF_UNIX, SOCK_STREAM, 0); + PCHECK(sock >= 0) << "socket() failed"; + + int rv = net::SetNonBlocking(sock); + DCHECK_EQ(0, rv) << "Failed to make non-blocking socket."; + rv = SetCloseOnExec(sock); + DCHECK_EQ(0, rv) << "Failed to set CLOEXEC on socket."; + + return sock; +} + +// Set up a socket and sockaddr appropriate for messaging. +void SetupSocket(const std::string& path, int* sock, struct sockaddr_un* addr) { + *sock = SetupSocketOnly(); + SetupSockAddr(path, addr); +} + +// Read a symbolic link, return empty string if given path is not a symbol link. +base::FilePath ReadLink(const base::FilePath& path) { + base::FilePath target; + if (!base::ReadSymbolicLink(path, &target)) { + // The only errno that should occur is ENOENT. + if (errno != 0 && errno != ENOENT) + PLOG(ERROR) << "readlink(" << path.value() << ") failed"; + } + return target; +} + +// Unlink a path. Return true on success. +bool UnlinkPath(const base::FilePath& path) { + int rv = unlink(path.value().c_str()); + if (rv < 0 && errno != ENOENT) + PLOG(ERROR) << "Failed to unlink " << path.value(); + + return rv == 0; +} + +// Create a symlink. Returns true on success. +bool SymlinkPath(const base::FilePath& target, const base::FilePath& path) { + if (!base::CreateSymbolicLink(target, path)) { + // Double check the value in case symlink suceeded but we got an incorrect + // failure due to NFS packet loss & retry. + int saved_errno = errno; + if (ReadLink(path) != target) { + // If we failed to create the lock, most likely another instance won the + // startup race. + errno = saved_errno; + PLOG(ERROR) << "Failed to create " << path.value(); + return false; + } + } + return true; +} + +// Extract the hostname and pid from the lock symlink. +// Returns true if the lock existed. +bool ParseLockPath(const base::FilePath& path, + std::string* hostname, + int* pid) { + std::string real_path = ReadLink(path).value(); + if (real_path.empty()) + return false; + + std::string::size_type pos = real_path.rfind(kLockDelimiter); + + // If the path is not a symbolic link, or doesn't contain what we expect, + // bail. + if (pos == std::string::npos) { + *hostname = ""; + *pid = -1; + return true; + } + + *hostname = real_path.substr(0, pos); + + const std::string& pid_str = real_path.substr(pos + 1); + if (!base::StringToInt(pid_str, pid)) + *pid = -1; + + return true; +} + +// Returns true if the user opted to unlock the profile. +bool DisplayProfileInUseError(const base::FilePath& lock_path, + const std::string& hostname, + int pid) { + base::string16 error = l10n_util::GetStringFUTF16( + IDS_PROFILE_IN_USE_POSIX, + base::IntToString16(pid), + base::ASCIIToUTF16(hostname)); + LOG(ERROR) << error; + + if (g_disable_prompt) + return false; + +#if defined(OS_LINUX) + base::string16 relaunch_button_text = l10n_util::GetStringUTF16( + IDS_PROFILE_IN_USE_LINUX_RELAUNCH); + return ShowProcessSingletonDialog(error, relaunch_button_text); +#elif defined(OS_MACOSX) + // On Mac, always usurp the lock. + return true; +#endif + + NOTREACHED(); + return false; +} + +bool IsChromeProcess(pid_t pid) { + base::FilePath other_chrome_path(base::GetProcessExecutablePath(pid)); + return (!other_chrome_path.empty() && + other_chrome_path.BaseName() == + base::FilePath(chrome::kBrowserProcessExecutableName)); +} + +// A helper class to hold onto a socket. +class ScopedSocket { + public: + ScopedSocket() : fd_(-1) { Reset(); } + ~ScopedSocket() { Close(); } + int fd() { return fd_; } + void Reset() { + Close(); + fd_ = SetupSocketOnly(); + } + void Close() { + if (fd_ >= 0) + CloseSocket(fd_); + fd_ = -1; + } + private: + int fd_; +}; + +// Returns a random string for uniquifying profile connections. +std::string GenerateCookie() { + return base::Uint64ToString(base::RandUint64()); +} + +bool CheckCookie(const base::FilePath& path, const base::FilePath& cookie) { + return (cookie == ReadLink(path)); +} + +bool ConnectSocket(ScopedSocket* socket, + const base::FilePath& socket_path, + const base::FilePath& cookie_path) { + base::FilePath socket_target; + if (base::ReadSymbolicLink(socket_path, &socket_target)) { + // It's a symlink. Read the cookie. + base::FilePath cookie = ReadLink(cookie_path); + if (cookie.empty()) + return false; + base::FilePath remote_cookie = socket_target.DirName(). + Append(chrome::kSingletonCookieFilename); + // Verify the cookie before connecting. + if (!CheckCookie(remote_cookie, cookie)) + return false; + // Now we know the directory was (at that point) created by the profile + // owner. Try to connect. + sockaddr_un addr; + SetupSockAddr(socket_target.value(), &addr); + int ret = HANDLE_EINTR(connect(socket->fd(), + reinterpret_cast(&addr), + sizeof(addr))); + if (ret != 0) + return false; + // Check the cookie again. We only link in /tmp, which is sticky, so, if the + // directory is still correct, it must have been correct in-between when we + // connected. POSIX, sadly, lacks a connectat(). + if (!CheckCookie(remote_cookie, cookie)) { + socket->Reset(); + return false; + } + // Success! + return true; + } else if (errno == EINVAL) { + // It exists, but is not a symlink (or some other error we detect + // later). Just connect to it directly; this is an older version of Chrome. + sockaddr_un addr; + SetupSockAddr(socket_path.value(), &addr); + int ret = HANDLE_EINTR(connect(socket->fd(), + reinterpret_cast(&addr), + sizeof(addr))); + return (ret == 0); + } else { + // File is missing, or other error. + if (errno != ENOENT) + PLOG(ERROR) << "readlink failed"; + return false; + } +} + +#if defined(OS_MACOSX) +bool ReplaceOldSingletonLock(const base::FilePath& symlink_content, + const base::FilePath& lock_path) { + // Try taking an flock(2) on the file. Failure means the lock is taken so we + // should quit. + base::ScopedFD lock_fd(HANDLE_EINTR( + open(lock_path.value().c_str(), O_RDWR | O_CREAT | O_SYMLINK, 0644))); + if (!lock_fd.is_valid()) { + PLOG(ERROR) << "Could not open singleton lock"; + return false; + } + + int rc = HANDLE_EINTR(flock(lock_fd.get(), LOCK_EX | LOCK_NB)); + if (rc == -1) { + if (errno == EWOULDBLOCK) { + LOG(ERROR) << "Singleton lock held by old process."; + } else { + PLOG(ERROR) << "Error locking singleton lock"; + } + return false; + } + + // Successfully taking the lock means we can replace it with the a new symlink + // lock. We never flock() the lock file from now on. I.e. we assume that an + // old version of Chrome will not run with the same user data dir after this + // version has run. + if (!base::DeleteFile(lock_path, false)) { + PLOG(ERROR) << "Could not delete old singleton lock."; + return false; + } + + return SymlinkPath(symlink_content, lock_path); +} +#endif // defined(OS_MACOSX) + +} // namespace + +/////////////////////////////////////////////////////////////////////////////// +// ProcessSingleton::LinuxWatcher +// A helper class for a Linux specific implementation of the process singleton. +// This class sets up a listener on the singleton socket and handles parsing +// messages that come in on the singleton socket. +class ProcessSingleton::LinuxWatcher + : public base::MessageLoopForIO::Watcher, + public base::MessageLoop::DestructionObserver, + public base::RefCountedThreadSafe { + public: + // A helper class to read message from an established socket. + class SocketReader : public base::MessageLoopForIO::Watcher { + public: + SocketReader(ProcessSingleton::LinuxWatcher* parent, + base::MessageLoop* ui_message_loop, + int fd) + : parent_(parent), + ui_message_loop_(ui_message_loop), + fd_(fd), + bytes_read_(0) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + // Wait for reads. + base::MessageLoopForIO::current()->WatchFileDescriptor( + fd, true, base::MessageLoopForIO::WATCH_READ, &fd_reader_, this); + // If we haven't completed in a reasonable amount of time, give up. + timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kTimeoutInSeconds), + this, &SocketReader::CleanupAndDeleteSelf); + } + + ~SocketReader() override { CloseSocket(fd_); } + + // MessageLoopForIO::Watcher impl. + void OnFileCanReadWithoutBlocking(int fd) override; + void OnFileCanWriteWithoutBlocking(int fd) override { + // SocketReader only watches for accept (read) events. + NOTREACHED(); + } + + // Finish handling the incoming message by optionally sending back an ACK + // message and removing this SocketReader. + void FinishWithACK(const char *message, size_t length); + + private: + void CleanupAndDeleteSelf() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + parent_->RemoveSocketReader(this); + // We're deleted beyond this point. + } + + base::MessageLoopForIO::FileDescriptorWatcher fd_reader_; + + // The ProcessSingleton::LinuxWatcher that owns us. + ProcessSingleton::LinuxWatcher* const parent_; + + // A reference to the UI message loop. + base::MessageLoop* const ui_message_loop_; + + // The file descriptor we're reading. + const int fd_; + + // Store the message in this buffer. + char buf_[kMaxMessageLength]; + + // Tracks the number of bytes we've read in case we're getting partial + // reads. + size_t bytes_read_; + + base::OneShotTimer timer_; + + DISALLOW_COPY_AND_ASSIGN(SocketReader); + }; + + // We expect to only be constructed on the UI thread. + explicit LinuxWatcher(ProcessSingleton* parent) + : ui_message_loop_(base::MessageLoop::current()), + parent_(parent) { + } + + // Start listening for connections on the socket. This method should be + // called from the IO thread. + void StartListening(int socket); + + // This method determines if we should use the same process and if we should, + // opens a new browser tab. This runs on the UI thread. + // |reader| is for sending back ACK message. + void HandleMessage(const std::string& current_dir, + const std::vector& argv, + SocketReader* reader); + + // MessageLoopForIO::Watcher impl. These run on the IO thread. + void OnFileCanReadWithoutBlocking(int fd) override; + void OnFileCanWriteWithoutBlocking(int fd) override { + // ProcessSingleton only watches for accept (read) events. + NOTREACHED(); + } + + // MessageLoop::DestructionObserver + void WillDestroyCurrentMessageLoop() override { + fd_watcher_.StopWatchingFileDescriptor(); + } + + private: + friend struct BrowserThread::DeleteOnThread; + friend class base::DeleteHelper; + + ~LinuxWatcher() override { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + STLDeleteElements(&readers_); + + base::MessageLoopForIO* ml = base::MessageLoopForIO::current(); + ml->RemoveDestructionObserver(this); + } + + // Removes and deletes the SocketReader. + void RemoveSocketReader(SocketReader* reader); + + base::MessageLoopForIO::FileDescriptorWatcher fd_watcher_; + + // A reference to the UI message loop (i.e., the message loop we were + // constructed on). + base::MessageLoop* ui_message_loop_; + + // The ProcessSingleton that owns us. + ProcessSingleton* const parent_; + + std::set readers_; + + DISALLOW_COPY_AND_ASSIGN(LinuxWatcher); +}; + +void ProcessSingleton::LinuxWatcher::OnFileCanReadWithoutBlocking(int fd) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + // Accepting incoming client. + sockaddr_un from; + socklen_t from_len = sizeof(from); + int connection_socket = HANDLE_EINTR(accept( + fd, reinterpret_cast(&from), &from_len)); + if (-1 == connection_socket) { + PLOG(ERROR) << "accept() failed"; + return; + } + int rv = net::SetNonBlocking(connection_socket); + DCHECK_EQ(0, rv) << "Failed to make non-blocking socket."; + SocketReader* reader = new SocketReader(this, + ui_message_loop_, + connection_socket); + readers_.insert(reader); +} + +void ProcessSingleton::LinuxWatcher::StartListening(int socket) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + // Watch for client connections on this socket. + base::MessageLoopForIO* ml = base::MessageLoopForIO::current(); + ml->AddDestructionObserver(this); + ml->WatchFileDescriptor(socket, true, base::MessageLoopForIO::WATCH_READ, + &fd_watcher_, this); +} + +void ProcessSingleton::LinuxWatcher::HandleMessage( + const std::string& current_dir, const std::vector& argv, + SocketReader* reader) { + DCHECK(ui_message_loop_ == base::MessageLoop::current()); + DCHECK(reader); + + if (parent_->notification_callback_.Run(base::CommandLine(argv), + base::FilePath(current_dir))) { + // Send back "ACK" message to prevent the client process from starting up. + reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1); + } else { + LOG(WARNING) << "Not handling interprocess notification as browser" + " is shutting down"; + // Send back "SHUTDOWN" message, so that the client process can start up + // without killing this process. + reader->FinishWithACK(kShutdownToken, arraysize(kShutdownToken) - 1); + return; + } +} + +void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(reader); + readers_.erase(reader); + delete reader; +} + +/////////////////////////////////////////////////////////////////////////////// +// ProcessSingleton::LinuxWatcher::SocketReader +// + +void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking( + int fd) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_EQ(fd, fd_); + while (bytes_read_ < sizeof(buf_)) { + ssize_t rv = HANDLE_EINTR( + read(fd, buf_ + bytes_read_, sizeof(buf_) - bytes_read_)); + if (rv < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + PLOG(ERROR) << "read() failed"; + CloseSocket(fd); + return; + } else { + // It would block, so we just return and continue to watch for the next + // opportunity to read. + return; + } + } else if (!rv) { + // No more data to read. It's time to process the message. + break; + } else { + bytes_read_ += rv; + } + } + + // Validate the message. The shortest message is kStartToken\0x\0x + const size_t kMinMessageLength = arraysize(kStartToken) + 4; + if (bytes_read_ < kMinMessageLength) { + buf_[bytes_read_] = 0; + LOG(ERROR) << "Invalid socket message (wrong length):" << buf_; + CleanupAndDeleteSelf(); + return; + } + + std::string str(buf_, bytes_read_); + std::vector tokens = base::SplitString( + str, std::string(1, kTokenDelimiter), + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + + if (tokens.size() < 3 || tokens[0] != kStartToken) { + LOG(ERROR) << "Wrong message format: " << str; + CleanupAndDeleteSelf(); + return; + } + + // Stop the expiration timer to prevent this SocketReader object from being + // terminated unexpectly. + timer_.Stop(); + + std::string current_dir = tokens[1]; + // Remove the first two tokens. The remaining tokens should be the command + // line argv array. + tokens.erase(tokens.begin()); + tokens.erase(tokens.begin()); + + // Return to the UI thread to handle opening a new browser tab. + ui_message_loop_->task_runner()->PostTask( + FROM_HERE, base::Bind(&ProcessSingleton::LinuxWatcher::HandleMessage, + parent_, current_dir, tokens, this)); + fd_reader_.StopWatchingFileDescriptor(); + + // LinuxWatcher::HandleMessage() is in charge of destroying this SocketReader + // object by invoking SocketReader::FinishWithACK(). +} + +void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK( + const char *message, size_t length) { + if (message && length) { + // Not necessary to care about the return value. + WriteToSocket(fd_, message, length); + } + + if (shutdown(fd_, SHUT_WR) < 0) + PLOG(ERROR) << "shutdown() failed"; + + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&ProcessSingleton::LinuxWatcher::RemoveSocketReader, + parent_, + this)); + // We will be deleted once the posted RemoveSocketReader task runs. +} + +/////////////////////////////////////////////////////////////////////////////// +// ProcessSingleton +// +ProcessSingleton::ProcessSingleton( + const base::FilePath& user_data_dir, + const NotificationCallback& notification_callback) + : notification_callback_(notification_callback), + current_pid_(base::GetCurrentProcId()), + watcher_(new LinuxWatcher(this)) { + socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename); + lock_path_ = user_data_dir.Append(chrome::kSingletonLockFilename); + cookie_path_ = user_data_dir.Append(chrome::kSingletonCookieFilename); + + kill_callback_ = base::Bind(&ProcessSingleton::KillProcess, + base::Unretained(this)); +} + +ProcessSingleton::~ProcessSingleton() { +} + +ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { + return NotifyOtherProcessWithTimeout( + *base::CommandLine::ForCurrentProcess(), kRetryAttempts, + base::TimeDelta::FromSeconds(kTimeoutInSeconds), true); +} + +ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( + const base::CommandLine& cmd_line, + int retry_attempts, + const base::TimeDelta& timeout, + bool kill_unresponsive) { + DCHECK_GE(retry_attempts, 0); + DCHECK_GE(timeout.InMicroseconds(), 0); + + base::TimeDelta sleep_interval = timeout / retry_attempts; + + ScopedSocket socket; + for (int retries = 0; retries <= retry_attempts; ++retries) { + // Try to connect to the socket. + if (ConnectSocket(&socket, socket_path_, cookie_path_)) + break; + + // If we're in a race with another process, they may be in Create() and have + // created the lock but not attached to the socket. So we check if the + // process with the pid from the lockfile is currently running and is a + // chrome browser. If so, we loop and try again for |timeout|. + + std::string hostname; + int pid; + if (!ParseLockPath(lock_path_, &hostname, &pid)) { + // No lockfile exists. + return PROCESS_NONE; + } + + if (hostname.empty()) { + // Invalid lockfile. + UnlinkPath(lock_path_); + return PROCESS_NONE; + } + + if (hostname != net::GetHostName() && !IsChromeProcess(pid)) { + // Locked by process on another host. If the user selected to unlock + // the profile, try to continue; otherwise quit. + if (DisplayProfileInUseError(lock_path_, hostname, pid)) { + UnlinkPath(lock_path_); + return PROCESS_NONE; + } + return PROFILE_IN_USE; + } + + if (!IsChromeProcess(pid)) { + // Orphaned lockfile (no process with pid, or non-chrome process.) + UnlinkPath(lock_path_); + return PROCESS_NONE; + } + + if (IsSameChromeInstance(pid)) { + // Orphaned lockfile (pid is part of same chrome instance we are, even + // though we haven't tried to create a lockfile yet). + UnlinkPath(lock_path_); + return PROCESS_NONE; + } + + if (retries == retry_attempts) { + // Retries failed. Kill the unresponsive chrome process and continue. + if (!kill_unresponsive || !KillProcessByLockPath()) + return PROFILE_IN_USE; + return PROCESS_NONE; + } + + base::PlatformThread::Sleep(sleep_interval); + } + + timeval socket_timeout = TimeDeltaToTimeVal(timeout); + setsockopt(socket.fd(), + SOL_SOCKET, + SO_SNDTIMEO, + &socket_timeout, + sizeof(socket_timeout)); + + // Found another process, prepare our command line + // format is "START\0\0\0...\0". + std::string to_send(kStartToken); + to_send.push_back(kTokenDelimiter); + + base::FilePath current_dir; + if (!PathService::Get(base::DIR_CURRENT, ¤t_dir)) + return PROCESS_NONE; + to_send.append(current_dir.value()); + + const std::vector& argv = cmd_line.argv(); + for (std::vector::const_iterator it = argv.begin(); + it != argv.end(); ++it) { + to_send.push_back(kTokenDelimiter); + to_send.append(*it); + } + + // Send the message + if (!WriteToSocket(socket.fd(), to_send.data(), to_send.length())) { + // Try to kill the other process, because it might have been dead. + if (!kill_unresponsive || !KillProcessByLockPath()) + return PROFILE_IN_USE; + return PROCESS_NONE; + } + + if (shutdown(socket.fd(), SHUT_WR) < 0) + PLOG(ERROR) << "shutdown() failed"; + + // Read ACK message from the other process. It might be blocked for a certain + // timeout, to make sure the other process has enough time to return ACK. + char buf[kMaxACKMessageLength + 1]; + ssize_t len = ReadFromSocket(socket.fd(), buf, kMaxACKMessageLength, timeout); + + // Failed to read ACK, the other process might have been frozen. + if (len <= 0) { + if (!kill_unresponsive || !KillProcessByLockPath()) + return PROFILE_IN_USE; + return PROCESS_NONE; + } + + buf[len] = '\0'; + if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) { + // The other process is shutting down, it's safe to start a new process. + return PROCESS_NONE; + } else if (strncmp(buf, kACKToken, arraysize(kACKToken) - 1) == 0) { +#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) + // Likely NULL in unit tests. + views::LinuxUI* linux_ui = views::LinuxUI::instance(); + if (linux_ui) + linux_ui->NotifyWindowManagerStartupComplete(); +#endif + + // Assume the other process is handling the request. + return PROCESS_NOTIFIED; + } + + NOTREACHED() << "The other process returned unknown message: " << buf; + return PROCESS_NOTIFIED; +} + +ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate() { + return NotifyOtherProcessWithTimeoutOrCreate( + *base::CommandLine::ForCurrentProcess(), kRetryAttempts, + base::TimeDelta::FromSeconds(kTimeoutInSeconds)); +} + +ProcessSingleton::NotifyResult +ProcessSingleton::NotifyOtherProcessWithTimeoutOrCreate( + const base::CommandLine& command_line, + int retry_attempts, + const base::TimeDelta& timeout) { + NotifyResult result = NotifyOtherProcessWithTimeout( + command_line, retry_attempts, timeout, true); + if (result != PROCESS_NONE) + return result; + if (Create()) + return PROCESS_NONE; + // If the Create() failed, try again to notify. (It could be that another + // instance was starting at the same time and managed to grab the lock before + // we did.) + // This time, we don't want to kill anything if we aren't successful, since we + // aren't going to try to take over the lock ourselves. + result = NotifyOtherProcessWithTimeout( + command_line, retry_attempts, timeout, false); + if (result != PROCESS_NONE) + return result; + + return LOCK_ERROR; +} + +void ProcessSingleton::OverrideCurrentPidForTesting(base::ProcessId pid) { + current_pid_ = pid; +} + +void ProcessSingleton::OverrideKillCallbackForTesting( + const base::Callback& callback) { + kill_callback_ = callback; +} + +void ProcessSingleton::DisablePromptForTesting() { + g_disable_prompt = true; +} + +bool ProcessSingleton::Create() { + int sock; + sockaddr_un addr; + + // The symlink lock is pointed to the hostname and process id, so other + // processes can find it out. + base::FilePath symlink_content(base::StringPrintf( + "%s%c%u", + net::GetHostName().c_str(), + kLockDelimiter, + current_pid_)); + + // Create symbol link before binding the socket, to ensure only one instance + // can have the socket open. + if (!SymlinkPath(symlink_content, lock_path_)) { + // TODO(jackhou): Remove this case once this code is stable on Mac. + // http://crbug.com/367612 +#if defined(OS_MACOSX) + // On Mac, an existing non-symlink lock file means the lock could be held by + // the old process singleton code. If we can successfully replace the lock, + // continue as normal. + if (base::IsLink(lock_path_) || + !ReplaceOldSingletonLock(symlink_content, lock_path_)) { + return false; + } +#else + // If we failed to create the lock, most likely another instance won the + // startup race. + return false; +#endif + } + + // Create the socket file somewhere in /tmp which is usually mounted as a + // normal filesystem. Some network filesystems (notably AFS) are screwy and + // do not support Unix domain sockets. + if (!socket_dir_.CreateUniqueTempDir()) { + LOG(ERROR) << "Failed to create socket directory."; + return false; + } + + // Check that the directory was created with the correct permissions. + int dir_mode = 0; + CHECK(base::GetPosixFilePermissions(socket_dir_.path(), &dir_mode) && + dir_mode == base::FILE_PERMISSION_USER_MASK) + << "Temp directory mode is not 700: " << std::oct << dir_mode; + + // Setup the socket symlink and the two cookies. + base::FilePath socket_target_path = + socket_dir_.path().Append(chrome::kSingletonSocketFilename); + base::FilePath cookie(GenerateCookie()); + base::FilePath remote_cookie_path = + socket_dir_.path().Append(chrome::kSingletonCookieFilename); + UnlinkPath(socket_path_); + UnlinkPath(cookie_path_); + if (!SymlinkPath(socket_target_path, socket_path_) || + !SymlinkPath(cookie, cookie_path_) || + !SymlinkPath(cookie, remote_cookie_path)) { + // We've already locked things, so we can't have lost the startup race, + // but something doesn't like us. + LOG(ERROR) << "Failed to create symlinks."; + if (!socket_dir_.Delete()) + LOG(ERROR) << "Encountered a problem when deleting socket directory."; + return false; + } + + SetupSocket(socket_target_path.value(), &sock, &addr); + + if (bind(sock, reinterpret_cast(&addr), sizeof(addr)) < 0) { + PLOG(ERROR) << "Failed to bind() " << socket_target_path.value(); + CloseSocket(sock); + return false; + } + + if (listen(sock, 5) < 0) + NOTREACHED() << "listen failed: " << base::safe_strerror(errno); + + DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO)); + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&ProcessSingleton::LinuxWatcher::StartListening, + watcher_.get(), + sock)); + + return true; +} + +void ProcessSingleton::Cleanup() { + UnlinkPath(socket_path_); + UnlinkPath(cookie_path_); + UnlinkPath(lock_path_); +} + +bool ProcessSingleton::IsSameChromeInstance(pid_t pid) { + pid_t cur_pid = current_pid_; + while (pid != cur_pid) { + pid = base::GetParentProcessId(pid); + if (pid < 0) + return false; + if (!IsChromeProcess(pid)) + return false; + } + return true; +} + +bool ProcessSingleton::KillProcessByLockPath() { + std::string hostname; + int pid; + ParseLockPath(lock_path_, &hostname, &pid); + + if (!hostname.empty() && hostname != net::GetHostName()) { + return DisplayProfileInUseError(lock_path_, hostname, pid); + } + UnlinkPath(lock_path_); + + if (IsSameChromeInstance(pid)) + return true; + + if (pid > 0) { + kill_callback_.Run(pid); + return true; + } + + LOG(ERROR) << "Failed to extract pid from path: " << lock_path_.value(); + return true; +} + +void ProcessSingleton::KillProcess(int pid) { + // TODO(james.su@gmail.com): Is SIGKILL ok? + int rv = kill(static_cast(pid), SIGKILL); + // ESRCH = No Such Process (can happen if the other process is already in + // progress of shutting down and finishes before we try to kill it). + DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " + << base::safe_strerror(errno); +} \ No newline at end of file diff --git a/chromium_src/chrome/browser/process_singleton_startup_lock.cc b/chromium_src/chrome/browser/process_singleton_startup_lock.cc new file mode 100644 index 000000000000..b97ada658c35 --- /dev/null +++ b/chromium_src/chrome/browser/process_singleton_startup_lock.cc @@ -0,0 +1,53 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/process_singleton_startup_lock.h" + +#include "base/bind.h" +#include "base/logging.h" + +ProcessSingletonStartupLock::ProcessSingletonStartupLock( + const ProcessSingleton::NotificationCallback& original_callback) + : locked_(true), + original_callback_(original_callback) {} + +ProcessSingletonStartupLock::~ProcessSingletonStartupLock() {} + +ProcessSingleton::NotificationCallback +ProcessSingletonStartupLock::AsNotificationCallback() { + return base::Bind(&ProcessSingletonStartupLock::NotificationCallbackImpl, + base::Unretained(this)); +} + +void ProcessSingletonStartupLock::Unlock() { + DCHECK(CalledOnValidThread()); + locked_ = false; + + // Replay the command lines of the messages which were received while the + // ProcessSingleton was locked. Only replay each message once. + std::set replayed_messages; + for (std::vector::const_iterator it = + saved_startup_messages_.begin(); + it != saved_startup_messages_.end(); ++it) { + if (replayed_messages.find(*it) != replayed_messages.end()) + continue; + original_callback_.Run(base::CommandLine(it->first), it->second); + replayed_messages.insert(*it); + } + saved_startup_messages_.clear(); +} + +bool ProcessSingletonStartupLock::NotificationCallbackImpl( + const base::CommandLine& command_line, + const base::FilePath& current_directory) { + if (locked_) { + // If locked, it means we are not ready to process this message because + // we are probably in a first run critical phase. + saved_startup_messages_.push_back( + std::make_pair(command_line.argv(), current_directory)); + return true; + } else { + return original_callback_.Run(command_line, current_directory); + } +} \ No newline at end of file diff --git a/chromium_src/chrome/browser/process_singleton_startup_lock.h b/chromium_src/chrome/browser/process_singleton_startup_lock.h new file mode 100644 index 000000000000..3df51d8b177b --- /dev/null +++ b/chromium_src/chrome/browser/process_singleton_startup_lock.h @@ -0,0 +1,57 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ +#define CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ + +#include +#include +#include + +#include "base/basictypes.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/threading/non_thread_safe.h" +#include "chrome/browser/process_singleton.h" + +// Provides a ProcessSingleton::NotificationCallback that can queue up +// command-line invocations during startup and execute them when startup +// completes. +// +// The object starts in a locked state. |Unlock()| must be called +// when the process is prepared to handle command-line invocations. +// +// Once unlocked, notifications are forwarded to a wrapped NotificationCallback. +class ProcessSingletonStartupLock : public base::NonThreadSafe { + public: + explicit ProcessSingletonStartupLock( + const ProcessSingleton::NotificationCallback& original_callback); + ~ProcessSingletonStartupLock(); + + // Returns the ProcessSingleton::NotificationCallback. + // The callback is only valid during the lifetime of the + // ProcessSingletonStartupLock instance. + ProcessSingleton::NotificationCallback AsNotificationCallback(); + + // Executes previously queued command-line invocations and allows future + // invocations to be executed immediately. + void Unlock(); + + bool locked() { return locked_; } + + private: + typedef std::pair + DelayedStartupMessage; + + bool NotificationCallbackImpl(const base::CommandLine& command_line, + const base::FilePath& current_directory); + + bool locked_; + std::vector saved_startup_messages_; + ProcessSingleton::NotificationCallback original_callback_; + + DISALLOW_COPY_AND_ASSIGN(ProcessSingletonStartupLock); +}; + +#endif // CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ \ No newline at end of file diff --git a/chromium_src/chrome/browser/process_singleton_win.cc b/chromium_src/chrome/browser/process_singleton_win.cc new file mode 100644 index 000000000000..623aa7f42f7f --- /dev/null +++ b/chromium_src/chrome/browser/process_singleton_win.cc @@ -0,0 +1,441 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/process_singleton.h" + +#include + +#include "base/base_paths.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/process/process.h" +#include "base/process/process_info.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" +#include "base/win/metro.h" +#include "base/win/registry.h" +#include "base/win/scoped_handle.h" +#include "base/win/windows_version.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part.h" +#include "chrome/browser/chrome_process_finder_win.h" +#include "chrome/browser/metro_utils/metro_chrome_win.h" +#include "chrome/browser/shell_integration.h" +#include "chrome/browser/ui/simple_message_box.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_paths_internal.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/grit/chromium_strings.h" +#include "chrome/installer/util/wmi.h" +#include "content/public/common/result_codes.h" +#include "net/base/escape.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/win/hwnd_util.h" + +namespace { + +const char kLockfile[] = "lockfile"; + +const int kMetroChromeActivationTimeoutMs = 3000; + +// A helper class that acquires the given |mutex| while the AutoLockMutex is in +// scope. +class AutoLockMutex { + public: + explicit AutoLockMutex(HANDLE mutex) : mutex_(mutex) { + DWORD result = ::WaitForSingleObject(mutex_, INFINITE); + DPCHECK(result == WAIT_OBJECT_0) << "Result = " << result; + } + + ~AutoLockMutex() { + BOOL released = ::ReleaseMutex(mutex_); + DPCHECK(released); + } + + private: + HANDLE mutex_; + DISALLOW_COPY_AND_ASSIGN(AutoLockMutex); +}; + +// A helper class that releases the given |mutex| while the AutoUnlockMutex is +// in scope and immediately re-acquires it when going out of scope. +class AutoUnlockMutex { + public: + explicit AutoUnlockMutex(HANDLE mutex) : mutex_(mutex) { + BOOL released = ::ReleaseMutex(mutex_); + DPCHECK(released); + } + + ~AutoUnlockMutex() { + DWORD result = ::WaitForSingleObject(mutex_, INFINITE); + DPCHECK(result == WAIT_OBJECT_0) << "Result = " << result; + } + + private: + HANDLE mutex_; + DISALLOW_COPY_AND_ASSIGN(AutoUnlockMutex); +}; + +// Checks the visibility of the enumerated window and signals once a visible +// window has been found. +BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) { + bool* result = reinterpret_cast(param); + *result = ::IsWindowVisible(window) != 0; + // Stops enumeration if a visible window has been found. + return !*result; +} + +bool ParseCommandLine(const COPYDATASTRUCT* cds, + base::CommandLine* parsed_command_line, + base::FilePath* current_directory) { + // We should have enough room for the shortest command (min_message_size) + // and also be a multiple of wchar_t bytes. The shortest command + // possible is L"START\0\0" (empty current directory and command line). + static const int min_message_size = 7; + if (cds->cbData < min_message_size * sizeof(wchar_t) || + cds->cbData % sizeof(wchar_t) != 0) { + LOG(WARNING) << "Invalid WM_COPYDATA, length = " << cds->cbData; + return false; + } + + // We split the string into 4 parts on NULLs. + DCHECK(cds->lpData); + const std::wstring msg(static_cast(cds->lpData), + cds->cbData / sizeof(wchar_t)); + const std::wstring::size_type first_null = msg.find_first_of(L'\0'); + if (first_null == 0 || first_null == std::wstring::npos) { + // no NULL byte, don't know what to do + LOG(WARNING) << "Invalid WM_COPYDATA, length = " << msg.length() << + ", first null = " << first_null; + return false; + } + + // Decode the command, which is everything until the first NULL. + if (msg.substr(0, first_null) == L"START") { + // Another instance is starting parse the command line & do what it would + // have done. + VLOG(1) << "Handling STARTUP request from another process"; + const std::wstring::size_type second_null = + msg.find_first_of(L'\0', first_null + 1); + if (second_null == std::wstring::npos || + first_null == msg.length() - 1 || second_null == msg.length()) { + LOG(WARNING) << "Invalid format for start command, we need a string in 4 " + "parts separated by NULLs"; + return false; + } + + // Get current directory. + *current_directory = base::FilePath(msg.substr(first_null + 1, + second_null - first_null)); + + const std::wstring::size_type third_null = + msg.find_first_of(L'\0', second_null + 1); + if (third_null == std::wstring::npos || + third_null == msg.length()) { + LOG(WARNING) << "Invalid format for start command, we need a string in 4 " + "parts separated by NULLs"; + } + + // Get command line. + const std::wstring cmd_line = + msg.substr(second_null + 1, third_null - second_null); + *parsed_command_line = base::CommandLine::FromString(cmd_line); + return true; + } + return false; +} + +bool ProcessLaunchNotification( + const ProcessSingleton::NotificationCallback& notification_callback, + UINT message, + WPARAM wparam, + LPARAM lparam, + LRESULT* result) { + if (message != WM_COPYDATA) + return false; + + // Handle the WM_COPYDATA message from another process. + const COPYDATASTRUCT* cds = reinterpret_cast(lparam); + + base::CommandLine parsed_command_line(base::CommandLine::NO_PROGRAM); + base::FilePath current_directory; + if (!ParseCommandLine(cds, &parsed_command_line, ¤t_directory)) { + *result = TRUE; + return true; + } + + *result = notification_callback.Run(parsed_command_line, current_directory) ? + TRUE : FALSE; + return true; +} + +// Returns true if Chrome needs to be relaunched into Windows 8 immersive mode. +// Following conditions apply:- +// 1. Windows 8 or greater. +// 2. Not in Windows 8 immersive mode. +// 3. Chrome is default browser. +// 4. Process integrity level is not high. +// 5. The profile data directory is the default directory. +// 6. Last used mode was immersive/machine is a tablet. +// TODO(ananta) +// Move this function to a common place as the Windows 8 delegate_execute +// handler can possibly use this. +bool ShouldLaunchInWindows8ImmersiveMode(const base::FilePath& user_data_dir) { + // Returning false from this function doesn't mean we don't launch immersive + // mode in Aura. This function is specifically called in case when we need + // to relaunch desktop launched chrome into immersive mode through 'relaunch' + // menu. In case of Aura, we will use delegate_execute to do the relaunch. + return false; +} + +bool DisplayShouldKillMessageBox() { + return chrome::ShowMessageBox( + NULL, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), + l10n_util::GetStringUTF16(IDS_BROWSER_HUNGBROWSER_MESSAGE), + chrome::MESSAGE_BOX_TYPE_QUESTION) != + chrome::MESSAGE_BOX_RESULT_NO; +} + +} // namespace + +// Microsoft's Softricity virtualization breaks the sandbox processes. +// So, if we detect the Softricity DLL we use WMI Win32_Process.Create to +// break out of the virtualization environment. +// http://code.google.com/p/chromium/issues/detail?id=43650 +bool ProcessSingleton::EscapeVirtualization( + const base::FilePath& user_data_dir) { + if (::GetModuleHandle(L"sftldr_wow64.dll") || + ::GetModuleHandle(L"sftldr.dll")) { + int process_id; + if (!installer::WMIProcess::Launch(::GetCommandLineW(), &process_id)) + return false; + is_virtualized_ = true; + // The new window was spawned from WMI, and won't be in the foreground. + // So, first we sleep while the new chrome.exe instance starts (because + // WaitForInputIdle doesn't work here). Then we poll for up to two more + // seconds and make the window foreground if we find it (or we give up). + HWND hwnd = 0; + ::Sleep(90); + for (int tries = 200; tries; --tries) { + hwnd = chrome::FindRunningChromeWindow(user_data_dir); + if (hwnd) { + ::SetForegroundWindow(hwnd); + break; + } + ::Sleep(10); + } + return true; + } + return false; +} + +ProcessSingleton::ProcessSingleton( + const base::FilePath& user_data_dir, + const NotificationCallback& notification_callback) + : notification_callback_(notification_callback), + is_virtualized_(false), + lock_file_(INVALID_HANDLE_VALUE), + user_data_dir_(user_data_dir), + should_kill_remote_process_callback_( + base::Bind(&DisplayShouldKillMessageBox)) { +} + +ProcessSingleton::~ProcessSingleton() { + if (lock_file_ != INVALID_HANDLE_VALUE) + ::CloseHandle(lock_file_); +} + +// Code roughly based on Mozilla. +ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { + if (is_virtualized_) + return PROCESS_NOTIFIED; // We already spawned the process in this case. + if (lock_file_ == INVALID_HANDLE_VALUE && !remote_window_) { + return LOCK_ERROR; + } else if (!remote_window_) { + return PROCESS_NONE; + } + + switch (chrome::AttemptToNotifyRunningChrome(remote_window_, false)) { + case chrome::NOTIFY_SUCCESS: + return PROCESS_NOTIFIED; + case chrome::NOTIFY_FAILED: + remote_window_ = NULL; + return PROCESS_NONE; + case chrome::NOTIFY_WINDOW_HUNG: + // Fall through and potentially terminate the hung browser. + break; + } + + DWORD process_id = 0; + DWORD thread_id = ::GetWindowThreadProcessId(remote_window_, &process_id); + if (!thread_id || !process_id) { + remote_window_ = NULL; + return PROCESS_NONE; + } + base::Process process = base::Process::Open(process_id); + + // The window is hung. Scan for every window to find a visible one. + bool visible_window = false; + ::EnumThreadWindows(thread_id, + &BrowserWindowEnumeration, + reinterpret_cast(&visible_window)); + + // If there is a visible browser window, ask the user before killing it. + if (visible_window && !should_kill_remote_process_callback_.Run()) { + // The user denied. Quit silently. + return PROCESS_NOTIFIED; + } + + // Time to take action. Kill the browser process. + process.Terminate(content::RESULT_CODE_HUNG, true); + remote_window_ = NULL; + return PROCESS_NONE; +} + +ProcessSingleton::NotifyResult +ProcessSingleton::NotifyOtherProcessOrCreate() { + ProcessSingleton::NotifyResult result = PROCESS_NONE; + if (!Create()) { + result = NotifyOtherProcess(); + if (result == PROCESS_NONE) + result = PROFILE_IN_USE; + } else { + g_browser_process->platform_part()->PlatformSpecificCommandLineProcessing( + *base::CommandLine::ForCurrentProcess()); + } + return result; +} + +// Look for a Chrome instance that uses the same profile directory. If there +// isn't one, create a message window with its title set to the profile +// directory path. +bool ProcessSingleton::Create() { + static const wchar_t kMutexName[] = L"Local\\ChromeProcessSingletonStartup!"; + static const wchar_t kMetroActivationEventName[] = + L"Local\\ChromeProcessSingletonStartupMetroActivation!"; + + remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); + if (!remote_window_ && !EscapeVirtualization(user_data_dir_)) { + // Make sure we will be the one and only process creating the window. + // We use a named Mutex since we are protecting against multi-process + // access. As documented, it's clearer to NOT request ownership on creation + // since it isn't guaranteed we will get it. It is better to create it + // without ownership and explicitly get the ownership afterward. + base::win::ScopedHandle only_me(::CreateMutex(NULL, FALSE, kMutexName)); + if (!only_me.IsValid()) { + DPLOG(FATAL) << "CreateMutex failed"; + return false; + } + + AutoLockMutex auto_lock_only_me(only_me.Get()); + + // We now own the mutex so we are the only process that can create the + // window at this time, but we must still check if someone created it + // between the time where we looked for it above and the time the mutex + // was given to us. + remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); + + + // In Win8+, a new Chrome process launched in Desktop mode may need to be + // transmuted into Metro Chrome (see ShouldLaunchInWindows8ImmersiveMode for + // heuristics). To accomplish this, the current Chrome activates Metro + // Chrome, releases the startup mutex, and waits for metro Chrome to take + // the singleton. From that point onward, the command line for this Chrome + // process will be sent to Metro Chrome by the usual channels. + if (!remote_window_ && base::win::GetVersion() >= base::win::VERSION_WIN8 && + !base::win::IsMetroProcess()) { + // |metro_activation_event| is created right before activating a Metro + // Chrome (note that there can only be one Metro Chrome process; by OS + // design); all following Desktop processes will then wait for this event + // to be signaled by Metro Chrome which will do so as soon as it grabs + // this singleton (should any of the waiting processes timeout waiting for + // the signal they will try to grab the singleton for themselves which + // will result in a forced Desktop Chrome launch in the worst case). + base::win::ScopedHandle metro_activation_event( + ::OpenEvent(SYNCHRONIZE, FALSE, kMetroActivationEventName)); + if (!metro_activation_event.IsValid() && + ShouldLaunchInWindows8ImmersiveMode(user_data_dir_)) { + // No Metro activation is under way, but the desire is to launch in + // Metro mode: activate and rendez-vous with the activated process. + metro_activation_event.Set( + ::CreateEvent(NULL, TRUE, FALSE, kMetroActivationEventName)); + if (!chrome::ActivateMetroChrome()) { + // Failed to launch immersive Chrome, default to launching on Desktop. + LOG(ERROR) << "Failed to launch immersive chrome"; + metro_activation_event.Close(); + } + } + + if (metro_activation_event.IsValid()) { + // Release |only_me| (to let Metro Chrome grab this singleton) and wait + // until the event is signaled (i.e. Metro Chrome was successfully + // activated). Ignore timeout waiting for |metro_activation_event|. + { + AutoUnlockMutex auto_unlock_only_me(only_me.Get()); + + DWORD result = ::WaitForSingleObject(metro_activation_event.Get(), + kMetroChromeActivationTimeoutMs); + DPCHECK(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT) + << "Result = " << result; + } + + // Check if this singleton was successfully grabbed by another process + // (hopefully Metro Chrome). Failing to do so, this process will grab + // the singleton and launch in Desktop mode. + remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); + } + } + + if (!remote_window_) { + // We have to make sure there is no Chrome instance running on another + // machine that uses the same profile. + base::FilePath lock_file_path = user_data_dir_.AppendASCII(kLockfile); + lock_file_ = ::CreateFile(lock_file_path.value().c_str(), + GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | + FILE_FLAG_DELETE_ON_CLOSE, + NULL); + DWORD error = ::GetLastError(); + LOG_IF(WARNING, lock_file_ != INVALID_HANDLE_VALUE && + error == ERROR_ALREADY_EXISTS) << "Lock file exists but is writable."; + LOG_IF(ERROR, lock_file_ == INVALID_HANDLE_VALUE) + << "Lock file can not be created! Error code: " << error; + + if (lock_file_ != INVALID_HANDLE_VALUE) { + // Set the window's title to the path of our user data directory so + // other Chrome instances can decide if they should forward to us. + bool result = window_.CreateNamed( + base::Bind(&ProcessLaunchNotification, notification_callback_), + user_data_dir_.value()); + CHECK(result && window_.hwnd()); + } + + if (base::win::GetVersion() >= base::win::VERSION_WIN8) { + // Make sure no one is still waiting on Metro activation whether it + // succeeded (i.e., this is the Metro process) or failed. + base::win::ScopedHandle metro_activation_event( + ::OpenEvent(EVENT_MODIFY_STATE, FALSE, kMetroActivationEventName)); + if (metro_activation_event.IsValid()) + ::SetEvent(metro_activation_event.Get()); + } + } + } + + return window_.hwnd() != NULL; +} + +void ProcessSingleton::Cleanup() { +} + +void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting( + const ShouldKillRemoteProcessCallback& display_dialog_callback) { + should_kill_remote_process_callback_ = display_dialog_callback; +} From 5886398f22bbdc1ed9e0bb3c4fca44bdaa82090b Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 14:21:06 -0700 Subject: [PATCH 270/738] Port our changes over --- .../browser/chrome_process_finder_win.cc | 9 -- .../chrome/browser/process_singleton.h | 6 +- .../chrome/browser/process_singleton_posix.cc | 55 +++---- .../chrome/browser/process_singleton_win.cc | 145 ++---------------- 4 files changed, 31 insertions(+), 184 deletions(-) diff --git a/chromium_src/chrome/browser/chrome_process_finder_win.cc b/chromium_src/chrome/browser/chrome_process_finder_win.cc index 13c4a0eb5a56..299877a65db6 100644 --- a/chromium_src/chrome/browser/chrome_process_finder_win.cc +++ b/chromium_src/chrome/browser/chrome_process_finder_win.cc @@ -20,8 +20,6 @@ #include "base/win/scoped_handle.h" #include "base/win/win_util.h" #include "base/win/windows_version.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_switches.h" namespace { @@ -45,13 +43,6 @@ NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window, return NOTIFY_FAILED; base::CommandLine command_line(*base::CommandLine::ForCurrentProcess()); - command_line.AppendSwitchASCII( - switches::kOriginalProcessStartTime, - base::Int64ToString( - base::CurrentProcessInfo::CreationTime().ToInternalValue())); - - if (fast_start) - command_line.AppendSwitch(switches::kFastStart); // Send the command line to the remote chrome window. // Format is "START\0<<>>\0<<>>". diff --git a/chromium_src/chrome/browser/process_singleton.h b/chromium_src/chrome/browser/process_singleton.h index 9d99b02b9f4c..3265c9597a77 100644 --- a/chromium_src/chrome/browser/process_singleton.h +++ b/chromium_src/chrome/browser/process_singleton.h @@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_PROCESS_SINGLETON_H_ #define CHROME_BROWSER_PROCESS_SINGLETON_H_ -#include "build/build_config.h" - #if defined(OS_WIN) #include #endif // defined(OS_WIN) @@ -128,8 +126,6 @@ class ProcessSingleton : public base::NonThreadSafe { NotificationCallback notification_callback_; // Handler for notifications. #if defined(OS_WIN) - bool EscapeVirtualization(const base::FilePath& user_data_dir); - HWND remote_window_; // The HWND_MESSAGE of another browser. base::win::MessageWindow window_; // The message-only window. bool is_virtualized_; // Stuck inside Microsoft Softricity VM environment. @@ -180,4 +176,4 @@ class ProcessSingleton : public base::NonThreadSafe { DISALLOW_COPY_AND_ASSIGN(ProcessSingleton); }; -#endif // CHROME_BROWSER_PROCESS_SINGLETON_H_ \ No newline at end of file +#endif // CHROME_BROWSER_PROCESS_SINGLETON_H_ diff --git a/chromium_src/chrome/browser/process_singleton_posix.cc b/chromium_src/chrome/browser/process_singleton_posix.cc index e855207ea77b..5ab6eb6d8a78 100644 --- a/chromium_src/chrome/browser/process_singleton_posix.cc +++ b/chromium_src/chrome/browser/process_singleton_posix.cc @@ -77,17 +77,10 @@ #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/grit/chromium_strings.h" -#include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_thread.h" #include "net/base/net_util.h" #include "ui/base/l10n/l10n_util.h" -#if defined(OS_LINUX) -#include "chrome/browser/ui/process_singleton_dialog_linux.h" -#endif - #if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) #include "ui/views/linux_ui/linux_ui.h" #endif @@ -112,6 +105,13 @@ const int kMaxACKMessageLength = arraysize(kShutdownToken) - 1; const char kLockDelimiter = '-'; +const base::FilePath::CharType kSingletonCookieFilename[] = + FILE_PATH_LITERAL("SingletonCookie"); + +const base::FilePath::CharType kSingletonLockFilename[] = FILE_PATH_LITERAL("SingletonLock"); +const base::FilePath::CharType kSingletonSocketFilename[] = + FILE_PATH_LITERAL("SingletonSocket"); + // Set the close-on-exec bit on a file descriptor. // Returns 0 on success, -1 on failure. int SetCloseOnExec(int fd) { @@ -304,33 +304,20 @@ bool ParseLockPath(const base::FilePath& path, bool DisplayProfileInUseError(const base::FilePath& lock_path, const std::string& hostname, int pid) { - base::string16 error = l10n_util::GetStringFUTF16( - IDS_PROFILE_IN_USE_POSIX, - base::IntToString16(pid), - base::ASCIIToUTF16(hostname)); - LOG(ERROR) << error; - - if (g_disable_prompt) - return false; - -#if defined(OS_LINUX) - base::string16 relaunch_button_text = l10n_util::GetStringUTF16( - IDS_PROFILE_IN_USE_LINUX_RELAUNCH); - return ShowProcessSingletonDialog(error, relaunch_button_text); -#elif defined(OS_MACOSX) - // On Mac, always usurp the lock. + // TODO: yolo return true; -#endif - - NOTREACHED(); - return false; } bool IsChromeProcess(pid_t pid) { base::FilePath other_chrome_path(base::GetProcessExecutablePath(pid)); + + auto command_line = base::CommandLine::ForCurrentProcess(); + base::FilePath exec_path(command_line->GetProgram()); + PathService::Get(base::FILE_EXE, &exec_path); + return (!other_chrome_path.empty() && other_chrome_path.BaseName() == - base::FilePath(chrome::kBrowserProcessExecutableName)); + exec_path.BaseName()); } // A helper class to hold onto a socket. @@ -371,7 +358,7 @@ bool ConnectSocket(ScopedSocket* socket, if (cookie.empty()) return false; base::FilePath remote_cookie = socket_target.DirName(). - Append(chrome::kSingletonCookieFilename); + Append(kSingletonCookieFilename); // Verify the cookie before connecting. if (!CheckCookie(remote_cookie, cookie)) return false; @@ -516,7 +503,7 @@ class ProcessSingleton::LinuxWatcher // reads. size_t bytes_read_; - base::OneShotTimer timer_; + base::OneShotTimer timer_; DISALLOW_COPY_AND_ASSIGN(SocketReader); }; @@ -731,9 +718,9 @@ ProcessSingleton::ProcessSingleton( : notification_callback_(notification_callback), current_pid_(base::GetCurrentProcId()), watcher_(new LinuxWatcher(this)) { - socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename); - lock_path_ = user_data_dir.Append(chrome::kSingletonLockFilename); - cookie_path_ = user_data_dir.Append(chrome::kSingletonCookieFilename); + socket_path_ = user_data_dir.Append(kSingletonSocketFilename); + lock_path_ = user_data_dir.Append(kSingletonLockFilename); + cookie_path_ = user_data_dir.Append(kSingletonCookieFilename); kill_callback_ = base::Bind(&ProcessSingleton::KillProcess, base::Unretained(this)); @@ -973,10 +960,10 @@ bool ProcessSingleton::Create() { // Setup the socket symlink and the two cookies. base::FilePath socket_target_path = - socket_dir_.path().Append(chrome::kSingletonSocketFilename); + socket_dir_.path().Append(kSingletonSocketFilename); base::FilePath cookie(GenerateCookie()); base::FilePath remote_cookie_path = - socket_dir_.path().Append(chrome::kSingletonCookieFilename); + socket_dir_.path().Append(kSingletonCookieFilename); UnlinkPath(socket_path_); UnlinkPath(cookie_path_); if (!SymlinkPath(socket_target_path, socket_path_) || diff --git a/chromium_src/chrome/browser/process_singleton_win.cc b/chromium_src/chrome/browser/process_singleton_win.cc index 623aa7f42f7f..bedc861c4068 100644 --- a/chromium_src/chrome/browser/process_singleton_win.cc +++ b/chromium_src/chrome/browser/process_singleton_win.cc @@ -20,18 +20,7 @@ #include "base/win/registry.h" #include "base/win/scoped_handle.h" #include "base/win/windows_version.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chrome_process_finder_win.h" -#include "chrome/browser/metro_utils/metro_chrome_win.h" -#include "chrome/browser/shell_integration.h" -#include "chrome/browser/ui/simple_message_box.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_paths_internal.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/grit/chromium_strings.h" -#include "chrome/installer/util/wmi.h" #include "content/public/common/result_codes.h" #include "net/base/escape.h" #include "ui/base/l10n/l10n_util.h" @@ -41,8 +30,6 @@ namespace { const char kLockfile[] = "lockfile"; -const int kMetroChromeActivationTimeoutMs = 3000; - // A helper class that acquires the given |mutex| while the AutoLockMutex is in // scope. class AutoLockMutex { @@ -174,66 +161,14 @@ bool ProcessLaunchNotification( return true; } -// Returns true if Chrome needs to be relaunched into Windows 8 immersive mode. -// Following conditions apply:- -// 1. Windows 8 or greater. -// 2. Not in Windows 8 immersive mode. -// 3. Chrome is default browser. -// 4. Process integrity level is not high. -// 5. The profile data directory is the default directory. -// 6. Last used mode was immersive/machine is a tablet. -// TODO(ananta) -// Move this function to a common place as the Windows 8 delegate_execute -// handler can possibly use this. -bool ShouldLaunchInWindows8ImmersiveMode(const base::FilePath& user_data_dir) { - // Returning false from this function doesn't mean we don't launch immersive - // mode in Aura. This function is specifically called in case when we need - // to relaunch desktop launched chrome into immersive mode through 'relaunch' - // menu. In case of Aura, we will use delegate_execute to do the relaunch. +bool TerminateAppWithError() { + // TODO: This is called when the secondary process can't ping the primary + // process. Need to find out what to do here. return false; } -bool DisplayShouldKillMessageBox() { - return chrome::ShowMessageBox( - NULL, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), - l10n_util::GetStringUTF16(IDS_BROWSER_HUNGBROWSER_MESSAGE), - chrome::MESSAGE_BOX_TYPE_QUESTION) != - chrome::MESSAGE_BOX_RESULT_NO; -} - } // namespace -// Microsoft's Softricity virtualization breaks the sandbox processes. -// So, if we detect the Softricity DLL we use WMI Win32_Process.Create to -// break out of the virtualization environment. -// http://code.google.com/p/chromium/issues/detail?id=43650 -bool ProcessSingleton::EscapeVirtualization( - const base::FilePath& user_data_dir) { - if (::GetModuleHandle(L"sftldr_wow64.dll") || - ::GetModuleHandle(L"sftldr.dll")) { - int process_id; - if (!installer::WMIProcess::Launch(::GetCommandLineW(), &process_id)) - return false; - is_virtualized_ = true; - // The new window was spawned from WMI, and won't be in the foreground. - // So, first we sleep while the new chrome.exe instance starts (because - // WaitForInputIdle doesn't work here). Then we poll for up to two more - // seconds and make the window foreground if we find it (or we give up). - HWND hwnd = 0; - ::Sleep(90); - for (int tries = 200; tries; --tries) { - hwnd = chrome::FindRunningChromeWindow(user_data_dir); - if (hwnd) { - ::SetForegroundWindow(hwnd); - break; - } - ::Sleep(10); - } - return true; - } - return false; -} - ProcessSingleton::ProcessSingleton( const base::FilePath& user_data_dir, const NotificationCallback& notification_callback) @@ -242,7 +177,7 @@ ProcessSingleton::ProcessSingleton( lock_file_(INVALID_HANDLE_VALUE), user_data_dir_(user_data_dir), should_kill_remote_process_callback_( - base::Bind(&DisplayShouldKillMessageBox)) { + base::Bind(&TerminateAppWithError)) { } ProcessSingleton::~ProcessSingleton() { @@ -305,8 +240,9 @@ ProcessSingleton::NotifyOtherProcessOrCreate() { if (result == PROCESS_NONE) result = PROFILE_IN_USE; } else { - g_browser_process->platform_part()->PlatformSpecificCommandLineProcessing( - *base::CommandLine::ForCurrentProcess()); + // TODO: Figure out how to implement this + //g_browser_process->platform_part()->PlatformSpecificCommandLineProcessing( + // *base::CommandLine::ForCurrentProcess()); } return result; } @@ -315,12 +251,10 @@ ProcessSingleton::NotifyOtherProcessOrCreate() { // isn't one, create a message window with its title set to the profile // directory path. bool ProcessSingleton::Create() { - static const wchar_t kMutexName[] = L"Local\\ChromeProcessSingletonStartup!"; - static const wchar_t kMetroActivationEventName[] = - L"Local\\ChromeProcessSingletonStartupMetroActivation!"; + static const wchar_t kMutexName[] = L"Local\\AtomProcessSingletonStartup!"; remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); - if (!remote_window_ && !EscapeVirtualization(user_data_dir_)) { + if (!remote_window_) { // Make sure we will be the one and only process creating the window. // We use a named Mutex since we are protecting against multi-process // access. As documented, it's clearer to NOT request ownership on creation @@ -339,58 +273,6 @@ bool ProcessSingleton::Create() { // between the time where we looked for it above and the time the mutex // was given to us. remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); - - - // In Win8+, a new Chrome process launched in Desktop mode may need to be - // transmuted into Metro Chrome (see ShouldLaunchInWindows8ImmersiveMode for - // heuristics). To accomplish this, the current Chrome activates Metro - // Chrome, releases the startup mutex, and waits for metro Chrome to take - // the singleton. From that point onward, the command line for this Chrome - // process will be sent to Metro Chrome by the usual channels. - if (!remote_window_ && base::win::GetVersion() >= base::win::VERSION_WIN8 && - !base::win::IsMetroProcess()) { - // |metro_activation_event| is created right before activating a Metro - // Chrome (note that there can only be one Metro Chrome process; by OS - // design); all following Desktop processes will then wait for this event - // to be signaled by Metro Chrome which will do so as soon as it grabs - // this singleton (should any of the waiting processes timeout waiting for - // the signal they will try to grab the singleton for themselves which - // will result in a forced Desktop Chrome launch in the worst case). - base::win::ScopedHandle metro_activation_event( - ::OpenEvent(SYNCHRONIZE, FALSE, kMetroActivationEventName)); - if (!metro_activation_event.IsValid() && - ShouldLaunchInWindows8ImmersiveMode(user_data_dir_)) { - // No Metro activation is under way, but the desire is to launch in - // Metro mode: activate and rendez-vous with the activated process. - metro_activation_event.Set( - ::CreateEvent(NULL, TRUE, FALSE, kMetroActivationEventName)); - if (!chrome::ActivateMetroChrome()) { - // Failed to launch immersive Chrome, default to launching on Desktop. - LOG(ERROR) << "Failed to launch immersive chrome"; - metro_activation_event.Close(); - } - } - - if (metro_activation_event.IsValid()) { - // Release |only_me| (to let Metro Chrome grab this singleton) and wait - // until the event is signaled (i.e. Metro Chrome was successfully - // activated). Ignore timeout waiting for |metro_activation_event|. - { - AutoUnlockMutex auto_unlock_only_me(only_me.Get()); - - DWORD result = ::WaitForSingleObject(metro_activation_event.Get(), - kMetroChromeActivationTimeoutMs); - DPCHECK(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT) - << "Result = " << result; - } - - // Check if this singleton was successfully grabbed by another process - // (hopefully Metro Chrome). Failing to do so, this process will grab - // the singleton and launch in Desktop mode. - remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); - } - } - if (!remote_window_) { // We have to make sure there is no Chrome instance running on another // machine that uses the same profile. @@ -417,15 +299,6 @@ bool ProcessSingleton::Create() { user_data_dir_.value()); CHECK(result && window_.hwnd()); } - - if (base::win::GetVersion() >= base::win::VERSION_WIN8) { - // Make sure no one is still waiting on Metro activation whether it - // succeeded (i.e., this is the Metro process) or failed. - base::win::ScopedHandle metro_activation_event( - ::OpenEvent(EVENT_MODIFY_STATE, FALSE, kMetroActivationEventName)); - if (metro_activation_event.IsValid()) - ::SetEvent(metro_activation_event.Get()); - } } } From 4bc54ac5e376a6022b37f16f79460055893bdc2a Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 14:33:34 -0700 Subject: [PATCH 271/738] Fix up filenames to include Chrome source --- filenames.gypi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/filenames.gypi b/filenames.gypi index 54fedb9f4130..3f3d1019c243 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -128,10 +128,9 @@ 'atom/browser/atom_browser_main_parts.h', 'atom/browser/atom_browser_main_parts_mac.mm', 'atom/browser/atom_browser_main_parts_posix.cc', - 'atom/browser/atom_process_finder_win.cc', - 'atom/browser/atom_process_singleton.cc', 'atom/browser/atom_javascript_dialog_manager.cc', 'atom/browser/atom_javascript_dialog_manager.h', + 'atom/browser/atom_process_singleton.cc', 'atom/browser/atom_quota_permission_context.cc', 'atom/browser/atom_quota_permission_context.h', 'atom/browser/atom_resource_dispatcher_host_delegate.cc', @@ -184,9 +183,6 @@ 'atom/browser/net/url_request_fetch_job.h', 'atom/browser/node_debugger.cc', 'atom/browser/node_debugger.h', - 'atom/browser/process_singleton_posix.cc', - 'atom/browser/process_singleton_startup_lock.cc', - 'atom/browser/process_singleton_win.cc', 'atom/browser/ui/accelerator_util.cc', 'atom/browser/ui/accelerator_util.h', 'atom/browser/ui/accelerator_util_mac.mm', @@ -351,6 +347,7 @@ 'atom/utility/atom_content_utility_client.h', 'chromium_src/chrome/browser/browser_process.cc', 'chromium_src/chrome/browser/browser_process.h', + 'chromium_src/chrome/browser/chrome_process_finder_win.cc', 'chromium_src/chrome/browser/chrome_notification_types.h', 'chromium_src/chrome/browser/extensions/global_shortcut_listener.cc', 'chromium_src/chrome/browser/extensions/global_shortcut_listener.h', @@ -379,6 +376,9 @@ 'chromium_src/chrome/browser/printing/printing_message_filter.h', 'chromium_src/chrome/browser/printing/print_preview_message_handler.cc', 'chromium_src/chrome/browser/printing/print_preview_message_handler.h', + 'chromium_src/chrome/browser/process_singleton_posix.cc', + 'chromium_src/chrome/browser/process_singleton_startup_lock.cc', + 'chromium_src/chrome/browser/process_singleton_win.cc', 'chromium_src/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc', 'chromium_src/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h', 'chromium_src/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc', From f759471e015f89acca76ef163a6599b0312a0a8d Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 14:36:01 -0700 Subject: [PATCH 272/738] Update to use Chromium sources --- atom/browser/api/atom_api_app.h | 2 +- atom/browser/atom_process_finder_win.cc | 88 -- atom/browser/atom_process_finder_win.h | 39 - atom/browser/atom_process_singleton.h | 4 +- atom/browser/process_singleton.h | 181 --- atom/browser/process_singleton_posix.cc | 1049 ----------------- .../browser/process_singleton_startup_lock.cc | 53 - atom/browser/process_singleton_startup_lock.h | 57 - atom/browser/process_singleton_win.cc | 317 ----- 9 files changed, 3 insertions(+), 1787 deletions(-) delete mode 100644 atom/browser/atom_process_finder_win.cc delete mode 100644 atom/browser/atom_process_finder_win.h delete mode 100644 atom/browser/process_singleton.h delete mode 100644 atom/browser/process_singleton_posix.cc delete mode 100644 atom/browser/process_singleton_startup_lock.cc delete mode 100644 atom/browser/process_singleton_startup_lock.h delete mode 100644 atom/browser/process_singleton_win.cc diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index b8285553b497..3dafdbc28490 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -9,8 +9,8 @@ #include "atom/browser/api/event_emitter.h" #include "atom/browser/browser_observer.h" -#include "atom/browser/process_singleton.h" #include "atom/common/native_mate_converters/callback.h" +#include "chrome/browser/process_singleton.h" #include "content/public/browser/gpu_data_manager_observer.h" #include "native_mate/handle.h" diff --git a/atom/browser/atom_process_finder_win.cc b/atom/browser/atom_process_finder_win.cc deleted file mode 100644 index a658b7163b3c..000000000000 --- a/atom/browser/atom_process_finder_win.cc +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "atom/browser/atom_process_finder_win.h" - -#include -#include - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/process/process.h" -#include "base/process/process_info.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/win/message_window.h" -#include "base/win/scoped_handle.h" -#include "base/win/win_util.h" -#include "base/win/windows_version.h" - - -namespace { - -int timeout_in_milliseconds = 20 * 1000; - -} // namespace - -namespace atom { - -HWND FindRunningAtomWindow(const base::FilePath& user_data_dir) { - return base::win::MessageWindow::FindWindow(user_data_dir.value()); -} - -NotifyChromeResult AttemptToNotifyRunningAtom(HWND remote_window, - bool fast_start) { - DCHECK(remote_window); - DWORD process_id = 0; - DWORD thread_id = GetWindowThreadProcessId(remote_window, &process_id); - if (!thread_id || !process_id) - return NOTIFY_FAILED; - - base::CommandLine command_line(*base::CommandLine::ForCurrentProcess()); - - // Send the command line to the remote chrome window. - // Format is "START\0<<>>\0<<>>". - std::wstring to_send(L"START\0", 6); // want the NULL in the string. - base::FilePath cur_dir; - if (!base::GetCurrentDirectory(&cur_dir)) - return NOTIFY_FAILED; - to_send.append(cur_dir.value()); - to_send.append(L"\0", 1); // Null separator. - to_send.append(command_line.GetCommandLineString()); - to_send.append(L"\0", 1); // Null separator. - - // Allow the current running browser window to make itself the foreground - // window (otherwise it will just flash in the taskbar). - ::AllowSetForegroundWindow(process_id); - - COPYDATASTRUCT cds; - cds.dwData = 0; - cds.cbData = static_cast((to_send.length() + 1) * sizeof(wchar_t)); - cds.lpData = const_cast(to_send.c_str()); - DWORD_PTR result = 0; - if (::SendMessageTimeout(remote_window, WM_COPYDATA, NULL, - reinterpret_cast(&cds), SMTO_ABORTIFHUNG, - timeout_in_milliseconds, &result)) { - return result ? NOTIFY_SUCCESS : NOTIFY_FAILED; - } - - // It is possible that the process owning this window may have died by now. - if (!::IsWindow(remote_window)) - return NOTIFY_FAILED; - - // If the window couldn't be notified but still exists, assume it is hung. - return NOTIFY_WINDOW_HUNG; -} - -base::TimeDelta SetNotificationTimeoutForTesting(base::TimeDelta new_timeout) { - base::TimeDelta old_timeout = - base::TimeDelta::FromMilliseconds(timeout_in_milliseconds); - timeout_in_milliseconds = new_timeout.InMilliseconds(); - return old_timeout; -} - -} // namespace chrome diff --git a/atom/browser/atom_process_finder_win.h b/atom/browser/atom_process_finder_win.h deleted file mode 100644 index f8aa72fdd956..000000000000 --- a/atom/browser/atom_process_finder_win.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_ATOM_PROCESS_FINDER_WIN_H_ -#define ATOM_BROWSER_ATOM_PROCESS_FINDER_WIN_H_ - -#include - -#include "base/time/time.h" - -namespace base { -class FilePath; -} - -namespace atom { - -enum NotifyChromeResult { - NOTIFY_SUCCESS, - NOTIFY_FAILED, - NOTIFY_WINDOW_HUNG, -}; - -// Finds an already running Chrome window if it exists. -HWND FindRunningAtomWindow(const base::FilePath& user_data_dir); - -// Attempts to send the current command line to an already running instance of -// Chrome via a WM_COPYDATA message. -// Returns true if a running Chrome is found and successfully notified. -// |fast_start| is true when this is being called on the window fast start path. -NotifyChromeResult AttemptToNotifyRunningAtom(HWND remote_window, - bool fast_start); - -// Changes the notification timeout to |new_timeout|, returns the old timeout. -base::TimeDelta SetNotificationTimeoutForTesting(base::TimeDelta new_timeout); - -} // namespace chrome - -#endif // ATOM_BROWSER_ATOM_PROCESS_FINDER_WIN_H_ diff --git a/atom/browser/atom_process_singleton.h b/atom/browser/atom_process_singleton.h index de4e2463a080..56548621436c 100644 --- a/atom/browser/atom_process_singleton.h +++ b/atom/browser/atom_process_singleton.h @@ -7,8 +7,8 @@ #include "base/basictypes.h" #include "base/files/file_path.h" -#include "atom/browser/process_singleton.h" -#include "atom/browser/process_singleton_startup_lock.h" +#include "chrome/browser/process_singleton.h" +#include "chrome/browser/process_singleton_startup_lock.h" // Composes a basic ProcessSingleton with ProcessSingletonStartupLock class AtomProcessSingleton { diff --git a/atom/browser/process_singleton.h b/atom/browser/process_singleton.h deleted file mode 100644 index 451414613eb1..000000000000 --- a/atom/browser/process_singleton.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_PROCESS_SINGLETON_H_ -#define CHROME_BROWSER_PROCESS_SINGLETON_H_ - -#if defined(OS_WIN) -#include -#endif // defined(OS_WIN) - -#include -#include - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/process/process.h" -#include "base/threading/non_thread_safe.h" -#include "ui/gfx/native_widget_types.h" - -#if defined(OS_POSIX) && !defined(OS_ANDROID) -#include "base/files/scoped_temp_dir.h" -#endif - -#if defined(OS_WIN) -#include "base/win/message_window.h" -#endif // defined(OS_WIN) - -namespace base { -class CommandLine; -} - -// ProcessSingleton ---------------------------------------------------------- -// -// This class allows different browser processes to communicate with -// each other. It is named according to the user data directory, so -// we can be sure that no more than one copy of the application can be -// running at once with a given data directory. -// -// Implementation notes: -// - the Windows implementation uses an invisible global message window; -// - the Linux implementation uses a Unix domain socket in the user data dir. - -class ProcessSingleton : public base::NonThreadSafe { - public: - enum NotifyResult { - PROCESS_NONE, - PROCESS_NOTIFIED, - PROFILE_IN_USE, - LOCK_ERROR, - }; - - // Implement this callback to handle notifications from other processes. The - // callback will receive the command line and directory with which the other - // Chrome process was launched. Return true if the command line will be - // handled within the current browser instance or false if the remote process - // should handle it (i.e., because the current process is shutting down). - using NotificationCallback = - base::Callback; - - ProcessSingleton(const base::FilePath& user_data_dir, - const NotificationCallback& notification_callback); - ~ProcessSingleton(); - - // Notify another process, if available. Otherwise sets ourselves as the - // singleton instance. Returns PROCESS_NONE if we became the singleton - // instance. Callers are guaranteed to either have notified an existing - // process or have grabbed the singleton (unless the profile is locked by an - // unreachable process). - // TODO(brettw): Make the implementation of this method non-platform-specific - // by making Linux re-use the Windows implementation. - NotifyResult NotifyOtherProcessOrCreate(); - - // Sets ourself up as the singleton instance. Returns true on success. If - // false is returned, we are not the singleton instance and the caller must - // exit. - // NOTE: Most callers should generally prefer NotifyOtherProcessOrCreate() to - // this method, only callers for whom failure is preferred to notifying - // another process should call this directly. - bool Create(); - - // Clear any lock state during shutdown. - void Cleanup(); - -#if defined(OS_POSIX) && !defined(OS_ANDROID) - static void DisablePromptForTesting(); -#endif -#if defined(OS_WIN) - // Called to query whether to kill a hung browser process that has visible - // windows. Return true to allow killing the hung process. - using ShouldKillRemoteProcessCallback = base::Callback; - void OverrideShouldKillRemoteProcessCallbackForTesting( - const ShouldKillRemoteProcessCallback& display_dialog_callback); -#endif - - protected: - // Notify another process, if available. - // Returns true if another process was found and notified, false if we should - // continue with the current process. - // On Windows, Create() has to be called before this. - NotifyResult NotifyOtherProcess(); - -#if defined(OS_POSIX) && !defined(OS_ANDROID) - // Exposed for testing. We use a timeout on Linux, and in tests we want - // this timeout to be short. - NotifyResult NotifyOtherProcessWithTimeout( - const base::CommandLine& command_line, - int retry_attempts, - const base::TimeDelta& timeout, - bool kill_unresponsive); - NotifyResult NotifyOtherProcessWithTimeoutOrCreate( - const base::CommandLine& command_line, - int retry_attempts, - const base::TimeDelta& timeout); - void OverrideCurrentPidForTesting(base::ProcessId pid); - void OverrideKillCallbackForTesting( - const base::Callback& callback); -#endif - - private: - NotificationCallback notification_callback_; // Handler for notifications. - -#if defined(OS_WIN) - bool EscapeVirtualization(const base::FilePath& user_data_dir); - - HWND remote_window_; // The HWND_MESSAGE of another browser. - base::win::MessageWindow window_; // The message-only window. - bool is_virtualized_; // Stuck inside Microsoft Softricity VM environment. - HANDLE lock_file_; - base::FilePath user_data_dir_; - ShouldKillRemoteProcessCallback should_kill_remote_process_callback_; -#elif defined(OS_POSIX) && !defined(OS_ANDROID) - // Return true if the given pid is one of our child processes. - // Assumes that the current pid is the root of all pids of the current - // instance. - bool IsSameChromeInstance(pid_t pid); - - // Extract the process's pid from a symbol link path and if it is on - // the same host, kill the process, unlink the lock file and return true. - // If the process is part of the same chrome instance, unlink the lock file - // and return true without killing it. - // If the process is on a different host, return false. - bool KillProcessByLockPath(); - - // Default function to kill a process, overridable by tests. - void KillProcess(int pid); - - // Allow overriding for tests. - base::ProcessId current_pid_; - - // Function to call when the other process is hung and needs to be killed. - // Allows overriding for tests. - base::Callback kill_callback_; - - // Path in file system to the socket. - base::FilePath socket_path_; - - // Path in file system to the lock. - base::FilePath lock_path_; - - // Path in file system to the cookie file. - base::FilePath cookie_path_; - - // Temporary directory to hold the socket. - base::ScopedTempDir socket_dir_; - - // Helper class for linux specific messages. LinuxWatcher is ref counted - // because it posts messages between threads. - class LinuxWatcher; - scoped_refptr watcher_; -#endif - - DISALLOW_COPY_AND_ASSIGN(ProcessSingleton); -}; - -#endif // CHROME_BROWSER_PROCESS_SINGLETON_H_ diff --git a/atom/browser/process_singleton_posix.cc b/atom/browser/process_singleton_posix.cc deleted file mode 100644 index 5810af2a2a55..000000000000 --- a/atom/browser/process_singleton_posix.cc +++ /dev/null @@ -1,1049 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// On Linux, when the user tries to launch a second copy of chrome, we check -// for a socket in the user's profile directory. If the socket file is open we -// send a message to the first chrome browser process with the current -// directory and second process command line flags. The second process then -// exits. -// -// Because many networked filesystem implementations do not support unix domain -// sockets, we create the socket in a temporary directory and create a symlink -// in the profile. This temporary directory is no longer bound to the profile, -// and may disappear across a reboot or login to a separate session. To bind -// them, we store a unique cookie in the profile directory, which must also be -// present in the remote directory to connect. The cookie is checked both before -// and after the connection. /tmp is sticky, and different Chrome sessions use -// different cookies. Thus, a matching cookie before and after means the -// connection was to a directory with a valid cookie. -// -// We also have a lock file, which is a symlink to a non-existent destination. -// The destination is a string containing the hostname and process id of -// chrome's browser process, eg. "SingletonLock -> example.com-9156". When the -// first copy of chrome exits it will delete the lock file on shutdown, so that -// a different instance on a different host may then use the profile directory. -// -// If writing to the socket fails, the hostname in the lock is checked to see if -// another instance is running a different host using a shared filesystem (nfs, -// etc.) If the hostname differs an error is displayed and the second process -// exits. Otherwise the first process (if any) is killed and the second process -// starts as normal. -// -// When the second process sends the current directory and command line flags to -// the first process, it waits for an ACK message back from the first process -// for a certain time. If there is no ACK message back in time, then the first -// process will be considered as hung for some reason. The second process then -// retrieves the process id from the symbol link and kills it by sending -// SIGKILL. Then the second process starts as normal. - -#include "atom/browser/process_singleton.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "base/base_paths.h" -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/posix/eintr_wrapper.h" -#include "base/posix/safe_strerror.h" -#include "base/rand_util.h" -#include "base/sequenced_task_runner_helpers.h" -#include "base/single_thread_task_runner.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/platform_thread.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "content/public/browser/browser_thread.h" -#include "net/base/net_util.h" -#include "ui/base/l10n/l10n_util.h" - -#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) -#include "ui/views/linux_ui/linux_ui.h" -#endif - -using content::BrowserThread; - -namespace { - -// Timeout for the current browser process to respond. 20 seconds should be -// enough. -const int kTimeoutInSeconds = 20; -// Number of retries to notify the browser. 20 retries over 20 seconds = 1 try -// per second. -const int kRetryAttempts = 20; -static bool g_disable_prompt; -const char kStartToken[] = "START"; -const char kACKToken[] = "ACK"; -const char kShutdownToken[] = "SHUTDOWN"; -const char kTokenDelimiter = '\0'; -const int kMaxMessageLength = 32 * 1024; -const int kMaxACKMessageLength = arraysize(kShutdownToken) - 1; - -const char kLockDelimiter = '-'; - -const base::FilePath::CharType kSingletonCookieFilename[] = - FILE_PATH_LITERAL("SingletonCookie"); - -const base::FilePath::CharType kSingletonLockFilename[] = FILE_PATH_LITERAL("SingletonLock"); -const base::FilePath::CharType kSingletonSocketFilename[] = - FILE_PATH_LITERAL("SingletonSocket"); - -// Set the close-on-exec bit on a file descriptor. -// Returns 0 on success, -1 on failure. -int SetCloseOnExec(int fd) { - int flags = fcntl(fd, F_GETFD, 0); - if (-1 == flags) - return flags; - if (flags & FD_CLOEXEC) - return 0; - return fcntl(fd, F_SETFD, flags | FD_CLOEXEC); -} - -// Close a socket and check return value. -void CloseSocket(int fd) { - int rv = IGNORE_EINTR(close(fd)); - DCHECK_EQ(0, rv) << "Error closing socket: " << base::safe_strerror(errno); -} - -// Write a message to a socket fd. -bool WriteToSocket(int fd, const char *message, size_t length) { - DCHECK(message); - DCHECK(length); - size_t bytes_written = 0; - do { - ssize_t rv = HANDLE_EINTR( - write(fd, message + bytes_written, length - bytes_written)); - if (rv < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - // The socket shouldn't block, we're sending so little data. Just give - // up here, since NotifyOtherProcess() doesn't have an asynchronous api. - LOG(ERROR) << "ProcessSingleton would block on write(), so it gave up."; - return false; - } - PLOG(ERROR) << "write() failed"; - return false; - } - bytes_written += rv; - } while (bytes_written < length); - - return true; -} - -struct timeval TimeDeltaToTimeVal(const base::TimeDelta& delta) { - struct timeval result; - result.tv_sec = delta.InSeconds(); - result.tv_usec = delta.InMicroseconds() % base::Time::kMicrosecondsPerSecond; - return result; -} - -// Wait a socket for read for a certain timeout. -// Returns -1 if error occurred, 0 if timeout reached, > 0 if the socket is -// ready for read. -int WaitSocketForRead(int fd, const base::TimeDelta& timeout) { - fd_set read_fds; - struct timeval tv = TimeDeltaToTimeVal(timeout); - - FD_ZERO(&read_fds); - FD_SET(fd, &read_fds); - - return HANDLE_EINTR(select(fd + 1, &read_fds, NULL, NULL, &tv)); -} - -// Read a message from a socket fd, with an optional timeout. -// If |timeout| <= 0 then read immediately. -// Return number of bytes actually read, or -1 on error. -ssize_t ReadFromSocket(int fd, - char* buf, - size_t bufsize, - const base::TimeDelta& timeout) { - if (timeout > base::TimeDelta()) { - int rv = WaitSocketForRead(fd, timeout); - if (rv <= 0) - return rv; - } - - size_t bytes_read = 0; - do { - ssize_t rv = HANDLE_EINTR(read(fd, buf + bytes_read, bufsize - bytes_read)); - if (rv < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - PLOG(ERROR) << "read() failed"; - return rv; - } else { - // It would block, so we just return what has been read. - return bytes_read; - } - } else if (!rv) { - // No more data to read. - return bytes_read; - } else { - bytes_read += rv; - } - } while (bytes_read < bufsize); - - return bytes_read; -} - -// Set up a sockaddr appropriate for messaging. -void SetupSockAddr(const std::string& path, struct sockaddr_un* addr) { - addr->sun_family = AF_UNIX; - CHECK(path.length() < arraysize(addr->sun_path)) - << "Socket path too long: " << path; - base::strlcpy(addr->sun_path, path.c_str(), arraysize(addr->sun_path)); -} - -// Set up a socket appropriate for messaging. -int SetupSocketOnly() { - int sock = socket(PF_UNIX, SOCK_STREAM, 0); - PCHECK(sock >= 0) << "socket() failed"; - - int rv = net::SetNonBlocking(sock); - DCHECK_EQ(0, rv) << "Failed to make non-blocking socket."; - rv = SetCloseOnExec(sock); - DCHECK_EQ(0, rv) << "Failed to set CLOEXEC on socket."; - - return sock; -} - -// Set up a socket and sockaddr appropriate for messaging. -void SetupSocket(const std::string& path, int* sock, struct sockaddr_un* addr) { - *sock = SetupSocketOnly(); - SetupSockAddr(path, addr); -} - -// Read a symbolic link, return empty string if given path is not a symbol link. -base::FilePath ReadLink(const base::FilePath& path) { - base::FilePath target; - if (!base::ReadSymbolicLink(path, &target)) { - // The only errno that should occur is ENOENT. - if (errno != 0 && errno != ENOENT) - PLOG(ERROR) << "readlink(" << path.value() << ") failed"; - } - return target; -} - -// Unlink a path. Return true on success. -bool UnlinkPath(const base::FilePath& path) { - int rv = unlink(path.value().c_str()); - if (rv < 0 && errno != ENOENT) - PLOG(ERROR) << "Failed to unlink " << path.value(); - - return rv == 0; -} - -// Create a symlink. Returns true on success. -bool SymlinkPath(const base::FilePath& target, const base::FilePath& path) { - if (!base::CreateSymbolicLink(target, path)) { - // Double check the value in case symlink suceeded but we got an incorrect - // failure due to NFS packet loss & retry. - int saved_errno = errno; - if (ReadLink(path) != target) { - // If we failed to create the lock, most likely another instance won the - // startup race. - errno = saved_errno; - PLOG(ERROR) << "Failed to create " << path.value(); - return false; - } - } - return true; -} - -// Extract the hostname and pid from the lock symlink. -// Returns true if the lock existed. -bool ParseLockPath(const base::FilePath& path, - std::string* hostname, - int* pid) { - std::string real_path = ReadLink(path).value(); - if (real_path.empty()) - return false; - - std::string::size_type pos = real_path.rfind(kLockDelimiter); - - // If the path is not a symbolic link, or doesn't contain what we expect, - // bail. - if (pos == std::string::npos) { - *hostname = ""; - *pid = -1; - return true; - } - - *hostname = real_path.substr(0, pos); - - const std::string& pid_str = real_path.substr(pos + 1); - if (!base::StringToInt(pid_str, pid)) - *pid = -1; - - return true; -} - -// Returns true if the user opted to unlock the profile. -bool DisplayProfileInUseError(const base::FilePath& lock_path, - const std::string& hostname, - int pid) { - // TODO: yolo - return true; -} - -bool IsChromeProcess(pid_t pid) { - base::FilePath other_chrome_path(base::GetProcessExecutablePath(pid)); - - auto command_line = base::CommandLine::ForCurrentProcess(); - base::FilePath exec_path(command_line->GetProgram()); - PathService::Get(base::FILE_EXE, &exec_path); - - return (!other_chrome_path.empty() && - other_chrome_path.BaseName() == - exec_path.BaseName()); -} - -// A helper class to hold onto a socket. -class ScopedSocket { - public: - ScopedSocket() : fd_(-1) { Reset(); } - ~ScopedSocket() { Close(); } - int fd() { return fd_; } - void Reset() { - Close(); - fd_ = SetupSocketOnly(); - } - void Close() { - if (fd_ >= 0) - CloseSocket(fd_); - fd_ = -1; - } - private: - int fd_; -}; - -// Returns a random string for uniquifying profile connections. -std::string GenerateCookie() { - return base::Uint64ToString(base::RandUint64()); -} - -bool CheckCookie(const base::FilePath& path, const base::FilePath& cookie) { - return (cookie == ReadLink(path)); -} - -bool ConnectSocket(ScopedSocket* socket, - const base::FilePath& socket_path, - const base::FilePath& cookie_path) { - base::FilePath socket_target; - if (base::ReadSymbolicLink(socket_path, &socket_target)) { - // It's a symlink. Read the cookie. - base::FilePath cookie = ReadLink(cookie_path); - if (cookie.empty()) - return false; - base::FilePath remote_cookie = socket_target.DirName(). - Append(kSingletonCookieFilename); - // Verify the cookie before connecting. - if (!CheckCookie(remote_cookie, cookie)) - return false; - // Now we know the directory was (at that point) created by the profile - // owner. Try to connect. - sockaddr_un addr; - SetupSockAddr(socket_target.value(), &addr); - int ret = HANDLE_EINTR(connect(socket->fd(), - reinterpret_cast(&addr), - sizeof(addr))); - if (ret != 0) - return false; - // Check the cookie again. We only link in /tmp, which is sticky, so, if the - // directory is still correct, it must have been correct in-between when we - // connected. POSIX, sadly, lacks a connectat(). - if (!CheckCookie(remote_cookie, cookie)) { - socket->Reset(); - return false; - } - // Success! - return true; - } else if (errno == EINVAL) { - // It exists, but is not a symlink (or some other error we detect - // later). Just connect to it directly; this is an older version of Chrome. - sockaddr_un addr; - SetupSockAddr(socket_path.value(), &addr); - int ret = HANDLE_EINTR(connect(socket->fd(), - reinterpret_cast(&addr), - sizeof(addr))); - return (ret == 0); - } else { - // File is missing, or other error. - if (errno != ENOENT) - PLOG(ERROR) << "readlink failed"; - return false; - } -} - -#if defined(OS_MACOSX) -bool ReplaceOldSingletonLock(const base::FilePath& symlink_content, - const base::FilePath& lock_path) { - // Try taking an flock(2) on the file. Failure means the lock is taken so we - // should quit. - base::ScopedFD lock_fd(HANDLE_EINTR( - open(lock_path.value().c_str(), O_RDWR | O_CREAT | O_SYMLINK, 0644))); - if (!lock_fd.is_valid()) { - PLOG(ERROR) << "Could not open singleton lock"; - return false; - } - - int rc = HANDLE_EINTR(flock(lock_fd.get(), LOCK_EX | LOCK_NB)); - if (rc == -1) { - if (errno == EWOULDBLOCK) { - LOG(ERROR) << "Singleton lock held by old process."; - } else { - PLOG(ERROR) << "Error locking singleton lock"; - } - return false; - } - - // Successfully taking the lock means we can replace it with the a new symlink - // lock. We never flock() the lock file from now on. I.e. we assume that an - // old version of Chrome will not run with the same user data dir after this - // version has run. - if (!base::DeleteFile(lock_path, false)) { - PLOG(ERROR) << "Could not delete old singleton lock."; - return false; - } - - return SymlinkPath(symlink_content, lock_path); -} -#endif // defined(OS_MACOSX) - -} // namespace - -/////////////////////////////////////////////////////////////////////////////// -// ProcessSingleton::LinuxWatcher -// A helper class for a Linux specific implementation of the process singleton. -// This class sets up a listener on the singleton socket and handles parsing -// messages that come in on the singleton socket. -class ProcessSingleton::LinuxWatcher - : public base::MessageLoopForIO::Watcher, - public base::MessageLoop::DestructionObserver, - public base::RefCountedThreadSafe { - public: - // A helper class to read message from an established socket. - class SocketReader : public base::MessageLoopForIO::Watcher { - public: - SocketReader(ProcessSingleton::LinuxWatcher* parent, - base::MessageLoop* ui_message_loop, - int fd) - : parent_(parent), - ui_message_loop_(ui_message_loop), - fd_(fd), - bytes_read_(0) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - // Wait for reads. - base::MessageLoopForIO::current()->WatchFileDescriptor( - fd, true, base::MessageLoopForIO::WATCH_READ, &fd_reader_, this); - // If we haven't completed in a reasonable amount of time, give up. - timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kTimeoutInSeconds), - this, &SocketReader::CleanupAndDeleteSelf); - } - - ~SocketReader() override { CloseSocket(fd_); } - - // MessageLoopForIO::Watcher impl. - void OnFileCanReadWithoutBlocking(int fd) override; - void OnFileCanWriteWithoutBlocking(int fd) override { - // SocketReader only watches for accept (read) events. - NOTREACHED(); - } - - // Finish handling the incoming message by optionally sending back an ACK - // message and removing this SocketReader. - void FinishWithACK(const char *message, size_t length); - - private: - void CleanupAndDeleteSelf() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - parent_->RemoveSocketReader(this); - // We're deleted beyond this point. - } - - base::MessageLoopForIO::FileDescriptorWatcher fd_reader_; - - // The ProcessSingleton::LinuxWatcher that owns us. - ProcessSingleton::LinuxWatcher* const parent_; - - // A reference to the UI message loop. - base::MessageLoop* const ui_message_loop_; - - // The file descriptor we're reading. - const int fd_; - - // Store the message in this buffer. - char buf_[kMaxMessageLength]; - - // Tracks the number of bytes we've read in case we're getting partial - // reads. - size_t bytes_read_; - - base::OneShotTimer timer_; - - DISALLOW_COPY_AND_ASSIGN(SocketReader); - }; - - // We expect to only be constructed on the UI thread. - explicit LinuxWatcher(ProcessSingleton* parent) - : ui_message_loop_(base::MessageLoop::current()), - parent_(parent) { - } - - // Start listening for connections on the socket. This method should be - // called from the IO thread. - void StartListening(int socket); - - // This method determines if we should use the same process and if we should, - // opens a new browser tab. This runs on the UI thread. - // |reader| is for sending back ACK message. - void HandleMessage(const std::string& current_dir, - const std::vector& argv, - SocketReader* reader); - - // MessageLoopForIO::Watcher impl. These run on the IO thread. - void OnFileCanReadWithoutBlocking(int fd) override; - void OnFileCanWriteWithoutBlocking(int fd) override { - // ProcessSingleton only watches for accept (read) events. - NOTREACHED(); - } - - // MessageLoop::DestructionObserver - void WillDestroyCurrentMessageLoop() override { - fd_watcher_.StopWatchingFileDescriptor(); - } - - private: - friend struct BrowserThread::DeleteOnThread; - friend class base::DeleteHelper; - - ~LinuxWatcher() override { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - STLDeleteElements(&readers_); - - base::MessageLoopForIO* ml = base::MessageLoopForIO::current(); - ml->RemoveDestructionObserver(this); - } - - // Removes and deletes the SocketReader. - void RemoveSocketReader(SocketReader* reader); - - base::MessageLoopForIO::FileDescriptorWatcher fd_watcher_; - - // A reference to the UI message loop (i.e., the message loop we were - // constructed on). - base::MessageLoop* ui_message_loop_; - - // The ProcessSingleton that owns us. - ProcessSingleton* const parent_; - - std::set readers_; - - DISALLOW_COPY_AND_ASSIGN(LinuxWatcher); -}; - -void ProcessSingleton::LinuxWatcher::OnFileCanReadWithoutBlocking(int fd) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - // Accepting incoming client. - sockaddr_un from; - socklen_t from_len = sizeof(from); - int connection_socket = HANDLE_EINTR(accept( - fd, reinterpret_cast(&from), &from_len)); - if (-1 == connection_socket) { - PLOG(ERROR) << "accept() failed"; - return; - } - int rv = net::SetNonBlocking(connection_socket); - DCHECK_EQ(0, rv) << "Failed to make non-blocking socket."; - SocketReader* reader = new SocketReader(this, - ui_message_loop_, - connection_socket); - readers_.insert(reader); -} - -void ProcessSingleton::LinuxWatcher::StartListening(int socket) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - // Watch for client connections on this socket. - base::MessageLoopForIO* ml = base::MessageLoopForIO::current(); - ml->AddDestructionObserver(this); - ml->WatchFileDescriptor(socket, true, base::MessageLoopForIO::WATCH_READ, - &fd_watcher_, this); -} - -void ProcessSingleton::LinuxWatcher::HandleMessage( - const std::string& current_dir, const std::vector& argv, - SocketReader* reader) { - DCHECK(ui_message_loop_ == base::MessageLoop::current()); - DCHECK(reader); - - if (parent_->notification_callback_.Run(base::CommandLine(argv), - base::FilePath(current_dir))) { - // Send back "ACK" message to prevent the client process from starting up. - reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1); - } else { - LOG(WARNING) << "Not handling interprocess notification as browser" - " is shutting down"; - // Send back "SHUTDOWN" message, so that the client process can start up - // without killing this process. - reader->FinishWithACK(kShutdownToken, arraysize(kShutdownToken) - 1); - return; - } -} - -void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(reader); - readers_.erase(reader); - delete reader; -} - -/////////////////////////////////////////////////////////////////////////////// -// ProcessSingleton::LinuxWatcher::SocketReader -// - -void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking( - int fd) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK_EQ(fd, fd_); - while (bytes_read_ < sizeof(buf_)) { - ssize_t rv = HANDLE_EINTR( - read(fd, buf_ + bytes_read_, sizeof(buf_) - bytes_read_)); - if (rv < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - PLOG(ERROR) << "read() failed"; - CloseSocket(fd); - return; - } else { - // It would block, so we just return and continue to watch for the next - // opportunity to read. - return; - } - } else if (!rv) { - // No more data to read. It's time to process the message. - break; - } else { - bytes_read_ += rv; - } - } - - // Validate the message. The shortest message is kStartToken\0x\0x - const size_t kMinMessageLength = arraysize(kStartToken) + 4; - if (bytes_read_ < kMinMessageLength) { - buf_[bytes_read_] = 0; - LOG(ERROR) << "Invalid socket message (wrong length):" << buf_; - CleanupAndDeleteSelf(); - return; - } - - std::string str(buf_, bytes_read_); - std::vector tokens = base::SplitString( - str, std::string(1, kTokenDelimiter), - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - if (tokens.size() < 3 || tokens[0] != kStartToken) { - LOG(ERROR) << "Wrong message format: " << str; - CleanupAndDeleteSelf(); - return; - } - - // Stop the expiration timer to prevent this SocketReader object from being - // terminated unexpectly. - timer_.Stop(); - - std::string current_dir = tokens[1]; - // Remove the first two tokens. The remaining tokens should be the command - // line argv array. - tokens.erase(tokens.begin()); - tokens.erase(tokens.begin()); - - // Return to the UI thread to handle opening a new browser tab. - ui_message_loop_->task_runner()->PostTask( - FROM_HERE, base::Bind(&ProcessSingleton::LinuxWatcher::HandleMessage, - parent_, current_dir, tokens, this)); - fd_reader_.StopWatchingFileDescriptor(); - - // LinuxWatcher::HandleMessage() is in charge of destroying this SocketReader - // object by invoking SocketReader::FinishWithACK(). -} - -void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK( - const char *message, size_t length) { - if (message && length) { - // Not necessary to care about the return value. - WriteToSocket(fd_, message, length); - } - - if (shutdown(fd_, SHUT_WR) < 0) - PLOG(ERROR) << "shutdown() failed"; - - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&ProcessSingleton::LinuxWatcher::RemoveSocketReader, - parent_, - this)); - // We will be deleted once the posted RemoveSocketReader task runs. -} - -/////////////////////////////////////////////////////////////////////////////// -// ProcessSingleton -// -ProcessSingleton::ProcessSingleton( - const base::FilePath& user_data_dir, - const NotificationCallback& notification_callback) - : notification_callback_(notification_callback), - current_pid_(base::GetCurrentProcId()), - watcher_(new LinuxWatcher(this)) { - socket_path_ = user_data_dir.Append(kSingletonSocketFilename); - lock_path_ = user_data_dir.Append(kSingletonLockFilename); - cookie_path_ = user_data_dir.Append(kSingletonCookieFilename); - - kill_callback_ = base::Bind(&ProcessSingleton::KillProcess, - base::Unretained(this)); -} - -ProcessSingleton::~ProcessSingleton() { -} - -ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { - return NotifyOtherProcessWithTimeout( - *base::CommandLine::ForCurrentProcess(), kRetryAttempts, - base::TimeDelta::FromSeconds(kTimeoutInSeconds), true); -} - -ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( - const base::CommandLine& cmd_line, - int retry_attempts, - const base::TimeDelta& timeout, - bool kill_unresponsive) { - DCHECK_GE(retry_attempts, 0); - DCHECK_GE(timeout.InMicroseconds(), 0); - - base::TimeDelta sleep_interval = timeout / retry_attempts; - - ScopedSocket socket; - for (int retries = 0; retries <= retry_attempts; ++retries) { - // Try to connect to the socket. - if (ConnectSocket(&socket, socket_path_, cookie_path_)) - break; - - // If we're in a race with another process, they may be in Create() and have - // created the lock but not attached to the socket. So we check if the - // process with the pid from the lockfile is currently running and is a - // chrome browser. If so, we loop and try again for |timeout|. - - std::string hostname; - int pid; - if (!ParseLockPath(lock_path_, &hostname, &pid)) { - // No lockfile exists. - return PROCESS_NONE; - } - - if (hostname.empty()) { - // Invalid lockfile. - UnlinkPath(lock_path_); - return PROCESS_NONE; - } - - if (hostname != net::GetHostName() && !IsChromeProcess(pid)) { - // Locked by process on another host. If the user selected to unlock - // the profile, try to continue; otherwise quit. - if (DisplayProfileInUseError(lock_path_, hostname, pid)) { - UnlinkPath(lock_path_); - return PROCESS_NONE; - } - return PROFILE_IN_USE; - } - - if (!IsChromeProcess(pid)) { - // Orphaned lockfile (no process with pid, or non-chrome process.) - UnlinkPath(lock_path_); - return PROCESS_NONE; - } - - if (IsSameChromeInstance(pid)) { - // Orphaned lockfile (pid is part of same chrome instance we are, even - // though we haven't tried to create a lockfile yet). - UnlinkPath(lock_path_); - return PROCESS_NONE; - } - - if (retries == retry_attempts) { - // Retries failed. Kill the unresponsive chrome process and continue. - if (!kill_unresponsive || !KillProcessByLockPath()) - return PROFILE_IN_USE; - return PROCESS_NONE; - } - - base::PlatformThread::Sleep(sleep_interval); - } - - timeval socket_timeout = TimeDeltaToTimeVal(timeout); - setsockopt(socket.fd(), - SOL_SOCKET, - SO_SNDTIMEO, - &socket_timeout, - sizeof(socket_timeout)); - - // Found another process, prepare our command line - // format is "START\0\0\0...\0". - std::string to_send(kStartToken); - to_send.push_back(kTokenDelimiter); - - base::FilePath current_dir; - if (!PathService::Get(base::DIR_CURRENT, ¤t_dir)) - return PROCESS_NONE; - to_send.append(current_dir.value()); - - const std::vector& argv = cmd_line.argv(); - for (std::vector::const_iterator it = argv.begin(); - it != argv.end(); ++it) { - to_send.push_back(kTokenDelimiter); - to_send.append(*it); - } - - // Send the message - if (!WriteToSocket(socket.fd(), to_send.data(), to_send.length())) { - // Try to kill the other process, because it might have been dead. - if (!kill_unresponsive || !KillProcessByLockPath()) - return PROFILE_IN_USE; - return PROCESS_NONE; - } - - if (shutdown(socket.fd(), SHUT_WR) < 0) - PLOG(ERROR) << "shutdown() failed"; - - // Read ACK message from the other process. It might be blocked for a certain - // timeout, to make sure the other process has enough time to return ACK. - char buf[kMaxACKMessageLength + 1]; - ssize_t len = ReadFromSocket(socket.fd(), buf, kMaxACKMessageLength, timeout); - - // Failed to read ACK, the other process might have been frozen. - if (len <= 0) { - if (!kill_unresponsive || !KillProcessByLockPath()) - return PROFILE_IN_USE; - return PROCESS_NONE; - } - - buf[len] = '\0'; - if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) { - // The other process is shutting down, it's safe to start a new process. - return PROCESS_NONE; - } else if (strncmp(buf, kACKToken, arraysize(kACKToken) - 1) == 0) { -#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) - // Likely NULL in unit tests. - views::LinuxUI* linux_ui = views::LinuxUI::instance(); - if (linux_ui) - linux_ui->NotifyWindowManagerStartupComplete(); -#endif - - // Assume the other process is handling the request. - return PROCESS_NOTIFIED; - } - - NOTREACHED() << "The other process returned unknown message: " << buf; - return PROCESS_NOTIFIED; -} - -ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate() { - return NotifyOtherProcessWithTimeoutOrCreate( - *base::CommandLine::ForCurrentProcess(), kRetryAttempts, - base::TimeDelta::FromSeconds(kTimeoutInSeconds)); -} - -ProcessSingleton::NotifyResult -ProcessSingleton::NotifyOtherProcessWithTimeoutOrCreate( - const base::CommandLine& command_line, - int retry_attempts, - const base::TimeDelta& timeout) { - NotifyResult result = NotifyOtherProcessWithTimeout( - command_line, retry_attempts, timeout, true); - if (result != PROCESS_NONE) - return result; - if (Create()) - return PROCESS_NONE; - // If the Create() failed, try again to notify. (It could be that another - // instance was starting at the same time and managed to grab the lock before - // we did.) - // This time, we don't want to kill anything if we aren't successful, since we - // aren't going to try to take over the lock ourselves. - result = NotifyOtherProcessWithTimeout( - command_line, retry_attempts, timeout, false); - if (result != PROCESS_NONE) - return result; - - return LOCK_ERROR; -} - -void ProcessSingleton::OverrideCurrentPidForTesting(base::ProcessId pid) { - current_pid_ = pid; -} - -void ProcessSingleton::OverrideKillCallbackForTesting( - const base::Callback& callback) { - kill_callback_ = callback; -} - -void ProcessSingleton::DisablePromptForTesting() { - g_disable_prompt = true; -} - -bool ProcessSingleton::Create() { - int sock; - sockaddr_un addr; - - // The symlink lock is pointed to the hostname and process id, so other - // processes can find it out. - base::FilePath symlink_content(base::StringPrintf( - "%s%c%u", - net::GetHostName().c_str(), - kLockDelimiter, - current_pid_)); - - // Create symbol link before binding the socket, to ensure only one instance - // can have the socket open. - if (!SymlinkPath(symlink_content, lock_path_)) { - // TODO(jackhou): Remove this case once this code is stable on Mac. - // http://crbug.com/367612 -#if defined(OS_MACOSX) - // On Mac, an existing non-symlink lock file means the lock could be held by - // the old process singleton code. If we can successfully replace the lock, - // continue as normal. - if (base::IsLink(lock_path_) || - !ReplaceOldSingletonLock(symlink_content, lock_path_)) { - return false; - } -#else - // If we failed to create the lock, most likely another instance won the - // startup race. - return false; -#endif - } - - // Create the socket file somewhere in /tmp which is usually mounted as a - // normal filesystem. Some network filesystems (notably AFS) are screwy and - // do not support Unix domain sockets. - if (!socket_dir_.CreateUniqueTempDir()) { - LOG(ERROR) << "Failed to create socket directory."; - return false; - } - - // Check that the directory was created with the correct permissions. - int dir_mode = 0; - CHECK(base::GetPosixFilePermissions(socket_dir_.path(), &dir_mode) && - dir_mode == base::FILE_PERMISSION_USER_MASK) - << "Temp directory mode is not 700: " << std::oct << dir_mode; - - // Setup the socket symlink and the two cookies. - base::FilePath socket_target_path = - socket_dir_.path().Append(kSingletonSocketFilename); - base::FilePath cookie(GenerateCookie()); - base::FilePath remote_cookie_path = - socket_dir_.path().Append(kSingletonCookieFilename); - UnlinkPath(socket_path_); - UnlinkPath(cookie_path_); - if (!SymlinkPath(socket_target_path, socket_path_) || - !SymlinkPath(cookie, cookie_path_) || - !SymlinkPath(cookie, remote_cookie_path)) { - // We've already locked things, so we can't have lost the startup race, - // but something doesn't like us. - LOG(ERROR) << "Failed to create symlinks."; - if (!socket_dir_.Delete()) - LOG(ERROR) << "Encountered a problem when deleting socket directory."; - return false; - } - - SetupSocket(socket_target_path.value(), &sock, &addr); - - if (bind(sock, reinterpret_cast(&addr), sizeof(addr)) < 0) { - PLOG(ERROR) << "Failed to bind() " << socket_target_path.value(); - CloseSocket(sock); - return false; - } - - if (listen(sock, 5) < 0) - NOTREACHED() << "listen failed: " << base::safe_strerror(errno); - - DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO)); - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&ProcessSingleton::LinuxWatcher::StartListening, - watcher_.get(), - sock)); - - return true; -} - -void ProcessSingleton::Cleanup() { - UnlinkPath(socket_path_); - UnlinkPath(cookie_path_); - UnlinkPath(lock_path_); -} - -bool ProcessSingleton::IsSameChromeInstance(pid_t pid) { - pid_t cur_pid = current_pid_; - while (pid != cur_pid) { - pid = base::GetParentProcessId(pid); - if (pid < 0) - return false; - if (!IsChromeProcess(pid)) - return false; - } - return true; -} - -bool ProcessSingleton::KillProcessByLockPath() { - std::string hostname; - int pid; - ParseLockPath(lock_path_, &hostname, &pid); - - if (!hostname.empty() && hostname != net::GetHostName()) { - return DisplayProfileInUseError(lock_path_, hostname, pid); - } - UnlinkPath(lock_path_); - - if (IsSameChromeInstance(pid)) - return true; - - if (pid > 0) { - kill_callback_.Run(pid); - return true; - } - - LOG(ERROR) << "Failed to extract pid from path: " << lock_path_.value(); - return true; -} - -void ProcessSingleton::KillProcess(int pid) { - // TODO(james.su@gmail.com): Is SIGKILL ok? - int rv = kill(static_cast(pid), SIGKILL); - // ESRCH = No Such Process (can happen if the other process is already in - // progress of shutting down and finishes before we try to kill it). - DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " - << base::safe_strerror(errno); -} diff --git a/atom/browser/process_singleton_startup_lock.cc b/atom/browser/process_singleton_startup_lock.cc deleted file mode 100644 index fa53284f0514..000000000000 --- a/atom/browser/process_singleton_startup_lock.cc +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "atom/browser/process_singleton_startup_lock.h" - -#include "base/bind.h" -#include "base/logging.h" - -ProcessSingletonStartupLock::ProcessSingletonStartupLock( - const ProcessSingleton::NotificationCallback& original_callback) - : locked_(true), - original_callback_(original_callback) {} - -ProcessSingletonStartupLock::~ProcessSingletonStartupLock() {} - -ProcessSingleton::NotificationCallback -ProcessSingletonStartupLock::AsNotificationCallback() { - return base::Bind(&ProcessSingletonStartupLock::NotificationCallbackImpl, - base::Unretained(this)); -} - -void ProcessSingletonStartupLock::Unlock() { - DCHECK(CalledOnValidThread()); - locked_ = false; - - // Replay the command lines of the messages which were received while the - // ProcessSingleton was locked. Only replay each message once. - std::set replayed_messages; - for (std::vector::const_iterator it = - saved_startup_messages_.begin(); - it != saved_startup_messages_.end(); ++it) { - if (replayed_messages.find(*it) != replayed_messages.end()) - continue; - original_callback_.Run(base::CommandLine(it->first), it->second); - replayed_messages.insert(*it); - } - saved_startup_messages_.clear(); -} - -bool ProcessSingletonStartupLock::NotificationCallbackImpl( - const base::CommandLine& command_line, - const base::FilePath& current_directory) { - if (locked_) { - // If locked, it means we are not ready to process this message because - // we are probably in a first run critical phase. - saved_startup_messages_.push_back( - std::make_pair(command_line.argv(), current_directory)); - return true; - } else { - return original_callback_.Run(command_line, current_directory); - } -} diff --git a/atom/browser/process_singleton_startup_lock.h b/atom/browser/process_singleton_startup_lock.h deleted file mode 100644 index aecff8414e14..000000000000 --- a/atom/browser/process_singleton_startup_lock.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ -#define ATOM_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ - -#include -#include -#include - -#include "base/basictypes.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/threading/non_thread_safe.h" -#include "atom/browser/process_singleton.h" - -// Provides a ProcessSingleton::NotificationCallback that can queue up -// command-line invocations during startup and execute them when startup -// completes. -// -// The object starts in a locked state. |Unlock()| must be called -// when the process is prepared to handle command-line invocations. -// -// Once unlocked, notifications are forwarded to a wrapped NotificationCallback. -class ProcessSingletonStartupLock : public base::NonThreadSafe { - public: - explicit ProcessSingletonStartupLock( - const ProcessSingleton::NotificationCallback& original_callback); - ~ProcessSingletonStartupLock(); - - // Returns the ProcessSingleton::NotificationCallback. - // The callback is only valid during the lifetime of the - // ProcessSingletonStartupLock instance. - ProcessSingleton::NotificationCallback AsNotificationCallback(); - - // Executes previously queued command-line invocations and allows future - // invocations to be executed immediately. - void Unlock(); - - bool locked() { return locked_; } - - private: - typedef std::pair - DelayedStartupMessage; - - bool NotificationCallbackImpl(const base::CommandLine& command_line, - const base::FilePath& current_directory); - - bool locked_; - std::vector saved_startup_messages_; - ProcessSingleton::NotificationCallback original_callback_; - - DISALLOW_COPY_AND_ASSIGN(ProcessSingletonStartupLock); -}; - -#endif // CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ diff --git a/atom/browser/process_singleton_win.cc b/atom/browser/process_singleton_win.cc deleted file mode 100644 index cf667f11e443..000000000000 --- a/atom/browser/process_singleton_win.cc +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "atom/browser/process_singleton.h" - -#include - -#include "base/base_paths.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/process/process.h" -#include "base/process/process_info.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" -#include "base/win/metro.h" -#include "base/win/registry.h" -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" -//#include "chrome/browser/browser_process.h" -//#include "chrome/browser/browser_process_platform_part.h" -#include "atom/browser/atom_process_finder_win.h" -//#include "chrome/browser/shell_integration.h" // TODO: Maybe pull this in? -#include "content/public/common/result_codes.h" -#include "net/base/escape.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/win/hwnd_util.h" - -namespace { - -const char kLockfile[] = "lockfile"; - -// A helper class that acquires the given |mutex| while the AutoLockMutex is in -// scope. -class AutoLockMutex { - public: - explicit AutoLockMutex(HANDLE mutex) : mutex_(mutex) { - DWORD result = ::WaitForSingleObject(mutex_, INFINITE); - DPCHECK(result == WAIT_OBJECT_0) << "Result = " << result; - } - - ~AutoLockMutex() { - BOOL released = ::ReleaseMutex(mutex_); - DPCHECK(released); - } - - private: - HANDLE mutex_; - DISALLOW_COPY_AND_ASSIGN(AutoLockMutex); -}; - -// A helper class that releases the given |mutex| while the AutoUnlockMutex is -// in scope and immediately re-acquires it when going out of scope. -class AutoUnlockMutex { - public: - explicit AutoUnlockMutex(HANDLE mutex) : mutex_(mutex) { - BOOL released = ::ReleaseMutex(mutex_); - DPCHECK(released); - } - - ~AutoUnlockMutex() { - DWORD result = ::WaitForSingleObject(mutex_, INFINITE); - DPCHECK(result == WAIT_OBJECT_0) << "Result = " << result; - } - - private: - HANDLE mutex_; - DISALLOW_COPY_AND_ASSIGN(AutoUnlockMutex); -}; - -// Checks the visibility of the enumerated window and signals once a visible -// window has been found. -BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) { - bool* result = reinterpret_cast(param); - *result = ::IsWindowVisible(window) != 0; - // Stops enumeration if a visible window has been found. - return !*result; -} - -bool ParseCommandLine(const COPYDATASTRUCT* cds, - base::CommandLine* parsed_command_line, - base::FilePath* current_directory) { - // We should have enough room for the shortest command (min_message_size) - // and also be a multiple of wchar_t bytes. The shortest command - // possible is L"START\0\0" (empty current directory and command line). - static const int min_message_size = 7; - if (cds->cbData < min_message_size * sizeof(wchar_t) || - cds->cbData % sizeof(wchar_t) != 0) { - LOG(WARNING) << "Invalid WM_COPYDATA, length = " << cds->cbData; - return false; - } - - // We split the string into 4 parts on NULLs. - DCHECK(cds->lpData); - const std::wstring msg(static_cast(cds->lpData), - cds->cbData / sizeof(wchar_t)); - const std::wstring::size_type first_null = msg.find_first_of(L'\0'); - if (first_null == 0 || first_null == std::wstring::npos) { - // no NULL byte, don't know what to do - LOG(WARNING) << "Invalid WM_COPYDATA, length = " << msg.length() << - ", first null = " << first_null; - return false; - } - - // Decode the command, which is everything until the first NULL. - if (msg.substr(0, first_null) == L"START") { - // Another instance is starting parse the command line & do what it would - // have done. - VLOG(1) << "Handling STARTUP request from another process"; - const std::wstring::size_type second_null = - msg.find_first_of(L'\0', first_null + 1); - if (second_null == std::wstring::npos || - first_null == msg.length() - 1 || second_null == msg.length()) { - LOG(WARNING) << "Invalid format for start command, we need a string in 4 " - "parts separated by NULLs"; - return false; - } - - // Get current directory. - *current_directory = base::FilePath(msg.substr(first_null + 1, - second_null - first_null)); - - const std::wstring::size_type third_null = - msg.find_first_of(L'\0', second_null + 1); - if (third_null == std::wstring::npos || - third_null == msg.length()) { - LOG(WARNING) << "Invalid format for start command, we need a string in 4 " - "parts separated by NULLs"; - } - - // Get command line. - const std::wstring cmd_line = - msg.substr(second_null + 1, third_null - second_null); - *parsed_command_line = base::CommandLine::FromString(cmd_line); - return true; - } - return false; -} - -bool ProcessLaunchNotification( - const ProcessSingleton::NotificationCallback& notification_callback, - UINT message, - WPARAM wparam, - LPARAM lparam, - LRESULT* result) { - if (message != WM_COPYDATA) - return false; - - // Handle the WM_COPYDATA message from another process. - const COPYDATASTRUCT* cds = reinterpret_cast(lparam); - - base::CommandLine parsed_command_line(base::CommandLine::NO_PROGRAM); - base::FilePath current_directory; - if (!ParseCommandLine(cds, &parsed_command_line, ¤t_directory)) { - *result = TRUE; - return true; - } - - *result = notification_callback.Run(parsed_command_line, current_directory) ? - TRUE : FALSE; - return true; -} - -bool TerminateAppWithError() { - // TODO: This is called when the secondary process can't ping the primary - // process. Need to find out what to do here. - return false; -} - -} // namespace - -ProcessSingleton::ProcessSingleton( - const base::FilePath& user_data_dir, - const NotificationCallback& notification_callback) - : notification_callback_(notification_callback), - is_virtualized_(false), - lock_file_(INVALID_HANDLE_VALUE), - user_data_dir_(user_data_dir), - should_kill_remote_process_callback_( - base::Bind(&TerminateAppWithError)) { -} - -ProcessSingleton::~ProcessSingleton() { - if (lock_file_ != INVALID_HANDLE_VALUE) - ::CloseHandle(lock_file_); -} - -// Code roughly based on Mozilla. -ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { - if (is_virtualized_) - return PROCESS_NOTIFIED; // We already spawned the process in this case. - if (lock_file_ == INVALID_HANDLE_VALUE && !remote_window_) { - return LOCK_ERROR; - } else if (!remote_window_) { - return PROCESS_NONE; - } - - switch (atom::AttemptToNotifyRunningAtom(remote_window_, false)) { - case atom::NOTIFY_SUCCESS: - return PROCESS_NOTIFIED; - case atom::NOTIFY_FAILED: - remote_window_ = NULL; - return PROCESS_NONE; - case atom::NOTIFY_WINDOW_HUNG: - // Fall through and potentially terminate the hung browser. - break; - } - - DWORD process_id = 0; - DWORD thread_id = ::GetWindowThreadProcessId(remote_window_, &process_id); - if (!thread_id || !process_id) { - remote_window_ = NULL; - return PROCESS_NONE; - } - base::Process process = base::Process::Open(process_id); - - // The window is hung. Scan for every window to find a visible one. - bool visible_window = false; - ::EnumThreadWindows(thread_id, - &BrowserWindowEnumeration, - reinterpret_cast(&visible_window)); - - // If there is a visible browser window, ask the user before killing it. - if (visible_window && !should_kill_remote_process_callback_.Run()) { - // The user denied. Quit silently. - return PROCESS_NOTIFIED; - } - - // Time to take action. Kill the browser process. - process.Terminate(content::RESULT_CODE_HUNG, true); - remote_window_ = NULL; - return PROCESS_NONE; -} - -ProcessSingleton::NotifyResult -ProcessSingleton::NotifyOtherProcessOrCreate() { - ProcessSingleton::NotifyResult result = PROCESS_NONE; - if (!Create()) { - result = NotifyOtherProcess(); - if (result == PROCESS_NONE) - result = PROFILE_IN_USE; - } else { - // TODO: Figure out how to implement this - //g_browser_process->platform_part()->PlatformSpecificCommandLineProcessing( - // *base::CommandLine::ForCurrentProcess()); - } - return result; -} - -// Look for a Chrome instance that uses the same profile directory. If there -// isn't one, create a message window with its title set to the profile -// directory path. -bool ProcessSingleton::Create() { - static const wchar_t kMutexName[] = L"Local\\AtomProcessSingletonStartup!"; - - remote_window_ = atom::FindRunningAtomWindow(user_data_dir_); - if (!remote_window_) { - // Make sure we will be the one and only process creating the window. - // We use a named Mutex since we are protecting against multi-process - // access. As documented, it's clearer to NOT request ownership on creation - // since it isn't guaranteed we will get it. It is better to create it - // without ownership and explicitly get the ownership afterward. - base::win::ScopedHandle only_me(::CreateMutex(NULL, FALSE, kMutexName)); - if (!only_me.IsValid()) { - DPLOG(FATAL) << "CreateMutex failed"; - return false; - } - - AutoLockMutex auto_lock_only_me(only_me.Get()); - - // We now own the mutex so we are the only process that can create the - // window at this time, but we must still check if someone created it - // between the time where we looked for it above and the time the mutex - // was given to us. - remote_window_ = atom::FindRunningAtomWindow(user_data_dir_); - if (!remote_window_) { - // We have to make sure there is no Chrome instance running on another - // machine that uses the same profile. - base::FilePath lock_file_path = user_data_dir_.AppendASCII(kLockfile); - lock_file_ = ::CreateFile(lock_file_path.value().c_str(), - GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | - FILE_FLAG_DELETE_ON_CLOSE, - NULL); - DWORD error = ::GetLastError(); - LOG_IF(WARNING, lock_file_ != INVALID_HANDLE_VALUE && - error == ERROR_ALREADY_EXISTS) << "Lock file exists but is writable."; - LOG_IF(ERROR, lock_file_ == INVALID_HANDLE_VALUE) - << "Lock file can not be created! Error code: " << error; - - if (lock_file_ != INVALID_HANDLE_VALUE) { - // Set the window's title to the path of our user data directory so - // other Chrome instances can decide if they should forward to us. - bool result = window_.CreateNamed( - base::Bind(&ProcessLaunchNotification, notification_callback_), - user_data_dir_.value()); - CHECK(result && window_.hwnd()); - } - } - } - - return window_.hwnd() != NULL; -} - -void ProcessSingleton::Cleanup() { -} - -void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting( - const ShouldKillRemoteProcessCallback& display_dialog_callback) { - should_kill_remote_process_callback_ = display_dialog_callback; -} From 4a7a09aae1779e548d505741d3d2fbe1f257dcb5 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 15:00:10 -0700 Subject: [PATCH 273/738] Infinite Linting --- atom/browser/api/atom_api_app.cc | 5 +++-- atom/browser/api/atom_api_app.h | 2 +- atom/browser/atom_process_singleton.h | 2 +- atom/browser/browser.cc | 5 +++-- atom/browser/browser.h | 3 ++- .../common/native_mate_converters/command_line_converter.h | 7 ++++--- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index f3955d2d03ab..b16e3460650f 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -276,11 +276,12 @@ bool App::MakeSingleInstance(v8::Local callback) { browser->InitializeSingleInstance(); ProcessSingleton::NotificationCallback cb; - mate::Converter::FromV8(isolate(), single_instance_callback_, &cb); + mate::Converter::FromV8( + isolate(), single_instance_callback_, &cb); browser->SetSingleInstanceCallback(cb); - switch(browser->GetSingleInstanceResult()) { + switch (browser->GetSingleInstanceResult()) { case ProcessSingleton::NotifyResult::PROCESS_NONE: return false; case ProcessSingleton::NotifyResult::LOCK_ERROR: diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 3dafdbc28490..b10b40e5c967 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -71,7 +71,7 @@ class App : public mate::EventEmitter, void AllowNTLMCredentialsForAllDomains(bool should_allow); bool MakeSingleInstance(v8::Local callback); - + std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); diff --git a/atom/browser/atom_process_singleton.h b/atom/browser/atom_process_singleton.h index 56548621436c..89feeaecb37c 100644 --- a/atom/browser/atom_process_singleton.h +++ b/atom/browser/atom_process_singleton.h @@ -16,7 +16,7 @@ class AtomProcessSingleton { AtomProcessSingleton( const base::FilePath& user_data_dir, const ProcessSingleton::NotificationCallback& notification_callback); - + ~AtomProcessSingleton(); // Notify another process, if available. Otherwise sets ourselves as the diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 5c12a0d338f8..4308395eb714 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -117,7 +117,7 @@ void Browser::WillFinishLaunching() { void Browser::DidFinishLaunching() { is_ready_ = true; - process_singleton_->Unlock() ; + process_singleton_->Unlock(); FOR_EACH_OBSERVER(BrowserObserver, observers_, OnFinishLaunching()); } @@ -174,7 +174,8 @@ ProcessSingleton::NotifyResult Browser::GetSingleInstanceResult() { return process_notify_result_; } -void Browser::SetSingleInstanceCallback(ProcessSingleton::NotificationCallback callback) { +void Browser::SetSingleInstanceCallback( + ProcessSingleton::NotificationCallback callback) { process_notify_callback_ = callback; process_notify_callback_set_ = true; } diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 9113c58dd12d..1ac4d03e095a 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -68,7 +68,8 @@ class Browser : public WindowListObserver { void InitializeSingleInstance(); ProcessSingleton::NotifyResult GetSingleInstanceResult(); - void SetSingleInstanceCallback(ProcessSingleton::NotificationCallback callback); + void SetSingleInstanceCallback( + ProcessSingleton::NotificationCallback callback); #if defined(OS_MACOSX) // Bounce the dock icon. diff --git a/atom/common/native_mate_converters/command_line_converter.h b/atom/common/native_mate_converters/command_line_converter.h index 7941c9a0968b..a704ed7e92b7 100644 --- a/atom/common/native_mate_converters/command_line_converter.h +++ b/atom/common/native_mate_converters/command_line_converter.h @@ -16,13 +16,14 @@ template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, const base::CommandLine& val) { - return Converter::ToV8(isolate, val.GetCommandLineString()); + return Converter::ToV8( + isolate, val.GetCommandLineString()); } static bool FromV8(v8::Isolate* isolate, v8::Local val, base::CommandLine* out) { base::FilePath::StringType path; - + if (Converter::FromV8(isolate, val, &path)) { *out = base::CommandLine(base::FilePath(path)); return true; @@ -34,4 +35,4 @@ struct Converter { } // namespace mate -#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_FILE_PATH_CONVERTER_H_ +#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_COMMAND_LINE_CONVERTER_H_ From 15f00db1bf3bef8266d78ca582a0810d2068f52e Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 15:03:59 -0700 Subject: [PATCH 274/738] I don't think we need this --- chromium_src/chrome/browser/process_singleton_win.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/chromium_src/chrome/browser/process_singleton_win.cc b/chromium_src/chrome/browser/process_singleton_win.cc index bedc861c4068..b1008c37607b 100644 --- a/chromium_src/chrome/browser/process_singleton_win.cc +++ b/chromium_src/chrome/browser/process_singleton_win.cc @@ -239,10 +239,6 @@ ProcessSingleton::NotifyOtherProcessOrCreate() { result = NotifyOtherProcess(); if (result == PROCESS_NONE) result = PROFILE_IN_USE; - } else { - // TODO: Figure out how to implement this - //g_browser_process->platform_part()->PlatformSpecificCommandLineProcessing( - // *base::CommandLine::ForCurrentProcess()); } return result; } From fe25f3e747fa64475423acd2ff25cc1171162422 Mon Sep 17 00:00:00 2001 From: Juan Roa Date: Tue, 20 Oct 2015 18:10:08 -0500 Subject: [PATCH 275/738] grammatical corrections for spanish translations at api, styleguide and README --- docs-translations/es/README.md | 6 ++-- .../es/api/chrome-command-line-switches.md | 28 +++++++++---------- docs-translations/es/api/process.md | 8 +++--- docs-translations/es/api/synopsis.md | 14 +++++----- docs-translations/es/styleguide.md | 10 +++---- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/docs-translations/es/README.md b/docs-translations/es/README.md index 6e2374cfd449..706261c417e1 100644 --- a/docs-translations/es/README.md +++ b/docs-translations/es/README.md @@ -1,8 +1,8 @@ ## Guías -* [Platfaformas Soportadas](tutorial/supported-platforms.md) -* [Distribución de la Aplicacion](tutorial/application-distribution.md) -* [Empaquetamiento de la Aplicacion](tutorial/application-packaging.md) +* [Plataformas Soportadas](tutorial/supported-platforms.md) +* [Distribución de la Aplicación](tutorial/application-distribution.md) +* [Empaquetamiento de la Aplicación](tutorial/application-packaging.md) * [Utilizando Módulos Node Nativos](tutorial/using-native-node-modules.md) * [Depurando el Proceso Principal](tutorial/debugging-main-process.md) * [Utilizando Selenium y WebDriver](tutorial/using-selenium-and-webdriver.md) diff --git a/docs-translations/es/api/chrome-command-line-switches.md b/docs-translations/es/api/chrome-command-line-switches.md index c063869adf95..56973ec06ad3 100644 --- a/docs-translations/es/api/chrome-command-line-switches.md +++ b/docs-translations/es/api/chrome-command-line-switches.md @@ -1,9 +1,9 @@ # Parámetros CLI soportados (Chrome) -Esta página lista las líneas de comandos usadas por el navegador Chrome que también son +Esta página lista las líneas de comandos usadas por el navegador Chrome que también son soportadas por Electron. Puedes usar [app.commandLine.appendSwitch][append-switch] para anexarlas en el script principal de tu aplicación antes de que el evento [ready][ready] del -modulo [app][app] sea emitido: +módulo [app][app] sea emitido: ```javascript var app = require('app'); @@ -25,7 +25,7 @@ Ignora el límite de conexiones para la lista de `domains` separados por `,`. ## --disable-http-cache -Deshabilita la cacheé del disco para las peticiones HTTP. +Deshabilita la caché del disco para las peticiones HTTP. ## --remote-debugging-port=`port` @@ -42,7 +42,7 @@ Utiliza el script PAC en la `url` especificada. ## --no-proxy-server -No usa un servidor proxy y siempre establece conexiones directas. Anula cualquier +No usa un servidor proxy y siempre establece conexiones directas. Anula cualquier otra bandera de servidor proxy bandera que se pase. ## --host-rules=`rules` @@ -55,12 +55,12 @@ Por ejemplo: * `MAP * 127.0.0.1` Obliga a todos los nombres de host a ser asignados a 127.0.0.1 * `MAP *.google.com proxy` Obliga todos los subdominios google.com a resolverse con "proxy". -* `MAP test.com [::1]:77` Obliga a resolver "test.com" con un bucle invertido de IPv6. +* `MAP test.com [::1]:77` Obliga a resolver "test.com" con un bucle invertido de IPv6. También obligará a que el puerto de la dirección respuesta sea 77. * `MAP * baz, EXCLUDE www.google.com` Reasigna todo a "baz", excepto a "www.google.com". Estas asignaciones especifican el host final en una petición de red (Anfitrión de la conexión TCP -y de resolución de conexión directa, y el `CONNECT` en una conexión proxy HTTP, y el host final de +y de resolución de conexión directa, y el `CONNECT` en una conexión proxy HTTP, y el host final de la conexión proxy `SOCKS`). ## --host-resolver-rules=`rules` @@ -89,30 +89,30 @@ Permite guardar y escribir eventos de registros de red en `path`. ## --ssl-version-fallback-min=`version` -Establece la versión mínima de SSL/TLS ("tls1", "tls1.1" o "tls1.2") que +Establece la versión mínima de SSL/TLS ("tls1", "tls1.1" o "tls1.2") que el repliegue de TLC aceptará. ## --enable-logging Imprime el registro de Chromium en consola. -Este cambio no puede ser usado en `app.commandLine.appendSwitch` ya que se analiza antes de que la -aplicación del usuario este cargada. +Este cambio no puede ser usado en `app.commandLine.appendSwitch` ya que se analiza antes de que la +aplicación del usuario esté cargada. ## --v=`log_level` -Da el maximo nivel activo de V-logging por defecto; 0 es el predeterminado. Valores positivos +Da el máximo nivel activo de V-logging por defecto; 0 es el predeterminado. Valores positivos son normalmente usados para los niveles de V-logging. Este modificador sólo funciona cuando también se pasa `--enable-logging`. ## --vmodule=`pattern` -Da los niveles máximos de V-logging por módulo para sobreescribir el valor dado por -`--v`. Ej. `my_module=2,foo*=3` cambiaria el nivel de registro para todo el código -el archivos de origen `my_module.*` y `foo*.*`. +Da los niveles máximos de V-logging por módulo para sobreescribir el valor dado por +`--v`. Ej. `my_module=2,foo*=3` cambiaría el nivel de registro para todo el código, +los archivos de origen `my_module.*` y `foo*.*`. -Cualquier patron que contiene un slash o un slash invertido será probado contra toda la ruta +Cualquier patrón que contiene un slash o un slash invertido será probado contra toda la ruta y no sólo con el módulo. Ej. `*/foo/bar/*=2` cambiaría el nivel de registro para todo el código en los archivos origen bajo un directorio `foo/bar`. diff --git a/docs-translations/es/api/process.md b/docs-translations/es/api/process.md index e03ef5fa1c36..9e95ba988541 100644 --- a/docs-translations/es/api/process.md +++ b/docs-translations/es/api/process.md @@ -1,7 +1,7 @@ # process -El objeto `process` en Electron tiene las siguientes diferencias con respecto -al node convencional: +El objeto `process` en Electron tiene las siguientes diferencias con respecto +al node convencional: * `process.type` String - El tipo del proceso puede ser `browser` (ej. proceso principal) o `renderer`. @@ -16,7 +16,7 @@ al node convencional: Se emite cuando Electron ha cargado su script de inicialización interna y está comenzando a cargar la página web o el script principal. -Puede ser usado por el script precargado para añadir de nuevo los símbolos globales +Puede ser usado por el script precargado para añadir de nuevo los símbolos globales de Node eliminados, al alcance global cuando la integración de Node está apagada: ```js @@ -43,5 +43,5 @@ Interrumpe el hilo principal del proceso actual. * `maxDescriptors` Integer Establece el límite dinámico del descriptor del archivo en `maxDescriptors` -o en el límite estricto del Sistema Operativo, el que sea menor para el +o en el límite estricto del Sistema Operativo, el que sea menor para el proceso actual. diff --git a/docs-translations/es/api/synopsis.md b/docs-translations/es/api/synopsis.md index 0da368dea459..eb4fcb39f636 100644 --- a/docs-translations/es/api/synopsis.md +++ b/docs-translations/es/api/synopsis.md @@ -4,14 +4,14 @@ Todos los [Módulos integrados de Node.js](http://nodejs.org/api/) se encuentran disponibles en Electron y módulos de terceros son támbien totalmente compatibles (incluyendo los [módulos nativos](../tutorial/using-native-node-modules.md)). -Electron también provee algunos módulos integrados adicionales para desarrollar +Electron también provee algunos módulos integrados adicionales para desarrollar aplicaciones nativas de escritorio. Algunos módulos sólo se encuentran disponibles -en el proceso principal, algunos sólo en el proceso renderer (pagina web), y +en el proceso principal, algunos sólo en el proceso renderer (página web), y algunos pueden ser usados en ambos procesos. -La regla básica es: Si un módulo es -[GUI](https://es.wikipedia.org/wiki/Interfaz_gráfica_de_usuario) o de bajo nivel, -entonces solo estará disponible en el proceso principal. Necesitas familiarizarte +La regla básica es: Si un módulo es +[GUI](https://es.wikipedia.org/wiki/Interfaz_gráfica_de_usuario) o de bajo nivel, +entonces solo estará disponible en el proceso principal. Necesitas familiarizarte con el concepto de [scripts para proceso principal vs scripts para proceso renderer] (../tutorial/quick-start.md#the-main-process) para ser capaz de usar esos módulos. @@ -29,7 +29,7 @@ app.on('ready', function() { }); ``` -El proceso renderer no es diferente de una página web normal, excepto por la +El proceso renderer no es diferente de una página web normal, excepto por la capacidad extra de utilizar módulos de node: ```html @@ -44,4 +44,4 @@ capacidad extra de utilizar módulos de node: ``` -Para ejecutar tu aplicación, lee [Ejecutar la aplicación](../tutorial/quick-start.md#run-your-app). \ No newline at end of file +Para ejecutar tu aplicación, lee [Ejecutar la aplicación](../tutorial/quick-start.md#run-your-app). diff --git a/docs-translations/es/styleguide.md b/docs-translations/es/styleguide.md index 2e8e7c6f4a9e..4948035ffffe 100644 --- a/docs-translations/es/styleguide.md +++ b/docs-translations/es/styleguide.md @@ -15,7 +15,7 @@ Estas son las maneras en las que construimos la documentación de Electron. - Archivos separados por guiones, mas sin embargo, es correcto. - No subtítulos seguidos por otros subtítulos, añadir por lo menos un enunciado de descripción. -- Métodos de cabecera son delimitados con apóstrofes: `codigo`. +- Métodos de cabecera son delimitados con apóstrofes: `código`. - Cabeceras de Eventos son delimitados con 'comillas' simples. - No generar listas de mas de dos niveles (debido al renderizador de Markdown desafortunadamente). @@ -25,7 +25,7 @@ Estas son las maneras en las que construimos la documentación de Electron. - Argumentos opcionales escritos como `function (required[, optional])`. - Argumentos opcionales son denotados cuando se llaman en listas. - Delimitador de línea de 80-columnas. -- Métodos específicos de Plataformas son denotados en italicas seguidas por la cabecera del método. +- Métodos específicos de Plataformas son denotados en itálicas seguidas por la cabecera del método. - ```### `method(foo, bar)` _OS X_``` - Preferir 'en el ___ proceso' en lugar de 'sobre el' @@ -47,7 +47,7 @@ Para agregar otro set (o un set parcial): ## Leyendo la Documentación de Electron -Estos son algunos consejos para entender la syntaxis de la documentación de +Estos son algunos consejos para entender la sintaxis de la documentación de Electron. ### Métodos @@ -67,7 +67,7 @@ El nombre del método es seguido por los argumentos que recibe. Argumentos opcionales son denotados por corchetes rodeados por el argumento opcional y la coma requerida si el argumento opcional fuera seguido por otro argumento. -Debajo del método se encuentra mas información detallada de cada uno de los +Debajo del método se encuentra más información detallada de cada uno de los argumentos. El tipo de argumento es denotado por los tipos comúnes: [`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), @@ -90,7 +90,7 @@ Returns: --- El evento es una cadena que es utilizada luego de un método observador `.on`. Si -regresa un valor, el y su tipo son denotados abajo. Si se estaba a la escucha y +regresa un valor, él y su tipo son denotados abajo. Si se estaba a la escucha y respondió a este evento se debería ver así: ```javascript From e5094fff3eb06b9feae8ac5e6bf22b7cffe90b87 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 17:27:28 -0700 Subject: [PATCH 276/738] Since setting up process_singleton is now conditional, its cleanup / unlock must be too --- atom/browser/browser.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 4308395eb714..483e58a988be 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -117,7 +117,11 @@ void Browser::WillFinishLaunching() { void Browser::DidFinishLaunching() { is_ready_ = true; - process_singleton_->Unlock(); + + if (process_notify_callback_set_) { + process_singleton_->Unlock(); + } + FOR_EACH_OBSERVER(BrowserObserver, observers_, OnFinishLaunching()); } @@ -144,7 +148,10 @@ void Browser::NotifyAndShutdown() { return; } - process_singleton_->Cleanup(); + if (process_notify_callback_set_) { + process_singleton_->Cleanup(); + } + Shutdown(); } @@ -167,6 +174,10 @@ void Browser::InitializeSingleInstance() { base::Bind(&Browser::OnProcessSingletonNotification, no_refcount_this))); process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); + + if (is_ready_) { + process_singleton_->Unlock(); + } } ProcessSingleton::NotifyResult Browser::GetSingleInstanceResult() { From 99c496471b665ac81e42e71603f14b87cfc6b637 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Tue, 20 Oct 2015 17:36:05 -0700 Subject: [PATCH 277/738] Allow WM_COPYDATA from all processes --- chromium_src/chrome/browser/process_singleton_win.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/chromium_src/chrome/browser/process_singleton_win.cc b/chromium_src/chrome/browser/process_singleton_win.cc index b1008c37607b..0007b713b13b 100644 --- a/chromium_src/chrome/browser/process_singleton_win.cc +++ b/chromium_src/chrome/browser/process_singleton_win.cc @@ -293,6 +293,11 @@ bool ProcessSingleton::Create() { bool result = window_.CreateNamed( base::Bind(&ProcessLaunchNotification, notification_callback_), user_data_dir_.value()); + + // NB: Ensure that if the primary app gets started as elevated + // admin inadvertently, secondary windows running not as elevated + // will still be able to send messages + ::ChangeWindowMessageFilterEx(window_.hwnd(), WM_COPYDATA, MSGFLT_ALLOW, NULL); CHECK(result && window_.hwnd()); } } From d092c6acc956fd5b2c4e1431f9a25dbac17e681b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 21 Oct 2015 07:33:43 +0800 Subject: [PATCH 278/738] osx: Implement draggable region with mouseDownCanMoveWindow Previously we implemented draggable region by tracking mouse position, it is buggy and causing some problems. But it is interesting that until this didn't cause troubles until recently. --- atom/browser/native_window.cc | 34 +++---- atom/browser/native_window.h | 13 ++- atom/browser/native_window_mac.h | 25 ++--- atom/browser/native_window_mac.mm | 148 ++++++++++++++++-------------- 4 files changed, 116 insertions(+), 104 deletions(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 7f30aa00389f..8f3af83885f1 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -43,26 +43,6 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay); namespace atom { -namespace { - -// Convert draggable regions in raw format to SkRegion format. Caller is -// responsible for deleting the returned SkRegion instance. -scoped_ptr DraggableRegionsToSkRegion( - const std::vector& regions) { - scoped_ptr sk_region(new SkRegion); - for (const DraggableRegion& region : regions) { - sk_region->op( - region.bounds.x(), - region.bounds.y(), - region.bounds.right(), - region.bounds.bottom(), - region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op); - } - return sk_region.Pass(); -} - -} // namespace - NativeWindow::NativeWindow( brightray::InspectableWebContents* inspectable_web_contents, const mate::Dictionary& options) @@ -480,6 +460,20 @@ void NativeWindow::NotifyWindowExecuteWindowsCommand( OnExecuteWindowsCommand(command)); } +scoped_ptr NativeWindow::DraggableRegionsToSkRegion( + const std::vector& regions) { + scoped_ptr sk_region(new SkRegion); + for (const DraggableRegion& region : regions) { + sk_region->op( + region.bounds.x(), + region.bounds.y(), + region.bounds.right(), + region.bounds.bottom(), + region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op); + } + return sk_region.Pass(); +} + void NativeWindow::RenderViewCreated( content::RenderViewHost* render_view_host) { if (!transparent_) diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 379c23837b19..67bac88f32d4 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -241,10 +241,19 @@ class NativeWindow : public base::SupportsUserData, NativeWindow(brightray::InspectableWebContents* inspectable_web_contents, const mate::Dictionary& options); + // Convert draggable regions in raw format to SkRegion format. Caller is + // responsible for deleting the returned SkRegion instance. + scoped_ptr DraggableRegionsToSkRegion( + const std::vector& regions); + // Converts between content size to window size. virtual gfx::Size ContentSizeToWindowSize(const gfx::Size& size) = 0; virtual gfx::Size WindowSizeToContentSize(const gfx::Size& size) = 0; + // Called when the window needs to update its draggable region. + virtual void UpdateDraggableRegions( + const std::vector& regions); + // content::WebContentsObserver: void RenderViewCreated(content::RenderViewHost* render_view_host) override; void BeforeUnloadDialogCancelled() override; @@ -252,10 +261,6 @@ class NativeWindow : public base::SupportsUserData, bool OnMessageReceived(const IPC::Message& message) override; private: - // Called when the window needs to update its draggable region. - void UpdateDraggableRegions( - const std::vector& regions); - // Schedule a notification unresponsive event. void ScheduleUnresponsiveEvent(int ms); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 60581a2d977b..7a97032d75ff 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -71,12 +71,10 @@ class NativeWindowMac : public NativeWindow { void SetVisibleOnAllWorkspaces(bool visible) override; bool IsVisibleOnAllWorkspaces() override; - // Returns true if |point| in local Cocoa coordinate system falls within - // the draggable region. - bool IsWithinDraggableRegion(NSPoint point) const; - - // Called to handle a mouse event. - void HandleMouseEvent(NSEvent* event); + // Refresh the DraggableRegion views. + void UpdateDraggableRegionViews() { + UpdateDraggableRegionViews(draggable_regions_); + } protected: // NativeWindow: @@ -84,17 +82,24 @@ class NativeWindowMac : public NativeWindow { content::WebContents*, const content::NativeWebKeyboardEvent&) override; + // Return a vector of non-draggable regions that fill a window of size + // |width| by |height|, but leave gaps where the window should be draggable. + std::vector CalculateNonDraggableRegions( + const std::vector& regions, int width, int height); + private: // NativeWindow: gfx::Size ContentSizeToWindowSize(const gfx::Size& size) override; gfx::Size WindowSizeToContentSize(const gfx::Size& size) override; + void UpdateDraggableRegions( + const std::vector& regions) override; void InstallView(); void UninstallView(); // Install the drag view, which will cover the whole window and decides // whehter we can drag. - void InstallDraggableRegionView(); + void UpdateDraggableRegionViews(const std::vector& regions); base::scoped_nsobject window_; base::scoped_nsobject window_delegate_; @@ -102,6 +107,8 @@ class NativeWindowMac : public NativeWindow { // The view that will fill the whole frameless window. base::scoped_nsobject content_view_; + std::vector draggable_regions_; + bool is_kiosk_; NSInteger attention_request_id_; // identifier from requestUserAttention @@ -109,10 +116,6 @@ class NativeWindowMac : public NativeWindow { // The presentation options before entering kiosk mode. NSApplicationPresentationOptions kiosk_options_; - // Mouse location since the last mouse event, in screen coordinates. This is - // used in custom drag to compute the window movement. - NSPoint last_mouse_offset_; - DISALLOW_COPY_AND_ASSIGN(NativeWindowMac); }; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 6420345da9b6..9724930c4885 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -19,6 +19,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "native_mate/dictionary.h" +#include "ui/gfx/skia_util.h" namespace { @@ -146,6 +147,7 @@ bool ScopedDisableResize::disable_resize_ = false; } - (void)windowDidResize:(NSNotification*)notification { + shell_->UpdateDraggableRegionViews(); shell_->NotifyWindowResize(); } @@ -257,43 +259,23 @@ bool ScopedDisableResize::disable_resize_ = false; @end -@interface ControlRegionView : NSView { - @private - atom::NativeWindowMac* shellWindow_; // Weak; owns self. -} +@interface ControlRegionView : NSView @end @implementation ControlRegionView -- (id)initWithShellWindow:(atom::NativeWindowMac*)shellWindow { - if ((self = [super init])) - shellWindow_ = shellWindow; - return self; -} - - (BOOL)mouseDownCanMoveWindow { return NO; } - (NSView*)hitTest:(NSPoint)aPoint { - if (!shellWindow_->IsWithinDraggableRegion(aPoint)) { - return nil; - } - return self; + return nil; } -- (void)mouseDown:(NSEvent*)event { - shellWindow_->HandleMouseEvent(event); -} - -- (void)mouseDragged:(NSEvent*)event { - shellWindow_->HandleMouseEvent(event); -} - -- (BOOL)acceptsFirstMouse:(NSEvent*)event { - return YES; -} +@end +@interface NSView (WebContentsView) +- (void)setMouseDownCanMoveWindow:(BOOL)can_move; @end @interface AtomProgressBar : NSProgressIndicator @@ -439,11 +421,6 @@ NativeWindowMac::NativeWindowMac( [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; InstallView(); - - // Install the DraggableRegionView if it is forced to use draggable regions - // for normal window. - if (has_frame() && force_using_draggable_region()) - InstallDraggableRegionView(); } NativeWindowMac::~NativeWindowMac() { @@ -746,36 +723,6 @@ bool NativeWindowMac::IsVisibleOnAllWorkspaces() { return collectionBehavior & NSWindowCollectionBehaviorCanJoinAllSpaces; } -bool NativeWindowMac::IsWithinDraggableRegion(NSPoint point) const { - if (!draggable_region()) - return false; - if (!web_contents()) - return false; - NSView* webView = web_contents()->GetNativeView(); - NSInteger webViewHeight = NSHeight([webView bounds]); - // |draggable_region_| is stored in local platform-indepdent coordiate system - // while |point| is in local Cocoa coordinate system. Do the conversion - // to match these two. - return draggable_region()->contains(point.x, webViewHeight - point.y); -} - -void NativeWindowMac::HandleMouseEvent(NSEvent* event) { - NSPoint eventLoc = [event locationInWindow]; - NSRect mouseRect = [window_ convertRectToScreen:NSMakeRect(eventLoc.x, eventLoc.y, 0, 0)]; - NSPoint current_mouse_location = mouseRect.origin; - - if ([event type] == NSLeftMouseDown) { - NSPoint frame_origin = [window_ frame].origin; - last_mouse_offset_ = NSMakePoint( - frame_origin.x - current_mouse_location.x, - frame_origin.y - current_mouse_location.y); - } else if ([event type] == NSLeftMouseDragged) { - [window_ setFrameOrigin:NSMakePoint( - current_mouse_location.x + last_mouse_offset_.x, - current_mouse_location.y + last_mouse_offset_.y)]; - } -} - void NativeWindowMac::HandleKeyboardEvent( content::WebContents*, const content::NativeWebKeyboardEvent& event) { @@ -800,6 +747,23 @@ void NativeWindowMac::HandleKeyboardEvent( } } +std::vector NativeWindowMac::CalculateNonDraggableRegions( + const std::vector& regions, int width, int height) { + std::vector result; + if (regions.empty()) { + result.push_back(gfx::Rect(0, 0, width, height)); + } else { + scoped_ptr draggable(DraggableRegionsToSkRegion(regions)); + scoped_ptr non_draggable(new SkRegion); + non_draggable->op(0, 0, width, height, SkRegion::kUnion_Op); + non_draggable->op(*draggable, SkRegion::kDifference_Op); + for (SkRegion::Iterator it(*non_draggable); !it.done(); it.next()) { + result.push_back(gfx::SkIRectToRect(it.rect())); + } + } + return result; +} + gfx::Size NativeWindowMac::ContentSizeToWindowSize(const gfx::Size& size) { if (!has_frame()) return size; @@ -818,6 +782,13 @@ gfx::Size NativeWindowMac::WindowSizeToContentSize(const gfx::Size& size) { return gfx::Size(content.size); } +void NativeWindowMac::UpdateDraggableRegions( + const std::vector& regions) { + NativeWindow::UpdateDraggableRegions(regions); + draggable_regions_ = regions; + UpdateDraggableRegionViews(regions); +} + void NativeWindowMac::InstallView() { // Make sure the bottom corner is rounded: http://crbug.com/396264. [[window_ contentView] setWantsLayer:YES]; @@ -840,8 +811,6 @@ void NativeWindowMac::InstallView() { [view setFrame:[content_view_ bounds]]; [content_view_ addSubview:view]; - InstallDraggableRegionView(); - [[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES]; [[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES]; [[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES]; @@ -858,14 +827,55 @@ void NativeWindowMac::UninstallView() { [view removeFromSuperview]; } -void NativeWindowMac::InstallDraggableRegionView() { +void NativeWindowMac::UpdateDraggableRegionViews( + const std::vector& regions) { + if (has_frame() && !force_using_draggable_region()) + return; + + // All ControlRegionViews should be added as children of the WebContentsView, + // because WebContentsView will be removed and re-added when entering and + // leaving fullscreen mode. NSView* webView = web_contents()->GetNativeView(); - base::scoped_nsobject controlRegion( - [[ControlRegionView alloc] initWithShellWindow:this]); - [controlRegion setFrame:NSMakeRect(0, 0, - NSWidth([webView bounds]), - NSHeight([webView bounds]))]; - [webView addSubview:controlRegion]; + NSInteger webViewWidth = NSWidth([webView bounds]); + NSInteger webViewHeight = NSHeight([webView bounds]); + + [webView setMouseDownCanMoveWindow:YES]; + + // Remove all ControlRegionViews that are added last time. + // Note that [webView subviews] returns the view's mutable internal array and + // it should be copied to avoid mutating the original array while enumerating + // it. + base::scoped_nsobject subviews([[webView subviews] copy]); + for (NSView* subview in subviews.get()) + if ([subview isKindOfClass:[ControlRegionView class]]) + [subview removeFromSuperview]; + + // Draggable regions is implemented by having the whole web view draggable + // (mouseDownCanMoveWindow) and overlaying regions that are not draggable. + std::vector system_drag_exclude_areas = + CalculateNonDraggableRegions(regions, webViewWidth, webViewHeight); + + // Create and add a ControlRegionView for each region that needs to be + // excluded from the dragging. + for (std::vector::const_iterator iter = + system_drag_exclude_areas.begin(); + iter != system_drag_exclude_areas.end(); + ++iter) { + base::scoped_nsobject controlRegion( + [[ControlRegionView alloc] initWithFrame:NSZeroRect]); + [controlRegion setFrame:NSMakeRect(iter->x(), + webViewHeight - iter->bottom(), + iter->width(), + iter->height())]; + [webView addSubview:controlRegion]; + } + + // AppKit will not update its cache of mouseDownCanMoveWindow unless something + // changes. Previously we tried adding an NSView and removing it, but for some + // reason it required reposting the mouse-down event, and didn't always work. + // Calling the below seems to be an effective solution. + [window_ setMovableByWindowBackground:NO]; + [window_ setMovableByWindowBackground:YES]; } // static From 2d410ede4890551240f7745a967c67213ca29b3e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 21 Oct 2015 07:34:15 +0800 Subject: [PATCH 279/738] Initialize things in the same sequence with main process --- atom/app/atom_library_main.mm | 2 ++ atom/app/node_main.cc | 17 +++++++---------- atom/browser/javascript_environment.cc | 1 - vendor/brightray | 2 +- vendor/node | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/atom/app/atom_library_main.mm b/atom/app/atom_library_main.mm index 885500beb5d3..7ee752293468 100644 --- a/atom/app/atom_library_main.mm +++ b/atom/app/atom_library_main.mm @@ -10,6 +10,7 @@ #include "base/at_exit.h" #include "base/i18n/icu_util.h" #include "base/mac/bundle_locations.h" +#include "base/mac/scoped_nsautorelease_pool.h" #include "brightray/common/mac/main_application_bundle.h" #include "content/public/app/content_main.h" @@ -25,6 +26,7 @@ int AtomMain(int argc, const char* argv[]) { int AtomInitializeICUandStartNode(int argc, char *argv[]) { base::AtExitManager atexit_manager; + base::mac::ScopedNSAutoreleasePool pool; base::mac::SetOverrideFrameworkBundlePath( brightray::MainApplicationBundlePath() .Append("Contents") diff --git a/atom/app/node_main.cc b/atom/app/node_main.cc index 7efb1b40eece..b946ae28ff94 100644 --- a/atom/app/node_main.cc +++ b/atom/app/node_main.cc @@ -7,8 +7,8 @@ #include "atom/app/uv_task_runner.h" #include "atom/browser/javascript_environment.h" #include "atom/browser/node_debugger.h" -#include "atom/common/node_includes.h" #include "base/command_line.h" +#include "atom/common/node_includes.h" #include "base/thread_task_runner_handle.h" #include "gin/array_buffer.h" #include "gin/public/isolate_holder.h" @@ -19,25 +19,22 @@ namespace atom { int NodeMain(int argc, char *argv[]) { base::CommandLine::Init(argc, argv); - argv = uv_setup_args(argc, argv); - int exec_argc; - const char** exec_argv; - node::Init(&argc, const_cast(argv), &exec_argc, &exec_argv); - int exit_code = 1; { // Feed gin::PerIsolateData with a task runner. + argv = uv_setup_args(argc, argv); uv_loop_t* loop = uv_default_loop(); scoped_refptr uv_task_runner(new UvTaskRunner(loop)); base::ThreadTaskRunnerHandle handle(uv_task_runner); gin::V8Initializer::LoadV8Snapshot(); gin::V8Initializer::LoadV8Natives(); - gin::IsolateHolder::Initialize( - gin::IsolateHolder::kNonStrictMode, - gin::ArrayBufferAllocator::SharedInstance()); - JavascriptEnvironment gin_env; + + int exec_argc; + const char** exec_argv; + node::Init(&argc, const_cast(argv), &exec_argc, &exec_argv); + node::Environment* env = node::CreateEnvironment( gin_env.isolate(), loop, gin_env.context(), argc, argv, exec_argc, exec_argv); diff --git a/atom/browser/javascript_environment.cc b/atom/browser/javascript_environment.cc index 3788fcad8b68..4e825e38142d 100644 --- a/atom/browser/javascript_environment.cc +++ b/atom/browser/javascript_environment.cc @@ -20,7 +20,6 @@ JavascriptEnvironment::JavascriptEnvironment() } bool JavascriptEnvironment::Initialize() { - gin::V8Initializer::LoadV8Snapshot(); gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, gin::ArrayBufferAllocator::SharedInstance()); return true; diff --git a/vendor/brightray b/vendor/brightray index f1cbfd1d457f..49a86c123f4c 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit f1cbfd1d457f9b40bca23a2f30948a093d6048a9 +Subproject commit 49a86c123f4cc43f4dca886ded612104a8a1fec6 diff --git a/vendor/node b/vendor/node index f4243f5c84a3..edfbc29d0942 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit f4243f5c84a371632d8d72a1a2210a0e994afdcc +Subproject commit edfbc29d09425f2f387c52d77f6351b6ce101659 From 444f461269f77c67d4ce1bb6009baba15d98b71e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 21 Oct 2015 20:46:16 +0800 Subject: [PATCH 280/738] Fix memory corruption when cleaning timer --- atom/app/uv_task_runner.cc | 9 +++++++-- atom/app/uv_task_runner.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/atom/app/uv_task_runner.cc b/atom/app/uv_task_runner.cc index 23463e44e2ef..f49ba259bac8 100644 --- a/atom/app/uv_task_runner.cc +++ b/atom/app/uv_task_runner.cc @@ -48,8 +48,13 @@ void UvTaskRunner::OnTimeout(uv_timer_t* timer) { self->tasks_[timer].Run(); self->tasks_.erase(timer); - uv_unref(reinterpret_cast(timer)); - delete timer; + uv_timer_stop(timer); + uv_close(reinterpret_cast(timer), UvTaskRunner::OnClose); +} + +// static +void UvTaskRunner::OnClose(uv_handle_t* handle) { + delete reinterpret_cast(handle); } } // namespace atom diff --git a/atom/app/uv_task_runner.h b/atom/app/uv_task_runner.h index e4eac0155354..c7302766c2d1 100644 --- a/atom/app/uv_task_runner.h +++ b/atom/app/uv_task_runner.h @@ -31,6 +31,7 @@ class UvTaskRunner : public base::SingleThreadTaskRunner { private: static void OnTimeout(uv_timer_t* timer); + static void OnClose(uv_handle_t* handle); uv_loop_t* loop_; From 38d6ff79c806a8ce7e3da6770b058eeb11a384a2 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 21 Oct 2015 11:06:42 -0700 Subject: [PATCH 281/738] Need to free this early or get a SIGSEGV on Linux --- atom/browser/browser.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 483e58a988be..c8d6104beae4 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -150,6 +150,7 @@ void Browser::NotifyAndShutdown() { if (process_notify_callback_set_) { process_singleton_->Cleanup(); + process_notify_callback_.Reset(); } Shutdown(); From acbd7d7541a76d5496fcaa2049c1c9b0334a6ee3 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 22 Oct 2015 03:36:14 +0900 Subject: [PATCH 282/738] Update as upstream --- docs-translations/ko-KR/api/app.md | 4 ++++ docs-translations/ko-KR/tutorial/quick-start.md | 2 +- 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 c364d9dc606e..498fbb59bfcd 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -284,6 +284,10 @@ Windows에서 사용할 수 있는 JumpList의 [Tasks][tasks] 카테고리에 `t 항상 동적으로 HTTP NTLM 또는 Negotiate 인증에 자격 증명을 보낼 것인지 설정합니다. +기본적으로 Electron은 "로컬 인터넷" 사이트 URL에서 NTLM/Kerberos 자격 증명만을 보냅니다. (같은 도메인 내에서) +그러나 기업 네트워크가 잘못 구성된 경우 종종 작업에 실패할 수 있습니다. +이때 이 메서드를 통해 모든 URL을 허용할 수 있습니다. + ### `app.commandLine.appendSwitch(switch[, value])` Chrominum의 명령줄에 스위치를 추가합니다. `value`는 추가적인 값을 뜻하며 옵션입니다. diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index ce3c7e29e0e8..5c2cc80f4060 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -93,7 +93,7 @@ app.on('ready', function() { mainWindow.loadUrl('file://' + __dirname + '/index.html'); // 개발자 콘솔을 엽니다. - mainWindow.openDevTools(); + mainWindow.webContents.openDevTools(); // 창이 닫히면 호출됩니다. mainWindow.on('closed', function() { From a160891a27ddfa7ad68860ed45a61300f2ef2c5e Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 21 Oct 2015 12:29:00 -0700 Subject: [PATCH 283/738] If a user calls makeSingleInstance more than once, just ignore it --- atom/browser/api/atom_api_app.cc | 14 +++++++------- atom/browser/browser.cc | 7 ++++--- atom/browser/browser.h | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index b16e3460650f..96f1ce025372 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -271,15 +271,15 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { bool App::MakeSingleInstance(v8::Local callback) { auto browser = Browser::Get(); - single_instance_callback_ = callback; + if (browser->InitializeSingleInstance()) { + single_instance_callback_ = callback; - browser->InitializeSingleInstance(); + ProcessSingleton::NotificationCallback cb; + mate::Converter::FromV8( + isolate(), single_instance_callback_, &cb); - ProcessSingleton::NotificationCallback cb; - mate::Converter::FromV8( - isolate(), single_instance_callback_, &cb); - - browser->SetSingleInstanceCallback(cb); + browser->SetSingleInstanceCallback(cb); + } switch (browser->GetSingleInstanceResult()) { case ProcessSingleton::NotifyResult::PROCESS_NONE: diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index c8d6104beae4..6bfeae3c56b1 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -165,7 +165,7 @@ bool Browser::HandleBeforeQuit() { return !prevent_default; } -void Browser::InitializeSingleInstance() { +bool Browser::InitializeSingleInstance() { base::FilePath userDir; PathService::Get(brightray::DIR_USER_DATA, &userDir); @@ -174,11 +174,12 @@ void Browser::InitializeSingleInstance() { userDir, base::Bind(&Browser::OnProcessSingletonNotification, no_refcount_this))); - process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); - if (is_ready_) { process_singleton_->Unlock(); } + + process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); + return true; } ProcessSingleton::NotifyResult Browser::GetSingleInstanceResult() { diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 1ac4d03e095a..f9b86b6924a0 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -66,7 +66,7 @@ class Browser : public WindowListObserver { // Clear the recent documents list. void ClearRecentDocuments(); - void InitializeSingleInstance(); + bool InitializeSingleInstance(); ProcessSingleton::NotifyResult GetSingleInstanceResult(); void SetSingleInstanceCallback( ProcessSingleton::NotificationCallback callback); From 658a9872fb681c331f154cadc508380959e36df3 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 21 Oct 2015 12:29:21 -0700 Subject: [PATCH 284/738] Only cleanup if we are the main process --- atom/browser/browser.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 6bfeae3c56b1..6d39cdcc8b96 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -149,8 +149,11 @@ void Browser::NotifyAndShutdown() { } if (process_notify_callback_set_) { - process_singleton_->Cleanup(); process_notify_callback_.Reset(); + + if (process_notify_result_ == ProcessSingleton::PROCESS_NONE) { + process_singleton_->Cleanup(); + } } Shutdown(); From b61c2e6ff7333f172dca600ee8bbd419cf00f9f6 Mon Sep 17 00:00:00 2001 From: Thomas J Fox Date: Wed, 21 Oct 2015 15:03:12 -0500 Subject: [PATCH 285/738] quick fix removing excess character --- .../mac-app-store-submission-guide.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md index fb04a5573b12..113185918803 100644 --- a/docs/tutorial/mac-app-store-submission-guide.md +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -1,26 +1,26 @@ # Mac App Store Submission Guide -Since v0.34.0, Electron allows submitting packaged apps to the Mac App Store -(MAS). This guide provides information on: how to submit your app and the +Since v0.34.0, Electron allows submitting packaged apps to the Mac App Store +(MAS). This guide provides information on: how to submit your app and the limitations of the MAS build. ## How to Submit Your App -The following steps introduce a simple way to submit your app to Mac App Store. -However, these steps do not ensure sure your app will be approved by Apple; you -still need to read Apple's [Submitting Your App][submitting-your-app] guide on +The following steps introduce a simple way to submit your app to Mac App Store. +However, these steps do not ensure sure your app will be approved by Apple; you +still need to read Apple's [Submitting Your App][submitting-your-app] guide on how to meet the Mac App Store requirements. ### Get Certificate -To submit your app to the Mac App Store, you first must get a certificate from +To submit your app to the Mac App Store, you first must get a certificate from Apple. You can follow these [existing guides][nwjs-guide] on web. ### Sign Your App After getting the certificate from Apple, you can package your app by following -[Application Distribution](application-distribution.md), and then proceed to -signing your app. This step is basically the same with other programs, but the +[Application Distribution](application-distribution.md), and then proceed to +signing your app. This step is basically the same with other programs, but the key is to sign every dependency of Electron one by one. First, you need to prepare two entitlements files. @@ -79,9 +79,9 @@ codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$APP_PATH" ``` -a + If you are new to app sandboxing under OS X, you should also read through -Apple's [Enabling App Sandbox][enable-app-sandbox] to have a basic idea, then +Apple's [Enabling App Sandbox][enable-app-sandbox] to have a basic idea, then add keys for the permissions needed by your app to the entitlements files. ### Upload Your App and Submit for Review @@ -92,7 +92,7 @@ before uploading. Then you can [submit your app for review][submit-for-review]. ## Limitations of MAS Build -In order to satisfy all requirements for app sandboxing, the following modules +In order to satisfy all requirements for app sandboxing, the following modules have been disabled in the MAS build: * `crash-reporter` From 938d68eb3607140313f4048dfc87be3075c7e1c6 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 21 Oct 2015 13:04:50 -0700 Subject: [PATCH 286/738] Move all the browser.cc code over to atom_api_app.cc --- atom/browser/api/atom_api_app.cc | 40 ++++++++++++++++------- atom/browser/api/atom_api_app.h | 7 ++-- atom/browser/browser.cc | 56 +------------------------------- atom/browser/browser.h | 16 --------- 4 files changed, 34 insertions(+), 85 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 96f1ce025372..97d5cf6aa2df 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -161,6 +161,14 @@ void App::OnWindowAllClosed() { void App::OnQuit() { Emit("quit"); + + if (process_singleton_.get()) { + if (process_notify_result_ == ProcessSingleton::PROCESS_NONE) { + process_singleton_->Cleanup(); + } + + process_singleton_.reset(); + } } void App::OnOpenFile(bool* prevent_default, const std::string& file_path) { @@ -187,6 +195,10 @@ void App::OnFinishLaunching() { AtomBrowserMainParts::Get()->browser_context()); auto handle = Session::CreateFrom(isolate(), browser_context); default_session_.Reset(isolate(), handle.ToV8()); + + if (process_singleton_.get()) { + process_singleton_->Unlock(); + } Emit("ready"); } @@ -269,28 +281,32 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { return v8::Local::New(isolate, default_session_); } -bool App::MakeSingleInstance(v8::Local callback) { - auto browser = Browser::Get(); - if (browser->InitializeSingleInstance()) { - single_instance_callback_ = callback; +bool App::MakeSingleInstance(ProcessSingleton::NotificationCallback callback) { + + base::FilePath userDir; + PathService::Get(brightray::DIR_USER_DATA, &userDir); + + if (!process_singleton_.get()) { + auto browser = Browser::Get(); + process_singleton_.reset(new AtomProcessSingleton(userDir, callback)); + + if (browser->is_ready()) { + process_singleton_->Unlock(); + } - ProcessSingleton::NotificationCallback cb; - mate::Converter::FromV8( - isolate(), single_instance_callback_, &cb); - - browser->SetSingleInstanceCallback(cb); + process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); } - switch (browser->GetSingleInstanceResult()) { + switch (process_notify_result_) { case ProcessSingleton::NotifyResult::PROCESS_NONE: return false; case ProcessSingleton::NotifyResult::LOCK_ERROR: case ProcessSingleton::NotifyResult::PROFILE_IN_USE: case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: return true; + default: + return false; } - - return false; } mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index b10b40e5c967..82ae04502030 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -8,6 +8,7 @@ #include #include "atom/browser/api/event_emitter.h" +#include "atom/browser/atom_process_singleton.h" #include "atom/browser/browser_observer.h" #include "atom/common/native_mate_converters/callback.h" #include "chrome/browser/process_singleton.h" @@ -70,13 +71,15 @@ class App : public mate::EventEmitter, void AllowNTLMCredentialsForAllDomains(bool should_allow); - bool MakeSingleInstance(v8::Local callback); + bool MakeSingleInstance(ProcessSingleton::NotificationCallback callback); std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); - v8::Local single_instance_callback_; v8::Global default_session_; + + scoped_ptr process_singleton_; + ProcessSingleton::NotifyResult process_notify_result_; DISALLOW_COPY_AND_ASSIGN(App); }; diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 6d39cdcc8b96..d8bb94103cd9 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -9,8 +9,6 @@ #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/window_list.h" #include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "brightray/browser/brightray_paths.h" #include "content/public/browser/client_certificate_delegate.h" #include "net/ssl/ssl_cert_request_info.h" @@ -19,8 +17,7 @@ namespace atom { Browser::Browser() : is_quiting_(false), is_ready_(false), - is_shutdown_(false), - process_notify_callback_set_(false) { + is_shutdown_(false) { WindowList::AddObserver(this); } @@ -117,11 +114,6 @@ void Browser::WillFinishLaunching() { void Browser::DidFinishLaunching() { is_ready_ = true; - - if (process_notify_callback_set_) { - process_singleton_->Unlock(); - } - FOR_EACH_OBSERVER(BrowserObserver, observers_, OnFinishLaunching()); } @@ -148,14 +140,6 @@ void Browser::NotifyAndShutdown() { return; } - if (process_notify_callback_set_) { - process_notify_callback_.Reset(); - - if (process_notify_result_ == ProcessSingleton::PROCESS_NONE) { - process_singleton_->Cleanup(); - } - } - Shutdown(); } @@ -168,34 +152,6 @@ bool Browser::HandleBeforeQuit() { return !prevent_default; } -bool Browser::InitializeSingleInstance() { - base::FilePath userDir; - PathService::Get(brightray::DIR_USER_DATA, &userDir); - - auto no_refcount_this = base::Unretained(this); - process_singleton_.reset(new AtomProcessSingleton( - userDir, - base::Bind(&Browser::OnProcessSingletonNotification, no_refcount_this))); - - if (is_ready_) { - process_singleton_->Unlock(); - } - - process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); - return true; -} - -ProcessSingleton::NotifyResult Browser::GetSingleInstanceResult() { - LOG(ERROR) << "Process Notify Result: " << process_notify_result_; - return process_notify_result_; -} - -void Browser::SetSingleInstanceCallback( - ProcessSingleton::NotificationCallback callback) { - process_notify_callback_ = callback; - process_notify_callback_set_ = true; -} - void Browser::OnWindowCloseCancelled(NativeWindow* window) { if (is_quiting_) // Once a beforeunload handler has prevented the closing, we think the quit @@ -210,14 +166,4 @@ void Browser::OnWindowAllClosed() { FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWindowAllClosed()); } -bool Browser::OnProcessSingletonNotification( - const base::CommandLine& command_line, - const base::FilePath& current_directory) { - if (process_notify_callback_set_) { - return process_notify_callback_.Run(command_line, current_directory); - } else { - return true; // We'll handle this, not a different process - } -} - } // namespace atom diff --git a/atom/browser/browser.h b/atom/browser/browser.h index f9b86b6924a0..3c5abd2f0405 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -9,10 +9,8 @@ #include #include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" #include "base/compiler_specific.h" #include "base/observer_list.h" -#include "atom/browser/atom_process_singleton.h" #include "atom/browser/browser_observer.h" #include "atom/browser/window_list_observer.h" @@ -66,11 +64,6 @@ class Browser : public WindowListObserver { // Clear the recent documents list. void ClearRecentDocuments(); - bool InitializeSingleInstance(); - ProcessSingleton::NotifyResult GetSingleInstanceResult(); - void SetSingleInstanceCallback( - ProcessSingleton::NotificationCallback callback); - #if defined(OS_MACOSX) // Bounce the dock icon. enum BounceType { @@ -160,10 +153,6 @@ class Browser : public WindowListObserver { void OnWindowCloseCancelled(NativeWindow* window) override; void OnWindowAllClosed() override; - bool OnProcessSingletonNotification( - const base::CommandLine& command_line, - const base::FilePath& current_directory); - // Observers of the browser. base::ObserverList observers_; @@ -176,11 +165,6 @@ class Browser : public WindowListObserver { std::string version_override_; std::string name_override_; - scoped_ptr process_singleton_; - ProcessSingleton::NotifyResult process_notify_result_; - ProcessSingleton::NotificationCallback process_notify_callback_; - bool process_notify_callback_set_; - #if defined(OS_WIN) base::string16 app_user_model_id_; #endif From d020a7dc86f7c628ea3a78fe2c0719c4b72bb48e Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 21 Oct 2015 13:17:56 -0700 Subject: [PATCH 287/738] cpplinting --- atom/browser/api/atom_api_app.cc | 11 +++++------ atom/browser/api/atom_api_app.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 97d5cf6aa2df..6906608fb76f 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -161,12 +161,12 @@ void App::OnWindowAllClosed() { void App::OnQuit() { Emit("quit"); - + if (process_singleton_.get()) { if (process_notify_result_ == ProcessSingleton::PROCESS_NONE) { process_singleton_->Cleanup(); } - + process_singleton_.reset(); } } @@ -195,7 +195,7 @@ void App::OnFinishLaunching() { AtomBrowserMainParts::Get()->browser_context()); auto handle = Session::CreateFrom(isolate(), browser_context); default_session_.Reset(isolate(), handle.ToV8()); - + if (process_singleton_.get()) { process_singleton_->Unlock(); } @@ -282,14 +282,13 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { } bool App::MakeSingleInstance(ProcessSingleton::NotificationCallback callback) { - base::FilePath userDir; PathService::Get(brightray::DIR_USER_DATA, &userDir); - + if (!process_singleton_.get()) { auto browser = Browser::Get(); process_singleton_.reset(new AtomProcessSingleton(userDir, callback)); - + if (browser->is_ready()) { process_singleton_->Unlock(); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 82ae04502030..77944d3441ea 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -77,7 +77,7 @@ class App : public mate::EventEmitter, v8::Local DefaultSession(v8::Isolate* isolate); v8::Global default_session_; - + scoped_ptr process_singleton_; ProcessSingleton::NotifyResult process_notify_result_; From de668880518525fd2430f00278516681a7b746fa Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 21 Oct 2015 13:38:32 -0700 Subject: [PATCH 288/738] Remove atom_process_singleton, just use the Chrome classes directly --- atom/browser/api/atom_api_app.cc | 12 ++++-- atom/browser/api/atom_api_app.h | 5 ++- atom/browser/atom_process_singleton.cc | 29 -------------- atom/browser/atom_process_singleton.h | 52 -------------------------- filenames.gypi | 1 - 5 files changed, 12 insertions(+), 87 deletions(-) delete mode 100644 atom/browser/atom_process_singleton.cc delete mode 100644 atom/browser/atom_process_singleton.h diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 6906608fb76f..c46f0748e3b6 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -197,7 +197,7 @@ void App::OnFinishLaunching() { default_session_.Reset(isolate(), handle.ToV8()); if (process_singleton_.get()) { - process_singleton_->Unlock(); + process_singleton_startup_lock_->Unlock(); } Emit("ready"); @@ -287,10 +287,16 @@ bool App::MakeSingleInstance(ProcessSingleton::NotificationCallback callback) { if (!process_singleton_.get()) { auto browser = Browser::Get(); - process_singleton_.reset(new AtomProcessSingleton(userDir, callback)); + process_singleton_startup_lock_.reset( + new ProcessSingletonStartupLock(callback)); + + process_singleton_.reset( + new ProcessSingleton( + userDir, + process_singleton_startup_lock_->AsNotificationCallback())); if (browser->is_ready()) { - process_singleton_->Unlock(); + process_singleton_startup_lock_->Unlock(); } process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 77944d3441ea..314eeea8811d 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -8,10 +8,10 @@ #include #include "atom/browser/api/event_emitter.h" -#include "atom/browser/atom_process_singleton.h" #include "atom/browser/browser_observer.h" #include "atom/common/native_mate_converters/callback.h" #include "chrome/browser/process_singleton.h" +#include "chrome/browser/process_singleton_startup_lock.h" #include "content/public/browser/gpu_data_manager_observer.h" #include "native_mate/handle.h" @@ -78,7 +78,8 @@ class App : public mate::EventEmitter, v8::Global default_session_; - scoped_ptr process_singleton_; + scoped_ptr process_singleton_; + scoped_ptr process_singleton_startup_lock_; ProcessSingleton::NotifyResult process_notify_result_; DISALLOW_COPY_AND_ASSIGN(App); diff --git a/atom/browser/atom_process_singleton.cc b/atom/browser/atom_process_singleton.cc deleted file mode 100644 index e9e4dc727bf7..000000000000 --- a/atom/browser/atom_process_singleton.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "atom/browser/atom_process_singleton.h" - -AtomProcessSingleton::AtomProcessSingleton( - const base::FilePath& user_data_dir, - const ProcessSingleton::NotificationCallback& notification_callback) - : startup_lock_(notification_callback), - process_singleton_(user_data_dir, - startup_lock_.AsNotificationCallback()) { -} - -AtomProcessSingleton::~AtomProcessSingleton() { -} - -ProcessSingleton::NotifyResult - AtomProcessSingleton::NotifyOtherProcessOrCreate() { - return process_singleton_.NotifyOtherProcessOrCreate(); -} - -void AtomProcessSingleton::Cleanup() { - process_singleton_.Cleanup(); -} - -void AtomProcessSingleton::Unlock() { - startup_lock_.Unlock(); -} diff --git a/atom/browser/atom_process_singleton.h b/atom/browser/atom_process_singleton.h deleted file mode 100644 index 89feeaecb37c..000000000000 --- a/atom/browser/atom_process_singleton.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_ATOM_PROCESS_SINGLETON_H_ -#define ATOM_BROWSER_ATOM_PROCESS_SINGLETON_H_ - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "chrome/browser/process_singleton.h" -#include "chrome/browser/process_singleton_startup_lock.h" - -// Composes a basic ProcessSingleton with ProcessSingletonStartupLock -class AtomProcessSingleton { - public: - AtomProcessSingleton( - const base::FilePath& user_data_dir, - const ProcessSingleton::NotificationCallback& notification_callback); - - ~AtomProcessSingleton(); - - // Notify another process, if available. Otherwise sets ourselves as the - // singleton instance. Returns PROCESS_NONE if we became the singleton - // instance. Callers are guaranteed to either have notified an existing - // process or have grabbed the singleton (unless the profile is locked by an - // unreachable process). - ProcessSingleton::NotifyResult NotifyOtherProcessOrCreate(); - - // Clear any lock state during shutdown. - void Cleanup(); - - // Executes previously queued command-line invocations and allows future - // invocations to be executed immediately. - // This only has an effect the first time it is called. - void Unlock(); - - private: - // We compose these two locks with the client-supplied notification callback. - // First |modal_dialog_lock_| will discard any notifications that arrive while - // a modal dialog is active. Otherwise, it will pass the notification to - // |startup_lock_|, which will queue notifications until |Unlock()| is called. - // Notifications passing through both locks are finally delivered to our - // client. - ProcessSingletonStartupLock startup_lock_; - - // The basic ProcessSingleton - ProcessSingleton process_singleton_; - - DISALLOW_COPY_AND_ASSIGN(AtomProcessSingleton); -}; - -#endif // ATOM_BROWSER_ATOM_PROCESS_SINGLETON_H_ diff --git a/filenames.gypi b/filenames.gypi index 3f3d1019c243..ec7ab3291b3f 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -130,7 +130,6 @@ 'atom/browser/atom_browser_main_parts_posix.cc', 'atom/browser/atom_javascript_dialog_manager.cc', 'atom/browser/atom_javascript_dialog_manager.h', - 'atom/browser/atom_process_singleton.cc', 'atom/browser/atom_quota_permission_context.cc', 'atom/browser/atom_quota_permission_context.h', 'atom/browser/atom_resource_dispatcher_host_delegate.cc', From 759b6a15341d1eedefe67882e9d24251696da02c Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 21 Oct 2015 13:52:17 -0700 Subject: [PATCH 289/738] :memo: for makeSingleInstance --- docs/api/app.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/docs/api/app.md b/docs/api/app.md index 41098d4279c9..9c9afdee763a 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -290,6 +290,51 @@ 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. +### `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` is called when a second instance has been executed, and provides +the command-line (including Chromium flags) and the working directory of the +secondary instance. Usually applications respond to this by making their +primary window focused and non-minimized. + +`callback` should return `true` if the message was successfully handled, or +`false` if the secondary process should retry sending it or it failed. + +```js +app.on('ready', function() { + var myWindow; + + var shouldQuit = app.makeSingleInstance(function(command_line, working_directory) { + // Someone tried to run a second instance, we should focus our window + if (myWindow) { + if (myWindow.isMinimized()) myWindow.restore(); + myWindow.focus(); + } + + // We successfully handled the command line + return true; + }); + + if (shouldQuit) { + app.quit(); + return; + } + + // Create myWindow, load the rest of the app, etc... +}); +``` + +Returns a Boolean - if `false`, your process is the primary instance of the +application and your app should continue loading. If `true`, your process has +sent its parameters to another instance, and you should immediately quit. + ### `app.commandLine.appendSwitch(switch[, value])` Append a switch (with optional `value`) to Chromium's command line. From bac3d2e372b68a252c89adad91cac64b9801a9e4 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Wed, 21 Oct 2015 17:07:36 -0700 Subject: [PATCH 290/738] Update crash-reporter.md --- docs/api/crash-reporter.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/api/crash-reporter.md b/docs/api/crash-reporter.md index 86670fcc90c9..64a3b2cf748d 100644 --- a/docs/api/crash-reporter.md +++ b/docs/api/crash-reporter.md @@ -59,11 +59,10 @@ ID. The crash reporter will send the following data to the `submitUrl` as `POST`: -* `rept` String - e.g. 'electron-crash-service'. * `ver` String - The version of Electron. * `platform` String - e.g. 'win32'. * `process_type` String - e.g. 'renderer'. -* `ptime` Number +* `guid` String - e.g. '5e1286fc-da97-479e-918b-6bfb0c3d1c72' * `_version` String - The version in `package.json`. * `_productName` String - The product name in the `crashReporter` `options` object. From 9411508d3e435fccc082fee4a5c0d18b79e39686 Mon Sep 17 00:00:00 2001 From: Robo Date: Wed, 21 Oct 2015 15:47:28 +0530 Subject: [PATCH 291/738] browser: option to set window background color --- atom/browser/native_window_views.cc | 31 ++++++++++++++++++++++++++++- atom/common/options_switches.cc | 3 +++ atom/common/options_switches.h | 1 + docs/api/browser-window.md | 7 +++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index e3688235bd4e..1e4207bf0c6f 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -77,6 +77,29 @@ bool IsAltModifier(const content::NativeWebKeyboardEvent& event) { (modifiers == (Modifiers::AltKey | Modifiers::IsRight)); } +SkColor ParseHexColor(const std::string& name) { + SkColor result = 0xFF000000; + unsigned value = 0; + auto color = name.substr(1); + unsigned length = color.size(); + if (length != 3 && length != 6) + return result; + for (unsigned i = 0; i < length; ++i) { + if (!base::IsHexDigit(color[i])) + return result; + value <<= 4; + value |= (color[i] < 'A' ? color[i] - '0' : (color[i] - 'A' + 10) & 0xF); + } + if (length == 6) { + result |= value; + return result; + } + result |= (value & 0xF00) << 12 | (value & 0xF00) << 8 + | (value & 0xF0) << 8 | (value & 0xF0) << 4 + | (value & 0xF) << 4 | (value & 0xF); + return result; +} + class NativeWindowClientView : public views::ClientView { public: NativeWindowClientView(views::Widget* widget, @@ -205,7 +228,13 @@ NativeWindowViews::NativeWindowViews( // Add web view. SetLayoutManager(new MenuLayout(this, kMenuBarHeight)); - set_background(views::Background::CreateStandardPanelBackground()); + + // web views' background color. + std::string background_color = "#fff"; + options.Get(switches::kBackgroundColor, &background_color); + set_background(views::Background::CreateSolidBackground( + ParseHexColor(background_color))); + AddChildView(web_view_); #if defined(OS_WIN) diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 8ea16f27b4f8..903c15ee6dd1 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -93,6 +93,9 @@ const char kDisableAutoHideCursor[] = "disable-auto-hide-cursor"; // Use the OS X's standard window instead of the textured window. const char kStandardWindow[] = "standard-window"; +// Default browser window background color. +const char kBackgroundColor[] = "background-color"; + // Path to client certificate. const char kClientCertificate[] = "client-certificate"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 33c2790cc152..9887359a502b 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -47,6 +47,7 @@ extern const char kTransparent[]; extern const char kType[]; extern const char kDisableAutoHideCursor[]; extern const char kStandardWindow[]; +extern const char kBackgroundColor[]; extern const char kClientCertificate[]; extern const char kExperimentalFeatures[]; diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index fd25f8cdc982..c59fbbdbcb47 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -61,6 +61,13 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. key is pressed. * `enable-larger-than-screen` Boolean - Enable the window to be resized larger than screen. +* `background-color` String - Window's background color as Hexadecimal value. +```javascript +var win = new BrowserWindow({ width: 800, height: 600, 'background-color': '#66CD00' }) + +// #abc will be expanded to #aabbcc +var win = new BrowserWindow({ width: 800, height: 600, 'background-color': '#fff' }) +``` * `dark-theme` Boolean - Forces using dark theme for the window, only works on some GTK+3 desktop environments. * `transparent` Boolean - Makes the window [transparent](frameless-window.md). From f7840e7379783973b99542b4d8e8b505f8b327e4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 14:16:17 +0800 Subject: [PATCH 292/738] docs: background-color is Linux-only for now --- docs/api/browser-window.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index c59fbbdbcb47..165ce70a977e 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -61,13 +61,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. key is pressed. * `enable-larger-than-screen` Boolean - Enable the window to be resized larger than screen. -* `background-color` String - Window's background color as Hexadecimal value. -```javascript -var win = new BrowserWindow({ width: 800, height: 600, 'background-color': '#66CD00' }) - -// #abc will be expanded to #aabbcc -var win = new BrowserWindow({ width: 800, height: 600, 'background-color': '#fff' }) -``` +* `background-color` String - Window's background color as Hexadecimal value, + like `#66CD00` or `#FFF`. This is only implemented on Linux. * `dark-theme` Boolean - Forces using dark theme for the window, only works on some GTK+3 desktop environments. * `transparent` Boolean - Makes the window [transparent](frameless-window.md). From 63cc2ec3691324df91ae3814bae21327baf16ffd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 14:24:09 +0800 Subject: [PATCH 293/738] docs: Make code more JS-style --- docs/api/app.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/api/app.md b/docs/api/app.md index 9c9afdee763a..95aa80b6dc83 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -245,7 +245,7 @@ Returns the current application locale. Resolves the proxy information for `url`. The `callback` will be called with `callback(proxy)` when the request is performed. -### `app.addRecentDocument(path)` +### `app.addRecentDocument(path)` _OS X_ _Windows_ * `path` String @@ -254,7 +254,7 @@ Adds `path` to the recent documents list. This list is managed by the OS. On Windows you can visit the list from the task bar, and on OS X you can visit it from dock menu. -### `app.clearRecentDocuments()` +### `app.clearRecentDocuments()` _OS X_ _Windows_ Clears the recent documents list. @@ -308,10 +308,9 @@ primary window focused and non-minimized. `false` if the secondary process should retry sending it or it failed. ```js +var myWindow; app.on('ready', function() { - var myWindow; - - var shouldQuit = app.makeSingleInstance(function(command_line, working_directory) { + 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(); From acb2c099f6dde04bffa8e3c2cf422409abee8987 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 14:56:57 +0800 Subject: [PATCH 294/738] Make sure current task runner is available When calling makeSingleInstance we have to ensure current task runnder is available, otherwise crash may happen. --- atom/browser/atom_browser_main_parts.cc | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 4c11176997ca..dfbdf4477fba 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -62,17 +62,15 @@ void AtomBrowserMainParts::PreEarlyInitialization() { void AtomBrowserMainParts::PostEarlyInitialization() { brightray::BrowserMainParts::PostEarlyInitialization(); - { - // Temporary set the bridge_task_runner_ as current thread's task runner, - // so we can fool gin::PerIsolateData to use it as its task runner, instead - // of getting current message loop's task runner, which is null for now. - bridge_task_runner_ = new BridgeTaskRunner; - base::ThreadTaskRunnerHandle handle(bridge_task_runner_); + // Temporary set the bridge_task_runner_ as current thread's task runner, + // so we can fool gin::PerIsolateData to use it as its task runner, instead + // of getting current message loop's task runner, which is null for now. + bridge_task_runner_ = new BridgeTaskRunner; + base::ThreadTaskRunnerHandle handle(bridge_task_runner_); - // The ProxyResolverV8 has setup a complete V8 environment, in order to - // avoid conflicts we only initialize our V8 environment after that. - js_env_.reset(new JavascriptEnvironment); - } + // The ProxyResolverV8 has setup a complete V8 environment, in order to + // avoid conflicts we only initialize our V8 environment after that. + js_env_.reset(new JavascriptEnvironment); node_bindings_->Initialize(); From 310954713f96245549f4f9cfc28c01ade72fde15 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 14:59:12 +0800 Subject: [PATCH 295/738] Simplify the usage of singleton --- atom/browser/api/atom_api_app.cc | 38 ++++++++----------- atom/browser/api/atom_api_app.h | 1 - .../chrome/browser/process_singleton_posix.cc | 2 +- .../browser/process_singleton_startup_lock.cc | 2 +- .../browser/process_singleton_startup_lock.h | 2 +- 5 files changed, 18 insertions(+), 27 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index c46f0748e3b6..2dfc3e056da5 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -163,10 +163,7 @@ void App::OnQuit() { Emit("quit"); if (process_singleton_.get()) { - if (process_notify_result_ == ProcessSingleton::PROCESS_NONE) { - process_singleton_->Cleanup(); - } - + process_singleton_->Cleanup(); process_singleton_.reset(); } } @@ -196,9 +193,8 @@ void App::OnFinishLaunching() { auto handle = Session::CreateFrom(isolate(), browser_context); default_session_.Reset(isolate(), handle.ToV8()); - if (process_singleton_.get()) { + if (process_singleton_startup_lock_.get()) process_singleton_startup_lock_->Unlock(); - } Emit("ready"); } @@ -282,35 +278,31 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { } bool App::MakeSingleInstance(ProcessSingleton::NotificationCallback callback) { - base::FilePath userDir; - PathService::Get(brightray::DIR_USER_DATA, &userDir); + if (process_singleton_.get()) + return false; - if (!process_singleton_.get()) { - auto browser = Browser::Get(); - process_singleton_startup_lock_.reset( + base::FilePath user_dir; + PathService::Get(brightray::DIR_USER_DATA, &user_dir); + + process_singleton_startup_lock_.reset( new ProcessSingletonStartupLock(callback)); - - process_singleton_.reset( + process_singleton_.reset( new ProcessSingleton( - userDir, + user_dir, process_singleton_startup_lock_->AsNotificationCallback())); - if (browser->is_ready()) { - process_singleton_startup_lock_->Unlock(); - } + if (Browser::Get()->is_ready()) + process_singleton_startup_lock_->Unlock(); - process_notify_result_ = process_singleton_->NotifyOtherProcessOrCreate(); - } - - switch (process_notify_result_) { + switch (process_singleton_->NotifyOtherProcessOrCreate()) { case ProcessSingleton::NotifyResult::PROCESS_NONE: return false; case ProcessSingleton::NotifyResult::LOCK_ERROR: case ProcessSingleton::NotifyResult::PROFILE_IN_USE: case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: + process_singleton_.reset(); + process_singleton_startup_lock_.reset(); return true; - default: - return false; } } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 314eeea8811d..8d55fc27c3b2 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -80,7 +80,6 @@ class App : public mate::EventEmitter, scoped_ptr process_singleton_; scoped_ptr process_singleton_startup_lock_; - ProcessSingleton::NotifyResult process_notify_result_; DISALLOW_COPY_AND_ASSIGN(App); }; diff --git a/chromium_src/chrome/browser/process_singleton_posix.cc b/chromium_src/chrome/browser/process_singleton_posix.cc index 5ab6eb6d8a78..4117dff8863e 100644 --- a/chromium_src/chrome/browser/process_singleton_posix.cc +++ b/chromium_src/chrome/browser/process_singleton_posix.cc @@ -1046,4 +1046,4 @@ void ProcessSingleton::KillProcess(int pid) { // progress of shutting down and finishes before we try to kill it). DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " << base::safe_strerror(errno); -} \ No newline at end of file +} diff --git a/chromium_src/chrome/browser/process_singleton_startup_lock.cc b/chromium_src/chrome/browser/process_singleton_startup_lock.cc index b97ada658c35..f564de7dca4d 100644 --- a/chromium_src/chrome/browser/process_singleton_startup_lock.cc +++ b/chromium_src/chrome/browser/process_singleton_startup_lock.cc @@ -50,4 +50,4 @@ bool ProcessSingletonStartupLock::NotificationCallbackImpl( } else { return original_callback_.Run(command_line, current_directory); } -} \ No newline at end of file +} diff --git a/chromium_src/chrome/browser/process_singleton_startup_lock.h b/chromium_src/chrome/browser/process_singleton_startup_lock.h index 3df51d8b177b..187dd35bce3d 100644 --- a/chromium_src/chrome/browser/process_singleton_startup_lock.h +++ b/chromium_src/chrome/browser/process_singleton_startup_lock.h @@ -54,4 +54,4 @@ class ProcessSingletonStartupLock : public base::NonThreadSafe { DISALLOW_COPY_AND_ASSIGN(ProcessSingletonStartupLock); }; -#endif // CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ \ No newline at end of file +#endif // CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ From bcb78ebc00e9f04299fd26955b3aa0e97c20a2e4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 15:02:32 +0800 Subject: [PATCH 296/738] app.makeSingleInstance is not available on OS X --- atom/browser/api/atom_api_app.cc | 4 ++++ docs/api/app.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 2dfc3e056da5..5ce918be78ad 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -278,6 +278,10 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { } bool App::MakeSingleInstance(ProcessSingleton::NotificationCallback callback) { +#if defined(OS_MACOSX) + LOG(ERROR) << "MakeSingleInstance is not implemnted on OS X"; + return false; +#endif if (process_singleton_.get()) return false; diff --git a/docs/api/app.md b/docs/api/app.md index 95aa80b6dc83..bd017456a78c 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -290,7 +290,7 @@ 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. -### `app.makeSingleInstance(callback)` +### `app.makeSingleInstance(callback)` _Windows_ _Linux_ * `callback` Function From 05c63003294ccd8ef8b8b25524e713b1a0de9752 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 15:54:27 +0800 Subject: [PATCH 297/738] Don't discard tasks in BridgeTaskRunner --- atom/browser/atom_browser_main_parts.cc | 1 + atom/browser/bridge_task_runner.cc | 32 +++++++++++++++++++++---- atom/browser/bridge_task_runner.h | 13 +++++++++- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index dfbdf4477fba..5fae5bfdbedd 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -105,6 +105,7 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() { 1000)); brightray::BrowserMainParts::PreMainMessageLoopRun(); + BridgeTaskRunner::MessageLoopIsReady(); #if defined(USE_X11) libgtk2ui::GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess()); diff --git a/atom/browser/bridge_task_runner.cc b/atom/browser/bridge_task_runner.cc index 24572f3990d8..882a3050de48 100644 --- a/atom/browser/bridge_task_runner.cc +++ b/atom/browser/bridge_task_runner.cc @@ -8,13 +8,33 @@ namespace atom { +// static +std::vector BridgeTaskRunner::tasks_; +std::vector BridgeTaskRunner::non_nestable_tasks_; + +// static +void BridgeTaskRunner::MessageLoopIsReady() { + auto message_loop = base::MessageLoop::current(); + CHECK(message_loop); + for (const TaskPair& task : tasks_) { + message_loop->task_runner()->PostDelayedTask( + base::get<0>(task), base::get<1>(task), base::get<2>(task)); + } + for (const TaskPair& task : non_nestable_tasks_) { + message_loop->task_runner()->PostNonNestableDelayedTask( + base::get<0>(task), base::get<1>(task), base::get<2>(task)); + } +} + bool BridgeTaskRunner::PostDelayedTask( const tracked_objects::Location& from_here, const base::Closure& task, base::TimeDelta delay) { auto message_loop = base::MessageLoop::current(); - if (!message_loop) - return false; + if (!message_loop) { + tasks_.push_back(base::MakeTuple(from_here, task, delay)); + return true; + } return message_loop->task_runner()->PostDelayedTask(from_here, task, delay); } @@ -22,7 +42,7 @@ bool BridgeTaskRunner::PostDelayedTask( bool BridgeTaskRunner::RunsTasksOnCurrentThread() const { auto message_loop = base::MessageLoop::current(); if (!message_loop) - return false; + return true; return message_loop->task_runner()->RunsTasksOnCurrentThread(); } @@ -32,8 +52,10 @@ bool BridgeTaskRunner::PostNonNestableDelayedTask( const base::Closure& task, base::TimeDelta delay) { auto message_loop = base::MessageLoop::current(); - if (!message_loop) - return false; + if (!message_loop) { + non_nestable_tasks_.push_back(base::MakeTuple(from_here, task, delay)); + return true; + } return message_loop->task_runner()->PostNonNestableDelayedTask( from_here, task, delay); diff --git a/atom/browser/bridge_task_runner.h b/atom/browser/bridge_task_runner.h index fb42aa3852f9..12508f009d17 100644 --- a/atom/browser/bridge_task_runner.h +++ b/atom/browser/bridge_task_runner.h @@ -5,17 +5,23 @@ #ifndef ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_ #define ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_ +#include + #include "base/single_thread_task_runner.h" +#include "base/tuple.h" namespace atom { // Post all tasks to the current message loop's task runner if available, -// otherwise fail silently. +// otherwise delay the work until message loop is ready. class BridgeTaskRunner : public base::SingleThreadTaskRunner { public: BridgeTaskRunner() {} ~BridgeTaskRunner() override {} + // Called when message loop is ready. + static void MessageLoopIsReady(); + // base::SingleThreadTaskRunner: bool PostDelayedTask(const tracked_objects::Location& from_here, const base::Closure& task, @@ -27,6 +33,11 @@ class BridgeTaskRunner : public base::SingleThreadTaskRunner { base::TimeDelta delay) override; private: + using TaskPair = base::Tuple< + tracked_objects::Location, base::Closure, base::TimeDelta>; + static std::vector tasks_; + static std::vector non_nestable_tasks_; + DISALLOW_COPY_AND_ASSIGN(BridgeTaskRunner); }; From f01e84a4182eb2ce7aa86fb987b14b30cdfdabae Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 15:54:58 +0800 Subject: [PATCH 298/738] linux: Delay listening to socket until message loop is ready --- .../chrome/browser/process_singleton.h | 3 +++ .../chrome/browser/process_singleton_posix.cc | 27 +++++++++++++------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/chromium_src/chrome/browser/process_singleton.h b/chromium_src/chrome/browser/process_singleton.h index 3265c9597a77..05288dc37cfe 100644 --- a/chromium_src/chrome/browser/process_singleton.h +++ b/chromium_src/chrome/browser/process_singleton.h @@ -133,6 +133,9 @@ class ProcessSingleton : public base::NonThreadSafe { base::FilePath user_data_dir_; ShouldKillRemoteProcessCallback should_kill_remote_process_callback_; #elif defined(OS_POSIX) && !defined(OS_ANDROID) + // Start listening to the socket. + void StartListening(int sock); + // Return true if the given pid is one of our child processes. // Assumes that the current pid is the root of all pids of the current // instance. diff --git a/chromium_src/chrome/browser/process_singleton_posix.cc b/chromium_src/chrome/browser/process_singleton_posix.cc index 4117dff8863e..5a8aac90793e 100644 --- a/chromium_src/chrome/browser/process_singleton_posix.cc +++ b/chromium_src/chrome/browser/process_singleton_posix.cc @@ -316,8 +316,7 @@ bool IsChromeProcess(pid_t pid) { PathService::Get(base::FILE_EXE, &exec_path); return (!other_chrome_path.empty() && - other_chrome_path.BaseName() == - exec_path.BaseName()); + other_chrome_path.BaseName() == exec_path.BaseName()); } // A helper class to hold onto a socket. @@ -988,13 +987,15 @@ bool ProcessSingleton::Create() { if (listen(sock, 5) < 0) NOTREACHED() << "listen failed: " << base::safe_strerror(errno); - DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO)); - BrowserThread::PostTask( - BrowserThread::IO, + // In Electron the ProcessSingleton is created earlier than the IO + // thread gets created, so we have to postpone the call until message + // loop is up an running. + scoped_refptr task_runner( + base::ThreadTaskRunnerHandle::Get()); + task_runner->PostTask( FROM_HERE, - base::Bind(&ProcessSingleton::LinuxWatcher::StartListening, - watcher_.get(), - sock)); + base::Bind(&ProcessSingleton::StartListening, + base::Unretained(this), sock)); return true; } @@ -1005,6 +1006,16 @@ void ProcessSingleton::Cleanup() { UnlinkPath(lock_path_); } +void ProcessSingleton::StartListening(int sock) { + DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO)); + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&ProcessSingleton::LinuxWatcher::StartListening, + watcher_.get(), + sock)); +} + bool ProcessSingleton::IsSameChromeInstance(pid_t pid) { pid_t cur_pid = current_pid_; while (pid != cur_pid) { From 230f2760e7c9136f94b2893d94b90339a7e0208c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 15:57:37 +0800 Subject: [PATCH 299/738] linux: Delay creating watcher until message loop is ready --- chromium_src/chrome/browser/process_singleton_posix.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chromium_src/chrome/browser/process_singleton_posix.cc b/chromium_src/chrome/browser/process_singleton_posix.cc index 5a8aac90793e..811c5c16a24e 100644 --- a/chromium_src/chrome/browser/process_singleton_posix.cc +++ b/chromium_src/chrome/browser/process_singleton_posix.cc @@ -715,8 +715,7 @@ ProcessSingleton::ProcessSingleton( const base::FilePath& user_data_dir, const NotificationCallback& notification_callback) : notification_callback_(notification_callback), - current_pid_(base::GetCurrentProcId()), - watcher_(new LinuxWatcher(this)) { + current_pid_(base::GetCurrentProcId()) { socket_path_ = user_data_dir.Append(kSingletonSocketFilename); lock_path_ = user_data_dir.Append(kSingletonLockFilename); cookie_path_ = user_data_dir.Append(kSingletonCookieFilename); @@ -1007,6 +1006,7 @@ void ProcessSingleton::Cleanup() { } void ProcessSingleton::StartListening(int sock) { + watcher_ = new LinuxWatcher(this); DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO)); BrowserThread::PostTask( BrowserThread::IO, From ca876e424bd71de5fe09d6efb56e79482cfffed9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 16:06:37 +0800 Subject: [PATCH 300/738] Fix crash when calling app.quit() before app is ready --- atom/browser/browser.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index d8bb94103cd9..79ebe91a87e6 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -53,8 +53,14 @@ void Browser::Shutdown() { is_quiting_ = true; FOR_EACH_OBSERVER(BrowserObserver, observers_, OnQuit()); - base::MessageLoop::current()->PostTask( - FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); + + if (base::MessageLoop::current()) { + base::MessageLoop::current()->PostTask( + FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); + } else { + // There is no message loop available so we are in early stage. + exit(0); + } } std::string Browser::GetVersion() const { From e14fd62f4626bb016f3bf2f2e48ec7d892924304 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 16:24:35 +0800 Subject: [PATCH 301/738] Correctly handle notification callback when shutting down When returning false in the notification callback the ProcessSingleton will assume current process is quitting, we should met its expectation. --- atom/browser/api/atom_api_app.cc | 15 +++++++++++++-- atom/browser/api/atom_api_app.h | 6 ++---- atom/browser/browser.h | 1 + 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 5ce918be78ad..fa2a97de4d90 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -112,6 +112,15 @@ int GetPathConstant(const std::string& name) { return -1; } +// Run the NotificationCallback and returns whether browser is shuting down. +bool NotificationCallbackWrapper( + const ProcessSingleton::NotificationCallback& callback, + const base::CommandLine& command_line, + const base::FilePath& current_directory) { + callback.Run(command_line, current_directory); + return !Browser::Get()->is_shutting_down(); +} + void OnClientCertificateSelected( v8::Isolate* isolate, std::shared_ptr delegate, @@ -277,7 +286,8 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { return v8::Local::New(isolate, default_session_); } -bool App::MakeSingleInstance(ProcessSingleton::NotificationCallback callback) { +bool App::MakeSingleInstance( + const ProcessSingleton::NotificationCallback& callback) { #if defined(OS_MACOSX) LOG(ERROR) << "MakeSingleInstance is not implemnted on OS X"; return false; @@ -289,7 +299,8 @@ bool App::MakeSingleInstance(ProcessSingleton::NotificationCallback callback) { PathService::Get(brightray::DIR_USER_DATA, &user_dir); process_singleton_startup_lock_.reset( - new ProcessSingletonStartupLock(callback)); + new ProcessSingletonStartupLock( + base::Bind(NotificationCallbackWrapper, callback))); process_singleton_.reset( new ProcessSingleton( user_dir, diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 8d55fc27c3b2..bd87b3885035 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -68,11 +68,9 @@ class App : public mate::EventEmitter, void SetDesktopName(const std::string& desktop_name); void SetAppUserModelId(const std::string& app_id); - void AllowNTLMCredentialsForAllDomains(bool should_allow); - - bool MakeSingleInstance(ProcessSingleton::NotificationCallback callback); - + bool MakeSingleInstance( + const ProcessSingleton::NotificationCallback& callback); std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 3c5abd2f0405..bae281d4d370 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -130,6 +130,7 @@ class Browser : public WindowListObserver { observers_.RemoveObserver(obs); } + bool is_shutting_down() const { return is_shutdown_; } bool is_quiting() const { return is_quiting_; } bool is_ready() const { return is_ready_; } From f9d797d1ea00e9239a7b1c74bae3861cefb8e023 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 16:55:54 +0800 Subject: [PATCH 302/738] win: Fix compiler warning --- atom/browser/api/atom_api_app.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index fa2a97de4d90..a9011c6e2e75 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -310,14 +310,15 @@ bool App::MakeSingleInstance( process_singleton_startup_lock_->Unlock(); switch (process_singleton_->NotifyOtherProcessOrCreate()) { - case ProcessSingleton::NotifyResult::PROCESS_NONE: - return false; case ProcessSingleton::NotifyResult::LOCK_ERROR: case ProcessSingleton::NotifyResult::PROFILE_IN_USE: case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: process_singleton_.reset(); process_singleton_startup_lock_.reset(); return true; + case ProcessSingleton::NotifyResult::PROCESS_NONE: + default: // Shouldn't be needed, but VS warns if it is not there. + return false; } } From 70e74d05e0b4cca5824b1d69b705207025c251b7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 17:03:18 +0800 Subject: [PATCH 303/738] Revert "app.makeSingleInstance is not available on OS X" This reverts commit bcb78ebc00e9f04299fd26955b3aa0e97c20a2e4. --- atom/browser/api/atom_api_app.cc | 4 ---- docs/api/app.md | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index a9011c6e2e75..42feaf8dc4ec 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -288,10 +288,6 @@ v8::Local App::DefaultSession(v8::Isolate* isolate) { bool App::MakeSingleInstance( const ProcessSingleton::NotificationCallback& callback) { -#if defined(OS_MACOSX) - LOG(ERROR) << "MakeSingleInstance is not implemnted on OS X"; - return false; -#endif if (process_singleton_.get()) return false; diff --git a/docs/api/app.md b/docs/api/app.md index bd017456a78c..95aa80b6dc83 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -290,7 +290,7 @@ 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. -### `app.makeSingleInstance(callback)` _Windows_ _Linux_ +### `app.makeSingleInstance(callback)` * `callback` Function From afc1fff7920da5c7dc5c7ea526b5705309128b7a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 17:12:09 +0800 Subject: [PATCH 304/738] Remove the need for ProcessSingletonStartupLock --- atom/browser/api/atom_api_app.cc | 33 +++++------ atom/browser/api/atom_api_app.h | 2 - .../browser/process_singleton_startup_lock.cc | 53 ----------------- .../browser/process_singleton_startup_lock.h | 57 ------------------- filenames.gypi | 3 +- 5 files changed, 16 insertions(+), 132 deletions(-) delete mode 100644 chromium_src/chrome/browser/process_singleton_startup_lock.cc delete mode 100644 chromium_src/chrome/browser/process_singleton_startup_lock.h diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 42feaf8dc4ec..84b9301316f6 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -112,12 +112,20 @@ int GetPathConstant(const std::string& name) { return -1; } -// Run the NotificationCallback and returns whether browser is shuting down. bool NotificationCallbackWrapper( const ProcessSingleton::NotificationCallback& callback, - const base::CommandLine& command_line, - const base::FilePath& current_directory) { - callback.Run(command_line, current_directory); + const base::CommandLine& cmd, + const base::FilePath& cwd) { + // Make sure the callback is called after app gets ready. + if (Browser::Get()->is_ready()) { + callback.Run(cmd, cwd); + } else { + scoped_refptr task_runner( + base::ThreadTaskRunnerHandle::Get()); + task_runner->PostTask( + FROM_HERE, base::Bind(base::IgnoreResult(callback), cmd, cwd)); + } + // ProcessSingleton needs to know whether current process is quiting. return !Browser::Get()->is_shutting_down(); } @@ -202,9 +210,6 @@ void App::OnFinishLaunching() { auto handle = Session::CreateFrom(isolate(), browser_context); default_session_.Reset(isolate(), handle.ToV8()); - if (process_singleton_startup_lock_.get()) - process_singleton_startup_lock_->Unlock(); - Emit("ready"); } @@ -293,24 +298,14 @@ bool App::MakeSingleInstance( base::FilePath user_dir; PathService::Get(brightray::DIR_USER_DATA, &user_dir); - - process_singleton_startup_lock_.reset( - new ProcessSingletonStartupLock( - base::Bind(NotificationCallbackWrapper, callback))); - process_singleton_.reset( - new ProcessSingleton( - user_dir, - process_singleton_startup_lock_->AsNotificationCallback())); - - if (Browser::Get()->is_ready()) - process_singleton_startup_lock_->Unlock(); + process_singleton_.reset(new ProcessSingleton( + user_dir, base::Bind(NotificationCallbackWrapper, callback))); switch (process_singleton_->NotifyOtherProcessOrCreate()) { case ProcessSingleton::NotifyResult::LOCK_ERROR: case ProcessSingleton::NotifyResult::PROFILE_IN_USE: case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: process_singleton_.reset(); - process_singleton_startup_lock_.reset(); return true; case ProcessSingleton::NotifyResult::PROCESS_NONE: default: // Shouldn't be needed, but VS warns if it is not there. diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index bd87b3885035..94cd9bbc68f9 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -11,7 +11,6 @@ #include "atom/browser/browser_observer.h" #include "atom/common/native_mate_converters/callback.h" #include "chrome/browser/process_singleton.h" -#include "chrome/browser/process_singleton_startup_lock.h" #include "content/public/browser/gpu_data_manager_observer.h" #include "native_mate/handle.h" @@ -77,7 +76,6 @@ class App : public mate::EventEmitter, v8::Global default_session_; scoped_ptr process_singleton_; - scoped_ptr process_singleton_startup_lock_; DISALLOW_COPY_AND_ASSIGN(App); }; diff --git a/chromium_src/chrome/browser/process_singleton_startup_lock.cc b/chromium_src/chrome/browser/process_singleton_startup_lock.cc deleted file mode 100644 index f564de7dca4d..000000000000 --- a/chromium_src/chrome/browser/process_singleton_startup_lock.cc +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/process_singleton_startup_lock.h" - -#include "base/bind.h" -#include "base/logging.h" - -ProcessSingletonStartupLock::ProcessSingletonStartupLock( - const ProcessSingleton::NotificationCallback& original_callback) - : locked_(true), - original_callback_(original_callback) {} - -ProcessSingletonStartupLock::~ProcessSingletonStartupLock() {} - -ProcessSingleton::NotificationCallback -ProcessSingletonStartupLock::AsNotificationCallback() { - return base::Bind(&ProcessSingletonStartupLock::NotificationCallbackImpl, - base::Unretained(this)); -} - -void ProcessSingletonStartupLock::Unlock() { - DCHECK(CalledOnValidThread()); - locked_ = false; - - // Replay the command lines of the messages which were received while the - // ProcessSingleton was locked. Only replay each message once. - std::set replayed_messages; - for (std::vector::const_iterator it = - saved_startup_messages_.begin(); - it != saved_startup_messages_.end(); ++it) { - if (replayed_messages.find(*it) != replayed_messages.end()) - continue; - original_callback_.Run(base::CommandLine(it->first), it->second); - replayed_messages.insert(*it); - } - saved_startup_messages_.clear(); -} - -bool ProcessSingletonStartupLock::NotificationCallbackImpl( - const base::CommandLine& command_line, - const base::FilePath& current_directory) { - if (locked_) { - // If locked, it means we are not ready to process this message because - // we are probably in a first run critical phase. - saved_startup_messages_.push_back( - std::make_pair(command_line.argv(), current_directory)); - return true; - } else { - return original_callback_.Run(command_line, current_directory); - } -} diff --git a/chromium_src/chrome/browser/process_singleton_startup_lock.h b/chromium_src/chrome/browser/process_singleton_startup_lock.h deleted file mode 100644 index 187dd35bce3d..000000000000 --- a/chromium_src/chrome/browser/process_singleton_startup_lock.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ -#define CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ - -#include -#include -#include - -#include "base/basictypes.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/threading/non_thread_safe.h" -#include "chrome/browser/process_singleton.h" - -// Provides a ProcessSingleton::NotificationCallback that can queue up -// command-line invocations during startup and execute them when startup -// completes. -// -// The object starts in a locked state. |Unlock()| must be called -// when the process is prepared to handle command-line invocations. -// -// Once unlocked, notifications are forwarded to a wrapped NotificationCallback. -class ProcessSingletonStartupLock : public base::NonThreadSafe { - public: - explicit ProcessSingletonStartupLock( - const ProcessSingleton::NotificationCallback& original_callback); - ~ProcessSingletonStartupLock(); - - // Returns the ProcessSingleton::NotificationCallback. - // The callback is only valid during the lifetime of the - // ProcessSingletonStartupLock instance. - ProcessSingleton::NotificationCallback AsNotificationCallback(); - - // Executes previously queued command-line invocations and allows future - // invocations to be executed immediately. - void Unlock(); - - bool locked() { return locked_; } - - private: - typedef std::pair - DelayedStartupMessage; - - bool NotificationCallbackImpl(const base::CommandLine& command_line, - const base::FilePath& current_directory); - - bool locked_; - std::vector saved_startup_messages_; - ProcessSingleton::NotificationCallback original_callback_; - - DISALLOW_COPY_AND_ASSIGN(ProcessSingletonStartupLock); -}; - -#endif // CHROME_BROWSER_PROCESS_SINGLETON_STARTUP_LOCK_H_ diff --git a/filenames.gypi b/filenames.gypi index ec7ab3291b3f..1c52cf50b2ae 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -347,6 +347,7 @@ 'chromium_src/chrome/browser/browser_process.cc', 'chromium_src/chrome/browser/browser_process.h', 'chromium_src/chrome/browser/chrome_process_finder_win.cc', + 'chromium_src/chrome/browser/chrome_process_finder_win.h', 'chromium_src/chrome/browser/chrome_notification_types.h', 'chromium_src/chrome/browser/extensions/global_shortcut_listener.cc', 'chromium_src/chrome/browser/extensions/global_shortcut_listener.h', @@ -376,8 +377,8 @@ 'chromium_src/chrome/browser/printing/print_preview_message_handler.cc', 'chromium_src/chrome/browser/printing/print_preview_message_handler.h', 'chromium_src/chrome/browser/process_singleton_posix.cc', - 'chromium_src/chrome/browser/process_singleton_startup_lock.cc', 'chromium_src/chrome/browser/process_singleton_win.cc', + 'chromium_src/chrome/browser/process_singleton.h', 'chromium_src/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc', 'chromium_src/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h', 'chromium_src/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc', From 93a3a946f3c7e6e4156d9491c3ba52b4cbf6df5f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 17:43:55 +0800 Subject: [PATCH 305/738] posix: Pass original command line --- chromium_src/chrome/browser/process_singleton_posix.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chromium_src/chrome/browser/process_singleton_posix.cc b/chromium_src/chrome/browser/process_singleton_posix.cc index 811c5c16a24e..e338b55c5f88 100644 --- a/chromium_src/chrome/browser/process_singleton_posix.cc +++ b/chromium_src/chrome/browser/process_singleton_posix.cc @@ -52,6 +52,7 @@ #include #include +#include "atom/common/atom_command_line.h" #include "base/base_paths.h" #include "base/basictypes.h" #include "base/bind.h" @@ -817,7 +818,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( return PROCESS_NONE; to_send.append(current_dir.value()); - const std::vector& argv = cmd_line.argv(); + const std::vector& argv = atom::AtomCommandLine::argv(); for (std::vector::const_iterator it = argv.begin(); it != argv.end(); ++it) { to_send.push_back(kTokenDelimiter); From d52ef50b017725f5b20daf8f168d45268eab564f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 17:51:51 +0800 Subject: [PATCH 306/738] win: Pass original command line --- chromium_src/chrome/browser/chrome_process_finder_win.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/chromium_src/chrome/browser/chrome_process_finder_win.cc b/chromium_src/chrome/browser/chrome_process_finder_win.cc index 299877a65db6..5a662258a0be 100644 --- a/chromium_src/chrome/browser/chrome_process_finder_win.cc +++ b/chromium_src/chrome/browser/chrome_process_finder_win.cc @@ -42,8 +42,6 @@ NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window, if (!thread_id || !process_id) return NOTIFY_FAILED; - base::CommandLine command_line(*base::CommandLine::ForCurrentProcess()); - // Send the command line to the remote chrome window. // Format is "START\0<<>>\0<<>>". std::wstring to_send(L"START\0", 6); // want the NULL in the string. @@ -52,7 +50,7 @@ NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window, return NOTIFY_FAILED; to_send.append(cur_dir.value()); to_send.append(L"\0", 1); // Null separator. - to_send.append(command_line.GetCommandLineString()); + to_send.append(::GetCommandLineW()); to_send.append(L"\0", 1); // Null separator. // Allow the current running browser window to make itself the foreground From 7b5a1b06ba40e2faa11b2be48af2c1856bd2fad7 Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 22 Oct 2015 16:20:48 +0530 Subject: [PATCH 307/738] debugger: expose v8debug --- atom/browser/javascript_environment.cc | 7 +++++++ atom/browser/node_debugger.cc | 8 +------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/atom/browser/javascript_environment.cc b/atom/browser/javascript_environment.cc index 4e825e38142d..cc06bb6ff9c2 100644 --- a/atom/browser/javascript_environment.cc +++ b/atom/browser/javascript_environment.cc @@ -4,6 +4,7 @@ #include "atom/browser/javascript_environment.h" +#include "base/command_line.h" #include "gin/array_buffer.h" #include "gin/v8_initializer.h" @@ -20,6 +21,12 @@ JavascriptEnvironment::JavascriptEnvironment() } bool JavascriptEnvironment::Initialize() { + auto cmd = base::CommandLine::ForCurrentProcess(); + if (cmd->HasSwitch("debug-brk")) { + // Need to be called before v8::Initialize(). + const char expose_debug_as[] = "--expose_debug_as=v8debug"; + v8::V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1); + } gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, gin::ArrayBufferAllocator::SharedInstance()); return true; diff --git a/atom/browser/node_debugger.cc b/atom/browser/node_debugger.cc index da5602a88137..2cfcdb222aea 100644 --- a/atom/browser/node_debugger.cc +++ b/atom/browser/node_debugger.cc @@ -35,17 +35,14 @@ NodeDebugger::NodeDebugger(v8::Isolate* isolate) weak_factory_(this) { bool use_debug_agent = false; int port = 5858; - bool wait_for_connection = false; std::string port_str; base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); if (cmd->HasSwitch("debug")) { use_debug_agent = true; port_str = cmd->GetSwitchValueASCII("debug"); - } - if (cmd->HasSwitch("debug-brk")) { + } else if (cmd->HasSwitch("debug-brk")) { use_debug_agent = true; - wait_for_connection = true; port_str = cmd->GetSwitchValueASCII("debug-brk"); } @@ -56,9 +53,6 @@ NodeDebugger::NodeDebugger(v8::Isolate* isolate) isolate_->SetData(kIsolateSlot, this); v8::Debug::SetMessageHandler(DebugMessageHandler); - if (wait_for_connection) - v8::Debug::DebugBreak(isolate_); - uv_async_init(uv_default_loop(), &weak_up_ui_handle_, ProcessMessageInUI); // Start a new IO thread. From 6bfe06ec4e5bc1dac93542bb920f680c7898698c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 19:02:21 +0800 Subject: [PATCH 308/738] Pass original argv in callback --- atom/browser/api/atom_api_app.cc | 3 +- atom/common/api/atom_bindings.cc | 2 +- .../command_line_converter.h | 38 ------------------- .../chrome/browser/process_singleton.h | 2 +- .../chrome/browser/process_singleton_posix.cc | 2 +- .../chrome/browser/process_singleton_win.cc | 19 ++++++++-- 6 files changed, 20 insertions(+), 46 deletions(-) delete mode 100644 atom/common/native_mate_converters/command_line_converter.h diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 84b9301316f6..c79dea9f7c5c 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -19,7 +19,6 @@ #include "atom/browser/api/atom_api_web_contents.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/file_path_converter.h" -#include "atom/common/native_mate_converters/command_line_converter.h" #include "atom/common/node_includes.h" #include "atom/common/options_switches.h" #include "base/command_line.h" @@ -114,7 +113,7 @@ int GetPathConstant(const std::string& name) { bool NotificationCallbackWrapper( const ProcessSingleton::NotificationCallback& callback, - const base::CommandLine& cmd, + const base::CommandLine::StringVector& cmd, const base::FilePath& cwd) { // Make sure the callback is called after app gets ready. if (Browser::Get()->is_ready()) { diff --git a/atom/common/api/atom_bindings.cc b/atom/common/api/atom_bindings.cc index 06fc30e7e3cd..60052a7216d0 100644 --- a/atom/common/api/atom_bindings.cc +++ b/atom/common/api/atom_bindings.cc @@ -41,7 +41,7 @@ void FatalErrorCallback(const char* location, const char* message) { } void Log(const base::string16& message) { - std::cout << message; + std::cout << message << std::flush; } } // namespace diff --git a/atom/common/native_mate_converters/command_line_converter.h b/atom/common/native_mate_converters/command_line_converter.h deleted file mode 100644 index a704ed7e92b7..000000000000 --- a/atom/common/native_mate_converters/command_line_converter.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_COMMAND_LINE_CONVERTER_H_ -#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_COMMAND_LINE_CONVERTER_H_ - -#include - -#include "atom/common/native_mate_converters/string16_converter.h" -#include "base/command_line.h" - -namespace mate { - -template<> -struct Converter { - static v8::Local ToV8(v8::Isolate* isolate, - const base::CommandLine& val) { - return Converter::ToV8( - isolate, val.GetCommandLineString()); - } - static bool FromV8(v8::Isolate* isolate, - v8::Local val, - base::CommandLine* out) { - base::FilePath::StringType path; - - if (Converter::FromV8(isolate, val, &path)) { - *out = base::CommandLine(base::FilePath(path)); - return true; - } else { - return false; - } - } -}; - -} // namespace mate - -#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_COMMAND_LINE_CONVERTER_H_ diff --git a/chromium_src/chrome/browser/process_singleton.h b/chromium_src/chrome/browser/process_singleton.h index 05288dc37cfe..3eeb53393e12 100644 --- a/chromium_src/chrome/browser/process_singleton.h +++ b/chromium_src/chrome/browser/process_singleton.h @@ -60,7 +60,7 @@ class ProcessSingleton : public base::NonThreadSafe { // handled within the current browser instance or false if the remote process // should handle it (i.e., because the current process is shutting down). using NotificationCallback = - base::Callback; ProcessSingleton(const base::FilePath& user_data_dir, diff --git a/chromium_src/chrome/browser/process_singleton_posix.cc b/chromium_src/chrome/browser/process_singleton_posix.cc index e338b55c5f88..b03ce431e47e 100644 --- a/chromium_src/chrome/browser/process_singleton_posix.cc +++ b/chromium_src/chrome/browser/process_singleton_posix.cc @@ -600,7 +600,7 @@ void ProcessSingleton::LinuxWatcher::HandleMessage( DCHECK(ui_message_loop_ == base::MessageLoop::current()); DCHECK(reader); - if (parent_->notification_callback_.Run(base::CommandLine(argv), + if (parent_->notification_callback_.Run(argv, base::FilePath(current_dir))) { // Send back "ACK" message to prevent the client process from starting up. reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1); diff --git a/chromium_src/chrome/browser/process_singleton_win.cc b/chromium_src/chrome/browser/process_singleton_win.cc index 0007b713b13b..14e53bec5fa7 100644 --- a/chromium_src/chrome/browser/process_singleton_win.cc +++ b/chromium_src/chrome/browser/process_singleton_win.cc @@ -77,8 +77,21 @@ BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) { return !*result; } +// Convert Command line string to argv. +base::CommandLine::StringVector CommandLineStringToArgv( + const std::wstring& command_line_string) { + int num_args = 0; + wchar_t** args = NULL; + args = ::CommandLineToArgvW(command_line_string.c_str(), &num_args); + base::CommandLine::StringVector argv; + for (int i = 0; i < num_args; ++i) + argv.push_back(std::wstring(args[i])); + LocalFree(args); + return argv; +} + bool ParseCommandLine(const COPYDATASTRUCT* cds, - base::CommandLine* parsed_command_line, + base::CommandLine::StringVector* parsed_command_line, base::FilePath* current_directory) { // We should have enough room for the shortest command (min_message_size) // and also be a multiple of wchar_t bytes. The shortest command @@ -131,7 +144,7 @@ bool ParseCommandLine(const COPYDATASTRUCT* cds, // Get command line. const std::wstring cmd_line = msg.substr(second_null + 1, third_null - second_null); - *parsed_command_line = base::CommandLine::FromString(cmd_line); + *parsed_command_line = CommandLineStringToArgv(cmd_line); return true; } return false; @@ -149,7 +162,7 @@ bool ProcessLaunchNotification( // Handle the WM_COPYDATA message from another process. const COPYDATASTRUCT* cds = reinterpret_cast(lparam); - base::CommandLine parsed_command_line(base::CommandLine::NO_PROGRAM); + base::CommandLine::StringVector parsed_command_line; base::FilePath current_directory; if (!ParseCommandLine(cds, &parsed_command_line, ¤t_directory)) { *result = TRUE; From 61f07307cb7c15b36e26cb4f099708b07609121b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 22 Oct 2015 19:26:05 +0800 Subject: [PATCH 309/738] docs: New behaviors of makeSingleInstance --- docs/api/app.md | 62 ++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/docs/api/app.md b/docs/api/app.md index 95aa80b6dc83..bb1509b68688 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -299,41 +299,51 @@ 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` is called when a second instance has been executed, and provides -the command-line (including Chromium flags) and the working directory of the -secondary instance. Usually applications respond to this by making their -primary window focused and non-minimized. +`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` should return `true` if the message was successfully handled, or -`false` if the secondary process should retry sending it or it failed. +The `callback` is guaranteed to be executed after the `ready` event of `app` +gets emitted. + +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. + +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. + +An example of activating the window of primary instance when a second instance +starts: ```js -var myWindow; -app.on('ready', function() { - 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(); - } +var myWindow = null; - // We successfully handled the command line - return true; - }); - - if (shouldQuit) { - app.quit(); - return; +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(); } + return true; +}); - // Create myWindow, load the rest of the app, etc... +if (shouldQuit) { + app.quit(); + return; +} + +// Create myWindow, load the rest of the app, etc... +app.on('ready', function() { }); ``` -Returns a Boolean - if `false`, your process is the primary instance of the -application and your app should continue loading. If `true`, your process has -sent its parameters to another instance, and you should immediately quit. - ### `app.commandLine.appendSwitch(switch[, value])` Append a switch (with optional `value`) to Chromium's command line. From e9a5d05b279d60322c21ceb7220060a6d3a2ea36 Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 22 Oct 2015 22:56:36 +0530 Subject: [PATCH 310/738] session: allow setproxy to use external pac script --- atom/browser/api/atom_api_session.cc | 28 +++++++++++++++++++++++----- atom/browser/api/atom_api_session.h | 6 +++++- docs/api/session.md | 4 +++- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 3c92266be33c..5bb96710f226 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -105,6 +105,24 @@ struct Converter { } }; +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + net::ProxyConfig* out) { + std::string proxy; + if (!ConvertFromV8(isolate, val, &proxy)) + return false; + auto pac_url = GURL(proxy); + if (pac_url.is_valid()) { + out->set_pac_url(pac_url); + } else { + out->proxy_rules().ParseFromString(proxy); + } + return true; + } +}; + } // namespace mate namespace atom { @@ -209,12 +227,12 @@ void ClearHttpCacheInIO( } void SetProxyInIO(net::URLRequestContextGetter* getter, - const std::string& proxy, + const net::ProxyConfig& config, const base::Closure& callback) { - net::ProxyConfig config; - config.proxy_rules().ParseFromString(proxy); auto proxy_service = getter->GetURLRequestContext()->proxy_service(); proxy_service->ResetConfigService(new net::ProxyConfigServiceFixed(config)); + // Refetches and applies the new pac script if provided. + proxy_service->ForceReloadProxyConfig(); RunCallbackInUI(callback); } @@ -287,11 +305,11 @@ void Session::ClearStorageData(mate::Arguments* args) { base::Time(), base::Time::Max(), callback); } -void Session::SetProxy(const std::string& proxy, +void Session::SetProxy(const net::ProxyConfig& config, const base::Closure& callback) { auto getter = browser_context_->GetRequestContext(); BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&SetProxyInIO, base::Unretained(getter), proxy, callback)); + base::Bind(&SetProxyInIO, base::Unretained(getter), config, callback)); } void Session::SetDownloadPath(const base::FilePath& path) { diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 68ee3634e6c4..39712f6c8486 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -23,6 +23,10 @@ class Arguments; class Dictionary; } +namespace net { +class ProxyConfig; +} + namespace atom { class AtomBrowserContext; @@ -64,7 +68,7 @@ class Session: public mate::TrackableObject, void ResolveProxy(const GURL& url, ResolveProxyCallback callback); void ClearCache(const net::CompletionCallback& callback); void ClearStorageData(mate::Arguments* args); - void SetProxy(const std::string& proxy, const base::Closure& callback); + void SetProxy(const net::ProxyConfig& config, const base::Closure& callback); void SetDownloadPath(const base::FilePath& path); void EnableNetworkEmulation(const mate::Dictionary& options); void DisableNetworkEmulation(); diff --git a/docs/api/session.md b/docs/api/session.md index 392b6826414d..25db92b73b25 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -154,7 +154,9 @@ Clears the data of web storages. * `config` String * `callback` Function - Called when operation is done. -Parses the `config` indicating which proxies to use for the session. +If `config` is a PAC url, it is used directly otherwise +`config` is parsed based on the following rules indicating which +proxies to use for the session. ``` config = scheme-proxies[";"] From 4a6134f3f71ab7cd7e1406d588f74480b870a3da Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 11:17:14 +0800 Subject: [PATCH 311/738] win: Set native window's background color --- atom/browser/native_window_views.cc | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 1e4207bf0c6f..ab4df82df75d 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -42,6 +42,7 @@ #elif defined(OS_WIN) #include "atom/browser/ui/views/win_frame_view.h" #include "atom/browser/ui/win/atom_desktop_window_tree_host_win.h" +#include "skia/ext/skia_utils_win.h" #include "ui/base/win/shell.h" #include "ui/gfx/win/dpi.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" @@ -230,14 +231,22 @@ NativeWindowViews::NativeWindowViews( SetLayoutManager(new MenuLayout(this, kMenuBarHeight)); // web views' background color. - std::string background_color = "#fff"; - options.Get(switches::kBackgroundColor, &background_color); - set_background(views::Background::CreateSolidBackground( - ParseHexColor(background_color))); + SkColor background_color = SK_ColorWHITE; + std::string color_name; + if (options.Get(switches::kBackgroundColor, &color_name)) + background_color = ParseHexColor(color_name); + set_background(views::Background::CreateSolidBackground(background_color)); AddChildView(web_view_); #if defined(OS_WIN) + // Set the background color of native window. + HBRUSH brush = CreateSolidBrush(skia::SkColorToCOLORREF(background_color)); + ULONG_PTR previous_brush = SetClassLongPtr( + GetAcceleratedWidget(), GCLP_HBRBACKGROUND, (LONG)brush); + if (previous_brush) + DeleteObject((HBRUSH)previous_brush); + // Save initial window state. if (fullscreen) last_window_state_ = ui::SHOW_STATE_FULLSCREEN; From e36d455d518cf79bc06a33a27df6e597dbc39485 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 11:35:33 +0800 Subject: [PATCH 312/738] Add setBackgroundColor method --- atom/browser/api/atom_api_window.cc | 5 +++++ atom/browser/api/atom_api_window.h | 1 + atom/browser/native_window.cc | 4 ++++ atom/browser/native_window.h | 1 + atom/browser/native_window_mac.h | 1 + atom/browser/native_window_mac.mm | 3 +++ atom/browser/native_window_views.cc | 29 +++++++++++++++-------------- atom/browser/native_window_views.h | 1 + 8 files changed, 31 insertions(+), 14 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index c4beaace6728..62994c9c93d4 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -385,6 +385,10 @@ bool Window::IsKiosk() { return window_->IsKiosk(); } +void Window::SetBackgroundColor(const std::string& color_name) { + window_->SetBackgroundColor(color_name); +} + void Window::FocusOnWebView() { window_->FocusOnWebView(); } @@ -564,6 +568,7 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("setSkipTaskbar", &Window::SetSkipTaskbar) .SetMethod("setKiosk", &Window::SetKiosk) .SetMethod("isKiosk", &Window::IsKiosk) + .SetMethod("setBackgroundColor", &Window::SetBackgroundColor) .SetMethod("setRepresentedFilename", &Window::SetRepresentedFilename) .SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename) .SetMethod("setDocumentEdited", &Window::SetDocumentEdited) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index d2886b5fac94..8a8ff266a883 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -122,6 +122,7 @@ class Window : public mate::TrackableObject, void SetSkipTaskbar(bool skip); void SetKiosk(bool kiosk); bool IsKiosk(); + void SetBackgroundColor(const std::string& color_name); void FocusOnWebView(); void BlurWebView(); bool IsWebViewFocused(); diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 8f3af83885f1..c19bcdf467f3 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -139,6 +139,10 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { if (options.Get(switches::kKiosk, &kiosk) && kiosk) { SetKiosk(kiosk); } + std::string color; + if (options.Get(switches::kBackgroundColor, &color)) { + SetBackgroundColor(color); + } std::string title("Electron"); options.Get(switches::kTitle, &title); SetTitle(title); diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 67bac88f32d4..37a59ff8a9e4 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -134,6 +134,7 @@ class NativeWindow : public base::SupportsUserData, virtual void SetSkipTaskbar(bool skip) = 0; virtual void SetKiosk(bool kiosk) = 0; virtual bool IsKiosk() = 0; + virtual void SetBackgroundColor(const std::string& color_name) = 0; virtual void SetRepresentedFilename(const std::string& filename); virtual std::string GetRepresentedFilename(); virtual void SetDocumentEdited(bool edited); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 7a97032d75ff..08f9198e4ff1 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -57,6 +57,7 @@ class NativeWindowMac : public NativeWindow { void SetSkipTaskbar(bool skip) override; void SetKiosk(bool kiosk) override; bool IsKiosk() override; + void SetBackgroundColor(const std::string& color_name) override; void SetRepresentedFilename(const std::string& filename) override; std::string GetRepresentedFilename() override; void SetDocumentEdited(bool edited) override; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 9724930c4885..28c8a5ae59a0 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -635,6 +635,9 @@ bool NativeWindowMac::IsKiosk() { return is_kiosk_; } +void NativeWindowMac::SetBackgroundColor(const std::string& color_name) { +} + void NativeWindowMac::SetRepresentedFilename(const std::string& filename) { [window_ setRepresentedFilename:base::SysUTF8ToNSString(filename)]; } diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index ab4df82df75d..876058789d0f 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -230,23 +230,9 @@ NativeWindowViews::NativeWindowViews( // Add web view. SetLayoutManager(new MenuLayout(this, kMenuBarHeight)); - // web views' background color. - SkColor background_color = SK_ColorWHITE; - std::string color_name; - if (options.Get(switches::kBackgroundColor, &color_name)) - background_color = ParseHexColor(color_name); - set_background(views::Background::CreateSolidBackground(background_color)); - AddChildView(web_view_); #if defined(OS_WIN) - // Set the background color of native window. - HBRUSH brush = CreateSolidBrush(skia::SkColorToCOLORREF(background_color)); - ULONG_PTR previous_brush = SetClassLongPtr( - GetAcceleratedWidget(), GCLP_HBRBACKGROUND, (LONG)brush); - if (previous_brush) - DeleteObject((HBRUSH)previous_brush); - // Save initial window state. if (fullscreen) last_window_state_ = ui::SHOW_STATE_FULLSCREEN; @@ -534,6 +520,21 @@ bool NativeWindowViews::IsKiosk() { return IsFullscreen(); } +void NativeWindowViews::SetBackgroundColor(const std::string& color_name) { + // web views' background color. + SkColor background_color = ParseHexColor(color_name); + set_background(views::Background::CreateSolidBackground(background_color)); + +#if defined(OS_WIN) + // Set the background color of native window. + HBRUSH brush = CreateSolidBrush(skia::SkColorToCOLORREF(background_color)); + ULONG_PTR previous_brush = SetClassLongPtr( + GetAcceleratedWidget(), GCLP_HBRBACKGROUND, (LONG)brush); + if (previous_brush) + DeleteObject((HBRUSH)previous_brush); +#endif +} + void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) { if (menu_model == nullptr) { // Remove accelerators diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 0014acd073c1..6c47c74331d0 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -77,6 +77,7 @@ class NativeWindowViews : public NativeWindow, void SetSkipTaskbar(bool skip) override; void SetKiosk(bool kiosk) override; bool IsKiosk() override; + void SetBackgroundColor(const std::string& color_name) override; void SetMenu(ui::MenuModel* menu_model) override; gfx::NativeWindow GetNativeWindow() override; void SetOverlayIcon(const gfx::Image& overlay, From 83ef23ff8def8913ead0329164c1890532647997 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 13:32:04 +0800 Subject: [PATCH 313/738] docs: background-color on Windows --- docs/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 165ce70a977e..aa46590c746b 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -62,7 +62,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `enable-larger-than-screen` Boolean - Enable the window to be resized larger than screen. * `background-color` String - Window's background color as Hexadecimal value, - like `#66CD00` or `#FFF`. This is only implemented on Linux. + like `#66CD00` or `#FFF`. This is only implemented on Linux and Windows. * `dark-theme` Boolean - Forces using dark theme for the window, only works on some GTK+3 desktop environments. * `transparent` Boolean - Makes the window [transparent](frameless-window.md). From d5c964c68c6cee99af54a0053322bda6d793cda8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 14:23:05 +0800 Subject: [PATCH 314/738] Fix passing Error object in remote Closes #3089 --- atom/browser/lib/rpc-server.coffee | 27 +++++++++++++++------------ atom/renderer/api/lib/remote.coffee | 3 ++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index a1e159a16a7f..6a20d09d119a 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -10,6 +10,7 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta.type = 'buffer' if Buffer.isBuffer value meta.type = 'value' if value is null meta.type = 'array' if Array.isArray value + meta.type = 'error' if value instanceof Error meta.type = 'promise' if value? and value.constructor.name is 'Promise' # Treat simple objects as value. @@ -36,6 +37,8 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta.value = Array::slice.call value, 0 else if meta.type is 'promise' meta.then = valueToMeta(sender, value.then.bind(value)) + else if meta.type is 'error' + meta.message = value.message else meta.type = 'value' meta.value = value @@ -43,8 +46,8 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta # Convert Error into meta data. -errorToMeta = (error) -> - type: 'error', message: error.message, stack: (error.stack || error) +exceptionToMeta = (error) -> + type: 'exception', message: error.message, stack: (error.stack || error) # Convert array of meta data from renderer into array of real values. unwrapArgs = (sender, args) -> @@ -100,19 +103,19 @@ ipc.on 'ATOM_BROWSER_REQUIRE', (event, module) -> try event.returnValue = valueToMeta event.sender, process.mainModule.require(module) catch e - event.returnValue = errorToMeta e + event.returnValue = exceptionToMeta e ipc.on 'ATOM_BROWSER_GLOBAL', (event, name) -> try event.returnValue = valueToMeta event.sender, global[name] catch e - event.returnValue = errorToMeta e + event.returnValue = exceptionToMeta e ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event) -> try event.returnValue = valueToMeta event.sender, event.sender.getOwnerBrowserWindow() catch e - event.returnValue = errorToMeta e + event.returnValue = exceptionToMeta e ipc.on 'ATOM_BROWSER_CURRENT_WEB_CONTENTS', (event) -> event.returnValue = valueToMeta event.sender, event.sender @@ -126,7 +129,7 @@ ipc.on 'ATOM_BROWSER_CONSTRUCTOR', (event, id, args) -> obj = new (Function::bind.apply(constructor, [null].concat(args))) event.returnValue = valueToMeta event.sender, obj catch e - event.returnValue = errorToMeta e + event.returnValue = exceptionToMeta e ipc.on 'ATOM_BROWSER_FUNCTION_CALL', (event, id, args) -> try @@ -134,7 +137,7 @@ ipc.on 'ATOM_BROWSER_FUNCTION_CALL', (event, id, args) -> func = objectsRegistry.get id callFunction event, func, global, args catch e - event.returnValue = errorToMeta e + event.returnValue = exceptionToMeta e ipc.on 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', (event, id, method, args) -> try @@ -144,7 +147,7 @@ ipc.on 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', (event, id, method, args) -> obj = new (Function::bind.apply(constructor, [null].concat(args))) event.returnValue = valueToMeta event.sender, obj catch e - event.returnValue = errorToMeta e + event.returnValue = exceptionToMeta e ipc.on 'ATOM_BROWSER_MEMBER_CALL', (event, id, method, args) -> try @@ -152,7 +155,7 @@ ipc.on 'ATOM_BROWSER_MEMBER_CALL', (event, id, method, args) -> obj = objectsRegistry.get id callFunction event, obj[method], obj, args catch e - event.returnValue = errorToMeta e + event.returnValue = exceptionToMeta e ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, id, name, value) -> try @@ -160,14 +163,14 @@ ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, id, name, value) -> obj[name] = value event.returnValue = null catch e - event.returnValue = errorToMeta e + event.returnValue = exceptionToMeta e ipc.on 'ATOM_BROWSER_MEMBER_GET', (event, id, name) -> try obj = objectsRegistry.get id event.returnValue = valueToMeta event.sender, obj[name] catch e - event.returnValue = errorToMeta e + event.returnValue = exceptionToMeta e ipc.on 'ATOM_BROWSER_DEREFERENCE', (event, id) -> objectsRegistry.remove event.sender.getId(), id @@ -177,4 +180,4 @@ ipc.on 'ATOM_BROWSER_GUEST_WEB_CONTENTS', (event, guestInstanceId) -> guestViewManager = require './guest-view-manager' event.returnValue = valueToMeta event.sender, guestViewManager.getGuest(guestInstanceId) catch e - event.returnValue = errorToMeta e + event.returnValue = exceptionToMeta e diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index 1f17cf340020..4eb56bcf0279 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -46,7 +46,8 @@ metaToValue = (meta) -> when 'array' then (metaToValue(el) for el in meta.members) when 'buffer' then new Buffer(meta.value) when 'promise' then Promise.resolve(then: metaToValue(meta.then)) - when 'error' + when 'error' then new Error(meta.message) + when 'exception' throw new Error("#{meta.message}\n#{meta.stack}") else if meta.type is 'function' From 95fe4beda83318949c51e0100d46f221ab2b265e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 14:36:36 +0800 Subject: [PATCH 315/738] Pass real Error object in error event --- atom/browser/api/atom_api_auto_updater.cc | 11 +++++++++-- docs/api/auto-updater.md | 3 +-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_auto_updater.cc b/atom/browser/api/atom_api_auto_updater.cc index 250aa3e45f64..d8407f60b327 100644 --- a/atom/browser/api/atom_api_auto_updater.cc +++ b/atom/browser/api/atom_api_auto_updater.cc @@ -23,8 +23,15 @@ AutoUpdater::~AutoUpdater() { auto_updater::AutoUpdater::SetDelegate(NULL); } -void AutoUpdater::OnError(const std::string& error) { - Emit("error", error); +void AutoUpdater::OnError(const std::string& message) { + v8::Locker locker(isolate()); + v8::HandleScope handle_scope(isolate()); + auto error = v8::Exception::Error(mate::StringToV8(isolate(), message)); + EmitCustomEvent( + "error", + error->ToObject(isolate()->GetCurrentContext()).ToLocalChecked(), + // Message is also emitted to keep compatibility with old code. + message); } void AutoUpdater::OnCheckingForUpdate() { diff --git a/docs/api/auto-updater.md b/docs/api/auto-updater.md index 9734f592c8fe..ea731cd869a9 100644 --- a/docs/api/auto-updater.md +++ b/docs/api/auto-updater.md @@ -110,8 +110,7 @@ The `autoUpdater` object emits the following events: Returns: -* `event` Event -* `message` String +* `error` Error Emitted when there is an error while updating. From a3f62da615221a3e98c43d518b0c03a45783aa4d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 14:51:25 +0800 Subject: [PATCH 316/738] Fix passing Date object in remote Close #2017. --- atom/browser/lib/rpc-server.coffee | 3 +++ atom/renderer/api/lib/remote.coffee | 1 + 2 files changed, 4 insertions(+) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 6a20d09d119a..6b1f95a841ab 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -11,6 +11,7 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta.type = 'value' if value is null meta.type = 'array' if Array.isArray value meta.type = 'error' if value instanceof Error + meta.type = 'date' if value instanceof Date meta.type = 'promise' if value? and value.constructor.name is 'Promise' # Treat simple objects as value. @@ -39,6 +40,8 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta.then = valueToMeta(sender, value.then.bind(value)) else if meta.type is 'error' meta.message = value.message + else if meta.type is 'date' + meta.value = value.getTime() else meta.type = 'value' meta.value = value diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index 4eb56bcf0279..8a5565f06562 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -47,6 +47,7 @@ metaToValue = (meta) -> when 'buffer' then new Buffer(meta.value) when 'promise' then Promise.resolve(then: metaToValue(meta.then)) when 'error' then new Error(meta.message) + when 'date' then new Date(meta.value) when 'exception' throw new Error("#{meta.message}\n#{meta.stack}") else From 85c84a0eb034ce552e4ed48ed56ed513d365a555 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 14:58:19 +0800 Subject: [PATCH 317/738] Emit Date object in C++ directly --- atom/browser/api/atom_api_auto_updater.cc | 22 +++++++++++++++++++--- atom/browser/api/lib/auto-updater.coffee | 19 ++++++++----------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/atom/browser/api/atom_api_auto_updater.cc b/atom/browser/api/atom_api_auto_updater.cc index d8407f60b327..9a240a27903c 100644 --- a/atom/browser/api/atom_api_auto_updater.cc +++ b/atom/browser/api/atom_api_auto_updater.cc @@ -11,6 +11,23 @@ #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" +namespace mate { + +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + const base::Time& val) { + v8::MaybeLocal date = v8::Date::New( + isolate->GetCurrentContext(), val.ToJsTime()); + if (date.IsEmpty()) + return v8::Null(isolate); + else + return date.ToLocalChecked(); + } +}; + +} // namespace mate + namespace atom { namespace api { @@ -49,11 +66,10 @@ void AutoUpdater::OnUpdateNotAvailable() { void AutoUpdater::OnUpdateDownloaded(const std::string& release_notes, const std::string& release_name, const base::Time& release_date, - const std::string& update_url, + const std::string& url, const base::Closure& quit_and_install) { quit_and_install_ = quit_and_install; - Emit("update-downloaded-raw", release_notes, release_name, - release_date.ToJsTime(), update_url); + Emit("update-downloaded", release_notes, release_name, release_date, url); } mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder( diff --git a/atom/browser/api/lib/auto-updater.coffee b/atom/browser/api/lib/auto-updater.coffee index c039bd12dc46..7e3fa99a76d9 100644 --- a/atom/browser/api/lib/auto-updater.coffee +++ b/atom/browser/api/lib/auto-updater.coffee @@ -1,15 +1,12 @@ -switch process.platform - when 'win32' - autoUpdater = require './auto-updater/auto-updater-win' - else - # take the default binding for the current platform - autoUpdater = process.atomBinding('auto_updater').autoUpdater - EventEmitter = require('events').EventEmitter - autoUpdater.__proto__ = EventEmitter.prototype +if process.platform is 'win32' + module.exports = require './auto-updater/auto-updater-win' + return -autoUpdater.on 'update-downloaded-raw', (args...) -> - args[3] = new Date(args[3]) # releaseDate - @emit 'update-downloaded', args..., => @quitAndInstall() +# Implementation on OS X. +autoUpdater = process.atomBinding('auto_updater').autoUpdater +EventEmitter = require('events').EventEmitter + +autoUpdater.__proto__ = EventEmitter.prototype autoUpdater.quitAndInstall = -> # If we don't have any window then quitAndInstall immediately. From d74ef5c078e2a13074147281cbed51378ee5315d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 15:13:24 +0800 Subject: [PATCH 318/738] Move implementation of auto-updater on OS X to another file --- atom/browser/api/lib/auto-updater.coffee | 32 ++++--------------- .../lib/auto-updater/auto-updater-mac.coffee | 20 ++++++++++++ filenames.gypi | 1 + 3 files changed, 28 insertions(+), 25 deletions(-) create mode 100644 atom/browser/api/lib/auto-updater/auto-updater-mac.coffee diff --git a/atom/browser/api/lib/auto-updater.coffee b/atom/browser/api/lib/auto-updater.coffee index 7e3fa99a76d9..41b78a00d7e0 100644 --- a/atom/browser/api/lib/auto-updater.coffee +++ b/atom/browser/api/lib/auto-updater.coffee @@ -1,25 +1,7 @@ -if process.platform is 'win32' - module.exports = require './auto-updater/auto-updater-win' - return - -# Implementation on OS X. -autoUpdater = process.atomBinding('auto_updater').autoUpdater -EventEmitter = require('events').EventEmitter - -autoUpdater.__proto__ = EventEmitter.prototype - -autoUpdater.quitAndInstall = -> - # If we don't have any window then quitAndInstall immediately. - BrowserWindow = require 'browser-window' - windows = BrowserWindow.getAllWindows() - if windows.length is 0 - @_quitAndInstall() - return - - # Do the restart after all windows have been closed. - app = require 'app' - app.removeAllListeners 'window-all-closed' - app.once 'window-all-closed', @_quitAndInstall.bind(this) - win.close() for win in windows - -module.exports = autoUpdater +switch process.platform + when 'win32' + module.exports = require './auto-updater/auto-updater-win' + when 'darwin' + module.exports = require './auto-updater/auto-updater-mac' + else + throw new Error('auto-updater is not implemented on this platform') diff --git a/atom/browser/api/lib/auto-updater/auto-updater-mac.coffee b/atom/browser/api/lib/auto-updater/auto-updater-mac.coffee new file mode 100644 index 000000000000..9ec9f3f91749 --- /dev/null +++ b/atom/browser/api/lib/auto-updater/auto-updater-mac.coffee @@ -0,0 +1,20 @@ +{EventEmitter} = require 'events' +{autoUpdater} = process.atomBinding 'auto_updater' + +autoUpdater.__proto__ = EventEmitter.prototype + +autoUpdater.quitAndInstall = -> + # If we don't have any window then quitAndInstall immediately. + BrowserWindow = require 'browser-window' + windows = BrowserWindow.getAllWindows() + if windows.length is 0 + @_quitAndInstall() + return + + # Do the restart after all windows have been closed. + app = require 'app' + app.removeAllListeners 'window-all-closed' + app.once 'window-all-closed', @_quitAndInstall.bind(this) + win.close() for win in windows + +module.exports = autoUpdater diff --git a/filenames.gypi b/filenames.gypi index 389c245ffa8a..f6a7dbd08680 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -11,6 +11,7 @@ 'atom/browser/api/lib/app.coffee', 'atom/browser/api/lib/atom-delegate.coffee', 'atom/browser/api/lib/auto-updater.coffee', + 'atom/browser/api/lib/auto-updater/auto-updater-mac.coffee', 'atom/browser/api/lib/auto-updater/auto-updater-win.coffee', 'atom/browser/api/lib/auto-updater/squirrel-update-win.coffee', 'atom/browser/api/lib/browser-window.coffee', From f89d28a63ebdaff666a2d22cec50f27a753562da Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 15:40:56 +0800 Subject: [PATCH 319/738] Simplify the auto-updater implementations We used to use Sparkle on OS X, and the design was reserved to be extended to all platforms, which are all wrong now. --- atom/browser/api/atom_api_auto_updater.cc | 30 ++++++++----- atom/browser/api/atom_api_auto_updater.h | 24 +++++----- .../lib/auto-updater/auto-updater-mac.coffee | 14 ------ atom/browser/auto_updater.cc | 11 +++-- atom/browser/auto_updater.h | 35 +++++++++++++-- atom/browser/auto_updater_delegate.h | 45 ------------------- atom/browser/auto_updater_linux.cc | 17 ------- atom/browser/auto_updater_mac.mm | 26 +++++------ atom/browser/auto_updater_win.cc | 17 ------- filenames.gypi | 3 -- 10 files changed, 81 insertions(+), 141 deletions(-) delete mode 100644 atom/browser/auto_updater_delegate.h delete mode 100644 atom/browser/auto_updater_linux.cc delete mode 100644 atom/browser/auto_updater_win.cc diff --git a/atom/browser/api/atom_api_auto_updater.cc b/atom/browser/api/atom_api_auto_updater.cc index 9a240a27903c..1b7c0cee7d96 100644 --- a/atom/browser/api/atom_api_auto_updater.cc +++ b/atom/browser/api/atom_api_auto_updater.cc @@ -5,8 +5,9 @@ #include "atom/browser/api/atom_api_auto_updater.h" #include "base/time/time.h" -#include "atom/browser/auto_updater.h" #include "atom/browser/browser.h" +#include "atom/browser/native_window.h" +#include "atom/browser/window_list.h" #include "atom/common/node_includes.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" @@ -37,7 +38,7 @@ AutoUpdater::AutoUpdater() { } AutoUpdater::~AutoUpdater() { - auto_updater::AutoUpdater::SetDelegate(NULL); + auto_updater::AutoUpdater::SetDelegate(nullptr); } void AutoUpdater::OnError(const std::string& message) { @@ -66,25 +67,34 @@ void AutoUpdater::OnUpdateNotAvailable() { void AutoUpdater::OnUpdateDownloaded(const std::string& release_notes, const std::string& release_name, const base::Time& release_date, - const std::string& url, - const base::Closure& quit_and_install) { - quit_and_install_ = quit_and_install; + const std::string& url) { Emit("update-downloaded", release_notes, release_name, release_date, url); } +void AutoUpdater::OnWindowAllClosed() { + QuitAndInstall(); +} + mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) .SetMethod("setFeedUrl", &auto_updater::AutoUpdater::SetFeedURL) .SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates) - .SetMethod("_quitAndInstall", &AutoUpdater::QuitAndInstall); + .SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall); } void AutoUpdater::QuitAndInstall() { - if (quit_and_install_.is_null()) - Browser::Get()->Shutdown(); - else - quit_and_install_.Run(); + // If we don't have any window then quitAndInstall immediately. + WindowList* window_list = WindowList::GetInstance(); + if (window_list->size() == 0) { + auto_updater::AutoUpdater::QuitAndInstall(); + return; + } + + // Otherwise do the restart after all windows have been closed. + window_list->AddObserver(this); + for (NativeWindow* window : *window_list) + window->Close(); } // static diff --git a/atom/browser/api/atom_api_auto_updater.h b/atom/browser/api/atom_api_auto_updater.h index 50c3989703a1..95b91041e9e3 100644 --- a/atom/browser/api/atom_api_auto_updater.h +++ b/atom/browser/api/atom_api_auto_updater.h @@ -7,9 +7,9 @@ #include -#include "base/callback.h" #include "atom/browser/api/event_emitter.h" -#include "atom/browser/auto_updater_delegate.h" +#include "atom/browser/auto_updater.h" +#include "atom/browser/window_list_observer.h" #include "native_mate/handle.h" namespace atom { @@ -17,7 +17,8 @@ namespace atom { namespace api { class AutoUpdater : public mate::EventEmitter, - public auto_updater::AutoUpdaterDelegate { + public auto_updater::Delegate, + public WindowListObserver { public: static mate::Handle Create(v8::Isolate* isolate); @@ -25,17 +26,18 @@ class AutoUpdater : public mate::EventEmitter, AutoUpdater(); virtual ~AutoUpdater(); - // AutoUpdaterDelegate implementations. + // Delegate implementations. void OnError(const std::string& error) override; void OnCheckingForUpdate() override; void OnUpdateAvailable() override; void OnUpdateNotAvailable() override; - void OnUpdateDownloaded( - const std::string& release_notes, - const std::string& release_name, - const base::Time& release_date, - const std::string& update_url, - const base::Closure& quit_and_install) override; + void OnUpdateDownloaded(const std::string& release_notes, + const std::string& release_name, + const base::Time& release_date, + const std::string& update_url) override; + + // WindowListObserver: + void OnWindowAllClosed() override; // mate::Wrappable implementations: mate::ObjectTemplateBuilder GetObjectTemplateBuilder( @@ -44,8 +46,6 @@ class AutoUpdater : public mate::EventEmitter, private: void QuitAndInstall(); - base::Closure quit_and_install_; - DISALLOW_COPY_AND_ASSIGN(AutoUpdater); }; diff --git a/atom/browser/api/lib/auto-updater/auto-updater-mac.coffee b/atom/browser/api/lib/auto-updater/auto-updater-mac.coffee index 9ec9f3f91749..187be64f5ade 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-mac.coffee +++ b/atom/browser/api/lib/auto-updater/auto-updater-mac.coffee @@ -3,18 +3,4 @@ autoUpdater.__proto__ = EventEmitter.prototype -autoUpdater.quitAndInstall = -> - # If we don't have any window then quitAndInstall immediately. - BrowserWindow = require 'browser-window' - windows = BrowserWindow.getAllWindows() - if windows.length is 0 - @_quitAndInstall() - return - - # Do the restart after all windows have been closed. - app = require 'app' - app.removeAllListeners 'window-all-closed' - app.once 'window-all-closed', @_quitAndInstall.bind(this) - win.close() for win in windows - module.exports = autoUpdater diff --git a/atom/browser/auto_updater.cc b/atom/browser/auto_updater.cc index 7ebae510e9f8..7dbfc5a6feba 100644 --- a/atom/browser/auto_updater.cc +++ b/atom/browser/auto_updater.cc @@ -6,22 +6,25 @@ namespace auto_updater { -AutoUpdaterDelegate* AutoUpdater::delegate_ = NULL; +Delegate* AutoUpdater::delegate_ = nullptr; -AutoUpdaterDelegate* AutoUpdater::GetDelegate() { +Delegate* AutoUpdater::GetDelegate() { return delegate_; } -void AutoUpdater::SetDelegate(AutoUpdaterDelegate* delegate) { +void AutoUpdater::SetDelegate(Delegate* delegate) { delegate_ = delegate; } -#if defined(OS_MACOSX) && defined(MAS_BUILD) +#if !defined(OS_MACOSX) || defined(MAS_BUILD) void AutoUpdater::SetFeedURL(const std::string& url) { } void AutoUpdater::CheckForUpdates() { } + +void AutoUpdater::QuitAndInstall() { +} #endif } // namespace auto_updater diff --git a/atom/browser/auto_updater.h b/atom/browser/auto_updater.h index e31aa0978a1c..9e479d4220de 100644 --- a/atom/browser/auto_updater.h +++ b/atom/browser/auto_updater.h @@ -9,21 +9,48 @@ #include "base/basictypes.h" +namespace base { +class Time; +} + namespace auto_updater { -class AutoUpdaterDelegate; +class Delegate { + public: + // An error happened. + virtual void OnError(const std::string& error) {} + + // Checking to see if there is an update + virtual void OnCheckingForUpdate() {} + + // There is an update available and it is being downloaded + virtual void OnUpdateAvailable() {} + + // There is no available update. + virtual void OnUpdateNotAvailable() {} + + // There is a new update which has been downloaded. + virtual void OnUpdateDownloaded(const std::string& release_notes, + const std::string& release_name, + const base::Time& release_date, + const std::string& update_url) {} + + protected: + virtual ~Delegate() {} +}; class AutoUpdater { public: // Gets/Sets the delegate. - static AutoUpdaterDelegate* GetDelegate(); - static void SetDelegate(AutoUpdaterDelegate* delegate); + static Delegate* GetDelegate(); + static void SetDelegate(Delegate* delegate); static void SetFeedURL(const std::string& url); static void CheckForUpdates(); + static void QuitAndInstall(); private: - static AutoUpdaterDelegate* delegate_; + static Delegate* delegate_; DISALLOW_IMPLICIT_CONSTRUCTORS(AutoUpdater); }; diff --git a/atom/browser/auto_updater_delegate.h b/atom/browser/auto_updater_delegate.h deleted file mode 100644 index 804bc8503a1e..000000000000 --- a/atom/browser/auto_updater_delegate.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_AUTO_UPDATER_DELEGATE_H_ -#define ATOM_BROWSER_AUTO_UPDATER_DELEGATE_H_ - -#include - -#include "base/callback_forward.h" - -namespace base { -class Time; -} - -namespace auto_updater { - -class AutoUpdaterDelegate { - public: - // An error happened. - virtual void OnError(const std::string& error) {} - - // Checking to see if there is an update - virtual void OnCheckingForUpdate() {} - - // There is an update available and it is being downloaded - virtual void OnUpdateAvailable() {} - - // There is no available update. - virtual void OnUpdateNotAvailable() {} - - // There is a new update which has been downloaded. - virtual void OnUpdateDownloaded(const std::string& release_notes, - const std::string& release_name, - const base::Time& release_date, - const std::string& update_url, - const base::Closure& quit_and_install) {} - - protected: - virtual ~AutoUpdaterDelegate() {} -}; - -} // namespace auto_updater - -#endif // ATOM_BROWSER_AUTO_UPDATER_DELEGATE_H_ diff --git a/atom/browser/auto_updater_linux.cc b/atom/browser/auto_updater_linux.cc deleted file mode 100644 index 00c95d0d45d7..000000000000 --- a/atom/browser/auto_updater_linux.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/browser/auto_updater.h" - -namespace auto_updater { - -// static -void AutoUpdater::SetFeedURL(const std::string& url) { -} - -// static -void AutoUpdater::CheckForUpdates() { -} - -} // namespace auto_updater diff --git a/atom/browser/auto_updater_mac.mm b/atom/browser/auto_updater_mac.mm index 42ee8413632e..a55cdd281265 100644 --- a/atom/browser/auto_updater_mac.mm +++ b/atom/browser/auto_updater_mac.mm @@ -12,9 +12,6 @@ #include "base/bind.h" #include "base/time/time.h" #include "base/strings/sys_string_conversions.h" -#include "atom/browser/auto_updater_delegate.h" - -#include namespace auto_updater { @@ -23,20 +20,12 @@ namespace { // The gloal SQRLUpdater object. SQRLUpdater* g_updater = nil; -void RelaunchToInstallUpdate() { - [[g_updater relaunchToInstallUpdate] subscribeError:^(NSError* error) { - AutoUpdaterDelegate* delegate = AutoUpdater::GetDelegate(); - if (delegate) - delegate->OnError(base::SysNSStringToUTF8(error.localizedDescription)); - }]; -} - } // namespace // static void AutoUpdater::SetFeedURL(const std::string& feed) { if (g_updater == nil) { - AutoUpdaterDelegate* delegate = GetDelegate(); + Delegate* delegate = GetDelegate(); if (!delegate) return; @@ -67,7 +56,7 @@ void AutoUpdater::SetFeedURL(const std::string& feed) { // static void AutoUpdater::CheckForUpdates() { - AutoUpdaterDelegate* delegate = GetDelegate(); + Delegate* delegate = GetDelegate(); if (!delegate) return; @@ -86,8 +75,7 @@ void AutoUpdater::CheckForUpdates() { base::SysNSStringToUTF8(update.releaseNotes), base::SysNSStringToUTF8(update.releaseName), base::Time::FromDoubleT(update.releaseDate.timeIntervalSince1970), - base::SysNSStringToUTF8(update.updateURL.absoluteString), - base::Bind(RelaunchToInstallUpdate)); + base::SysNSStringToUTF8(update.updateURL.absoluteString)); } else { // When the completed event is sent with no update, then we know there // is no update available. @@ -100,4 +88,12 @@ void AutoUpdater::CheckForUpdates() { }]; } +void AutoUpdater::QuitAndInstall() { + [[g_updater relaunchToInstallUpdate] subscribeError:^(NSError* error) { + Delegate* delegate = AutoUpdater::GetDelegate(); + if (delegate) + delegate->OnError(base::SysNSStringToUTF8(error.localizedDescription)); + }]; +} + } // namespace auto_updater diff --git a/atom/browser/auto_updater_win.cc b/atom/browser/auto_updater_win.cc deleted file mode 100644 index 00c95d0d45d7..000000000000 --- a/atom/browser/auto_updater_win.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/browser/auto_updater.h" - -namespace auto_updater { - -// static -void AutoUpdater::SetFeedURL(const std::string& url) { -} - -// static -void AutoUpdater::CheckForUpdates() { -} - -} // namespace auto_updater diff --git a/filenames.gypi b/filenames.gypi index f6a7dbd08680..e6d180d652e1 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -115,10 +115,7 @@ 'atom/browser/api/save_page_handler.h', 'atom/browser/auto_updater.cc', 'atom/browser/auto_updater.h', - 'atom/browser/auto_updater_delegate.h', - 'atom/browser/auto_updater_linux.cc', 'atom/browser/auto_updater_mac.mm', - 'atom/browser/auto_updater_win.cc', 'atom/browser/atom_access_token_store.cc', 'atom/browser/atom_access_token_store.h', 'atom/browser/atom_browser_client.cc', From aeafc46dede25f05e28ca87efa961637e6118011 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 15:50:55 +0800 Subject: [PATCH 320/738] Keep compatibility with old API style --- atom/browser/api/atom_api_auto_updater.cc | 5 ++++- docs/api/auto-updater.md | 13 ++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/atom/browser/api/atom_api_auto_updater.cc b/atom/browser/api/atom_api_auto_updater.cc index 1b7c0cee7d96..1c80f73f7a7d 100644 --- a/atom/browser/api/atom_api_auto_updater.cc +++ b/atom/browser/api/atom_api_auto_updater.cc @@ -8,6 +8,7 @@ #include "atom/browser/browser.h" #include "atom/browser/native_window.h" #include "atom/browser/window_list.h" +#include "atom/common/native_mate_converters/callback.h" #include "atom/common/node_includes.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" @@ -68,7 +69,9 @@ void AutoUpdater::OnUpdateDownloaded(const std::string& release_notes, const std::string& release_name, const base::Time& release_date, const std::string& url) { - Emit("update-downloaded", release_notes, release_name, release_date, url); + Emit("update-downloaded", release_notes, release_name, release_date, url, + // Keep compatibility with old APIs. + base::Bind(&AutoUpdater::QuitAndInstall, base::Unretained(this))); } void AutoUpdater::OnWindowAllClosed() { diff --git a/docs/api/auto-updater.md b/docs/api/auto-updater.md index ea731cd869a9..55c605762e39 100644 --- a/docs/api/auto-updater.md +++ b/docs/api/auto-updater.md @@ -136,10 +136,8 @@ Returns: * `releaseName` String * `releaseDate` Date * `updateUrl` String -* `quitAndUpdate` Function -Emitted when an update has been downloaded. Calling `quitAndUpdate()` will -restart the application and install the update. +Emitted when an update has been downloaded. ## Methods @@ -149,10 +147,15 @@ The `autoUpdater` object has the following methods: * `url` String -Set the `url` and initialize the auto updater. The `url` cannot be changed +Sets the `url` and initialize the auto updater. The `url` cannot be changed once it is set. ### `autoUpdater.checkForUpdates()` -Ask the server whether there is an update. You must call `setFeedUrl` before +Asks the server whether there is an update. You must call `setFeedUrl` before using this API. + +### `autoUpdater.quitAndUpdate()` + +Restarts the app and install the update after it has been downloaded. It should +only be called after `update-downloaded` has been emitted. From 79e593aca67beea3950852eb101f140972db44b1 Mon Sep 17 00:00:00 2001 From: Alexandru Bau Date: Fri, 23 Oct 2015 11:37:51 +0300 Subject: [PATCH 321/738] Updated docs Updated docs to better understand how to use electron-rebuild on Windows --- docs/tutorial/using-native-node-modules.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/tutorial/using-native-node-modules.md b/docs/tutorial/using-native-node-modules.md index 491415b900ac..305f30e02ea0 100644 --- a/docs/tutorial/using-native-node-modules.md +++ b/docs/tutorial/using-native-node-modules.md @@ -31,8 +31,13 @@ which handles the manual steps of downloading headers and building native module ```sh npm install --save-dev electron-rebuild -# Every time you run npm install, run this +# Every time you run "npm install", run this + +# Linux or Mac node ./node_modules/.bin/electron-rebuild + +# Windows +./node_modules/.bin/electron-rebuild ``` ### The npm Way From 96130dd4c2dc3937e76b9bb77025aca61f531d85 Mon Sep 17 00:00:00 2001 From: Alexandru Bau Date: Fri, 23 Oct 2015 14:15:39 +0300 Subject: [PATCH 322/738] Updated docs Updated docs to better understand how to use electron-rebuild on all platforms --- docs/tutorial/using-native-node-modules.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/tutorial/using-native-node-modules.md b/docs/tutorial/using-native-node-modules.md index 305f30e02ea0..6954fc64b1a1 100644 --- a/docs/tutorial/using-native-node-modules.md +++ b/docs/tutorial/using-native-node-modules.md @@ -32,11 +32,6 @@ which handles the manual steps of downloading headers and building native module npm install --save-dev electron-rebuild # Every time you run "npm install", run this - -# Linux or Mac -node ./node_modules/.bin/electron-rebuild - -# Windows ./node_modules/.bin/electron-rebuild ``` From fae2c7bc7a129e86b17e8222b61e3c6aca96afbd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 19:41:54 +0800 Subject: [PATCH 323/738] win: Make auto-updater really work Apparently that PR was never tested. --- .../lib/auto-updater/auto-updater-win.coffee | 55 ++++++------- .../auto-updater/squirrel-update-win.coffee | 80 +++++++++++-------- 2 files changed, 71 insertions(+), 64 deletions(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee index 764f76a2253f..a9a61d8efe3f 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee @@ -1,45 +1,42 @@ +app = require 'app' +url = require 'url' {EventEmitter} = require 'events' -SquirrelUpdate = require './auto-updater/squirrel-update-win' -app = require 'app' -url = require 'url' + +squirrelUpdate = require './squirrel-update-win' class AutoUpdater extends EventEmitter - quitAndInstall: -> - SquirrelUpdate.processStart -> - app.quit() + squirrelUpdate.processStart() + app.quit() setFeedUrl: (updateUrl) -> - # set feed URL only when it hasn't been set before - unless @updateUrl - @updateUrl = updateUrl + @updateUrl = updateUrl checkForUpdates: -> - throw new Error('Update URL is not set') unless @updateUrl + return @emitError 'Update URL is not set' unless @updateUrl + return @emitError 'Can not find Squirrel' unless squirrelUpdate.supported() @emit 'checking-for-update' - unless SquirrelUpdate.supported() - @emit 'update-not-available' - return - - SquirrelUpdate.download (error, update) => - if error? - @emit 'update-not-available' - return - - unless update? - @emit 'update-not-available' - return + squirrelUpdate.download @updateUrl, (error, update) => + return @emitError error if error? + return @emit 'update-not-available' unless update? @emit 'update-available' - SquirrelUpdate.update @updateUrl, (error) => - if error? - @emit 'update-not-available' - return + squirrelUpdate.update @updateUrl, (error) => + return @emitError error if error? - # info about the newly installed version and a function any of the event listeners can call to restart the application - @emit 'update-downloaded', {}, update.releaseNotes, update.version, new Date(), @updateUrl, => @quitAndInstall() + {releaseNotes, version} = update + # Following information is not available on Windows, so fake them. + date = new Date + url = @updateUrl -module.exports = new AutoUpdater() + @emit 'update-downloaded', {}, releaseNotes, version, date, url, => @quitAndInstall() + + # Private: Emit both error object and message, this is to keep compatibility + # with Old APIs. + emitError: (message) -> + @emit 'error', new Error(message), message + +module.exports = new AutoUpdater diff --git a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee index 95d9e1465d8a..ed302124e52e 100644 --- a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee +++ b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee @@ -1,57 +1,67 @@ -ChildProcess = require 'child_process' -fs = require 'fs' -path = require 'path' +fs = require 'fs' +path = require 'path' +{spawn} = require 'child_process' -appFolder = path.dirname process.execPath # i.e. my-app/app-0.1.13/ -rootApplicationFolder = path.resolve appFolder, '..' # i.e. my-app/ -updateDotExe = path.join rootApplicationFolder, 'Update.exe' -exeName = path.basename process.execPath +appFolder = path.dirname process.execPath # i.e. my-app/app-0.1.13/ +updateExe = path.resolve appFolder, '..', 'Update.exe' # i.e. my-app/Update.exe +exeName = path.basename process.execPath # Spawn a command and invoke the callback when it completes with an error # and the output from standard out. -spawnUpdate = (args, callback) -> - stdout = '' - +spawnUpdate = (args, detached, callback) -> try - spawnedProcess = ChildProcess.spawn(updateDotExe, args) + spawnedProcess = spawn updateExe, args, {detached} catch error - # Spawn can throw an error - process.nextTick -> callback?(error, stdout) + # Shouldn't happen, but still guard it. + process.nextTick -> callback error return + stdout = '' + stderr = '' spawnedProcess.stdout.on 'data', (data) -> stdout += data + spawnedProcess.stderr.on 'data', (data) -> stderr += data - error = null - spawnedProcess.on 'error', (processError) -> error ?= processError - spawnedProcess.on 'close', (code, signal) -> - error ?= new Error("Command failed: #{signal ? code}") if code isnt 0 - error?.code ?= code - error?.stdout ?= stdout - callback?(error, stdout) + errorEmitted = false + spawnedProcess.on 'error', (error) -> + errorEmitted = true + callback error + spawnedProcess.on 'exit', (code, signal) -> + # We may have already emitted an error. + return if errorEmitted -processStart = (callback) -> - spawnUpdate(['--processStart', exeName], callback) + # Process terminated with error. + if code isnt 0 + return callback "Command failed: #{signal ? code}\n#{stderr}" -download = (callback) -> - spawnUpdate ['--download', @updateUrl], (error, stdout) -> + # Success. + callback null, stdout + +# Start an instance of the installed app. +exports.processStart = (callback) -> + spawnUpdate ['--processStart', exeName], true, -> + +# Download the releases specified by the URL and write new results to stdout. +exports.download = (updateUrl, callback) -> + spawnUpdate ['--download', updateUrl], false, (error, stdout) -> return callback(error) if error? try # Last line of output is the JSON details about the releases - json = stdout.trim().split('\n').pop() + json = stdout.trim().split('\n').pop() update = JSON.parse(json)?.releasesToApply?.pop?() - catch error - error.stdout = stdout - return callback(error) + catch + return callback "Invalid result:\n#{stdout}" - callback(null, update) + callback null, update -update = (updateUrl, callback) -> - spawnUpdate ['--update', updateUrl], callback +# Update the application to the latest remote version specified by URL. +exports.update = (updateUrl, callback) -> + spawnUpdate ['--update', updateUrl], false, callback # Is the Update.exe installed with the current application? exports.supported = -> - fs.accessSync(updateDotExe, fs.R_OK) -exports.processStart = processStart -exports.download = download -exports.update = update + try + fs.accessSync updateExe, fs.R_OK + return true + catch + return false From 88b05cff3e21627fcf0ed1a7223cf325f68cd48a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 20:11:59 +0800 Subject: [PATCH 324/738] docs: auto-updater on Windows --- docs/api/auto-updater.md | 116 ++++++++------------------------------- 1 file changed, 24 insertions(+), 92 deletions(-) diff --git a/docs/api/auto-updater.md b/docs/api/auto-updater.md index 55c605762e39..7649f0f10489 100644 --- a/docs/api/auto-updater.md +++ b/docs/api/auto-updater.md @@ -1,106 +1,31 @@ # autoUpdater -**This module has only been implemented for OS X.** +This module provides an interface for the `Squirrel` auto-updater framework. -Check out [atom/grunt-electron-installer](https://github.com/atom/grunt-electron-installer) -to build a Windows installer for your app. +## Platform notices -The `auto-updater` module is a simple wrapper around the -[Squirrel.Mac](https://github.com/Squirrel/Squirrel.Mac) framework. +Though `autoUpdater` provides an uniform API for different platforms, there are +still some subtle differences on each platform. -Squirrel.Mac requires that your `.app` folder is signed using the -[codesign](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/codesign.1.html) -utility for updates to be installed. +### OS X -## Squirrel +On OS X the `autoUpdater` module is built upon [Squirrel.Mac][squirrel-mac], you +don't need any special setup to make it work. For server-side requirements, you +can read [Server Support][server-support]. -Squirrel is an OS X framework focused on making application updates **as safe -and transparent as updates to a website**. +### Windows -Instead of publishing a feed of versions from which your app must select, -Squirrel updates to the version your server tells it to. This allows you to -intelligently update your clients based on the request you give to Squirrel. +On Windows you have to install your app into user's machine before you can use +the auto-updater, it is recommended to use [grunt-electron-installer][installer] +module to generate a Windows installer. -Your request can include authentication details, custom headers or a request -body so that your server has the context it needs in order to supply the most -suitable update. +The server-side setup is also different from OS X, you can read the documents of +[Squirrel.Windows][squirrel-windows] to get more details. -The update JSON Squirrel requests should be dynamically generated based on -criteria in the request and whether an update is required. Squirrel relies -on server-side support to determine whether an update is required. See -[Server Support](#server-support). +### Linux -Squirrel's installer is designed to be fault tolerant and ensures that any -updates installed are valid. - -## Update Requests - -Squirrel is indifferent to the request the client application provides for -update checking. `Accept: application/json` is added to the request headers -because Squirrel is responsible for parsing the response. - -For the requirements imposed on the responses and the body format of an update -response, see [Server Support](#server-support). - -Your update request must *at least* include a version identifier so that the -server can determine whether an update for this specific version is required. It -may also include other identifying criteria, such as operating system version or -username, to allow the server to deliver as fine grained an update as you -would like. - -How you include the version identifier or other criteria is specific to the -server that you are requesting updates from. A common approach is to use query -parameters, like this: - -```javascript -// In the main process -var app = require('app'); -var autoUpdater = require('auto-updater'); -autoUpdater.setFeedUrl('http://mycompany.com/myapp/latest?version=' + app.getVersion()); -``` - -## Server Support - -Your server should determine whether an update is required based on the -[Update Request](#update-requests) your client issues. - -If an update is required, your server should respond with a status code of -[200 OK](http://tools.ietf.org/html/rfc2616#section-10.2.1) and include the -[update JSON](#update-json-format) in the body. Squirrel **will** download and -install this update, even if the version of the update is the same as the -currently running version. To save redundantly downloading the same version -multiple times your server must not inform the client to update. - -If no update is required your server must respond with a status code of -[204 No Content](http://tools.ietf.org/html/rfc2616#section-10.2.5). Squirrel -will check for an update again at the interval you specify. - -## Update JSON Format - -When an update is available, Squirrel expects the following schema in response -to the update request provided: - -```json -{ - "url": "http://mycompany.com/myapp/releases/myrelease", - "name": "My Release Name", - "notes": "Theses are some release notes innit", - "pub_date": "2013-09-18T12:29:53+01:00" -} -``` - -The only required key is "url"; the others are optional. - -Squirrel will request "url" with `Accept: application/zip` and only supports -installing ZIP updates. If future update formats are supported their MIME type -will be added to the `Accept` header so that your server can return the -appropriate format. - -`pub_date` (if present) must be formatted according to ISO 8601. - -## Update server implementations - -[Nuts](https://github.com/GitbookIO/nuts) is an open source implementation of the update server described above, it integrates beautifully with GitHub releases. Nuts manages downloads and updates, it’s compatible with `Squirrel.Mac` and `Squirrel.Windows` so you get cross-platform support out of the box. +There is not built-in support for auto-updater on Linux, it is recommended to +use the distribution's package manager to update your app. ## Events @@ -139,6 +64,8 @@ Returns: Emitted when an update has been downloaded. +On Windows only `releaseName` is available. + ## Methods The `autoUpdater` object has the following methods: @@ -159,3 +86,8 @@ using this API. Restarts the app and install the update after it has been downloaded. It should only be called after `update-downloaded` has been emitted. + +[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 From 30ec7fdeed715f4a8e234bb2557497081f8d1171 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 23 Oct 2015 20:32:02 +0800 Subject: [PATCH 325/738] Bump v0.34.1 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/atom.gyp b/atom.gyp index d6d9e2e2268e..d4b4f67b6310 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.34.0', + 'version%': '0.34.1', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 01c4bc7e6281..aff46850004f 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.34.0 + 0.34.1 CFBundleShortVersionString - 0.34.0 + 0.34.1 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 5a25256831cc..3adf196e8ba5 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,34,0,0 - PRODUCTVERSION 0,34,0,0 + FILEVERSION 0,34,1,0 + PRODUCTVERSION 0,34,1,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.34.0" + VALUE "FileVersion", "0.34.1" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.34.0" + VALUE "ProductVersion", "0.34.1" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 8351fff18ca2..1f8b8dec714f 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 34 -#define ATOM_PATCH_VERSION 0 +#define ATOM_PATCH_VERSION 1 #define ATOM_VERSION_IS_RELEASE 1 From 8555aea40f300418b957509631e8c1a065925e70 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sat, 24 Oct 2015 05:57:37 +0900 Subject: [PATCH 326/738] Update as upstream --- docs-translations/ko-KR/api/app.md | 64 +++++++++-- docs-translations/ko-KR/api/auto-updater.md | 108 +++++------------- .../ko-KR/api/chrome-command-line-switches.md | 4 +- docs-translations/ko-KR/api/crash-reporter.md | 3 +- docs-translations/ko-KR/api/session.md | 2 + .../tutorial/using-native-node-modules.md | 2 +- 6 files changed, 92 insertions(+), 91 deletions(-) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index 498fbb59bfcd..d1263d00abc3 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -74,11 +74,11 @@ Returns: 사용자가 어플리케이션을 통해 파일을 열고자 할 때 발생하는 이벤트입니다. -`open-file` 이벤트는 보통 어플리케이션이 열려 있을 때와 OS가 파일을 열기 위해 어플리케이션을 재사용할 때 발생합니다. -`open-file` 이벤트는 파일을 dock에 떨어트릴 때와 어플리케이션이 실행되기 전에도 발생합니다. -이 경우엔 확실히 `open-file` 이벤트 리스너를 어플리케이션이 시작하기 전에 설정해 놓았는지 확인해야 합니다. (`ready` 이벤트가 발생하기 전에) +`open-file` 이벤트는 보통 어플리케이션이 열려 있을 때 OS가 파일을 열기 위해 어플리케이션을 재사용할 때 발생합니다. +이 이벤트는 파일을 dock에 떨어트릴 때, 어플리케이션이 실행되기 전에도 발생합니다. +따라서 이 이벤트를 제대로 처리하려면 `open-file` 이벤트 핸들러를 어플리케이션이 시작하기 전에 등록해 놓았는지 확실히 확인해야 합니다. (`ready` 이벤트가 발생하기 전에) -이 이벤트를 처리하려면 반드시 `event.preventDefault()`를 호출해야 합니다. +이 이벤트를 처리할 땐 반드시 `event.preventDefault()`를 호출해야 합니다. ### Event: 'open-url' @@ -89,9 +89,9 @@ Returns: 유저가 어플리케이션을 통해 URL을 열고자 할 때 발생하는 이벤트입니다. -어플리케이션에서 URL을 열기 위해선 반드시 URL 스킴이 등록되어 있어야 합니다. +어플리케이션에서 URL을 열기 위해 반드시 URL 스킴이 등록되어 있어야 합니다. -이 이벤트를 처리하려면 반드시 `event.preventDefault()`를 호출해야 합니다. +이 이벤트를 처리할 땐 반드시 `event.preventDefault()`를 호출해야 합니다. ### Event: 'activate' _OS X_ @@ -245,7 +245,7 @@ npm 모듈 규칙에 따라 대부분의 경우 `package.json`의 `name` 필드 `url`의 프록시 정보를 해석합니다. `callback`은 요청이 수행되었을 때 `callback(proxy)` 형태로 호출됩니다. -### `app.addRecentDocument(path)` +### `app.addRecentDocument(path)` _OS X_ _Windows_ * `path` String @@ -254,7 +254,7 @@ npm 모듈 규칙에 따라 대부분의 경우 `package.json`의 `name` 필드 이 목록은 OS에 의해 관리됩니다. 최근 문서 목록은 Windows의 경우 작업 표시줄에서 찾을 수 있고, OS X의 경우 dock 메뉴에서 찾을 수 있습니다. -### `app.clearRecentDocuments()` +### `app.clearRecentDocuments()` _OS X_ _Windows_ 최근 문서 목록을 모두 비웁니다. @@ -288,6 +288,52 @@ Windows에서 사용할 수 있는 JumpList의 [Tasks][tasks] 카테고리에 `t 그러나 기업 네트워크가 잘못 구성된 경우 종종 작업에 실패할 수 있습니다. 이때 이 메서드를 통해 모든 URL을 허용할 수 있습니다. +### `app.makeSingleInstance(callback)` + +* `callback` Function + +현재 어플리케이션을 **Single Instance Application**으로 만들어줍니다. +이 메서드는 어플리케이션이 여러 번 실행됐을 때 다중 인스턴스가 생성되는 대신 한 개의 주 인스턴스만 유지되도록 만들 수 있습니다. +이때 중복 생성된 인스턴스는 주 인스턴스에 신호를 보내고 종료됩니다. + +`callback`은 주 인스턴스가 생성된 이후 또 다른 인스턴스가 생성됐을 때 `callback(argv, workingDirectory)` 형식으로 호출됩니다. +`argv`는 두 번째 인스턴스의 명령줄 인수이며 `workingDirectory`는 현재 작업중인 디렉터리입니다. +보통 대부분의 어플리케이션은 이러한 콜백이 호출될 때 주 윈도우창을 포커스하고 최소화되어있으면 창 복구를 실행합니다. + +`callback`은 `app`의 `ready` 이벤트가 발생한 후 실행됨을 보장합니다. + +이 메서드는 현재 실행된 어플리케이션이 주 인스턴스인 경우 `false`를 반환하고 어플리케이션의 로드가 계속 진행 되도록 합니다. +그리고 두 번째 중복된 인스턴스 생성인 경우 `true`를 반환합니다. (다른 인스턴스에 인수가 전달됬을 때) +이 불리언 값을 통해 중복 생성된 인스턴스는 즉시 종료시켜야 합니다. + +OS X에선 사용자가 Finder에서 어플리케이션의 두 번째 인스턴스를 열려고 했을 때 자동으로 **Single Instance**화 하고 `open-file`과 `open-url` 이벤트를 발생시킵니다. +그러나 사용자가 어플리케이션을 CLI 터미널에서 실행하면 운영체제 시스템의 싱글 인스턴스 메커니즘이 무시되며 그대로 중복 실행됩니다. +따라서 OS X에서도 이 메서드를 통해 확실히 중복 실행을 방지하는 것이 좋습니다. + +다음 예제는 두 번째 인스턴스가 생성되었을 때 중복된 인스턴스를 종료하고 주 어플리케이션 인스턴스의 윈도우창을 활성화 시키는 예제입니다: + +```javascript +var myWindow = null; + +var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) { + // 어플리케이션을 중복 실행했습니다. 주 어플리케이션 인스턴스를 활성화 합니다. + if (myWindow) { + if (myWindow.isMinimized()) myWindow.restore(); + myWindow.focus(); + } + return true; +}); + +if (shouldQuit) { + app.quit(); + return; +} + +// 윈도우창을 생성하고 각종 리소스를 로드하고 작업합니다.. +app.on('ready', function() { +}); +``` + ### `app.commandLine.appendSwitch(switch[, value])` Chrominum의 명령줄에 스위치를 추가합니다. `value`는 추가적인 값을 뜻하며 옵션입니다. @@ -297,7 +343,7 @@ Chrominum의 명령줄에 스위치를 추가합니다. `value`는 추가적인 ### `app.commandLine.appendArgument(value)` -Chrominum의 명령줄에 인자를 추가합니다. 인자는 올바르게 인용됩니다. +Chrominum의 명령줄에 인수를 추가합니다. 인수는 올바르게 인용됩니다. **참고:** 이 메서드는 `process.argv`에 영향을 주지 않습니다. diff --git a/docs-translations/ko-KR/api/auto-updater.md b/docs-translations/ko-KR/api/auto-updater.md index 98bd65dd0a86..b940bb536181 100644 --- a/docs-translations/ko-KR/api/auto-updater.md +++ b/docs-translations/ko-KR/api/auto-updater.md @@ -1,86 +1,28 @@ # autoUpdater -**이 모듈은 현재 OS X에서만 사용할 수 있습니다.** +이 모듈은 `Squirrel` 자동 업데이트 프레임워크의 인터페이스를 제공합니다. -Windows 인스톨러를 생성하려면 [atom/grunt-electron-installer](https://github.com/atom/grunt-electron-installer)를 참고하세요. +## 플랫폼별 참고 사항 -`auto-updater` 모듈은 [Squirrel.Mac](https://github.com/Squirrel/Squirrel.Mac) 프레임워크의 간단한 wrapper 입니다. +`autoUpdater`는 기본적으로 모든 플랫폼에 대해 같은 API를 제공하지만, 여전히 플랫폼별로 약간씩 다른 점이 있습니다. -Squirrel.Mac은 업데이트 설치를 위해 `.app` 폴더에 -[codesign](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/codesign.1.html) -툴을 사용한 서명을 요구합니다. +### OS X -## Squirrel +OS X에선 `auto-updater` 모듈이 [Squirrel.Mac][squirrel-mac]를 기반으로 작동합니다. +따라서 이 모듈을 작동시키기 위해 특별히 준비해야 할 작업은 없습니다. +서버 사이드 요구 사항은 [서버 지원][server-support]을 참고하세요. -Squirrel은 어플리케이션이 **안전하고 투명한 업데이트**를 제공할 수 있도록 하는데 초점이 맞춰진 OS X 프레임워크입니다. +### Windows -Squirrel은 사용자에게 어플리케이션의 업데이트를 알릴 필요 없이 자동으로 서버가 지시하는 버전을 받아 어플리케이션을 업데이트합니다. -지능적으로 클라이언트 어플리케이션을 업데이트 할 수 있습니다. +Windows에선 `auto-updater` 모듈을 사용하기 전에 어플리케이션을 사용자의 장치에 설치해야 합니다. +[grunt-electron-installer][installer]를 사용하여 어플리케이션 셋업을 만드는 것을 권장합니다. -업데이트 요청은 커스텀 헤더 또는 요청 본문에 인증 정보를 포함시킬 수 있습니다. -이에 따라 서버에선 이러한 요청을 분석 처리하여 사용자에게 적당한 업데이트를 제공할 수 있습니다. +서버 사이드 요구 사항 또한 OS X와 다르게 적용됩니다. 자세한 내용은 [Squirrel.Windows][squirrel-windows]를 참고하세요. -Squirrel JSON 업데이트 요청시 처리는 반드시 어떤 업데이트가 필요한지 요청의 기준에 맞춰 동적으로 생성되어야 합니다. -Squirrel은 사용해야 하는 업데이트 선택하는 과정을 서버에 의존합니다. [서버 지원](#서버-지원)을 참고하세요. +### Linux -Squirrel의 인스톨러는 오류에 관대하게 설계되었습니다. 그리고 업데이트가 유효한지 확인합니다. - -## 업데이트 요청 - -Squirrel은 클라이언트 어플리케이션이 업데이트 확인을 위해 제공하는 요청을 무시합니다. -Squirrel이 응답을 분석할 수 있어야하기 때문에 요청 헤더에 `Accept: application/json` 헤더가 추가됩니다. - -업데이트 응답과 본문 포맷에 대한 요구 사항은 [서버 지원](#서버-지원)를 참고하세요. - -업데이트 요청에는 서버가 해당 어플리케이션이 어떤 버전을 사용해야 하는지 판단하기 위해 *반드시* 버전 식별자를 포함시켜야 합니다. -추가로 OS 버전, 사용자 이름 같은 다른 식별 기준을 포함하여 서버에서 적합한 어플리케이션을 제공할 수 있도록 할 수 있습니다. - -버전 식별자와 다른 기준을 특정하는 업데이트 요청 폼을 서버로 전달하기 위한 공통적인 방법으로 쿼리 인자를 사용하는 방법이 있습니다: - -```javascript -// In the main process -var app = require('app'); -var autoUpdater = require('auto-updater'); -autoUpdater.setFeedUrl('http://mycompany.com/myapp/latest?version=' + app.getVersion()); -``` - -## 서버 지원 - -업데이트를 제공하는 서버는 반드시 클라이언트로부터 받은 [업데이트 요청](#업데이트-요청)을 기반으로 업데이트를 처리할 수 있어야 합니다. - -만약 업데이트 요청이 들어오면 서버는 반드시 [200 OK](http://tools.ietf.org/html/rfc2616#section-10.2.1) 상태 코드를 포함한 -[업데이트 JSON](#update-json-format)을 본문으로 보내야 합니다. -이 응답을 받으면 Squirrel은 이 업데이트를 다운로드할 것입니다. 참고로 현재 설치된 버전과 서버에서 받아온 새로운 버전이 같아도 상관하지 않고 무조건 받습니다. -업데이트시 버전 중복을 피하려면 서버에서 클라이언트 업데이트 요청에 대해 통보하지 않으면 됩니다. - -만약 따로 업데이트가 없다면 [204 No Content](http://tools.ietf.org/html/rfc2616#section-10.2.5) 상태 코드를 반환해야 합니다. -Squirrel은 지정한 시간이 지난 후 다시 업데이트를 확인합니다. - -## JSON 포맷 업데이트 - -업데이트가 사용 가능한 경우 Squirrel은 다음과 같은 구조의 json 데이터를 응답으로 받습니다: - -```json -{ - "url": "http://mycompany.com/myapp/releases/myrelease", - "name": "My Release Name", - "notes": "Theses are some release notes innit", - "pub_date": "2013-09-18T12:29:53+01:00" -} -``` - -응답 json 데이터에서 "url" 키는 필수적으로 포함해야 하고 다른 키들은 옵션입니다. - -Squirrel은 "url"로 `Accept: application/zip` 헤더와 함께 업데이트 zip 파일을 요청합니다. -향후 업데이트 포맷에 대해 서버에서 적절한 포맷을 반환할 수 있도록 MIME 타입을 `Accept` 헤더에 담아 요청합니다. - -`pub_date`은 ISO 8601 표준에 따라 포맷된 날짜입니다. - -## 업데이트 서버 구현 - -[Nuts](https://github.com/GitbookIO/nuts)는 위에서 설명한 업데이트 서버의 오픈 소스 구현입니다. -이 구현은 Github 릴리즈와 완벽하게 통합되어 있습니다. Nuts는 `Squirrel.Mac`과 `Squirrel.Windows`를 지원하고 다운로드와 업데이트를 관리합니다. -이 구현을 사용하면 cross-platform 지원을 신경 쓸 필요가 없습니다. +Linux는 따로 `auto-updater`를 지원하지 않습니다. +각 배포판의 패키지 관리자를 통해 어플리케이션 업데이트를 제공하는 것을 권장합니다. ## Events @@ -88,10 +30,11 @@ Squirrel은 "url"로 `Accept: application/zip` 헤더와 함께 업데이트 zip ### Event: 'error' -* `event` Event -* `message` String +Returns: -업데이트시 에러가 나면 발생하는 이벤트입니다. +* `error` Error + +업데이트에 문제가 생기면 발생하는 이벤트입니다. ### Event: 'checking-for-update' @@ -107,14 +50,15 @@ Squirrel은 "url"로 `Accept: application/zip` 헤더와 함께 업데이트 zip ### Event: 'update-downloaded' +Returns: + * `event` Event * `releaseNotes` String * `releaseName` String * `releaseDate` Date * `updateUrl` String -* `quitAndUpdate` Function -업데이트의 다운로드가 완료되었을 때 발생하는 이벤트입니다. `quitAndUpdate()`를 호출하면 어플리케이션을 종료하고 업데이트를 설치합니다. +업데이트의 다운로드가 완료되었을 때 발생하는 이벤트입니다. ## Methods @@ -129,3 +73,13 @@ Squirrel은 "url"로 `Accept: application/zip` 헤더와 함께 업데이트 zip ### `autoUpdater.checkForUpdates()` 서버에 새로운 업데이트가 있는지 요청을 보내 확인합니다. API를 사용하기 전에 `setFeedUrl`를 호출해야 합니다. + +### `autoUpdater.quitAndUpdate()` + +어플리케이션을 다시 시작하고 다운로드된 업데이트를 설치합니다. +이 메서드는 `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 diff --git a/docs-translations/ko-KR/api/chrome-command-line-switches.md b/docs-translations/ko-KR/api/chrome-command-line-switches.md index c3ef6ee33b7a..5b055c49ec9d 100644 --- a/docs-translations/ko-KR/api/chrome-command-line-switches.md +++ b/docs-translations/ko-KR/api/chrome-command-line-switches.md @@ -94,8 +94,8 @@ SSL 암호화를 비활성화할 대상 목록을 지정합니다. (`,`로 구 Chromium의 로그를 콘솔에 출력합니다. -이 스위치는 어플리케이션이 로드되기 전에 인식 되므로 `app.commandLine.appendSwitch` 메서드에선 사용할 수 없습니다. -하지만 `ELECTRON_ENABLE_LOGGING` 환경 변수를 설정하면 본 스위치와 같은 효과를 낼 수 있습니다. +이 스위치는 어플리케이션이 로드되기 전에 분석 되므로 `app.commandLine.appendSwitch` 메서드에선 사용할 수 없습니다. +하지만 `ELECTRON_ENABLE_LOGGING` 환경 변수를 설정하면 본 스위치를 지정한 것과 같은 효과를 낼 수 있습니다. ## --v=`log_level` diff --git a/docs-translations/ko-KR/api/crash-reporter.md b/docs-translations/ko-KR/api/crash-reporter.md index 3a7bc35f0982..88cd3b82f301 100644 --- a/docs-translations/ko-KR/api/crash-reporter.md +++ b/docs-translations/ko-KR/api/crash-reporter.md @@ -54,11 +54,10 @@ crashReporter.start({ Crash Reporter는 다음과 같은 데이터를 `submitUrl`에 `POST` 방식으로 전송합니다: -* `rept` String - 예시 'electron-crash-service' * `ver` String - Electron의 버전 * `platform` String - 예시 'win32' * `process_type` String - 예시 'renderer' -* `ptime` Number +* `guid` String - e.g. '5e1286fc-da97-479e-918b-6bfb0c3d1c72' * `_version` String - `package.json`내의 `version` 필드 * `_productName` String - Crash Reporter의 `options` 객체에서 정의한 제품명. * `prod` String - 기본 제품의 이름. 이 경우 Electron으로 표시됩니다. diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index 96d38dda5d62..b5cd79cbb93e 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -147,6 +147,8 @@ win.webContents.on('did-finish-load', function() { 세션에 사용할 프록시 `config`를 분석하고 프록시를 적용합니다. +세션에 사용할 프록시는 `config`가 PAC 주소일 경우 그대로 적용하고, 다른 형식일 경우 다음 규칙에 따라 적용합니다. + ``` config = scheme-proxies[";"] scheme-proxies = ["="] diff --git a/docs-translations/ko-KR/tutorial/using-native-node-modules.md b/docs-translations/ko-KR/tutorial/using-native-node-modules.md index 6a0c67770b0b..0691fefc864d 100644 --- a/docs-translations/ko-KR/tutorial/using-native-node-modules.md +++ b/docs-translations/ko-KR/tutorial/using-native-node-modules.md @@ -28,7 +28,7 @@ Electron도 이 모듈을 통해 포팅된 네이티브 모듈을 사용할 수 npm install --save-dev electron-rebuild # 필요한 네이티브 모듈을 `npm install`로 설치한 후 다음 명령을 실행하세요: -node ./node_modules/.bin/electron-rebuild +./node_modules/.bin/electron-rebuild ``` ### `npm`을 이용한 방법 From 8e5c1a505e985d5234ec649b9e723e8ca690aaab Mon Sep 17 00:00:00 2001 From: Jhen Date: Sun, 25 Oct 2015 01:34:17 +0800 Subject: [PATCH 327/738] Update tutorial/quick-start.md for zh-TW docs --- .../zh-TW/tutorial/quick-start.md | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/docs-translations/zh-TW/tutorial/quick-start.md b/docs-translations/zh-TW/tutorial/quick-start.md index 4655549167c1..068138587f1d 100644 --- a/docs-translations/zh-TW/tutorial/quick-start.md +++ b/docs-translations/zh-TW/tutorial/quick-start.md @@ -30,7 +30,7 @@ Electron 的用戶擁有在網頁中呼叫 Node.js APIs 的能力,允許低級 在網頁中,是不允許呼叫原生 GUI 相關 APIs 因為管理原生 GUI 資源在網頁上是非常危險而且容易造成資源洩露。 如果你想要在網頁中呼叫 GUI 相關的 APIs 的操作,網頁的渲染行程必須與主行程進行通訊,請求主行程進行相關的操作。 -在 Electron ,我們提供用於在主行程與渲染行程之間通訊的 [ipc][1] 模組。並且也有一個遠端模使用 RPC 通訊方式 [remote][2]。 +在 Electron,我們提供用於在主行程與渲染行程之間通訊的 [ipc](../api/ipc-renderer.md) 模組。並且也有一個遠端模組使用 RPC 通訊方式 [remote](../api/remote.md)。 # 打造你第一個 Electron 應用 @@ -43,7 +43,7 @@ your-app/ └── index.html ``` -`package.json ` 的格式與 Node 的模組完全一樣,並且有個腳本被指定為 `main` 是用來啟動你的應用程式,它運行在主行程上。 +`package.json` 的格式與 Node 的模組完全一樣,並且有個腳本被指定為 `main` 是用來啟動你的應用程式,它運行在主行程上。 你應用裡的 一個範例在你的 `package.json` 看起來可能像這樣: ```json @@ -88,7 +88,7 @@ app.on('ready', function() {   mainWindow.loadUrl('file://' + __dirname + '/index.html');   // 打開開發者工具 -  mainWindow.openDevTools(); +  mainWindow.webContents.openDevTools();   // 當window 被關閉,這個事件會被觸發   mainWindow.on('closed', function() { @@ -110,8 +110,9 @@ app.on('ready', function() {           

Hello World!

-    We are using Node.js -    and Electron . + We are using node , + Chrome , + and Electron .    ``` @@ -160,6 +161,17 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/ # 作為版本發行 在你完成了你的應用程式後,你可以依照 [應用部署](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md) 指南發布一個版本,並且運行已經打包好的應用程式。 -[1]: https://github.com/atom/electron/blob/master/docs/api/ipc-renderer.md +# 試試這個範例 -[2]: https://github.com/atom/electron/blob/master/docs/api/remote.md +Clone 與執行本篇教學的程式碼,它們都放在 [`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) 這個 repository。 + +**Note**: 執行這個範例需要 [Git](https://git-scm.com) 以及 [Node.js](https://nodejs.org/en/download/) (其中包括 [npm](https://npmjs.org)) 在你的作業系統。 + +```bash +# Clone the repository +$ git clone https://github.com/atom/electron-quick-start +# Go into the repository +$ cd electron-quick-start +# Install dependencies and run the app +$ npm install && npm start +``` \ No newline at end of file From 9b36abc8167af721a0128fadda04800a31a8132b Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sun, 25 Oct 2015 17:00:29 +0200 Subject: [PATCH 328/738] Update web-contents.md The `did-fail-load` event returns an error code and error description. The error description is at least sometimes empty (e.g. when the error code is -102 on Windows), so you're left with an error code without knowing what happened. So I add a link to Chromium's net_error_list.h. --- docs/api/web-contents.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 006d7e3934b9..7633efbfb3de 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -36,6 +36,7 @@ Returns: This event is like `did-finish-load` but emitted when the load failed or was cancelled, e.g. `window.stop()` is invoked. +The full list of error codes and their meaning is available [here](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h). ### Event: 'did-frame-finish-load' From fd94ff97e714b0feac8a0f64015dd20bba86a5ed Mon Sep 17 00:00:00 2001 From: Diego Ponce Date: Sun, 25 Oct 2015 14:04:03 -0600 Subject: [PATCH 329/738] Remove english words in description --- docs-translations/es/tutorial/quick-start.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs-translations/es/tutorial/quick-start.md b/docs-translations/es/tutorial/quick-start.md index 5c3095deb3ef..3db92177ca24 100644 --- a/docs-translations/es/tutorial/quick-start.md +++ b/docs-translations/es/tutorial/quick-start.md @@ -65,7 +65,6 @@ a ser ejecutado por el proceso principal. Un ejemplo de `package.json` podría v ``` El `main.js` debería crear las ventanas y gestionar los eventos del sistema, un ejemplo típico sería: -example being: ```javascript var app = require('app'); // Módulo para controlar el ciclo de vida de la aplicación. From da82eaefa797f3a91e8a3b5239fe79ba77f613a2 Mon Sep 17 00:00:00 2001 From: Everardo Medina Date: Sun, 25 Oct 2015 22:37:06 -0600 Subject: [PATCH 330/738] :memo: Add coding style spanish translation --- .../es/development/coding-style.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 docs-translations/es/development/coding-style.md diff --git a/docs-translations/es/development/coding-style.md b/docs-translations/es/development/coding-style.md new file mode 100644 index 000000000000..de02a33a86d3 --- /dev/null +++ b/docs-translations/es/development/coding-style.md @@ -0,0 +1,37 @@ +# Guía de estilo de código + +Esta es la guía de estilo de código para Electron. + +## C++ y Python + +Para C++ y Python, nosotros seguimos la [guía de estilo](http://www.chromium.org/developers/coding-style) de Chromium. +Además hay un script `script/cpplint.py` para verificar si todos los archivos +siguen el estilo. + +La versión de Python que estamos usando ahora es Python 2.7. + +El código C++ usa muchas abstracciones y tipos de Chromium, por eso +se recomienda familiarizarse con ellos. Un buen lugar para iniciar es +el documento de Chromium sobre [Abstracciones importantes y estructras de datos](https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures). El documento menciona algunos tipos especiales, tipos por alcance (que +automaticamente liberan su memoria cuando salen de su alcance), mecanismos de +registro de eventos, etcétera. + +## CoffeeScript + +Para CoffeeScript, nosotros seguimos la [guía de estilo](https://github.com/styleguide/javascript) de Github y también las +siguientes reglas: + +* Los archivos **NO** deberían terminar con una nueva línea, por que se busca + seguir los estilos que usa Google. +* Los nombres de los archivos debén estar concatenados con `-` en vez de `_`, + por ejemplo `nombre-de-archivo.coffee` en vez de `nombre_de_archivo.coffee`, + esto es por que en [github/atom](https://github.com/github/atom) + los nombres de los módulos usualmente estan en la forma `nombre-de-modulo`. + Esta regla aplica únicamente a los archivos `.coffee`. + +## Nombres de las API + +Al crear una nueva API, nosotros deberíamos preferir usar metodos `get` y `set` +en vez de usar el estilo de jQuery que utiliza una sola función. Por ejemplo, +se prefiere `.getText()` y `.setText()` por sobre `.text([text])`. Hay una +[discusión](https://github.com/atom/electron/issues/46) sobre esto. From 70fe169b0f2c091c32ace2b5455e5023ad0bf143 Mon Sep 17 00:00:00 2001 From: Robo Date: Sat, 24 Oct 2015 22:10:38 +0530 Subject: [PATCH 331/738] nativemate: use maybe version of v8::Function::Call to avoid exceptions --- atom/common/native_mate_converters/callback.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/atom/common/native_mate_converters/callback.h b/atom/common/native_mate_converters/callback.h index 6e51cda79c49..68ea911fe143 100644 --- a/atom/common/native_mate_converters/callback.h +++ b/atom/common/native_mate_converters/callback.h @@ -70,10 +70,13 @@ struct V8FunctionInvoker { v8::Local holder = function->NewHandle(); v8::Local context = holder->CreationContext(); v8::Context::Scope context_scope(context); - ReturnType ret; + ReturnType ret = ReturnType(); std::vector> args = { ConvertToV8(isolate, raw)... }; - v8::Local val(holder->Call(holder, args.size(), &args.front())); - Converter::FromV8(isolate, val, &ret); + v8::Local result; + auto maybe_result = + holder->Call(context, holder, args.size(), &args.front()); + if (maybe_result.ToLocal(&result)) + Converter::FromV8(isolate, result, &ret); return ret; } }; From b71ec748ad173cc6f1a4c06d7eaa53a80e69da67 Mon Sep 17 00:00:00 2001 From: Everardo Medina Date: Mon, 26 Oct 2015 00:04:11 -0600 Subject: [PATCH 332/738] :memo: Add source code directory structure spanish translation --- docs-translations/es/README.md | 2 +- .../source-code-directory-structure.md | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 docs-translations/es/development/source-code-directory-structure.md diff --git a/docs-translations/es/README.md b/docs-translations/es/README.md index 706261c417e1..687dff4bde2d 100644 --- a/docs-translations/es/README.md +++ b/docs-translations/es/README.md @@ -62,7 +62,7 @@ ## Desarrollo * [Guía de Estilo](development/coding-style.md) -* [Estructura de los directorios del Código Fuente](../../development/source-code-directory-structure.md) +* [Estructura de los directorios del Código Fuente](development/source-code-directory-structure.md) * [Diferencias Técnicas con NW.js (anteriormente conocido como node-webkit)](../../development/atom-shell-vs-node-webkit.md) * [Repaso del Sistema de Compilación](../../development/build-system-overview.md) * [Instrucciones de Compilación (Mac)](../../development/build-instructions-osx.md) diff --git a/docs-translations/es/development/source-code-directory-structure.md b/docs-translations/es/development/source-code-directory-structure.md new file mode 100644 index 000000000000..cc738d241277 --- /dev/null +++ b/docs-translations/es/development/source-code-directory-structure.md @@ -0,0 +1,62 @@ +# Estructura de los directorios del código fuente + +El código fuente de electron es separado en pocas partes, en su mayoría +siguiendo las especificaciones para separar archivos que usa Chromium. + +Quizá necesites familiarizarte con la [arquitectura multiprocesos](http://dev.chromium.org/developers/design-documents/multi-process-architecture) de Chromium para comprender mejor el código fuente. + +## Estructura del código fuente + +``` +Electron +├──atom - Código fuente de Electron. +| ├── app - Código de arranque. +| ├── browser - La interfaz incluyendo la ventana principal, UI, +| | y todas las cosas del proceso principal. Este le habla al renderizador +| | para manejar las páginas web. +| | ├── lib - Código Javascript para inicializar el proceso principal. +| | ├── ui - Implementaciones de UI para distintas plataformas. +| | | ├── cocoa - Código fuente específico para Cocoa. +| | | ├── gtk - Código fuente específico para GTK+. +| | | └── win - Código fuente específico para Windows GUI. +| | ├── default_app - La página por defecto para mostrar cuando Electron +| | | es iniciado sin proveer una app. +| | ├── api - La implementación de las APIs para el proceso principal. +| | | └── lib - Código Javascript parte de la implementación de la API. +| | ├── net - Código relacionado a la red. +| | ├── mac - Código fuente de Objective-C específico para Mac. +| | └── resources - Iconos, archivos específicos de plataforma, etc. +| ├── renderer - Código que se ejecuta en el proceso de renderizado. +| | ├── lib - Código Javascript del proceso de inicio del renderizador. +| | └── api - La implementación de las APIs para el proceso de renderizado. +| | └── lib - Código Javascript parte de la implementación de la API. +| └── common - Código que se utiliza en ambos procesos, el principal y el de +| renderizado. Incluye algunas funciones de utilidad y código para integrar +| el ciclo de mensajes de Node en el ciclo de mensajes de Chromium. +| ├── lib - Código Javascript común para la inicialización. +| └── api - La implementación de APIs comunes, y los fundamentos de +| los módulos integrados de Electron. +| └── lib - Código Javascript parte de la implementación de la API. +├── chromium_src - Código fuente copiado de Chromium. +├── docs - Documentación. +├── spec - Pruebas automaticas. +├── atom.gyp - Reglas de compilado de Electron. +└── common.gypi - Configuración específica para compilar y reglas + de empaquetado para otros componentes como `node` y `breakpad`. +``` + +## Estructura de otros directorios + +* **script** - Scripts usados para propositos de desarrollo + como compilar, empaquetar, realizar pruebas, etc. +* **tools** - Scripts de ayuda usados por los archivos gyp, contrario a la + carpeta `scripts`, estos scripts nunca deberían ser llamados por los usuarios. +* **vendor** - Código fuente de dependencias externas, no usamos `third_party` + como nombre por que se podría confundir con el mismo directorio + en las carpetas del código fuente de Chromium. +* **node_modules** - Módulos de node usados para la compilación. +* **out** - Directorio temporal de salida usado por `ninja`. +* **dist** - Directorio temporal creado por `script/create-dist.py` cuando + se esta creando una distribución. +* **external_binaries** - Binarios descargados de frameworks externos que no + soportan la compilación con `gyp`. From adb11225d22e1c1d0a1d6848e28105d15118bf4b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 26 Oct 2015 16:16:50 +0800 Subject: [PATCH 333/738] Ship LICENSES.chromium.html in zip archive --- script/create-dist.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/script/create-dist.py b/script/create-dist.py index 5f47b2d358f0..d79d963c12ab 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -176,7 +176,8 @@ def create_dist_zip(): zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name) with scoped_cwd(DIST_DIR): - files = TARGET_BINARIES[PLATFORM] + ['LICENSE', 'version'] + files = TARGET_BINARIES[PLATFORM] + ['LICENSE', 'LICENSES.chromium.html', + 'version'] if PLATFORM == 'linux': files += [lib for lib in SYSTEM_LIBRARIES if os.path.exists(lib)] dirs = TARGET_DIRECTORIES[PLATFORM] @@ -189,7 +190,7 @@ def create_chrome_binary_zip(binary, version): zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name) with scoped_cwd(DIST_DIR): - files = ['LICENSE'] + files = ['LICENSE', 'LICENSES.chromium.html'] if PLATFORM == 'win32': files += [binary + '.exe'] else: @@ -205,7 +206,7 @@ def create_symbols_zip(): zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name) with scoped_cwd(DIST_DIR): - files = ['LICENSE', 'version'] + files = ['LICENSE', 'LICENSES.chromium.html', 'version'] dirs = ['{0}.breakpad.syms'.format(PROJECT_NAME)] make_zip(zip_file, files, dirs) From f399f50e9ee11f51a2d02eeef3eb1672e95434bc Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 26 Oct 2015 16:48:27 +0800 Subject: [PATCH 334/738] Fix calling showItemInFolder in renderer The remote method always assumes the existence of the remote object but doesn't keep a reference to it, so if we only keep the reference of a remote method we will get into troubles once the remote object is garbage collected. We should probably fix this in remote module, but since most things are already working quite good, I'm using the work-around for now. Fix #3139. --- atom/common/api/lib/shell.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/common/api/lib/shell.coffee b/atom/common/api/lib/shell.coffee index 8e06826f7076..bd7109e34518 100644 --- a/atom/common/api/lib/shell.coffee +++ b/atom/common/api/lib/shell.coffee @@ -1,4 +1,5 @@ module.exports = process.atomBinding 'shell' if process.platform is 'win32' and process.type is 'renderer' - module.exports.showItemInFolder = require('remote').process.atomBinding('shell').showItemInFolder + module.exports.showItemInFolder = (item) -> + require('remote').require('shell').showItemInFolder item From b29a8c94b927ecb16ba7c83748a692332310f836 Mon Sep 17 00:00:00 2001 From: Gohy Leandre Date: Mon, 26 Oct 2015 22:18:16 +0100 Subject: [PATCH 335/738] Add extra headers option to webContents.loadUrl --- atom/browser/api/atom_api_web_contents.cc | 4 ++++ docs/api/web-contents.md | 1 + 2 files changed, 5 insertions(+) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 5b3ef2f4aa7b..900c3e65a376 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -618,6 +618,10 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) { if (options.Get("userAgent", &user_agent)) SetUserAgent(user_agent); + std::string extra_headers; + if (options.Get("extraHeaders", &extra_headers)) + params.extra_headers = extra_headers; + params.transition_type = ui::PAGE_TRANSITION_TYPED; params.should_clear_history_list = true; params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 7633efbfb3de..3113356e34b4 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -183,6 +183,7 @@ See [session documentation](session.md) for this object's methods. * `options` Object (optional), properties: * `httpReferrer` String - A HTTP Referrer url. * `userAgent` String - A user agent originating the request. + * `extraHeaders` String - Extra headers separated by "\n" Loads the `url` in the window, the `url` must contain the protocol prefix, e.g. the `http://` or `file://`. From edbebf84b9d5bf7d3dde71f7337e4ce48d7de7c6 Mon Sep 17 00:00:00 2001 From: Omri Litov Date: Tue, 27 Oct 2015 03:12:01 +0200 Subject: [PATCH 336/738] Added browser-window event 'message' --- atom/browser/api/atom_api_window.cc | 6 ++++++ atom/browser/api/atom_api_window.h | 5 +++++ atom/browser/native_window.cc | 8 ++++++++ atom/browser/native_window.h | 4 ++++ atom/browser/native_window_observer.h | 9 +++++++++ atom/browser/native_window_views_win.cc | 2 ++ docs/api/browser-window.md | 4 ++++ 7 files changed, 38 insertions(+) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 62994c9c93d4..7daab4d1a085 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -189,6 +189,12 @@ void Window::OnExecuteWindowsCommand(const std::string& command_name) { Emit("app-command", command_name); } +#if defined(OS_WIN) +void Window::OnWindowMessage(UINT message, LPARAM l_param, WPARAM w_param) { + Emit("message", message, l_param, w_param); +} +#endif + // static mate::Wrappable* Window::New(v8::Isolate* isolate, const mate::Dictionary& options) { diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 8a8ff266a883..419564146149 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -75,6 +75,11 @@ class Window : public mate::TrackableObject, void OnRendererResponsive() override; void OnExecuteWindowsCommand(const std::string& command_name) override; + #if defined(OS_WIN) + void OnWindowMessage(unsigned int message, LPARAM l_param, + WPARAM w_param) override; + #endif + // mate::Wrappable: bool IsDestroyed() const override; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index c19bcdf467f3..e3abed473e7d 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -464,6 +464,14 @@ void NativeWindow::NotifyWindowExecuteWindowsCommand( OnExecuteWindowsCommand(command)); } +#if defined(OS_WIN) +void NativeWindow::NotifyWindowMessage(UINT message, WPARAM w_param, + LPARAM l_param) { + FOR_EACH_OBSERVER(NativeWindowObserver, observers_, + OnWindowMessage(message, w_param, l_param)); +} +#endif + scoped_ptr NativeWindow::DraggableRegionsToSkRegion( const std::vector& regions) { scoped_ptr sk_region(new SkRegion); diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 37a59ff8a9e4..e32b94811823 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -210,6 +210,10 @@ class NativeWindow : public base::SupportsUserData, void NotifyWindowLeaveHtmlFullScreen(); void NotifyWindowExecuteWindowsCommand(const std::string& command); + #if defined(OS_WIN) + void NotifyWindowMessage(UINT message, WPARAM w_param, LPARAM l_param); + #endif + void AddObserver(NativeWindowObserver* obs) { observers_.AddObserver(obs); } diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 33ab1ecb6b3d..db693b47d53d 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -11,6 +11,10 @@ #include "ui/base/window_open_disposition.h" #include "url/gurl.h" +#if defined(OS_WIN) +#include +#endif + namespace atom { class NativeWindowObserver { @@ -55,6 +59,11 @@ class NativeWindowObserver { virtual void OnWindowEnterHtmlFullScreen() {} virtual void OnWindowLeaveHtmlFullScreen() {} + // Called when window message received + #if defined(OS_WIN) + virtual void OnWindowMessage(UINT message, LPARAM l_param, WPARAM w_param) {} + #endif + // Called when renderer is hung. virtual void OnRendererUnresponsive() {} diff --git a/atom/browser/native_window_views_win.cc b/atom/browser/native_window_views_win.cc index 6092a2242ac0..d49683acb3cf 100644 --- a/atom/browser/native_window_views_win.cc +++ b/atom/browser/native_window_views_win.cc @@ -80,6 +80,8 @@ bool NativeWindowViews::ExecuteWindowsCommand(int command_id) { bool NativeWindowViews::PreHandleMSG( UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) { + NotifyWindowMessage(message, w_param, l_param); + switch (message) { case WM_COMMAND: // Handle thumbar button click message. diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index aa46590c746b..99578c902ef0 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -232,6 +232,10 @@ Emitted when the window enters full screen state triggered by html api. Emitted when the window leaves full screen state triggered by html api. +### Event: 'message' _WINDOWS_ + +Emitted when the window receives a message from the operating system. + ### Event: 'app-command': Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) From 2e3a5f5a3ef9677eb19030304f31d42e12da4c6e Mon Sep 17 00:00:00 2001 From: Sitdhibong Laokok Date: Tue, 27 Oct 2015 12:09:49 +0700 Subject: [PATCH 337/738] Translate README.md --- docs-translations/th-TH/README.md | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 docs-translations/th-TH/README.md diff --git a/docs-translations/th-TH/README.md b/docs-translations/th-TH/README.md new file mode 100644 index 000000000000..47c5082f3651 --- /dev/null +++ b/docs-translations/th-TH/README.md @@ -0,0 +1,75 @@ +## คู่มือ + +* [แพลตฟอร์มที่รองรับ](tutorial/supported-platforms.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) +* [ส่วนเสริมของ DevTools](tutorial/devtools-extension.md) +* [การใช้งานส่วนเสริม Pepper Flash](tutorial/using-pepper-flash-plugin.md) + +## แนะนำ + +* [เริ่มต้นอย่างคราวๆ](tutorial/quick-start.md) +* [การร่วมกันของสภาพแวดล้อมบนเดสทอป](tutorial/desktop-environment-integration.md) +* [การตรวจจับเหตุการณ์ออนไลน์หรือออฟไลน์](tutorial/online-offline-events.md) + +## แหล่งอ้างอิงของ API + +* [สรุปความ](api/synopsis.md) +* [Process Object](api/process.md) +* [คำสั่งของ Chrome Command Line Switches ที่รองรับ](api/chrome-command-line-switches.md) + +### การปรับแต่ง DOM: + +* [วัตถุ `File`](api/file-object.md) +* [แท็ก `` Tag](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) +* [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) +* [protocol](api/protocol.md) +* [session](api/session.md) +* [web-contents](api/web-contents.md) +* [tray](api/tray.md) + +### Modules for the Renderer Process (Web Page): +### โมดูลสำหรับโปรเซส Renderer (Web Page): + +* [ipc (renderer)](api/ipc-renderer.md) +* [remote](api/remote.md) +* [web-frame](api/web-frame.md) + +### Modules for Both Processes: + +* [clipboard](api/clipboard.md) +* [crash-reporter](api/crash-reporter.md) +* [native-image](api/native-image.md) +* [screen](api/screen.md) +* [shell](api/shell.md) + +## การพัฒนา + +* [ลักษณะการเขียนโค้ด](development/coding-style.md) +* [โครงสร้างไดเรคทอรี่ของซอร์สโค้ด](development/source-code-directory-structure.md) +* [Technical Differences to NW.js (formerly node-webkit)](development/atom-shell-vs-node-webkit.md) +* [ความแตกต่างทางเทคนิคจาก NW.js (หรือ node-webkit)](development/atom-shell-vs-node-webkit.md) +* [ภาพรวมการสร้างระบบ](development/build-system-overview.md) +* [ขั้นตอนการสร้าง (OS X)](development/build-instructions-osx.md) +* [ขั้นตอนการสร้าง (Windows)](development/build-instructions-windows.md) +* [ขั้นตอนการสร้าง (Linux)](development/build-instructions-linux.md) +* [Setting Up Symbol Server in debugger](development/setting-up-symbol-server.md) +* [การติดตั้งเซิร์ฟเวอร์ Symbol Server ใน debugger](development/setting-up-symbol-server.md) From 00493f64b766051279eedd686b63800cd2955f88 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 27 Oct 2015 13:10:34 +0800 Subject: [PATCH 338/738] Win: Remove adding default file filter(*.*) in a save dialog. --- atom/browser/ui/file_dialog_win.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/atom/browser/ui/file_dialog_win.cc b/atom/browser/ui/file_dialog_win.cc index da00dc54e2fc..9620c44e420d 100644 --- a/atom/browser/ui/file_dialog_win.cc +++ b/atom/browser/ui/file_dialog_win.cc @@ -34,12 +34,6 @@ bool IsDirectory(const base::FilePath& path) { void ConvertFilters(const Filters& filters, std::vector* buffer, std::vector* filterspec) { - if (filters.empty()) { - COMDLG_FILTERSPEC spec = { L"All Files (*.*)", L"*.*" }; - filterspec->push_back(spec); - return; - } - buffer->reserve(filters.size() * 2); for (size_t i = 0; i < filters.size(); ++i) { const Filter& filter = filters[i]; From a84f4dc3e62a84e2cae0c90329b28ab89bd63660 Mon Sep 17 00:00:00 2001 From: Sitdhibong Laokok Date: Tue, 27 Oct 2015 12:20:54 +0700 Subject: [PATCH 339/738] Remove original msg --- docs-translations/th-TH/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs-translations/th-TH/README.md b/docs-translations/th-TH/README.md index 47c5082f3651..29c8523cccde 100644 --- a/docs-translations/th-TH/README.md +++ b/docs-translations/th-TH/README.md @@ -46,7 +46,6 @@ * [web-contents](api/web-contents.md) * [tray](api/tray.md) -### Modules for the Renderer Process (Web Page): ### โมดูลสำหรับโปรเซส Renderer (Web Page): * [ipc (renderer)](api/ipc-renderer.md) From f1fad96b568687e98c6d48b0a05e54f60b1dcadb Mon Sep 17 00:00:00 2001 From: Sitdhibong Laokok Date: Tue, 27 Oct 2015 12:36:43 +0700 Subject: [PATCH 340/738] Fix missing spell --- docs-translations/th-TH/README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs-translations/th-TH/README.md b/docs-translations/th-TH/README.md index 29c8523cccde..3b9f52077111 100644 --- a/docs-translations/th-TH/README.md +++ b/docs-translations/th-TH/README.md @@ -19,16 +19,16 @@ ## แหล่งอ้างอิงของ API * [สรุปความ](api/synopsis.md) -* [Process Object](api/process.md) -* [คำสั่งของ Chrome Command Line Switches ที่รองรับ](api/chrome-command-line-switches.md) +* [โปรเซสออบเจค](api/process.md) +* [คำสั่งสำหรับเปลี่ยนแปลงค่าของ Chrome ที่รองรับ](api/chrome-command-line-switches.md) ### การปรับแต่ง DOM: * [วัตถุ `File`](api/file-object.md) -* [แท็ก `` Tag](api/web-view-tag.md) +* [แท็ก ``](api/web-view-tag.md) * [ฟังก์ชัน `window.open`](api/window-open.md) -### โมดูลสำหรับโปรเซสหลัก : +### โมดูลสำหรับกระบวนการหลัก : * [app](api/app.md) * [auto-updater](api/auto-updater.md) @@ -46,7 +46,7 @@ * [web-contents](api/web-contents.md) * [tray](api/tray.md) -### โมดูลสำหรับโปรเซส Renderer (Web Page): +### โมดูลสำหรับกระบวนการ Renderer (เว็บเพจ): * [ipc (renderer)](api/ipc-renderer.md) * [remote](api/remote.md) @@ -64,7 +64,6 @@ * [ลักษณะการเขียนโค้ด](development/coding-style.md) * [โครงสร้างไดเรคทอรี่ของซอร์สโค้ด](development/source-code-directory-structure.md) -* [Technical Differences to NW.js (formerly node-webkit)](development/atom-shell-vs-node-webkit.md) * [ความแตกต่างทางเทคนิคจาก NW.js (หรือ node-webkit)](development/atom-shell-vs-node-webkit.md) * [ภาพรวมการสร้างระบบ](development/build-system-overview.md) * [ขั้นตอนการสร้าง (OS X)](development/build-instructions-osx.md) From 2a85bd3360e6cedad8607bc1c5ade2d635332e72 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 27 Oct 2015 14:25:42 +0800 Subject: [PATCH 341/738] Update libchromiumcontent: fix private API call --- 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 83468f819946..047ecf4faa76 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '78e54bc39a04b758ed5167cd980cc4d9951bd629' +LIBCHROMIUMCONTENT_COMMIT = '464aff2398f619b1d4d91b9187de69803919dca2' PLATFORM = { 'cygwin': 'win32', From dacd921a045d7155252a5b8912a7286cd349d3da Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 27 Oct 2015 14:58:44 +0800 Subject: [PATCH 342/738] Revert "Win: Remove adding default file filter(*.*) in a save dialog." This reverts commit 00493f64b766051279eedd686b63800cd2955f88. --- atom/browser/ui/file_dialog_win.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/atom/browser/ui/file_dialog_win.cc b/atom/browser/ui/file_dialog_win.cc index 9620c44e420d..da00dc54e2fc 100644 --- a/atom/browser/ui/file_dialog_win.cc +++ b/atom/browser/ui/file_dialog_win.cc @@ -34,6 +34,12 @@ bool IsDirectory(const base::FilePath& path) { void ConvertFilters(const Filters& filters, std::vector* buffer, std::vector* filterspec) { + if (filters.empty()) { + COMDLG_FILTERSPEC spec = { L"All Files (*.*)", L"*.*" }; + filterspec->push_back(spec); + return; + } + buffer->reserve(filters.size() * 2); for (size_t i = 0; i < filters.size(); ++i) { const Filter& filter = filters[i]; From e355532d27c333862bfac3f38a4d6e520d2dd581 Mon Sep 17 00:00:00 2001 From: Omri Litov Date: Tue, 27 Oct 2015 14:00:08 +0200 Subject: [PATCH 343/738] Change windows messages api to hook instead of emitter --- atom/browser/api/atom_api_window.cc | 35 +++++++++++++++++++++++++-- atom/browser/api/atom_api_window.h | 17 +++++++++++-- atom/browser/native_window_observer.h | 2 +- docs/api/browser-window.md | 28 ++++++++++++++++++--- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 7daab4d1a085..45b57f5307be 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -190,8 +190,10 @@ void Window::OnExecuteWindowsCommand(const std::string& command_name) { } #if defined(OS_WIN) -void Window::OnWindowMessage(UINT message, LPARAM l_param, WPARAM w_param) { - Emit("message", message, l_param, w_param); +void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) { + if (IsWindowMessageHooked(message)) { + messages_callback_map_[message].Run(w_param, l_param); + } } #endif @@ -498,6 +500,29 @@ bool Window::IsMenuBarVisible() { return window_->IsMenuBarVisible(); } +#if defined(OS_WIN) +bool Window::HookWindowMessage(UINT message, + const MessageCallback& callback) { + messages_callback_map_[message] = callback; + return true; +} + +void Window::UnhookWindowMessage(UINT message) { + if (!ContainsKey(messages_callback_map_, message)) + return; + + messages_callback_map_.erase(message); +} + +bool Window::IsWindowMessageHooked(UINT message) { + return ContainsKey(messages_callback_map_, message); +} + +void Window::UnhookAllWindowMessages() { + messages_callback_map_.clear(); +} +#endif + #if defined(OS_MACOSX) void Window::ShowDefinitionForSelection() { window_->ShowDefinitionForSelection(); @@ -596,6 +621,12 @@ void Window::BuildPrototype(v8::Isolate* isolate, &Window::SetVisibleOnAllWorkspaces) .SetMethod("isVisibleOnAllWorkspaces", &Window::IsVisibleOnAllWorkspaces) +#if defined(OS_WIN) + .SetMethod("hookWindowMessage", &Window::HookWindowMessage) + .SetMethod("isWindowMessageHooked", &Window::IsWindowMessageHooked) + .SetMethod("unhookWindowMessage", &Window::UnhookWindowMessage) + .SetMethod("unhookAllWindowMessages", &Window::UnhookAllWindowMessages) +#endif #if defined(OS_MACOSX) .SetMethod("showDefinitionForSelection", &Window::ShowDefinitionForSelection) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 419564146149..870f8e134216 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -5,6 +5,7 @@ #ifndef ATOM_BROWSER_API_ATOM_API_WINDOW_H_ #define ATOM_BROWSER_API_ATOM_API_WINDOW_H_ +#include #include #include @@ -76,8 +77,8 @@ class Window : public mate::TrackableObject, void OnExecuteWindowsCommand(const std::string& command_name) override; #if defined(OS_WIN) - void OnWindowMessage(unsigned int message, LPARAM l_param, - WPARAM w_param) override; + void OnWindowMessage(UINT message, WPARAM w_param, + LPARAM l_param) override; #endif // mate::Wrappable: @@ -148,6 +149,18 @@ class Window : public mate::TrackableObject, bool IsMenuBarVisible(); void SetAspectRatio(double aspect_ratio, mate::Arguments* args); +#if defined(OS_WIN) + typedef base::Callback MessageCallback; + typedef std::map MessageCallbackMap; + MessageCallbackMap messages_callback_map_; + + bool HookWindowMessage(UINT message, + const MessageCallback& callback); + bool IsWindowMessageHooked(UINT message); + void UnhookWindowMessage(UINT message); + void UnhookAllWindowMessages(); +#endif + #if defined(OS_MACOSX) void ShowDefinitionForSelection(); #endif diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index db693b47d53d..54004a300d94 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -61,7 +61,7 @@ class NativeWindowObserver { // Called when window message received #if defined(OS_WIN) - virtual void OnWindowMessage(UINT message, LPARAM l_param, WPARAM w_param) {} + virtual void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {} #endif // Called when renderer is hung. diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 99578c902ef0..d7bf5be374d4 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -232,10 +232,6 @@ Emitted when the window enters full screen state triggered by html api. Emitted when the window leaves full screen state triggered by html api. -### Event: 'message' _WINDOWS_ - -Emitted when the window receives a message from the operating system. - ### Event: 'app-command': Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) @@ -556,6 +552,30 @@ Enters or leaves the kiosk mode. Returns whether the window is in kiosk mode. +### `win.hookWindowMessage(message, callback)` _WINDOWS_ + +* `message` Integer +* `callback` Function + +Hooks a windows message. The `callback` is called when +the message is received in the WndProc. + +### `win.isWindowMessageHooked(message)` _WINDOWS_ + +* `message` Integer + +Returns `true` or `false` depending on whether the message is hooked. + +### `win.unhookWindowMessage(message)` _WINDOWS_ + +* `message` Integer + +Unhook the window message. + +### `win.unhookAllWindowMessages()` _WINDOWS_ + +Unhooks all of the window messages. + ### `win.setRepresentedFilename(filename)` _OS X_ * `filename` String From fa24e15d8bfd5371050d89a47b711aefc247566e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 27 Oct 2015 13:10:34 +0800 Subject: [PATCH 344/738] Win: Remove adding '*.*' to file name in a save dialog. --- atom/browser/ui/file_dialog_win.cc | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/atom/browser/ui/file_dialog_win.cc b/atom/browser/ui/file_dialog_win.cc index da00dc54e2fc..edbb4b332b54 100644 --- a/atom/browser/ui/file_dialog_win.cc +++ b/atom/browser/ui/file_dialog_win.cc @@ -79,8 +79,25 @@ class FileDialog { if (!title.empty()) GetPtr()->SetTitle(base::UTF8ToUTF16(title).c_str()); - if (!filterspec.empty()) - GetPtr()->SetDefaultExtension(filterspec.front().pszSpec); + // By default, *.* will be added to the file name if file type is "*.*". In + // Electron, we disable it to make a better experience. + // + // From MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ + // bb775970(v=vs.85).aspx + // + // If SetDefaultExtension is not called, the dialog will not update + // automatically when user choose a new file type in the file dialog. + // + // We set file extension to the first none-wildcard extension to make + // sure the dialog will update file extension automatically. + for (size_t i = 0; i < filterspec.size(); ++i) { + if (std::wstring(filterspec[i].pszSpec) != L"*.*") { + // SetFileTypeIndex is regarded as one-based index. + GetPtr()->SetFileTypeIndex(i+1); + GetPtr()->SetDefaultExtension(filterspec[i].pszSpec); + break; + } + } SetDefaultFolder(default_path); } From f69bafd48a69054908f91b3a419491c2c504a96e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 27 Oct 2015 20:03:28 +0800 Subject: [PATCH 345/738] Win: Fix adding '.*' to filename in callback. --- atom/browser/ui/file_dialog_win.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/ui/file_dialog_win.cc b/atom/browser/ui/file_dialog_win.cc index edbb4b332b54..d218beaa27f1 100644 --- a/atom/browser/ui/file_dialog_win.cc +++ b/atom/browser/ui/file_dialog_win.cc @@ -272,7 +272,8 @@ bool ShowSaveDialog(atom::NativeWindow* parent_window, bool matched = false; for (size_t i = 0; i < filter.second.size(); ++i) { - if (base::EndsWith(file_name, filter.second[i], false)) { + if (filter.second[i] == "*" || + base::EndsWith(file_name, filter.second[i], false)) { matched = true; break;; } From e90961ac4f0d9731e882e02ef77869ed99aaf4e0 Mon Sep 17 00:00:00 2001 From: Matias Insaurralde Date: Wed, 28 Oct 2015 03:19:19 -0300 Subject: [PATCH 346/738] Creating supported-platforms.md --- .../es/tutorial/supported-platforms.md | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 docs-translations/es/tutorial/supported-platforms.md diff --git a/docs-translations/es/tutorial/supported-platforms.md b/docs-translations/es/tutorial/supported-platforms.md new file mode 100644 index 000000000000..95ccc267722d --- /dev/null +++ b/docs-translations/es/tutorial/supported-platforms.md @@ -0,0 +1,30 @@ +# Plataformas soportadas + +Las siguientes plataformas son soportadas por Electron: + +### OS X + +Sólo se proveen binarios de 64 bit para OS X. +La versión mínima soportada es OS X 10.8. + +### Windows + +Windows 7 y posteriores son soportados, las versiones antiguas no son soportadas (y no funcionan). + +Se proveen binarios para las arquitecturas `x86` y `amd64` (x64). +Nota: La versión para `ARM` de Windows no está soportada aún. + +### Linux + +Los binarios preconstruidos para `ia32`(`i686`) y `x64`(`amd64`) son construidos sobre +Ubuntu 12.04, el binario para `arm` es construido sobre ARM v7 con la ABI hard-float +y NEON para Debian Wheezy. + +La posibilidad de que un binario preconstruido se ejecute en una distribución determinada +depende de las librerías contra las que fue enlazado Electron. +Por ahora sólo se garantiza la ejecución en Ubuntu 12.04, aunque también se ha verificado +el funcionamiento de los binarios preconstruidos en las siguientes plataformas: + +* Ubuntu 12.04 and later +* Fedora 21 +* Debian 8 From 0c5fe03999919f97395229d3e9414686770d5cf0 Mon Sep 17 00:00:00 2001 From: Antoine Pairet Date: Wed, 28 Oct 2015 11:40:01 +0100 Subject: [PATCH 347/738] Fix module types available in the renderer process The doc previously stated `only GUI-unrelated` modules are available to the renderer process. I think it should be `only GUI-related` --- docs/api/remote.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/remote.md b/docs/api/remote.md index 55893c65f1c4..14805923562c 100644 --- a/docs/api/remote.md +++ b/docs/api/remote.md @@ -3,7 +3,7 @@ The `remote` module provides a simple way to do inter-process communication (IPC) between the renderer process (web page) and the main process. -In Electron, only GUI-unrelated modules are available in the renderer process. +In Electron, only GUI-related modules are available in the renderer process. Without the `remote` module, users who want to call a main process API in the renderer process will have to explicitly send inter-process messages to the main process. With the `remote` module, you can invoke methods of the From 5fd310c75f1f08ac772181f31ba9972b0ea7385e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 19:43:05 +0800 Subject: [PATCH 348/738] Add converter for LPARAM --- atom/browser/api/atom_api_window.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 45b57f5307be..5d0a501629f8 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -42,6 +42,14 @@ struct Converter { } }; +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + LPARAM val) { + return ConvertToV8(isolate, static_cast(val)); + } +}; + } // namespace mate #endif From b86267aa3bc51b895e6bb18579bd447e7cfa0d93 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 19:51:24 +0800 Subject: [PATCH 349/738] Use uint64_t instead of LPARAM LPARAM is defined to differnt types on differnt machines with different SDKs, so there is no way to represent it on all platforms safely, using uint64_t seems to be the only safe choice. --- atom/browser/api/atom_api_window.cc | 10 +--------- atom/browser/api/atom_api_window.h | 5 ++--- atom/browser/native_window.cc | 5 +++-- atom/browser/native_window_observer.h | 2 +- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 5d0a501629f8..077dffe0bc5c 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -42,14 +42,6 @@ struct Converter { } }; -template<> -struct Converter { - static v8::Local ToV8(v8::Isolate* isolate, - LPARAM val) { - return ConvertToV8(isolate, static_cast(val)); - } -}; - } // namespace mate #endif @@ -198,7 +190,7 @@ void Window::OnExecuteWindowsCommand(const std::string& command_name) { } #if defined(OS_WIN) -void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) { +void Window::OnWindowMessage(UINT message, WPARAM w_param, uint64_t l_param) { if (IsWindowMessageHooked(message)) { messages_callback_map_[message].Run(w_param, l_param); } diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 870f8e134216..f4bc4cdba01a 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -77,8 +77,7 @@ class Window : public mate::TrackableObject, void OnExecuteWindowsCommand(const std::string& command_name) override; #if defined(OS_WIN) - void OnWindowMessage(UINT message, WPARAM w_param, - LPARAM l_param) override; + void OnWindowMessage(UINT message, WPARAM w_param, uint64_t l_param) override; #endif // mate::Wrappable: @@ -150,7 +149,7 @@ class Window : public mate::TrackableObject, void SetAspectRatio(double aspect_ratio, mate::Arguments* args); #if defined(OS_WIN) - typedef base::Callback MessageCallback; + typedef base::Callback MessageCallback; typedef std::map MessageCallbackMap; MessageCallbackMap messages_callback_map_; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index e3abed473e7d..6e38f4028745 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -467,8 +467,9 @@ void NativeWindow::NotifyWindowExecuteWindowsCommand( #if defined(OS_WIN) void NativeWindow::NotifyWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) { - FOR_EACH_OBSERVER(NativeWindowObserver, observers_, - OnWindowMessage(message, w_param, l_param)); + FOR_EACH_OBSERVER( + NativeWindowObserver, observers_, + OnWindowMessage(message, w_param, static_cast(l_param))); } #endif diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 54004a300d94..240a7277fa09 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -61,7 +61,7 @@ class NativeWindowObserver { // Called when window message received #if defined(OS_WIN) - virtual void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {} + virtual void OnWindowMessage(UINT message, WPARAM wparam, uint64_t lparam) {} #endif // Called when renderer is hung. From 9df89cf79b7679b73f6c4b43c853a07076ddf9ac Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 15:34:41 +0800 Subject: [PATCH 350/738] Add dummy LoginHandler --- .../atom_resource_dispatcher_host_delegate.cc | 8 ++++ .../atom_resource_dispatcher_host_delegate.h | 3 ++ atom/browser/login_handler.cc | 22 ++++++++++ atom/browser/login_handler.h | 43 +++++++++++++++++++ filenames.gypi | 2 + 5 files changed, 78 insertions(+) create mode 100644 atom/browser/login_handler.cc create mode 100644 atom/browser/login_handler.h diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index 46904d2ff99d..aaba1f31045b 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -4,6 +4,7 @@ #include "atom/browser/atom_resource_dispatcher_host_delegate.h" +#include "atom/browser/login_handler.h" #include "atom/common/platform_util.h" #include "content/public/browser/browser_thread.h" #include "net/base/escape.h" @@ -29,4 +30,11 @@ bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( return true; } +content::ResourceDispatcherHostLoginDelegate* +AtomResourceDispatcherHostDelegate::CreateLoginDelegate( + net::AuthChallengeInfo* auth_info, + net::URLRequest* request) { + return new LoginHandler(auth_info, request); +} + } // namespace atom diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.h b/atom/browser/atom_resource_dispatcher_host_delegate.h index 876554f0f964..a90b366bc75b 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.h +++ b/atom/browser/atom_resource_dispatcher_host_delegate.h @@ -21,6 +21,9 @@ class AtomResourceDispatcherHostDelegate bool is_main_frame, ui::PageTransition transition, bool has_user_gesture) override; + content::ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( + net::AuthChallengeInfo* auth_info, + net::URLRequest* request) override; }; } // namespace atom diff --git a/atom/browser/login_handler.cc b/atom/browser/login_handler.cc new file mode 100644 index 000000000000..1980cc133abc --- /dev/null +++ b/atom/browser/login_handler.cc @@ -0,0 +1,22 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/login_handler.h" + +#include "net/base/auth.h" + +namespace atom { + +LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info, + net::URLRequest* request) + : auth_info_(auth_info), request_(request), weak_factory_(this) { +} + +LoginHandler::~LoginHandler() { +} + +void LoginHandler::OnRequestCancelled() { +} + +} // namespace atom diff --git a/atom/browser/login_handler.h b/atom/browser/login_handler.h new file mode 100644 index 000000000000..421e2e43837d --- /dev/null +++ b/atom/browser/login_handler.h @@ -0,0 +1,43 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_LOGIN_HANDLER_H_ +#define ATOM_BROWSER_LOGIN_HANDLER_H_ + +#include "base/memory/weak_ptr.h" +#include "content/public/browser/resource_dispatcher_host_login_delegate.h" + +namespace net { +class AuthChallengeInfo; +class URLRequest; +} + +namespace atom { + +class LoginHandler : public content::ResourceDispatcherHostLoginDelegate { + public: + LoginHandler(net::AuthChallengeInfo* auth_info, net::URLRequest* request); + + protected: + ~LoginHandler() override; + + // content::ResourceDispatcherHostLoginDelegate: + void OnRequestCancelled() override; + + private: + // Who/where/what asked for the authentication. + scoped_refptr auth_info_; + + // The request that wants login data. + // This should only be accessed on the IO loop. + net::URLRequest* request_; + + base::WeakPtrFactory weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(LoginHandler); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_LOGIN_HANDLER_H_ diff --git a/filenames.gypi b/filenames.gypi index e6d180d652e1..a294a1e8083f 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -150,6 +150,8 @@ 'atom/browser/common_web_contents_delegate.h', 'atom/browser/javascript_environment.cc', 'atom/browser/javascript_environment.h', + 'atom/browser/login_handler.cc', + 'atom/browser/login_handler.h', 'atom/browser/mac/atom_application.h', 'atom/browser/mac/atom_application.mm', 'atom/browser/mac/atom_application_delegate.h', From 3881ad1c4b49db71a24b6ed2e1208ce6e954e1c0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 17:36:01 +0800 Subject: [PATCH 351/738] Don't leak FunctionTemplate when converting C++ callback --- .../common/native_mate_converters/callback.cc | 62 +++++++++++++++++++ atom/common/native_mate_converters/callback.h | 33 +++++++++- filenames.gypi | 1 + 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 atom/common/native_mate_converters/callback.cc diff --git a/atom/common/native_mate_converters/callback.cc b/atom/common/native_mate_converters/callback.cc new file mode 100644 index 000000000000..0be90f63e757 --- /dev/null +++ b/atom/common/native_mate_converters/callback.cc @@ -0,0 +1,62 @@ +// Copyright (c) 2015 GitHub, Inc. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/native_mate_converters/callback.h" + +namespace mate { + +namespace internal { + +namespace { + +struct TranslaterHolder { + Translater translater; +}; + +// Cached JavaScript version of |CallTranslater|. +v8::Persistent g_call_translater; + +void CallTranslater(v8::Local external, mate::Arguments* args) { + TranslaterHolder* holder = static_cast(external->Value()); + holder->translater.Run(args); +} + +// func.bind(func, arg1). +// NB(zcbenz): Using C++11 version crashes VS. +v8::Local BindFunctionWith(v8::Isolate* isolate, + v8::Local context, + v8::Local func, + v8::Local arg1) { + v8::MaybeLocal bind = func->Get(mate::StringToV8(isolate, "bind")); + CHECK(!bind.IsEmpty()); + v8::Local bind_func = + v8::Local::Cast(bind.ToLocalChecked()); + v8::Local converted[] = { func, arg1 }; + return bind_func->Call( + context, func, arraysize(converted), converted).ToLocalChecked(); +} + +} // namespace + +v8::Local CreateFunctionFromTranslater( + v8::Isolate* isolate, const Translater& translater) { + // The FunctionTemplate is cached. + if (g_call_translater.IsEmpty()) + g_call_translater.Reset( + isolate, + mate::CreateFunctionTemplate(isolate, base::Bind(&CallTranslater))); + + v8::Local call_translater = + v8::Local::New(isolate, g_call_translater); + TranslaterHolder* holder = new TranslaterHolder; + holder->translater = translater; + return BindFunctionWith(isolate, + isolate->GetCurrentContext(), + call_translater->GetFunction(), + v8::External::New(isolate, holder)); +} + +} // namespace internal + +} // namespace mate diff --git a/atom/common/native_mate_converters/callback.h b/atom/common/native_mate_converters/callback.h index 68ea911fe143..4349b9997b25 100644 --- a/atom/common/native_mate_converters/callback.h +++ b/atom/common/native_mate_converters/callback.h @@ -20,6 +20,7 @@ namespace internal { typedef scoped_refptr > SafeV8Function; +// Helper to invoke a V8 function with C++ parameters. template struct V8FunctionInvoker {}; @@ -81,13 +82,41 @@ struct V8FunctionInvoker { } }; +// Helper to pass a C++ funtion to JavaScript. +using Translater = base::Callback; +v8::Local CreateFunctionFromTranslater( + v8::Isolate* isolate, const Translater& translater); + +// Calls callback with Arguments. +template +struct NativeFunctionInvoker {}; + +template +struct NativeFunctionInvoker { + static void Go(base::Callback val, Arguments* args) { + using Indices = typename IndicesGenerator::type; + Invoker invoker(args, 0); + if (invoker.IsOK()) + invoker.DispatchToCallback(val); + } +}; + +// Create a static function that accepts generic callback. +template +Translater ConvertToTranslater(const base::Callback& val) { + return base::Bind(&NativeFunctionInvoker::Go, val); +} + } // namespace internal template struct Converter > { static v8::Local ToV8(v8::Isolate* isolate, - const base::Callback& val) { - return CreateFunctionTemplate(isolate, val)->GetFunction(); + const base::Callback& val) { + // We don't use CreateFunctionTemplate here because it creates a new + // FunctionTemplate everytime, which is cached by V8 and causes leaks. + internal::Translater translater = internal::ConvertToTranslater(val); + return internal::CreateFunctionFromTranslater(isolate, translater); } static bool FromV8(v8::Isolate* isolate, v8::Local val, diff --git a/filenames.gypi b/filenames.gypi index a294a1e8083f..65bf6b79a2c2 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -304,6 +304,7 @@ 'atom/common/native_mate_converters/accelerator_converter.h', 'atom/common/native_mate_converters/blink_converter.cc', 'atom/common/native_mate_converters/blink_converter.h', + 'atom/common/native_mate_converters/callback.cc', 'atom/common/native_mate_converters/callback.h', 'atom/common/native_mate_converters/file_path_converter.h', 'atom/common/native_mate_converters/gfx_converter.cc', From 5d8a31c1401bccf21bac1d50c111871f292258e7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 18:19:36 +0800 Subject: [PATCH 352/738] spec: Return early on error --- spec/api-protocol-spec.coffee | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/spec/api-protocol-spec.coffee b/spec/api-protocol-spec.coffee index 02fd8d5e402a..8990f8029ee1 100644 --- a/spec/api-protocol-spec.coffee +++ b/spec/api-protocol-spec.coffee @@ -26,6 +26,7 @@ describe 'protocol module', -> callback(text) callback() protocol.registerStringProtocol protocolName, doubleHandler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -36,6 +37,7 @@ describe 'protocol module', -> it 'sends error when callback is called with nothing', (done) -> protocol.registerBufferProtocol protocolName, emptyHandler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -48,6 +50,7 @@ describe 'protocol module', -> handler = (request, callback) -> setImmediate -> callback(text) protocol.registerStringProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -66,6 +69,7 @@ describe 'protocol module', -> it 'sends string as response', (done) -> handler = (request, callback) -> callback(text) protocol.registerStringProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -77,6 +81,7 @@ describe 'protocol module', -> it 'sends object as response', (done) -> handler = (request, callback) -> callback(data: text, mimeType: 'text/html') protocol.registerStringProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data, statux, request) -> @@ -88,6 +93,7 @@ describe 'protocol module', -> it 'fails when sending object other than string', (done) -> handler = (request, callback) -> callback(new Date) protocol.registerBufferProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -102,6 +108,7 @@ describe 'protocol module', -> it 'sends Buffer as response', (done) -> handler = (request, callback) -> callback(buffer) protocol.registerBufferProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -113,6 +120,7 @@ describe 'protocol module', -> it 'sends object as response', (done) -> handler = (request, callback) -> callback(data: buffer, mimeType: 'text/html') protocol.registerBufferProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data, statux, request) -> @@ -124,6 +132,7 @@ describe 'protocol module', -> it 'fails when sending string', (done) -> handler = (request, callback) -> callback(text) protocol.registerBufferProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -142,6 +151,7 @@ describe 'protocol module', -> it 'sends file path as response', (done) -> handler = (request, callback) -> callback(filePath) protocol.registerFileProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -153,6 +163,7 @@ describe 'protocol module', -> it 'sends object as response', (done) -> handler = (request, callback) -> callback(path: filePath) protocol.registerFileProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data, statux, request) -> @@ -164,6 +175,7 @@ describe 'protocol module', -> it 'can send normal file', (done) -> handler = (request, callback) -> callback(normalPath) protocol.registerFileProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -176,6 +188,7 @@ describe 'protocol module', -> fakeFilePath = path.join __dirname, 'fixtures', 'asar', 'a.asar', 'not-exist' handler = (request, callback) -> callback(fakeFilePath) protocol.registerBufferProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -187,6 +200,7 @@ describe 'protocol module', -> it 'fails when sending unsupported content', (done) -> handler = (request, callback) -> callback(new Date) protocol.registerBufferProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -206,6 +220,7 @@ describe 'protocol module', -> url = "http://127.0.0.1:#{port}" handler = (request, callback) -> callback({url}) protocol.registerHttpProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -217,6 +232,7 @@ describe 'protocol module', -> it 'fails when sending invalid url', (done) -> handler = (request, callback) -> callback({url: 'url'}) protocol.registerHttpProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -228,6 +244,7 @@ describe 'protocol module', -> it 'fails when sending unsupported content', (done) -> handler = (request, callback) -> callback(new Date) protocol.registerHttpProtocol protocolName, handler, (error) -> + return done(error) if error $.ajax url: "#{protocolName}://fake-host" success: (data) -> @@ -288,6 +305,7 @@ describe 'protocol module', -> callback(text) callback() protocol.interceptStringProtocol 'http', doubleHandler, (error) -> + return done(error) if error $.ajax url: 'http://fake-host' success: (data) -> @@ -298,6 +316,7 @@ describe 'protocol module', -> it 'sends error when callback is called with nothing', (done) -> protocol.interceptBufferProtocol 'http', emptyHandler, (error) -> + return done(error) if error $.ajax url: 'http://fake-host' success: (data) -> @@ -310,6 +329,7 @@ describe 'protocol module', -> it 'can intercept http protocol', (done) -> handler = (request, callback) -> callback(text) protocol.interceptStringProtocol 'http', handler, (error) -> + return done(error) if error $.ajax url: 'http://fake-host' success: (data) -> @@ -322,6 +342,7 @@ describe 'protocol module', -> handler = (request, callback) -> callback({mimeType: 'application/json', data: '{"value": 1}'}) protocol.interceptStringProtocol 'http', handler, (error) -> + return done(error) if error $.ajax url: 'http://fake-host' success: (data) -> @@ -335,6 +356,7 @@ describe 'protocol module', -> it 'can intercept http protocol', (done) -> handler = (request, callback) -> callback(new Buffer(text)) protocol.interceptBufferProtocol 'http', handler, (error) -> + return done(error) if error $.ajax url: 'http://fake-host' success: (data) -> From 984774773670fbbcf58f7bbed07cc3138a0a5cf1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 18:25:55 +0800 Subject: [PATCH 353/738] Use the callback converter in JsAsker --- atom/browser/net/js_asker.cc | 69 +++++------------------------------- 1 file changed, 9 insertions(+), 60 deletions(-) diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index d838ae39638f..444124b24b61 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -8,7 +8,6 @@ #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/v8_value_converter.h" -#include "native_mate/function_template.h" namespace atom { @@ -16,18 +15,12 @@ namespace internal { namespace { -struct CallbackHolder { - ResponseCallback callback; -}; - -// Cached JavaScript version of |HandlerCallback|. -v8::Persistent g_handler_callback_; - // The callback which is passed to |handler|. -void HandlerCallback(v8::Isolate* isolate, - v8::Local external, +void HandlerCallback(const ResponseCallback& callback, v8::Local state, mate::Arguments* args) { + v8::Isolate* isolate = args->isolate(); + // Check if the callback has already been called. v8::Local called_symbol = mate::StringToSymbol(isolate, "called"); if (state->Has(called_symbol)) @@ -36,14 +29,11 @@ void HandlerCallback(v8::Isolate* isolate, state->Set(called_symbol, v8::Boolean::New(isolate, true)); // If there is no argument passed then we failed. - scoped_ptr holder( - static_cast(external->Value())); - CHECK(holder); v8::Local value; if (!args->GetNext(&value)) { content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(holder->callback, false, nullptr)); + base::Bind(callback, false, nullptr)); return; } @@ -53,42 +43,7 @@ void HandlerCallback(v8::Isolate* isolate, scoped_ptr options(converter.FromV8Value(value, context)); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(holder->callback, true, base::Passed(&options))); -} - -// func.bind(func, arg1, arg2). -// NB(zcbenz): Using C++11 version crashes VS. -v8::Local BindFunctionWith(v8::Isolate* isolate, - v8::Local context, - v8::Local func, - v8::Local arg1, - v8::Local arg2) { - v8::MaybeLocal bind = func->Get(mate::StringToV8(isolate, "bind")); - CHECK(!bind.IsEmpty()); - v8::Local bind_func = - v8::Local::Cast(bind.ToLocalChecked()); - v8::Local converted[] = { func, arg1, arg2 }; - return bind_func->Call( - context, func, arraysize(converted), converted).ToLocalChecked(); -} - -// Generate the callback that will be passed to |handler|. -v8::MaybeLocal GenerateCallback(v8::Isolate* isolate, - v8::Local context, - const ResponseCallback& callback) { - // The FunctionTemplate is cached. - if (g_handler_callback_.IsEmpty()) - g_handler_callback_.Reset( - isolate, - mate::CreateFunctionTemplate(isolate, base::Bind(&HandlerCallback))); - - v8::Local handler_callback = - v8::Local::New(isolate, g_handler_callback_); - CallbackHolder* holder = new CallbackHolder; - holder->callback = callback; - return BindFunctionWith(isolate, context, handler_callback->GetFunction(), - v8::External::New(isolate, holder), - v8::Object::New(isolate)); + base::Bind(callback, true, base::Passed(&options))); } } // namespace @@ -102,16 +57,10 @@ void AskForOptions(v8::Isolate* isolate, v8::HandleScope handle_scope(isolate); v8::Local context = isolate->GetCurrentContext(); v8::Context::Scope context_scope(context); - // We don't convert the callback to C++ directly because creating - // FunctionTemplate will cause memory leak since V8 never releases it. So we - // have to create the function object in JavaScript to work around it. - v8::MaybeLocal wrapped_callback = GenerateCallback( - isolate, context, callback); - if (wrapped_callback.IsEmpty()) { - callback.Run(false, nullptr); - return; - } - handler.Run(request, wrapped_callback.ToLocalChecked()); + v8::Local state = v8::Object::New(isolate); + handler.Run(request, + mate::ConvertToV8(isolate, + base::Bind(&HandlerCallback, callback, state))); } bool IsErrorOptions(base::Value* value, int* error) { From 54dad72d922d203e70878803dc9b75ead2ce3600 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 18:32:21 +0800 Subject: [PATCH 354/738] Don't leak TranslaterHolder --- atom/common/native_mate_converters/callback.cc | 9 +++++---- atom/common/native_mate_converters/callback.h | 11 +++-------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/atom/common/native_mate_converters/callback.cc b/atom/common/native_mate_converters/callback.cc index 0be90f63e757..dbfa3b4babef 100644 --- a/atom/common/native_mate_converters/callback.cc +++ b/atom/common/native_mate_converters/callback.cc @@ -4,21 +4,22 @@ #include "atom/common/native_mate_converters/callback.h" +#include "native_mate/wrappable.h" + namespace mate { namespace internal { namespace { -struct TranslaterHolder { +struct TranslaterHolder : public Wrappable { Translater translater; }; // Cached JavaScript version of |CallTranslater|. v8::Persistent g_call_translater; -void CallTranslater(v8::Local external, mate::Arguments* args) { - TranslaterHolder* holder = static_cast(external->Value()); +void CallTranslater(TranslaterHolder* holder, mate::Arguments* args) { holder->translater.Run(args); } @@ -54,7 +55,7 @@ v8::Local CreateFunctionFromTranslater( return BindFunctionWith(isolate, isolate->GetCurrentContext(), call_translater->GetFunction(), - v8::External::New(isolate, holder)); + holder->GetWrapper(isolate)); } } // namespace internal diff --git a/atom/common/native_mate_converters/callback.h b/atom/common/native_mate_converters/callback.h index 4349b9997b25..228fc0d3bb1d 100644 --- a/atom/common/native_mate_converters/callback.h +++ b/atom/common/native_mate_converters/callback.h @@ -101,21 +101,16 @@ struct NativeFunctionInvoker { } }; -// Create a static function that accepts generic callback. -template -Translater ConvertToTranslater(const base::Callback& val) { - return base::Bind(&NativeFunctionInvoker::Go, val); -} - } // namespace internal template -struct Converter > { +struct Converter> { static v8::Local ToV8(v8::Isolate* isolate, const base::Callback& val) { // We don't use CreateFunctionTemplate here because it creates a new // FunctionTemplate everytime, which is cached by V8 and causes leaks. - internal::Translater translater = internal::ConvertToTranslater(val); + internal::Translater translater = base::Bind( + &internal::NativeFunctionInvoker::Go, val); return internal::CreateFunctionFromTranslater(isolate, translater); } static bool FromV8(v8::Isolate* isolate, From d05255179a6b451041472354066f847384dfe787 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 19:34:01 +0800 Subject: [PATCH 355/738] Add login event for "app" module --- atom/browser/api/atom_api_app.cc | 25 +++++++++++--- atom/browser/api/atom_api_app.h | 1 + atom/browser/browser.cc | 4 +++ atom/browser/browser.h | 5 +++ atom/browser/browser_observer.h | 5 +++ atom/browser/login_handler.cc | 59 +++++++++++++++++++++++++++++++- atom/browser/login_handler.h | 15 ++++++-- 7 files changed, 106 insertions(+), 8 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index c79dea9f7c5c..436d76fb9022 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -13,10 +13,11 @@ #include "atom/browser/api/atom_api_menu.h" #include "atom/browser/api/atom_api_session.h" +#include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/browser.h" -#include "atom/browser/api/atom_api_web_contents.h" +#include "atom/browser/login_handler.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/node_includes.h" @@ -132,8 +133,6 @@ void OnClientCertificateSelected( v8::Isolate* isolate, std::shared_ptr delegate, mate::Arguments* args) { - v8::Locker locker(isolate); - v8::HandleScope handle_scope(isolate); mate::Dictionary cert_data; if (!(args->Length() == 1 && args->GetNext(&cert_data))) { args->ThrowError(); @@ -147,10 +146,18 @@ void OnClientCertificateSelected( net::X509Certificate::CreateCertificateListFromBytes( encoded_data.data(), encoded_data.size(), net::X509Certificate::FORMAT_AUTO); - delegate->ContinueWithCertificate(certs[0].get()); } +void PassLoginInformation(scoped_refptr login_handler, + mate::Arguments* args) { + base::string16 username, password; + if (args->GetNext(&username) && args->GetNext(&password)) + login_handler->Login(username, password); + else + login_handler->CancelAuth(); +} + } // namespace App::App() { @@ -233,6 +240,16 @@ void App::OnSelectCertificate( cert_request_info->client_certs[0].get()); } +void App::OnLogin(LoginHandler* login_handler) { + bool prevent_default = + Emit("login", base::Bind(&PassLoginInformation, + make_scoped_refptr(login_handler))); + + // Default behavior is to alwasy cancel the auth. + if (!prevent_default) + login_handler->CancelAuth(); +} + void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) { Emit("gpu-process-crashed"); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 94cd9bbc68f9..63cda4447e32 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -50,6 +50,7 @@ class App : public mate::EventEmitter, content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, scoped_ptr delegate) override; + void OnLogin(LoginHandler* login_handler) override; // content::GpuDataManagerObserver: void OnGpuProcessCrashed(base::TerminationStatus exit_code) override; diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 79ebe91a87e6..739921fda90f 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -134,6 +134,10 @@ void Browser::ClientCertificateSelector( delegate.Pass())); } +void Browser::RequestLogin(LoginHandler* login_handler) { + FOR_EACH_OBSERVER(BrowserObserver, observers_, OnLogin(login_handler)); +} + void Browser::NotifyAndShutdown() { if (is_shutdown_) return; diff --git a/atom/browser/browser.h b/atom/browser/browser.h index bae281d4d370..8719e18f3140 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -29,6 +29,8 @@ class MenuModel; namespace atom { +class LoginHandler; + // This class is used for control application-wide operations. class Browser : public WindowListObserver { public: @@ -122,6 +124,9 @@ class Browser : public WindowListObserver { net::SSLCertRequestInfo* cert_request_info, scoped_ptr delegate); + // Request basic auth login. + void RequestLogin(LoginHandler* login_handler); + void AddObserver(BrowserObserver* obs) { observers_.AddObserver(obs); } diff --git a/atom/browser/browser_observer.h b/atom/browser/browser_observer.h index 45e86e620f84..7dccbfbac3c5 100644 --- a/atom/browser/browser_observer.h +++ b/atom/browser/browser_observer.h @@ -20,6 +20,8 @@ class SSLCertRequestInfo; namespace atom { +class LoginHandler; + class BrowserObserver { public: // The browser is about to close all windows. @@ -57,6 +59,9 @@ class BrowserObserver { net::SSLCertRequestInfo* cert_request_info, scoped_ptr delegate) {} + // The browser requests HTTP login. + virtual void OnLogin(LoginHandler* login_handler) {} + protected: virtual ~BrowserObserver() {} }; diff --git a/atom/browser/login_handler.cc b/atom/browser/login_handler.cc index 1980cc133abc..ededcd0c8513 100644 --- a/atom/browser/login_handler.cc +++ b/atom/browser/login_handler.cc @@ -4,19 +4,76 @@ #include "atom/browser/login_handler.h" +#include "atom/browser/browser.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/resource_dispatcher_host.h" #include "net/base/auth.h" +#include "net/url_request/url_request.h" + +using content::BrowserThread; namespace atom { +namespace { + +// Helper to remove the ref from an net::URLRequest to the LoginHandler. +// Should only be called from the IO thread, since it accesses an +// net::URLRequest. +void ResetLoginHandlerForRequest(net::URLRequest* request) { + content::ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request); +} + +} // namespace + LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info, net::URLRequest* request) - : auth_info_(auth_info), request_(request), weak_factory_(this) { + : auth_info_(auth_info), request_(request) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&Browser::RequestLogin, + base::Unretained(Browser::Get()), + make_scoped_refptr(this))); } LoginHandler::~LoginHandler() { } +void LoginHandler::Login(const base::string16& username, + const base::string16& password) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&LoginHandler::DoLogin, this, username, password)); +} + +void LoginHandler::CancelAuth() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&LoginHandler::DoCancelAuth, this)); +} + void LoginHandler::OnRequestCancelled() { + request_ = nullptr; +} + +void LoginHandler::DoCancelAuth() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (request_) { + request_->CancelAuth(); + // Verify that CancelAuth doesn't destroy the request via our delegate. + DCHECK(request_ != nullptr); + ResetLoginHandlerForRequest(request_); + } +} + +void LoginHandler::DoLogin(const base::string16& username, + const base::string16& password) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (request_) { + request_->SetAuth(net::AuthCredentials(username, password)); + ResetLoginHandlerForRequest(request_); + } } } // namespace atom diff --git a/atom/browser/login_handler.h b/atom/browser/login_handler.h index 421e2e43837d..077e4b6cf950 100644 --- a/atom/browser/login_handler.h +++ b/atom/browser/login_handler.h @@ -5,7 +5,7 @@ #ifndef ATOM_BROWSER_LOGIN_HANDLER_H_ #define ATOM_BROWSER_LOGIN_HANDLER_H_ -#include "base/memory/weak_ptr.h" +#include "base/strings/string16.h" #include "content/public/browser/resource_dispatcher_host_login_delegate.h" namespace net { @@ -15,10 +15,17 @@ class URLRequest; namespace atom { +// Handles the HTTP basic auth, must be created on IO thread. class LoginHandler : public content::ResourceDispatcherHostLoginDelegate { public: LoginHandler(net::AuthChallengeInfo* auth_info, net::URLRequest* request); + // The auth is cancelled, must be called on UI thread. + void CancelAuth(); + + // Login with |username| and |password|, must be called on UI thread. + void Login(const base::string16& username, const base::string16& password); + protected: ~LoginHandler() override; @@ -26,6 +33,10 @@ class LoginHandler : public content::ResourceDispatcherHostLoginDelegate { void OnRequestCancelled() override; private: + // Must be called on IO thread. + void DoCancelAuth(); + void DoLogin(const base::string16& username, const base::string16& password); + // Who/where/what asked for the authentication. scoped_refptr auth_info_; @@ -33,8 +44,6 @@ class LoginHandler : public content::ResourceDispatcherHostLoginDelegate { // This should only be accessed on the IO loop. net::URLRequest* request_; - base::WeakPtrFactory weak_factory_; - DISALLOW_COPY_AND_ASSIGN(LoginHandler); }; From 131531219e172f70d374f315b7301a7c2b1e93f9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 20:13:06 +0800 Subject: [PATCH 356/738] Pass auth_info and request in "login" event --- atom/browser/api/atom_api_app.cc | 7 ++-- atom/browser/api/atom_api_protocol.cc | 17 +--------- atom/browser/login_handler.h | 3 ++ .../content_converter.cc | 34 +++++++++++++++++++ .../content_converter.h | 31 +++++++++++++++++ filenames.gypi | 2 ++ 6 files changed, 75 insertions(+), 19 deletions(-) create mode 100644 atom/common/native_mate_converters/content_converter.cc create mode 100644 atom/common/native_mate_converters/content_converter.h diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 436d76fb9022..db1f99352309 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -19,6 +19,7 @@ #include "atom/browser/browser.h" #include "atom/browser/login_handler.h" #include "atom/common/native_mate_converters/callback.h" +#include "atom/common/native_mate_converters/content_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/node_includes.h" #include "atom/common/options_switches.h" @@ -241,9 +242,9 @@ void App::OnSelectCertificate( } void App::OnLogin(LoginHandler* login_handler) { - bool prevent_default = - Emit("login", base::Bind(&PassLoginInformation, - make_scoped_refptr(login_handler))); + bool prevent_default = Emit( + "login", login_handler->request(), login_handler->auth_info(), + base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler))); // Default behavior is to alwasy cancel the auth. if (!prevent_default) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 661ab1b5cbdd..f6cc6d796557 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -12,27 +12,12 @@ #include "atom/browser/net/url_request_fetch_job.h" #include "atom/browser/net/url_request_string_job.h" #include "atom/common/native_mate_converters/callback.h" +#include "atom/common/native_mate_converters/content_converter.h" #include "atom/common/node_includes.h" #include "native_mate/dictionary.h" using content::BrowserThread; -namespace mate { - -template<> -struct Converter { - static v8::Local ToV8(v8::Isolate* isolate, - const net::URLRequest* val) { - return mate::ObjectTemplateBuilder(isolate) - .SetValue("method", val->method()) - .SetValue("url", val->url().spec()) - .SetValue("referrer", val->referrer()) - .Build()->NewInstance(); - } -}; - -} // namespace mate - namespace atom { namespace api { diff --git a/atom/browser/login_handler.h b/atom/browser/login_handler.h index 077e4b6cf950..60e0a7a5298d 100644 --- a/atom/browser/login_handler.h +++ b/atom/browser/login_handler.h @@ -26,6 +26,9 @@ class LoginHandler : public content::ResourceDispatcherHostLoginDelegate { // Login with |username| and |password|, must be called on UI thread. void Login(const base::string16& username, const base::string16& password); + const net::AuthChallengeInfo* auth_info() const { return auth_info_.get(); } + const net::URLRequest* request() const { return request_; } + protected: ~LoginHandler() override; diff --git a/atom/common/native_mate_converters/content_converter.cc b/atom/common/native_mate_converters/content_converter.cc new file mode 100644 index 000000000000..0ab9f272041e --- /dev/null +++ b/atom/common/native_mate_converters/content_converter.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/native_mate_converters/content_converter.h" + +#include "native_mate/dictionary.h" +#include "net/url_request/url_request.h" + +namespace mate { + +// static +v8::Local Converter::ToV8( + v8::Isolate* isolate, const net::URLRequest* val) { + mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); + dict.Set("method", val->method()); + dict.Set("url", val->url().spec()); + dict.Set("referrer", val->referrer()); + return mate::ConvertToV8(isolate, dict); +}; + +// static +v8::Local Converter::ToV8( + v8::Isolate* isolate, const net::AuthChallengeInfo* val) { + mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); + dict.Set("isProxy", val->is_proxy); + dict.Set("scheme", val->scheme); + dict.Set("host", val->challenger.host()); + dict.Set("port", static_cast(val->challenger.port())); + dict.Set("realm", val->realm); + return mate::ConvertToV8(isolate, dict); +}; + +} // namespace mate diff --git a/atom/common/native_mate_converters/content_converter.h b/atom/common/native_mate_converters/content_converter.h new file mode 100644 index 000000000000..0d4d5fe2cce0 --- /dev/null +++ b/atom/common/native_mate_converters/content_converter.h @@ -0,0 +1,31 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_ +#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_ + +#include "native_mate/converter.h" + +namespace net { +class AuthChallengeInfo; +class URLRequest; +} + +namespace mate { + +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + const net::URLRequest* val); +}; + +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + const net::AuthChallengeInfo* val); +}; + +} // namespace mate + +#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_ diff --git a/filenames.gypi b/filenames.gypi index 65bf6b79a2c2..f66485edd19d 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -306,6 +306,8 @@ 'atom/common/native_mate_converters/blink_converter.h', 'atom/common/native_mate_converters/callback.cc', 'atom/common/native_mate_converters/callback.h', + 'atom/common/native_mate_converters/content_converter.cc', + 'atom/common/native_mate_converters/content_converter.h', 'atom/common/native_mate_converters/file_path_converter.h', 'atom/common/native_mate_converters/gfx_converter.cc', 'atom/common/native_mate_converters/gfx_converter.h', From 4eac6b31b15c0a5df839be3c2f4238eef065b453 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 20:21:56 +0800 Subject: [PATCH 357/738] Also pass "webContents" in "login" event --- atom/browser/api/atom_api_app.cc | 1 + atom/browser/login_handler.cc | 18 +++++++++++++++++- atom/browser/login_handler.h | 12 ++++++++++++ .../content_converter.cc | 4 ++-- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index db1f99352309..5380d52ad693 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -244,6 +244,7 @@ void App::OnSelectCertificate( void App::OnLogin(LoginHandler* login_handler) { bool prevent_default = Emit( "login", login_handler->request(), login_handler->auth_info(), + api::WebContents::CreateFrom(isolate(), login_handler->GetWebContents()), base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler))); // Default behavior is to alwasy cancel the auth. diff --git a/atom/browser/login_handler.cc b/atom/browser/login_handler.cc index ededcd0c8513..ca6e5de57df0 100644 --- a/atom/browser/login_handler.cc +++ b/atom/browser/login_handler.cc @@ -6,7 +6,10 @@ #include "atom/browser/browser.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/resource_dispatcher_host.h" +#include "content/public/browser/resource_request_info.h" +#include "content/public/browser/web_contents.h" #include "net/base/auth.h" #include "net/url_request/url_request.h" @@ -27,7 +30,12 @@ void ResetLoginHandlerForRequest(net::URLRequest* request) { LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info, net::URLRequest* request) - : auth_info_(auth_info), request_(request) { + : auth_info_(auth_info), + request_(request), + render_process_host_id_(0), + render_frame_id_(0) { + content::ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderFrame( + &render_process_host_id_, &render_frame_id_); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&Browser::RequestLogin, base::Unretained(Browser::Get()), @@ -37,6 +45,14 @@ LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info, LoginHandler::~LoginHandler() { } +content::WebContents* LoginHandler::GetWebContents() const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( + render_process_host_id_, render_frame_id_); + return content::WebContents::FromRenderFrameHost(rfh); +} + void LoginHandler::Login(const base::string16& username, const base::string16& password) { DCHECK_CURRENTLY_ON(BrowserThread::UI); diff --git a/atom/browser/login_handler.h b/atom/browser/login_handler.h index 60e0a7a5298d..899bc8ca450e 100644 --- a/atom/browser/login_handler.h +++ b/atom/browser/login_handler.h @@ -8,6 +8,10 @@ #include "base/strings/string16.h" #include "content/public/browser/resource_dispatcher_host_login_delegate.h" +namespace content { +class WebContents; +} + namespace net { class AuthChallengeInfo; class URLRequest; @@ -20,6 +24,10 @@ class LoginHandler : public content::ResourceDispatcherHostLoginDelegate { public: LoginHandler(net::AuthChallengeInfo* auth_info, net::URLRequest* request); + // Returns the WebContents associated with the request, must be called on UI + // thread. + content::WebContents* GetWebContents() const; + // The auth is cancelled, must be called on UI thread. void CancelAuth(); @@ -47,6 +55,10 @@ class LoginHandler : public content::ResourceDispatcherHostLoginDelegate { // This should only be accessed on the IO loop. net::URLRequest* request_; + // Cached from the net::URLRequest, in case it goes NULL on us. + int render_process_host_id_; + int render_frame_id_; + DISALLOW_COPY_AND_ASSIGN(LoginHandler); }; diff --git a/atom/common/native_mate_converters/content_converter.cc b/atom/common/native_mate_converters/content_converter.cc index 0ab9f272041e..b6f3a2c1cc03 100644 --- a/atom/common/native_mate_converters/content_converter.cc +++ b/atom/common/native_mate_converters/content_converter.cc @@ -17,7 +17,7 @@ v8::Local Converter::ToV8( dict.Set("url", val->url().spec()); dict.Set("referrer", val->referrer()); return mate::ConvertToV8(isolate, dict); -}; +} // static v8::Local Converter::ToV8( @@ -29,6 +29,6 @@ v8::Local Converter::ToV8( dict.Set("port", static_cast(val->challenger.port())); dict.Set("realm", val->realm); return mate::ConvertToV8(isolate, dict); -}; +} } // namespace mate From f40a3f72d72dc9659dce0208abd298f4253a183a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 20:44:46 +0800 Subject: [PATCH 358/738] Converted callback can only be called for once --- atom/browser/net/js_asker.cc | 16 ++-------- .../common/native_mate_converters/callback.cc | 29 ++++++++++++++----- spec/api-protocol-spec.coffee | 12 +++++--- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index 444124b24b61..8f0d1d2b9577 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -16,18 +16,7 @@ namespace internal { namespace { // The callback which is passed to |handler|. -void HandlerCallback(const ResponseCallback& callback, - v8::Local state, - mate::Arguments* args) { - v8::Isolate* isolate = args->isolate(); - - // Check if the callback has already been called. - v8::Local called_symbol = mate::StringToSymbol(isolate, "called"); - if (state->Has(called_symbol)) - return; // no nothing - else - state->Set(called_symbol, v8::Boolean::New(isolate, true)); - +void HandlerCallback(const ResponseCallback& callback, mate::Arguments* args) { // If there is no argument passed then we failed. v8::Local value; if (!args->GetNext(&value)) { @@ -57,10 +46,9 @@ void AskForOptions(v8::Isolate* isolate, v8::HandleScope handle_scope(isolate); v8::Local context = isolate->GetCurrentContext(); v8::Context::Scope context_scope(context); - v8::Local state = v8::Object::New(isolate); handler.Run(request, mate::ConvertToV8(isolate, - base::Bind(&HandlerCallback, callback, state))); + base::Bind(&HandlerCallback, callback))); } bool IsErrorOptions(base::Value* value, int* error) { diff --git a/atom/common/native_mate_converters/callback.cc b/atom/common/native_mate_converters/callback.cc index dbfa3b4babef..3bcb748689fb 100644 --- a/atom/common/native_mate_converters/callback.cc +++ b/atom/common/native_mate_converters/callback.cc @@ -4,23 +4,36 @@ #include "atom/common/native_mate_converters/callback.h" -#include "native_mate/wrappable.h" - namespace mate { namespace internal { namespace { -struct TranslaterHolder : public Wrappable { +struct TranslaterHolder { Translater translater; }; // Cached JavaScript version of |CallTranslater|. v8::Persistent g_call_translater; -void CallTranslater(TranslaterHolder* holder, mate::Arguments* args) { +void CallTranslater(v8::Local external, + v8::Local state, + mate::Arguments* args) { + v8::Isolate* isolate = args->isolate(); + + // Check if the callback has already been called. + v8::Local called_symbol = mate::StringToSymbol(isolate, "called"); + if (state->Has(called_symbol)) { + args->ThrowError("callback can only be called for once"); + return; + } else { + state->Set(called_symbol, v8::Boolean::New(isolate, true)); + } + + TranslaterHolder* holder = static_cast(external->Value()); holder->translater.Run(args); + delete holder; } // func.bind(func, arg1). @@ -28,12 +41,13 @@ void CallTranslater(TranslaterHolder* holder, mate::Arguments* args) { v8::Local BindFunctionWith(v8::Isolate* isolate, v8::Local context, v8::Local func, - v8::Local arg1) { + v8::Local arg1, + v8::Local arg2) { v8::MaybeLocal bind = func->Get(mate::StringToV8(isolate, "bind")); CHECK(!bind.IsEmpty()); v8::Local bind_func = v8::Local::Cast(bind.ToLocalChecked()); - v8::Local converted[] = { func, arg1 }; + v8::Local converted[] = { func, arg1, arg2 }; return bind_func->Call( context, func, arraysize(converted), converted).ToLocalChecked(); } @@ -55,7 +69,8 @@ v8::Local CreateFunctionFromTranslater( return BindFunctionWith(isolate, isolate->GetCurrentContext(), call_translater->GetFunction(), - holder->GetWrapper(isolate)); + v8::External::New(isolate, holder), + v8::Object::New(isolate)); } } // namespace internal diff --git a/spec/api-protocol-spec.coffee b/spec/api-protocol-spec.coffee index 8990f8029ee1..4ac7786b057b 100644 --- a/spec/api-protocol-spec.coffee +++ b/spec/api-protocol-spec.coffee @@ -23,8 +23,10 @@ describe 'protocol module', -> it 'does not crash when handler is called twice', (done) -> doubleHandler = (request, callback) -> - callback(text) - callback() + try + callback(text) + callback() + catch protocol.registerStringProtocol protocolName, doubleHandler, (error) -> return done(error) if error $.ajax @@ -302,8 +304,10 @@ describe 'protocol module', -> it 'does not crash when handler is called twice', (done) -> doubleHandler = (request, callback) -> - callback(text) - callback() + try + callback(text) + callback() + catch protocol.interceptStringProtocol 'http', doubleHandler, (error) -> return done(error) if error $.ajax From 569e87035add289e89a80e1aa74363dd85a964c0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 21:00:39 +0800 Subject: [PATCH 359/738] Also emit "login" on WebContents --- atom/browser/api/atom_api_app.cc | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 5380d52ad693..21a553e4d1d5 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -242,12 +242,26 @@ void App::OnSelectCertificate( } void App::OnLogin(LoginHandler* login_handler) { - bool prevent_default = Emit( - "login", login_handler->request(), login_handler->auth_info(), - api::WebContents::CreateFrom(isolate(), login_handler->GetWebContents()), + // Convert the args explicitly since they will be passed for twice. + v8::Locker locker(isolate()); + v8::HandleScope handle_scope(isolate()); + auto web_contents = + WebContents::CreateFrom(isolate(), login_handler->GetWebContents()); + auto request = mate::ConvertToV8(isolate(), login_handler->request()); + auto auth_info = mate::ConvertToV8(isolate(), login_handler->auth_info()); + auto callback = mate::ConvertToV8( + isolate(), base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler))); - // Default behavior is to alwasy cancel the auth. + bool prevent_default = + Emit("login", web_contents, request, auth_info, callback); + + // Also pass it to WebContents. + if (!prevent_default) + prevent_default = + web_contents->Emit("login", request, auth_info, callback); + + // Default behavior is to always cancel the auth. if (!prevent_default) login_handler->CancelAuth(); } From 862c3187f58daae649d9c360147025e9f5909279 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 21:14:00 +0800 Subject: [PATCH 360/738] docs: login event --- docs/api/app.md | 47 +++++++++++++++++++++++++++++++++------- docs/api/web-contents.md | 21 ++++++++++++++++++ 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/docs/api/app.md b/docs/api/app.md index bb1509b68688..dbb46698f926 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -133,18 +133,23 @@ Emitted when a new [browserWindow](browser-window.md) is created. ### Event: 'select-certificate' -Emitted when a client certificate is requested. - Returns: * `event` Event -* `webContents` [WebContents](browser-window.md#class-webcontents) -* `url` String +* `webContents` [WebContents](web-contents.md) +* `url` URL * `certificateList` [Objects] * `data` PEM encoded data * `issuerName` Issuer's Common Name * `callback` Function +Emitted when a client certificate is requested. + +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. + ```javascript app.on('select-certificate', function(event, host, url, list, callback) { event.preventDefault(); @@ -152,10 +157,36 @@ app.on('select-certificate', function(event, host, url, list, callback) { }) ``` -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. +### Event: 'login' + +Returns: + +* `event` Event +* `webContents` [WebContents](web-contents.md) +* `request` Object + * `method` String + * `url` URL + * `referrer` URL +* `authInfo` Object + * `isProxy` Boolean + * `scheme` String + * `host` String + * `port` Integer + * `realm` String +* `callback` Function + +Emitted when `webContents` wants to do basic auth. + +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. + +```javascript +app.on('login', function(event, webContents, request, authInfo, callback) { + event.preventDefault(); + callback('username', 'secret'); +}) +``` ### Event: 'gpu-process-crashed' diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 3113356e34b4..52a06b87edb1 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -167,6 +167,27 @@ Emitted when DevTools is closed. Emitted when DevTools is focused / opened. +### Event: 'login' + +Returns: + +* `event` Event +* `request` Object + * `method` String + * `url` URL + * `referrer` URL +* `authInfo` Object + * `isProxy` Boolean + * `scheme` String + * `host` String + * `port` Integer + * `realm` String +* `callback` Function + +Emitted when `webContents` wants to do basic auth. + +The usage is the same with [the `login` event of `app`](app.md#event-login). + ## Instance Methods The `webContents` object has the following instance methods: From 51ba37440d9008ed4a0cb5293ec15d3331367017 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 28 Oct 2015 21:20:08 +0800 Subject: [PATCH 361/738] Guard against multiple calls of auth --- atom/browser/login_handler.cc | 16 +++++++++++++++- atom/browser/login_handler.h | 9 +++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/atom/browser/login_handler.cc b/atom/browser/login_handler.cc index ca6e5de57df0..7a1a77cc2b13 100644 --- a/atom/browser/login_handler.cc +++ b/atom/browser/login_handler.cc @@ -30,7 +30,8 @@ void ResetLoginHandlerForRequest(net::URLRequest* request) { LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info, net::URLRequest* request) - : auth_info_(auth_info), + : handled_auth_(false), + auth_info_(auth_info), request_(request), render_process_host_id_(0), render_frame_id_(0) { @@ -56,6 +57,8 @@ content::WebContents* LoginHandler::GetWebContents() const { void LoginHandler::Login(const base::string16& username, const base::string16& password) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (TestAndSetAuthHandled()) + return; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&LoginHandler::DoLogin, this, username, password)); @@ -63,14 +66,25 @@ void LoginHandler::Login(const base::string16& username, void LoginHandler::CancelAuth() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (TestAndSetAuthHandled()) + return; BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(&LoginHandler::DoCancelAuth, this)); } void LoginHandler::OnRequestCancelled() { + TestAndSetAuthHandled(); request_ = nullptr; } +// Marks authentication as handled and returns the previous handled state. +bool LoginHandler::TestAndSetAuthHandled() { + base::AutoLock lock(handled_auth_lock_); + bool was_handled = handled_auth_; + handled_auth_ = true; + return was_handled; +} + void LoginHandler::DoCancelAuth() { DCHECK_CURRENTLY_ON(BrowserThread::IO); diff --git a/atom/browser/login_handler.h b/atom/browser/login_handler.h index 899bc8ca450e..52ec1abf5b1a 100644 --- a/atom/browser/login_handler.h +++ b/atom/browser/login_handler.h @@ -6,6 +6,7 @@ #define ATOM_BROWSER_LOGIN_HANDLER_H_ #include "base/strings/string16.h" +#include "base/synchronization/lock.h" #include "content/public/browser/resource_dispatcher_host_login_delegate.h" namespace content { @@ -48,6 +49,14 @@ class LoginHandler : public content::ResourceDispatcherHostLoginDelegate { void DoCancelAuth(); void DoLogin(const base::string16& username, const base::string16& password); + // Marks authentication as handled and returns the previous handled + // state. + bool TestAndSetAuthHandled(); + + // True if we've handled auth (Login or CancelAuth has been called). + bool handled_auth_; + mutable base::Lock handled_auth_lock_; + // Who/where/what asked for the authentication. scoped_refptr auth_info_; From 974b5005bcf21055280b5a1caf8563fb9a572b69 Mon Sep 17 00:00:00 2001 From: Antoine Pairet Date: Wed, 28 Oct 2015 14:28:30 +0100 Subject: [PATCH 362/738] Update from @jlord --- docs/api/remote.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/api/remote.md b/docs/api/remote.md index 14805923562c..aa7114e278ee 100644 --- a/docs/api/remote.md +++ b/docs/api/remote.md @@ -3,12 +3,7 @@ The `remote` module provides a simple way to do inter-process communication (IPC) between the renderer process (web page) and the main process. -In Electron, only GUI-related modules are available in the renderer process. -Without the `remote` module, users who want to call a main process API in -the renderer process will have to explicitly send inter-process messages -to the main process. With the `remote` module, you can invoke methods of the -main process object without explicitly sending inter-process messages, similar -to Java's [RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation). +In Electron, GUI-related modules (such as `dialog`, `menu` etc.) are only available in the main process, not in the renderer process. In order to use them from the render process, the ipc module is necessary to send inter-process messages to the main process. With the `remote` module, you can invoke methods of the main process object without explicitly sending inter-process messages, similar to Java's [RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation). An example of creating a browser window from a renderer process: From 4efff0800716262d69f24494ef4cff38358746d8 Mon Sep 17 00:00:00 2001 From: Antoine Pairet Date: Wed, 28 Oct 2015 17:55:18 +0100 Subject: [PATCH 363/738] Fix comments from @jlord --- docs/api/remote.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/remote.md b/docs/api/remote.md index aa7114e278ee..d80312c8e1a5 100644 --- a/docs/api/remote.md +++ b/docs/api/remote.md @@ -3,7 +3,7 @@ The `remote` module provides a simple way to do inter-process communication (IPC) between the renderer process (web page) and the main process. -In Electron, GUI-related modules (such as `dialog`, `menu` etc.) are only available in the main process, not in the renderer process. In order to use them from the render process, the ipc module is necessary to send inter-process messages to the main process. With the `remote` module, you can invoke methods of the main process object without explicitly sending inter-process messages, similar to Java's [RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation). +In Electron, GUI-related modules (such as `dialog`, `menu` etc.) are only available in the main process, not in the renderer process. In order to use them from the renderer process, the `ipc` module is necessary to send inter-process messages to the main process. With the `remote` module, you can invoke methods of the main process object without explicitly sending inter-process messages, similar to Java's [RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation). An example of creating a browser window from a renderer process: From 16eafdb0ce1bf1dd9a4f8590d15f2837515e2634 Mon Sep 17 00:00:00 2001 From: taemu Date: Thu, 29 Oct 2015 03:22:08 +0900 Subject: [PATCH 364/738] Fix remove boolean parameter at IsSwitchEnabled function --- atom/renderer/atom_renderer_client.cc | 38 ++++++++++----------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 10dd2541b9cf..362b0b8026a7 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -39,16 +39,8 @@ namespace atom { namespace { bool IsSwitchEnabled(base::CommandLine* command_line, - const char* switch_string, - bool* enabled) { - std::string value = command_line->GetSwitchValueASCII(switch_string); - if (value == "true") - *enabled = true; - else if (value == "false") - *enabled = false; - else - return false; - return true; + const char* switch_string) { + return command_line->GetSwitchValueASCII(switch_string) == "true"; } // Helper class to forward the messages to the client. @@ -216,10 +208,8 @@ bool AtomRendererClient::ShouldOverridePageVisibilityState( const content::RenderFrame* render_frame, blink::WebPageVisibilityState* override_state) { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - bool b; - if (IsSwitchEnabled(command_line, switches::kPageVisibility, &b) - && b) { + if (IsSwitchEnabled(command_line, switches::kPageVisibility)) { *override_state = blink::WebPageVisibilityStateVisible; return true; } @@ -229,17 +219,17 @@ bool AtomRendererClient::ShouldOverridePageVisibilityState( void AtomRendererClient::EnableWebRuntimeFeatures() { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - bool b; - if (IsSwitchEnabled(command_line, switches::kExperimentalFeatures, &b)) - blink::WebRuntimeFeatures::enableExperimentalFeatures(b); - if (IsSwitchEnabled(command_line, switches::kExperimentalCanvasFeatures, &b)) - blink::WebRuntimeFeatures::enableExperimentalCanvasFeatures(b); - if (IsSwitchEnabled(command_line, switches::kOverlayScrollbars, &b)) - blink::WebRuntimeFeatures::enableOverlayScrollbars(b); - if (IsSwitchEnabled(command_line, switches::kOverlayFullscreenVideo, &b)) - blink::WebRuntimeFeatures::enableOverlayFullscreenVideo(b); - if (IsSwitchEnabled(command_line, switches::kSharedWorker, &b)) - blink::WebRuntimeFeatures::enableSharedWorker(b); + + if (IsSwitchEnabled(command_line, switches::kExperimentalFeatures)) + blink::WebRuntimeFeatures::enableExperimentalFeatures(true); + if (IsSwitchEnabled(command_line, switches::kExperimentalCanvasFeatures)) + blink::WebRuntimeFeatures::enableExperimentalCanvasFeatures(true); + if (IsSwitchEnabled(command_line, switches::kOverlayScrollbars)) + blink::WebRuntimeFeatures::enableOverlayScrollbars(true); + if (IsSwitchEnabled(command_line, switches::kOverlayFullscreenVideo)) + blink::WebRuntimeFeatures::enableOverlayFullscreenVideo(true); + if (IsSwitchEnabled(command_line, switches::kSharedWorker)) + blink::WebRuntimeFeatures::enableSharedWorker(true); } } // namespace atom From 2ac40cc28eb7160cc5493311f3945de3b90ace70 Mon Sep 17 00:00:00 2001 From: Omri Litov Date: Wed, 28 Oct 2015 21:30:52 +0200 Subject: [PATCH 365/738] Added .idea to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0c6f4cb79dd0..b8a221c9e52f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +/.idea/ /build/ /dist/ /external_binaries/ From f22837523f1dd67b2eafd7f2e75a7ff185906f3c Mon Sep 17 00:00:00 2001 From: Omri Litov Date: Wed, 28 Oct 2015 21:54:50 +0200 Subject: [PATCH 366/738] Use WPARAM as uint64_t and LPARAM as int64_t --- atom/browser/api/atom_api_window.cc | 2 +- atom/browser/api/atom_api_window.h | 3 ++- atom/browser/native_window.cc | 3 ++- atom/browser/native_window_observer.h | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 077dffe0bc5c..bf0d0fad721c 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -190,7 +190,7 @@ void Window::OnExecuteWindowsCommand(const std::string& command_name) { } #if defined(OS_WIN) -void Window::OnWindowMessage(UINT message, WPARAM w_param, uint64_t l_param) { +void Window::OnWindowMessage(UINT message, uint64_t w_param, int64_t l_param) { if (IsWindowMessageHooked(message)) { messages_callback_map_[message].Run(w_param, l_param); } diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index f4bc4cdba01a..ea86150ae1e3 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -77,7 +77,8 @@ class Window : public mate::TrackableObject, void OnExecuteWindowsCommand(const std::string& command_name) override; #if defined(OS_WIN) - void OnWindowMessage(UINT message, WPARAM w_param, uint64_t l_param) override; + void OnWindowMessage(UINT message, uint64_t w_param, + int64_t l_param) override; #endif // mate::Wrappable: diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 6e38f4028745..a1b6f95c3ac9 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -469,7 +469,8 @@ void NativeWindow::NotifyWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) { FOR_EACH_OBSERVER( NativeWindowObserver, observers_, - OnWindowMessage(message, w_param, static_cast(l_param))); + OnWindowMessage(message, static_cast(w_param), + static_cast(l_param))); } #endif diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 240a7277fa09..559d5f72a804 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -61,7 +61,7 @@ class NativeWindowObserver { // Called when window message received #if defined(OS_WIN) - virtual void OnWindowMessage(UINT message, WPARAM wparam, uint64_t lparam) {} + virtual void OnWindowMessage(UINT message, uint64_t wparam, int64_t lparam) {} #endif // Called when renderer is hung. From ef038257d194611852d13d057b88dd0ed814bc3f Mon Sep 17 00:00:00 2001 From: Omri Litov Date: Thu, 29 Oct 2015 03:00:44 +0200 Subject: [PATCH 367/738] Returns buffer instead of WPARAM and LPARAM --- atom/browser/api/atom_api_window.cc | 16 ++++++++++++++-- atom/browser/api/atom_api_window.h | 9 ++++++--- atom/browser/native_window.cc | 4 ++-- atom/browser/native_window_observer.h | 2 +- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index bf0d0fad721c..352b9284cf45 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -190,9 +190,21 @@ void Window::OnExecuteWindowsCommand(const std::string& command_name) { } #if defined(OS_WIN) -void Window::OnWindowMessage(UINT message, uint64_t w_param, int64_t l_param) { +v8::Local Window::ToBuffer(void* val, int size) { + auto buffer = node::Buffer::New(isolate(), static_cast(val), size); + + if (buffer.IsEmpty()) { + return v8::Null(isolate()); + } else { + return buffer.ToLocalChecked(); + } +} + +void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) { if (IsWindowMessageHooked(message)) { - messages_callback_map_[message].Run(w_param, l_param); + messages_callback_map_[message].Run( + ToBuffer(static_cast(&w_param), sizeof(WPARAM)), + ToBuffer(static_cast(&l_param), sizeof(LPARAM))); } } #endif diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index ea86150ae1e3..ffbd9b63b40a 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -77,8 +77,8 @@ class Window : public mate::TrackableObject, void OnExecuteWindowsCommand(const std::string& command_name) override; #if defined(OS_WIN) - void OnWindowMessage(UINT message, uint64_t w_param, - int64_t l_param) override; + void OnWindowMessage(UINT message, WPARAM w_param, + LPARAM l_param) override; #endif // mate::Wrappable: @@ -150,7 +150,10 @@ class Window : public mate::TrackableObject, void SetAspectRatio(double aspect_ratio, mate::Arguments* args); #if defined(OS_WIN) - typedef base::Callback MessageCallback; + v8::Local ToBuffer(void* val, int size); + + typedef base::Callback, + v8::Local)> MessageCallback; typedef std::map MessageCallbackMap; MessageCallbackMap messages_callback_map_; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index a1b6f95c3ac9..bf400dc8c74e 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -469,8 +469,8 @@ void NativeWindow::NotifyWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) { FOR_EACH_OBSERVER( NativeWindowObserver, observers_, - OnWindowMessage(message, static_cast(w_param), - static_cast(l_param))); + OnWindowMessage(message, w_param, + l_param)); } #endif diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 559d5f72a804..a76f314129f6 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -61,7 +61,7 @@ class NativeWindowObserver { // Called when window message received #if defined(OS_WIN) - virtual void OnWindowMessage(UINT message, uint64_t wparam, int64_t lparam) {} + virtual void OnWindowMessage(UINT message, WPARAM wparam, LPARAM lparam) {} #endif // Called when renderer is hung. From 917b33dbe7f9bfac3f668dd386f67f737b0d0c6e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 29 Oct 2015 10:53:48 +0800 Subject: [PATCH 368/738] Small code cleanup --- atom/browser/api/atom_api_window.cc | 24 ++++++++++++------------ atom/browser/api/atom_api_window.h | 15 +++++++-------- atom/browser/native_window.cc | 10 ++++------ atom/browser/native_window_observer.h | 2 +- 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 352b9284cf45..497b5a6930ff 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -60,6 +60,16 @@ void OnCapturePageDone( callback.Run(gfx::Image::CreateFrom1xBitmap(bitmap)); } +#if defined(OS_WIN) +v8::Local ToBuffer(v8::Isolate* isolate, void* val, int size) { + auto buffer = node::Buffer::New(isolate, static_cast(val), size); + if (buffer.IsEmpty()) + return v8::Null(isolate); + else + return buffer.ToLocalChecked(); +} +#endif + } // namespace @@ -190,21 +200,11 @@ void Window::OnExecuteWindowsCommand(const std::string& command_name) { } #if defined(OS_WIN) -v8::Local Window::ToBuffer(void* val, int size) { - auto buffer = node::Buffer::New(isolate(), static_cast(val), size); - - if (buffer.IsEmpty()) { - return v8::Null(isolate()); - } else { - return buffer.ToLocalChecked(); - } -} - void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) { if (IsWindowMessageHooked(message)) { messages_callback_map_[message].Run( - ToBuffer(static_cast(&w_param), sizeof(WPARAM)), - ToBuffer(static_cast(&l_param), sizeof(LPARAM))); + ToBuffer(isolate(), static_cast(&w_param), sizeof(WPARAM)), + ToBuffer(isolate(), static_cast(&l_param), sizeof(LPARAM))); } } #endif diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index ffbd9b63b40a..1c582551cc93 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -77,8 +77,7 @@ class Window : public mate::TrackableObject, void OnExecuteWindowsCommand(const std::string& command_name) override; #if defined(OS_WIN) - void OnWindowMessage(UINT message, WPARAM w_param, - LPARAM l_param) override; + void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override; #endif // mate::Wrappable: @@ -150,15 +149,10 @@ class Window : public mate::TrackableObject, void SetAspectRatio(double aspect_ratio, mate::Arguments* args); #if defined(OS_WIN) - v8::Local ToBuffer(void* val, int size); - typedef base::Callback, v8::Local)> MessageCallback; - typedef std::map MessageCallbackMap; - MessageCallbackMap messages_callback_map_; - bool HookWindowMessage(UINT message, - const MessageCallback& callback); + bool HookWindowMessage(UINT message, const MessageCallback& callback); bool IsWindowMessageHooked(UINT message); void UnhookWindowMessage(UINT message); void UnhookAllWindowMessages(); @@ -174,6 +168,11 @@ class Window : public mate::TrackableObject, int32_t ID() const; v8::Local WebContents(v8::Isolate* isolate); +#if defined(OS_WIN) + typedef std::map MessageCallbackMap; + MessageCallbackMap messages_callback_map_; +#endif + v8::Global web_contents_; v8::Global menu_; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index bf400dc8c74e..8027fdfa4c1c 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -465,12 +465,10 @@ void NativeWindow::NotifyWindowExecuteWindowsCommand( } #if defined(OS_WIN) -void NativeWindow::NotifyWindowMessage(UINT message, WPARAM w_param, - LPARAM l_param) { - FOR_EACH_OBSERVER( - NativeWindowObserver, observers_, - OnWindowMessage(message, w_param, - l_param)); +void NativeWindow::NotifyWindowMessage( + UINT message, WPARAM w_param, LPARAM l_param) { + FOR_EACH_OBSERVER(NativeWindowObserver, observers_, + OnWindowMessage(message, w_param, l_param)); } #endif diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index a76f314129f6..54004a300d94 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -61,7 +61,7 @@ class NativeWindowObserver { // Called when window message received #if defined(OS_WIN) - virtual void OnWindowMessage(UINT message, WPARAM wparam, LPARAM lparam) {} + virtual void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {} #endif // Called when renderer is hung. From c7372f8f9311d297cca1d87a5b8ce2b82683bd1c Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 29 Oct 2015 14:18:07 +0900 Subject: [PATCH 369/738] Update as upstream --- docs-translations/ko-KR/api/app.md | 44 ++++++++++++++++++++++----- docs-translations/ko-KR/api/remote.md | 8 ++--- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index d1263d00abc3..a443d1252f8e 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -134,18 +134,22 @@ Returns: ### Event: 'select-certificate' -사용자 인증이 요청되었을 때 발생하는 이벤트 입니다. - Returns: * `event` Event -* `webContents` [WebContents](browser-window.md#class-webcontents) -* `url` String +* `webContents` [WebContents](web-contents.md) +* `url` URL * `certificateList` [Objects] * `data` PEM으로 인코딩된 데이터 * `issuerName` 발급자의 공통 이름 * `callback` Function +사용자 인증이 요청되었을 때 발생하는 이벤트 입니다. + +`url`은 클라이언트 인증서를 요청하는 탐색 항목에 해당합니다. +그리고 `callback`은 목록에서 필터링된 항목과 함께 호출될 필요가 있습니다. +이 이벤트에서의 `event.preventDefault()` 호출은 초기 인증 때 저장된 데이터를 사용하는 것을 막습니다. + ```javascript app.on('select-certificate', function(event, host, url, list, callback) { event.preventDefault(); @@ -153,12 +157,36 @@ app.on('select-certificate', function(event, host, url, list, callback) { }) ``` -`url`에 대한 +### Event: 'login' -`url`은 클라이언트 인증서를 요청하는 탐색 항목에 해당합니다. -그리고 `callback`은 목록에서 필터링된 항목과 함께 호출될 필요가 있습니다. +Returns: -이 이벤트에서의 `event.preventDefault()` 호출은 초기 인증에 사용한 저장된 데이터를 사용하는 것을 막습니다. +* `event` Event +* `webContents` [WebContents](web-contents.md) +* `request` Object + * `method` String + * `url` URL + * `referrer` URL +* `authInfo` Object + * `isProxy` Boolean + * `scheme` String + * `host` String + * `port` Integer + * `realm` String +* `callback` Function + +`webContents`가 기본 인증을 요청할 때 발생하는 이벤트입니다. + +기본 동작은 인증 요청을 모두 취소시킵니다. +동작을 새로 정의하려면 반드시 `event.preventDefault()`를 호출한 후 +`callback(username, password)` 형태의 콜백을 호출하여 인증을 처리해야 합니다. + +```javascript +app.on('login', function(event, webContents, request, authInfo, callback) { + event.preventDefault(); + callback('username', 'secret'); +}) +``` ### Event: 'gpu-process-crashed' diff --git a/docs-translations/ko-KR/api/remote.md b/docs-translations/ko-KR/api/remote.md index 756acd429a1b..462c99263961 100644 --- a/docs-translations/ko-KR/api/remote.md +++ b/docs-translations/ko-KR/api/remote.md @@ -2,10 +2,10 @@ `remote` 모듈은 메인 프로세스와 랜더러 프로세스(웹 페이지) 사이의 inter-process (IPC) 통신을 간단하게 추상화 한 모듈입니다. -Electron의 랜더러 프로세스에선 GUI와 관련 없는 모듈만 사용할 수 있습니다. -기본적으로 랜더러 프로세스에서 메인 프로세스의 API를 사용하려면 메인 프로세스와 inter-process 통신을 해야 합니다. -하지만 `remote` 모듈을 사용하면 따로 inter-process 통신을 하지 않고 직접 명시적으로 모듈을 사용할 수 있습니다. -Java의 [RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation)와 개념이 비슷합니다. +Electron의 메인 프로세스에선 GUI와 관련 있는(`dialog`, `menu`등) 모듈만 사용할 수 있습니다. +랜더러 프로세스에서 이러한 모듈들을 사용하려면 `ipc` 모듈을 통해 메인 프로세스와 inter-process 통신을 해야합니다. +또한, `remote` 모듈을 사용하면 inter-process 통신을 하지 않고도 간단한 메서드를 통해 직접 메인 프로세스의 모듈과 메서드를 사용할 수 있습니다. +이 개념은 Java의 [RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation)와 비슷합니다. 다음 예제는 랜더러 프로세스에서 브라우저 창을 만드는 예제입니다: From b8cc2e1649edfc39e6c08e457979d84dc8144efd Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 29 Oct 2015 14:22:00 +0900 Subject: [PATCH 370/738] Remove extra spaces --- 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 dbb46698f926..204155cfa053 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -178,7 +178,7 @@ Returns: Emitted when `webContents` wants to do basic auth. The default behavior is to cancel all authentications, to override this you -should prevent the default behavior with `event.preventDefault()` and call +should prevent the default behavior with `event.preventDefault()` and call `callback(username, password)` with the credentials. ```javascript From 62d15953ffea6932622c771daba56b408a311fee Mon Sep 17 00:00:00 2001 From: Robo Date: Wed, 28 Oct 2015 03:45:46 +0530 Subject: [PATCH 371/738] remote: track listeners for browser side --- atom/browser/lib/rpc-server.coffee | 7 +++++++ atom/common/api/lib/callbacks-registry.coffee | 4 ++++ spec/api-ipc-spec.coffee | 13 +++++++++++++ 3 files changed, 24 insertions(+) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 6b1f95a841ab..c4d91830b5f1 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -3,6 +3,9 @@ path = require 'path' objectsRegistry = require './objects-registry.js' v8Util = process.atomBinding 'v8_util' +# caches callback with their registry ID. +rendererCallbacks = {} + # Convert a real value into meta data. valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta = type: typeof value @@ -74,6 +77,8 @@ unwrapArgs = (sender, args) -> objectsRegistry.once "clear-#{sender.getId()}", -> rendererReleased = true + return rendererCallbacks[meta.id] if rendererCallbacks[meta.id]? + ret = -> if rendererReleased throw new Error("Attempting to call a function in a renderer window @@ -81,7 +86,9 @@ unwrapArgs = (sender, args) -> sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments) v8Util.setDestructor ret, -> return if rendererReleased + delete rendererCallbacks[meta.id] sender.send 'ATOM_RENDERER_RELEASE_CALLBACK', meta.id + rendererCallbacks[meta.id] = ret ret else throw new TypeError("Unknown type: #{meta.type}") diff --git a/atom/common/api/lib/callbacks-registry.coffee b/atom/common/api/lib/callbacks-registry.coffee index d4c37f087b1e..5151640b2b80 100644 --- a/atom/common/api/lib/callbacks-registry.coffee +++ b/atom/common/api/lib/callbacks-registry.coffee @@ -7,6 +7,10 @@ class CallbacksRegistry add: (callback) -> id = ++@nextId + for id,value of @callbacks + if value == callback + return id + # Capture the location of the function and put it in the ID string, # so that release errors can be tracked down easily. regexp = /at (.*)/gi diff --git a/spec/api-ipc-spec.coffee b/spec/api-ipc-spec.coffee index 142f06c00ff3..1155aa73e83d 100644 --- a/spec/api-ipc-spec.coffee +++ b/spec/api-ipc-spec.coffee @@ -88,3 +88,16 @@ describe 'ipc module', -> w.destroy() done() w.loadUrl 'file://' + path.join(fixtures, 'api', 'send-sync-message.html') + + describe 'remote listeners', -> + it 'can be added and removed correctly', -> + count = 0 + w = new BrowserWindow(show: false) + listener = () -> + count += 1 + w.removeListener 'blur', listener + w.on 'blur', listener + w.emit 'blur' + w.emit 'blur' + assert.equal count, 1 + w.destroy() From eae7c840b7ce8a954c67efb60553102dcde9f106 Mon Sep 17 00:00:00 2001 From: Robo Date: Wed, 28 Oct 2015 21:29:46 +0530 Subject: [PATCH 372/738] use idweakmap for holding callbacks in browser --- atom/browser/lib/rpc-server.coffee | 13 ++++---- atom/common/api/atom_api_v8_util.cc | 8 +++++ atom/common/api/lib/callbacks-registry.coffee | 12 ++++---- atom/common/id_weak_map.cc | 30 +++++++++++++++++++ atom/common/id_weak_map.h | 11 ++++++- atom/renderer/api/lib/remote.coffee | 2 +- 6 files changed, 63 insertions(+), 13 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index c4d91830b5f1..13c8ceb16e03 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -3,8 +3,8 @@ path = require 'path' objectsRegistry = require './objects-registry.js' v8Util = process.atomBinding 'v8_util' -# caches callback with their registry ID. -rendererCallbacks = {} +# weak refereence to callback with their registry ID. +rendererCallbacks = v8Util.createWeakMap() # Convert a real value into meta data. valueToMeta = (sender, value, optimizeSimpleObject=false) -> @@ -77,18 +77,19 @@ unwrapArgs = (sender, args) -> objectsRegistry.once "clear-#{sender.getId()}", -> rendererReleased = true - return rendererCallbacks[meta.id] if rendererCallbacks[meta.id]? + if rendererCallbacks.has(meta.id) + return rendererCallbacks.get(meta.id) ret = -> if rendererReleased throw new Error("Attempting to call a function in a renderer window - that has been closed or released. Function provided here: #{meta.id}.") + that has been closed or released. Function provided here: #{meta.location}.") sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments) v8Util.setDestructor ret, -> return if rendererReleased - delete rendererCallbacks[meta.id] + rendererCallbacks.remove meta.id sender.send 'ATOM_RENDERER_RELEASE_CALLBACK', meta.id - rendererCallbacks[meta.id] = ret + rendererCallbacks.set meta.id, ret ret else throw new TypeError("Unknown type: #{meta.type}") diff --git a/atom/common/api/atom_api_v8_util.cc b/atom/common/api/atom_api_v8_util.cc index bba3399a8dbd..4a321f84d80e 100644 --- a/atom/common/api/atom_api_v8_util.cc +++ b/atom/common/api/atom_api_v8_util.cc @@ -3,7 +3,9 @@ // found in the LICENSE file. #include "atom/common/api/object_life_monitor.h" +#include "atom/common/id_weak_map.h" #include "atom/common/node_includes.h" +#include "native_mate/handle.h" #include "native_mate/dictionary.h" #include "v8/include/v8-profiler.h" @@ -46,6 +48,11 @@ void TakeHeapSnapshot(v8::Isolate* isolate) { isolate->GetHeapProfiler()->TakeHeapSnapshot(); } +mate::Handle CreateWeakMap(v8::Isolate* isolate) { + auto handle = mate::CreateHandle(isolate, new atom::IDWeakMap); + return handle; +} + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); @@ -56,6 +63,7 @@ void Initialize(v8::Local exports, v8::Local unused, dict.SetMethod("getObjectHash", &GetObjectHash); dict.SetMethod("setDestructor", &SetDestructor); dict.SetMethod("takeHeapSnapshot", &TakeHeapSnapshot); + dict.SetMethod("createWeakMap", &CreateWeakMap); } } // namespace diff --git a/atom/common/api/lib/callbacks-registry.coffee b/atom/common/api/lib/callbacks-registry.coffee index 5151640b2b80..b777f7a462df 100644 --- a/atom/common/api/lib/callbacks-registry.coffee +++ b/atom/common/api/lib/callbacks-registry.coffee @@ -1,3 +1,5 @@ +v8Util = process.atomBinding 'v8_util' + module.exports = class CallbacksRegistry constructor: -> @@ -7,10 +9,6 @@ class CallbacksRegistry add: (callback) -> id = ++@nextId - for id,value of @callbacks - if value == callback - return id - # Capture the location of the function and put it in the ID string, # so that release errors can be tracked down easily. regexp = /at (.*)/gi @@ -21,10 +19,14 @@ class CallbacksRegistry continue if location.indexOf('(native)') isnt -1 continue if location.indexOf('atom.asar') isnt -1 [x, filenameAndLine] = /([^/^\)]*)\)?$/gi.exec(location) - id = "#{filenameAndLine} (#{id})" break + if v8Util.getHiddenValue(callback, 'metaId')? + return v8Util.getHiddenValue(callback, 'metaId') + @callbacks[id] = callback + v8Util.setHiddenValue callback, 'metaId', id + v8Util.setHiddenValue callback, 'location', filenameAndLine id get: (id) -> diff --git a/atom/common/id_weak_map.cc b/atom/common/id_weak_map.cc index c5c4b60cac5c..3d7e1513597c 100644 --- a/atom/common/id_weak_map.cc +++ b/atom/common/id_weak_map.cc @@ -8,6 +8,18 @@ #include "native_mate/converter.h" +namespace mate { + +template +struct Converter> { + static v8::Local ToV8(v8::Isolate* isolate, + v8::MaybeLocal val) { + return ConvertToV8(isolate, val.ToLocalChecked()); + } +}; + +} // namespace mate + namespace atom { namespace { @@ -41,6 +53,15 @@ int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Local object) { return id; } +void IDWeakMap::Set(v8::Isolate* isolate, + int32_t id, + v8::Local object) { + auto global = make_linked_ptr(new v8::Global(isolate, object)); + ObjectKey* key = new ObjectKey(id, this); + global->SetWeak(key, OnObjectGC, v8::WeakCallbackType::kParameter); + map_[id] = global; +} + v8::MaybeLocal IDWeakMap::Get(v8::Isolate* isolate, int32_t id) { auto iter = map_.find(id); if (iter == map_.end()) @@ -85,4 +106,13 @@ int32_t IDWeakMap::GetNextID() { return ++next_id_; } +mate::ObjectTemplateBuilder IDWeakMap::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + return mate::ObjectTemplateBuilder(isolate) + .SetMethod("set", &IDWeakMap::Set) + .SetMethod("get", &IDWeakMap::Get) + .SetMethod("has", &IDWeakMap::Has) + .SetMethod("remove", &IDWeakMap::Remove); +} + } // namespace atom diff --git a/atom/common/id_weak_map.h b/atom/common/id_weak_map.h index 9fe71ebb616f..c291f76a430e 100644 --- a/atom/common/id_weak_map.h +++ b/atom/common/id_weak_map.h @@ -9,12 +9,14 @@ #include #include "base/memory/linked_ptr.h" +#include "native_mate/object_template_builder.h" +#include "native_mate/wrappable.h" #include "v8/include/v8.h" namespace atom { // Like ES6's WeakMap, but the key is Integer and the value is Weak Pointer. -class IDWeakMap { +class IDWeakMap : public mate::Wrappable { public: IDWeakMap(); ~IDWeakMap(); @@ -22,6 +24,9 @@ class IDWeakMap { // Adds |object| to WeakMap and returns its allocated |id|. int32_t Add(v8::Isolate* isolate, v8::Local object); + // Sets the object to WeakMap with the given |id|. + void Set(v8::Isolate* isolate, int32_t id, v8::Local object); + // Gets the object from WeakMap by its |id|. v8::MaybeLocal Get(v8::Isolate* isolate, int32_t id); @@ -40,6 +45,10 @@ class IDWeakMap { // Clears the weak map. void Clear(); + protected: + mate::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override; + private: // Returns next available ID. int32_t GetNextID(); diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index 8a5565f06562..b5a3a694ee37 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -33,7 +33,7 @@ wrapArgs = (args, visited=[]) -> else if typeof value is 'function' and v8Util.getHiddenValue value, 'returnValue' type: 'function-with-return-value', value: valueToMeta(value()) else if typeof value is 'function' - type: 'function', id: callbacksRegistry.add(value) + type: 'function', id: callbacksRegistry.add(value), location: v8Util.getHiddenValue value, 'location' else type: 'value', value: value From ac4df34ecd8a306e5cf71fd6696fae4362f3e515 Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 29 Oct 2015 16:27:30 +0530 Subject: [PATCH 373/738] create binding to idweakmap --- atom/browser/lib/rpc-server.coffee | 11 ++-- atom/common/api/atom_api_v8_util.cc | 7 --- atom/common/api/atom_api_weak_map.cc | 79 ++++++++++++++++++++++++++++ atom/common/api/atom_api_weak_map.h | 46 ++++++++++++++++ atom/common/id_weak_map.cc | 21 -------- atom/common/id_weak_map.h | 8 +-- atom/common/node_bindings.cc | 1 + filenames.gypi | 2 + 8 files changed, 135 insertions(+), 40 deletions(-) create mode 100644 atom/common/api/atom_api_weak_map.cc create mode 100644 atom/common/api/atom_api_weak_map.h diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 13c8ceb16e03..3a4f896da5ec 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -2,9 +2,10 @@ ipc = require 'ipc' path = require 'path' objectsRegistry = require './objects-registry.js' v8Util = process.atomBinding 'v8_util' +WeakMap = process.atomBinding('weak_map').WeakMap -# weak refereence to callback with their registry ID. -rendererCallbacks = v8Util.createWeakMap() +# Weak reference to callback with their registry ID. +rendererCallbacks = new WeakMap() # Convert a real value into meta data. valueToMeta = (sender, value, optimizeSimpleObject=false) -> @@ -73,13 +74,13 @@ unwrapArgs = (sender, args) -> returnValue = metaToValue meta.value -> returnValue when 'function' + if rendererCallbacks.has(meta.id) + return rendererCallbacks.get(meta.id) + rendererReleased = false objectsRegistry.once "clear-#{sender.getId()}", -> rendererReleased = true - if rendererCallbacks.has(meta.id) - return rendererCallbacks.get(meta.id) - ret = -> if rendererReleased throw new Error("Attempting to call a function in a renderer window diff --git a/atom/common/api/atom_api_v8_util.cc b/atom/common/api/atom_api_v8_util.cc index 4a321f84d80e..1c8c8c9f7e09 100644 --- a/atom/common/api/atom_api_v8_util.cc +++ b/atom/common/api/atom_api_v8_util.cc @@ -5,7 +5,6 @@ #include "atom/common/api/object_life_monitor.h" #include "atom/common/id_weak_map.h" #include "atom/common/node_includes.h" -#include "native_mate/handle.h" #include "native_mate/dictionary.h" #include "v8/include/v8-profiler.h" @@ -48,11 +47,6 @@ void TakeHeapSnapshot(v8::Isolate* isolate) { isolate->GetHeapProfiler()->TakeHeapSnapshot(); } -mate::Handle CreateWeakMap(v8::Isolate* isolate) { - auto handle = mate::CreateHandle(isolate, new atom::IDWeakMap); - return handle; -} - void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); @@ -63,7 +57,6 @@ void Initialize(v8::Local exports, v8::Local unused, dict.SetMethod("getObjectHash", &GetObjectHash); dict.SetMethod("setDestructor", &SetDestructor); dict.SetMethod("takeHeapSnapshot", &TakeHeapSnapshot); - dict.SetMethod("createWeakMap", &CreateWeakMap); } } // namespace diff --git a/atom/common/api/atom_api_weak_map.cc b/atom/common/api/atom_api_weak_map.cc new file mode 100644 index 000000000000..6cc75c43c927 --- /dev/null +++ b/atom/common/api/atom_api_weak_map.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/api/atom_api_weak_map.h" + +#include "atom/common/node_includes.h" +#include "native_mate/constructor.h" +#include "native_mate/dictionary.h" + +namespace atom { + +namespace api { + +WeakMap::WeakMap() { + id_weak_map_.reset(new atom::IDWeakMap); +} + +WeakMap::~WeakMap() { +} + +void WeakMap::Set(v8::Isolate* isolate, + int32_t id, + v8::Local object) { + id_weak_map_->Set(isolate, id, object); +} + +v8::Local WeakMap::Get(v8::Isolate* isolate, int32_t id) { + return id_weak_map_->Get(isolate, id).ToLocalChecked(); +} + +bool WeakMap::Has(int32_t id) { + return id_weak_map_->Has(id); +} + +void WeakMap::Remove(int32_t id) { + id_weak_map_->Remove(id); +} + +bool WeakMap::IsDestroyed() const { + return !id_weak_map_; +} + +// static +void WeakMap::BuildPrototype(v8::Isolate* isolate, + v8::Local prototype) { + mate::ObjectTemplateBuilder(isolate, prototype) + .SetMethod("set", &WeakMap::Set) + .SetMethod("get", &WeakMap::Get) + .SetMethod("has", &WeakMap::Has) + .SetMethod("remove", &WeakMap::Remove); +} + +// static +mate::Wrappable* WeakMap::Create(v8::Isolate* isolate) { + return new WeakMap; +} + +} // namespace api + +} // namespace atom + +namespace { + +using atom::api::WeakMap; + +void Initialize(v8::Local exports, v8::Local unused, + v8::Local context, void* priv) { + v8::Isolate* isolate = context->GetIsolate(); + v8::Local constructor = mate::CreateConstructor( + isolate, "WeakMap", base::Bind(&WeakMap::Create)); + mate::Dictionary weak_map(isolate, constructor); + mate::Dictionary dict(isolate, exports); + dict.Set("WeakMap", weak_map); +} + +} // namespace + +NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_weak_map, Initialize) diff --git a/atom/common/api/atom_api_weak_map.h b/atom/common/api/atom_api_weak_map.h new file mode 100644 index 000000000000..7c747e1a384e --- /dev/null +++ b/atom/common/api/atom_api_weak_map.h @@ -0,0 +1,46 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_API_ATOM_API_WEAK_MAP_H_ +#define ATOM_COMMON_API_ATOM_API_WEAK_MAP_H_ + +#include "atom/common/id_weak_map.h" +#include "native_mate/object_template_builder.h" +#include "native_mate/handle.h" + +namespace atom { + +namespace api { + +class WeakMap : public mate::Wrappable { + public: + static mate::Wrappable* Create(v8::Isolate* isolate); + + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); + + protected: + WeakMap(); + virtual ~WeakMap(); + + // mate::Wrappable: + bool IsDestroyed() const override; + + private: + // Api for IDWeakMap. + void Set(v8::Isolate* isolate, int32_t id, v8::Local object); + v8::Local Get(v8::Isolate* isolate, int32_t id); + bool Has(int32_t id); + void Remove(int32_t id); + + scoped_ptr id_weak_map_; + + DISALLOW_COPY_AND_ASSIGN(WeakMap); +}; + +} // namespace api + +} // namespace atom + +#endif // ATOM_COMMON_API_ATOM_API_WEAK_MAP_H_ diff --git a/atom/common/id_weak_map.cc b/atom/common/id_weak_map.cc index 3d7e1513597c..7fda009e0ee1 100644 --- a/atom/common/id_weak_map.cc +++ b/atom/common/id_weak_map.cc @@ -8,18 +8,6 @@ #include "native_mate/converter.h" -namespace mate { - -template -struct Converter> { - static v8::Local ToV8(v8::Isolate* isolate, - v8::MaybeLocal val) { - return ConvertToV8(isolate, val.ToLocalChecked()); - } -}; - -} // namespace mate - namespace atom { namespace { @@ -106,13 +94,4 @@ int32_t IDWeakMap::GetNextID() { return ++next_id_; } -mate::ObjectTemplateBuilder IDWeakMap::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return mate::ObjectTemplateBuilder(isolate) - .SetMethod("set", &IDWeakMap::Set) - .SetMethod("get", &IDWeakMap::Get) - .SetMethod("has", &IDWeakMap::Has) - .SetMethod("remove", &IDWeakMap::Remove); -} - } // namespace atom diff --git a/atom/common/id_weak_map.h b/atom/common/id_weak_map.h index c291f76a430e..688e85cd0cce 100644 --- a/atom/common/id_weak_map.h +++ b/atom/common/id_weak_map.h @@ -9,14 +9,12 @@ #include #include "base/memory/linked_ptr.h" -#include "native_mate/object_template_builder.h" -#include "native_mate/wrappable.h" #include "v8/include/v8.h" namespace atom { // Like ES6's WeakMap, but the key is Integer and the value is Weak Pointer. -class IDWeakMap : public mate::Wrappable { +class IDWeakMap { public: IDWeakMap(); ~IDWeakMap(); @@ -45,10 +43,6 @@ class IDWeakMap : public mate::Wrappable { // Clears the weak map. void Clear(); - protected: - mate::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate) override; - private: // Returns next available ID. int32_t GetNextID(); diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index 2da68854ad14..b6fcdb82f819 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -52,6 +52,7 @@ REFERENCE_MODULE(atom_common_native_image); REFERENCE_MODULE(atom_common_screen); REFERENCE_MODULE(atom_common_shell); REFERENCE_MODULE(atom_common_v8_util); +REFERENCE_MODULE(atom_common_weak_map); REFERENCE_MODULE(atom_renderer_ipc); REFERENCE_MODULE(atom_renderer_web_frame); #undef REFERENCE_MODULE diff --git a/filenames.gypi b/filenames.gypi index f66485edd19d..0f5b794a0361 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -260,6 +260,8 @@ 'atom/common/api/atom_api_native_image_mac.mm', 'atom/common/api/atom_api_shell.cc', 'atom/common/api/atom_api_v8_util.cc', + 'atom/common/api/atom_api_weak_map.cc', + 'atom/common/api/atom_api_weak_map.h', 'atom/common/api/atom_bindings.cc', 'atom/common/api/atom_bindings.h', 'atom/common/api/event_emitter_caller.cc', From 3a154ab8ead41151977ef857490610a895f5ee87 Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 29 Oct 2015 16:52:12 +0530 Subject: [PATCH 374/738] add line and column values to callback id --- atom/browser/lib/rpc-server.coffee | 4 +- atom/common/api/atom_api_id_weak_map.cc | 79 +++++++++++++++++++ ..._api_weak_map.h => atom_api_id_weak_map.h} | 16 ++-- atom/common/api/atom_api_v8_util.cc | 1 - atom/common/api/atom_api_weak_map.cc | 79 ------------------- atom/common/api/lib/callbacks-registry.coffee | 8 +- atom/common/node_bindings.cc | 2 +- filenames.gypi | 4 +- 8 files changed, 97 insertions(+), 96 deletions(-) create mode 100644 atom/common/api/atom_api_id_weak_map.cc rename atom/common/api/{atom_api_weak_map.h => atom_api_id_weak_map.h} (72%) delete mode 100644 atom/common/api/atom_api_weak_map.cc diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 3a4f896da5ec..40e1b0e46ac7 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -2,10 +2,10 @@ ipc = require 'ipc' path = require 'path' objectsRegistry = require './objects-registry.js' v8Util = process.atomBinding 'v8_util' -WeakMap = process.atomBinding('weak_map').WeakMap +IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap # Weak reference to callback with their registry ID. -rendererCallbacks = new WeakMap() +rendererCallbacks = new IDWeakMap() # Convert a real value into meta data. valueToMeta = (sender, value, optimizeSimpleObject=false) -> diff --git a/atom/common/api/atom_api_id_weak_map.cc b/atom/common/api/atom_api_id_weak_map.cc new file mode 100644 index 000000000000..bdc298fa0c49 --- /dev/null +++ b/atom/common/api/atom_api_id_weak_map.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/api/atom_api_id_weak_map.h" + +#include "atom/common/node_includes.h" +#include "native_mate/constructor.h" +#include "native_mate/dictionary.h" + +namespace atom { + +namespace api { + +IDWeakMap::IDWeakMap() { + id_weak_map_.reset(new atom::IDWeakMap); +} + +IDWeakMap::~IDWeakMap() { +} + +void IDWeakMap::Set(v8::Isolate* isolate, + int32_t id, + v8::Local object) { + id_weak_map_->Set(isolate, id, object); +} + +v8::Local IDWeakMap::Get(v8::Isolate* isolate, int32_t id) { + return id_weak_map_->Get(isolate, id).ToLocalChecked(); +} + +bool IDWeakMap::Has(int32_t id) { + return id_weak_map_->Has(id); +} + +void IDWeakMap::Remove(int32_t id) { + id_weak_map_->Remove(id); +} + +bool IDWeakMap::IsDestroyed() const { + return !id_weak_map_; +} + +// static +void IDWeakMap::BuildPrototype(v8::Isolate* isolate, + v8::Local prototype) { + mate::ObjectTemplateBuilder(isolate, prototype) + .SetMethod("set", &IDWeakMap::Set) + .SetMethod("get", &IDWeakMap::Get) + .SetMethod("has", &IDWeakMap::Has) + .SetMethod("remove", &IDWeakMap::Remove); +} + +// static +mate::Wrappable* IDWeakMap::Create(v8::Isolate* isolate) { + return new IDWeakMap; +} + +} // namespace api + +} // namespace atom + +namespace { + +using atom::api::IDWeakMap; + +void Initialize(v8::Local exports, v8::Local unused, + v8::Local context, void* priv) { + v8::Isolate* isolate = context->GetIsolate(); + v8::Local constructor = mate::CreateConstructor( + isolate, "IDWeakMap", base::Bind(&IDWeakMap::Create)); + mate::Dictionary id_weak_map(isolate, constructor); + mate::Dictionary dict(isolate, exports); + dict.Set("IDWeakMap", id_weak_map); +} + +} // namespace + +NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_id_weak_map, Initialize) diff --git a/atom/common/api/atom_api_weak_map.h b/atom/common/api/atom_api_id_weak_map.h similarity index 72% rename from atom/common/api/atom_api_weak_map.h rename to atom/common/api/atom_api_id_weak_map.h index 7c747e1a384e..3acdddc9c75f 100644 --- a/atom/common/api/atom_api_weak_map.h +++ b/atom/common/api/atom_api_id_weak_map.h @@ -2,8 +2,8 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#ifndef ATOM_COMMON_API_ATOM_API_WEAK_MAP_H_ -#define ATOM_COMMON_API_ATOM_API_WEAK_MAP_H_ +#ifndef ATOM_COMMON_API_ATOM_API_ID_WEAK_MAP_H_ +#define ATOM_COMMON_API_ATOM_API_ID_WEAK_MAP_H_ #include "atom/common/id_weak_map.h" #include "native_mate/object_template_builder.h" @@ -13,7 +13,7 @@ namespace atom { namespace api { -class WeakMap : public mate::Wrappable { +class IDWeakMap : public mate::Wrappable { public: static mate::Wrappable* Create(v8::Isolate* isolate); @@ -21,8 +21,8 @@ class WeakMap : public mate::Wrappable { v8::Local prototype); protected: - WeakMap(); - virtual ~WeakMap(); + IDWeakMap(); + virtual ~IDWeakMap(); // mate::Wrappable: bool IsDestroyed() const override; @@ -34,13 +34,13 @@ class WeakMap : public mate::Wrappable { bool Has(int32_t id); void Remove(int32_t id); - scoped_ptr id_weak_map_; + scoped_ptr id_weak_map_; - DISALLOW_COPY_AND_ASSIGN(WeakMap); + DISALLOW_COPY_AND_ASSIGN(IDWeakMap); }; } // namespace api } // namespace atom -#endif // ATOM_COMMON_API_ATOM_API_WEAK_MAP_H_ +#endif // ATOM_COMMON_API_ATOM_API_ID_WEAK_MAP_H_ diff --git a/atom/common/api/atom_api_v8_util.cc b/atom/common/api/atom_api_v8_util.cc index 1c8c8c9f7e09..bba3399a8dbd 100644 --- a/atom/common/api/atom_api_v8_util.cc +++ b/atom/common/api/atom_api_v8_util.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "atom/common/api/object_life_monitor.h" -#include "atom/common/id_weak_map.h" #include "atom/common/node_includes.h" #include "native_mate/dictionary.h" #include "v8/include/v8-profiler.h" diff --git a/atom/common/api/atom_api_weak_map.cc b/atom/common/api/atom_api_weak_map.cc deleted file mode 100644 index 6cc75c43c927..000000000000 --- a/atom/common/api/atom_api_weak_map.cc +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2015 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/common/api/atom_api_weak_map.h" - -#include "atom/common/node_includes.h" -#include "native_mate/constructor.h" -#include "native_mate/dictionary.h" - -namespace atom { - -namespace api { - -WeakMap::WeakMap() { - id_weak_map_.reset(new atom::IDWeakMap); -} - -WeakMap::~WeakMap() { -} - -void WeakMap::Set(v8::Isolate* isolate, - int32_t id, - v8::Local object) { - id_weak_map_->Set(isolate, id, object); -} - -v8::Local WeakMap::Get(v8::Isolate* isolate, int32_t id) { - return id_weak_map_->Get(isolate, id).ToLocalChecked(); -} - -bool WeakMap::Has(int32_t id) { - return id_weak_map_->Has(id); -} - -void WeakMap::Remove(int32_t id) { - id_weak_map_->Remove(id); -} - -bool WeakMap::IsDestroyed() const { - return !id_weak_map_; -} - -// static -void WeakMap::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { - mate::ObjectTemplateBuilder(isolate, prototype) - .SetMethod("set", &WeakMap::Set) - .SetMethod("get", &WeakMap::Get) - .SetMethod("has", &WeakMap::Has) - .SetMethod("remove", &WeakMap::Remove); -} - -// static -mate::Wrappable* WeakMap::Create(v8::Isolate* isolate) { - return new WeakMap; -} - -} // namespace api - -} // namespace atom - -namespace { - -using atom::api::WeakMap; - -void Initialize(v8::Local exports, v8::Local unused, - v8::Local context, void* priv) { - v8::Isolate* isolate = context->GetIsolate(); - v8::Local constructor = mate::CreateConstructor( - isolate, "WeakMap", base::Bind(&WeakMap::Create)); - mate::Dictionary weak_map(isolate, constructor); - mate::Dictionary dict(isolate, exports); - dict.Set("WeakMap", weak_map); -} - -} // namespace - -NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_weak_map, Initialize) diff --git a/atom/common/api/lib/callbacks-registry.coffee b/atom/common/api/lib/callbacks-registry.coffee index b777f7a462df..57f5d0343dc2 100644 --- a/atom/common/api/lib/callbacks-registry.coffee +++ b/atom/common/api/lib/callbacks-registry.coffee @@ -7,6 +7,9 @@ class CallbacksRegistry @callbacks = {} add: (callback) -> + if v8Util.getHiddenValue(callback, 'metaId')? + return v8Util.getHiddenValue(callback, 'metaId') + id = ++@nextId # Capture the location of the function and put it in the ID string, @@ -19,11 +22,10 @@ class CallbacksRegistry continue if location.indexOf('(native)') isnt -1 continue if location.indexOf('atom.asar') isnt -1 [x, filenameAndLine] = /([^/^\)]*)\)?$/gi.exec(location) + [x, line, column] = /(\d+):(\d+)/g.exec(filenameAndLine) + id += parseInt(line) + parseInt(column) break - if v8Util.getHiddenValue(callback, 'metaId')? - return v8Util.getHiddenValue(callback, 'metaId') - @callbacks[id] = callback v8Util.setHiddenValue callback, 'metaId', id v8Util.setHiddenValue callback, 'location', filenameAndLine diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index b6fcdb82f819..10da202da70d 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -48,11 +48,11 @@ REFERENCE_MODULE(atom_browser_window); REFERENCE_MODULE(atom_common_asar); REFERENCE_MODULE(atom_common_clipboard); REFERENCE_MODULE(atom_common_crash_reporter); +REFERENCE_MODULE(atom_common_id_weak_map); REFERENCE_MODULE(atom_common_native_image); REFERENCE_MODULE(atom_common_screen); REFERENCE_MODULE(atom_common_shell); REFERENCE_MODULE(atom_common_v8_util); -REFERENCE_MODULE(atom_common_weak_map); REFERENCE_MODULE(atom_renderer_ipc); REFERENCE_MODULE(atom_renderer_web_frame); #undef REFERENCE_MODULE diff --git a/filenames.gypi b/filenames.gypi index 0f5b794a0361..ba739764f492 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -255,13 +255,13 @@ 'atom/common/api/atom_api_asar.cc', 'atom/common/api/atom_api_clipboard.cc', 'atom/common/api/atom_api_crash_reporter.cc', + 'atom/common/api/atom_api_id_weak_map.cc', + 'atom/common/api/atom_api_id_weak_map.h', 'atom/common/api/atom_api_native_image.cc', 'atom/common/api/atom_api_native_image.h', 'atom/common/api/atom_api_native_image_mac.mm', 'atom/common/api/atom_api_shell.cc', 'atom/common/api/atom_api_v8_util.cc', - 'atom/common/api/atom_api_weak_map.cc', - 'atom/common/api/atom_api_weak_map.h', 'atom/common/api/atom_bindings.cc', 'atom/common/api/atom_bindings.h', 'atom/common/api/event_emitter_caller.cc', From 8cd8495df7f55f5c46e155a97dff9dcf7e99a861 Mon Sep 17 00:00:00 2001 From: Simon Knight Date: Fri, 30 Oct 2015 16:10:46 +1030 Subject: [PATCH 375/738] fix capital I -> i in isDocumentEdited Uncaught Exception: TypeError: mainWindow.IsDocumentEdited is not a function --- docs/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index d7bf5be374d4..fbac6b10863b 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -594,7 +594,7 @@ Returns the pathname of the file the window represents. Specifies whether the window’s document has been edited, and the icon in title bar will become grey when set to `true`. -### `win.IsDocumentEdited()` _OS X_ +### `win.isDocumentEdited()` _OS X_ Whether the window's document has been edited. From 21a7c459d821266331660f82f76efcd5adf661e0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 30 Oct 2015 13:12:20 +0800 Subject: [PATCH 376/738] Bump v0.34.2 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/atom.gyp b/atom.gyp index d4b4f67b6310..7b88df4d8013 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.34.1', + 'version%': '0.34.2', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index aff46850004f..a703c01a766c 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.34.1 + 0.34.2 CFBundleShortVersionString - 0.34.1 + 0.34.2 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 3adf196e8ba5..8401e1d7d09e 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,34,1,0 - PRODUCTVERSION 0,34,1,0 + FILEVERSION 0,34,2,0 + PRODUCTVERSION 0,34,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.34.1" + VALUE "FileVersion", "0.34.2" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.34.1" + VALUE "ProductVersion", "0.34.2" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 1f8b8dec714f..5b1dc4ab44a6 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 34 -#define ATOM_PATCH_VERSION 1 +#define ATOM_PATCH_VERSION 2 #define ATOM_VERSION_IS_RELEASE 1 From 9c6987742103c1a2984ac9be2d3ddeb1e0c2070f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 30 Oct 2015 10:30:08 +0100 Subject: [PATCH 377/738] Allow v8 to optimize fs.readFileSync --- atom/common/lib/asar.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/common/lib/asar.coffee b/atom/common/lib/asar.coffee index d2a7799fa694..e7f845bba928 100644 --- a/atom/common/lib/asar.coffee +++ b/atom/common/lib/asar.coffee @@ -254,7 +254,8 @@ exports.wrapFsWithAsar = (fs) -> openSync = fs.openSync readFileSync = fs.readFileSync - fs.readFileSync = (p, options) -> + fs.readFileSync = (p, opts) -> + options = opts # this allows v8 to optimize this function [isAsar, asarPath, filePath] = splitPath p return readFileSync.apply this, arguments unless isAsar From 95ef73ebc16ed2b1592e5602a8756bddb9b4759e Mon Sep 17 00:00:00 2001 From: "Michael J. Zoidl" Date: Fri, 30 Oct 2015 12:17:30 +0100 Subject: [PATCH 378/738] Update autoUpdater api docs The event `quitAndUpdate` event changed to `quitAndInstall` --- docs/api/auto-updater.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/auto-updater.md b/docs/api/auto-updater.md index 7649f0f10489..972f93ea5922 100644 --- a/docs/api/auto-updater.md +++ b/docs/api/auto-updater.md @@ -82,7 +82,7 @@ once it is set. Asks the server whether there is an update. You must call `setFeedUrl` before using this API. -### `autoUpdater.quitAndUpdate()` +### `autoUpdater.quitAndInstall()` Restarts the app and install the update after it has been downloaded. It should only be called after `update-downloaded` has been emitted. From 2c59f4567e2e1b707b0e5493188f0106801837e4 Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 30 Oct 2015 08:34:40 +0530 Subject: [PATCH 379/738] use webcontents id to identify callbacks --- atom/browser/lib/rpc-server.coffee | 15 ++++++++++++--- atom/common/api/atom_api_id_weak_map.cc | 4 ++-- atom/common/api/atom_api_id_weak_map.h | 4 ++-- atom/common/api/lib/callbacks-registry.coffee | 2 -- atom/common/id_weak_map.cc | 15 ++++++--------- atom/common/id_weak_map.h | 6 +++--- 6 files changed, 25 insertions(+), 21 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 40e1b0e46ac7..eb97c721396f 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -4,8 +4,8 @@ objectsRegistry = require './objects-registry.js' v8Util = process.atomBinding 'v8_util' IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap -# Weak reference to callback with their registry ID. -rendererCallbacks = new IDWeakMap() +# Object mapping from webcontents id to their renderer callbacks weakmap. +rendererRegistry = {} # Convert a real value into meta data. valueToMeta = (sender, value, optimizeSimpleObject=false) -> @@ -74,11 +74,18 @@ unwrapArgs = (sender, args) -> returnValue = metaToValue meta.value -> returnValue when 'function' + webContentsId = sender.getId() + rendererCallbacks = rendererRegistry[webContentsId] + if not rendererCallbacks? + # Weak reference to callbacks with their ID + rendererCallbacks = new IDWeakMap() + rendererRegistry[webContentsId] = rendererCallbacks + if rendererCallbacks.has(meta.id) return rendererCallbacks.get(meta.id) rendererReleased = false - objectsRegistry.once "clear-#{sender.getId()}", -> + objectsRegistry.once "clear-#{webContentsId}", -> rendererReleased = true ret = -> @@ -109,6 +116,8 @@ callFunction = (event, func, caller, args) -> # Send by BrowserWindow when its render view is deleted. process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) -> + if rendererRegistry.id? + delete rendererRegistry.id objectsRegistry.clear id ipc.on 'ATOM_BROWSER_REQUIRE', (event, module) -> diff --git a/atom/common/api/atom_api_id_weak_map.cc b/atom/common/api/atom_api_id_weak_map.cc index bdc298fa0c49..8c17e8330ccc 100644 --- a/atom/common/api/atom_api_id_weak_map.cc +++ b/atom/common/api/atom_api_id_weak_map.cc @@ -12,11 +12,11 @@ namespace atom { namespace api { -IDWeakMap::IDWeakMap() { - id_weak_map_.reset(new atom::IDWeakMap); +IDWeakMap::IDWeakMap() : id_weak_map_(new atom::IDWeakMap) { } IDWeakMap::~IDWeakMap() { + id_weak_map_ = nullptr; } void IDWeakMap::Set(v8::Isolate* isolate, diff --git a/atom/common/api/atom_api_id_weak_map.h b/atom/common/api/atom_api_id_weak_map.h index 3acdddc9c75f..4a2f8e397a80 100644 --- a/atom/common/api/atom_api_id_weak_map.h +++ b/atom/common/api/atom_api_id_weak_map.h @@ -22,7 +22,7 @@ class IDWeakMap : public mate::Wrappable { protected: IDWeakMap(); - virtual ~IDWeakMap(); + ~IDWeakMap(); // mate::Wrappable: bool IsDestroyed() const override; @@ -34,7 +34,7 @@ class IDWeakMap : public mate::Wrappable { bool Has(int32_t id); void Remove(int32_t id); - scoped_ptr id_weak_map_; + atom::IDWeakMap* id_weak_map_; DISALLOW_COPY_AND_ASSIGN(IDWeakMap); }; diff --git a/atom/common/api/lib/callbacks-registry.coffee b/atom/common/api/lib/callbacks-registry.coffee index 57f5d0343dc2..001ecae14a61 100644 --- a/atom/common/api/lib/callbacks-registry.coffee +++ b/atom/common/api/lib/callbacks-registry.coffee @@ -22,8 +22,6 @@ class CallbacksRegistry continue if location.indexOf('(native)') isnt -1 continue if location.indexOf('atom.asar') isnt -1 [x, filenameAndLine] = /([^/^\)]*)\)?$/gi.exec(location) - [x, line, column] = /(\d+):(\d+)/g.exec(filenameAndLine) - id += parseInt(line) + parseInt(column) break @callbacks[id] = callback diff --git a/atom/common/id_weak_map.cc b/atom/common/id_weak_map.cc index 7fda009e0ee1..a78dcbceba53 100644 --- a/atom/common/id_weak_map.cc +++ b/atom/common/id_weak_map.cc @@ -32,15 +32,6 @@ IDWeakMap::IDWeakMap() : next_id_(0) { IDWeakMap::~IDWeakMap() { } -int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Local object) { - int32_t id = GetNextID(); - auto global = make_linked_ptr(new v8::Global(isolate, object)); - ObjectKey* key = new ObjectKey(id, this); - global->SetWeak(key, OnObjectGC, v8::WeakCallbackType::kParameter); - map_[id] = global; - return id; -} - void IDWeakMap::Set(v8::Isolate* isolate, int32_t id, v8::Local object) { @@ -50,6 +41,12 @@ void IDWeakMap::Set(v8::Isolate* isolate, map_[id] = global; } +int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Local object) { + int32_t id = GetNextID(); + Set(isolate, id, object); + return id; +} + v8::MaybeLocal IDWeakMap::Get(v8::Isolate* isolate, int32_t id) { auto iter = map_.find(id); if (iter == map_.end()) diff --git a/atom/common/id_weak_map.h b/atom/common/id_weak_map.h index 688e85cd0cce..72c64c6ae5d4 100644 --- a/atom/common/id_weak_map.h +++ b/atom/common/id_weak_map.h @@ -19,12 +19,12 @@ class IDWeakMap { IDWeakMap(); ~IDWeakMap(); - // Adds |object| to WeakMap and returns its allocated |id|. - int32_t Add(v8::Isolate* isolate, v8::Local object); - // Sets the object to WeakMap with the given |id|. void Set(v8::Isolate* isolate, int32_t id, v8::Local object); + // Adds |object| to WeakMap and returns its allocated |id|. + int32_t Add(v8::Isolate* isolate, v8::Local object); + // Gets the object from WeakMap by its |id|. v8::MaybeLocal Get(v8::Isolate* isolate, int32_t id); From aa9872035657720354bbf914082156f436d01c42 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 30 Oct 2015 14:46:18 -0700 Subject: [PATCH 380/738] Update dialog.md Clarification of showErrorBox behavior on Linux if called before app `ready` event. --- docs/api/dialog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/api/dialog.md b/docs/api/dialog.md index 0fadfa37f80c..a665f7aa081d 100644 --- a/docs/api/dialog.md +++ b/docs/api/dialog.md @@ -114,4 +114,5 @@ will be passed via `callback(response)`. Displays a modal dialog that shows an error message. This API can be called safely before the `ready` event the `app` module emits, -it is usually used to report errors in early stage of startup. +it is usually used to report errors in early stage of startup. If called before the app `ready` ++event on Linux, the message will be emitted to stderr, and no GUI dialog will appear. From a957ea1ed9b0628a9ab1eed93fdad277e8d40d25 Mon Sep 17 00:00:00 2001 From: bureken Date: Sat, 31 Oct 2015 05:30:18 +0300 Subject: [PATCH 381/738] Replace Mac with OS X --- README.md | 2 +- docs-translations/es/tutorial/using-pepper-flash-plugin.md | 2 +- docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md | 2 +- docs/tutorial/using-pepper-flash-plugin.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index dd03f7099e10..8fb9128d9c10 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ unacceptable behavior to atom@github.com. ## Downloads -Prebuilt binaries and debug symbols of Electron for Linux, Windows and Mac can +Prebuilt binaries and debug symbols of Electron for Linux, Windows and OS X can be found on the [releases](https://github.com/atom/electron/releases) page. You can also use [`npm`](https://docs.npmjs.com/) to install prebuilt electron diff --git a/docs-translations/es/tutorial/using-pepper-flash-plugin.md b/docs-translations/es/tutorial/using-pepper-flash-plugin.md index fbb2b6f83aa0..53d2d024c1d1 100644 --- a/docs-translations/es/tutorial/using-pepper-flash-plugin.md +++ b/docs-translations/es/tutorial/using-pepper-flash-plugin.md @@ -31,7 +31,7 @@ app.on('window-all-closed', function() { // Specify flash path. // On Windows, it might be /path/to/pepflashplayer.dll -// On Mac, /path/to/PepperFlashPlayer.plugin +// On OS X, /path/to/PepperFlashPlayer.plugin // On Linux, /path/to/libpepflashplayer.so app.commandLine.appendSwitch('ppapi-flash-path', '/path/to/libpepflashplayer.so'); diff --git a/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md b/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md index a92f61c78e28..dfcca01a5c7e 100644 --- a/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md +++ b/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md @@ -39,7 +39,7 @@ app.on('window-all-closed', function() { // Epecifica o caminho do flash. // No Windows, deve ser /path/to/pepflashplayer.dll -// No Mac, /path/to/PepperFlashPlayer.plugin +// No OS X, /path/to/PepperFlashPlayer.plugin // No Linux, /path/to/libpepflashplayer.so app.commandLine.appendSwitch('ppapi-flash-path', '/path/to/libpepflashplayer.so'); diff --git a/docs/tutorial/using-pepper-flash-plugin.md b/docs/tutorial/using-pepper-flash-plugin.md index 5c8820c2fad4..9321798ffca4 100644 --- a/docs/tutorial/using-pepper-flash-plugin.md +++ b/docs/tutorial/using-pepper-flash-plugin.md @@ -38,7 +38,7 @@ app.on('window-all-closed', function() { // Specify flash path. // On Windows, it might be /path/to/pepflashplayer.dll -// On Mac, /path/to/PepperFlashPlayer.plugin +// On OS X, /path/to/PepperFlashPlayer.plugin // On Linux, /path/to/libpepflashplayer.so app.commandLine.appendSwitch('ppapi-flash-path', '/path/to/libpepflashplayer.so'); From db3cd1af36a4b54a4f7d2296db88deb78a8316bc Mon Sep 17 00:00:00 2001 From: Jesus David Rojas Date: Fri, 30 Oct 2015 14:30:39 -0430 Subject: [PATCH 382/738] =?UTF-8?q?Translate=20"Diferencias=20T=C3=A9cnica?= =?UTF-8?q?s=20con=20NW.js"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs-translations/es/README.md | 2 +- .../development/atom-shell-vs-node-webkit.md | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 docs-translations/es/development/atom-shell-vs-node-webkit.md diff --git a/docs-translations/es/README.md b/docs-translations/es/README.md index 687dff4bde2d..ee2c52b98f85 100644 --- a/docs-translations/es/README.md +++ b/docs-translations/es/README.md @@ -63,7 +63,7 @@ * [Guía de Estilo](development/coding-style.md) * [Estructura de los directorios del Código Fuente](development/source-code-directory-structure.md) -* [Diferencias Técnicas con NW.js (anteriormente conocido como node-webkit)](../../development/atom-shell-vs-node-webkit.md) +* [Diferencias Técnicas con NW.js (anteriormente conocido como node-webkit)](development/atom-shell-vs-node-webkit.md) * [Repaso del Sistema de Compilación](../../development/build-system-overview.md) * [Instrucciones de Compilación (Mac)](../../development/build-instructions-osx.md) * [Instrucciones de Compilación (Windows)](../../development/build-instructions-windows.md) diff --git a/docs-translations/es/development/atom-shell-vs-node-webkit.md b/docs-translations/es/development/atom-shell-vs-node-webkit.md new file mode 100644 index 000000000000..4072976a2ff4 --- /dev/null +++ b/docs-translations/es/development/atom-shell-vs-node-webkit.md @@ -0,0 +1,34 @@ +#Diferencias Técnicas entre Electron y NW.js (anteriormente conocido como node-webkit) + +**Nota:Electron se llamaba antes Atom Shell.** + +Como NW.js, Electron proporciona una plataforma para escribir aplicaciones de escritorio con JavaScript y HTML y tiene la integración de nodo para permitir el acceso al sistema de bajo nivel de las páginas web. + +Pero también hay diferencias fundamentales entre los dos proyectos que hacen a Electron un producto totalmente independiente de NW.js: + +**1. Ingreso a la aplicación** + +En NW.js el principal punto de ingreso de una aplicación es una página web. Usted especifica una página principal de URL en el `package.json` y se abre en una ventana del navegador como ventana principal de la aplicación. + +En Electron, el punto de ingreso es un script de JavaScript. En lugar de proporcionar una dirección URL directamente, usted crea manualmente una ventana del navegador y carga un archivo HTML utilizando la API. También es necesario escuchar a los eventos de la ventana para decidir cuándo salir de la aplicación. + +Electron funciona más como el tiempo de ejecución(Runtime) de Node.js. Las Api's de Electron son de bajo nivel asi que puede usarlo para las pruebas del navegador en lugar de usar [PhantomJS.](http://phantomjs.org/) + +**2.Construir un sistema** + +Con el fin de evitar la complejidad de la construcción de todo Chromium, Electron utiliza `libchromiumcontent` para acceder a al contenido Chromium's API. `libchromiumcontent` es solo una liberia compartida que incluye el módulo de contenido de Chromium y todas sus dependencias. Los usuarios no necesitan una máquina potente para construir con Electron. + +**3.Integración de Node** + +In NW.js, the Node integration in web pages requires patching Chromium to work, while in Electron we chose a different way to integrate the libuv loop with each platform's message loop to avoid hacking Chromium. See the node_bindings code for how that was done. + +En NW.js, la integración de Node en las páginas web requiere parchear Chromium para que funcione, mientras que en Electron elegimos una manera diferente para integrar el cilco libuv con cada ciclo de mensaje de las plataformas para evitar el hacking en Chromium. Ver el código `node_bindings` de cómo se hizo. + + +**4. Multi-contexto** + +Si usted es un usuario experimentado NW.js, usted debe estar familiarizado con el concepto de contexto Node y el contexto web. Estos conceptos fueron inventados debido a la forma cómo se implementó NW.js. + +Mediante el uso de la característica [multi-contexto](http://strongloop.com/strongblog/whats-new-node-js-v0-12-multiple-context-execution/) de Node, Electron no introduce un nuevo contexto JavaScript en páginas web.Resultados de búsqueda + + From cb91d4487b2e961503f3e8e01dcc207f2ba58b7e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 31 Oct 2015 15:00:06 +0800 Subject: [PATCH 383/738] Clean up the code handling renderer callback --- atom/browser/lib/rpc-server.coffee | 26 +++++++------------ atom/common/api/atom_api_id_weak_map.cc | 18 ++++++------- atom/common/api/atom_api_id_weak_map.h | 6 ++--- atom/common/api/lib/callbacks-registry.coffee | 7 ++--- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index eb97c721396f..24ece2205cac 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -4,9 +4,6 @@ objectsRegistry = require './objects-registry.js' v8Util = process.atomBinding 'v8_util' IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap -# Object mapping from webcontents id to their renderer callbacks weakmap. -rendererRegistry = {} - # Convert a real value into meta data. valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta = type: typeof value @@ -74,18 +71,15 @@ unwrapArgs = (sender, args) -> returnValue = metaToValue meta.value -> returnValue when 'function' - webContentsId = sender.getId() - rendererCallbacks = rendererRegistry[webContentsId] - if not rendererCallbacks? - # Weak reference to callbacks with their ID - rendererCallbacks = new IDWeakMap() - rendererRegistry[webContentsId] = rendererCallbacks - - if rendererCallbacks.has(meta.id) - return rendererCallbacks.get(meta.id) + # Cache the callbacks in renderer. + unless sender.callbacks + sender.callbacks = new IDWeakMap + sender.on 'render-view-deleted', -> + sender.callbacks.clear() + return sender.callbacks.get meta.id if sender.callbacks.has meta.id rendererReleased = false - objectsRegistry.once "clear-#{webContentsId}", -> + objectsRegistry.once "clear-#{sender.getId()}", -> rendererReleased = true ret = -> @@ -95,9 +89,9 @@ unwrapArgs = (sender, args) -> sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments) v8Util.setDestructor ret, -> return if rendererReleased - rendererCallbacks.remove meta.id + sender.callbacks.remove meta.id sender.send 'ATOM_RENDERER_RELEASE_CALLBACK', meta.id - rendererCallbacks.set meta.id, ret + sender.callbacks.set meta.id, ret ret else throw new TypeError("Unknown type: #{meta.type}") @@ -116,8 +110,6 @@ callFunction = (event, func, caller, args) -> # Send by BrowserWindow when its render view is deleted. process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) -> - if rendererRegistry.id? - delete rendererRegistry.id objectsRegistry.clear id ipc.on 'ATOM_BROWSER_REQUIRE', (event, module) -> diff --git a/atom/common/api/atom_api_id_weak_map.cc b/atom/common/api/atom_api_id_weak_map.cc index 8c17e8330ccc..f32e33682dff 100644 --- a/atom/common/api/atom_api_id_weak_map.cc +++ b/atom/common/api/atom_api_id_weak_map.cc @@ -12,33 +12,32 @@ namespace atom { namespace api { -IDWeakMap::IDWeakMap() : id_weak_map_(new atom::IDWeakMap) { +IDWeakMap::IDWeakMap() { } IDWeakMap::~IDWeakMap() { - id_weak_map_ = nullptr; } void IDWeakMap::Set(v8::Isolate* isolate, int32_t id, v8::Local object) { - id_weak_map_->Set(isolate, id, object); + id_weak_map_.Set(isolate, id, object); } v8::Local IDWeakMap::Get(v8::Isolate* isolate, int32_t id) { - return id_weak_map_->Get(isolate, id).ToLocalChecked(); + return id_weak_map_.Get(isolate, id).ToLocalChecked(); } bool IDWeakMap::Has(int32_t id) { - return id_weak_map_->Has(id); + return id_weak_map_.Has(id); } void IDWeakMap::Remove(int32_t id) { - id_weak_map_->Remove(id); + id_weak_map_.Remove(id); } -bool IDWeakMap::IsDestroyed() const { - return !id_weak_map_; +void IDWeakMap::Clear() { + id_weak_map_.Clear(); } // static @@ -48,7 +47,8 @@ void IDWeakMap::BuildPrototype(v8::Isolate* isolate, .SetMethod("set", &IDWeakMap::Set) .SetMethod("get", &IDWeakMap::Get) .SetMethod("has", &IDWeakMap::Has) - .SetMethod("remove", &IDWeakMap::Remove); + .SetMethod("remove", &IDWeakMap::Remove) + .SetMethod("clear", &IDWeakMap::Clear); } // static diff --git a/atom/common/api/atom_api_id_weak_map.h b/atom/common/api/atom_api_id_weak_map.h index 4a2f8e397a80..0cf656f455bc 100644 --- a/atom/common/api/atom_api_id_weak_map.h +++ b/atom/common/api/atom_api_id_weak_map.h @@ -24,17 +24,15 @@ class IDWeakMap : public mate::Wrappable { IDWeakMap(); ~IDWeakMap(); - // mate::Wrappable: - bool IsDestroyed() const override; - private: // Api for IDWeakMap. void Set(v8::Isolate* isolate, int32_t id, v8::Local object); v8::Local Get(v8::Isolate* isolate, int32_t id); bool Has(int32_t id); void Remove(int32_t id); + void Clear(); - atom::IDWeakMap* id_weak_map_; + atom::IDWeakMap id_weak_map_; DISALLOW_COPY_AND_ASSIGN(IDWeakMap); }; diff --git a/atom/common/api/lib/callbacks-registry.coffee b/atom/common/api/lib/callbacks-registry.coffee index 001ecae14a61..c546df34f9a8 100644 --- a/atom/common/api/lib/callbacks-registry.coffee +++ b/atom/common/api/lib/callbacks-registry.coffee @@ -7,8 +7,9 @@ class CallbacksRegistry @callbacks = {} add: (callback) -> - if v8Util.getHiddenValue(callback, 'metaId')? - return v8Util.getHiddenValue(callback, 'metaId') + # The callback is already added. + id = v8Util.getHiddenValue callback, 'callbackId' + return id if id? id = ++@nextId @@ -25,7 +26,7 @@ class CallbacksRegistry break @callbacks[id] = callback - v8Util.setHiddenValue callback, 'metaId', id + v8Util.setHiddenValue callback, 'callbackId', id v8Util.setHiddenValue callback, 'location', filenameAndLine id From 6a02586176cb5d8c483fff73c075b5cac20d9341 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Sat, 31 Oct 2015 08:57:04 -0700 Subject: [PATCH 384/738] Add Windows version of running cmd --- docs/tutorial/using-native-node-modules.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/tutorial/using-native-node-modules.md b/docs/tutorial/using-native-node-modules.md index 6954fc64b1a1..2defedd74183 100644 --- a/docs/tutorial/using-native-node-modules.md +++ b/docs/tutorial/using-native-node-modules.md @@ -33,6 +33,9 @@ npm install --save-dev electron-rebuild # Every time you run "npm install", run this ./node_modules/.bin/electron-rebuild + +# On Windows if you have trouble, try: +.\node_modules\.bin\electron-rebuild.cmd ``` ### The npm Way From c969052f1256643fd746e5320f7cfdad8d9a3f27 Mon Sep 17 00:00:00 2001 From: Robo Date: Sat, 31 Oct 2015 19:09:07 +0530 Subject: [PATCH 385/738] browser: handle flash context menu --- atom/browser/api/atom_api_app.cc | 2 +- atom/browser/api/atom_api_protocol.cc | 2 +- atom/browser/api/atom_api_web_contents.cc | 20 ++++++++ atom/browser/api/atom_api_web_contents.h | 7 +++ atom/browser/api/lib/web-contents.coffee | 41 +++++++++++++++++ .../content_converter.cc | 46 +++++++++++++------ .../content_converter.h | 14 +++--- .../native_mate_converters/net_converter.cc | 34 ++++++++++++++ .../native_mate_converters/net_converter.h | 31 +++++++++++++ filenames.gypi | 2 + 10 files changed, 177 insertions(+), 22 deletions(-) create mode 100644 atom/common/native_mate_converters/net_converter.cc create mode 100644 atom/common/native_mate_converters/net_converter.h diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 21a553e4d1d5..bd49f9fddc05 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -19,7 +19,7 @@ #include "atom/browser/browser.h" #include "atom/browser/login_handler.h" #include "atom/common/native_mate_converters/callback.h" -#include "atom/common/native_mate_converters/content_converter.h" +#include "atom/common/native_mate_converters/net_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/node_includes.h" #include "atom/common/options_switches.h" diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index f6cc6d796557..e76f26f0d4f5 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -12,7 +12,7 @@ #include "atom/browser/net/url_request_fetch_job.h" #include "atom/browser/net/url_request_string_job.h" #include "atom/common/native_mate_converters/callback.h" -#include "atom/common/native_mate_converters/content_converter.h" +#include "atom/common/native_mate_converters/net_converter.h" #include "atom/common/node_includes.h" #include "native_mate/dictionary.h" diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 900c3e65a376..fa40296f57d8 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -18,6 +18,7 @@ #include "atom/common/api/event_emitter_caller.h" #include "atom/common/native_mate_converters/blink_converter.h" #include "atom/common/native_mate_converters/callback.h" +#include "atom/common/native_mate_converters/content_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/gfx_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h" @@ -404,6 +405,12 @@ void WebContents::RendererResponsive(content::WebContents* source) { owner_window()->RendererResponsive(source); } +bool WebContents::HandleContextMenu(const content::ContextMenuParams& params) { + context_menu_context_ = params.custom_context; + Emit("-context-menu", params); + return true; +} + void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) { // Do nothing, we override this method just to avoid compilation error since // there are two virtual functions named BeforeUnloadFired. @@ -840,6 +847,15 @@ void WebContents::RemoveWorkSpace(mate::Arguments* args, DevToolsRemoveFileSystem(path); } +void WebContents::ExecuteContextMenuCommand(int action) { + web_contents()->ExecuteCustomContextMenuCommand(action, + context_menu_context_); +} + +void WebContents::NotifyContextMenuClosed() { + web_contents()->NotifyContextMenuClosed(context_menu_context_); +} + void WebContents::Undo() { web_contents()->Undo(); } @@ -1051,6 +1067,10 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("_printToPDF", &WebContents::PrintToPDF) .SetMethod("addWorkSpace", &WebContents::AddWorkSpace) .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace) + .SetMethod("_executeContextMenuCommand", + &WebContents::ExecuteContextMenuCommand) + .SetMethod("_notifyContextMenuClosed", + &WebContents::NotifyContextMenuClosed) .SetProperty("session", &WebContents::Session, true) .SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents, true) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 7fa8951106b2..5a55ad2abd7a 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -13,6 +13,7 @@ #include "atom/browser/api/trackable_object.h" #include "atom/browser/common_web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" +#include "content/public/common/context_menu_params.h" #include "content/public/common/favicon_url.h" #include "native_mate/handle.h" #include "ui/gfx/image/image.h" @@ -92,6 +93,8 @@ class WebContents : public mate::TrackableObject, void SetAudioMuted(bool muted); bool IsAudioMuted(); void Print(mate::Arguments* args); + void ExecuteContextMenuCommand(int action); + void NotifyContextMenuClosed(); // Print current page as PDF. void PrintToPDF(const base::DictionaryValue& setting, @@ -189,6 +192,7 @@ class WebContents : public mate::TrackableObject, void ExitFullscreenModeForTab(content::WebContents* source) override; void RendererUnresponsive(content::WebContents* source) override; void RendererResponsive(content::WebContents* source) override; + bool HandleContextMenu(const content::ContextMenuParams& params) override; // content::WebContentsObserver: void BeforeUnloadFired(const base::TimeTicks& proceed_time) override; @@ -255,6 +259,9 @@ class WebContents : public mate::TrackableObject, // embedders' zoom level change. void OnZoomLevelChanged(double level); + // Recent unhandled context menu context. + content::CustomContextMenuContext context_menu_context_; + v8::Global session_; v8::Global devtools_web_contents_; diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index 3a2abfb5155f..afe70323f0a5 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -1,4 +1,5 @@ EventEmitter = require('events').EventEmitter +Menu = require './menu' NavigationController = require './navigation-controller' binding = process.atomBinding 'web_contents' ipc = require 'ipc' @@ -34,6 +35,36 @@ PDFPageSize = width_microns: 279400 custom_display_name: "Tabloid" +clickHandler = (action) -> + @_executeContextMenuCommand action + +convertToMenuTemplate = (items, handler) -> + template = [] + for item in items + do (item) -> + transformed = + if item.type is 'submenu' + type: 'submenu' + label: item.label + enabled: item.enabled + submenu: convertToMenuTemplate item.subItems, handler + else if item.type is 'separator' + type: 'separator' + else if item.type is 'checkbox' + type: 'checkbox' + label: item.label + enabled: item.enabled + checked: item.checked + else + type: 'normal' + label: item.label + enabled: item.enabled + if item.id? + transformed.click = -> + handler item.id + template.push transformed + template + wrapWebContents = (webContents) -> # webContents is an EventEmitter. webContents.__proto__ = EventEmitter.prototype @@ -65,6 +96,16 @@ wrapWebContents = (webContents) -> Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value) ipc.emit channel, event, args... + # Handle context menu action request from renderer widget. + webContents.on '-context-menu', (event, params) -> + if params.isPepperMenu + template = convertToMenuTemplate(params.menuItems, clickHandler.bind(webContents)) + menu = Menu.buildFromTemplate template + # The menu is expected to show asynchronously. + setImmediate -> + menu.popup params.x, params.y + webContents._notifyContextMenuClosed() + webContents.printToPDF = (options, callback) -> printingSetting = pageRage: [] diff --git a/atom/common/native_mate_converters/content_converter.cc b/atom/common/native_mate_converters/content_converter.cc index b6f3a2c1cc03..2318e7d8e837 100644 --- a/atom/common/native_mate_converters/content_converter.cc +++ b/atom/common/native_mate_converters/content_converter.cc @@ -4,30 +4,50 @@ #include "atom/common/native_mate_converters/content_converter.h" +#include "atom/common/native_mate_converters/string16_converter.h" +#include "content/public/common/context_menu_params.h" +#include "content/public/common/menu_item.h" #include "native_mate/dictionary.h" -#include "net/url_request/url_request.h" namespace mate { +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + const content::MenuItem::Type& val) { + switch (val) { + case content::MenuItem::CHECKABLE_OPTION: + return StringToV8(isolate, "checkbox"); + case content::MenuItem::SEPARATOR: + return StringToV8(isolate, "separator"); + case content::MenuItem::SUBMENU: + return StringToV8(isolate, "submenu"); + default: + return StringToV8(isolate, "normal"); + } + } +}; + // static -v8::Local Converter::ToV8( - v8::Isolate* isolate, const net::URLRequest* val) { +v8::Local Converter::ToV8( + v8::Isolate* isolate, const content::MenuItem& val) { mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); - dict.Set("method", val->method()); - dict.Set("url", val->url().spec()); - dict.Set("referrer", val->referrer()); + dict.Set("id", val.action); + dict.Set("type", val.type); + dict.Set("label", val.label); + dict.Set("enabled", val.enabled); + dict.Set("checked", val.checked); return mate::ConvertToV8(isolate, dict); } // static -v8::Local Converter::ToV8( - v8::Isolate* isolate, const net::AuthChallengeInfo* val) { +v8::Local Converter::ToV8( + v8::Isolate* isolate, const content::ContextMenuParams& val) { mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); - dict.Set("isProxy", val->is_proxy); - dict.Set("scheme", val->scheme); - dict.Set("host", val->challenger.host()); - dict.Set("port", static_cast(val->challenger.port())); - dict.Set("realm", val->realm); + dict.Set("x", val.x); + dict.Set("y", val.y); + dict.Set("isPepperMenu", val.custom_context.is_pepper_menu); + dict.Set("menuItems", val.custom_items); return mate::ConvertToV8(isolate, dict); } diff --git a/atom/common/native_mate_converters/content_converter.h b/atom/common/native_mate_converters/content_converter.h index 0d4d5fe2cce0..5cca2b38b251 100644 --- a/atom/common/native_mate_converters/content_converter.h +++ b/atom/common/native_mate_converters/content_converter.h @@ -7,23 +7,23 @@ #include "native_mate/converter.h" -namespace net { -class AuthChallengeInfo; -class URLRequest; +namespace content { +struct ContextMenuParams; +struct MenuItem; } namespace mate { template<> -struct Converter { +struct Converter { static v8::Local ToV8(v8::Isolate* isolate, - const net::URLRequest* val); + const content::MenuItem& val); }; template<> -struct Converter { +struct Converter { static v8::Local ToV8(v8::Isolate* isolate, - const net::AuthChallengeInfo* val); + const content::ContextMenuParams& val); }; } // namespace mate diff --git a/atom/common/native_mate_converters/net_converter.cc b/atom/common/native_mate_converters/net_converter.cc new file mode 100644 index 000000000000..4796d962660a --- /dev/null +++ b/atom/common/native_mate_converters/net_converter.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/native_mate_converters/net_converter.h" + +#include "native_mate/dictionary.h" +#include "net/url_request/url_request.h" + +namespace mate { + +// static +v8::Local Converter::ToV8( + v8::Isolate* isolate, const net::URLRequest* val) { + mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); + dict.Set("method", val->method()); + dict.Set("url", val->url().spec()); + dict.Set("referrer", val->referrer()); + return mate::ConvertToV8(isolate, dict); +} + +// static +v8::Local Converter::ToV8( + v8::Isolate* isolate, const net::AuthChallengeInfo* val) { + mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); + dict.Set("isProxy", val->is_proxy); + dict.Set("scheme", val->scheme); + dict.Set("host", val->challenger.host()); + dict.Set("port", static_cast(val->challenger.port())); + dict.Set("realm", val->realm); + return mate::ConvertToV8(isolate, dict); +} + +} // namespace mate diff --git a/atom/common/native_mate_converters/net_converter.h b/atom/common/native_mate_converters/net_converter.h new file mode 100644 index 000000000000..352c613eaabb --- /dev/null +++ b/atom/common/native_mate_converters/net_converter.h @@ -0,0 +1,31 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_ +#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_ + +#include "native_mate/converter.h" + +namespace net { +class AuthChallengeInfo; +class URLRequest; +} + +namespace mate { + +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + const net::URLRequest* val); +}; + +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + const net::AuthChallengeInfo* val); +}; + +} // namespace mate + +#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_ diff --git a/filenames.gypi b/filenames.gypi index ba739764f492..0e70347309c0 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -316,6 +316,8 @@ 'atom/common/native_mate_converters/gurl_converter.h', 'atom/common/native_mate_converters/image_converter.cc', 'atom/common/native_mate_converters/image_converter.h', + 'atom/common/native_mate_converters/net_converter.cc', + 'atom/common/native_mate_converters/net_converter.h', 'atom/common/native_mate_converters/string16_converter.h', 'atom/common/native_mate_converters/v8_value_converter.cc', 'atom/common/native_mate_converters/v8_value_converter.h', From 5b49655d1fc7af269e77dc13a07edc89b09930b6 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Sat, 31 Oct 2015 16:04:01 -0700 Subject: [PATCH 386/738] Update dialog.md --- docs/api/dialog.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/api/dialog.md b/docs/api/dialog.md index a665f7aa081d..6acfb79884e3 100644 --- a/docs/api/dialog.md +++ b/docs/api/dialog.md @@ -114,5 +114,6 @@ will be passed via `callback(response)`. Displays a modal dialog that shows an error message. This API can be called safely before the `ready` event the `app` module emits, -it is usually used to report errors in early stage of startup. If called before the app `ready` -+event on Linux, the message will be emitted to stderr, and no GUI dialog will appear. +it is usually used to report errors in early stage of startup. If called +before the app `ready`event on Linux, the message will be emitted to stderr, +and no GUI dialog will appear. From bbb5aef5d268c4f64801c8f96c1bf3e18a9cf836 Mon Sep 17 00:00:00 2001 From: Max Claus Nunes Date: Sat, 31 Oct 2015 21:20:54 -0200 Subject: [PATCH 387/738] Improve error handling from remote This way copy all properties available in the error object and keep the real stack trace --- atom/browser/lib/rpc-server.coffee | 9 ++++++++- atom/renderer/api/lib/remote.coffee | 13 ++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 24ece2205cac..953436e16f37 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -40,7 +40,7 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> else if meta.type is 'promise' meta.then = valueToMeta(sender, value.then.bind(value)) else if meta.type is 'error' - meta.message = value.message + meta = errorValueToMeta(value, meta) else if meta.type is 'date' meta.value = value.getTime() else @@ -49,6 +49,13 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta +# Convert Error into meta data. +errorValueToMeta = (err, meta) -> + Object.getOwnPropertyNames(err).reduce((obj, key) -> + obj[key] = err[key] + obj + , meta) + # Convert Error into meta data. exceptionToMeta = (error) -> type: 'exception', message: error.message, stack: (error.stack || error) diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index b5a3a694ee37..d01027e27de0 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -46,7 +46,7 @@ metaToValue = (meta) -> when 'array' then (metaToValue(el) for el in meta.members) when 'buffer' then new Buffer(meta.value) when 'promise' then Promise.resolve(then: metaToValue(meta.then)) - when 'error' then new Error(meta.message) + when 'error' then metaToError(meta) when 'date' then new Date(meta.value) when 'exception' throw new Error("#{meta.message}\n#{meta.stack}") @@ -110,6 +110,17 @@ metaToValue = (meta) -> ret +# Convert meta data from browser into Error. +metaToError = (meta) -> + Object.getOwnPropertyNames(meta).reduce((error, prop) -> + Object.defineProperty(error, prop, { + get: -> meta[prop], + enumerable: false, + configurable: false + }) + error + , new Error()) + # Browser calls a callback in renderer. ipc.on 'ATOM_RENDERER_CALLBACK', (id, args) -> callbacksRegistry.apply id, metaToValue(args) From d097082baf74d64c861c3585aeb936b3767e285c Mon Sep 17 00:00:00 2001 From: Greg Gamel Date: Sat, 31 Oct 2015 21:25:07 -0500 Subject: [PATCH 388/738] Update auto-updater.md to improve readability Fix minor grammatical mistakes, correct sentence structures, and improve readability. --- docs/api/auto-updater.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/api/auto-updater.md b/docs/api/auto-updater.md index 972f93ea5922..bda1d46bb094 100644 --- a/docs/api/auto-updater.md +++ b/docs/api/auto-updater.md @@ -4,27 +4,27 @@ This module provides an interface for the `Squirrel` auto-updater framework. ## Platform notices -Though `autoUpdater` provides an uniform API for different platforms, there are +Though `autoUpdater` provides a uniform API for different platforms, there are still some subtle differences on each platform. ### OS X -On OS X the `autoUpdater` module is built upon [Squirrel.Mac][squirrel-mac], you +On OS X, the `autoUpdater` module is built upon [Squirrel.Mac][squirrel-mac], meaning you don't need any special setup to make it work. For server-side requirements, you can read [Server Support][server-support]. ### Windows -On Windows you have to install your app into user's machine before you can use -the auto-updater, it is recommended to use [grunt-electron-installer][installer] +On Windows, you have to install your app into a user's machine before you can use +the auto-updater, so it is recommended to use [grunt-electron-installer][installer] module to generate a Windows installer. -The server-side setup is also different from OS X, you can read the documents of +The server-side setup is also different from OS X. You can read the documents of [Squirrel.Windows][squirrel-windows] to get more details. ### Linux -There is not built-in support for auto-updater on Linux, it is recommended to +There is not built-in support for auto-updater on Linux, so it is recommended to use the distribution's package manager to update your app. ## Events @@ -84,7 +84,7 @@ using this API. ### `autoUpdater.quitAndInstall()` -Restarts the app and install the update after it has been downloaded. It should +Restarts the app and installs the update after it has been downloaded. It should only be called after `update-downloaded` has been emitted. [squirrel-mac]: https://github.com/Squirrel/Squirrel.Mac From f7108af36b63e1e968b5551a891c9660e5a59a6a Mon Sep 17 00:00:00 2001 From: Jesus David Rojas Date: Fri, 30 Oct 2015 14:30:39 -0430 Subject: [PATCH 389/738] Spanish translations of the documents --- docs-translations/es/README.md | 6 +- .../development/build-instructions-linux.md | 96 +++++++++++++++++++ .../es/development/build-instructions-osx.md | 48 ++++++++++ .../es/development/build-system-overview.md | 35 +++++++ 4 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 docs-translations/es/development/build-instructions-linux.md create mode 100644 docs-translations/es/development/build-instructions-osx.md create mode 100644 docs-translations/es/development/build-system-overview.md diff --git a/docs-translations/es/README.md b/docs-translations/es/README.md index ee2c52b98f85..e69e76b1c4c7 100644 --- a/docs-translations/es/README.md +++ b/docs-translations/es/README.md @@ -64,8 +64,8 @@ * [Guía de Estilo](development/coding-style.md) * [Estructura de los directorios del Código Fuente](development/source-code-directory-structure.md) * [Diferencias Técnicas con NW.js (anteriormente conocido como node-webkit)](development/atom-shell-vs-node-webkit.md) -* [Repaso del Sistema de Compilación](../../development/build-system-overview.md) -* [Instrucciones de Compilación (Mac)](../../development/build-instructions-osx.md) +* [Repaso del Sistema de Compilación](development/build-system-overview.md) +* [Instrucciones de Compilación (Mac)](development/build-instructions-osx.md) * [Instrucciones de Compilación (Windows)](../../development/build-instructions-windows.md) -* [Instrucciones de Compilación (Linux)](../../development/build-instructions-linux.md) +* [Instrucciones de Compilación (Linux)](development/build-instructions-linux.md) * [Configurando un Servidor de Símbolos en el depurador](../../development/setting-up-symbol-server.md) diff --git a/docs-translations/es/development/build-instructions-linux.md b/docs-translations/es/development/build-instructions-linux.md new file mode 100644 index 000000000000..28ad828fa709 --- /dev/null +++ b/docs-translations/es/development/build-instructions-linux.md @@ -0,0 +1,96 @@ +#Instrucciones de Compilación (Linux) + +Siga las siguientes pautas para la construcción de Electron en Linux. +#Requisitos previos + + * Python 2.7.x. Algunas distribuciones como CentOS siguen utilizando Python 2.6.x por lo que puede que tenga que comprobar su versión de Python con `Python -V`. + * Node.js v0.12.x. Hay varias formas de instalar Node. Puede descargar el código fuente de Node.js y compilar desde las fuentes. Si lo hace, permite la instalación de Node en el directorio personal como usuario estándar. O intentar de repositorios como NodeSource. + * Clang 3.4 o mayor. + * Cabeceras de desarrollo de GTK + y libnotify. + +En Ubuntu, instalar las siguientes bibliotecas: + +`$ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \ + libnotify-dev libgnome-keyring-dev libgconf2-dev \ + libasound2-dev libcap-dev libcups2-dev libxtst-dev \ + libxss1 libnss3-dev gcc-multilib g++-multilib` + +En Fedora, instale las siguientes bibliotecas: + +`$ sudo yum install clang dbus-devel gtk2-devel libnotify-devel libgnome-keyring-devel \ + xorg-x11-server-utils libcap-devel cups-devel libXtst-devel \ + alsa-lib-devel libXrandr-devel GConf2-devel nss-devel` + +Otras distribuciones pueden ofrecer paquetes similares para la instalación, a través de gestores de paquetes como el pacman. O puede compilarlo a partir del código fuente. + +#Si utiliza máquinas virtuales para la construcción + +Si usted planea construir Electron en una máquina virtual, necesitará un dispositivo de al menos 25 gigabytes de tamaño. + +#Obteniendo el codigo + +`$ git clone https://github.com/atom/electron.git` + +#Bootstrapping (Arranque) + +The bootstrap script will download all necessary build dependencies and create the build project files. You must have Python 2.7.x for the script to succeed. Downloading certain files can take a long time. Notice that we are using ninja to build Electron so there is no Makefile generated. + +El script de bootstrap descargará todas las dependencias necesarias para construcción y creara los archivos del proyecto de construcción. Debe tener Python 2.7.x para que la secuencia de comandos tenga éxito. La descarga de determinados archivos puede llevar mucho tiempo. Nótese que estamos usando`ninja` para construir Electron por lo que no hay `Makefile` generado. + + $ cd electron + $ ./script/bootstrap.py -v + +#compilación cruzada + +Si usted quiere construir para un `arm` objetivo también debe instalar las siguientes dependencias: + +`$ sudo apt-get install libc6-dev-armhf-cross linux-libc-dev-armhf-cross \ g++-arm-linux-gnueabihf` + +And to cross compile for arm or ia32 targets, you should pass the --target_arch parameter to the bootstrap.py script: +cruzar y compilar para `arm` o `ia32` objetivos, debe pasar el parámetro `--target_arch` al script `bootstrap.py`: +`$ ./script/bootstrap.py -v --target_arch=arm` + +#Construcción + +Si a usted le gustaría construir dos objetivos de `Release` y `Debug`: + + `$ ./script/build.py` + + +Este script causará que el ejecutable de Electron se muy grande para ser colocado en el directorio `out / R`. El tamaño del archivo es de más de 1,3 gigabytes. Esto sucede porque el binario de destino lanzamiento contiene los símbolos de depuración. Para reducir el tamaño de archivo, ejecute el script `create-dist.py`: + +`$ ./script/create-dist.py` + +This will put a working distribution with much smaller file sizes in the dist directory. After running the create-dist.py script, you may want to remove the 1.3+ gigabyte binary which is still in out/R. + +Esto pondrá una distribución a trabajar con tamaños de archivo mucho más pequeños en el directorio `dist`. Después de ejecutar el script create-dist.py, es posible que desee quitar el binario 1.3+ gigabyte que todavía está en `out/R`. + +También se puede construir sólo el objetivo `Debug`: +`$ ./script/build.py -c D` + +Después de la construcción está hecho, usted puede encontrar el `Electron` de depuración binario bajo `out / D`. + +#Limpieza + +Para limpiar los archivos de creación: + +`$ ./script/clean.py` + +#Solución de problemas +Asegúrese de que ha instalado todas las dependencias de construcción. + +#Error al cargar bibliotecas compartidas: libtinfo.so.5 + +Prebulit clang will try to link to libtinfo.so.5. Depending on the host architecture, symlink to appropriate libncurses: +preconstruir `clang` intentará enlazar a `libtinfo.so.5`. Dependiendo de la arquitectura anfitrión, enlace simbólico apropiado a `libncurses` : + +`$ sudo ln -s /usr/lib/libncurses.so.5 /usr/lib/libtinfo.so.5` + +#Pruebas +Pon a prueba tus cambios que ajustan al estilo de codificación proyecto mediante: + +`$ ./script/cpplint.py` + +prueba de funcionalidad utilizando: + +`$ ./script/test.py` diff --git a/docs-translations/es/development/build-instructions-osx.md b/docs-translations/es/development/build-instructions-osx.md new file mode 100644 index 000000000000..6e2d7b7f392e --- /dev/null +++ b/docs-translations/es/development/build-instructions-osx.md @@ -0,0 +1,48 @@ +#Instrucciones de Compilación (Mac) +Siga las siguientes pautas para la construcción de Electron en OS X. + +#Requisitos previos + + `OS X >= 10.8` + `Xcode >= 5.1` + `node.js (external)` + + +Si está utilizando Python descargado de Homebrew, también es necesario instalar los siguientes módulos de python: + `pyobjc` + +#Obtener el Código + +`$ git clone https://github.com/atom/electron.git` + +#Bootstrapping (arranque) + +The bootstrap script will download all necessary build dependencies and create the build project files. Notice that we're using ninja to build Electron so there is no Xcode project generated. + +El script de bootstrap descargará todas las dependencias de construcción necesarias y creara los archivos del proyecto de compilación. notemos que estamos usando `ninja` para construir Electron por lo que no hay un proyecto de Xcode generado. + +`$ cd electron` +`$ ./script/bootstrap.py -v` + +#Construcción +Construir ambos objetivos de `Release` y `Debug`: + +`$ ./script/build.py` + +También sólo se puede construir el objetivo de `Debug`: +`$ ./script/build.py -c D` + +Después de la construcción está hecho, usted puede encontrar `Electron.app` bajo `out / D.` + +#Soporte de 32bit + +Electron sólo puede construirse para un objetivo de 64 bits en OS X y no hay un plan para apoyar a 32 bit OS X en el futuro. + +#Pruebas + +Pon a prueba tus cambios ajustandose al estilo de codificación del proyecto mediante: +`$ ./script/cpplint.py` + +Prueba la funcionalidad usando: + +`$ ./script/test.py` diff --git a/docs-translations/es/development/build-system-overview.md b/docs-translations/es/development/build-system-overview.md new file mode 100644 index 000000000000..1e6a42da84bf --- /dev/null +++ b/docs-translations/es/development/build-system-overview.md @@ -0,0 +1,35 @@ +#Repaso del Sistema de construcción +Electron utiliza `gyp` para la generación de proyectos y` ninja` para la contrucción. Las Configuraciones del proyecto se pueden encontrar en los archivos `.gypi` y `.gyp `. + +#Archivos Gyp +los siguientes archivos `gyp` contienen las principales reglas para la contrucción en electron: + + * `atom.gyp` define en si como se compila en Electron. + * `common.gypi` ajusta las configuraciones de generación de Node para construir junto con Chromium. + * `vendor/brightray/brightray.gyp` define cómo se construye `brightray` e incluye las configuraciones predeterminadas para linkear con Chromium. + * `vendor/brightray/brightray.gypi` incluye configuraciones de generación generales sobre la construcción. + +#Construir un componente +Desde Chromium es un proyecto bastante largo, la etapa de enlace final puede tomar pocos minutos, lo que hace que sea difícil para el desarrollo. Con el fin de resolver esto, Chromium introdujo el "componente de construcción", que se basa en construir cada componente como una libreria compartida por separado, haciendo que se enlace muy rápido, pero sacrificando el tamaño del archivo y el rendimiento. + +En Electron tomamos un enfoque muy similar: para versiones de `Debug` (depuración), el binario será linkeado a una versión de la libreria compartida de los componentes de Chromium para lograr un tiempo de enlace rápido; para versiones de `Release` (lanzamiento), el binario será linkeado a las versiones de las librerias estáticas, por lo que puede tener es posible tener un mejor tamaño binario y rendimiento. + +#Bootstrapping minimo (minimo arranque) +Todos los binarios pre-compilados de Chromium (`libchromiumcontent`) son descargados al ejecutar el script de arranque. Por defecto ambas librerias estáticas y librerias compartidas se descargarán y el tamaño final debe estar entre 800 MB y 2 GB dependiendo de la plataforma. + +Por defecto, `libchromiumcontent` se descarga de Amazon Web Services. Si se establece la variable de entorno `LIBCHROMIUMCONTENT_MIRROR`, el bootstrap script se descargará de ella. `libchromiumcontent-qiniu-mirror` es un espejo para el` libchromiumcontent`. Si tiene problemas para acceder a AWS, puede cambiar la dirección de descarga a la misma a través de `exportación LIBCHROMIUMCONTENT_MIRROR = http: // 7xk3d2.dl1.z0.glb.clouddn.com /` + +Si sólo desea construir en Electron rápidamente para pruebas o desarrollo, puede descargar sólo las versiones de librerias compartidas pasando el parámetro `--dev`: + +`$ ./script/bootstrap.py --dev` +`$ ./script/build.py -c D` + +#generación de proyecto de dos frases +Los enlaces de Electron con diferentes conjuntos de librerias en versiones `Release` y `Debug`. `gyp`, sin embargo, no es compatible con la configuración de los diferentes ajustes de enlace para diferentes configuraciones. + +Para evitar que Electron utilice una variable de `gyp` `libchromiumcontent_component` para controlar qué configuraciones de enlace usar y sólo generar un objetivo cuando se ejecute `gyp`. + +#Nombres de destino +A diferencia de la mayoría de los proyectos que utilizan `Release` y `Debug` como nombres de destino, Electron utiliza `R` y `D` en su lugar. Esto se debe a `gyp` bloquea aleatoriamente si sólo hay una configuración de `Release` o `Debug` definidas, y Electron sólo tiene que generar un objetivo a la vez como se ha indicado anteriormente. + +Esto sólo afecta a los desarrolladores, si usted está construyendo Electron para rebranding no se ven afectados. From 647a0c4e2b40a69da5a6153374a2f0ccac03fc1f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 2 Nov 2015 20:28:01 +0800 Subject: [PATCH 390/738] Code cleanup for remote module --- atom/browser/lib/rpc-server.coffee | 16 ++++++---------- atom/renderer/api/lib/remote.coffee | 19 ++++++++----------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 953436e16f37..ae4b161674bd 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -33,14 +33,13 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> # it. meta.id = objectsRegistry.add sender.getId(), value - meta.members = [] - meta.members.push {name: prop, type: typeof field} for prop, field of value + meta.members = ({name, type: typeof field} for name, field of value) else if meta.type is 'buffer' meta.value = Array::slice.call value, 0 else if meta.type is 'promise' - meta.then = valueToMeta(sender, value.then.bind(value)) + meta.then = valueToMeta sender, value.then.bind(value) else if meta.type is 'error' - meta = errorValueToMeta(value, meta) + meta.members = plainObjectToMeta value else if meta.type is 'date' meta.value = value.getTime() else @@ -49,12 +48,9 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta -# Convert Error into meta data. -errorValueToMeta = (err, meta) -> - Object.getOwnPropertyNames(err).reduce((obj, key) -> - obj[key] = err[key] - obj - , meta) +# Convert object to meta by value. +plainObjectToMeta = (obj) -> + Object.getOwnPropertyNames(obj).map (name) -> {name, value: obj[name]} # Convert Error into meta data. exceptionToMeta = (error) -> diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index d01027e27de0..2de14d541527 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -46,7 +46,7 @@ metaToValue = (meta) -> when 'array' then (metaToValue(el) for el in meta.members) when 'buffer' then new Buffer(meta.value) when 'promise' then Promise.resolve(then: metaToValue(meta.then)) - when 'error' then metaToError(meta) + when 'error' then metaToPlainObject meta when 'date' then new Date(meta.value) when 'exception' throw new Error("#{meta.message}\n#{meta.stack}") @@ -110,16 +110,13 @@ metaToValue = (meta) -> ret -# Convert meta data from browser into Error. -metaToError = (meta) -> - Object.getOwnPropertyNames(meta).reduce((error, prop) -> - Object.defineProperty(error, prop, { - get: -> meta[prop], - enumerable: false, - configurable: false - }) - error - , new Error()) +# Construct a plain object from the meta. +metaToPlainObject = (meta) -> + obj = switch meta.type + when 'error' then new Error + else {} + obj[name] = value for {name, value} in meta.members + obj # Browser calls a callback in renderer. ipc.on 'ATOM_RENDERER_CALLBACK', (id, args) -> From 4804d6b79b07f61d983d70c5c898b251d9e7a39a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 2 Nov 2015 21:07:48 +0800 Subject: [PATCH 391/738] Update native-mate --- vendor/native_mate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/native_mate b/vendor/native_mate index b7387da0854b..21cda4e7fcff 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit b7387da0854b20d376fdae0d93a01f83d080668d +Subproject commit 21cda4e7fcff592f33f989c1fea575658281711d From f7c0418bd8f2163d08ab359c993d01fd59f45bf0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 2 Nov 2015 21:19:00 +0800 Subject: [PATCH 392/738] Ignore case for type of savePage --- atom/browser/api/atom_api_web_contents.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 900c3e65a376..295948995528 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -169,11 +169,12 @@ struct Converter { std::string save_type; if (!ConvertFromV8(isolate, val, &save_type)) return false; - if (save_type == "HTMLOnly") { + save_type = base::StringToLowerASCII(save_type); + if (save_type == "htmlonly") { *out = content::SAVE_PAGE_TYPE_AS_ONLY_HTML; - } else if (save_type == "HTMLComplete") { + } else if (save_type == "htmlcomplete") { *out = content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML; - } else if (save_type == "MHTML") { + } else if (save_type == "mhtml") { *out = content::SAVE_PAGE_TYPE_AS_MHTML; } else { return false; From 9236adfbf57946e554c09f90760bb666dbf6e1e1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 2 Nov 2015 23:28:45 +0800 Subject: [PATCH 393/738] Translate menu template directly in C++ --- atom/browser/api/atom_api_web_contents.cc | 21 +--- atom/browser/api/atom_api_web_contents.h | 6 - atom/browser/api/lib/web-contents.coffee | 43 +------ .../content_converter.cc | 112 ++++++++++++------ .../content_converter.h | 16 ++- 5 files changed, 100 insertions(+), 98 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 5ffa37e95d44..c329b257a290 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -47,6 +47,7 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/context_menu_params.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" #include "net/http/http_response_headers.h" @@ -407,8 +408,11 @@ void WebContents::RendererResponsive(content::WebContents* source) { } bool WebContents::HandleContextMenu(const content::ContextMenuParams& params) { - context_menu_context_ = params.custom_context; - Emit("-context-menu", params); + if (!params.custom_context.is_pepper_menu) + return false; + + Emit("pepper-context-menu", std::make_pair(params, web_contents())); + web_contents()->NotifyContextMenuClosed(params.custom_context); return true; } @@ -848,15 +852,6 @@ void WebContents::RemoveWorkSpace(mate::Arguments* args, DevToolsRemoveFileSystem(path); } -void WebContents::ExecuteContextMenuCommand(int action) { - web_contents()->ExecuteCustomContextMenuCommand(action, - context_menu_context_); -} - -void WebContents::NotifyContextMenuClosed() { - web_contents()->NotifyContextMenuClosed(context_menu_context_); -} - void WebContents::Undo() { web_contents()->Undo(); } @@ -1068,10 +1063,6 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("_printToPDF", &WebContents::PrintToPDF) .SetMethod("addWorkSpace", &WebContents::AddWorkSpace) .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace) - .SetMethod("_executeContextMenuCommand", - &WebContents::ExecuteContextMenuCommand) - .SetMethod("_notifyContextMenuClosed", - &WebContents::NotifyContextMenuClosed) .SetProperty("session", &WebContents::Session, true) .SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents, true) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 5a55ad2abd7a..ae231cd3c61d 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -13,7 +13,6 @@ #include "atom/browser/api/trackable_object.h" #include "atom/browser/common_web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" -#include "content/public/common/context_menu_params.h" #include "content/public/common/favicon_url.h" #include "native_mate/handle.h" #include "ui/gfx/image/image.h" @@ -93,8 +92,6 @@ class WebContents : public mate::TrackableObject, void SetAudioMuted(bool muted); bool IsAudioMuted(); void Print(mate::Arguments* args); - void ExecuteContextMenuCommand(int action); - void NotifyContextMenuClosed(); // Print current page as PDF. void PrintToPDF(const base::DictionaryValue& setting, @@ -259,9 +256,6 @@ class WebContents : public mate::TrackableObject, // embedders' zoom level change. void OnZoomLevelChanged(double level); - // Recent unhandled context menu context. - content::CustomContextMenuContext context_menu_context_; - v8::Global session_; v8::Global devtools_web_contents_; diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index afe70323f0a5..eab9f1967158 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -35,36 +35,6 @@ PDFPageSize = width_microns: 279400 custom_display_name: "Tabloid" -clickHandler = (action) -> - @_executeContextMenuCommand action - -convertToMenuTemplate = (items, handler) -> - template = [] - for item in items - do (item) -> - transformed = - if item.type is 'submenu' - type: 'submenu' - label: item.label - enabled: item.enabled - submenu: convertToMenuTemplate item.subItems, handler - else if item.type is 'separator' - type: 'separator' - else if item.type is 'checkbox' - type: 'checkbox' - label: item.label - enabled: item.enabled - checked: item.checked - else - type: 'normal' - label: item.label - enabled: item.enabled - if item.id? - transformed.click = -> - handler item.id - template.push transformed - template - wrapWebContents = (webContents) -> # webContents is an EventEmitter. webContents.__proto__ = EventEmitter.prototype @@ -96,15 +66,10 @@ wrapWebContents = (webContents) -> Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value) ipc.emit channel, event, args... - # Handle context menu action request from renderer widget. - webContents.on '-context-menu', (event, params) -> - if params.isPepperMenu - template = convertToMenuTemplate(params.menuItems, clickHandler.bind(webContents)) - menu = Menu.buildFromTemplate template - # The menu is expected to show asynchronously. - setImmediate -> - menu.popup params.x, params.y - webContents._notifyContextMenuClosed() + # Handle context menu action request from pepper plugin. + webContents.on 'pepper-context-menu', (event, params) -> + menu = Menu.buildFromTemplate params.menu + menu.popup params.x, params.y webContents.printToPDF = (options, callback) -> printingSetting = diff --git a/atom/common/native_mate_converters/content_converter.cc b/atom/common/native_mate_converters/content_converter.cc index 2318e7d8e837..15a57dea5fb8 100644 --- a/atom/common/native_mate_converters/content_converter.cc +++ b/atom/common/native_mate_converters/content_converter.cc @@ -4,50 +4,96 @@ #include "atom/common/native_mate_converters/content_converter.h" +#include + +#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/string16_converter.h" +#include "content/public/browser/web_contents.h" #include "content/public/common/context_menu_params.h" -#include "content/public/common/menu_item.h" #include "native_mate/dictionary.h" +namespace { + +void ExecuteCommand(content::WebContents* web_contents, + int action, + const content::CustomContextMenuContext& context) { + web_contents->ExecuteCustomContextMenuCommand(action, context); +} + +// Forward declaration for nested recursive call. +v8::Local MenuToV8(v8::Isolate* isolate, + content::WebContents* web_contents, + const content::CustomContextMenuContext& context, + const std::vector& menu); + +v8::Local MenuItemToV8( + v8::Isolate* isolate, + content::WebContents* web_contents, + const content::CustomContextMenuContext& context, + const content::MenuItem& item) { + mate::Dictionary v8_item = mate::Dictionary::CreateEmpty(isolate); + switch (item.type) { + case content::MenuItem::CHECKABLE_OPTION: + case content::MenuItem::GROUP: + v8_item.Set("checked", item.checked); + case content::MenuItem::OPTION: + case content::MenuItem::SUBMENU: + v8_item.Set("label", item.label); + v8_item.Set("enabled", item.enabled); + default: + v8_item.Set("type", item.type); + } + if (item.type == content::MenuItem::SUBMENU) + v8_item.Set("submenu", + MenuToV8(isolate, web_contents, context, item.submenu)); + else if (item.action > 0) + v8_item.Set("click", + base::Bind(ExecuteCommand, web_contents, item.action, context)); + return v8_item.GetHandle(); +} + +v8::Local MenuToV8(v8::Isolate* isolate, + content::WebContents* web_contents, + const content::CustomContextMenuContext& context, + const std::vector& menu) { + std::vector> v8_menu; + for (const auto& menu_item : menu) + v8_menu.push_back(MenuItemToV8(isolate, web_contents, context, menu_item)); + return mate::ConvertToV8(isolate, v8_menu); +} + +} // namespace + namespace mate { -template<> -struct Converter { - static v8::Local ToV8(v8::Isolate* isolate, - const content::MenuItem::Type& val) { - switch (val) { - case content::MenuItem::CHECKABLE_OPTION: - return StringToV8(isolate, "checkbox"); - case content::MenuItem::SEPARATOR: - return StringToV8(isolate, "separator"); - case content::MenuItem::SUBMENU: - return StringToV8(isolate, "submenu"); - default: - return StringToV8(isolate, "normal"); - } - } -}; - // static -v8::Local Converter::ToV8( - v8::Isolate* isolate, const content::MenuItem& val) { - mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); - dict.Set("id", val.action); - dict.Set("type", val.type); - dict.Set("label", val.label); - dict.Set("enabled", val.enabled); - dict.Set("checked", val.checked); - return mate::ConvertToV8(isolate, dict); +v8::Local Converter::ToV8( + v8::Isolate* isolate, const content::MenuItem::Type& val) { + switch (val) { + case content::MenuItem::CHECKABLE_OPTION: + return StringToV8(isolate, "checkbox"); + case content::MenuItem::GROUP: + return StringToV8(isolate, "radio"); + case content::MenuItem::SEPARATOR: + return StringToV8(isolate, "separator"); + case content::MenuItem::SUBMENU: + return StringToV8(isolate, "submenu"); + case content::MenuItem::OPTION: + default: + return StringToV8(isolate, "normal"); + } } // static -v8::Local Converter::ToV8( - v8::Isolate* isolate, const content::ContextMenuParams& val) { +v8::Local Converter::ToV8( + v8::Isolate* isolate, const ContextMenuParamsWithWebContents& val) { + const auto& params = val.first; mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); - dict.Set("x", val.x); - dict.Set("y", val.y); - dict.Set("isPepperMenu", val.custom_context.is_pepper_menu); - dict.Set("menuItems", val.custom_items); + dict.Set("x", params.x); + dict.Set("y", params.y); + if (params.custom_context.is_pepper_menu) + dict.Set("menu", MenuToV8(isolate, val.second, params.custom_context, + params.custom_items)); return mate::ConvertToV8(isolate, dict); } diff --git a/atom/common/native_mate_converters/content_converter.h b/atom/common/native_mate_converters/content_converter.h index 5cca2b38b251..7edee24fa142 100644 --- a/atom/common/native_mate_converters/content_converter.h +++ b/atom/common/native_mate_converters/content_converter.h @@ -5,25 +5,31 @@ #ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_ #define ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_ +#include + +#include "content/public/common/menu_item.h" #include "native_mate/converter.h" namespace content { struct ContextMenuParams; -struct MenuItem; +class WebContents; } +using ContextMenuParamsWithWebContents = + std::pair; + namespace mate { template<> -struct Converter { +struct Converter { static v8::Local ToV8(v8::Isolate* isolate, - const content::MenuItem& val); + const content::MenuItem::Type& val); }; template<> -struct Converter { +struct Converter { static v8::Local ToV8(v8::Isolate* isolate, - const content::ContextMenuParams& val); + const ContextMenuParamsWithWebContents& val); }; } // namespace mate From d332f2ab1c5eb555ea47345e9badc869dd337dcd Mon Sep 17 00:00:00 2001 From: frankenbot Date: Mon, 2 Nov 2015 21:16:12 -0800 Subject: [PATCH 394/738] Update redirects --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8fb9128d9c10..f8e1f2909ef6 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,14 @@ :zap: *Formerly known as Atom Shell* :zap: The Electron framework lets you write cross-platform desktop applications -using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org) and +using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/en/) and [Chromium](http://www.chromium.org) and is used in the [Atom editor](https://github.com/atom/atom). Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important announcements. -This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0). +This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0/). By participating, you are expected to uphold this code. Please report unacceptable behavior to atom@github.com. @@ -62,7 +62,7 @@ repository to see a minimal Electron app in action. You can ask questions and interact with the community in the following locations: -- [`electron`](http://discuss.atom.io/category/electron) category on the Atom +- [`electron`](http://discuss.atom.io/c/electron) category on the Atom forums - `#atom-shell` channel on Freenode - [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack From 7c7a7b96de198b1dff7d35334079d229ea372c6e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 3 Nov 2015 14:55:43 +0800 Subject: [PATCH 395/738] win: Do not set app user model id by default When user drags exe file into taskbar directly the pinned icon will not has an app user model id, so if we set app user model id in the application two icons will show in the taskbar. For apps installed with a installer it is not a problem since the shortcut icon will be created with app user model id, but we should also keep the ability to make portable apps work out of box. Fix #3303. --- atom/browser/browser.cc | 4 ---- atom/browser/browser.h | 9 +++++++-- atom/browser/browser_win.cc | 18 ++++++++++++------ 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 739921fda90f..e80cb4e60e20 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -89,10 +89,6 @@ std::string Browser::GetName() const { void Browser::SetName(const std::string& name) { name_override_ = name; - -#if defined(OS_WIN) - SetAppUserModelID(name); -#endif } bool Browser::OpenFile(const std::string& file_path) { diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 8719e18f3140..0500e317755b 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -100,8 +100,13 @@ class Browser : public WindowListObserver { // Add a custom task to jump list. void SetUserTasks(const std::vector& tasks); - // Set the application user model ID, called when "SetName" is called. - void SetAppUserModelID(const std::string& name); + // Set the application user model ID. + void SetAppUserModelID(const base::string16& name); + + // Returns the application user model ID, if there isn't one, then create + // one from app's name. + // The returned string managed by Browser, and should not be modified. + PCWSTR GetAppUserModelID(); #endif // Tell the application to open a file. diff --git a/atom/browser/browser_win.cc b/atom/browser/browser_win.cc index b861af945421..0e5ce8e2d955 100644 --- a/atom/browser/browser_win.cc +++ b/atom/browser/browser_win.cc @@ -56,7 +56,7 @@ void Browser::AddRecentDocument(const base::FilePath& path) { if (SUCCEEDED(hr)) { SHARDAPPIDINFO info; info.psi = item; - info.pszAppID = app_user_model_id_.c_str(); + info.pszAppID = GetAppUserModelID(); SHAddToRecentDocs(SHARD_APPIDINFO, &info); } } @@ -66,7 +66,7 @@ void Browser::ClearRecentDocuments() { if (FAILED(destinations.CoCreateInstance(CLSID_ApplicationDestinations, NULL, CLSCTX_INPROC_SERVER))) return; - if (FAILED(destinations->SetAppID(app_user_model_id_.c_str()))) + if (FAILED(destinations->SetAppID(GetAppUserModelID()))) return; destinations->RemoveAllDestinations(); } @@ -75,7 +75,7 @@ void Browser::SetUserTasks(const std::vector& tasks) { CComPtr destinations; if (FAILED(destinations.CoCreateInstance(CLSID_DestinationList))) return; - if (FAILED(destinations->SetAppID(app_user_model_id_.c_str()))) + if (FAILED(destinations->SetAppID(GetAppUserModelID()))) return; // Start a transaction that updates the JumpList of this application. @@ -117,12 +117,18 @@ void Browser::SetUserTasks(const std::vector& tasks) { destinations->CommitList(); } -void Browser::SetAppUserModelID(const std::string& name) { - app_user_model_id_ = base::string16(L"electron.app."); - app_user_model_id_ += base::UTF8ToUTF16(name); +void Browser::SetAppUserModelID(const base::string16& name) { + app_user_model_id_ = name; SetCurrentProcessExplicitAppUserModelID(app_user_model_id_.c_str()); } +PCWSTR Browser::GetAppUserModelID() { + if (app_user_model_id_.empty()) + SetAppUserModelID(base::UTF8ToUTF16(GetName())); + + return app_user_model_id_.c_str(); +} + std::string Browser::GetExecutableFileVersion() const { base::FilePath path; if (PathService::Get(base::FILE_EXE, &path)) { From 9047f81835d5e4d0c69d0c1634e17f68f4209601 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 3 Nov 2015 15:09:31 +0800 Subject: [PATCH 396/738] win: Set app user model ID in one place Fix #3297. Fix #2573. --- atom/browser/api/atom_api_app.cc | 14 ++------------ atom/browser/api/atom_api_app.h | 1 - atom/browser/browser.h | 6 +++--- atom/browser/browser_linux.cc | 3 +++ atom/browser/browser_mac.mm | 3 +++ atom/browser/browser_win.cc | 10 +++++----- 6 files changed, 16 insertions(+), 21 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index bd49f9fddc05..04ed06e0138f 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -7,10 +7,6 @@ #include #include -#if defined(OS_WIN) -#include -#endif - #include "atom/browser/api/atom_api_menu.h" #include "atom/browser/api/atom_api_session.h" #include "atom/browser/api/atom_api_web_contents.h" @@ -299,13 +295,6 @@ void App::SetDesktopName(const std::string& desktop_name) { #endif } -void App::SetAppUserModelId(const std::string& app_id) { -#if defined(OS_WIN) - base::string16 app_id_utf16 = base::UTF8ToUTF16(app_id); - SetCurrentProcessExplicitAppUserModelID(app_id_utf16.c_str()); -#endif -} - void App::AllowNTLMCredentialsForAllDomains(bool should_allow) { auto browser_context = static_cast( AtomBrowserMainParts::Get()->browser_context()); @@ -360,6 +349,8 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( base::Bind(&Browser::AddRecentDocument, browser)) .SetMethod("clearRecentDocuments", base::Bind(&Browser::ClearRecentDocuments, browser)) + .SetMethod("setAppUserModelId", + base::Bind(&Browser::SetAppUserModelID, browser)) #if defined(OS_WIN) .SetMethod("setUserTasks", base::Bind(&Browser::SetUserTasks, browser)) @@ -367,7 +358,6 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( .SetMethod("setPath", &App::SetPath) .SetMethod("getPath", &App::GetPath) .SetMethod("setDesktopName", &App::SetDesktopName) - .SetMethod("setAppUserModelId", &App::SetAppUserModelId) .SetMethod("allowNTLMCredentialsForAllDomains", &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 63cda4447e32..683093d886c9 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -67,7 +67,6 @@ class App : public mate::EventEmitter, const base::FilePath& path); void SetDesktopName(const std::string& desktop_name); - void SetAppUserModelId(const std::string& app_id); void AllowNTLMCredentialsForAllDomains(bool should_allow); bool MakeSingleInstance( const ProcessSingleton::NotificationCallback& callback); diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 0500e317755b..9f27816c5807 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -66,6 +66,9 @@ class Browser : public WindowListObserver { // Clear the recent documents list. void ClearRecentDocuments(); + // Set the application user model ID. + void SetAppUserModelID(const base::string16& name); + #if defined(OS_MACOSX) // Bounce the dock icon. enum BounceType { @@ -100,9 +103,6 @@ class Browser : public WindowListObserver { // Add a custom task to jump list. void SetUserTasks(const std::vector& tasks); - // Set the application user model ID. - void SetAppUserModelID(const base::string16& name); - // Returns the application user model ID, if there isn't one, then create // one from app's name. // The returned string managed by Browser, and should not be modified. diff --git a/atom/browser/browser_linux.cc b/atom/browser/browser_linux.cc index ea8fb7c10c5d..25cb9a0a2385 100644 --- a/atom/browser/browser_linux.cc +++ b/atom/browser/browser_linux.cc @@ -31,6 +31,9 @@ void Browser::AddRecentDocument(const base::FilePath& path) { void Browser::ClearRecentDocuments() { } +void Browser::SetAppUserModelID(const base::string16& name) { +} + std::string Browser::GetExecutableFileVersion() const { return brightray::GetApplicationVersion(); } diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index 2353aa6c42c3..6589057c2c6c 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -26,6 +26,9 @@ void Browser::AddRecentDocument(const base::FilePath& path) { void Browser::ClearRecentDocuments() { } +void Browser::SetAppUserModelID(const base::string16& name) { +} + std::string Browser::GetExecutableFileVersion() const { return brightray::GetApplicationVersion(); } diff --git a/atom/browser/browser_win.cc b/atom/browser/browser_win.cc index 0e5ce8e2d955..a2725b17c1f7 100644 --- a/atom/browser/browser_win.cc +++ b/atom/browser/browser_win.cc @@ -71,6 +71,11 @@ void Browser::ClearRecentDocuments() { destinations->RemoveAllDestinations(); } +void Browser::SetAppUserModelID(const base::string16& name) { + app_user_model_id_ = name; + SetCurrentProcessExplicitAppUserModelID(app_user_model_id_.c_str()); +} + void Browser::SetUserTasks(const std::vector& tasks) { CComPtr destinations; if (FAILED(destinations.CoCreateInstance(CLSID_DestinationList))) @@ -117,11 +122,6 @@ void Browser::SetUserTasks(const std::vector& tasks) { destinations->CommitList(); } -void Browser::SetAppUserModelID(const base::string16& name) { - app_user_model_id_ = name; - SetCurrentProcessExplicitAppUserModelID(app_user_model_id_.c_str()); -} - PCWSTR Browser::GetAppUserModelID() { if (app_user_model_id_.empty()) SetAppUserModelID(base::UTF8ToUTF16(GetName())); From 7b47b70c9e4dbf5edf1208e902e4a6ce27b4799e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 3 Nov 2015 15:16:45 +0800 Subject: [PATCH 397/738] Fix building on POSIX --- atom/browser/browser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 9f27816c5807..447a526de6df 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -11,12 +11,12 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/observer_list.h" +#include "base/strings/string16.h" #include "atom/browser/browser_observer.h" #include "atom/browser/window_list_observer.h" #if defined(OS_WIN) #include "base/files/file_path.h" -#include "base/strings/string16.h" #endif namespace base { From 8a3268b70c9eacf32a347831a509bec1122e7e19 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 3 Nov 2015 15:30:54 +0800 Subject: [PATCH 398/738] docs: Add notes for working together with Squirrel --- docs/api/auto-updater.md | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/docs/api/auto-updater.md b/docs/api/auto-updater.md index bda1d46bb094..eb0ea3752995 100644 --- a/docs/api/auto-updater.md +++ b/docs/api/auto-updater.md @@ -9,15 +9,22 @@ still some subtle differences on each platform. ### OS X -On OS X, the `autoUpdater` module is built upon [Squirrel.Mac][squirrel-mac], meaning you -don't need any special setup to make it work. For server-side requirements, you -can read [Server Support][server-support]. +On OS X, the `autoUpdater` module is built upon [Squirrel.Mac][squirrel-mac], +meaning you don't need any special setup to make it work. For server-side +requirements, you can read [Server Support][server-support]. ### Windows -On Windows, you have to install your app into a user's machine before you can use -the auto-updater, so it is recommended to use [grunt-electron-installer][installer] -module to generate a Windows installer. +On Windows, you have to install your app into a user's machine before you can +use the auto-updater, so it is recommended to use +[grunt-electron-installer][installer] module to generate a Windows installer. + +The installer generated with Squirrel will create a shortcut icon with an +[Application User Model ID][app-user-model-id] in the format of +`com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`, examples are +`com.squirrel.slack.Slack` and `com.squirrel.code.Code`. You have to use the +same ID for your app with `app.setAppUserModelId` API, otherwise Windows will +not be able to pin your app properly in task bar. The server-side setup is also different from OS X. You can read the documents of [Squirrel.Windows][squirrel-windows] to get more details. @@ -84,10 +91,11 @@ using this API. ### `autoUpdater.quitAndInstall()` -Restarts the app and installs the update after it has been downloaded. It should -only be called after `update-downloaded` has been emitted. +Restarts the app and installs the update after it has been downloaded. It +should only be called after `update-downloaded` has been emitted. [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 726910df39a94d1ac5fee432644cf732f19ee317 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 3 Nov 2015 15:36:44 +0800 Subject: [PATCH 399/738] docs: app.setAppUserModelId --- docs/api/app.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/api/app.md b/docs/api/app.md index 204155cfa053..00aade7c54ab 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -375,6 +375,12 @@ app.on('ready', function() { }); ``` +### `app.setAppUserModelId(id)` _Windows_ + +* `id` String + +Changes the [Application User Model ID][app-user-model-id] to `id`. + ### `app.commandLine.appendSwitch(switch[, value])` Append a switch (with optional `value`) to Chromium's command line. @@ -435,3 +441,4 @@ Sets the application's [dock menu][dock-menu]. [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 1b165559f550f7dc421683d345b032e71e070e04 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 3 Nov 2015 15:49:37 +0800 Subject: [PATCH 400/738] win: Use electron.app.$1 as default user model id This is to keep compatibility with old apps that don't set app user model id explicitly. --- atom/browser/browser_win.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/atom/browser/browser_win.cc b/atom/browser/browser_win.cc index a2725b17c1f7..ce36d56b620c 100644 --- a/atom/browser/browser_win.cc +++ b/atom/browser/browser_win.cc @@ -15,6 +15,7 @@ #include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" #include "base/path_service.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/win/win_util.h" @@ -25,6 +26,8 @@ namespace atom { namespace { +const wchar_t kAppUserModelIDFormat[] = L"electron.app.$1"; + BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) { DWORD target_process_id = *reinterpret_cast(param); DWORD process_id = 0; @@ -123,8 +126,10 @@ void Browser::SetUserTasks(const std::vector& tasks) { } PCWSTR Browser::GetAppUserModelID() { - if (app_user_model_id_.empty()) - SetAppUserModelID(base::UTF8ToUTF16(GetName())); + if (app_user_model_id_.empty()) { + SetAppUserModelID(ReplaceStringPlaceholders( + kAppUserModelIDFormat, base::UTF8ToUTF16(GetName()), nullptr)); + } return app_user_model_id_.c_str(); } From 8c989c4630d66138777849c56768ee66148f7dbe Mon Sep 17 00:00:00 2001 From: frankenbot Date: Tue, 3 Nov 2015 09:13:48 -0800 Subject: [PATCH 401/738] Update nodejs url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8e1f2909ef6..beb96b4e5c2a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ :zap: *Formerly known as Atom Shell* :zap: The Electron framework lets you write cross-platform desktop applications -using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/en/) and +using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and [Chromium](http://www.chromium.org) and is used in the [Atom editor](https://github.com/atom/atom). From 7c41f0e0e30977ed6a3f37ee0e524d7c75544c2d Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 3 Nov 2015 16:12:01 -0800 Subject: [PATCH 402/738] remove kDisableLegacyIntermediateWindow switch set --- atom/app/atom_main_delegate.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index e4ac7cfc0a99..3bc1ac497082 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -102,13 +102,6 @@ void AtomMainDelegate::PreSandboxStartup() { if (!IsBrowserProcess(command_line)) return; -#if defined(OS_WIN) - // Disable the LegacyRenderWidgetHostHWND, it made frameless windows unable - // to move and resize. We may consider enabling it again after upgraded to - // Chrome 38, which should have fixed the problem. - command_line->AppendSwitch(switches::kDisableLegacyIntermediateWindow); -#endif - // Disable renderer sandbox for most of node's functions. command_line->AppendSwitch(switches::kNoSandbox); From 4013b652ff1e0cab465b2319b6521be799a825f4 Mon Sep 17 00:00:00 2001 From: mgarciaisaia Date: Wed, 4 Nov 2015 01:09:05 -0300 Subject: [PATCH 403/738] :checkered_flag::bug: Buffer overflows in tooltips Fixes #3290. --- atom/browser/ui/win/notify_icon.cc | 6 +++--- atom/browser/ui/win/taskbar_host.cc | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/atom/browser/ui/win/notify_icon.cc b/atom/browser/ui/win/notify_icon.cc index c88d4c810ef8..b2ca4bceedd1 100644 --- a/atom/browser/ui/win/notify_icon.cc +++ b/atom/browser/ui/win/notify_icon.cc @@ -113,7 +113,7 @@ void NotifyIcon::SetToolTip(const std::string& tool_tip) { NOTIFYICONDATA icon_data; InitIconData(&icon_data); icon_data.uFlags |= NIF_TIP; - wcscpy_s(icon_data.szTip, base::UTF8ToUTF16(tool_tip).c_str()); + wcsncpy_s(icon_data.szTip, base::UTF8ToUTF16(tool_tip).c_str(), _TRUNCATE); BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data); if (!result) LOG(WARNING) << "Unable to set tooltip for status tray icon"; @@ -126,8 +126,8 @@ void NotifyIcon::DisplayBalloon(const gfx::Image& icon, InitIconData(&icon_data); icon_data.uFlags |= NIF_INFO; icon_data.dwInfoFlags = NIIF_INFO; - wcscpy_s(icon_data.szInfoTitle, title.c_str()); - wcscpy_s(icon_data.szInfo, contents.c_str()); + wcsncpy_s(icon_data.szInfoTitle, title.c_str(), _TRUNCATE); + wcsncpy_s(icon_data.szInfo, contents.c_str(), _TRUNCATE); icon_data.uTimeout = 0; base::win::Version win_version = base::win::GetVersion(); diff --git a/atom/browser/ui/win/taskbar_host.cc b/atom/browser/ui/win/taskbar_host.cc index a8e6ff2926cd..0d250829110f 100644 --- a/atom/browser/ui/win/taskbar_host.cc +++ b/atom/browser/ui/win/taskbar_host.cc @@ -97,7 +97,8 @@ bool TaskbarHost::SetThumbarButtons( // Set tooltip. if (!button.tooltip.empty()) { thumb_button.dwMask |= THB_TOOLTIP; - wcscpy_s(thumb_button.szTip, base::UTF8ToUTF16(button.tooltip).c_str()); + wcsncpy_s(thumb_button.szTip, base::UTF8ToUTF16(button.tooltip).c_str(), + _TRUNCATE); } // Save callback. From 96cc5485cb0f94d4a40e37a20c1c76c6a39c9fdc Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 4 Nov 2015 17:47:14 +0900 Subject: [PATCH 404/738] Update as upstream --- docs-translations/ko-KR/api/app.md | 7 +++++++ docs-translations/ko-KR/api/auto-updater.md | 11 +++++++++-- .../ko-KR/tutorial/using-native-node-modules.md | 3 +++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index a443d1252f8e..26235fbe444b 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -362,6 +362,12 @@ app.on('ready', function() { }); ``` +### `app.setAppUserModelId(id)` _Windows_ + +* `id` String + +[Application User Model ID][app-user-model-id]를 `id`로 변경합니다. + ### `app.commandLine.appendSwitch(switch[, value])` Chrominum의 명령줄에 스위치를 추가합니다. `value`는 추가적인 값을 뜻하며 옵션입니다. @@ -418,3 +424,4 @@ 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 diff --git a/docs-translations/ko-KR/api/auto-updater.md b/docs-translations/ko-KR/api/auto-updater.md index b940bb536181..f12d04042ef2 100644 --- a/docs-translations/ko-KR/api/auto-updater.md +++ b/docs-translations/ko-KR/api/auto-updater.md @@ -15,7 +15,13 @@ OS X에선 `auto-updater` 모듈이 [Squirrel.Mac][squirrel-mac]를 기반으로 ### Windows Windows에선 `auto-updater` 모듈을 사용하기 전에 어플리케이션을 사용자의 장치에 설치해야 합니다. -[grunt-electron-installer][installer]를 사용하여 어플리케이션 셋업을 만드는 것을 권장합니다. +[grunt-electron-installer][installer]를 사용하여 어플리케이션 인스톨러를 만드는 것을 권장합니다. + +Squirrel로 생성된 인스톨러는 [Application User Model ID][app-user-model-id]와 함께 +`com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`으로 형식화된 바로가기 아이콘을 생성합니다. +`com.squirrel.slack.Slack` 과 `com.squirrel.code.Code`가 그 예시입니다. +`app.setAppUserModelId` API를 통해 어플리케이션 ID를 동일하게 유지해야 합니다. +그렇지 않으면 Windows 작업 표시줄에 어플리케이션을 고정할 때 제대로 적용되지 않을 수 있습니다. 서버 사이드 요구 사항 또한 OS X와 다르게 적용됩니다. 자세한 내용은 [Squirrel.Windows][squirrel-windows]를 참고하세요. @@ -74,7 +80,7 @@ Returns: 서버에 새로운 업데이트가 있는지 요청을 보내 확인합니다. API를 사용하기 전에 `setFeedUrl`를 호출해야 합니다. -### `autoUpdater.quitAndUpdate()` +### `autoUpdater.quitAndInstall()` 어플리케이션을 다시 시작하고 다운로드된 업데이트를 설치합니다. 이 메서드는 `update-downloaded` 이벤트가 발생한 이후에만 사용할 수 있습니다. @@ -83,3 +89,4 @@ Returns: [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 diff --git a/docs-translations/ko-KR/tutorial/using-native-node-modules.md b/docs-translations/ko-KR/tutorial/using-native-node-modules.md index 0691fefc864d..45c4811aa1a1 100644 --- a/docs-translations/ko-KR/tutorial/using-native-node-modules.md +++ b/docs-translations/ko-KR/tutorial/using-native-node-modules.md @@ -29,6 +29,9 @@ npm install --save-dev electron-rebuild # 필요한 네이티브 모듈을 `npm install`로 설치한 후 다음 명령을 실행하세요: ./node_modules/.bin/electron-rebuild + +# Windows에서 문제가 발생하면 다음 명령을 대신 실행하세요: +.\node_modules\.bin\electron-rebuild.cmd ``` ### `npm`을 이용한 방법 From 441cc3e57ea926a9cc2b27f5d6e8a67b7abe2de3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 4 Nov 2015 16:50:19 +0800 Subject: [PATCH 405/738] Style fix --- atom/browser/api/lib/app.coffee | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 18c80dc2b1f4..cc676df0dd5a 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -11,14 +11,14 @@ wrapSession = (session) -> # session is an Event Emitter. session.__proto__ = EventEmitter.prototype -wrapDownloadItem = (download_item) -> - # download_item is an Event Emitter. - download_item.__proto__ = EventEmitter.prototype +wrapDownloadItem = (downloadItem) -> + # downloadItem is an Event Emitter. + downloadItem.__proto__ = EventEmitter.prototype # Be compatible with old APIs. - download_item.url = download_item.getUrl() - download_item.filename = download_item.getFilename() - download_item.mimeType = download_item.getMimeType() - download_item.hasUserGesture = download_item.hasUserGesture() + downloadItem.url = downloadItem.getUrl() + downloadItem.filename = downloadItem.getFilename() + downloadItem.mimeType = downloadItem.getMimeType() + downloadItem.hasUserGesture = downloadItem.hasUserGesture() app.setApplicationMenu = (menu) -> require('menu').setApplicationMenu menu @@ -57,7 +57,7 @@ app.setDataPath = (path) -> @setPath 'userData', path app.resolveProxy = -> @defaultSession.resolveProxy.apply @defaultSession, arguments app.on 'activate', (event, hasVisibleWindows) -> @emit 'activate-with-no-open-windows' if not hasVisibleWindows -# Session wrapper. +# Wrappers for native classes. sessionBindings._setWrapSession wrapSession process.once 'exit', sessionBindings._clearWrapSession From 75f49477ca4e2d25c6dfb4d19440325d84d5a3b5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 4 Nov 2015 16:54:36 +0800 Subject: [PATCH 406/738] Cleanup wrapper function when app has done quitting The app may still do something when quitting, we need to make sure the wrapper function is still there at that time. --- atom/browser/api/atom_api_download_item.cc | 22 +++++++++++++--------- atom/browser/api/atom_api_session.cc | 16 ++++++++++------ atom/browser/api/atom_api_web_contents.cc | 13 ++++++++----- atom/browser/api/lib/app.coffee | 3 --- atom/browser/api/lib/web-contents.coffee | 1 - 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index ec4dcd84b285..691cfbfef594 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -6,6 +6,7 @@ #include +#include "atom/browser/atom_browser_main_parts.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h" @@ -159,14 +160,6 @@ mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder( .SetMethod("setSavePath", &DownloadItem::SetSavePath); } -void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) { - g_wrap_download_item = callback; -} - -void ClearWrapDownloadItem() { - g_wrap_download_item.Reset(); -} - // static mate::Handle DownloadItem::Create( v8::Isolate* isolate, content::DownloadItem* item) { @@ -182,6 +175,18 @@ void* DownloadItem::UserDataKey() { return &kDownloadItemSavePathKey; } +void ClearWrapDownloadItem() { + g_wrap_download_item.Reset(); +} + +void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) { + g_wrap_download_item = callback; + + // Cleanup the wrapper on exit. + atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback( + base::Bind(ClearWrapDownloadItem)); +} + } // namespace api } // namespace atom @@ -193,7 +198,6 @@ void Initialize(v8::Local exports, v8::Local unused, v8::Isolate* isolate = context->GetIsolate(); mate::Dictionary dict(isolate, exports); dict.SetMethod("_setWrapDownloadItem", &atom::api::SetWrapDownloadItem); - dict.SetMethod("_clearWrapDownloadItem", &atom::api::ClearWrapDownloadItem); } } // namespace diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 5bb96710f226..0ec9c05ed84e 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -9,9 +9,10 @@ #include "atom/browser/api/atom_api_cookies.h" #include "atom/browser/api/atom_api_download_item.h" -#include "atom/browser/atom_browser_context.h" #include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/api/save_page_handler.h" +#include "atom/browser/atom_browser_context.h" +#include "atom/browser/atom_browser_main_parts.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" @@ -395,14 +396,18 @@ mate::Handle Session::FromPartition( static_cast(browser_context.get())); } -void SetWrapSession(const WrapSessionCallback& callback) { - g_wrap_session = callback; -} - void ClearWrapSession() { g_wrap_session.Reset(); } +void SetWrapSession(const WrapSessionCallback& callback) { + g_wrap_session = callback; + + // Cleanup the wrapper on exit. + atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback( + base::Bind(ClearWrapSession)); +} + } // namespace api } // namespace atom @@ -415,7 +420,6 @@ void Initialize(v8::Local exports, v8::Local unused, mate::Dictionary dict(isolate, exports); dict.SetMethod("fromPartition", &atom::api::Session::FromPartition); dict.SetMethod("_setWrapSession", &atom::api::SetWrapSession); - dict.SetMethod("_clearWrapSession", &atom::api::ClearWrapSession); } } // namespace diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index c329b257a290..5165877d1670 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1124,14 +1124,18 @@ mate::Handle WebContents::Create( return handle; } -void SetWrapWebContents(const WrapWebContentsCallback& callback) { - g_wrap_web_contents = callback; -} - void ClearWrapWebContents() { g_wrap_web_contents.Reset(); } +void SetWrapWebContents(const WrapWebContentsCallback& callback) { + g_wrap_web_contents = callback; + + // Cleanup the wrapper on exit. + atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback( + base::Bind(ClearWrapWebContents)); +} + } // namespace api } // namespace atom @@ -1145,7 +1149,6 @@ void Initialize(v8::Local exports, v8::Local unused, mate::Dictionary dict(isolate, exports); dict.SetMethod("create", &atom::api::WebContents::Create); dict.SetMethod("_setWrapWebContents", &atom::api::SetWrapWebContents); - dict.SetMethod("_clearWrapWebContents", &atom::api::ClearWrapWebContents); } } // namespace diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index cc676df0dd5a..ba68076177ae 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -59,10 +59,7 @@ app.on 'activate', (event, hasVisibleWindows) -> @emit 'activate-with-no-open-wi # Wrappers for native classes. sessionBindings._setWrapSession wrapSession -process.once 'exit', sessionBindings._clearWrapSession - downloadItemBindings._setWrapDownloadItem wrapDownloadItem -process.once 'exit', downloadItemBindings._clearWrapDownloadItem # Only one App object pemitted. module.exports = app diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index eab9f1967158..331a561189d7 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -112,7 +112,6 @@ wrapWebContents = (webContents) -> @_printToPDF printingSetting, callback binding._setWrapWebContents wrapWebContents -process.once 'exit', binding._clearWrapWebContents module.exports.create = (options={}) -> binding.create(options) From 84410a7e1c1a053220333e374b1445bd9d2259ff Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 4 Nov 2015 17:23:27 +0800 Subject: [PATCH 407/738] mac: Destroy the app delegate before running destruction callbacks Otherwise users might be able to access wrapper functions after they are destroyed. --- atom/browser/atom_browser_main_parts.cc | 4 ++++ atom/browser/atom_browser_main_parts.h | 5 ++++- atom/browser/atom_browser_main_parts_mac.mm | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 5fae5bfdbedd..f6d1070e875d 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -128,6 +128,10 @@ void AtomBrowserMainParts::PostMainMessageLoopStart() { void AtomBrowserMainParts::PostMainMessageLoopRun() { brightray::BrowserMainParts::PostMainMessageLoopRun(); +#if defined(OS_MACOSX) + FreeAppDelegate(); +#endif + // Make sure destruction callbacks are called before message loop is // destroyed, otherwise some objects that need to be deleted on IO thread // won't be freed. diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index 65b142157dc1..360b1cba1169 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -46,7 +46,6 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { void PostMainMessageLoopRun() override; #if defined(OS_MACOSX) void PreMainMessageLoopStart() override; - void PostDestroyThreads() override; #endif private: @@ -56,6 +55,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { void HandleShutdownSignals(); #endif +#if defined(OS_MACOSX) + void FreeAppDelegate(); +#endif + // A fake BrowserProcess object that used to feed the source code from chrome. scoped_ptr fake_browser_process_; diff --git a/atom/browser/atom_browser_main_parts_mac.mm b/atom/browser/atom_browser_main_parts_mac.mm index 1de07dfc0e44..42e3100f490e 100644 --- a/atom/browser/atom_browser_main_parts_mac.mm +++ b/atom/browser/atom_browser_main_parts_mac.mm @@ -34,7 +34,7 @@ void AtomBrowserMainParts::PreMainMessageLoopStart() { setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; } -void AtomBrowserMainParts::PostDestroyThreads() { +void AtomBrowserMainParts::FreeAppDelegate() { [[NSApp delegate] release]; [NSApp setDelegate:nil]; } From 07c55f321fd5baf8dc5c8646d171f6de90d7f165 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 4 Nov 2015 17:31:10 +0800 Subject: [PATCH 408/738] Destroy JS env immediately after running destruction callbacks --- atom/browser/atom_browser_main_parts.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index f6d1070e875d..041c9bfc8fbe 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -137,6 +137,14 @@ void AtomBrowserMainParts::PostMainMessageLoopRun() { // won't be freed. for (const auto& callback : destruction_callbacks_) callback.Run(); + + // Destroy JavaScript environment immediately after running destruction + // callbacks. + gc_timer_.Stop(); + node_debugger_.reset(); + atom_bindings_.reset(); + node_bindings_.reset(); + js_env_.reset(); } } // namespace atom From d56b34de3b9e3065f1b4aa8facdd78a840bb1acc Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 4 Nov 2015 18:21:03 +0800 Subject: [PATCH 409/738] Make sure all native resources get freed on exit --- atom/browser/api/atom_api_global_shortcut.cc | 3 +++ atom/browser/api/atom_api_global_shortcut.h | 9 ++++++--- atom/browser/api/atom_api_menu.cc | 8 ++++++++ atom/browser/api/atom_api_menu.h | 10 +++++++--- atom/browser/api/atom_api_menu_mac.h | 1 + atom/browser/api/atom_api_menu_mac.mm | 5 +++++ atom/browser/api/atom_api_power_monitor.cc | 3 +++ atom/browser/api/atom_api_power_monitor.h | 9 ++++++--- atom/browser/api/atom_api_power_save_blocker.cc | 5 +++++ atom/browser/api/atom_api_power_save_blocker.h | 10 ++++++---- atom/browser/api/atom_api_tray.h | 10 ++++++---- 11 files changed, 56 insertions(+), 17 deletions(-) diff --git a/atom/browser/api/atom_api_global_shortcut.cc b/atom/browser/api/atom_api_global_shortcut.cc index f5a03e4abf90..6ab4fa4b6186 100644 --- a/atom/browser/api/atom_api_global_shortcut.cc +++ b/atom/browser/api/atom_api_global_shortcut.cc @@ -23,6 +23,9 @@ GlobalShortcut::GlobalShortcut() { } GlobalShortcut::~GlobalShortcut() { +} + +void GlobalShortcut::Destroy() { UnregisterAll(); } diff --git a/atom/browser/api/atom_api_global_shortcut.h b/atom/browser/api/atom_api_global_shortcut.h index 15cd3d4e0edb..93eb7853ae0d 100644 --- a/atom/browser/api/atom_api_global_shortcut.h +++ b/atom/browser/api/atom_api_global_shortcut.h @@ -8,9 +8,9 @@ #include #include +#include "atom/browser/api/trackable_object.h" #include "base/callback.h" #include "chrome/browser/extensions/global_shortcut_listener.h" -#include "native_mate/wrappable.h" #include "native_mate/handle.h" #include "ui/base/accelerators/accelerator.h" @@ -19,13 +19,16 @@ namespace atom { namespace api { class GlobalShortcut : public extensions::GlobalShortcutListener::Observer, - public mate::Wrappable { + public mate::TrackableObject { public: static mate::Handle Create(v8::Isolate* isolate); protected: GlobalShortcut(); - virtual ~GlobalShortcut(); + ~GlobalShortcut() override; + + // mate::TrackableObject: + void Destroy() override; // mate::Wrappable implementations: mate::ObjectTemplateBuilder GetObjectTemplateBuilder( diff --git a/atom/browser/api/atom_api_menu.cc b/atom/browser/api/atom_api_menu.cc index 9bd724a9612e..1f16a428da01 100644 --- a/atom/browser/api/atom_api_menu.cc +++ b/atom/browser/api/atom_api_menu.cc @@ -27,6 +27,14 @@ Menu::Menu() Menu::~Menu() { } +void Menu::Destroy() { + model_.reset(); +} + +bool Menu::IsDestroyed() const { + return !model_; +} + void Menu::AfterInit(v8::Isolate* isolate) { mate::Dictionary wrappable(isolate, GetWrapper(isolate)); mate::Dictionary delegate; diff --git a/atom/browser/api/atom_api_menu.h b/atom/browser/api/atom_api_menu.h index 0d93c0d46be6..545dd18e386c 100644 --- a/atom/browser/api/atom_api_menu.h +++ b/atom/browser/api/atom_api_menu.h @@ -8,16 +8,16 @@ #include #include "atom/browser/api/atom_api_window.h" +#include "atom/browser/api/trackable_object.h" #include "atom/browser/ui/atom_menu_model.h" #include "base/callback.h" #include "base/memory/scoped_ptr.h" -#include "native_mate/wrappable.h" namespace atom { namespace api { -class Menu : public mate::Wrappable, +class Menu : public mate::TrackableObject, public AtomMenuModel::Delegate { public: static mate::Wrappable* Create(); @@ -37,9 +37,13 @@ class Menu : public mate::Wrappable, protected: Menu(); - virtual ~Menu(); + ~Menu() override; + + // mate::TrackableObject: + void Destroy() override; // mate::Wrappable: + bool IsDestroyed() const override; void AfterInit(v8::Isolate* isolate) override; // ui::SimpleMenuModel::Delegate: diff --git a/atom/browser/api/atom_api_menu_mac.h b/atom/browser/api/atom_api_menu_mac.h index 5a086776a639..baa2aff349e1 100644 --- a/atom/browser/api/atom_api_menu_mac.h +++ b/atom/browser/api/atom_api_menu_mac.h @@ -19,6 +19,7 @@ class MenuMac : public Menu { protected: MenuMac(); + void Destroy() override; void Popup(Window* window) override; void PopupAt(Window* window, int x, int y) override; diff --git a/atom/browser/api/atom_api_menu_mac.mm b/atom/browser/api/atom_api_menu_mac.mm index 071753218d6a..5936e0439f4f 100644 --- a/atom/browser/api/atom_api_menu_mac.mm +++ b/atom/browser/api/atom_api_menu_mac.mm @@ -18,6 +18,11 @@ namespace api { MenuMac::MenuMac() { } +void MenuMac::Destroy() { + menu_controller_.reset(); + Menu::Destroy(); +} + void MenuMac::Popup(Window* window) { NativeWindow* native_window = window->window(); if (!native_window) diff --git a/atom/browser/api/atom_api_power_monitor.cc b/atom/browser/api/atom_api_power_monitor.cc index 31b35e10cea8..eeb9475c2847 100644 --- a/atom/browser/api/atom_api_power_monitor.cc +++ b/atom/browser/api/atom_api_power_monitor.cc @@ -19,6 +19,9 @@ PowerMonitor::PowerMonitor() { } PowerMonitor::~PowerMonitor() { +} + +void PowerMonitor::Destroy() { base::PowerMonitor::Get()->RemoveObserver(this); } diff --git a/atom/browser/api/atom_api_power_monitor.h b/atom/browser/api/atom_api_power_monitor.h index dcf0906b437f..9303b3ab288f 100644 --- a/atom/browser/api/atom_api_power_monitor.h +++ b/atom/browser/api/atom_api_power_monitor.h @@ -5,7 +5,7 @@ #ifndef ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_ #define ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_ -#include "atom/browser/api/event_emitter.h" +#include "atom/browser/api/trackable_object.h" #include "base/compiler_specific.h" #include "base/power_monitor/power_observer.h" #include "native_mate/handle.h" @@ -14,14 +14,17 @@ namespace atom { namespace api { -class PowerMonitor : public mate::EventEmitter, +class PowerMonitor : public mate::TrackableObject, public base::PowerObserver { public: static v8::Local Create(v8::Isolate* isolate); protected: PowerMonitor(); - virtual ~PowerMonitor(); + ~PowerMonitor() override; + + // mate::TrackableObject: + void Destroy() override; // base::PowerObserver implementations: void OnPowerStateChange(bool on_battery_power) override; diff --git a/atom/browser/api/atom_api_power_save_blocker.cc b/atom/browser/api/atom_api_power_save_blocker.cc index 58983e6c846a..f77979ae417f 100644 --- a/atom/browser/api/atom_api_power_save_blocker.cc +++ b/atom/browser/api/atom_api_power_save_blocker.cc @@ -45,6 +45,11 @@ PowerSaveBlocker::PowerSaveBlocker() PowerSaveBlocker::~PowerSaveBlocker() { } +void PowerSaveBlocker::Destroy() { + power_save_blocker_types_.clear(); + power_save_blocker_.reset(); +} + void PowerSaveBlocker::UpdatePowerSaveBlocker() { if (power_save_blocker_types_.empty()) { power_save_blocker_.reset(); diff --git a/atom/browser/api/atom_api_power_save_blocker.h b/atom/browser/api/atom_api_power_save_blocker.h index 9861f2b0f7cd..e7ce97878ffb 100644 --- a/atom/browser/api/atom_api_power_save_blocker.h +++ b/atom/browser/api/atom_api_power_save_blocker.h @@ -7,10 +7,10 @@ #include +#include "atom/browser/api/trackable_object.h" #include "base/memory/scoped_ptr.h" #include "content/public/browser/power_save_blocker.h" #include "native_mate/handle.h" -#include "native_mate/wrappable.h" namespace mate { class Dictionary; @@ -20,13 +20,16 @@ namespace atom { namespace api { -class PowerSaveBlocker : public mate::Wrappable { +class PowerSaveBlocker : public mate::TrackableObject { public: static mate::Handle Create(v8::Isolate* isolate); protected: PowerSaveBlocker(); - virtual ~PowerSaveBlocker(); + ~PowerSaveBlocker() override; + + // mate::TrackableObject: + void Destroy() override; // mate::Wrappable implementations: mate::ObjectTemplateBuilder GetObjectTemplateBuilder( @@ -48,7 +51,6 @@ class PowerSaveBlocker : public mate::Wrappable { std::map; PowerSaveBlockerTypeMap power_save_blocker_types_; - DISALLOW_COPY_AND_ASSIGN(PowerSaveBlocker); }; diff --git a/atom/browser/api/atom_api_tray.h b/atom/browser/api/atom_api_tray.h index dc9302597cf3..9a423f61764f 100644 --- a/atom/browser/api/atom_api_tray.h +++ b/atom/browser/api/atom_api_tray.h @@ -8,7 +8,7 @@ #include #include -#include "atom/browser/api/event_emitter.h" +#include "atom/browser/api/trackable_object.h" #include "atom/browser/ui/tray_icon_observer.h" #include "base/memory/scoped_ptr.h" @@ -29,7 +29,7 @@ namespace api { class Menu; -class Tray : public mate::EventEmitter, +class Tray : public mate::TrackableObject, public TrayIconObserver { public: static mate::Wrappable* New(v8::Isolate* isolate, const gfx::Image& image); @@ -39,7 +39,7 @@ class Tray : public mate::EventEmitter, protected: explicit Tray(const gfx::Image& image); - virtual ~Tray(); + ~Tray() override; // TrayIconObserver: void OnClicked(const gfx::Rect& bounds, int modifiers) override; @@ -53,7 +53,9 @@ class Tray : public mate::EventEmitter, // mate::Wrappable: bool IsDestroyed() const override; - void Destroy(); + // mate::TrackableObject: + void Destroy() override; + void SetImage(mate::Arguments* args, const gfx::Image& image); void SetPressedImage(mate::Arguments* args, const gfx::Image& image); void SetToolTip(mate::Arguments* args, const std::string& tool_tip); From e4f74bb87ed246609b473920ab6cbd7a0e78d44a Mon Sep 17 00:00:00 2001 From: Kevin Simper Date: Tue, 3 Nov 2015 16:11:29 +0100 Subject: [PATCH 410/738] Update devtools-extension with a note about it not working --- docs/tutorial/devtools-extension.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/tutorial/devtools-extension.md b/docs/tutorial/devtools-extension.md index 20ba7031d8ad..8a2144be6966 100644 --- a/docs/tutorial/devtools-extension.md +++ b/docs/tutorial/devtools-extension.md @@ -8,6 +8,8 @@ the `BrowserWindow.addDevToolsExtension` API to load them. The loaded extensions will be remembered so you don't need to call the API every time when creating a window. +** NOTE: React DevTools does not work, follow the issue here https://github.com/atom/electron/issues/915 ** + For example, to use the [React DevTools Extension](https://github.com/facebook/react-devtools) , first you need to download its source code: From 4ce840d8e6c155f1465c286c87ac6edd63b2eb6f Mon Sep 17 00:00:00 2001 From: Ryan Molden Date: Wed, 4 Nov 2015 11:42:35 -0800 Subject: [PATCH 411/738] Re-enable accessibility in Electron on Windows In conjunction with commit 7c41f0e. --- atom/browser/native_window_views_win.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/atom/browser/native_window_views_win.cc b/atom/browser/native_window_views_win.cc index d49683acb3cf..02ebd2ef32fc 100644 --- a/atom/browser/native_window_views_win.cc +++ b/atom/browser/native_window_views_win.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "atom/browser/native_window_views.h" +#include "content/public/browser/browser_accessibility_state.h" namespace atom { @@ -83,6 +84,20 @@ bool NativeWindowViews::PreHandleMSG( NotifyWindowMessage(message, w_param, l_param); switch (message) { + // Screen readers send WM_GETOBJECT in order to get the accessibility + // object, so take this opportunity to push Chromium into accessible + // mode if it isn't already, always say we didn't handle the message + // because we still want Chromium to handle returning the actual + // accessibility object. + case WM_GETOBJECT: { + const DWORD obj_id = static_cast(l_param); + if (obj_id == OBJID_CLIENT) { + const auto axState = content::BrowserAccessibilityState::GetInstance(); + if (axState && !axState->IsAccessibleBrowser()) + axState->OnScreenReaderDetected(); + } + return false; + } case WM_COMMAND: // Handle thumbar button click message. if (HIWORD(w_param) == THBN_CLICKED) From 4ff5ce4d6d4b8104c1dfca2b95f15ab847a2a3ed Mon Sep 17 00:00:00 2001 From: Tyler Gibson Date: Wed, 4 Nov 2015 13:40:12 -0800 Subject: [PATCH 412/738] Fixing MoveItemToTrash behavior in Windows Modifying MoveItemToTrash for Windows to actually verify file can be moved to a drive's recycle bin before attempting to delete it. PR: #3337. --- atom/common/platform_util_win.cc | 212 +++++++++++++++++++++++++++---- 1 file changed, 188 insertions(+), 24 deletions(-) diff --git a/atom/common/platform_util_win.cc b/atom/common/platform_util_win.cc index 09ac5aca48f2..2ef8a0528088 100644 --- a/atom/common/platform_util_win.cc +++ b/atom/common/platform_util_win.cc @@ -5,7 +5,9 @@ #include "atom/common/platform_util.h" #include +#include #include +#include #include #include #include @@ -19,6 +21,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/win/registry.h" #include "base/win/scoped_co_mem.h" +#include "base/win/scoped_com_initializer.h" #include "base/win/scoped_comptr.h" #include "base/win/windows_version.h" #include "url/gurl.h" @@ -42,6 +45,159 @@ bool ValidateShellCommandForScheme(const std::string& scheme) { return true; } +// Required COM implementation of IFileOperationProgressSink so we can +// precheck files before deletion to make sure they can be move to the +// Recycle Bin. +class DeleteFileProgressSink : public IFileOperationProgressSink { + public: + DeleteFileProgressSink(); + + private: + ULONG STDMETHODCALLTYPE AddRef(void); + ULONG STDMETHODCALLTYPE Release(void); + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObj); + HRESULT STDMETHODCALLTYPE StartOperations(void); + HRESULT STDMETHODCALLTYPE FinishOperations(HRESULT); + HRESULT STDMETHODCALLTYPE PreRenameItem( + DWORD, IShellItem*, LPCWSTR); + HRESULT STDMETHODCALLTYPE PostRenameItem( + DWORD, IShellItem*, LPCWSTR, HRESULT, IShellItem*); + HRESULT STDMETHODCALLTYPE PreMoveItem( + DWORD, IShellItem*, IShellItem*, LPCWSTR); + HRESULT STDMETHODCALLTYPE PostMoveItem( + DWORD, IShellItem*, IShellItem*, LPCWSTR, HRESULT, IShellItem*); + HRESULT STDMETHODCALLTYPE PreCopyItem( + DWORD, IShellItem*, IShellItem*, LPCWSTR); + HRESULT STDMETHODCALLTYPE PostCopyItem( + DWORD, IShellItem*, IShellItem*, LPCWSTR, HRESULT, IShellItem*); + HRESULT STDMETHODCALLTYPE PreDeleteItem(DWORD, IShellItem*); + HRESULT STDMETHODCALLTYPE PostDeleteItem( + DWORD, IShellItem*, HRESULT, IShellItem*); + HRESULT STDMETHODCALLTYPE PreNewItem( + DWORD, IShellItem*, LPCWSTR); + HRESULT STDMETHODCALLTYPE PostNewItem( + DWORD, IShellItem*, LPCWSTR, LPCWSTR, DWORD, HRESULT, IShellItem*); + HRESULT STDMETHODCALLTYPE UpdateProgress(UINT, UINT); + HRESULT STDMETHODCALLTYPE ResetTimer(void); + HRESULT STDMETHODCALLTYPE PauseTimer(void); + HRESULT STDMETHODCALLTYPE ResumeTimer(void); + + ULONG m_cRef; +}; + +DeleteFileProgressSink::DeleteFileProgressSink() { + m_cRef = 0; +} + +HRESULT DeleteFileProgressSink::PreDeleteItem(DWORD dwFlags, IShellItem*) { + if (!(dwFlags & TSF_DELETE_RECYCLE_IF_POSSIBLE)) { + // TSF_DELETE_RECYCLE_IF_POSSIBLE will not be set for items that cannot be + // recycled. In this case, we abort the delete operation. This bubbles + // up and stops the Delete in IFileOperation. + return E_ABORT; + } + // Returns S_OK if successful, or an error value otherwise. In the case of an + // error value, the delete operation and all subsequent operations pending + // from the call to IFileOperation are canceled. + return S_OK; +} + +HRESULT DeleteFileProgressSink::QueryInterface(REFIID riid, LPVOID* ppvObj) { + // Always set out parameter to NULL, validating it first. + if (!ppvObj) + return E_INVALIDARG; + *ppvObj = nullptr; + if (riid == IID_IUnknown || riid == IID_IFileOperationProgressSink) { + // Increment the reference count and return the pointer. + *ppvObj = reinterpret_cast(this); + AddRef(); + return NOERROR; + } + return E_NOINTERFACE; +} + +ULONG DeleteFileProgressSink::AddRef() { + InterlockedIncrement(&m_cRef); + return m_cRef; +} + +ULONG DeleteFileProgressSink::Release() { + // Decrement the object's internal counter. + ULONG ulRefCount = InterlockedDecrement(&m_cRef); + if (0 == m_cRef) { + delete this; + } + return ulRefCount; +} + +HRESULT DeleteFileProgressSink::StartOperations() { + return S_OK; +} + +HRESULT DeleteFileProgressSink::FinishOperations(HRESULT) { + return S_OK; +} + +HRESULT DeleteFileProgressSink::PreRenameItem(DWORD, IShellItem*, LPCWSTR) { + return S_OK; +} + +HRESULT DeleteFileProgressSink::PostRenameItem( + DWORD, IShellItem*, __RPC__in_string LPCWSTR, HRESULT, IShellItem*) { + return E_NOTIMPL; +} + +HRESULT DeleteFileProgressSink::PreMoveItem( + DWORD, IShellItem*, IShellItem*, LPCWSTR) { + return E_NOTIMPL; +} + +HRESULT DeleteFileProgressSink::PostMoveItem( + DWORD, IShellItem*, IShellItem*, LPCWSTR, HRESULT, IShellItem*) { + return E_NOTIMPL; +} + +HRESULT DeleteFileProgressSink::PreCopyItem( + DWORD, IShellItem*, IShellItem*, LPCWSTR) { + return E_NOTIMPL; +} + +HRESULT DeleteFileProgressSink::PostCopyItem( + DWORD, IShellItem*, IShellItem*, LPCWSTR, HRESULT, IShellItem*) { + return E_NOTIMPL; +} + +HRESULT DeleteFileProgressSink::PostDeleteItem( + DWORD, IShellItem*, HRESULT, IShellItem*) { + return S_OK; +} + +HRESULT DeleteFileProgressSink::PreNewItem( + DWORD dwFlags, IShellItem*, LPCWSTR) { + return E_NOTIMPL; +} + +HRESULT DeleteFileProgressSink::PostNewItem( + DWORD, IShellItem*, LPCWSTR, LPCWSTR, DWORD, HRESULT, IShellItem*) { + return E_NOTIMPL; +} + +HRESULT DeleteFileProgressSink::UpdateProgress(UINT, UINT) { + return S_OK; +} + +HRESULT DeleteFileProgressSink::ResetTimer() { + return S_OK; +} + +HRESULT DeleteFileProgressSink::PauseTimer() { + return S_OK; +} + +HRESULT DeleteFileProgressSink::ResumeTimer() { + return S_OK; +} + } // namespace namespace platform_util { @@ -170,32 +326,40 @@ bool OpenExternal(const GURL& url) { } bool MoveItemToTrash(const base::FilePath& path) { - // SHFILEOPSTRUCT wants the path to be terminated with two NULLs, - // so we have to use wcscpy because wcscpy_s writes non-NULLs - // into the rest of the buffer. - wchar_t double_terminated_path[MAX_PATH + 1] = {0}; -#pragma warning(suppress:4996) // don't complain about wcscpy deprecation - wcscpy(double_terminated_path, path.value().c_str()); - - SHFILEOPSTRUCT file_operation = {0}; - file_operation.wFunc = FO_DELETE; - file_operation.pFrom = double_terminated_path; - file_operation.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_NOCONFIRMATION; - int err = SHFileOperation(&file_operation); - - // Since we're passing flags to the operation telling it to be silent, - // it's possible for the operation to be aborted/cancelled without err - // being set (although MSDN doesn't give any scenarios for how this can - // happen). See MSDN for SHFileOperation and SHFILEOPTSTRUCT. - if (file_operation.fAnyOperationsAborted) + base::win::ScopedCOMInitializer com_initializer; + if (!com_initializer.succeeded()) return false; - // Some versions of Windows return ERROR_FILE_NOT_FOUND (0x2) when deleting - // an empty directory and some return 0x402 when they should be returning - // ERROR_FILE_NOT_FOUND. MSDN says Vista and up won't return 0x402. Windows 7 - // can return DE_INVALIDFILES (0x7C) for nonexistent directories. - return (err == 0 || err == ERROR_FILE_NOT_FOUND || err == 0x402 || - err == 0x7C); + base::win::ScopedComPtr pfo; + if (FAILED(pfo.CreateInstance(CLSID_FileOperation))) + return false; + + // Elevation prompt enabled for UAC protected files. This overrides the + // SILENT, NO_UI and NOERRORUI flags. + if (FAILED(pfo->SetOperationFlags(FOF_NO_UI | + FOF_ALLOWUNDO | + FOF_NOERRORUI | + FOF_SILENT | + FOFX_SHOWELEVATIONPROMPT | + FOFX_RECYCLEONDELETE))) + return false; + + // Create an IShellItem from the supplied source path. + base::win::ScopedComPtr delete_item; + if (FAILED(SHCreateItemFromParsingName(path.value().c_str(), + NULL, + IID_PPV_ARGS(delete_item.Receive())))) + return false; + + base::win::ScopedComPtr delete_sink( + new DeleteFileProgressSink); + if (!delete_sink) + return false; + + // Processes the queued command DeleteItem. This will trigger + // the DeleteFileProgressSink to check for Recycle Bin. + return SUCCEEDED(pfo->DeleteItem(delete_item.get(), delete_sink.get())) && + SUCCEEDED(pfo->PerformOperations()); } void Beep() { From 47649ffd179a67cd9e5462856da8ca94c92915d2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 5 Nov 2015 20:47:27 +0800 Subject: [PATCH 413/738] win: Fix calling showItemInFolder in renderer process --- atom/common/api/lib/shell.coffee | 4 ---- atom/common/platform_util_win.cc | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/atom/common/api/lib/shell.coffee b/atom/common/api/lib/shell.coffee index bd7109e34518..5fb935bacd21 100644 --- a/atom/common/api/lib/shell.coffee +++ b/atom/common/api/lib/shell.coffee @@ -1,5 +1 @@ module.exports = process.atomBinding 'shell' - -if process.platform is 'win32' and process.type is 'renderer' - module.exports.showItemInFolder = (item) -> - require('remote').require('shell').showItemInFolder item diff --git a/atom/common/platform_util_win.cc b/atom/common/platform_util_win.cc index 2ef8a0528088..87f45e5cb2d4 100644 --- a/atom/common/platform_util_win.cc +++ b/atom/common/platform_util_win.cc @@ -203,6 +203,10 @@ HRESULT DeleteFileProgressSink::ResumeTimer() { namespace platform_util { void ShowItemInFolder(const base::FilePath& full_path) { + base::win::ScopedCOMInitializer com_initializer; + if (!com_initializer.succeeded()) + return; + base::FilePath dir = full_path.DirName().AsEndingWithSeparator(); // ParseDisplayName will fail if the directory is "C:", it must be "C:\\". if (dir.empty()) From 2505ebb9a60714bcfcba8545fa6f2051574bc053 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 5 Nov 2015 22:00:40 +0800 Subject: [PATCH 414/738] win: Guard against failure of RtlAddFunctionTable On some machines this call will fail and CHECK will abort the application. --- .../crash_reporter/crash_reporter_win.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/atom/common/crash_reporter/crash_reporter_win.cc b/atom/common/crash_reporter/crash_reporter_win.cc index 78bd196f6cce..240c229ca4b6 100644 --- a/atom/common/crash_reporter/crash_reporter_win.cc +++ b/atom/common/crash_reporter/crash_reporter_win.cc @@ -80,7 +80,7 @@ struct ExceptionHandlerRecord { unsigned char thunk[12]; }; -void RegisterNonABICompliantCodeRange(void* start, size_t size_in_bytes) { +bool RegisterNonABICompliantCodeRange(void* start, size_t size_in_bytes) { ExceptionHandlerRecord* record = reinterpret_cast(start); @@ -117,17 +117,17 @@ void RegisterNonABICompliantCodeRange(void* start, size_t size_in_bytes) { // Protect reserved page against modifications. DWORD old_protect; - CHECK(VirtualProtect( - start, sizeof(ExceptionHandlerRecord), PAGE_EXECUTE_READ, &old_protect)); - CHECK(RtlAddFunctionTable( - &record->runtime_function, 1, reinterpret_cast(start))); + return VirtualProtect(start, sizeof(ExceptionHandlerRecord), + PAGE_EXECUTE_READ, &old_protect) && + RtlAddFunctionTable(&record->runtime_function, 1, + reinterpret_cast(start)); } void UnregisterNonABICompliantCodeRange(void* start) { ExceptionHandlerRecord* record = reinterpret_cast(start); - CHECK(RtlDeleteFunctionTable(&record->runtime_function)); + RtlDeleteFunctionTable(&record->runtime_function); } #endif // _WIN64 @@ -184,6 +184,7 @@ void CrashReporterWin::InitBreakpad(const std::string& product_name, LOG(ERROR) << "Cannot initialize out-of-process crash handler"; #ifdef _WIN64 + bool registered = false; // Hook up V8 to breakpad. { // gin::Debug::SetCodeRangeCreatedCallback only runs the callback when @@ -192,9 +193,10 @@ void CrashReporterWin::InitBreakpad(const std::string& product_name, size_t size = 0; v8::Isolate::GetCurrent()->GetCodeRange(&code_range, &size); if (code_range && size) - RegisterNonABICompliantCodeRange(code_range, size); + registered = RegisterNonABICompliantCodeRange(code_range, size); } - gin::Debug::SetCodeRangeDeletedCallback(UnregisterNonABICompliantCodeRange); + if (registered) + gin::Debug::SetCodeRangeDeletedCallback(UnregisterNonABICompliantCodeRange); #endif } From 818892d474fce15c2aa9819561e5bd9986a80d1c Mon Sep 17 00:00:00 2001 From: Nishanth Shanmugham Date: Thu, 5 Nov 2015 18:45:43 -0600 Subject: [PATCH 415/738] Tray: Add drag-entered and drag-exited events --- atom/browser/api/atom_api_tray.cc | 8 ++++++++ atom/browser/api/atom_api_tray.h | 2 ++ atom/browser/ui/tray_icon.cc | 8 ++++++++ atom/browser/ui/tray_icon.h | 2 ++ atom/browser/ui/tray_icon_cocoa.mm | 5 +++++ atom/browser/ui/tray_icon_observer.h | 2 ++ 6 files changed, 27 insertions(+) diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index 0f5829e19c14..5381c77c3793 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -78,6 +78,14 @@ void Tray::OnDropFiles(const std::vector& files) { Emit("drop-files", files); } +void Tray::OnDragEntered() { + Emit("drag-entered"); +} + +void Tray::OnDragExited() { + Emit("drag-exited"); +} + bool Tray::IsDestroyed() const { return !tray_icon_; } diff --git a/atom/browser/api/atom_api_tray.h b/atom/browser/api/atom_api_tray.h index 9a423f61764f..b26796bccedc 100644 --- a/atom/browser/api/atom_api_tray.h +++ b/atom/browser/api/atom_api_tray.h @@ -49,6 +49,8 @@ class Tray : public mate::TrackableObject, void OnBalloonClicked() override; void OnBalloonClosed() override; void OnDropFiles(const std::vector& files) override; + void OnDragEntered() override; + void OnDragExited() override; // mate::Wrappable: bool IsDestroyed() const override; diff --git a/atom/browser/ui/tray_icon.cc b/atom/browser/ui/tray_icon.cc index d2c6bc1b2597..bc69b6e72759 100644 --- a/atom/browser/ui/tray_icon.cc +++ b/atom/browser/ui/tray_icon.cc @@ -59,4 +59,12 @@ void TrayIcon::NotifyDropFiles(const std::vector& files) { FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDropFiles(files)); } +void TrayIcon::NotifyDragEntered() { + FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDragEntered()); +} + +void TrayIcon::NotifyDragExited() { + FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDragExited()); +} + } // namespace atom diff --git a/atom/browser/ui/tray_icon.h b/atom/browser/ui/tray_icon.h index 539fe04f4bb6..bff3057bf612 100644 --- a/atom/browser/ui/tray_icon.h +++ b/atom/browser/ui/tray_icon.h @@ -62,6 +62,8 @@ class TrayIcon { void NotifyRightClicked(const gfx::Rect& bounds = gfx::Rect(), int modifiers = 0); void NotifyDropFiles(const std::vector& files); + void TrayIcon::NotifyDragEntered(); + void TrayIcon::NotifyDragExited(); protected: TrayIcon(); diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index 34ca4e9a9112..40505a64d8cd 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -254,9 +254,14 @@ const CGFloat kVerticalTitleMargin = 2; } - (NSDragOperation)draggingEntered:(id )sender { + trayIcon_->NotifyDragEntered(); return NSDragOperationCopy; } +- (void)draggingExited:(id )sender { + trayIcon_->NotifyDragExited(); +} + - (BOOL)performDragOperation:(id )sender { NSPasteboard* pboard = [sender draggingPasteboard]; diff --git a/atom/browser/ui/tray_icon_observer.h b/atom/browser/ui/tray_icon_observer.h index fa8090d7d6c5..e9a8bd33f1d3 100644 --- a/atom/browser/ui/tray_icon_observer.h +++ b/atom/browser/ui/tray_icon_observer.h @@ -23,6 +23,8 @@ class TrayIconObserver { virtual void OnBalloonClosed() {} virtual void OnRightClicked(const gfx::Rect& bounds, int modifiers) {} virtual void OnDropFiles(const std::vector& files) {} + virtual void OnDragEntered() {} + virtual void OnDragExited() {} protected: virtual ~TrayIconObserver() {} From ee783a13ad7553855f3789dc743d75ad08a01685 Mon Sep 17 00:00:00 2001 From: Nishanth Shanmugham Date: Thu, 5 Nov 2015 18:49:34 -0600 Subject: [PATCH 416/738] docs: Add Tray drag-entered and drag-exited events --- docs/api/tray.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/api/tray.md b/docs/api/tray.md index 528705acb325..5d187fc5b88c 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -119,6 +119,14 @@ closes it. Emitted when dragged files are dropped in the tray icon. +### Event: 'drag-entered' _OS X_ + +Emitted when a drag operation enters the tray icon. + +### Event: 'drag-exited' _OS X_ + +Emitted when a drag operation exits the tray icon. + ## Methods The `Tray` module has the following methods: From 8a296f82a09ffb59f84562d8e2e5b96c19c626c6 Mon Sep 17 00:00:00 2001 From: Nishanth Shanmugham Date: Thu, 5 Nov 2015 19:02:24 -0600 Subject: [PATCH 417/738] Tray: Remove extra qualification in header --- atom/browser/ui/tray_icon.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/ui/tray_icon.h b/atom/browser/ui/tray_icon.h index bff3057bf612..b63d3c48c262 100644 --- a/atom/browser/ui/tray_icon.h +++ b/atom/browser/ui/tray_icon.h @@ -62,8 +62,8 @@ class TrayIcon { void NotifyRightClicked(const gfx::Rect& bounds = gfx::Rect(), int modifiers = 0); void NotifyDropFiles(const std::vector& files); - void TrayIcon::NotifyDragEntered(); - void TrayIcon::NotifyDragExited(); + void NotifyDragEntered(); + void NotifyDragExited(); protected: TrayIcon(); From 0e950e6d26789bbf1725e1bb0872eae0b2cc5073 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 6 Nov 2015 10:52:55 +0900 Subject: [PATCH 418/738] Update as upstream --- docs-translations/ko-KR/tutorial/devtools-extension.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs-translations/ko-KR/tutorial/devtools-extension.md b/docs-translations/ko-KR/tutorial/devtools-extension.md index 966431dd72b8..659c769dde34 100644 --- a/docs-translations/ko-KR/tutorial/devtools-extension.md +++ b/docs-translations/ko-KR/tutorial/devtools-extension.md @@ -5,7 +5,9 @@ 개발자 콘솔 확장 기능은 간단하게 사용할 확장 기능 플러그인의 소스 코드를 다운로드한 후 `BrowserWindow.addDevToolsExtension` API를 이용하여 어플리케이션 내에 로드할 수 있습니다. 한가지 주의할 점은 확장 기능 사용시 창이 생성될 때 마다 일일이 해당 API를 호출할 필요는 없습니다. -예시로 [React DevTools Extension](https://github.com/facebook/react-devtools)을 사용합니다. +** 주의: 현재 React DevTools은 작동하지 않습니다. https://github.com/atom/electron/issues/915 이슈를 참고하세요! ** + +다음 예제는 [React DevTools Extension](https://github.com/facebook/react-devtools)을 사용합니다. 먼저 소스코드를 다운로드 받습니다: @@ -15,8 +17,7 @@ $ git clone --recursive https://github.com/facebook/react-devtools.git ``` [`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md) -가이드를 통해 확장 기능을 개발하는 방법을 알아볼 수 있습니다. - +를 통해 확장 기능을 개발하는 방법을 알아볼 수 있습니다. 그리고 개발자 콘솔에서 다음 코드를 입력하면 확장 기능을 로드할 수 있습니다: From 863199348f8a07cdff4dfa23fea0598ddb3dcf2b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 6 Nov 2015 18:27:13 +0800 Subject: [PATCH 419/738] Make process.exit() quit gracefully Instead of abrupting the whole program immediately, we should close all windows and release all native resources gracefully on exit. This avoids possible crashes. Fix #3350. --- atom/browser/api/atom_api_app.cc | 1 + atom/browser/api/lib/app.coffee | 1 - atom/browser/atom_browser_main_parts.cc | 14 ++++++++++++++ atom/browser/atom_browser_main_parts.h | 7 +++++++ atom/browser/browser.cc | 22 ++++++++++++++++++++++ atom/browser/browser.h | 3 +++ atom/browser/lib/init.coffee | 3 +++ docs/api/app.md | 9 +++++++++ 8 files changed, 59 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 04ed06e0138f..1c5c2c04f145 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -339,6 +339,7 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( auto browser = base::Unretained(Browser::Get()); return mate::ObjectTemplateBuilder(isolate) .SetMethod("quit", base::Bind(&Browser::Quit, browser)) + .SetMethod("exit", base::Bind(&Browser::Exit, browser)) .SetMethod("focus", base::Bind(&Browser::Focus, browser)) .SetMethod("getVersion", base::Bind(&Browser::GetVersion, browser)) .SetMethod("setVersion", base::Bind(&Browser::SetVersion, browser)) diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index ba68076177ae..4df7aef10bdf 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -50,7 +50,6 @@ app.getAppPath = -> # Be compatible with old API. app.once 'ready', -> @emit 'finish-launching' app.terminate = app.quit -app.exit = process.exit app.getHomeDir = -> @getPath 'home' app.getDataPath = -> @getPath 'userData' app.setDataPath = (path) -> @setPath 'userData', path diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 041c9bfc8fbe..0a8c16ca223f 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -30,6 +30,7 @@ AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL; AtomBrowserMainParts::AtomBrowserMainParts() : fake_browser_process_(new BrowserProcess), + exit_code_(nullptr), browser_(new Browser), node_bindings_(NodeBindings::Create(true)), atom_bindings_(new AtomBindings), @@ -47,6 +48,14 @@ AtomBrowserMainParts* AtomBrowserMainParts::Get() { return self_; } +bool AtomBrowserMainParts::SetExitCode(int code) { + if (!exit_code_) + return false; + + *exit_code_ = code; + return true; +} + void AtomBrowserMainParts::RegisterDestructionCallback( const base::Closure& callback) { destruction_callbacks_.push_back(callback); @@ -118,6 +127,11 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() { #endif } +bool AtomBrowserMainParts::MainMessageLoopRun(int* result_code) { + exit_code_ = result_code; + return brightray::BrowserMainParts::MainMessageLoopRun(result_code); +} + void AtomBrowserMainParts::PostMainMessageLoopStart() { brightray::BrowserMainParts::PostMainMessageLoopStart(); #if defined(OS_POSIX) diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index 360b1cba1169..bb4b204669fd 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -31,6 +31,9 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { static AtomBrowserMainParts* Get(); + // Sets the exit code, will fail if the the message loop is not ready. + bool SetExitCode(int code); + // Register a callback that should be destroyed before JavaScript environment // gets destroyed. void RegisterDestructionCallback(const base::Closure& callback); @@ -42,6 +45,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { void PreEarlyInitialization() override; void PostEarlyInitialization() override; void PreMainMessageLoopRun() override; + bool MainMessageLoopRun(int* result_code) override; void PostMainMessageLoopStart() override; void PostMainMessageLoopRun() override; #if defined(OS_MACOSX) @@ -66,6 +70,9 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { // with a task runner that will post all work to main loop. scoped_refptr bridge_task_runner_; + // Pointer to exit code. + int* exit_code_; + scoped_ptr browser_; scoped_ptr js_env_; scoped_ptr node_bindings_; diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index e80cb4e60e20..57741786520d 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -7,6 +7,7 @@ #include #include "atom/browser/atom_browser_main_parts.h" +#include "atom/browser/native_window.h" #include "atom/browser/window_list.h" #include "base/message_loop/message_loop.h" #include "content/public/browser/client_certificate_delegate.h" @@ -45,6 +46,27 @@ void Browser::Quit() { window_list->CloseAllWindows(); } +void Browser::Exit(int code) { + if (!AtomBrowserMainParts::Get()->SetExitCode(code)) { + // Message loop is not ready, quit directly. + exit(code); + } else { + // Prepare to quit when all windows have been closed.. + is_quiting_ = true; + + // Must destroy windows before quitting, otherwise bad things can happen. + atom::WindowList* window_list = atom::WindowList::GetInstance(); + if (window_list->size() == 0) { + NotifyAndShutdown(); + } else { + // Unlike Quit(), we do not ask to close window, but destroy the window + // without asking. + for (NativeWindow* window : *window_list) + window->CloseContents(nullptr); // e.g. Destroy() + } + } +} + void Browser::Shutdown() { if (is_shutdown_) return; diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 447a526de6df..e20db080b67a 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -42,6 +42,9 @@ class Browser : public WindowListObserver { // Try to close all windows and quit the application. void Quit(); + // Exit the application immediately and set exit code. + void Exit(int code); + // Cleanup everything and shutdown the application gracefully. void Shutdown(); diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index 9f92d700c73a..80d2da31b705 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -53,6 +53,9 @@ app = require 'app' app.on 'quit', -> process.emit 'exit' +# Map process.exit to app.exit, which quits gracefully. +process.exit = app.exit + # Load the RPC server. require './rpc-server' diff --git a/docs/api/app.md b/docs/api/app.md index 00aade7c54ab..fdb9f9980592 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -208,6 +208,15 @@ This method guarantees that all `beforeunload` and `unload` event handlers are correctly executed. It is possible that a window cancels the quitting by returning `false` in the `beforeunload` event handler. +### `app.exit(exitCode)` + +* `exitCode` Integer + +Exits immediately with `exitCode`. + +All windows will be closed immediately without asking user and the `before-quit` +and `will-quit` events will not be emitted. + ### `app.getAppPath()` Returns the current application directory. From acf4372cf7d8a07a9c55763ac2bb726e962aa251 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 6 Nov 2015 18:51:34 +0800 Subject: [PATCH 420/738] win: Add ELECTRON_DEFAULT_ERROR_MODE env It is useful to help debugging crashes without opening debugger. --- atom/common/node_bindings.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index 10da202da70d..dbd0bd8d96ee 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -14,6 +14,7 @@ #include "atom/common/node_includes.h" #include "base/command_line.h" #include "base/base_paths.h" +#include "base/environment.h" #include "base/files/file_path.h" #include "base/message_loop/message_loop.h" #include "base/path_service.h" @@ -141,6 +142,14 @@ void NodeBindings::Initialize() { // Init node. // (we assume node::Init would not modify the parameters under embedded mode). node::Init(nullptr, nullptr, nullptr, nullptr); + +#if defined(OS_WIN) + // uv_init overrides error mode to suppress the default crash dialog, bring + // it back if user wants to show it. + scoped_ptr env(base::Environment::Create()); + if (env->HasVar("ELECTRON_DEFAULT_ERROR_MODE")) + SetErrorMode(0); +#endif } node::Environment* NodeBindings::CreateEnvironment( From d70706f8765033138f4e19eef8c6ef723b217bc6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 6 Nov 2015 20:23:41 +0800 Subject: [PATCH 421/738] Make sure handles of callbacks are releases on exit Some callbacks are stored in native resources that not managed by JavaScript, so when those resources are destroyed the JavaScript context may already be destroyed, and releasing callbacks then would result in crash. --- .../common/native_mate_converters/callback.cc | 29 +++++++++++ atom/common/native_mate_converters/callback.h | 48 ++++++++++++++----- 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/atom/common/native_mate_converters/callback.cc b/atom/common/native_mate_converters/callback.cc index 3bcb748689fb..87faa3df3cd5 100644 --- a/atom/common/native_mate_converters/callback.cc +++ b/atom/common/native_mate_converters/callback.cc @@ -4,6 +4,8 @@ #include "atom/common/native_mate_converters/callback.h" +#include "atom/browser/atom_browser_main_parts.h" + namespace mate { namespace internal { @@ -54,6 +56,33 @@ v8::Local BindFunctionWith(v8::Isolate* isolate, } // namespace +SafeV8Function::SafeV8Function(v8::Isolate* isolate, v8::Local value) + : v8_function_(new RefCountedPersistent(isolate, value)), + weak_factory_(this) { + Init(); +} + +SafeV8Function::SafeV8Function(const SafeV8Function& other) + : v8_function_(other.v8_function_), + weak_factory_(this) { + Init(); +} + +v8::Local SafeV8Function::NewHandle() const { + return v8_function_->NewHandle(); +} + +void SafeV8Function::Init() { + if (Locker::IsBrowserProcess() && atom::AtomBrowserMainParts::Get()) + atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback( + base::Bind(&SafeV8Function::FreeHandle, weak_factory_.GetWeakPtr())); +} + +void SafeV8Function::FreeHandle() { + Locker locker(v8_function_->isolate()); + v8_function_ = nullptr; +} + v8::Local CreateFunctionFromTranslater( v8::Isolate* isolate, const Translater& translater) { // The FunctionTemplate is cached. diff --git a/atom/common/native_mate_converters/callback.h b/atom/common/native_mate_converters/callback.h index 228fc0d3bb1d..5dd9d3cec9b1 100644 --- a/atom/common/native_mate_converters/callback.h +++ b/atom/common/native_mate_converters/callback.h @@ -10,6 +10,7 @@ #include "atom/common/api/locker.h" #include "base/bind.h" #include "base/callback.h" +#include "base/memory/weak_ptr.h" #include "native_mate/function_template.h" #include "native_mate/scoped_persistent.h" #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" @@ -18,7 +19,24 @@ namespace mate { namespace internal { -typedef scoped_refptr > SafeV8Function; +// Manages the V8 function with RAII, and automatically cleans the handle when +// JavaScript context is destroyed, even when the class is not destroyed. +class SafeV8Function { + public: + SafeV8Function(v8::Isolate* isolate, v8::Local value); + SafeV8Function(const SafeV8Function& other); + + bool is_alive() const { return v8_function_.get(); } + + v8::Local NewHandle() const; + + private: + void Init(); + void FreeHandle(); + + scoped_refptr> v8_function_; + base::WeakPtrFactory weak_factory_; +}; // Helper to invoke a V8 function with C++ parameters. template @@ -26,14 +44,17 @@ struct V8FunctionInvoker {}; template struct V8FunctionInvoker(ArgTypes...)> { - static v8::Local Go(v8::Isolate* isolate, SafeV8Function function, + static v8::Local Go(v8::Isolate* isolate, + const SafeV8Function& function, ArgTypes... raw) { Locker locker(isolate); v8::EscapableHandleScope handle_scope(isolate); + if (!function.is_alive()) + return v8::Null(isolate); scoped_ptr script_scope( Locker::IsBrowserProcess() ? nullptr : new blink::WebScopedRunV8Script(isolate)); - v8::Local holder = function->NewHandle(); + v8::Local holder = function.NewHandle(); v8::Local context = holder->CreationContext(); v8::Context::Scope context_scope(context); std::vector> args = { ConvertToV8(isolate, raw)... }; @@ -44,14 +65,17 @@ struct V8FunctionInvoker(ArgTypes...)> { template struct V8FunctionInvoker { - static void Go(v8::Isolate* isolate, SafeV8Function function, + static void Go(v8::Isolate* isolate, + const SafeV8Function& function, ArgTypes... raw) { Locker locker(isolate); v8::HandleScope handle_scope(isolate); + if (!function.is_alive()) + return; scoped_ptr script_scope( Locker::IsBrowserProcess() ? nullptr : new blink::WebScopedRunV8Script(isolate)); - v8::Local holder = function->NewHandle(); + v8::Local holder = function.NewHandle(); v8::Local context = holder->CreationContext(); v8::Context::Scope context_scope(context); std::vector> args = { ConvertToV8(isolate, raw)... }; @@ -61,17 +85,20 @@ struct V8FunctionInvoker { template struct V8FunctionInvoker { - static ReturnType Go(v8::Isolate* isolate, SafeV8Function function, + static ReturnType Go(v8::Isolate* isolate, + const SafeV8Function& function, ArgTypes... raw) { Locker locker(isolate); v8::HandleScope handle_scope(isolate); + ReturnType ret = ReturnType(); + if (!function.is_alive()) + return ret; scoped_ptr script_scope( Locker::IsBrowserProcess() ? nullptr : new blink::WebScopedRunV8Script(isolate)); - v8::Local holder = function->NewHandle(); + v8::Local holder = function.NewHandle(); v8::Local context = holder->CreationContext(); v8::Context::Scope context_scope(context); - ReturnType ret = ReturnType(); std::vector> args = { ConvertToV8(isolate, raw)... }; v8::Local result; auto maybe_result = @@ -119,9 +146,8 @@ struct Converter> { if (!val->IsFunction()) return false; - internal::SafeV8Function function( - new RefCountedPersistent(isolate, val)); - *out = base::Bind(&internal::V8FunctionInvoker::Go, isolate, function); + *out = base::Bind(&internal::V8FunctionInvoker::Go, + isolate, internal::SafeV8Function(isolate, val)); return true; } }; From c4ee8c1b1f8d335931f6a8fdce6a37ecab2e3d07 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 6 Nov 2015 21:00:38 +0800 Subject: [PATCH 422/738] spec: Fix refreshing on Windows --- spec/api-crash-reporter-spec.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/api-crash-reporter-spec.coffee b/spec/api-crash-reporter-spec.coffee index 9aedb0c8ea1e..618adaaf9dec 100644 --- a/spec/api-crash-reporter-spec.coffee +++ b/spec/api-crash-reporter-spec.coffee @@ -53,5 +53,6 @@ describe 'crash-reporter module', -> protocol: 'file' pathname: path.join fixtures, 'api', 'crash.html' search: "?port=#{port}" - crashReporter.start {'submitUrl': 'http://127.0.0.1:' + port} + if process.platform is 'darwin' + crashReporter.start {'submitUrl': 'http://127.0.0.1:' + port} w.loadUrl url From 312a79165be96dcde56e6f7d270f0ff7d4c65a76 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 6 Nov 2015 21:37:37 +0800 Subject: [PATCH 423/738] Bump v0.34.3 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/atom.gyp b/atom.gyp index 7b88df4d8013..a57b7dbf58f8 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.34.2', + 'version%': '0.34.3', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index a703c01a766c..a7df1a582e08 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.34.2 + 0.34.3 CFBundleShortVersionString - 0.34.2 + 0.34.3 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 8401e1d7d09e..d3ebfaa8e0d9 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,34,2,0 - PRODUCTVERSION 0,34,2,0 + FILEVERSION 0,34,3,0 + PRODUCTVERSION 0,34,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.34.2" + VALUE "FileVersion", "0.34.3" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.34.2" + VALUE "ProductVersion", "0.34.3" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 5b1dc4ab44a6..b879da3066d4 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 34 -#define ATOM_PATCH_VERSION 2 +#define ATOM_PATCH_VERSION 3 #define ATOM_VERSION_IS_RELEASE 1 From 3465095c493f765bad2843c57c9af129222c94fa Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 7 Nov 2015 12:12:17 +0800 Subject: [PATCH 424/738] Update brightray for #3357 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 49a86c123f4c..98b3eb04d85a 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 49a86c123f4cc43f4dca886ded612104a8a1fec6 +Subproject commit 98b3eb04d85a8a70b8d9f29477437061c2e77a83 From 09169ed4026aa674d49e1be5898a3895a4b6b089 Mon Sep 17 00:00:00 2001 From: tejaspathak Date: Sun, 8 Nov 2015 16:18:22 +0900 Subject: [PATCH 425/738] Add option to build local libchromiumcontent - Currently libchromiumcontent is downloaded by default. - Now developer can choose to provide local libchromiumcontent src, shared and static path --- script/bootstrap.py | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/script/bootstrap.py b/script/bootstrap.py index d5ad41a61c59..81da2810eccb 100755 --- a/script/bootstrap.py +++ b/script/bootstrap.py @@ -26,6 +26,23 @@ def main(): os.chdir(SOURCE_ROOT) args = parse_args() + if (args.libcc_source_path != None and + args.libcc_shared_library_path != None and + args.libcc_static_library_path != None): + if (not os.path.isdir(args.libcc_source_path)): + print "Error: Directory does not exist:", args.libcc_source_path + sys.exit(0) + elif (not os.path.isdir(args.libcc_shared_library_path)): + print "Error: Directory does not exist:", args.libcc_shared_library_path + sys.exit(0) + elif (not os.path.isdir(args.libcc_static_library_path)): + print "Error: Directory does not exist:", args.libcc_static_library_path + sys.exit(0) + elif (args.libcc_source_path != None or + args.libcc_shared_library_path != None or + args.libcc_static_library_path != None): + print "Error: All options of libchromiumcontent are required OR let electron choose it" + sys.exit(0) if not args.yes and PLATFORM != 'win32': check_root() if args.verbose: @@ -39,7 +56,10 @@ def main(): update_submodules() setup_python_libs() update_node_modules('.') - bootstrap_brightray(args.dev, args.url, args.target_arch) + bootstrap_brightray(args.dev, args.url, args.target_arch, + args.libcc_source_path, + args.libcc_shared_library_path, + args.libcc_static_library_path) if args.target_arch in ['arm', 'ia32'] and PLATFORM == 'linux': download_sysroot(args.target_arch) @@ -69,6 +89,12 @@ def parse_args(): 'prompts.') parser.add_argument('--target_arch', default=get_target_arch(), help='Manually specify the arch to build for') + parser.add_argument('--libcc_source_path', required=False, + help='The source path of libchromiumcontent. NOTE: All options of libchromiumcontent are required OR let electron choose it') + parser.add_argument('--libcc_shared_library_path', required=False, + help='The shared library path of libchromiumcontent. NOTE: All options of libchromiumcontent are required OR let electron choose it') + parser.add_argument('--libcc_static_library_path', required=False, + help='The static library path of libchromiumcontent. NOTE: All options of libchromiumcontent are required OR let electron choose it') return parser.parse_args() @@ -91,15 +117,23 @@ def setup_python_libs(): execute_stdout([sys.executable, 'setup.py', 'build']) -def bootstrap_brightray(is_dev, url, target_arch): +def bootstrap_brightray(is_dev, url, target_arch, libcc_source_path, + libcc_shared_library_path, + libcc_static_library_path): bootstrap = os.path.join(VENDOR_DIR, 'brightray', 'script', 'bootstrap') args = [ '--commit', LIBCHROMIUMCONTENT_COMMIT, '--target_arch', target_arch, - url, + url ] if is_dev: args = ['--dev'] + args + if (libcc_source_path != None and + libcc_shared_library_path != None and + libcc_static_library_path != None): + args = args + ['--libcc_source_path', libcc_source_path, + '--libcc_shared_library_path', libcc_shared_library_path, + '--libcc_static_library_path', libcc_static_library_path] execute_stdout([sys.executable, bootstrap] + args) From ae2b004db747aec9edcd8a911991428867eee059 Mon Sep 17 00:00:00 2001 From: tejaspathak Date: Sun, 8 Nov 2015 17:41:16 +0900 Subject: [PATCH 426/738] Fix pylint errors --- script/bootstrap.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/script/bootstrap.py b/script/bootstrap.py index 81da2810eccb..c9a3b32ed49c 100755 --- a/script/bootstrap.py +++ b/script/bootstrap.py @@ -41,7 +41,8 @@ def main(): elif (args.libcc_source_path != None or args.libcc_shared_library_path != None or args.libcc_static_library_path != None): - print "Error: All options of libchromiumcontent are required OR let electron choose it" + print "Error: All options of libchromiumcontent are required OR let " \ + "electron choose it" sys.exit(0) if not args.yes and PLATFORM != 'win32': check_root() @@ -90,11 +91,17 @@ def parse_args(): parser.add_argument('--target_arch', default=get_target_arch(), help='Manually specify the arch to build for') parser.add_argument('--libcc_source_path', required=False, - help='The source path of libchromiumcontent. NOTE: All options of libchromiumcontent are required OR let electron choose it') + help='The source path of libchromiumcontent. ' \ + 'NOTE: All options of libchromiumcontent are ' + 'required OR let electron choose it') parser.add_argument('--libcc_shared_library_path', required=False, - help='The shared library path of libchromiumcontent. NOTE: All options of libchromiumcontent are required OR let electron choose it') + help='The shared library path of libchromiumcontent. ' \ + 'NOTE: All options of libchromiumcontent are ' \ + 'required OR let electron choose it') parser.add_argument('--libcc_static_library_path', required=False, - help='The static library path of libchromiumcontent. NOTE: All options of libchromiumcontent are required OR let electron choose it') + help='The static library path of libchromiumcontent. ' \ + 'NOTE: All options of libchromiumcontent are ' \ + 'required OR let electron choose it') return parser.parse_args() From 429723c8a9a913907295759063de4bacb62331ef Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Mon, 9 Nov 2015 07:48:40 +0900 Subject: [PATCH 427/738] Update as upstream --- docs-translations/ko-KR/api/app.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index 26235fbe444b..f5e8e8d96b96 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -206,6 +206,14 @@ GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입 이 함수는 모든 `beforeunload`와 `unload` 이벤트 핸들러가 제대로 실행됨을 보장합니다. `beforeunload` 이벤트 핸들러에서 `false`를 반환했을 때 윈도우창 종료가 취소 될 수 있습니다. +### `app.exit(exitCode)` + +* `exitCode` Integer + +`exitCode`와 함께 어플리케이션을 즉시 종료합니다. + +모든 윈도우창은 사용자의 동의 여부에 상관없이 즉시 종료되며 `before-quit` 이벤트와 `will-quit` 이벤트가 발생하지 않습니다. + ### `app.getAppPath()` 현재 어플리케이션의 디렉터리를 반환합니다. From 5e3b8d51e490bcd3468fac71779e4ac3be484c24 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 9 Nov 2015 11:42:37 +0800 Subject: [PATCH 428/738] docs: Fix typo --- docs/tutorial/mac-app-store-submission-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md index 113185918803..4dc6f900a167 100644 --- a/docs/tutorial/mac-app-store-submission-guide.md +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -77,10 +77,10 @@ codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper EH.app/" codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper NP.app/" codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" -productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$APP_PATH" +productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH" ``` -If you are new to app sandboxing under OS X, you should also read through +If you are new to app sandboxing under OS X, you should also read through Apple's [Enabling App Sandbox][enable-app-sandbox] to have a basic idea, then add keys for the permissions needed by your app to the entitlements files. From 13b917dd953dc7ac7ce6b9751c6c0ac68bfa88eb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 9 Nov 2015 16:38:51 +0800 Subject: [PATCH 429/738] Update brightray for atom/electron#3310 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 98b3eb04d85a..3773af58a204 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 98b3eb04d85a8a70b8d9f29477437061c2e77a83 +Subproject commit 3773af58a204c5899cc811d58f831466549277bf From a23ffd7a1bb815a1120c37e162705734bb4f827b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 9 Nov 2015 18:24:32 +0800 Subject: [PATCH 430/738] Rely on "download" script for argument verification --- script/bootstrap.py | 41 +++++++++-------------------------------- vendor/brightray | 2 +- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/script/bootstrap.py b/script/bootstrap.py index c9a3b32ed49c..ef48c1f8023f 100755 --- a/script/bootstrap.py +++ b/script/bootstrap.py @@ -26,24 +26,6 @@ def main(): os.chdir(SOURCE_ROOT) args = parse_args() - if (args.libcc_source_path != None and - args.libcc_shared_library_path != None and - args.libcc_static_library_path != None): - if (not os.path.isdir(args.libcc_source_path)): - print "Error: Directory does not exist:", args.libcc_source_path - sys.exit(0) - elif (not os.path.isdir(args.libcc_shared_library_path)): - print "Error: Directory does not exist:", args.libcc_shared_library_path - sys.exit(0) - elif (not os.path.isdir(args.libcc_static_library_path)): - print "Error: Directory does not exist:", args.libcc_static_library_path - sys.exit(0) - elif (args.libcc_source_path != None or - args.libcc_shared_library_path != None or - args.libcc_static_library_path != None): - print "Error: All options of libchromiumcontent are required OR let " \ - "electron choose it" - sys.exit(0) if not args.yes and PLATFORM != 'win32': check_root() if args.verbose: @@ -58,8 +40,7 @@ def main(): setup_python_libs() update_node_modules('.') bootstrap_brightray(args.dev, args.url, args.target_arch, - args.libcc_source_path, - args.libcc_shared_library_path, + args.libcc_source_path, args.libcc_shared_library_path, args.libcc_static_library_path) if args.target_arch in ['arm', 'ia32'] and PLATFORM == 'linux': @@ -91,17 +72,13 @@ def parse_args(): parser.add_argument('--target_arch', default=get_target_arch(), help='Manually specify the arch to build for') parser.add_argument('--libcc_source_path', required=False, - help='The source path of libchromiumcontent. ' \ - 'NOTE: All options of libchromiumcontent are ' - 'required OR let electron choose it') + help='The source path of libchromiumcontent. ' \ + 'NOTE: All options of libchromiumcontent are ' \ + 'required OR let electron choose it') parser.add_argument('--libcc_shared_library_path', required=False, - help='The shared library path of libchromiumcontent. ' \ - 'NOTE: All options of libchromiumcontent are ' \ - 'required OR let electron choose it') + help='The shared library path of libchromiumcontent.') parser.add_argument('--libcc_static_library_path', required=False, - help='The static library path of libchromiumcontent. ' \ - 'NOTE: All options of libchromiumcontent are ' \ - 'required OR let electron choose it') + help='The static library path of libchromiumcontent.') return parser.parse_args() @@ -138,9 +115,9 @@ def bootstrap_brightray(is_dev, url, target_arch, libcc_source_path, if (libcc_source_path != None and libcc_shared_library_path != None and libcc_static_library_path != None): - args = args + ['--libcc_source_path', libcc_source_path, - '--libcc_shared_library_path', libcc_shared_library_path, - '--libcc_static_library_path', libcc_static_library_path] + args += ['--libcc_source_path', libcc_source_path, + '--libcc_shared_library_path', libcc_shared_library_path, + '--libcc_static_library_path', libcc_static_library_path] execute_stdout([sys.executable, bootstrap] + args) diff --git a/vendor/brightray b/vendor/brightray index 3773af58a204..80543fe2b0fc 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 3773af58a204c5899cc811d58f831466549277bf +Subproject commit 80543fe2b0fc04b5096b1ba7ebb9553431d8dfc0 From 89ff62b1b566c58c0854e4d254475c434da87998 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 9 Nov 2015 18:09:22 +0800 Subject: [PATCH 431/738] Add "deprecate" module --- atom/common/api/lib/deprecate.coffee | 62 ++++++++++++++++++++++++++++ filenames.gypi | 1 + 2 files changed, 63 insertions(+) create mode 100644 atom/common/api/lib/deprecate.coffee diff --git a/atom/common/api/lib/deprecate.coffee b/atom/common/api/lib/deprecate.coffee new file mode 100644 index 000000000000..070a9feb6aab --- /dev/null +++ b/atom/common/api/lib/deprecate.coffee @@ -0,0 +1,62 @@ +# Deprecate a method. +deprecate = (oldName, newName, fn) -> + warned = false + -> + unless warned or process.noDeprecation + warned = true + deprecate.warn oldName, newName + fn.apply this, arguments + +# The method is renamed. +deprecate.rename = (object, oldName, newName) -> + warned = false + newMethod = -> + unless warned or process.noDeprecation + warned = true + deprecate.warn oldName, newName + this[newName].apply this, arguments + if typeof object is 'function' + object.prototype[oldName] = newMethod + else + object[oldName] = newMethod + +# Forward the method to member. +deprecate.member = (object, method, member) -> + warned = false + object.prototype[method] = -> + unless warned or process.noDeprecation + warned = true + deprecate.warn method, "#{member}.#{method}" + this[member][method].apply this[member], arguments + +# Deprecate a property. +deprecate.property = (object, property, method) -> + Object.defineProperty object, property, + get: -> + warned = false + unless warned or process.noDeprecation + warned = true + deprecate.warn "#{property} property", "#{method} method" + this[method]() + +# Deprecate an event. +deprecate.event = (emitter, oldName, newName, fn) -> + warned = false + emitter.on newName, -> + if @listenerCount(oldName) > 0 # there is listeners for old API. + unless warned or process.noDeprecation + warned = true + deprecate.warn "'#{oldName}' event", "'#{newName}' event" + fn.apply this, arguments + +# Print deprecate warning. +deprecate.warn = (oldName, newName) -> + message = "#{oldName} is deprecated. Use #{newName} instead." + if process.throwDeprecation + throw new Error(message) + else if process.traceDeprecation + console.trace message + else + console.warn "(electron) #{message}" + +module.exports = deprecate diff --git a/filenames.gypi b/filenames.gypi index 0e70347309c0..b39362bd1cd4 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -37,6 +37,7 @@ 'atom/common/api/lib/callbacks-registry.coffee', 'atom/common/api/lib/clipboard.coffee', 'atom/common/api/lib/crash-reporter.coffee', + 'atom/common/api/lib/deprecate.coffee', 'atom/common/api/lib/native-image.coffee', 'atom/common/api/lib/shell.coffee', 'atom/common/lib/init.coffee', From f0bd28ca8d3e362abcc600447784afb0ed0c22b1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 9 Nov 2015 19:07:55 +0800 Subject: [PATCH 432/738] Do not turn off deprecation notice by default It is v4 now, people should be punished if they are still using deprecated Node.js APIs. --- atom/common/api/atom_bindings.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/atom/common/api/atom_bindings.cc b/atom/common/api/atom_bindings.cc index 60052a7216d0..a000f6fc743a 100644 --- a/atom/common/api/atom_bindings.cc +++ b/atom/common/api/atom_bindings.cc @@ -69,9 +69,6 @@ void AtomBindings::BindTo(v8::Isolate* isolate, dict.SetMethod("activateUvLoop", base::Bind(&AtomBindings::ActivateUVLoop, base::Unretained(this))); - // Do not warn about deprecated APIs. - dict.Set("noDeprecation", true); - #if defined(MAS_BUILD) dict.Set("mas", true); #endif From 91c4ed26fc9e0ed2792abd2bf594dd0d2e4bb336 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 9 Nov 2015 21:18:57 +0800 Subject: [PATCH 433/738] Print warnings for deprecated APIs --- atom/browser/api/lib/app.coffee | 50 +++++++++++++--------- atom/browser/api/lib/atom-delegate.coffee | 6 --- atom/browser/api/lib/browser-window.coffee | 41 +++++++++--------- atom/browser/lib/chrome-extension.coffee | 2 +- atom/renderer/api/lib/ipc.coffee | 6 ++- filenames.gypi | 1 - 6 files changed, 55 insertions(+), 51 deletions(-) delete mode 100644 atom/browser/api/lib/atom-delegate.coffee diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 4df7aef10bdf..b5025a3a4fee 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -1,3 +1,4 @@ +deprecate = require 'deprecate' EventEmitter = require('events').EventEmitter bindings = process.atomBinding 'app' @@ -7,19 +8,6 @@ downloadItemBindings = process.atomBinding 'download_item' app = bindings.app app.__proto__ = EventEmitter.prototype -wrapSession = (session) -> - # session is an Event Emitter. - session.__proto__ = EventEmitter.prototype - -wrapDownloadItem = (downloadItem) -> - # downloadItem is an Event Emitter. - downloadItem.__proto__ = EventEmitter.prototype - # Be compatible with old APIs. - downloadItem.url = downloadItem.getUrl() - downloadItem.filename = downloadItem.getFilename() - downloadItem.mimeType = downloadItem.getMimeType() - downloadItem.hasUserGesture = downloadItem.hasUserGesture() - app.setApplicationMenu = (menu) -> require('menu').setApplicationMenu menu @@ -47,17 +35,37 @@ app.setAppPath = (path) -> app.getAppPath = -> appPath -# Be compatible with old API. -app.once 'ready', -> @emit 'finish-launching' -app.terminate = app.quit -app.getHomeDir = -> @getPath 'home' -app.getDataPath = -> @getPath 'userData' -app.setDataPath = (path) -> @setPath 'userData', path -app.resolveProxy = -> @defaultSession.resolveProxy.apply @defaultSession, arguments -app.on 'activate', (event, hasVisibleWindows) -> @emit 'activate-with-no-open-windows' if not hasVisibleWindows +# Helpers. +app.resolveProxy = (url, callback) -> @defaultSession.resolveProxy url, callback + +# Deprecated. +app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', -> + @getPath 'home' +app.getDataPath = deprecate 'app.getDataPath', 'app.getPath', -> + @getPath 'userData' +app.setDataPath = deprecate 'app.setDataPath', 'app.setPath', (path) -> + @setPath 'userData', path +deprecate.rename app, 'terminate', 'quit' +deprecate.event app, 'finish-launching', 'ready', -> + setImmediate => # give default app a chance to setup default menu. + @emit 'finish-launching' +deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) -> + @emit 'activate-with-no-open-windows' if not hasVisibleWindows # Wrappers for native classes. +wrapSession = (session) -> + # session is an EventEmitter. + session.__proto__ = EventEmitter.prototype sessionBindings._setWrapSession wrapSession + +wrapDownloadItem = (downloadItem) -> + # downloadItem is an EventEmitter. + downloadItem.__proto__ = EventEmitter.prototype + # Deprecated. + deprecate.property downloadItem, 'url', 'getUrl' + deprecate.property downloadItem, 'filename', 'getFilename' + deprecate.property downloadItem, 'mimeType', 'getMimeType' + deprecate.property downloadItem, 'hasUserGesture', 'hasUserGesture' downloadItemBindings._setWrapDownloadItem wrapDownloadItem # Only one App object pemitted. diff --git a/atom/browser/api/lib/atom-delegate.coffee b/atom/browser/api/lib/atom-delegate.coffee deleted file mode 100644 index 2e1e6334470b..000000000000 --- a/atom/browser/api/lib/atom-delegate.coffee +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = - browserMainParts: - preMainMessageLoopRun: -> - -setImmediate -> - module.exports.browserMainParts.preMainMessageLoopRun() diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 6ffba50d34cb..d8ac221c62e0 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -1,6 +1,7 @@ EventEmitter = require('events').EventEmitter app = require 'app' ipc = require 'ipc' +deprecate = require 'deprecate' BrowserWindow = process.atomBinding('window').BrowserWindow BrowserWindow::__proto__ = EventEmitter.prototype @@ -71,32 +72,32 @@ BrowserWindow.fromDevToolsWebContents = (webContents) -> # Helpers. BrowserWindow::loadUrl = -> @webContents.loadUrl.apply @webContents, arguments -BrowserWindow::send = -> @webContents.send.apply @webContents, arguments - -# Be compatible with old API. -BrowserWindow::undo = -> @webContents.undo() -BrowserWindow::redo = -> @webContents.redo() -BrowserWindow::cut = -> @webContents.cut() -BrowserWindow::copy = -> @webContents.copy() -BrowserWindow::paste = -> @webContents.paste() -BrowserWindow::selectAll = -> @webContents.selectAll() -BrowserWindow::restart = -> @webContents.reload() -BrowserWindow::getUrl = -> @webContents.getUrl() BrowserWindow::reload = -> @webContents.reload.apply @webContents, arguments -BrowserWindow::reloadIgnoringCache = -> @webContents.reloadIgnoringCache.apply @webContents, arguments -BrowserWindow::getPageTitle = -> @webContents.getTitle() -BrowserWindow::isLoading = -> @webContents.isLoading() -BrowserWindow::isWaitingForResponse = -> @webContents.isWaitingForResponse() -BrowserWindow::stop = -> @webContents.stop() -BrowserWindow::isCrashed = -> @webContents.isCrashed() -BrowserWindow::executeJavaScriptInDevTools = (code) -> @devToolsWebContents?.executeJavaScript code +BrowserWindow::send = -> @webContents.send.apply @webContents, arguments BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments BrowserWindow::closeDevTools = -> @webContents.closeDevTools() BrowserWindow::isDevToolsOpened = -> @webContents.isDevToolsOpened() BrowserWindow::toggleDevTools = -> @webContents.toggleDevTools() BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContents, arguments BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker() -BrowserWindow::print = -> @webContents.print.apply @webContents, arguments -BrowserWindow::printToPDF = -> @webContents.printToPDF.apply @webContents, arguments + +# Deprecated. +deprecate.rename BrowserWindow, 'restart', 'reload' +deprecate.member BrowserWindow, 'undo', 'webContents' +deprecate.member BrowserWindow, 'redo', 'webContents' +deprecate.member BrowserWindow, 'cut', 'webContents' +deprecate.member BrowserWindow, 'copy', 'webContents' +deprecate.member BrowserWindow, 'paste', 'webContents' +deprecate.member BrowserWindow, 'selectAll', 'webContents' +deprecate.member BrowserWindow, 'getUrl', 'webContents' +deprecate.member BrowserWindow, 'reloadIgnoringCache', 'webContents' +deprecate.member BrowserWindow, 'getPageTitle', 'webContents' +deprecate.member BrowserWindow, 'isLoading', 'webContents' +deprecate.member BrowserWindow, 'isWaitingForResponse', 'webContents' +deprecate.member BrowserWindow, 'stop', 'webContents' +deprecate.member BrowserWindow, 'isCrashed', 'webContents' +deprecate.member BrowserWindow, 'executeJavaScriptInDevTools', 'webContents' +deprecate.member BrowserWindow, 'print', 'webContents' +deprecate.member BrowserWindow, 'printToPDF', 'webContents' module.exports = BrowserWindow diff --git a/atom/browser/lib/chrome-extension.coffee b/atom/browser/lib/chrome-extension.coffee index 15f7bfd54c56..8d313ad0cb51 100644 --- a/atom/browser/lib/chrome-extension.coffee +++ b/atom/browser/lib/chrome-extension.coffee @@ -55,7 +55,7 @@ app.once 'ready', -> BrowserWindow = require 'browser-window' # Load persistented extensions. - loadedExtensionsPath = path.join app.getDataPath(), 'DevTools Extensions' + loadedExtensionsPath = path.join app.getPath('userData'), 'DevTools Extensions' try loadedExtensions = JSON.parse fs.readFileSync(loadedExtensionsPath) diff --git a/atom/renderer/api/lib/ipc.coffee b/atom/renderer/api/lib/ipc.coffee index 1c508a3a5493..01eeb4b6da14 100644 --- a/atom/renderer/api/lib/ipc.coffee +++ b/atom/renderer/api/lib/ipc.coffee @@ -1,3 +1,5 @@ +deprecate = require 'deprecate' + binding = process.atomBinding 'ipc' v8Util = process.atomBinding 'v8_util' @@ -14,7 +16,7 @@ ipc.sendToHost = (args...) -> binding.send 'ipc-message-host', [args...] # Deprecated. -ipc.sendChannel = ipc.send -ipc.sendChannelSync = ipc.sendSync +deprecate.rename ipc, 'sendChannel', 'send' +deprecate.rename ipc, 'sendChannelSync', 'sendSync' module.exports = ipc diff --git a/filenames.gypi b/filenames.gypi index b39362bd1cd4..fe05c34c3422 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -9,7 +9,6 @@ ], 'coffee_sources': [ 'atom/browser/api/lib/app.coffee', - 'atom/browser/api/lib/atom-delegate.coffee', 'atom/browser/api/lib/auto-updater.coffee', 'atom/browser/api/lib/auto-updater/auto-updater-mac.coffee', 'atom/browser/api/lib/auto-updater/auto-updater-win.coffee', From 5d1f7ed029d638319a6c3d31c7a916107dcfab3e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 9 Nov 2015 22:56:12 +0800 Subject: [PATCH 434/738] Update brightray for atom/brightray#161 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 80543fe2b0fc..7c9915847e84 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 80543fe2b0fc04b5096b1ba7ebb9553431d8dfc0 +Subproject commit 7c9915847e84076b5444ee945e6dc2904fb345d1 From 828d911ed195f31450d77b0b585baa1a1d4f708b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 15:12:07 +0800 Subject: [PATCH 435/738] Deprecate ipc module for ipcRenderer --- atom/renderer/api/lib/ipc-renderer.coffee | 16 +++++++++++++++ atom/renderer/api/lib/ipc.coffee | 24 ++++++++++------------ atom/renderer/atom_render_view_observer.cc | 5 ++++- filenames.gypi | 1 + 4 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 atom/renderer/api/lib/ipc-renderer.coffee diff --git a/atom/renderer/api/lib/ipc-renderer.coffee b/atom/renderer/api/lib/ipc-renderer.coffee new file mode 100644 index 000000000000..29004d212b56 --- /dev/null +++ b/atom/renderer/api/lib/ipc-renderer.coffee @@ -0,0 +1,16 @@ +binding = process.atomBinding 'ipc' +v8Util = process.atomBinding 'v8_util' + +# Created by init.coffee. +ipcRenderer = v8Util.getHiddenValue global, 'ipc' + +ipcRenderer.send = (args...) -> + binding.send 'ipc-message', [args...] + +ipcRenderer.sendSync = (args...) -> + JSON.parse binding.sendSync('ipc-message-sync', [args...]) + +ipcRenderer.sendToHost = (args...) -> + binding.send 'ipc-message-host', [args...] + +module.exports = ipcRenderer diff --git a/atom/renderer/api/lib/ipc.coffee b/atom/renderer/api/lib/ipc.coffee index 01eeb4b6da14..e2fcdcd86e8a 100644 --- a/atom/renderer/api/lib/ipc.coffee +++ b/atom/renderer/api/lib/ipc.coffee @@ -1,21 +1,19 @@ deprecate = require 'deprecate' +ipcRenderer = require 'ipc-renderer' +{EventEmitter} = require 'events' -binding = process.atomBinding 'ipc' -v8Util = process.atomBinding 'v8_util' +# This module is deprecated, we mirror everything from ipcRenderer. +deprecate.warn 'ipc module', 'ipcRenderer module' -# Created by init.coffee. -ipc = v8Util.getHiddenValue global, 'ipc' - -ipc.send = (args...) -> - binding.send 'ipc-message', [args...] - -ipc.sendSync = (args...) -> - JSON.parse binding.sendSync('ipc-message-sync', [args...]) - -ipc.sendToHost = (args...) -> - binding.send 'ipc-message-host', [args...] +# Routes events of ipcRenderer. +ipc = new EventEmitter +ipcRenderer.emit = (channel, event, args...) -> + ipc.emit channel, args... + EventEmitter::emit.apply ipcRenderer, arguments # Deprecated. +for method of ipcRenderer when method.startsWith 'send' + ipc[method] = ipcRenderer[method] deprecate.rename ipc, 'sendChannel', 'send' deprecate.rename ipc, 'sendChannelSync', 'sendSync' diff --git a/atom/renderer/atom_render_view_observer.cc b/atom/renderer/atom_render_view_observer.cc index 456ca5ba4b24..ecd9401420f8 100644 --- a/atom/renderer/atom_render_view_observer.cc +++ b/atom/renderer/atom_render_view_observer.cc @@ -142,7 +142,10 @@ void AtomRenderViewObserver::OnBrowserMessage(const base::string16& channel, v8::Local ipc; if (GetIPCObject(isolate, context, &ipc)) { - mate::EmitEvent(isolate, ipc, channel, ListValueToVector(isolate, args)); + auto args_vector = ListValueToVector(isolate, args); + // Insert a dummy Event object. + args_vector.insert(args_vector.begin(), v8::Object::New(isolate)); + mate::EmitEvent(isolate, ipc, channel, args_vector); } } diff --git a/filenames.gypi b/filenames.gypi index fe05c34c3422..93cb4f3e07aa 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -50,6 +50,7 @@ 'atom/renderer/lib/web-view/web-view-attributes.coffee', 'atom/renderer/lib/web-view/web-view-constants.coffee', 'atom/renderer/api/lib/ipc.coffee', + 'atom/renderer/api/lib/ipc-renderer.coffee', 'atom/renderer/api/lib/remote.coffee', 'atom/renderer/api/lib/screen.coffee', 'atom/renderer/api/lib/web-frame.coffee', From 765cfb10941dd3b04566b01ce71eb78e730fd742 Mon Sep 17 00:00:00 2001 From: Felix Rieseberg Date: Tue, 10 Nov 2015 08:28:14 +0100 Subject: [PATCH 436/738] Document Notifications --- .../desktop-environment-integration.md | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/tutorial/desktop-environment-integration.md b/docs/tutorial/desktop-environment-integration.md index 78067f3d8a12..08758d67933f 100644 --- a/docs/tutorial/desktop-environment-integration.md +++ b/docs/tutorial/desktop-environment-integration.md @@ -8,6 +8,44 @@ applications can put a custom menu in the dock menu. This guide explains how to integrate your application into those desktop environments with Electron APIs. +## Notifications (Windows, Linux, OS X) +All three operating systems provide means for applications to send notifications to the user. Electron conveniently allows developers to send notifications using the [JavaScript Notification API](https://notifications.spec.whatwg.org/), using the currently running operating system's native notification APIs to display it. + +```javascript +var myNotificiation = new Notification('Title', { + body: 'Lorem Ipsum Dolor Sit Amet' +}); + +myNotification.onclick = function () { + console.log('Notification clicked') +} +``` +While code and user experience across operating systems are similar, but there are fine differences. + +#### Windows + * On Windows 10, notifications "just work". + * On Windows 8.1 and Windows 8, a shortcut to your app, with a [System.AppUserModel.ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391569(v=vs.85).aspx), must be installed to the Start screen. Note, however, that it does not need to be pinned to the Start screen. + * On Windows 7 and below, notifications are not supported. You can however send "balloon notifications" using the [Tray API](trayballoon). + +To use an image in your notification, pass a local image file (preferably `png`) in the `icon` property of your notification's options. The notification will still display if you submit and incorrect or `http/https`-based URL, but the image will not be displayed. + +``` +new Notification('Title', { + body: 'Notification with icon', + icon: 'file:///C:/Users/feriese/Desktop/icon.png' +}); +``` + +Keep furthermore in mind that the maximum length for the body is 250 characters, with the Windows team recommending that notifications should be kept to 200 characters. + +#### Linux +Notifications are sent using Ubuntu's Unity (and will obviously not be displayed if Unity is not running). For more information about Unity's on screen notifications, [check out the project page](https://unity.ubuntu.com/projects/notifyosd/). + +#### OS X +Notifications are straight-forward on OS X, you should however be aware of [Apple's Human Interface guidelines regarding notifications](https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/NotificationCenter.html). + +Note that notifications are limited to 256 bytes in size - and will be truncated if you exceed that limit. + ## Recent documents (Windows & OS X) Windows and OS X provide easy access to a list of recent documents opened by @@ -252,3 +290,4 @@ window.setDocumentEdited(true); [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 \ No newline at end of file From 6515a445a0175102ab4e34be66723b9cd9cf6fd8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 15:29:43 +0800 Subject: [PATCH 437/738] Use ipcRenderer in Electron's code --- atom/renderer/api/lib/remote.coffee | 6 +++--- atom/renderer/lib/override.coffee | 6 +++--- atom/renderer/lib/web-view/guest-view-internal.coffee | 10 +++++----- atom/renderer/lib/web-view/web-view.coffee | 2 +- spec/api-ipc-spec.coffee | 4 ++-- spec/api-session-spec.coffee | 8 +++----- spec/fixtures/api/localstorage.html | 2 +- spec/fixtures/api/preload.html | 2 +- spec/fixtures/api/send-sync-message.html | 2 +- spec/fixtures/module/preload-ipc.js | 4 ++-- spec/fixtures/module/send-later.js | 2 +- spec/fixtures/pages/basic-auth.html | 2 +- spec/fixtures/pages/beforeunload-false.html | 2 +- spec/fixtures/pages/document-hidden.html | 2 +- spec/fixtures/pages/history.html | 2 +- spec/fixtures/pages/ipc-message.html | 2 +- spec/fixtures/pages/onkeyup.html | 2 +- spec/fixtures/pages/onmouseup.html | 2 +- spec/fixtures/pages/window-opener.html | 2 +- spec/static/index.html | 2 +- 20 files changed, 32 insertions(+), 34 deletions(-) diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index 2de14d541527..5d5905ba24a6 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -1,4 +1,4 @@ -ipc = require 'ipc' +ipc = require 'ipc-renderer' v8Util = process.atomBinding 'v8_util' CallbacksRegistry = require 'callbacks-registry' @@ -119,11 +119,11 @@ metaToPlainObject = (meta) -> obj # Browser calls a callback in renderer. -ipc.on 'ATOM_RENDERER_CALLBACK', (id, args) -> +ipc.on 'ATOM_RENDERER_CALLBACK', (event, id, args) -> callbacksRegistry.apply id, metaToValue(args) # A callback in browser is released. -ipc.on 'ATOM_RENDERER_RELEASE_CALLBACK', (id) -> +ipc.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) -> callbacksRegistry.remove id # Get remote module. diff --git a/atom/renderer/lib/override.coffee b/atom/renderer/lib/override.coffee index 93cf8b8357e8..e54a0e9685c2 100644 --- a/atom/renderer/lib/override.coffee +++ b/atom/renderer/lib/override.coffee @@ -1,4 +1,4 @@ -ipc = require 'ipc' +ipc = require 'ipc-renderer' remote = require 'remote' # Helper function to resolve relative url. @@ -11,7 +11,7 @@ resolveUrl = (url) -> class BrowserWindowProxy constructor: (@guestId) -> @closed = false - ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', (guestId) => + ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', (event, guestId) => if guestId is @guestId @closed = true @@ -99,7 +99,7 @@ if guestId? postMessage: (message, targetOrigin='*') -> ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', guestId, message, targetOrigin, location.origin -ipc.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (guestId, message, sourceOrigin) -> +ipc.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (event, guestId, message, sourceOrigin) -> # Manually dispatch event instead of using postMessage because we also need to # set event.source. event = document.createEvent 'Event' diff --git a/atom/renderer/lib/web-view/guest-view-internal.coffee b/atom/renderer/lib/web-view/guest-view-internal.coffee index 2852d1122874..37dc25f9ee04 100644 --- a/atom/renderer/lib/web-view/guest-view-internal.coffee +++ b/atom/renderer/lib/web-view/guest-view-internal.coffee @@ -1,4 +1,4 @@ -ipc = require 'ipc' +ipc = require 'ipc-renderer' webFrame = require 'web-frame' requestId = 0 @@ -37,16 +37,16 @@ dispatchEvent = (webView, event, args...) -> module.exports = registerEvents: (webView, viewInstanceId) -> - ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}", (event, args...) -> - dispatchEvent webView, event, args... + ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}", (event, domEvent, args...) -> + dispatchEvent webView, domEvent, args... - ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}", (channel, args...) -> + ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}", (event, channel, args...) -> domEvent = new Event('ipc-message') domEvent.channel = channel domEvent.args = [args...] webView.dispatchEvent domEvent - ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}", (args...) -> + ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}", (event, args...) -> domEvent = new Event('size-changed') for f, i in ['oldWidth', 'oldHeight', 'newWidth', 'newHeight'] domEvent[f] = args[i] diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 3a563101f003..3dc54b258d50 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -135,7 +135,7 @@ class WebViewImpl guestViewInternal.setSize @guestInstanceId, normal: newSize createGuest: -> - guestViewInternal.createGuest @buildParams(), (guestInstanceId) => + guestViewInternal.createGuest @buildParams(), (event, guestInstanceId) => @attachWindow guestInstanceId dispatchEvent: (webViewEvent) -> diff --git a/spec/api-ipc-spec.coffee b/spec/api-ipc-spec.coffee index 1155aa73e83d..e5028c602b1f 100644 --- a/spec/api-ipc-spec.coffee +++ b/spec/api-ipc-spec.coffee @@ -1,5 +1,5 @@ assert = require 'assert' -ipc = require 'ipc' +ipc = require 'ipc-renderer' path = require 'path' remote = require 'remote' @@ -70,7 +70,7 @@ describe 'ipc module', -> describe 'ipc.sender.send', -> it 'should work when sending an object containing id property', (done) -> obj = id: 1, name: 'ly' - ipc.once 'message', (message) -> + ipc.once 'message', (event, message) -> assert.deepEqual message, obj done() ipc.send 'message', obj diff --git a/spec/api-session-spec.coffee b/spec/api-session-spec.coffee index 9e083d27c0f7..8baca1557ccb 100644 --- a/spec/api-session-spec.coffee +++ b/spec/api-session-spec.coffee @@ -78,7 +78,7 @@ describe 'session module', -> # A 5 MB mock pdf. mockPDF = new Buffer 1024 * 1024 * 5 contentDisposition = 'inline; filename="mock.pdf"' - ipc = require 'ipc' + ipc = require 'ipc-renderer' downloadFilePath = path.join fixtures, 'mock.pdf' downloadServer = http.createServer (req, res) -> res.writeHead 200, { @@ -94,8 +94,7 @@ describe 'session module', -> {port} = downloadServer.address() ipc.sendSync 'set-download-option', false w.loadUrl "#{url}:#{port}" - ipc.once 'download-done', (state, url, mimeType, receivedBytes, - totalBytes, disposition, filename) -> + ipc.once 'download-done', (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) -> assert.equal state, 'completed' assert.equal filename, 'mock.pdf' assert.equal url, "http://127.0.0.1:#{port}/" @@ -112,8 +111,7 @@ describe 'session module', -> {port} = downloadServer.address() ipc.sendSync 'set-download-option', true w.loadUrl "#{url}:#{port}/" - ipc.once 'download-done', (state, url, mimeType, receivedBytes, - totalBytes, disposition, filename) -> + ipc.once 'download-done', (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) -> assert.equal state, 'cancelled' assert.equal filename, 'mock.pdf' assert.equal mimeType, 'application/pdf' diff --git a/spec/fixtures/api/localstorage.html b/spec/fixtures/api/localstorage.html index 8110a0b4be6a..d1450e93c98d 100644 --- a/spec/fixtures/api/localstorage.html +++ b/spec/fixtures/api/localstorage.html @@ -2,7 +2,7 @@ diff --git a/spec/fixtures/api/send-sync-message.html b/spec/fixtures/api/send-sync-message.html index d6fe83f907e1..40bae94b810f 100644 --- a/spec/fixtures/api/send-sync-message.html +++ b/spec/fixtures/api/send-sync-message.html @@ -1,7 +1,7 @@ diff --git a/spec/fixtures/module/preload-ipc.js b/spec/fixtures/module/preload-ipc.js index 9b6e0201248e..76bd481cab6f 100644 --- a/spec/fixtures/module/preload-ipc.js +++ b/spec/fixtures/module/preload-ipc.js @@ -1,4 +1,4 @@ -var ipc = require('ipc'); -ipc.on('ping', function(message) { +var ipc = require('ipc-renderer'); +ipc.on('ping', function(event, message) { ipc.sendToHost('pong', message); }); diff --git a/spec/fixtures/module/send-later.js b/spec/fixtures/module/send-later.js index fce96b84b787..9cd5bfd38853 100644 --- a/spec/fixtures/module/send-later.js +++ b/spec/fixtures/module/send-later.js @@ -1,4 +1,4 @@ -var ipc = require('ipc'); +var ipc = require('ipc-renderer'); window.onload = function() { ipc.send('answer', typeof window.process); } diff --git a/spec/fixtures/pages/basic-auth.html b/spec/fixtures/pages/basic-auth.html index aa95546a9c11..f2b9fab199fe 100644 --- a/spec/fixtures/pages/basic-auth.html +++ b/spec/fixtures/pages/basic-auth.html @@ -2,7 +2,7 @@ diff --git a/spec/fixtures/pages/history.html b/spec/fixtures/pages/history.html index b5029d638926..ef0083535973 100644 --- a/spec/fixtures/pages/history.html +++ b/spec/fixtures/pages/history.html @@ -2,7 +2,7 @@ diff --git a/spec/fixtures/pages/ipc-message.html b/spec/fixtures/pages/ipc-message.html index 15bfef49c4da..65e347275c21 100644 --- a/spec/fixtures/pages/ipc-message.html +++ b/spec/fixtures/pages/ipc-message.html @@ -1,7 +1,7 @@ diff --git a/spec/fixtures/pages/onkeyup.html b/spec/fixtures/pages/onkeyup.html index 99e6c3e98382..87e6dc596b5b 100644 --- a/spec/fixtures/pages/onkeyup.html +++ b/spec/fixtures/pages/onkeyup.html @@ -2,7 +2,7 @@ diff --git a/spec/fixtures/pages/onmouseup.html b/spec/fixtures/pages/onmouseup.html index 1fd38bc7211f..ea486fdf80ed 100644 --- a/spec/fixtures/pages/onmouseup.html +++ b/spec/fixtures/pages/onmouseup.html @@ -2,7 +2,7 @@ diff --git a/spec/fixtures/pages/window-opener.html b/spec/fixtures/pages/window-opener.html index 226b57dbd709..a7b59bd1a45b 100644 --- a/spec/fixtures/pages/window-opener.html +++ b/spec/fixtures/pages/window-opener.html @@ -4,7 +4,7 @@ if (window.opener !== null) window.opener.postMessage(typeof window.opener, '*'); else - require('ipc').send('opener', window.opener); + require('ipc-renderer').send('opener', window.opener); diff --git a/spec/static/index.html b/spec/static/index.html index 879d769860ed..e7c69f5ba7de 100644 --- a/spec/static/index.html +++ b/spec/static/index.html @@ -29,7 +29,7 @@ } require('coffee-script/register'); // Supports .coffee tests. - var ipc = require('ipc'); + var ipc = require('ipc-renderer'); // Rediret all output to browser. if (isCi) { From 844cea8f216539ad2233180ab28b934d060f12c7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 15:41:24 +0800 Subject: [PATCH 438/738] Deprecate ipc module for ipcMain --- atom/browser/api/lib/ipc-main.coffee | 3 +++ atom/browser/api/lib/ipc.coffee | 7 +++++-- filenames.gypi | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 atom/browser/api/lib/ipc-main.coffee diff --git a/atom/browser/api/lib/ipc-main.coffee b/atom/browser/api/lib/ipc-main.coffee new file mode 100644 index 000000000000..8021544479d2 --- /dev/null +++ b/atom/browser/api/lib/ipc-main.coffee @@ -0,0 +1,3 @@ +{EventEmitter} = require 'events' + +module.exports = new EventEmitter diff --git a/atom/browser/api/lib/ipc.coffee b/atom/browser/api/lib/ipc.coffee index 71cf1d17e491..f116b9a874a5 100644 --- a/atom/browser/api/lib/ipc.coffee +++ b/atom/browser/api/lib/ipc.coffee @@ -1,3 +1,6 @@ -EventEmitter = require('events').EventEmitter +deprecate = require 'deprecate' -module.exports = new EventEmitter +# This module is deprecated, we mirror everything from ipcRenderer. +deprecate.warn 'ipc module', 'ipcMain module' + +module.exports = require 'ipc-main' diff --git a/filenames.gypi b/filenames.gypi index 93cb4f3e07aa..4dc709c5ec57 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -18,6 +18,7 @@ 'atom/browser/api/lib/dialog.coffee', 'atom/browser/api/lib/global-shortcut.coffee', 'atom/browser/api/lib/ipc.coffee', + 'atom/browser/api/lib/ipc-main.coffee', 'atom/browser/api/lib/menu.coffee', 'atom/browser/api/lib/menu-item.coffee', 'atom/browser/api/lib/navigation-controller.coffee', From 751af25f374c0c144b3f56fb301170fc5b0829b8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 16:04:34 +0800 Subject: [PATCH 439/738] Use ipcMain in Electron's code --- atom/browser/api/lib/browser-window.coffee | 2 +- atom/browser/api/lib/navigation-controller.coffee | 2 +- atom/browser/api/lib/web-contents.coffee | 2 +- atom/browser/lib/guest-view-manager.coffee | 2 +- atom/browser/lib/guest-window-manager.coffee | 2 +- atom/browser/lib/rpc-server.coffee | 2 +- spec/api-browser-window-spec.coffee | 6 +++--- spec/api-ipc-spec.coffee | 2 +- spec/api-session-spec.coffee | 6 +++--- spec/asar-spec.coffee | 2 +- spec/static/main.js | 4 ++-- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index d8ac221c62e0..5bb633208840 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -1,6 +1,6 @@ EventEmitter = require('events').EventEmitter app = require 'app' -ipc = require 'ipc' +ipc = require 'ipc-main' deprecate = require 'deprecate' BrowserWindow = process.atomBinding('window').BrowserWindow diff --git a/atom/browser/api/lib/navigation-controller.coffee b/atom/browser/api/lib/navigation-controller.coffee index f78d92c341d6..34911dd759ec 100644 --- a/atom/browser/api/lib/navigation-controller.coffee +++ b/atom/browser/api/lib/navigation-controller.coffee @@ -1,4 +1,4 @@ -ipc = require 'ipc' +ipc = require 'ipc-main' # The history operation in renderer is redirected to browser. ipc.on 'ATOM_SHELL_NAVIGATION_CONTROLLER', (event, method, args...) -> diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index 331a561189d7..958c3f8270c6 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -2,7 +2,7 @@ EventEmitter = require('events').EventEmitter Menu = require './menu' NavigationController = require './navigation-controller' binding = process.atomBinding 'web_contents' -ipc = require 'ipc' +ipc = require 'ipc-main' nextId = 0 getNextId = -> ++nextId diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index 455e969812f7..c99b681498e4 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -1,4 +1,4 @@ -ipc = require 'ipc' +ipc = require 'ipc-main' webContents = require 'web-contents' webViewManager = null # Doesn't exist in early initialization. diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index 5de3ad3b042e..fe01c6fa771e 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -1,4 +1,4 @@ -ipc = require 'ipc' +ipc = require 'ipc-main' v8Util = process.atomBinding 'v8_util' BrowserWindow = require 'browser-window' diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index ae4b161674bd..c6a646edcd9b 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -1,4 +1,4 @@ -ipc = require 'ipc' +ipc = require 'ipc-main' path = require 'path' objectsRegistry = require './objects-registry.js' v8Util = process.atomBinding 'v8_util' diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 1218d27b7fd7..460a1c1ec17c 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -201,12 +201,12 @@ describe 'browser-window module', -> describe '"web-preferences" option', -> afterEach -> - remote.require('ipc').removeAllListeners('answer') + remote.require('ipc-main').removeAllListeners('answer') describe '"preload" option', -> it 'loads the script before other scripts in window', (done) -> preload = path.join fixtures, 'module', 'set-global.js' - remote.require('ipc').once 'answer', (event, test) -> + remote.require('ipc-main').once 'answer', (event, test) -> assert.equal(test, 'preload') done() w.destroy() @@ -219,7 +219,7 @@ describe 'browser-window module', -> describe '"node-integration" option', -> it 'disables node integration when specified to false', (done) -> preload = path.join fixtures, 'module', 'send-later.js' - remote.require('ipc').once 'answer', (event, test) -> + remote.require('ipc-main').once 'answer', (event, test) -> assert.equal(test, 'undefined') done() w.destroy() diff --git a/spec/api-ipc-spec.coffee b/spec/api-ipc-spec.coffee index e5028c602b1f..d8918338c96c 100644 --- a/spec/api-ipc-spec.coffee +++ b/spec/api-ipc-spec.coffee @@ -83,7 +83,7 @@ describe 'ipc module', -> it 'does not crash when reply is not sent and browser is destroyed', (done) -> @timeout 10000 w = new BrowserWindow(show: false) - remote.require('ipc').once 'send-sync-message', (event) -> + remote.require('ipc-main').once 'send-sync-message', (event) -> event.returnValue = null w.destroy() done() diff --git a/spec/api-session-spec.coffee b/spec/api-session-spec.coffee index 8baca1557ccb..028768f61d38 100644 --- a/spec/api-session-spec.coffee +++ b/spec/api-session-spec.coffee @@ -60,9 +60,9 @@ describe 'session module', -> describe 'session.clearStorageData(options)', -> fixtures = path.resolve __dirname, 'fixtures' it 'clears localstorage data', (done) -> - ipc = remote.require('ipc') - ipc.on 'count', (event, count) -> - ipc.removeAllListeners 'count' + ipcMain = remote.require('ipc-main') + ipcMain.on 'count', (event, count) -> + ipcMain.removeAllListeners 'count' assert not count done() w.loadUrl 'file://' + path.join(fixtures, 'api', 'localstorage.html') diff --git a/spec/asar-spec.coffee b/spec/asar-spec.coffee index 75f0cec63adb..3e3890d529f1 100644 --- a/spec/asar-spec.coffee +++ b/spec/asar-spec.coffee @@ -407,7 +407,7 @@ describe 'asar package', -> describe 'asar protocol', -> url = require 'url' remote = require 'remote' - ipc = remote.require 'ipc' + ipc = remote.require 'ipc-main' BrowserWindow = remote.require 'browser-window' it 'can request a file in package', (done) -> diff --git a/spec/static/main.js b/spec/static/main.js index 5b10bb6d43d7..702c88ecdd94 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -1,5 +1,5 @@ var app = require('app'); -var ipc = require('ipc'); +var ipc = require('ipc-main'); var dialog = require('dialog'); var path = require('path'); var BrowserWindow = require('browser-window'); @@ -78,7 +78,7 @@ app.on('ready', function() { // For session's download test, listen 'will-download' event in browser, and // reply the result to renderer for verifying var downloadFilePath = path.join(__dirname, '..', 'fixtures', 'mock.pdf'); - require('ipc').on('set-download-option', function(event, need_cancel) { + ipc.on('set-download-option', function(event, need_cancel) { window.webContents.session.once('will-download', function(e, item, webContents) { item.setSavePath(downloadFilePath); From 05611f5e60166f350d4b6776435e62924b8d6e7d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 16:21:08 +0800 Subject: [PATCH 440/738] spec: Use multiparty instead of formidable The latter is buggy and affects our specs. --- spec/api-crash-reporter-spec.coffee | 7 ++----- spec/package.json | 2 +- spec/static/main.js | 1 + 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/spec/api-crash-reporter-spec.coffee b/spec/api-crash-reporter-spec.coffee index 618adaaf9dec..5e06cade8cec 100644 --- a/spec/api-crash-reporter-spec.coffee +++ b/spec/api-crash-reporter-spec.coffee @@ -3,7 +3,7 @@ path = require 'path' http = require 'http' url = require 'url' remote = require 'remote' -formidable = require 'formidable' +multiparty = require 'multiparty' crashReporter = remote.require 'crash-reporter' BrowserWindow = remote.require 'browser-window' @@ -26,10 +26,8 @@ describe 'crash-reporter module', -> @timeout 120000 server = http.createServer (req, res) -> server.close() - form = new formidable.IncomingForm() - process.throwDeprecation = false + form = new multiparty.Form() form.parse req, (error, fields, files) -> - process.throwDeprecation = true assert.equal fields['prod'], 'Electron' assert.equal fields['ver'], process.versions['electron'] assert.equal fields['process_type'], 'renderer' @@ -39,7 +37,6 @@ describe 'crash-reporter module', -> assert.equal fields['_productName'], 'Zombies' assert.equal fields['_companyName'], 'Umbrella Corporation' assert.equal fields['_version'], require('remote').require('app').getVersion() - assert files['upload_file_minidump']['name']? res.end('abc-123-def') done() diff --git a/spec/package.json b/spec/package.json index cf1d0abe89e3..38bd83796701 100644 --- a/spec/package.json +++ b/spec/package.json @@ -5,7 +5,7 @@ "version": "0.1.0", "devDependencies": { "basic-auth": "^1.0.0", - "formidable": "1.0.16", + "multiparty": "4.1.2", "graceful-fs": "3.0.5", "mocha": "2.1.0", "q": "0.9.7", diff --git a/spec/static/main.js b/spec/static/main.js index 702c88ecdd94..70c47cc37e1c 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -9,6 +9,7 @@ process.port = 0; // will be used by crash-reporter spec. app.commandLine.appendSwitch('js-flags', '--expose_gc'); app.commandLine.appendSwitch('ignore-certificate-errors'); +app.commandLine.appendSwitch('disable-renderer-backgrounding'); // Accessing stdout in the main process will result in the process.stdout // throwing UnknownSystemError in renderer process sometimes. This line makes From 90a7d4a906e902a4212a57d2dcc860204b389b13 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 16:48:24 +0800 Subject: [PATCH 441/738] docs: Update with new IPC modules --- docs/README.md | 4 +- docs/api/ipc-main-process.md | 76 -------------------------- docs/api/ipc-main.md | 71 ++++++++++++++++++++++++ docs/api/ipc-renderer.md | 53 +++++++++--------- docs/api/web-contents.md | 18 ++---- docs/api/web-view-tag.md | 11 ++-- docs/tutorial/online-offline-events.md | 46 ++++++++-------- 7 files changed, 136 insertions(+), 143 deletions(-) delete mode 100644 docs/api/ipc-main-process.md create mode 100644 docs/api/ipc-main.md diff --git a/docs/README.md b/docs/README.md index 754048f5e3f3..fb5c64a8f17e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -36,7 +36,7 @@ * [content-tracing](api/content-tracing.md) * [dialog](api/dialog.md) * [global-shortcut](api/global-shortcut.md) -* [ipc (main process)](api/ipc-main-process.md) +* [ipc-main](api/ipc-main.md) * [menu](api/menu.md) * [menu-item](api/menu-item.md) * [power-monitor](api/power-monitor.md) @@ -48,7 +48,7 @@ ### Modules for the Renderer Process (Web Page): -* [ipc (renderer)](api/ipc-renderer.md) +* [ipc-renderer](api/ipc-renderer.md) * [remote](api/remote.md) * [web-frame](api/web-frame.md) diff --git a/docs/api/ipc-main-process.md b/docs/api/ipc-main-process.md deleted file mode 100644 index 98d9c3c22d43..000000000000 --- a/docs/api/ipc-main-process.md +++ /dev/null @@ -1,76 +0,0 @@ -# ipc (main process) - -The `ipc` module, when used in the main process, handles asynchronous and -synchronous messages sent from a renderer process (web page). Messages sent from -a renderer will be emitted to this 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-args) -for more information. - -- When sending a message, the event name is the `channel`. -- To reply a synchronous message, you need to set `event.returnValue`. -- To send an asynchronous back to the sender, you can use - `event.sender.send(...)`. - -An example of sending and handling messages between the render and main -processes: - -```javascript -// In main process. -var ipc = require('ipc'); -ipc.on('asynchronous-message', function(event, arg) { - console.log(arg); // prints "ping" - event.sender.send('asynchronous-reply', 'pong'); -}); - -ipc.on('synchronous-message', function(event, arg) { - console.log(arg); // prints "ping" - event.returnValue = 'pong'; -}); -``` - -```javascript -// In renderer process (web page). -var ipc = require('ipc'); -console.log(ipc.sendSync('synchronous-message', 'ping')); // prints "pong" - -ipc.on('asynchronous-reply', function(arg) { - console.log(arg); // prints "pong" -}); -ipc.send('asynchronous-message', 'ping'); -``` - -## Listening for Messages - -The `ipc` module has the following method to listen for events: - -### `ipc.on(channel, callback)` - -* `channel` String - The event name. -* `callback` Function - -When the event occurs the `callback` is called with an `event` object and a -message, `arg`. - -## IPC Events - -The `event` object passed to the `callback` has the following methods: - -### `Event.returnValue` - -Set this to the value to be returned in a synchronous message. - -### `Event.sender` - -Returns the `WebContents` that sent the message. - -### `Event.sender.send(channel[, arg1][, arg2][, ...])` - -* `channel` String - The event name. -* `arg` (optional) - -This sends an asynchronous message back to the render process. Optionally, there -can be one or a series of arguments, `arg`, which can have any type. diff --git a/docs/api/ipc-main.md b/docs/api/ipc-main.md new file mode 100644 index 000000000000..4f3d6ebc3bf7 --- /dev/null +++ b/docs/api/ipc-main.md @@ -0,0 +1,71 @@ +# ipcMain + +The `ipcMain` module, when used in the main process, handles asynchronous and +synchronous messages sent from a renderer process (web page). Messages sent from +a renderer will be emitted to this module. + +## Sending Messages + +It is also possible to send messages from the main process to the renderer +process, see [WebContents.send][webcontents-send] for more information. + +* When sending a message, the event name is the `channel`. +* To reply a synchronous message, you need to set `event.returnValue`. +* To send an asynchronous back to the sender, you can use + `event.sender.send(...)`. + +An example of sending and handling messages between the render and main +processes: + +```javascript +// In main process. +var ipcMain = require('ipc-main'); +ipcMain.on('asynchronous-message', function(event, arg) { + console.log(arg); // prints "ping" + event.sender.send('asynchronous-reply', 'pong'); +}); + +ipcMain.on('synchronous-message', function(event, arg) { + console.log(arg); // prints "ping" + event.returnValue = 'pong'; +}); +``` + +```javascript +// In renderer process (web page). +var ipcRenderer = require('ipc-renderer'); +console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong" + +ipcRenderer.on('asynchronous-reply', function(event, arg) { + console.log(arg); // prints "pong" +}); +ipcRenderer.send('asynchronous-message', 'ping'); +``` + +## Listening for Messages + +The `ipcMain` module has the following method to listen for events: + +### `ipcMain.on(channel, callback)` + +* `channel` String - The event name. +* `callback` Function + +When the event occurs the `callback` is called with an `event` object and a +message, `arg`. + +## IPC Event + +The `event` object passed to the `callback` has the following methods: + +### `event.returnValue` + +Set this to the value to be returned in a synchronous message. + +### `event.sender` + +Returns the `webContents` that sent the message, you can call +`event.sender.send` to reply to the asynchronous message, see +[WebContents.send][webcontents-send] for more information. + +[webcontents-send]: web-contents.md#webcontentssendchannel-args diff --git a/docs/api/ipc-renderer.md b/docs/api/ipc-renderer.md index 752af2ebe293..e591f9e0bca2 100644 --- a/docs/api/ipc-renderer.md +++ b/docs/api/ipc-renderer.md @@ -1,52 +1,55 @@ -# ipc (renderer) +# ipcRenderer -The `ipc` module provides a few methods so you can send synchronous and +The `ipcRenderer` module provides a few methods so you can send synchronous and asynchronous messages from the render process (web page) to the main process. You can also receive replies from the main process. -**Note:** If you want to make use of modules in the main process from the renderer -process, you might consider using the [remote](remote.md) module. +See [ipcMain](ipc-main.md) for code examples. -See [ipc (main process)](ipc-main-process.md) for code examples. +## Listening for Messages -## Methods +The `ipcRenderer` module has the following method to listen for events: -The `ipc` module has the following methods for sending messages: +### `ipcRenderer.on(channel, callback)` -**Note:** When using these methods to send a `message` you must also listen -for it in the main process with [`ipc (main process)`](ipc-main-process.md). +* `channel` String - The event name. +* `callback` Function -### `ipc.send(channel[, arg1][, arg2][, ...])` +When the event occurs the `callback` is called with an `event` object and +arbitrary arguments. + +## Sending Messages + +The `ipcRenderer` module has the following methods for sending messages: + +### `ipcRenderer.send(channel[, arg1][, arg2][, ...])` * `channel` String - The event name. * `arg` (optional) -Send an event to the main process asynchronously via a `channel`. Optionally, -there can be a message: one or a series of arguments, `arg`, which can have any -type. The main process handles it by listening for the `channel` event with -`ipc`. +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 +`channel` event with `ipcMain`. -### `ipc.sendSync(channel[, arg1][, arg2][, ...])` +### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])` * `channel` String - The event name. * `arg` (optional) -Send an event to the main process synchronously via a `channel`. Optionally, -there can be a message: one or a series of arguments, `arg`, which can have any -type. The main process handles it by listening for the `channel` event with -`ipc`. +Send an event to the main process synchronously via a `channel`, you can also +send arbitrary arguments. The main process handles it by listening for the +`channel` event with `ipcMain`. The main process handles it by listening for the `channel` event with `ipc` and replies by setting the `event.returnValue`. -**Note:** Sending a synchronous message will block the whole renderer process so -using this method is not recommended. +__Note:__ Sending a synchronous message will block the whole renderer process, +unless you know what you are doing you should never use it. -### `ipc.sendToHost(channel[, arg1][, arg2][, ...])` +### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])` * `channel` String - The event name. * `arg` (optional) -Like `ipc.send` but the event will be sent to the host page in a `` -instead of the main process. Optionally, there can be a message: one or a series -of arguments, `arg`, which can have any type. +Like `ipcRenderer.send` but the event will be sent to the `` element in +the host page instead of the main process. diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 52a06b87edb1..d62706b2ba9a 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -510,13 +510,14 @@ Starts inspecting element at position (`x`, `y`). Opens the developer tools for the service worker context. -### `webContents.send(channel[, args...])` +### `webContents.send(channel[, arg1][, arg2][, ...])` * `channel` String -* `args...` (optional) +* `arg` (optional) -Send `args...` to the web page via `channel` in an asynchronous message, the web -page can handle it by listening to the `channel` event of the `ipc` module. +Send an asynchronous message to renderer process via `channel`, you can also +send arbitrary arguments. 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: @@ -537,7 +538,7 @@ app.on('ready', function() { @@ -545,13 +546,6 @@ app.on('ready', function() { ``` -**Note:** - -1. The IPC message handler in web pages does not have an `event` parameter, - which is different from the handlers in the main process. -2. There is no way to send synchronous messages from the main process to a - renderer process, because it would be very easy to cause dead locks. - ### `webContents.enableDeviceEmulation(parameters)` `parameters` Object, properties: diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 3fda3a98edb5..9a0e0be33b36 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -355,15 +355,16 @@ Prints `webview`'s web page. Same with `webContents.print([options])`. Prints webview's web page as PDF, Same with `webContents.printToPDF(options, callback)` -### `.send(channel[, args...])` +### `.send(channel[, arg1][, arg2][, ...])` * `channel` String * `arg` (optional) -Send `args..` to guest page via `channel` in asynchronous message, the guest -page can handle it by listening to the `channel` event of `ipc` module. +Send an asynchronous message to renderer process via `channel`, you can also +send arbitrary arguments. The renderer process can handle the message by +listening to the `channel` event with the `ipcRenderer` module. -See [WebContents.send](web-contents.md#webcontentssendchannel-args) for +See [webContents.send](web-contents.md#webcontentssendchannel-args) for examples. ### `.sendInputEvent(event)` @@ -372,7 +373,7 @@ examples. Sends an input `event` to the page. -See [WebContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent) +See [webContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent) for detailed description of `event` object. ## DOM events diff --git a/docs/tutorial/online-offline-events.md b/docs/tutorial/online-offline-events.md index 88f9a32f2ec6..46d659e07d05 100644 --- a/docs/tutorial/online-offline-events.md +++ b/docs/tutorial/online-offline-events.md @@ -21,18 +21,18 @@ _online-status.html_ ```html - - - + alertOnlineStatus(); + + ``` @@ -46,7 +46,7 @@ _main.js_ ```javascript var app = require('app'); -var ipc = require('ipc'); +var ipcMain = require('ipc-main'); var BrowserWindow = require('browser-window'); var onlineStatusWindow; @@ -55,7 +55,7 @@ app.on('ready', function() { onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); }); -ipc.on('online-status-changed', function(event, status) { +ipcMain.on('online-status-changed', function(event, status) { console.log(status); }); ``` @@ -65,18 +65,18 @@ _online-status.html_ ```html - - - + updateOnlineStatus(); + + ``` From d234f10177c71cdf6860e90e3317f3b5d17eb13e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 16:59:08 +0800 Subject: [PATCH 442/738] Implement event.sender for ipcRenderer --- atom/renderer/atom_render_view_observer.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/atom/renderer/atom_render_view_observer.cc b/atom/renderer/atom_render_view_observer.cc index ecd9401420f8..931913dd75d0 100644 --- a/atom/renderer/atom_render_view_observer.cc +++ b/atom/renderer/atom_render_view_observer.cc @@ -31,6 +31,7 @@ #include "third_party/WebKit/public/web/WebScriptSource.h" #include "third_party/WebKit/public/web/WebView.h" #include "ui/base/resource/resource_bundle.h" +#include "native_mate/dictionary.h" namespace atom { @@ -143,8 +144,10 @@ void AtomRenderViewObserver::OnBrowserMessage(const base::string16& channel, v8::Local ipc; if (GetIPCObject(isolate, context, &ipc)) { auto args_vector = ListValueToVector(isolate, args); - // Insert a dummy Event object. - args_vector.insert(args_vector.begin(), v8::Object::New(isolate)); + // Insert the Event object, event.sender is ipc. + mate::Dictionary event = mate::Dictionary::CreateEmpty(isolate); + event.Set("sender", ipc); + args_vector.insert(args_vector.begin(), event.GetHandle()); mate::EmitEvent(isolate, ipc, channel, args_vector); } } From 682433028c8ebb5360f3ac0551f57f314aeb99ec Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 17:43:29 +0800 Subject: [PATCH 443/738] docs: Clean up the desktop-environment-integration.md --- .../desktop-environment-integration.md | 68 +++++++++++++------ 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/docs/tutorial/desktop-environment-integration.md b/docs/tutorial/desktop-environment-integration.md index 08758d67933f..39f74ff10771 100644 --- a/docs/tutorial/desktop-environment-integration.md +++ b/docs/tutorial/desktop-environment-integration.md @@ -9,7 +9,11 @@ This guide explains how to integrate your application into those desktop environments with Electron APIs. ## Notifications (Windows, Linux, OS X) -All three operating systems provide means for applications to send notifications to the user. Electron conveniently allows developers to send notifications using the [JavaScript Notification API](https://notifications.spec.whatwg.org/), using the currently running operating system's native notification APIs to display it. + +All three operating systems provide means for applications to send notifications +to the user. Electron conveniently allows developers to send notifications with +the [HTML5 Notification API](https://notifications.spec.whatwg.org/), using +the currently running operating system's native notification APIs to display it. ```javascript var myNotificiation = new Notification('Title', { @@ -20,31 +24,50 @@ myNotification.onclick = function () { console.log('Notification clicked') } ``` -While code and user experience across operating systems are similar, but there are fine differences. -#### Windows - * On Windows 10, notifications "just work". - * On Windows 8.1 and Windows 8, a shortcut to your app, with a [System.AppUserModel.ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391569(v=vs.85).aspx), must be installed to the Start screen. Note, however, that it does not need to be pinned to the Start screen. - * On Windows 7 and below, notifications are not supported. You can however send "balloon notifications" using the [Tray API](trayballoon). +While code and user experience across operating systems are similar, but there +are fine differences. -To use an image in your notification, pass a local image file (preferably `png`) in the `icon` property of your notification's options. The notification will still display if you submit and incorrect or `http/https`-based URL, but the image will not be displayed. +### Windows -``` +* On Windows 10, notifications "just work". +* On Windows 8.1 and Windows 8, a shortcut to your app, with a [Application User +Model ID][app-user-model-id], must be installed to the Start screen. Note, +however, that it does not need to be pinned to the Start screen. +* On Windows 7 and below, notifications are not supported. You can however send +"balloon notifications" using the [Tray API](tray-balloon). + +To use an image in your notification, pass a local image file (preferably `png`) +in the `icon` property of your notification's options. The notification will +still display if you submit and incorrect or `http/https`-based URL, but the +image will not be displayed. + +```javascript new Notification('Title', { body: 'Notification with icon', icon: 'file:///C:/Users/feriese/Desktop/icon.png' }); ``` -Keep furthermore in mind that the maximum length for the body is 250 characters, with the Windows team recommending that notifications should be kept to 200 characters. +Keep furthermore in mind that the maximum length for the body is 250 characters, +with the Windows team recommending that notifications should be kept to 200 +characters. -#### Linux -Notifications are sent using Ubuntu's Unity (and will obviously not be displayed if Unity is not running). For more information about Unity's on screen notifications, [check out the project page](https://unity.ubuntu.com/projects/notifyosd/). +### Linux -#### OS X -Notifications are straight-forward on OS X, you should however be aware of [Apple's Human Interface guidelines regarding notifications](https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/NotificationCenter.html). +Notifications are sent using `libnotify`, it can show notifications on any +desktop environment that follows [Desktop Notifications +Specification][notification-spec], including Cinnamon, Enlightenment, Unity, +GNOME, KDE. -Note that notifications are limited to 256 bytes in size - and will be truncated if you exceed that limit. +### OS X + +Notifications are straight-forward on OS X, you should however be aware of +[Apple's Human Interface guidelines regarding +notifications](https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/NotificationCenter.html). + +Note that notifications are limited to 256 bytes in size - and will be truncated +if you exceed that limit. ## Recent documents (Windows & OS X) @@ -81,7 +104,8 @@ registered as a handler of the file type of the document, otherwise the file won't appear in JumpList even after you have added it. You can find everything on registering your application in [Application Registration][app-registration]. -When a user clicks a file from the JumpList, a new instance of your application will be started with the path of the file added as a command line argument. +When a user clicks a file from the JumpList, a new instance of your application +will be started with the path of the file added as a command line argument. ### OS X Notes @@ -192,10 +216,10 @@ __Thumbnail toolbar of Windows Media Player:__ ![player](https://i-msdn.sec.s-msft.com/dynimg/IC420540.png) -You can use [BrowserWindow.setThumbarButtons][setthumbarbuttons] to set thumbnail -toolbar in your application: +You can use [BrowserWindow.setThumbarButtons][setthumbarbuttons] to set +thumbnail toolbar in your application: -``` +```javascript var BrowserWindow = require('browser-window'); var path = require('path'); var win = new BrowserWindow({ @@ -226,8 +250,8 @@ win.setThumbarButtons([]); ## Unity Launcher Shortcuts (Linux) -In Unity, you can add custom entries to its launcher via modifying the `.desktop` -file, see [Adding Shortcuts to a Launcher][unity-launcher]. +In Unity, you can add custom entries to its launcher via modifying the +`.desktop` file, see [Adding Shortcuts to a Launcher][unity-launcher]. __Launcher shortcuts of Audacious:__ @@ -290,4 +314,6 @@ window.setDocumentEdited(true); [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 \ No newline at end of file +[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 d582ddf790969527155e3dd6ccda3eaebb8d1327 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 17:44:14 +0800 Subject: [PATCH 444/738] Update brightray for win7 crash of using notification --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 7c9915847e84..29bd72a7537f 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 7c9915847e84076b5444ee945e6dc2904fb345d1 +Subproject commit 29bd72a7537ffb99775e3e56ad5662fd4a1bfed0 From 1f01a4535ae6073f6730b993a5b3089c14611cfb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 18:04:59 +0800 Subject: [PATCH 445/738] Fix compilation error of brightray --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 29bd72a7537f..871bc3ccf10a 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 29bd72a7537ffb99775e3e56ad5662fd4a1bfed0 +Subproject commit 871bc3ccf10a86c4d63116f6279dd6095faf3af4 From 08e245e3dc502baa1f84ec62c85add45738ce5ff Mon Sep 17 00:00:00 2001 From: Levin Rickert Date: Tue, 10 Nov 2015 12:42:05 +0100 Subject: [PATCH 446/738] Fix typo --- atom/browser/api/lib/ipc.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/api/lib/ipc.coffee b/atom/browser/api/lib/ipc.coffee index f116b9a874a5..b8ab05a886b9 100644 --- a/atom/browser/api/lib/ipc.coffee +++ b/atom/browser/api/lib/ipc.coffee @@ -1,6 +1,6 @@ deprecate = require 'deprecate' -# This module is deprecated, we mirror everything from ipcRenderer. +# This module is deprecated, we mirror everything from ipcMain. deprecate.warn 'ipc module', 'ipcMain module' module.exports = require 'ipc-main' From f6a0e5ad31d3fb187649b9a4658f5d6e8fae0eb2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 20:32:16 +0800 Subject: [PATCH 447/738] Update brightray for atom/brightray#167 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 871bc3ccf10a..4e069f1806ef 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 871bc3ccf10a86c4d63116f6279dd6095faf3af4 +Subproject commit 4e069f1806efe5da9a965e61f329b19b7791104a From f98147ea014734e02b43dec6170783b1ac43f3d2 Mon Sep 17 00:00:00 2001 From: Nishanth Shanmugham Date: Tue, 10 Nov 2015 09:27:39 -0600 Subject: [PATCH 448/738] Tray: Rename events to drag-enter and drag-leave Previously, the names were drag-entered and drag-exited. The new names mirror the HTML Drag and Drop event names --- atom/browser/api/atom_api_tray.cc | 4 ++-- docs/api/tray.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index 5381c77c3793..00b8eda7b54a 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -79,11 +79,11 @@ void Tray::OnDropFiles(const std::vector& files) { } void Tray::OnDragEntered() { - Emit("drag-entered"); + Emit("drag-enter"); } void Tray::OnDragExited() { - Emit("drag-exited"); + Emit("drag-leave"); } bool Tray::IsDestroyed() const { diff --git a/docs/api/tray.md b/docs/api/tray.md index 5d187fc5b88c..37e17d88ca25 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -119,11 +119,11 @@ closes it. Emitted when dragged files are dropped in the tray icon. -### Event: 'drag-entered' _OS X_ +### Event: 'drag-enter' _OS X_ Emitted when a drag operation enters the tray icon. -### Event: 'drag-exited' _OS X_ +### Event: 'drag-leave' _OS X_ Emitted when a drag operation exits the tray icon. From d1e8e71e3f786199db5ce843475775ddcc88634f Mon Sep 17 00:00:00 2001 From: Nishanth Shanmugham Date: Tue, 10 Nov 2015 10:02:50 -0600 Subject: [PATCH 449/738] Tray: Add drag-end and drop events --- atom/browser/api/atom_api_tray.cc | 8 ++++++++ atom/browser/api/atom_api_tray.h | 2 ++ atom/browser/ui/tray_icon.cc | 8 ++++++++ atom/browser/ui/tray_icon.h | 2 ++ atom/browser/ui/tray_icon_cocoa.mm | 9 +++++++++ atom/browser/ui/tray_icon_observer.h | 2 ++ 6 files changed, 31 insertions(+) diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index 00b8eda7b54a..0c24240f223c 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -74,6 +74,10 @@ void Tray::OnBalloonClosed() { Emit("balloon-closed"); } +void Tray::OnDrop() { + Emit("drop"); +} + void Tray::OnDropFiles(const std::vector& files) { Emit("drop-files", files); } @@ -86,6 +90,10 @@ void Tray::OnDragExited() { Emit("drag-leave"); } +void Tray::OnDragEnded() { + Emit("drag-end"); +} + bool Tray::IsDestroyed() const { return !tray_icon_; } diff --git a/atom/browser/api/atom_api_tray.h b/atom/browser/api/atom_api_tray.h index b26796bccedc..d8d6dcead16c 100644 --- a/atom/browser/api/atom_api_tray.h +++ b/atom/browser/api/atom_api_tray.h @@ -48,9 +48,11 @@ class Tray : public mate::TrackableObject, void OnBalloonShow() override; void OnBalloonClicked() override; void OnBalloonClosed() override; + void OnDrop() override; void OnDropFiles(const std::vector& files) override; void OnDragEntered() override; void OnDragExited() override; + void OnDragEnded() override; // mate::Wrappable: bool IsDestroyed() const override; diff --git a/atom/browser/ui/tray_icon.cc b/atom/browser/ui/tray_icon.cc index bc69b6e72759..1696aab276b1 100644 --- a/atom/browser/ui/tray_icon.cc +++ b/atom/browser/ui/tray_icon.cc @@ -55,6 +55,10 @@ void TrayIcon::NotifyRightClicked(const gfx::Rect& bounds, int modifiers) { OnRightClicked(bounds, modifiers)); } +void TrayIcon::NotifyDrop() { + FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDrop()); +} + void TrayIcon::NotifyDropFiles(const std::vector& files) { FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDropFiles(files)); } @@ -67,4 +71,8 @@ void TrayIcon::NotifyDragExited() { FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDragExited()); } +void TrayIcon::NotifyDragEnded() { + FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDragEnded()); +} + } // namespace atom diff --git a/atom/browser/ui/tray_icon.h b/atom/browser/ui/tray_icon.h index b63d3c48c262..bc29acd8a255 100644 --- a/atom/browser/ui/tray_icon.h +++ b/atom/browser/ui/tray_icon.h @@ -61,9 +61,11 @@ class TrayIcon { void NotifyBalloonClosed(); void NotifyRightClicked(const gfx::Rect& bounds = gfx::Rect(), int modifiers = 0); + void NotifyDrop(); void NotifyDropFiles(const std::vector& files); void NotifyDragEntered(); void NotifyDragExited(); + void NotifyDragEnded(); protected: TrayIcon(); diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index 40505a64d8cd..c373e94519bb 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -262,6 +262,15 @@ const CGFloat kVerticalTitleMargin = 2; trayIcon_->NotifyDragExited(); } +- (void)draggingEnded:(id )sender { + trayIcon_->NotifyDragEnded(); +} + +- (BOOL)prepareForDragOperation:(id )sender { + trayIcon_->NotifyDrop(); + return YES; +} + - (BOOL)performDragOperation:(id )sender { NSPasteboard* pboard = [sender draggingPasteboard]; diff --git a/atom/browser/ui/tray_icon_observer.h b/atom/browser/ui/tray_icon_observer.h index e9a8bd33f1d3..ed421ed85452 100644 --- a/atom/browser/ui/tray_icon_observer.h +++ b/atom/browser/ui/tray_icon_observer.h @@ -22,9 +22,11 @@ class TrayIconObserver { virtual void OnBalloonClicked() {} virtual void OnBalloonClosed() {} virtual void OnRightClicked(const gfx::Rect& bounds, int modifiers) {} + virtual void OnDrop() {} virtual void OnDropFiles(const std::vector& files) {} virtual void OnDragEntered() {} virtual void OnDragExited() {} + virtual void OnDragEnded() {} protected: virtual ~TrayIconObserver() {} From ed179ecf03fcfb40daeacd1b35621989dc65322b Mon Sep 17 00:00:00 2001 From: Nishanth Shanmugham Date: Tue, 10 Nov 2015 10:14:55 -0600 Subject: [PATCH 450/738] docs: Update tray docs with drop and drag-end events --- docs/api/tray.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/api/tray.md b/docs/api/tray.md index 37e17d88ca25..47f02c5478fa 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -112,6 +112,10 @@ Emitted when the tray balloon is clicked. Emitted when the tray balloon is closed because of timeout or user manually closes it. +### Event: 'drop' _OS X_ + +Emitted when any dragged items are dropped on the tray icon. + ### Event: 'drop-files' _OS X_ * `event` @@ -127,6 +131,10 @@ Emitted when a drag operation enters the tray icon. Emitted when a drag operation exits the tray icon. +### Event: 'drag-end' _OS X_ + +Emitted when a drag operation ends on the tray or ends at another location. + ## Methods The `Tray` module has the following methods: From 916671d4d2af9b5a9dcfdc6f67ef3a646d638ded Mon Sep 17 00:00:00 2001 From: Ming Luo Date: Tue, 10 Nov 2015 14:55:00 -0500 Subject: [PATCH 451/738] Suggest adding arguments when running webdriver --- docs/tutorial/using-selenium-and-webdriver.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/tutorial/using-selenium-and-webdriver.md b/docs/tutorial/using-selenium-and-webdriver.md index b87f8f11dac9..867e452442b3 100644 --- a/docs/tutorial/using-selenium-and-webdriver.md +++ b/docs/tutorial/using-selenium-and-webdriver.md @@ -46,9 +46,12 @@ var webdriver = require('selenium-webdriver'); var driver = new webdriver.Builder() // The "9515" is the port opened by chrome driver. .usingServer('http://localhost:9515') - .withCapabilities({chromeOptions: { - // Here is the path to your Electron binary. - binary: '/Path-to-Your-App.app/Contents/MacOS/Atom'}}) + .withCapabilities({ + chromeOptions: { + // Here is the path to your Electron binary. + binary: '/Path-to-Your-App.app/Contents/MacOS/Atom', + } + }) .forBrowser('electron') .build(); @@ -96,7 +99,10 @@ var options = { port: 9515, // "9515" is the port opened by chrome driver. desiredCapabilities: { browserName: 'chrome', - chromeOptions: {binary: '/Path-to-Your-App.app/Electron'} // Path to your Electron binary. + chromeOptions: { + binary: '/Path-to-Your-App/electron', // Path to your Electron binary. + args: [/* cli arguments */] // Optional, perhaps 'app=' + /path/to/your/app/ + } } }; @@ -119,4 +125,8 @@ To test your application without rebuilding Electron, simply [place](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md) your app source into Electron's resource directory. +Alternatively, pass an argument to run with your electron binary that points to +your app's folder. This eliminates the need to copy-paste your app into +Electron's resource directory. + [chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/ From b611154f4330d7dc67dd4de8dcdb59972390876c Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 11 Nov 2015 09:03:49 +0900 Subject: [PATCH 452/738] Standardize the webContents object name --- docs/api/ipc-main.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/ipc-main.md b/docs/api/ipc-main.md index 4f3d6ebc3bf7..f74c70426a5c 100644 --- a/docs/api/ipc-main.md +++ b/docs/api/ipc-main.md @@ -7,7 +7,7 @@ a renderer will be emitted to this module. ## Sending Messages It is also possible to send messages from the main process to the renderer -process, see [WebContents.send][webcontents-send] for more information. +process, see [webContents.send][webcontents-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`. @@ -66,6 +66,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][webcontents-send] for more information. +[webContents.send][webcontents-send] for more information. [webcontents-send]: web-contents.md#webcontentssendchannel-args From 319acc1e8afbeec7cb2ab2bedce2ee86284d6a40 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 11 Nov 2015 09:44:33 +0900 Subject: [PATCH 453/738] Update as upstream --- docs-translations/ko-KR/README.md | 4 +- .../ko-KR/api/ipc-main-process.md | 71 ------------------- docs-translations/ko-KR/api/ipc-main.md | 66 +++++++++++++++++ docs-translations/ko-KR/api/ipc-renderer.md | 43 +++++------ docs-translations/ko-KR/api/web-view-tag.md | 10 +-- .../desktop-environment-integration.md | 53 +++++++++++++- .../ko-KR/tutorial/online-offline-events.md | 46 ++++++------ 7 files changed, 171 insertions(+), 122 deletions(-) delete mode 100644 docs-translations/ko-KR/api/ipc-main-process.md create mode 100644 docs-translations/ko-KR/api/ipc-main.md diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index bfe08e5e1032..73df16241528 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -36,7 +36,7 @@ * [content-tracing](api/content-tracing.md) * [dialog](api/dialog.md) * [global-shortcut](api/global-shortcut.md) -* [ipc (main process)](api/ipc-main-process.md) +* [ipc-main](api/ipc-main.md) * [menu](api/menu.md) * [menu-item](api/menu-item.md) * [power-monitor](api/power-monitor.md) @@ -48,7 +48,7 @@ ### 랜더러 프로세스에서 사용할 수 있는 모듈 (웹 페이지): -* [ipc (renderer)](api/ipc-renderer.md) +* [ipc-renderer](api/ipc-renderer.md) * [remote](api/remote.md) * [web-frame](api/web-frame.md) diff --git a/docs-translations/ko-KR/api/ipc-main-process.md b/docs-translations/ko-KR/api/ipc-main-process.md deleted file mode 100644 index ad4e545ce474..000000000000 --- a/docs-translations/ko-KR/api/ipc-main-process.md +++ /dev/null @@ -1,71 +0,0 @@ -# ipc (main process) - -`ipc` (main process) 모듈은 메인 프로세스에서 사용할 때 랜더러 프로세스(웹 페이지)에서 전달된 동기 또는 비동기 메시지를 보내고 받는 방법을 제공합니다. -랜더러 프로세스에서 메시지를 전달하면 이 모듈을 통해 메시지를 받을 수 있습니다. - -## 메시지 전송 - -물론 메인 프로세스에서 랜더러 프로세스로 메시지를 보내는 것도 가능합니다. -자세한 내용은 [WebContents.send](web-contents.md#webcontentssendchannel-args)를 참고하세요. - -- 메시지를 전송할 때 이벤트 이름은 `channel`이 됩니다. -- 메시지에 동기로 응답할 땐 반드시 `event.returnValue`를 설정해야 합니다. -- 메시지를 비동기로 응답할 땐 `event.sender.send(...)` 메서드를 사용할 수 있습니다. - -랜더러 프로세스와 메인 프로세스간에 메시지를 전달하고 받는 예제입니다: - -```javascript -// 메인 프로세스 -var ipc = require('ipc'); -ipc.on('asynchronous-message', function(event, arg) { - console.log(arg); // prints "ping" - event.sender.send('asynchronous-reply', 'pong'); -}); - -ipc.on('synchronous-message', function(event, arg) { - console.log(arg); // prints "ping" - event.returnValue = 'pong'; -}); -``` - -```javascript -// 랜더러 프로세스 (web page) -var ipc = require('ipc'); -console.log(ipc.sendSync('synchronous-message', 'ping')); // prints "pong" - -ipc.on('asynchronous-reply', function(arg) { - console.log(arg); // prints "pong" -}); -ipc.send('asynchronous-message', 'ping'); -``` - -## 메시지 리스닝 - -`ipc` 모듈은 다음과 같은 이벤트 메서드를 가지고 있습니다: - -### `ipc.on(channel, callback)` - -* `channel` String - 이벤트 이름 -* `callback` Function - -이벤트가 발생하면 `callback`에 `event` 객체와 `arg` 메시지가 포함되어 호출됩니다. - -## IPC Events - -`callback`에서 전달된 `event` 객체는 다음과 같은 메서드와 속성을 가지고 있습니다: - -### `Event.returnValue` - -이 메시지를 지정하면 동기 메시지를 전달합니다. - -### `Event.sender` - -메시지를 보낸 `WebContents` 객체를 반환합니다. - -### `Event.sender.send(channel[, arg1][, arg2][, ...])` - -* `channel` String - The event name. -* `arg` (optional) - -랜더러 프로세스로 비동기 메시지를 전달합니다. -옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다. diff --git a/docs-translations/ko-KR/api/ipc-main.md b/docs-translations/ko-KR/api/ipc-main.md new file mode 100644 index 000000000000..cecbf980e720 --- /dev/null +++ b/docs-translations/ko-KR/api/ipc-main.md @@ -0,0 +1,66 @@ +# ipcMain + +`ipcMain` 모듈은 메인 프로세스에서 사용할 때 랜더러 프로세스(웹 페이지)에서 전달된 동기/비동기 메시지를 주고 받는 방법을 제공합니다. +랜더러 프로세스에서 메시지를 전달하면 이 모듈을 통해 메시지를 받을 수 있습니다. + +## 메시지 전송 + +물론 메시지를 받는 것 말고도 메인 프로세스에서 랜더러 프로세스로 보내는 것도 가능합니다. +자세한 내용은 [webContents.send](web-contents.md#webcontentssendchannel-args)를 참고하세요. + +* 메시지를 전송할 때 이벤트 이름은 `channel`이 됩니다. +* 메시지에 동기로 응답할 땐 반드시 `event.returnValue`를 설정해야 합니다. +* 메시지를 비동기로 응답할 땐 `event.sender.send(...)` 메서드를 사용할 수 있습니다. + +다음 예제는 랜더러 프로세스와 메인 프로세스간에 메시지를 전달하고 받는 예제입니다: + +```javascript +// 메인 프로세스 +var ipc = require('ipc'); +ipc.on('asynchronous-message', function(event, arg) { + console.log(arg); // prints "ping" + event.sender.send('asynchronous-reply', 'pong'); +}); + +ipc.on('synchronous-message', function(event, arg) { + console.log(arg); // prints "ping" + event.returnValue = 'pong'; +}); +``` + +```javascript +// 랜더러 프로세스 (웹 페이지) +var ipc = require('ipc'); +console.log(ipc.sendSync('synchronous-message', 'ping')); // prints "pong" + +ipc.on('asynchronous-reply', function(arg) { + console.log(arg); // prints "pong" +}); +ipc.send('asynchronous-message', 'ping'); +``` + +## 메시지 리스닝 + +`ipcMain`은 다음과 같은 이벤트 리스닝 메서드를 가지고 있습니다: + +### `ipc.on(channel, callback)` + +* `channel` String - 이벤트 이름 +* `callback` Function + +이벤트가 발생하면 `event` 객체와 `arg` 메시지와 함께 `callback`이 호출됩니다. + +## IPC 이벤트 + +`callback`에서 전달된 `event` 객체는 다음과 같은 메서드와 속성을 가지고 있습니다: + +### `Event.returnValue` + +이 메시지를 지정하면 동기 메시지를 전달합니다. + +### `Event.sender` + +메시지를 보낸 `webContents` 객체를 반환합니다. `event.sender.send` 메서드를 통해 비동기로 메시지를 전달할 수 있습니다. +자세한 내용은 [webContents.send][webcontents-send]를 참고하세요. + +[webcontents-send]: web-contents.md#webcontentssendchannel-args diff --git a/docs-translations/ko-KR/api/ipc-renderer.md b/docs-translations/ko-KR/api/ipc-renderer.md index 67864c4e1157..28442a29073a 100644 --- a/docs-translations/ko-KR/api/ipc-renderer.md +++ b/docs-translations/ko-KR/api/ipc-renderer.md @@ -1,45 +1,48 @@ -# ipc (renderer) +# ipcRenderer -`ipc` (renderer) 모듈은 메인 프로세스로 동기 또는 비동기 메시지를 보내고 받는 방법을 제공합니다. -물론 메인 프로세스로부터 받은 메시지에 응답할 수도 있습니다. +`ipcRenderer` 모듈은 랜더러 프로세스에서 메인 프로세스로 동기/비동기 메시지를 주고 받는 방법을 제공합니다. +또한 메인 프로세스로부터 받은 메시지에 응답할 수도 있습니다. -**참고:** 만약 랜더러 프로세스에서 메인 프로세스의 모듈을 직접적 사용하고 싶다면 [remote](remote.md) 모듈을 사용하는 것을 고려해보는 것이 좋습니다. +[ipcMain](ipc-main.md)에서 코드 예제를 확인할 수 있습니다. -[ipc (main process)](ipc-main-process.md)에서 예제를 확인 할 수 있습니다. +## 메시지 리스닝 -## Methods +`ipcRenderer`는 다음과 같은 이벤트 리스닝 메서드를 가지고 있습니다: -`ipc` 모듈은 다음과 같은 메서드를 가지고 있습니다: +### `ipcRenderer.on(channel, callback)` -**참고:** 이 메소드들을 사용하여 `message`를 보낼 땐 반드시 메인 프로세스의 -[`ipc (main process)`](ipc-main-process.md) 모듈에서도 이벤트 리스너를 등록해 두어야 합니다. +* `channel` String - 이벤트 이름 +* `callback` Function -### `ipc.send(channel[, arg1][, arg2][, ...])` +이벤트가 일어나면 `event` 객체와 임의의 인자와 함께 `callback` 함수가 호출됩니다. + +## 메시지 보내기 + +`ipcRenderer`는 다음과 같은 메시지 전송 메서드를 가지고 있습니다: + +### `ipcRenderer.send(channel[, arg1][, arg2][, ...])` * `channel` String - 이벤트 이름 * `arg` (optional) -`channel`을 통해 메인 프로세스에 비동기 메시지를 보냅니다. -옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다. -메인 프로세스는 `ipc`를 통해 `channel` 이벤트를 리스닝 할 수 있습니다. +`channel`을 통해 메인 프로세스에 비동기 메시지를 보냅니다. 그리고 필요에 따라 임의의 인자를 사용할 수도 있습니다. +메인 프로세스는 `ipcMain` 모듈의 `channel` 이벤트를 통해 이벤트를 리스닝 할 수 있습니다. -### `ipc.sendSync(channel[, arg1][, arg2][, ...])` +### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])` * `channel` String - 이벤트 이름 * `arg` (optional) -`channel`을 통해 메인 프로세스에 동기 메시지를 보냅니다. -옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다. +`channel`을 통해 메인 프로세스에 동기 메시지를 보냅니다. 그리고 필요에 따라 임의의 인자를 사용할 수도 있습니다. 메인 프로세스는 `ipc`를 통해 `channel` 이벤트를 리스닝 할 수 있습니다. 메인 프로세스에선 `ipc` 모듈의 `channel` 이벤트를 통해 받은 `event.returnValue`로 회신 할 수 있습니다. -**참고:** 동기 메시징은 모든 랜더러 프로세스의 작업을 일시 중단시킵니다. 이 메서드를 사용하는 것을 권장하지 않습니다. +__참고:__ 동기 메서드는 모든 랜더러 프로세스의 작업을 일시 중단시킵니다. 사용 목적이 확실하지 않다면 사용하지 않는 것이 좋습니다. -### `ipc.sendToHost(channel[, arg1][, arg2][, ...])` +### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])` * `channel` String - 이벤트 이름 * `arg` (optional) -`ipc.send`와 비슷하지만 이벤트를 메인 프로세스 대신 호스트 페이지내의 ``로 보냅니다. -옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다. +`ipcRenderer.send`와 비슷하지만 이벤트를 메인 프로세스 대신 호스트 페이지내의 `` 요소로 보냅니다. diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index 69b94465aede..bb9a1305c8a9 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -333,15 +333,15 @@ Webview 페이지를 인쇄합니다. `webContents.print([options])` 메서드 Webview 페이지를 PDF 형식으로 인쇄합니다. `webContents.printToPDF(options, callback)` 메서드와 같습니다. -### `.send(channel[, args...])` +### `.send(channel[, arg1][, arg2][, ...])` * `channel` String * `args` (optional) -`channel`을 통해 페이지에 `args` 비동기 메시지를 보냅니다. -페이지에선 `ipc` 모듈의 `channel` 이벤트를 사용하면 이 메시지를 받을 수 있습니다. +`channel`을 통해 랜더러 프로세스로 비동기 메시지를 보냅니다. 또한 `args`를 지정하여 임의의 인자를 보낼 수도 있습니다. +랜더러 프로세스는 `ipcRenderer` 모듈의 `channel` 이벤트로 이 메시지를 받아 처리할 수 있습니다. -예제는 [WebContents.send](web-contents.md#webcontentssendchannel-args)를 참고하세요. +예제는 [webContents.send](web-contents.md#webcontentssendchannel-args)를 참고하세요. ### `.sendInputEvent(event)` @@ -349,7 +349,7 @@ Webview 페이지를 PDF 형식으로 인쇄합니다. `webContents.printToPDF(o 페이지에 input `event`를 보냅니다. -`event` 객체에 대해 자세한 내용을 알아보려면 [WebContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent)를 참고하세요. +`event` 객체에 대해 자세히 알아보려면 [webContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent)를 참고하세요. ## DOM 이벤트 diff --git a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md index b721f5a4a358..1212cbb9c433 100644 --- a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md +++ b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md @@ -3,7 +3,57 @@ 어플리케이션 배포의 대상이 되는 서로 다른 운영체제 시스템의 환경에 맞춰 어플리케이션의 기능을 통합할 수 있습니다. 예를 들어 Windows에선 태스크바의 JumpList에 바로가기를 추가할 수 있고 Mac(OS X)에선 dock 메뉴에 커스텀 메뉴를 추가할 수 있습니다. -이 가이드는 Electron API를 이용하여 각 운영체제 시스템의 기능을 활용하는 방법을 설명합니다. +이 문서는 Electron API를 이용하여 각 운영체제 시스템의 기능을 활용하는 방법을 설명합니다. + +## 데스크톱 알림 (Windows, Linux, OS X) + +Windows, Linux, OS X 운영체제 모두 기본적으로 어플리케이션에서 유저에게 알림 보낼 수 있는 방법을 제공합니다. +Electron은 HTML5 Notification API](https://notifications.spec.whatwg.org/)를 통해 개발자가 +편리하게 데스크톱 알림을 사용할 수 있는 기능을 제공합니다. 데스크톱 알림은 운영체제의 네이티브 알림 API를 사용하여 표시합니다. + +```javascript +var myNotificiation = new Notification('Title', { + body: 'Lorem Ipsum Dolor Sit Amet' +}); + +myNotification.onclick = function () { + console.log('Notification clicked') +} +``` + +위 코드를 통해 생성한 데스크톱 알림은 각 운영체제 모두 비슷한 사용자 경험을 제공합니다. 하지만 몇 가지 다른 점들이 있습니다. + +### Windows + +* Windows 10에선 "아무 문제 없이 잘" 작동합니다. +* Windows 8.1과 8에선 [Application User Model ID][app-user-model-id]로 바로가기를 만들어 놔야 합니다. +이 바로가기는 반드시 시작 화면에 설치되어 있어야 합니다. 참고로 반드시 시작 화면에 고정 할 필요는 없습니다. +* Windows 7과 그 이하 버전은 데스크톱 알림을 지원하지 않습니다. 혹시 "풍선 알림" 기능을 찾는다면 [Tray API](tray-balloon)를 사용하세요. + +이미지를 데스크톱 알림에 사용하려면 알림 옵션의 `icon` 속성에 로컬 이미지 파일(`png` 권장)을 지정하면 됩니다. +데스크톱 알림은 잘못된 경로를 지정하거나 `http/https` 기반의 URL을 지정해도 이미지가 보이지 않을 뿐 정상 작동합니다. + +```javascript +new Notification('Title', { + body: 'Notification with icon', + icon: 'file:///C:/Users/feriese/Desktop/icon.png' +}); +``` + +또한 `body`의 최대 길이는 250자 입니다. Windows 개발팀에선 알림 문자열을 200자 이하로 유지하는 것을 권장합니다. + +### Linux + +데스크톱 알림의 구현으로 `libnotify`를 사용합니다. 따라서 [Desktop Notifications Specification][notification-spec]을 +따르는 모든 데스크탑 환경에서 데스크톱 알림 기능을 사용할 수 있습니다. Cinnamon, Enlightenment, Unity, GNOME, KDE등을 지원합니다. + +### OS X + +OS X에서의 데스크톱 알림은 아주 직관적입니다. 하지만 데스크톱 알림을 사용할 땐 +[Apple's Human Interface guidelines regarding notifications](https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/NotificationCenter.html) +가이드를 고려해야 합니다. + +참고로 데스크롭 알림의 최대 길이는 256 바이트 입니다. 길이가 초과할 경우 초과한 글자가 잘립니다. ## 최근 사용한 문서 (Windows & OS X) @@ -220,3 +270,4 @@ window.setDocumentEdited(true); [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 diff --git a/docs-translations/ko-KR/tutorial/online-offline-events.md b/docs-translations/ko-KR/tutorial/online-offline-events.md index cc8ae4855d55..5950d40525e2 100644 --- a/docs-translations/ko-KR/tutorial/online-offline-events.md +++ b/docs-translations/ko-KR/tutorial/online-offline-events.md @@ -20,18 +20,18 @@ _online-status.html_ ```html - - - + alertOnlineStatus(); + + ``` @@ -44,7 +44,7 @@ _main.js_ ```javascript var app = require('app'); -var ipc = require('ipc'); +var ipcMain = require('ipc-main'); var BrowserWindow = require('browser-window'); var onlineStatusWindow; @@ -53,7 +53,7 @@ app.on('ready', function() { onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); }); -ipc.on('online-status-changed', function(event, status) { +ipcMain.on('online-status-changed', function(event, status) { console.log(status); }); ``` @@ -63,18 +63,18 @@ _online-status.html_ ```html - - - + updateOnlineStatus(); + + ``` From d37aa8bed9b3131cd254a5cf396da9a28534d9db Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 22:17:27 +0800 Subject: [PATCH 454/738] Reorder switches --- atom/browser/api/atom_api_window.cc | 3 ++ atom/common/options_switches.cc | 63 +++++++++++++++-------------- atom/common/options_switches.h | 25 ++++++------ 3 files changed, 48 insertions(+), 43 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 497b5a6930ff..bd24b444db3a 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -60,7 +60,10 @@ void OnCapturePageDone( callback.Run(gfx::Image::CreateFrom1xBitmap(bitmap)); } +// Convert min-width to minWidth recursively in the dictionary. + #if defined(OS_WIN) +// Convert binary data to Buffer. v8::Local ToBuffer(v8::Isolate* isolate, void* val, int size) { auto buffer = node::Buffer::New(isolate, static_cast(val), size); if (buffer.IsEmpty()) diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 903c15ee6dd1..9fe38cdfd352 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -34,8 +34,6 @@ const char kKiosk[] = "kiosk"; // Make windows stays on the top of all other windows. const char kAlwaysOnTop[] = "always-on-top"; -const char kNodeIntegration[] = "node-integration"; - // Enable the NSView to accept first mouse event. const char kAcceptFirstMouse[] = "accept-first-mouse"; @@ -45,12 +43,6 @@ const char kUseContentSize[] = "use-content-size"; // The requested title bar style for the window const char kTitleBarStyle[] = "title-bar-style"; -// The WebPreferences. -const char kWebPreferences[] = "web-preferences"; - -// The factor of which page should be zoomed. -const char kZoomFactor[] = "zoom-factor"; - // The menu bar is hidden unless "Alt" is pressed. const char kAutoHideMenuBar[] = "auto-hide-menu-bar"; @@ -60,27 +52,6 @@ const char kEnableLargerThanScreen[] = "enable-larger-than-screen"; // Forces to use dark theme on Linux. const char kDarkTheme[] = "dark-theme"; -// Enable DirectWrite on Windows. -const char kDirectWrite[] = "direct-write"; - -// Enable plugins. -const char kEnablePlugins[] = "enable-plugins"; - -// Ppapi Flash path. -const char kPpapiFlashPath[] = "ppapi-flash-path"; - -// Ppapi Flash version. -const char kPpapiFlashVersion[] = "ppapi-flash-version"; - -// Instancd ID of guest WebContents. -const char kGuestInstanceID[] = "guest-instance-id"; - -// Script that will be loaded by guest WebContents before other scripts. -const char kPreloadScript[] = "preload"; - -// Like --preload, but the passed argument is an URL. -const char kPreloadUrl[] = "preload-url"; - // Whether the window should be transparent. const char kTransparent[] = "transparent"; @@ -96,8 +67,23 @@ const char kStandardWindow[] = "standard-window"; // Default browser window background color. const char kBackgroundColor[] = "background-color"; -// Path to client certificate. -const char kClientCertificate[] = "client-certificate"; +// The WebPreferences. +const char kWebPreferences[] = "web-preferences"; + +// The factor of which page should be zoomed. +const char kZoomFactor[] = "zoom-factor"; + +// Script that will be loaded by guest WebContents before other scripts. +const char kPreloadScript[] = "preload"; + +// Like --preload, but the passed argument is an URL. +const char kPreloadUrl[] = "preload-url"; + +// Enable the node integration. +const char kNodeIntegration[] = "node-integration"; + +// Instancd ID of guest WebContents. +const char kGuestInstanceID[] = "guest-instance-id"; // Web runtime features. const char kExperimentalFeatures[] = "experimental-features"; @@ -106,9 +92,24 @@ const char kOverlayScrollbars[] = "overlay-scrollbars"; const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video"; const char kSharedWorker[] = "shared-worker"; +// Enable plugins. +const char kEnablePlugins[] = "enable-plugins"; + +// Ppapi Flash path. +const char kPpapiFlashPath[] = "ppapi-flash-path"; + +// Ppapi Flash version. +const char kPpapiFlashVersion[] = "ppapi-flash-version"; + // Set page visiblity to always visible. const char kPageVisibility[] = "page-visibility"; +// Enable DirectWrite on Windows. +const char kDirectWrite[] = "direct-write"; + +// Path to client certificate. +const char kClientCertificate[] = "client-certificate"; + // Disable HTTP cache. const char kDisableHttpCache[] = "disable-http-cache"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 9887359a502b..9f171836f653 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -27,41 +27,42 @@ extern const char kFullscreen[]; extern const char kSkipTaskbar[]; extern const char kKiosk[]; extern const char kAlwaysOnTop[]; -extern const char kNodeIntegration[]; extern const char kAcceptFirstMouse[]; extern const char kUseContentSize[]; extern const char kTitleBarStyle[]; -extern const char kWebPreferences[]; -extern const char kZoomFactor[]; extern const char kAutoHideMenuBar[]; extern const char kEnableLargerThanScreen[]; extern const char kDarkTheme[]; -extern const char kDirectWrite[]; -extern const char kEnablePlugins[]; -extern const char kPpapiFlashPath[]; -extern const char kPpapiFlashVersion[]; -extern const char kGuestInstanceID[]; -extern const char kPreloadScript[]; -extern const char kPreloadUrl[]; extern const char kTransparent[]; extern const char kType[]; extern const char kDisableAutoHideCursor[]; extern const char kStandardWindow[]; extern const char kBackgroundColor[]; -extern const char kClientCertificate[]; +extern const char kWebPreferences[]; +// WebPreferences. +extern const char kZoomFactor[]; +extern const char kPreloadScript[]; +extern const char kPreloadUrl[]; +extern const char kNodeIntegration[]; +extern const char kGuestInstanceID[]; extern const char kExperimentalFeatures[]; extern const char kExperimentalCanvasFeatures[]; extern const char kOverlayScrollbars[]; extern const char kOverlayFullscreenVideo[]; extern const char kSharedWorker[]; extern const char kPageVisibility[]; +extern const char kDirectWrite[]; +// Following are actually command line switches, should be moved to other files. +extern const char kEnablePlugins[]; +extern const char kPpapiFlashPath[]; +extern const char kPpapiFlashVersion[]; +extern const char kClientCertificate[]; extern const char kDisableHttpCache[]; extern const char kRegisterStandardSchemes[]; extern const char kSSLVersionFallbackMin[]; extern const char kCipherSuiteBlacklist[]; - extern const char kAppUserModelId[]; } // namespace switches From 737e22b003a0a0f943e956b7d92b5216a77cdc5e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 10 Nov 2015 22:23:21 +0800 Subject: [PATCH 455/738] Use minWidth style for options instead of min-width --- atom/browser/lib/guest-view-manager.coffee | 10 ++-- atom/browser/lib/guest-window-manager.coffee | 4 +- atom/browser/web_contents_preferences.cc | 8 ++-- atom/common/options_switches.cc | 50 ++++++++++---------- atom/renderer/lib/init.coffee | 4 +- spec/chromium-spec.coffee | 2 +- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index c99b681498e4..8b2658a180cf 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -118,11 +118,11 @@ attachGuest = (embedder, elementInstanceId, guestInstanceId, params) -> destroyGuest embedder, oldGuestInstanceId webPreferences = - 'guest-instance-id': guestInstanceId - 'node-integration': params.nodeintegration ? false - 'plugins': params.plugins - 'web-security': !params.disablewebsecurity - webPreferences['preload-url'] = params.preload if params.preload + guestInstanceId: guestInstanceId + nodeIntegration: params.nodeintegration ? false + plugins: params.plugins + webSecurity: !params.disablewebsecurity + webPreferences.preloadUrl = params.preload if params.preload webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest, webPreferences guest.attachParams = params diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index fe01c6fa771e..f2c5fe3a43cd 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -11,8 +11,8 @@ mergeBrowserWindowOptions = (embedder, options) -> options.__proto__ = embedder.browserWindowOptions else # Or only inherit web-preferences if it is a webview. - options['web-preferences'] ?= {} - options['web-preferences'].__proto__ = embedder.getWebPreferences() + options.webPreferences ?= {} + options.webPreferences.__proto__ = embedder.getWebPreferences() options # Create a new guest created by |embedder| with |options|. diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 14e32353af65..a0088221ba2c 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -135,21 +135,21 @@ void WebContentsPreferences::OverrideWebkitPrefs( prefs->images_enabled = b; if (self->web_preferences_.GetBoolean("java", &b)) prefs->java_enabled = b; - if (self->web_preferences_.GetBoolean("text-areas-are-resizable", &b)) + if (self->web_preferences_.GetBoolean("textAreasAreResizable", &b)) prefs->text_areas_are_resizable = b; if (self->web_preferences_.GetBoolean("webgl", &b)) prefs->experimental_webgl_enabled = b; if (self->web_preferences_.GetBoolean("webaudio", &b)) prefs->webaudio_enabled = b; - if (self->web_preferences_.GetBoolean("web-security", &b)) { + if (self->web_preferences_.GetBoolean("webSecurity", &b)) { prefs->web_security_enabled = b; prefs->allow_displaying_insecure_content = !b; prefs->allow_running_insecure_content = !b; } - if (self->web_preferences_.GetBoolean("allow-displaying-insecure-content", + if (self->web_preferences_.GetBoolean("allowDisplayingInsecureContent", &b)) prefs->allow_displaying_insecure_content = b; - if (self->web_preferences_.GetBoolean("allow-running-insecure-content", &b)) + if (self->web_preferences_.GetBoolean("allowRunningInsecureContent", &b)) prefs->allow_running_insecure_content = b; } diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 9fe38cdfd352..9b3b50b4bf31 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -17,40 +17,40 @@ const char kX[] = "x"; const char kY[] = "y"; const char kWidth[] = "width"; const char kHeight[] = "height"; -const char kMinWidth[] = "min-width"; -const char kMinHeight[] = "min-height"; -const char kMaxWidth[] = "max-width"; -const char kMaxHeight[] = "max-height"; +const char kMinWidth[] = "minWidth"; +const char kMinHeight[] = "minHeight"; +const char kMaxWidth[] = "maxWidth"; +const char kMaxHeight[] = "maxHeight"; const char kResizable[] = "resizable"; const char kFullscreen[] = "fullscreen"; // Whether the window should show in taskbar. -const char kSkipTaskbar[] = "skip-taskbar"; +const char kSkipTaskbar[] = "skipTaskbar"; // Start with the kiosk mode, see Opera's page for description: // http://www.opera.com/support/mastering/kiosk/ const char kKiosk[] = "kiosk"; // Make windows stays on the top of all other windows. -const char kAlwaysOnTop[] = "always-on-top"; +const char kAlwaysOnTop[] = "alwaysOnTop"; // Enable the NSView to accept first mouse event. -const char kAcceptFirstMouse[] = "accept-first-mouse"; +const char kAcceptFirstMouse[] = "acceptFirstMouse"; // Whether window size should include window frame. -const char kUseContentSize[] = "use-content-size"; +const char kUseContentSize[] = "useContentSize"; // The requested title bar style for the window -const char kTitleBarStyle[] = "title-bar-style"; +const char kTitleBarStyle[] = "titleBarStyle"; // The menu bar is hidden unless "Alt" is pressed. -const char kAutoHideMenuBar[] = "auto-hide-menu-bar"; +const char kAutoHideMenuBar[] = "autoHideMenuBar"; // Enable window to be resized larger than screen. -const char kEnableLargerThanScreen[] = "enable-larger-than-screen"; +const char kEnableLargerThanScreen[] = "enableLargerThanScreen"; // Forces to use dark theme on Linux. -const char kDarkTheme[] = "dark-theme"; +const char kDarkTheme[] = "darkTheme"; // Whether the window should be transparent. const char kTransparent[] = "transparent"; @@ -59,38 +59,38 @@ const char kTransparent[] = "transparent"; const char kType[] = "type"; // Disable auto-hiding cursor. -const char kDisableAutoHideCursor[] = "disable-auto-hide-cursor"; +const char kDisableAutoHideCursor[] = "disableAutoHideCursor"; // Use the OS X's standard window instead of the textured window. -const char kStandardWindow[] = "standard-window"; +const char kStandardWindow[] = "standardWindow"; // Default browser window background color. -const char kBackgroundColor[] = "background-color"; +const char kBackgroundColor[] = "backgroundColor"; // The WebPreferences. -const char kWebPreferences[] = "web-preferences"; +const char kWebPreferences[] = "webPreferences"; // The factor of which page should be zoomed. -const char kZoomFactor[] = "zoom-factor"; +const char kZoomFactor[] = "zoomFactor"; // Script that will be loaded by guest WebContents before other scripts. const char kPreloadScript[] = "preload"; // Like --preload, but the passed argument is an URL. -const char kPreloadUrl[] = "preload-url"; +const char kPreloadUrl[] = "preloadUrl"; // Enable the node integration. -const char kNodeIntegration[] = "node-integration"; +const char kNodeIntegration[] = "nodeIntegration"; // Instancd ID of guest WebContents. -const char kGuestInstanceID[] = "guest-instance-id"; +const char kGuestInstanceID[] = "guestInstanceId"; // Web runtime features. -const char kExperimentalFeatures[] = "experimental-features"; -const char kExperimentalCanvasFeatures[] = "experimental-canvas-features"; -const char kOverlayScrollbars[] = "overlay-scrollbars"; -const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video"; -const char kSharedWorker[] = "shared-worker"; +const char kExperimentalFeatures[] = "experimentalFeatures"; +const char kExperimentalCanvasFeatures[] = "experimentalCanvasFeatures"; +const char kOverlayScrollbars[] = "overlayScrollbars"; +const char kOverlayFullscreenVideo[] = "overlayFullscreenVideo"; +const char kSharedWorker[] = "sharedWorker"; // Enable plugins. const char kEnablePlugins[] = "enable-plugins"; diff --git a/atom/renderer/lib/init.coffee b/atom/renderer/lib/init.coffee index b7224b39aeed..ed3482fb972b 100644 --- a/atom/renderer/lib/init.coffee +++ b/atom/renderer/lib/init.coffee @@ -25,10 +25,10 @@ v8Util.setHiddenValue global, 'ipc', new events.EventEmitter # Process command line arguments. nodeIntegration = 'false' for arg in process.argv - if arg.indexOf('--guest-instance-id=') == 0 + if arg.indexOf('--guestInstanceId=') == 0 # This is a guest web view. process.guestInstanceId = parseInt arg.substr(arg.indexOf('=') + 1) - else if arg.indexOf('--node-integration=') == 0 + else if arg.indexOf('--nodeIntegration=') == 0 nodeIntegration = arg.substr arg.indexOf('=') + 1 else if arg.indexOf('--preload=') == 0 preloadScript = arg.substr arg.indexOf('=') + 1 diff --git a/spec/chromium-spec.coffee b/spec/chromium-spec.coffee index a034f9378235..09bae3d92e7e 100644 --- a/spec/chromium-spec.coffee +++ b/spec/chromium-spec.coffee @@ -70,7 +70,7 @@ describe 'chromium feature', -> b.close() done() window.addEventListener 'message', listener - b = window.open "file://#{fixtures}/pages/window-opener-node.html", '', 'node-integration=no,show=no' + b = window.open "file://#{fixtures}/pages/window-opener-node.html", '', 'nodeIntegration=no,show=no' it 'inherit options of parent window', (done) -> listener = (event) -> From 5cca947f4d94e1fdd6c8d50a6b362cf5a6937f66 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Nov 2015 00:26:17 +0800 Subject: [PATCH 456/738] Remove unneeded override code --- atom/renderer/lib/override.coffee | 6 ------ 1 file changed, 6 deletions(-) diff --git a/atom/renderer/lib/override.coffee b/atom/renderer/lib/override.coffee index e54a0e9685c2..729de8ed64d2 100644 --- a/atom/renderer/lib/override.coffee +++ b/atom/renderer/lib/override.coffee @@ -60,12 +60,6 @@ window.open = (url, frameName='', features='') -> (options[name] = parseInt(options[name], 10) if options[name]?) for name in ints - # Inherit the node-integration option of current window. - unless options['node-integration']? - for arg in process.argv when arg.indexOf('--node-integration=') is 0 - options['node-integration'] = arg.substr(-4) is 'true' - break - guestId = ipc.sendSync 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', url, frameName, options if guestId new BrowserWindowProxy(guestId) From 960d325a58f636a676d3e67251542a1624785536 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Nov 2015 00:26:46 +0800 Subject: [PATCH 457/738] Be compatible with old BrowserWindow options --- atom/browser/api/atom_api_window.cc | 54 +++++++++++++++++++++++++++-- vendor/native_mate | 2 +- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index bd24b444db3a..048a8eff1df9 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "atom/browser/api/atom_api_window.h" +#include "atom/common/native_mate_converters/value_converter.h" #include "atom/browser/api/atom_api_menu.h" #include "atom/browser/api/atom_api_web_contents.h" @@ -60,10 +61,54 @@ void OnCapturePageDone( callback.Run(gfx::Image::CreateFrom1xBitmap(bitmap)); } -// Convert min-width to minWidth recursively in the dictionary. +// Converts min-width to minWidth, returns false if no conversion is needed. +bool TranslateOldKey(const std::string& key, std::string* new_key) { + if (key.find('-') == std::string::npos) + return false; + new_key->reserve(key.size()); + bool next_upper_case = false; + for (char c : key) { + if (c == '-') { + next_upper_case = true; + } else if (next_upper_case) { + new_key->push_back(base::ToUpperASCII(c)); + next_upper_case = false; + } else { + new_key->push_back(c); + } + } + return true; +} + +// Converts min-width to minWidth recursively in the dictionary. +void TranslateOldOptions(v8::Isolate* isolate, v8::Local options) { + auto context = isolate->GetCurrentContext(); + auto maybe_keys = options->GetOwnPropertyNames(context); + if (maybe_keys.IsEmpty()) + return; + std::vector keys; + if (!mate::ConvertFromV8(isolate, maybe_keys.ToLocalChecked(), &keys)) + return; + mate::Dictionary dict(isolate, options); + for (const auto& key : keys) { + v8::Local value; + if (!dict.Get(key, &value)) // Shouldn't happen, but guard it anyway. + continue; + // Go recursively. + v8::Local sub_options; + if (mate::ConvertFromV8(isolate, value, &sub_options)) + TranslateOldOptions(isolate, sub_options); + // Translate key. + std::string new_key; + if (TranslateOldKey(key, &new_key)) { + dict.Set(new_key, value); + dict.Delete(key); + } + } +} #if defined(OS_WIN) -// Convert binary data to Buffer. +// 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); if (buffer.IsEmpty()) @@ -77,7 +122,10 @@ v8::Local ToBuffer(v8::Isolate* isolate, void* val, int size) { Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) { - // Use options['web-preferences'] to create WebContents. + // Be compatible with old style field names like min-width. + TranslateOldOptions(isolate, options.GetHandle()); + + // Use options.webPreferences to create WebContents. mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate); options.Get(switches::kWebPreferences, &web_preferences); diff --git a/vendor/native_mate b/vendor/native_mate index 21cda4e7fcff..93984941005b 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit 21cda4e7fcff592f33f989c1fea575658281711d +Subproject commit 93984941005bab194a2d47aff655d525c064efcb From b807685453b06d3192a788c7fa24ca0fceff8f14 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Nov 2015 00:27:08 +0800 Subject: [PATCH 458/738] Deep copy the options Otherwise a window's options is possible to be affected by others. --- atom/browser/lib/guest-window-manager.coffee | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index f2c5fe3a43cd..3ed8932d444c 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -4,15 +4,24 @@ BrowserWindow = require 'browser-window' frameToGuest = {} +# Copy attribute of |parent| to |child| if it is not defined in |child|. +mergeOptions = (child, parent) -> + for own key, value of parent when key not in child + if typeof value is 'object' + child[key] = mergeOptions {}, value + else + child[key] = value + child + # Merge |options| with the |embedder|'s window's options. mergeBrowserWindowOptions = (embedder, options) -> if embedder.browserWindowOptions? # Inherit the original options if it is a BrowserWindow. - options.__proto__ = embedder.browserWindowOptions + mergeOptions options, embedder.browserWindowOptions else # Or only inherit web-preferences if it is a webview. options.webPreferences ?= {} - options.webPreferences.__proto__ = embedder.getWebPreferences() + mergeOptions options.webPreferences, embedder.getWebPreferences() options # Create a new guest created by |embedder| with |options|. From ba457681b200715068ab0db4e1672ef5e854ff9d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Nov 2015 10:32:25 +0800 Subject: [PATCH 459/738] Avoid storing unrelated things in WebContentsPreferences --- atom/browser/api/atom_api_web_contents.cc | 4 +--- atom/browser/web_contents_preferences.cc | 16 +++++++++++----- atom/browser/web_contents_preferences.h | 6 +++++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 5165877d1670..d67794a91aeb 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -269,9 +269,7 @@ WebContents::WebContents(v8::Isolate* isolate, managed_web_contents()->GetView()->SetDelegate(this); // Save the preferences in C++. - base::DictionaryValue web_preferences; - mate::ConvertFromV8(isolate, options.GetHandle(), &web_preferences); - new WebContentsPreferences(web_contents, &web_preferences); + new WebContentsPreferences(web_contents, options); web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent()); diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index a0088221ba2c..2adb77211b27 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -6,10 +6,12 @@ #include +#include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/options_switches.h" #include "base/command_line.h" #include "base/strings/string_number_conversions.h" #include "content/public/common/web_preferences.h" +#include "native_mate/dictionary.h" #include "net/base/filename_util.h" #if defined(OS_WIN) @@ -36,12 +38,16 @@ const char* kWebRuntimeFeatures[] = { WebContentsPreferences::WebContentsPreferences( content::WebContents* web_contents, - base::DictionaryValue* web_preferences) { - web_preferences_.Swap(web_preferences); - web_contents->SetUserData(UserDataKey(), this); + const mate::Dictionary& web_preferences) { + v8::Isolate* isolate = web_preferences.isolate(); + mate::Dictionary copied(isolate, web_preferences.GetHandle()->Clone()); + // Following fields should not be stored. + copied.Delete("embedder"); + copied.Delete("isGuest"); + copied.Delete("session"); - // The "isGuest" is not a preferences field. - web_preferences_.Remove("isGuest", nullptr); + mate::ConvertFromV8(isolate, copied.GetHandle(), &web_preferences_); + web_contents->SetUserData(UserDataKey(), this); } WebContentsPreferences::~WebContentsPreferences() { diff --git a/atom/browser/web_contents_preferences.h b/atom/browser/web_contents_preferences.h index 3e36df021478..8b04f9ee24e6 100644 --- a/atom/browser/web_contents_preferences.h +++ b/atom/browser/web_contents_preferences.h @@ -16,6 +16,10 @@ namespace content { struct WebPreferences; } +namespace mate { +class Dictionary; +} + namespace atom { // Stores and applies the preferences of WebContents. @@ -31,7 +35,7 @@ class WebContentsPreferences content::WebContents* web_contents, content::WebPreferences* prefs); WebContentsPreferences(content::WebContents* web_contents, - base::DictionaryValue* web_preferences); + const mate::Dictionary& web_preferences); ~WebContentsPreferences() override; // $.extend(|web_preferences_|, |new_web_preferences|). From 60ec1ca3f71d9e3ee08eb9e4b868a492d6073d20 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Nov 2015 10:33:59 +0800 Subject: [PATCH 460/738] Use new styles of browserWindow options --- atom/browser/default_app/default_app.js | 4 ++-- spec/api-browser-window-spec.coffee | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/atom/browser/default_app/default_app.js b/atom/browser/default_app/default_app.js index 2378902b44ec..de8b14d5f4d7 100644 --- a/atom/browser/default_app/default_app.js +++ b/atom/browser/default_app/default_app.js @@ -12,8 +12,8 @@ app.on('ready', function() { mainWindow = new BrowserWindow({ width: 800, height: 600, - 'auto-hide-menu-bar': true, - 'use-content-size': true, + autoHideMenuBar: true, + useContentSize: true, }); mainWindow.loadUrl('file://' + __dirname + '/index.html'); mainWindow.focus(); diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 460a1c1ec17c..4528ab72b660 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -138,10 +138,10 @@ describe 'browser-window module', -> w.setResizable not w.isResizable() assert.deepEqual s, w.getSize() - describe '"use-content-size" option', -> + describe '"useContentSize" option', -> it 'make window created with content size when used', -> w.destroy() - w = new BrowserWindow(show: false, width: 400, height: 400, 'use-content-size': true) + w = new BrowserWindow(show: false, width: 400, height: 400, useContentSize: true) contentSize = w.getContentSize() assert.equal contentSize[0], 400 assert.equal contentSize[1], 400 @@ -153,7 +153,7 @@ describe 'browser-window module', -> it 'works for framless window', -> w.destroy() - w = new BrowserWindow(show: false, frame: false, width: 400, height: 400, 'use-content-size': true) + w = new BrowserWindow(show: false, frame: false, width: 400, height: 400, useContentSize: true) contentSize = w.getContentSize() assert.equal contentSize[0], 400 assert.equal contentSize[1], 400 @@ -167,22 +167,22 @@ describe 'browser-window module', -> it 'creates browser window with hidden title bar', -> w.destroy() - w = new BrowserWindow(show: false, width: 400, height: 400, 'title-bar-style': 'hidden') + w = new BrowserWindow(show: false, width: 400, height: 400, titleBarStyle: 'hidden') contentSize = w.getContentSize() assert.equal contentSize[1], 400 it 'creates browser window with hidden inset title bar', -> w.destroy() - w = new BrowserWindow(show: false, width: 400, height: 400, 'title-bar-style': 'hidden-inset') + w = new BrowserWindow(show: false, width: 400, height: 400, titleBarStyle: 'hidden-inset') contentSize = w.getContentSize() assert.equal contentSize[1], 400 - describe '"enable-larger-than-screen" option', -> + describe '"enableLargerThanScreen" option', -> return if process.platform is 'linux' beforeEach -> w.destroy() - w = new BrowserWindow(show: true, width: 400, height: 400, 'enable-larger-than-screen': true) + w = new BrowserWindow(show: true, width: 400, height: 400, enableLargerThanScreen: true) it 'can move the window out of screen', -> w.setPosition -10, -10 @@ -212,7 +212,7 @@ describe 'browser-window module', -> w.destroy() w = new BrowserWindow show: false - 'web-preferences': + webPreferences: preload: preload w.loadUrl 'file://' + path.join(fixtures, 'api', 'preload.html') @@ -225,9 +225,9 @@ describe 'browser-window module', -> w.destroy() w = new BrowserWindow show: false - 'web-preferences': + webPreferences: preload: preload - 'node-integration': false + nodeIntegration: false w.loadUrl 'file://' + path.join(fixtures, 'api', 'blank.html') describe 'beforeunload handler', -> From f63a4a05b79c063bc81ebd75fc66ae4904c3a758 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Nov 2015 10:37:01 +0800 Subject: [PATCH 461/738] spec: Make the crash-reporter test more reliable --- spec/api-crash-reporter-spec.coffee | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/api-crash-reporter-spec.coffee b/spec/api-crash-reporter-spec.coffee index 5e06cade8cec..6232edfd3b6c 100644 --- a/spec/api-crash-reporter-spec.coffee +++ b/spec/api-crash-reporter-spec.coffee @@ -24,10 +24,15 @@ describe 'crash-reporter module', -> it 'should send minidump when renderer crashes', (done) -> @timeout 120000 + called = false server = http.createServer (req, res) -> server.close() form = new multiparty.Form() form.parse req, (error, fields, files) -> + # This callback can be called for twice sometimes. + return if called + called = true + assert.equal fields['prod'], 'Electron' assert.equal fields['ver'], process.versions['electron'] assert.equal fields['process_type'], 'renderer' From 0e9415a256764a84595489843c12b5f7e80df64f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Nov 2015 22:55:32 +0800 Subject: [PATCH 462/738] docs: More notes on --proxy-server, close #3390 --- docs/api/chrome-command-line-switches.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index 69e785f79e72..96dffb963135 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -33,8 +33,10 @@ Enables remote debugging over HTTP on the specified `port`. ## --proxy-server=`address:port` -Use a specified proxy server, which overrides the system setting. This switch only -affects HTTP and HTTPS requests. +Use a specified proxy server, which overrides the system setting. This switch +only affects requests with HTTP protocol, including HTTPS and WebSocket +requests. It is also noteworthy that not all proxy servers support HTTPS and +WebSocket requests. ## --proxy-pac-url=`url` From 28db51ad8340cb68313bb80893ddf3ae8c9b5a54 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Nov 2015 23:55:43 +0800 Subject: [PATCH 463/738] docs: Update BrowserWindow's options --- docs/api/browser-window.md | 60 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index fbac6b10863b..0499b6355a00 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -33,20 +33,20 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `height` Integer - Window's height. * `x` Integer - Window's left offset from screen. * `y` Integer - Window's top offset from screen. -* `use-content-size` Boolean - The `width` and `height` would be used as web +* `useContentSize` Boolean - The `width` and `height` would be used as web page's size, which means the actual window's size will include window frame's size and be slightly larger. * `center` Boolean - Show window in the center of the screen. -* `min-width` Integer - Window's minimum width. -* `min-height` Integer - Window's minimum height. -* `max-width` Integer - Window's maximum width. -* `max-height` Integer - Window's maximum height. +* `minWidth` Integer - Window's minimum width. +* `minHeight` Integer - Window's minimum height. +* `maxWidth` Integer - Window's maximum width. +* `maxHeight` Integer - Window's maximum height. * `resizable` Boolean - Whether window is resizable. -* `always-on-top` Boolean - Whether the window should always stay on top of +* `alwaysOnTop` Boolean - Whether the window should always stay on top of other windows. * `fullscreen` Boolean - Whether the window should show in fullscreen. When set to `false` the fullscreen button will be hidden or disabled on OS X. -* `skip-taskbar` Boolean - Whether to show the window in taskbar. +* `skipTaskbar` Boolean - Whether to show the window in taskbar. * `kiosk` Boolean - The kiosk mode. * `title` String - Default window title. * `icon` [NativeImage](native-image.md) - The window icon, when omitted on @@ -54,24 +54,24 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `show` Boolean - Whether window should be shown when created. * `frame` Boolean - Specify `false` to create a [Frameless Window](frameless-window.md). -* `accept-first-mouse` Boolean - Whether the web view accepts a single +* `acceptFirstMouse` Boolean - Whether the web view accepts a single mouse-down event that simultaneously activates the window. -* `disable-auto-hide-cursor` Boolean - Whether to hide cursor when typing. -* `auto-hide-menu-bar` Boolean - Auto hide the menu bar unless the `Alt` +* `disableAutoHideCursor` Boolean - Whether to hide cursor when typing. +* `autoHideMenuBar` Boolean - Auto hide the menu bar unless the `Alt` key is pressed. -* `enable-larger-than-screen` Boolean - Enable the window to be resized larger +* `enableLargerThanScreen` Boolean - Enable the window to be resized larger than screen. -* `background-color` String - Window's background color as Hexadecimal value, +* `backgroundColor` String - Window's background color as Hexadecimal value, like `#66CD00` or `#FFF`. This is only implemented on Linux and Windows. -* `dark-theme` Boolean - Forces using dark theme for the window, only works on +* `darkTheme` Boolean - Forces using dark theme for the window, only works on some GTK+3 desktop environments. * `transparent` Boolean - Makes the window [transparent](frameless-window.md). * `type` String - Specifies the type of the window, possible types are `desktop`, `dock`, `toolbar`, `splash`, `notification`. This only works on Linux. -* `standard-window` Boolean - Uses the OS X's standard window instead of the +* `standardWindow` Boolean - Uses the OS X's standard window instead of the textured window. Defaults to `true`. -* `title-bar-style` String, OS X - specifies the style of window title bar. +* `titleBarStyle` String, OS X - specifies the style of window title bar. This option is supported on OS X 10.10 Yosemite and newer. There are three possible values: * `default` or not specified results in the standard gray opaque Mac title @@ -81,8 +81,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. the top left. * `hidden-inset` results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge. -* `web-preferences` Object - Settings of web page's features, properties: - * `node-integration` Boolean - Whether node integration is enabled. Default +* `webPreferences` Object - Settings of web page's features, properties: + * `nodeIntegration` Boolean - Whether node integration is enabled. Default is `true`. * `preload` String - Specifies a script that will be loaded before other scripts run in the page. This script will always have access to node APIs @@ -94,31 +94,31 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. prefix, the page will use an in-memory session. By assigning the same `partition`, multiple pages can share the same session. If the `partition` is unset then default session of the app will be used. - * `zoom-factor` Number - The default zoom factor of the page, `3.0` represents + * `zoomFactor` Number - The default zoom factor of the page, `3.0` represents `300%`. * `javascript` Boolean - * `web-security` Boolean - When setting `false`, it will disable the + * `webSecurity` Boolean - When setting `false`, it will disable the same-origin policy (Usually using testing websites by people), and set - `allow_displaying_insecure_content` and `allow_running_insecure_content` to + `allowDisplayingInsecureContent` and `allowRunningInsecureContent` to `true` if these two options are not set by user. - * `allow-displaying-insecure-content` Boolean - Allow an https page to display + * `allowDisplayingInsecureContent` Boolean - Allow an https page to display content like images from http URLs. - * `allow-running-insecure-content` Boolean - Allow a https page to run + * `allowRunningInsecureContent` Boolean - Allow a https page to run JavaScript, CSS or plugins from http URLs. * `images` Boolean * `java` Boolean - * `text-areas-are-resizable` Boolean + * `textAreasAreResizable` Boolean * `webgl` Boolean * `webaudio` Boolean * `plugins` Boolean - Whether plugins should be enabled. - * `experimental-features` Boolean - * `experimental-canvas-features` Boolean - * `overlay-scrollbars` Boolean - * `overlay-fullscreen-video` Boolean - * `shared-worker` Boolean - * `direct-write` Boolean - Whether the DirectWrite font rendering system on + * `experimentalFeatures` Boolean + * `experimentalCanvasFeatures` Boolean + * `overlayScrollbars` Boolean + * `overlayFullscreenVideo` Boolean + * `sharedWorker` Boolean + * `directWrite` Boolean - Whether the DirectWrite font rendering system on Windows is enabled. - * `page-visibility` Boolean - Page would be forced to be always in visible + * `pageVisibility` Boolean - Page would be forced to be always in visible or hidden state once set, instead of reflecting current window's visibility. Users can set it to `true` to prevent throttling of DOM timers. From ca49ddc95dbc25e641e5258980dc4ee4673e1a23 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Nov 2015 09:49:05 +0800 Subject: [PATCH 464/738] Update brightray --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 4e069f1806ef..10ea3c5207dc 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 4e069f1806efe5da9a965e61f329b19b7791104a +Subproject commit 10ea3c5207dc18b3103aaf6e457193f8454becf1 From 020214ff951ff837f83247621b762689f1b1fa21 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 12 Nov 2015 12:24:28 +0900 Subject: [PATCH 465/738] Update as upstream --- .../ko-KR/api/chrome-command-line-switches.md | 4 ++++ docs-translations/ko-KR/api/tray.md | 16 ++++++++++++++++ .../tutorial/using-selenium-and-webdriver.md | 19 ++++++++++++++----- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/docs-translations/ko-KR/api/chrome-command-line-switches.md b/docs-translations/ko-KR/api/chrome-command-line-switches.md index 5b055c49ec9d..aea9c49a1021 100644 --- a/docs-translations/ko-KR/api/chrome-command-line-switches.md +++ b/docs-translations/ko-KR/api/chrome-command-line-switches.md @@ -34,6 +34,10 @@ HTTP 요청 캐시를 비활성화 합니다. 시스템 설정의 프록시 서버를 무시하고 지정한 서버로 연결합니다. HTTP와 HTTPS 요청에만 적용됩니다. +시스템 프록시 서버 설정을 무시하고 지정한 서버로 연결합니다. +이 스위치는 HTTP와 HTTPS 그리고 WebSocket 요청에만 적용됩니다. +그리고 모든 프록시 서버가 HTTPS가 WebSocket 요청을 지원하지 않고 있을 수 있으므로 사용시 주의해야 합니다. + ## --proxy-pac-url=`url` 지정한 `url`의 PAC 스크립트를 사용합니다. diff --git a/docs-translations/ko-KR/api/tray.md b/docs-translations/ko-KR/api/tray.md index cd821f581b32..22fec3089e69 100644 --- a/docs-translations/ko-KR/api/tray.md +++ b/docs-translations/ko-KR/api/tray.md @@ -107,6 +107,10 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다. 알림풍선이 시간이 지나 사라지거나 유저가 클릭하여 닫을 때 발생하는 이벤트입니다. +### Event: 'drop' _OS X_ + +드래그 가능한 아이템이 트레이 아이콘에 드롭되면 발생하는 이벤트입니다. + ### Event: 'drop-files' _OS X_ * `event` @@ -114,6 +118,18 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다. 트레이 아이콘에 파일이 드롭되면 발생하는 이벤트입니다. +### Event: 'drag-enter' _OS X_ + +트레이 아이콘에 드래그 작업이 시작될 때 발생하는 이벤트입니다. + +### Event: 'drag-leave' _OS X_ + +트레이 아이콘에 드래그 작업이 종료될 때 발생하는 이벤트입니다. + +### Event: 'drag-end' _OS X_ + +트레이 아이콘에 드래그 작업이 종료되거나 다른 위치에서 종료될 때 발생하는 이벤트입니다. + ## Methods `Tray` 모듈은 다음과 같은 메서드를 가지고 있습니다: 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 a9fd84a68bc2..52e6d28307c9 100644 --- a/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md +++ b/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md @@ -44,9 +44,12 @@ var webdriver = require('selenium-webdriver'); var driver = new webdriver.Builder() // 작동하고 있는 크롬 드라이버의 포트 "9515"를 사용합니다. .usingServer('http://localhost:9515') - .withCapabilities({chromeOptions: { - // 여기에 사용중인 Electron 바이너리의 경로를 지정하세요. - binary: '/Path-to-Your-App.app/Contents/MacOS/Atom'}}) + .withCapabilities({ + chromeOptions: { + // 여기에 사용중인 Electron 바이너리의 경로를 지정하세요. + binary: '/Path-to-Your-App.app/Contents/MacOS/Atom', + } + }) .forBrowser('electron') .build(); @@ -92,7 +95,10 @@ var options = { port: 9515, // 연결할 크롬 드라이버 서버의 포트를 설정합니다. desiredCapabilities: { browserName: 'chrome', - chromeOptions: {binary: '/Path-to-Your-App.app/Electron'} // Electron 바이너리의 위치 + chromeOptions: { + binary: '/Path-to-Your-App/electron', // Electron 바이너리 경로 + args: [/* cli arguments */] // 선택 사항, 'app=' + /path/to/your/app/ + } } }; @@ -109,9 +115,12 @@ client .end(); ``` -## 작업환경 +## 작업 환경 따로 Electron을 다시 빌드하지 않는 경우 간단히 어플리케이션을 Electron의 리소스 디렉터리에 [배치](application-distribution.md)하여 바로 테스트 할 수 있습니다. +또한, Electron 바이너리의 명령줄 인수에 어플리케이션 폴더를 지정하는 방법으로 실행할 수도 있습니다. +이 방법을 사용하면 어플리케이션 폴더를 Electron의 `resource` 디렉터리로 복사하는 불필요한 과정을 생략할 수 있습니다. + [chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/ From ce0167756e2a587eea6a31c6fad7660a68fab8f5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Nov 2015 16:27:28 +0800 Subject: [PATCH 466/738] Update node for atom/node#13 --- vendor/node | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/node b/vendor/node index edfbc29d0942..1445826ca73c 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit edfbc29d09425f2f387c52d77f6351b6ce101659 +Subproject commit 1445826ca73cc79bc57d503dd11d4ffaf695625c From c2c09daa236bc57c7bb79cbae617fc6ca72842da Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Nov 2015 16:28:22 +0800 Subject: [PATCH 467/738] Add "electron" module --- atom/browser/api/lib/exports/electron.coffee | 47 +++++++++++++++++++ atom/browser/lib/init.coffee | 1 + atom/common/api/lib/exports/electron.coffee | 15 ++++++ atom/renderer/api/lib/exports/electron.coffee | 17 +++++++ atom/renderer/lib/init.coffee | 1 + filenames.gypi | 3 ++ 6 files changed, 84 insertions(+) create mode 100644 atom/browser/api/lib/exports/electron.coffee create mode 100644 atom/common/api/lib/exports/electron.coffee create mode 100644 atom/renderer/api/lib/exports/electron.coffee diff --git a/atom/browser/api/lib/exports/electron.coffee b/atom/browser/api/lib/exports/electron.coffee new file mode 100644 index 000000000000..6c7929706cc6 --- /dev/null +++ b/atom/browser/api/lib/exports/electron.coffee @@ -0,0 +1,47 @@ +# Import common modules. +module.exports = require '../../../../common/api/lib/exports/electron' + +Object.defineProperties module.exports, + # Browser side modules, please sort with alphabet order. + app: + enumerable: true + get: -> require '../app' + autoUpdater: + enumerable: true + get: -> require '../auto-updater' + BrowserWindow: + enumerable: true + get: -> require '../browser-window' + contentTracing: + enumerable: true + get: -> require '../content-tracing' + dialog: + enumerable: true + get: -> require '../dialog' + ipcMain: + enumerable: true + get: -> require '../ipc-main' + globalShortcut: + enumerable: true + get: -> require '../global-shortcut' + Menu: + enumerable: true + get: -> require '../menu' + MenuItem: + enumerable: true + get: -> require '../menu-item' + powerMonitor: + enumerable: true + get: -> require '../power-monitor' + powerSaveBlocker: + enumerable: true + get: -> require '../power-save-blocker' + protocol: + enumerable: true + get: -> require '../protocol' + screen: + enumerable: true + get: -> require '../screen' + tray: + enumerable: true + get: -> require '../tray' diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index 80d2da31b705..fd6059bd739d 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -17,6 +17,7 @@ require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') # Electron's built-in libraries. globalPaths = Module.globalPaths globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') +globalPaths.push path.resolve(__dirname, '..', 'api', 'lib', 'exports') if process.platform is 'win32' # Redirect node's console to use our own implementations, since node can not diff --git a/atom/common/api/lib/exports/electron.coffee b/atom/common/api/lib/exports/electron.coffee new file mode 100644 index 000000000000..a57d5be94c22 --- /dev/null +++ b/atom/common/api/lib/exports/electron.coffee @@ -0,0 +1,15 @@ +Object.defineProperties exports, + # Common modules, please sort with alphabet order. + clipboard: + # Must be enumerable, otherwise it woulde be invisible to remote module. + enumerable: true + get: -> require '../clipboard' + crashRepoter: + enumerable: true + get: -> require '../crash-reporter' + nativeImage: + enumerable: true + get: -> require '../native-image' + shell: + enumerable: true + get: -> require '../shell' diff --git a/atom/renderer/api/lib/exports/electron.coffee b/atom/renderer/api/lib/exports/electron.coffee new file mode 100644 index 000000000000..5d7f2a57edd0 --- /dev/null +++ b/atom/renderer/api/lib/exports/electron.coffee @@ -0,0 +1,17 @@ +# Import common modules. +module.exports = require '../../../../common/api/lib/exports/electron' + +Object.defineProperties module.exports, + # Renderer side modules, please sort with alphabet order. + ipcRenderer: + enumerable: true + get: -> require '../ipc-renderer' + remote: + enumerable: true + get: -> require '../remote' + screen: + enumerable: true + get: -> require '../screen' + webFrame: + enumerable: true + get: -> require '../web-frame' diff --git a/atom/renderer/lib/init.coffee b/atom/renderer/lib/init.coffee index ed3482fb972b..4779794278c2 100644 --- a/atom/renderer/lib/init.coffee +++ b/atom/renderer/lib/init.coffee @@ -17,6 +17,7 @@ require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') # of Atom's built-in libraries. globalPaths = Module.globalPaths globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') +globalPaths.push path.resolve(__dirname, '..', 'api', 'lib', 'exports') # The global variable will be used by ipc for event dispatching v8Util = process.atomBinding 'v8_util' diff --git a/filenames.gypi b/filenames.gypi index 4dc709c5ec57..de7ee26c5e41 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -16,6 +16,7 @@ 'atom/browser/api/lib/browser-window.coffee', 'atom/browser/api/lib/content-tracing.coffee', 'atom/browser/api/lib/dialog.coffee', + 'atom/browser/api/lib/exports/electron.coffee', 'atom/browser/api/lib/global-shortcut.coffee', 'atom/browser/api/lib/ipc.coffee', 'atom/browser/api/lib/ipc-main.coffee', @@ -38,6 +39,7 @@ 'atom/common/api/lib/clipboard.coffee', 'atom/common/api/lib/crash-reporter.coffee', 'atom/common/api/lib/deprecate.coffee', + 'atom/common/api/lib/exports/electron.coffee', 'atom/common/api/lib/native-image.coffee', 'atom/common/api/lib/shell.coffee', 'atom/common/lib/init.coffee', @@ -50,6 +52,7 @@ 'atom/renderer/lib/web-view/web-view.coffee', 'atom/renderer/lib/web-view/web-view-attributes.coffee', 'atom/renderer/lib/web-view/web-view-constants.coffee', + 'atom/renderer/api/lib/exports/electron.coffee', 'atom/renderer/api/lib/ipc.coffee', 'atom/renderer/api/lib/ipc-renderer.coffee', 'atom/renderer/api/lib/remote.coffee', From f9d7e7ce559d28307058cf196e280e8e2d2eed0e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Nov 2015 17:02:04 +0800 Subject: [PATCH 468/738] Add ELECTRON_DISABLE_OLD_STYLE_MODULES env --- atom/browser/lib/init.coffee | 7 ++++--- atom/common/lib/init.coffee | 5 +++-- atom/renderer/lib/init.coffee | 7 ++++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index fd6059bd739d..a9092e3f9513 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -13,12 +13,13 @@ require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths # Import common settings. require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') -# Add browser/api/lib to module search paths, which contains javascript part of -# Electron's built-in libraries. +# Expose public APIs. globalPaths = Module.globalPaths -globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') globalPaths.push path.resolve(__dirname, '..', 'api', 'lib', 'exports') +unless process.env.ELECTRON_DISABLE_OLD_STYLE_MODULES + globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') + if process.platform is 'win32' # Redirect node's console to use our own implementations, since node can not # handle console output when running as GUI program. diff --git a/atom/common/lib/init.coffee b/atom/common/lib/init.coffee index 1c80e6171a4d..a92871994da1 100644 --- a/atom/common/lib/init.coffee +++ b/atom/common/lib/init.coffee @@ -9,8 +9,9 @@ process.atomBinding = (name) -> catch e process.binding "atom_common_#{name}" if /No such module/.test e.message -# Add common/api/lib to module search paths. -Module.globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') +unless process.env.ELECTRON_DISABLE_OLD_STYLE_MODULES + # Add common/api/lib to module search paths. + Module.globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') # setImmediate and process.nextTick makes use of uv_check and uv_prepare to # run the callbacks, however since we only run uv loop on requests, the diff --git a/atom/renderer/lib/init.coffee b/atom/renderer/lib/init.coffee index 4779794278c2..4f0e6a328794 100644 --- a/atom/renderer/lib/init.coffee +++ b/atom/renderer/lib/init.coffee @@ -13,12 +13,13 @@ require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths # Import common settings. require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') -# Add renderer/api/lib to require's search paths, which contains javascript part -# of Atom's built-in libraries. +# Expose public APIs. globalPaths = Module.globalPaths -globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') globalPaths.push path.resolve(__dirname, '..', 'api', 'lib', 'exports') +unless process.env.ELECTRON_DISABLE_OLD_STYLE_MODULES + globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') + # The global variable will be used by ipc for event dispatching v8Util = process.atomBinding 'v8_util' v8Util.setHiddenValue global, 'ipc', new events.EventEmitter From fb5beb9af541d3405329789ad61945c20b03ef39 Mon Sep 17 00:00:00 2001 From: Shawn K Date: Thu, 12 Nov 2015 01:00:41 -0800 Subject: [PATCH 469/738] Add --js-flags support for main thread. Allow use of flags that must be set before V8 is initialized, such as "--harmony_proxies", e.g. --js-flags="--harmony_proxies --harmony_collections" --- atom/browser/javascript_environment.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/atom/browser/javascript_environment.cc b/atom/browser/javascript_environment.cc index cc06bb6ff9c2..ae4f8e55e76e 100644 --- a/atom/browser/javascript_environment.cc +++ b/atom/browser/javascript_environment.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. +#include + #include "atom/browser/javascript_environment.h" #include "base/command_line.h" @@ -27,8 +29,18 @@ bool JavascriptEnvironment::Initialize() { const char expose_debug_as[] = "--expose_debug_as=v8debug"; v8::V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1); } + + const std::string js_flags_switch = "js-flags"; + + if (cmd->HasSwitch(js_flags_switch)) { + const char *js_flags_value = + (cmd->GetSwitchValueASCII(js_flags_switch)).c_str(); + v8::V8::SetFlagsFromString(js_flags_value, strlen(js_flags_value)); + } + gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, gin::ArrayBufferAllocator::SharedInstance()); + return true; } From 1d1f911b095ce29206f4b7f74221f3bac7b28e0d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Nov 2015 18:28:04 +0800 Subject: [PATCH 470/738] Use require('electron') in Electron's code --- atom/browser/api/lib/app.coffee | 9 ++--- atom/browser/api/lib/browser-window.coffee | 8 ++--- atom/browser/api/lib/dialog.coffee | 4 +-- atom/browser/api/lib/exports/electron.coffee | 5 +++ atom/browser/api/lib/global-shortcut.coffee | 4 +-- atom/browser/api/lib/ipc.coffee | 4 +-- atom/browser/api/lib/menu-item.coffee | 3 +- atom/browser/api/lib/menu.coffee | 7 ++-- .../api/lib/navigation-controller.coffee | 6 ++-- atom/browser/api/lib/power-monitor.coffee | 5 +-- .../browser/api/lib/power-save-blocker.coffee | 4 +-- atom/browser/api/lib/protocol.coffee | 5 +-- atom/browser/api/lib/screen.coffee | 4 +-- atom/browser/api/lib/tray.coffee | 5 ++- atom/browser/api/lib/web-contents.coffee | 11 +++---- atom/browser/default_app/default_app.js | 5 +-- atom/browser/default_app/index.html | 8 +++-- atom/browser/default_app/main.js | 20 ++++++----- atom/browser/lib/chrome-extension.coffee | 6 ++-- atom/browser/lib/guest-view-manager.coffee | 14 ++++---- atom/browser/lib/guest-window-manager.coffee | 17 +++++----- atom/browser/lib/init.coffee | 5 +-- atom/browser/lib/objects-registry.coffee | 2 +- atom/browser/lib/rpc-server.coffee | 31 +++++++++--------- atom/common/api/lib/clipboard.coffee | 3 +- atom/common/api/lib/crash-reporter.coffee | 7 ++-- atom/common/api/lib/exports/electron.coffee | 5 +++ atom/renderer/api/lib/ipc.coffee | 3 +- atom/renderer/api/lib/remote.coffee | 31 +++++++++--------- atom/renderer/api/lib/screen.coffee | 2 +- atom/renderer/lib/inspector.coffee | 8 ++--- atom/renderer/lib/override.coffee | 27 ++++++++------- .../lib/web-view/guest-view-internal.coffee | 27 ++++++++------- .../lib/web-view/web-view-attributes.coffee | 3 +- atom/renderer/lib/web-view/web-view.coffee | 4 +-- spec/api-app-spec.coffee | 5 ++- spec/api-browser-window-spec.coffee | 12 +++---- spec/api-clipboard-spec.coffee | 4 +-- spec/api-crash-reporter-spec.coffee | 7 ++-- spec/api-ipc-spec.coffee | 17 +++++----- spec/api-menu-spec.coffee | 5 ++- spec/api-protocol-spec.coffee | 5 +-- spec/api-screen-spec.coffee | 3 +- spec/api-session-spec.coffee | 16 ++++----- spec/asar-spec.coffee | 18 +++++----- spec/chromium-spec.coffee | 5 +-- spec/fixtures/api/beforeunload-false.html | 2 +- .../api/close-beforeunload-empty-string.html | 2 +- .../api/close-beforeunload-false.html | 2 +- .../api/close-beforeunload-string.html | 2 +- .../fixtures/api/close-beforeunload-true.html | 2 +- spec/fixtures/api/crash.html | 2 +- spec/fixtures/api/localstorage.html | 6 ++-- spec/fixtures/api/preload.html | 2 +- spec/fixtures/api/send-sync-message.html | 4 +-- spec/fixtures/asar/script.asar | Bin 204 -> 221 bytes spec/fixtures/asar/web.asar | Bin 201 -> 218 bytes spec/fixtures/module/preload-ipc.js | 6 ++-- spec/fixtures/module/send-later.js | 4 +-- spec/fixtures/pages/basic-auth.html | 6 ++-- spec/fixtures/pages/beforeunload-false.html | 4 +-- spec/fixtures/pages/document-hidden.html | 2 +- spec/fixtures/pages/history.html | 2 +- spec/fixtures/pages/ipc-message.html | 2 +- spec/fixtures/pages/onkeyup.html | 2 +- spec/fixtures/pages/onmouseup.html | 2 +- spec/fixtures/pages/window-open-size.html | 2 +- spec/fixtures/pages/window-opener.html | 2 +- spec/node-spec.coffee | 3 +- spec/static/index.html | 17 ++++++---- spec/static/main.js | 28 ++++++++-------- 71 files changed, 265 insertions(+), 250 deletions(-) diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index b5025a3a4fee..0113e90a1a1f 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -1,5 +1,5 @@ -deprecate = require 'deprecate' -EventEmitter = require('events').EventEmitter +electron = require 'electron' +{EventEmitter} = require 'events' bindings = process.atomBinding 'app' sessionBindings = process.atomBinding 'session' @@ -9,10 +9,10 @@ app = bindings.app app.__proto__ = EventEmitter.prototype app.setApplicationMenu = (menu) -> - require('menu').setApplicationMenu menu + electron.menu.setApplicationMenu menu app.getApplicationMenu = -> - require('menu').getApplicationMenu() + electron.menu.getApplicationMenu() app.commandLine = appendSwitch: bindings.appendSwitch, @@ -39,6 +39,7 @@ app.getAppPath = -> app.resolveProxy = (url, callback) -> @defaultSession.resolveProxy url, callback # Deprecated. +{deprecate} = electron app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', -> @getPath 'home' app.getDataPath = deprecate 'app.getDataPath', 'app.getPath', -> diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 5bb633208840..3cefa1bf60ce 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -1,7 +1,5 @@ -EventEmitter = require('events').EventEmitter -app = require 'app' -ipc = require 'ipc-main' -deprecate = require 'deprecate' +{app, ipcMain, deprecate} = require 'electron' +{EventEmitter} = require 'events' BrowserWindow = process.atomBinding('window').BrowserWindow BrowserWindow::__proto__ = EventEmitter.prototype @@ -15,7 +13,7 @@ BrowserWindow::_init = -> # Make new windows requested by links behave like "window.open" @webContents.on '-new-window', (event, url, frameName) -> options = show: true, width: 800, height: 600 - ipc.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options + ipcMain.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options # window.resizeTo(...) # window.moveTo(...) diff --git a/atom/browser/api/lib/dialog.coffee b/atom/browser/api/lib/dialog.coffee index 0843af04282e..f10ce58c17f5 100644 --- a/atom/browser/api/lib/dialog.coffee +++ b/atom/browser/api/lib/dialog.coffee @@ -1,7 +1,7 @@ +{app, BrowserWindow} = require 'electron' + binding = process.atomBinding 'dialog' v8Util = process.atomBinding 'v8_util' -app = require 'app' -BrowserWindow = require 'browser-window' fileDialogProperties = openFile: 1 << 0 diff --git a/atom/browser/api/lib/exports/electron.coffee b/atom/browser/api/lib/exports/electron.coffee index 6c7929706cc6..a09a6441c3f8 100644 --- a/atom/browser/api/lib/exports/electron.coffee +++ b/atom/browser/api/lib/exports/electron.coffee @@ -45,3 +45,8 @@ Object.defineProperties module.exports, tray: enumerable: true get: -> require '../tray' + # The internal modules, invisible unless you know their names. + NavigationController: + get: -> require '../navigation-controller' + webContents: + get: -> require '../web-contents' diff --git a/atom/browser/api/lib/global-shortcut.coffee b/atom/browser/api/lib/global-shortcut.coffee index 8b24d2725366..56c3e128767e 100644 --- a/atom/browser/api/lib/global-shortcut.coffee +++ b/atom/browser/api/lib/global-shortcut.coffee @@ -1,5 +1,3 @@ -bindings = process.atomBinding 'global_shortcut' - -globalShortcut = bindings.globalShortcut +{globalShortcut} = process.atomBinding 'global_shortcut' module.exports = globalShortcut diff --git a/atom/browser/api/lib/ipc.coffee b/atom/browser/api/lib/ipc.coffee index b8ab05a886b9..8019a385dd90 100644 --- a/atom/browser/api/lib/ipc.coffee +++ b/atom/browser/api/lib/ipc.coffee @@ -1,6 +1,6 @@ -deprecate = require 'deprecate' +{deprecate, ipcMain} = require 'electron' # This module is deprecated, we mirror everything from ipcMain. deprecate.warn 'ipc module', 'ipcMain module' -module.exports = require 'ipc-main' +module.exports = ipcMain diff --git a/atom/browser/api/lib/menu-item.coffee b/atom/browser/api/lib/menu-item.coffee index cfefeec4edbb..92e2283b417d 100644 --- a/atom/browser/api/lib/menu-item.coffee +++ b/atom/browser/api/lib/menu-item.coffee @@ -1,4 +1,3 @@ -BrowserWindow = require 'browser-window' v8Util = process.atomBinding 'v8_util' nextCommandId = 0 @@ -18,7 +17,7 @@ class MenuItem @types = ['normal', 'separator', 'submenu', 'checkbox', 'radio'] constructor: (options) -> - Menu = require 'menu' + {Menu} = require 'electron' {click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options diff --git a/atom/browser/api/lib/menu.coffee b/atom/browser/api/lib/menu.coffee index f66c1568c003..26e2dc233506 100644 --- a/atom/browser/api/lib/menu.coffee +++ b/atom/browser/api/lib/menu.coffee @@ -1,8 +1,7 @@ -BrowserWindow = require 'browser-window' -EventEmitter = require('events').EventEmitter -MenuItem = require 'menu-item' -v8Util = process.atomBinding 'v8_util' +{BrowserWindow, MenuItem} = require 'electron' +{EventEmitter} = require 'events' +v8Util = process.atomBinding 'v8_util' bindings = process.atomBinding 'menu' # Automatically generated radio menu item's group id. diff --git a/atom/browser/api/lib/navigation-controller.coffee b/atom/browser/api/lib/navigation-controller.coffee index 34911dd759ec..88b1ed30ddd3 100644 --- a/atom/browser/api/lib/navigation-controller.coffee +++ b/atom/browser/api/lib/navigation-controller.coffee @@ -1,10 +1,10 @@ -ipc = require 'ipc-main' +{ipcMain} = require 'electron' # The history operation in renderer is redirected to browser. -ipc.on 'ATOM_SHELL_NAVIGATION_CONTROLLER', (event, method, args...) -> +ipcMain.on 'ATOM_SHELL_NAVIGATION_CONTROLLER', (event, method, args...) -> event.sender[method] args... -ipc.on 'ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', (event, method, args...) -> +ipcMain.on 'ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', (event, method, args...) -> event.returnValue = event.sender[method] args... # JavaScript implementation of Chromium's NavigationController. diff --git a/atom/browser/api/lib/power-monitor.coffee b/atom/browser/api/lib/power-monitor.coffee index f13e60eb9da8..54bf9391827c 100644 --- a/atom/browser/api/lib/power-monitor.coffee +++ b/atom/browser/api/lib/power-monitor.coffee @@ -1,5 +1,6 @@ -powerMonitor = process.atomBinding('power_monitor').powerMonitor -EventEmitter = require('events').EventEmitter +{EventEmitter} = require 'events' + +{powerMonitor} = process.atomBinding 'power_monitor' powerMonitor.__proto__ = EventEmitter.prototype diff --git a/atom/browser/api/lib/power-save-blocker.coffee b/atom/browser/api/lib/power-save-blocker.coffee index 7f428bc40f19..58392bc9aa8b 100644 --- a/atom/browser/api/lib/power-save-blocker.coffee +++ b/atom/browser/api/lib/power-save-blocker.coffee @@ -1,3 +1,3 @@ -bindings = process.atomBinding 'power_save_blocker' +{powerSaveBlocker} = process.atomBinding 'power_save_blocker' -module.exports = bindings.powerSaveBlocker +module.exports = powerSaveBlocker diff --git a/atom/browser/api/lib/protocol.coffee b/atom/browser/api/lib/protocol.coffee index 13f2a6d10270..a1dbc7c17d75 100644 --- a/atom/browser/api/lib/protocol.coffee +++ b/atom/browser/api/lib/protocol.coffee @@ -1,7 +1,8 @@ -app = require 'app' +{app} = require 'electron' + throw new Error('Can not initialize protocol module before app is ready') unless app.isReady() -protocol = process.atomBinding('protocol').protocol +{protocol} = process.atomBinding 'protocol' # Warn about removed APIs. logAndThrow = (callback, message) -> diff --git a/atom/browser/api/lib/screen.coffee b/atom/browser/api/lib/screen.coffee index 6ef5a5f66338..87c42f091df2 100644 --- a/atom/browser/api/lib/screen.coffee +++ b/atom/browser/api/lib/screen.coffee @@ -1,6 +1,6 @@ -EventEmitter = require('events').EventEmitter +{EventEmitter} = require 'events' +{screen} = process.atomBinding 'screen' -screen = process.atomBinding('screen').screen screen.__proto__ = EventEmitter.prototype module.exports = screen diff --git a/atom/browser/api/lib/tray.coffee b/atom/browser/api/lib/tray.coffee index 1c225ddd403c..41cfc96d3f56 100644 --- a/atom/browser/api/lib/tray.coffee +++ b/atom/browser/api/lib/tray.coffee @@ -1,7 +1,6 @@ -EventEmitter = require('events').EventEmitter -bindings = process.atomBinding 'tray' +{EventEmitter} = require 'events' +{Tray} = process.atomBinding 'tray' -Tray = bindings.Tray Tray::__proto__ = EventEmitter.prototype Tray::setContextMenu = (menu) -> diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index 958c3f8270c6..b3b1e7ed9fa4 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -1,8 +1,7 @@ -EventEmitter = require('events').EventEmitter -Menu = require './menu' -NavigationController = require './navigation-controller' +{EventEmitter} = require 'events' +{ipcMain, NavigationController, Menu} = require 'electron' + binding = process.atomBinding 'web_contents' -ipc = require 'ipc-main' nextId = 0 getNextId = -> ++nextId @@ -60,11 +59,11 @@ wrapWebContents = (webContents) -> # Dispatch IPC messages to the ipc module. webContents.on 'ipc-message', (event, packed) -> [channel, args...] = packed - ipc.emit channel, event, args... + ipcMain.emit channel, event, args... webContents.on 'ipc-message-sync', (event, packed) -> [channel, args...] = packed Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value) - ipc.emit channel, event, args... + ipcMain.emit channel, event, args... # Handle context menu action request from pepper plugin. webContents.on 'pepper-context-menu', (event, params) -> diff --git a/atom/browser/default_app/default_app.js b/atom/browser/default_app/default_app.js index de8b14d5f4d7..6a94db4836f8 100644 --- a/atom/browser/default_app/default_app.js +++ b/atom/browser/default_app/default_app.js @@ -1,5 +1,6 @@ -var app = require('app'); -var BrowserWindow = require('browser-window'); +const electron = require('electron'); +const app = electron.app; +const BrowserWindow = electron.BrowserWindow; var mainWindow = null; diff --git a/atom/browser/default_app/index.html b/atom/browser/default_app/index.html index 96e45806d5dd..e55cdf77b7fd 100644 --- a/atom/browser/default_app/index.html +++ b/atom/browser/default_app/index.html @@ -57,13 +57,17 @@ diff --git a/spec/fixtures/api/preload.html b/spec/fixtures/api/preload.html index 5e73c92971c1..b0e42ebe2ea3 100644 --- a/spec/fixtures/api/preload.html +++ b/spec/fixtures/api/preload.html @@ -3,7 +3,7 @@ diff --git a/spec/fixtures/api/send-sync-message.html b/spec/fixtures/api/send-sync-message.html index 40bae94b810f..80950740570a 100644 --- a/spec/fixtures/api/send-sync-message.html +++ b/spec/fixtures/api/send-sync-message.html @@ -1,8 +1,8 @@ diff --git a/spec/fixtures/asar/script.asar b/spec/fixtures/asar/script.asar index 152045ad2a6bb6e1337bc70448fecde5100e3709..7239786ec90ea4317573ac9e080073a42b13e6d6 100755 GIT binary patch delta 58 zcmX@Zc$aZPFq5gt#L#Hn)ST4hlA`=Pbxpm@g5;poyp+_U)FQoNAVWjFATuvrT}MH^ LARkC;T5|yaT{;tO delta 41 vcmcc1c!qI8Fq5(Q#L#G&%z|WfO}*mOyc7-fg3P>hbsYuuf_xyYY0U)y91IMc diff --git a/spec/fixtures/asar/web.asar b/spec/fixtures/asar/web.asar index 0c7a788e759dc131689de6fb977bbbba4d795260..1e9db65b8128ec9ab0fa415ccf7dc6e6dc874b28 100644 GIT binary patch delta 38 tcmX@fc#Cm@0h6i0M5Ac2)ST4hlA`=Pbxpm@g5;poyp+_U)S`)#%mMz_4X6MB delta 21 ccmcb`c#?5~0h6)uM5Acd%z|Wf&54W60Zj!4=l}o! diff --git a/spec/fixtures/module/preload-ipc.js b/spec/fixtures/module/preload-ipc.js index 76bd481cab6f..ed95055c1249 100644 --- a/spec/fixtures/module/preload-ipc.js +++ b/spec/fixtures/module/preload-ipc.js @@ -1,4 +1,4 @@ -var ipc = require('ipc-renderer'); -ipc.on('ping', function(event, message) { - ipc.sendToHost('pong', message); +var ipcRenderer = require('electron').ipcRenderer; +ipcRenderer.on('ping', function(event, message) { + ipcRenderer.sendToHost('pong', message); }); diff --git a/spec/fixtures/module/send-later.js b/spec/fixtures/module/send-later.js index 9cd5bfd38853..13f02452db1c 100644 --- a/spec/fixtures/module/send-later.js +++ b/spec/fixtures/module/send-later.js @@ -1,4 +1,4 @@ -var ipc = require('ipc-renderer'); +var ipcRenderer = require('electron').ipcRenderer; window.onload = function() { - ipc.send('answer', typeof window.process); + ipcRenderer.send('answer', typeof window.process); } diff --git a/spec/fixtures/pages/basic-auth.html b/spec/fixtures/pages/basic-auth.html index f2b9fab199fe..ec9383ca4d08 100644 --- a/spec/fixtures/pages/basic-auth.html +++ b/spec/fixtures/pages/basic-auth.html @@ -2,7 +2,7 @@ diff --git a/spec/fixtures/pages/beforeunload-false.html b/spec/fixtures/pages/beforeunload-false.html index 4f14613bf371..0b71b07c834a 100644 --- a/spec/fixtures/pages/beforeunload-false.html +++ b/spec/fixtures/pages/beforeunload-false.html @@ -3,8 +3,8 @@ diff --git a/spec/fixtures/pages/history.html b/spec/fixtures/pages/history.html index ef0083535973..6100293fdac4 100644 --- a/spec/fixtures/pages/history.html +++ b/spec/fixtures/pages/history.html @@ -2,7 +2,7 @@ diff --git a/spec/fixtures/pages/ipc-message.html b/spec/fixtures/pages/ipc-message.html index 65e347275c21..f543c9abf082 100644 --- a/spec/fixtures/pages/ipc-message.html +++ b/spec/fixtures/pages/ipc-message.html @@ -1,7 +1,7 @@ diff --git a/spec/fixtures/pages/onkeyup.html b/spec/fixtures/pages/onkeyup.html index 87e6dc596b5b..4e75dbb1e4ac 100644 --- a/spec/fixtures/pages/onkeyup.html +++ b/spec/fixtures/pages/onkeyup.html @@ -2,7 +2,7 @@ diff --git a/spec/fixtures/pages/onmouseup.html b/spec/fixtures/pages/onmouseup.html index ea486fdf80ed..123825a28fbd 100644 --- a/spec/fixtures/pages/onmouseup.html +++ b/spec/fixtures/pages/onmouseup.html @@ -2,7 +2,7 @@ diff --git a/spec/fixtures/pages/window-open-size.html b/spec/fixtures/pages/window-open-size.html index 7b06cfddf551..b32e39889a4c 100644 --- a/spec/fixtures/pages/window-open-size.html +++ b/spec/fixtures/pages/window-open-size.html @@ -1,7 +1,7 @@ diff --git a/spec/fixtures/pages/window-opener.html b/spec/fixtures/pages/window-opener.html index a7b59bd1a45b..58a8b6ea1ae9 100644 --- a/spec/fixtures/pages/window-opener.html +++ b/spec/fixtures/pages/window-opener.html @@ -4,7 +4,7 @@ if (window.opener !== null) window.opener.postMessage(typeof window.opener, '*'); else - require('ipc-renderer').send('opener', window.opener); + require('electron').ipcRenderer.send('opener', window.opener); diff --git a/spec/node-spec.coffee b/spec/node-spec.coffee index 969fc76f41ff..e6b2aa15821c 100644 --- a/spec/node-spec.coffee +++ b/spec/node-spec.coffee @@ -3,7 +3,8 @@ child_process = require 'child_process' fs = require 'fs' path = require 'path' os = require 'os' -remote = require 'remote' + +{remote} = require 'electron' describe 'node feature', -> fixtures = path.join __dirname, 'fixtures' diff --git a/spec/static/index.html b/spec/static/index.html index e7c69f5ba7de..ea86f6ee302d 100644 --- a/spec/static/index.html +++ b/spec/static/index.html @@ -14,22 +14,25 @@ process.throwDeprecation = true; // Check if we are running in CI. - var argv = require('remote').process.argv; + var electron = require ('electron'); + var remote = electron.remote; + var ipcRenderer = electron.ipcRenderer; + + var argv = remote.process.argv; var isCi = argv[2] == '--ci'; if (!isCi) { - var win = require('remote').getCurrentWindow(); + var win = remote.getCurrentWindow(); win.show(); win.focus(); } // Show DevTools. document.oncontextmenu = function(e) { - require('remote').getCurrentWindow().inspectElement(e.clientX, e.clientY); + remote.getCurrentWindow().inspectElement(e.clientX, e.clientY); } require('coffee-script/register'); // Supports .coffee tests. - var ipc = require('ipc-renderer'); // Rediret all output to browser. if (isCi) { @@ -37,11 +40,11 @@ return { log: function() { args = Array.prototype.slice.call(arguments); - ipc.send('console.log', args); + ipcRenderer.send('console.log', args); }, error: function() { args = Array.prototype.slice.call(arguments); - ipc.send('console.error', args); + ipcRenderer.send('console.error', args); }, } }); @@ -70,7 +73,7 @@ var runner = mocha.run(function() { Mocha.utils.highlightTags('code'); if (isCi) - ipc.send('process.exit', runner.failures); + ipcRenderer.send('process.exit', runner.failures); }); }); })(); diff --git a/spec/static/main.js b/spec/static/main.js index 70c47cc37e1c..e071474f9a94 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -1,8 +1,10 @@ -var app = require('app'); -var ipc = require('ipc-main'); -var dialog = require('dialog'); -var path = require('path'); -var BrowserWindow = require('browser-window'); +const electron = require('electron'); +const app = electron.app; +const ipcMain = electron.ipcMain; +const dialog = electron.dialog; +const BrowserWindow = electron.BrowserWindow; + +const path = require('path'); var window = null; process.port = 0; // will be used by crash-reporter spec. @@ -16,27 +18,27 @@ app.commandLine.appendSwitch('disable-renderer-backgrounding'); // sure we can reproduce it in renderer process. process.stdout; -ipc.on('message', function(event, arg) { +ipcMain.on('message', function(event, arg) { event.sender.send('message', arg); }); -ipc.on('console.log', function(event, args) { +ipcMain.on('console.log', function(event, args) { console.error.apply(console, args); }); -ipc.on('console.error', function(event, args) { +ipcMain.on('console.error', function(event, args) { console.error.apply(console, args); }); -ipc.on('process.exit', function(event, code) { +ipcMain.on('process.exit', function(event, code) { process.exit(code); }); -ipc.on('eval', function(event, script) { +ipcMain.on('eval', function(event, script) { event.returnValue = eval(script); }); -ipc.on('echo', function(event, msg) { +ipcMain.on('echo', function(event, msg) { event.returnValue = msg; }); @@ -54,7 +56,7 @@ app.on('window-all-closed', function() { app.on('ready', function() { // Test if using protocol module would crash. - require('protocol').registerStringProtocol('test-if-crashes', function() {}); + electron.protocol.registerStringProtocol('test-if-crashes', function() {}); window = new BrowserWindow({ title: 'Electron Tests', @@ -79,7 +81,7 @@ app.on('ready', function() { // For session's download test, listen 'will-download' event in browser, and // reply the result to renderer for verifying var downloadFilePath = path.join(__dirname, '..', 'fixtures', 'mock.pdf'); - ipc.on('set-download-option', function(event, need_cancel) { + ipcMain.on('set-download-option', function(event, need_cancel) { window.webContents.session.once('will-download', function(e, item, webContents) { item.setSavePath(downloadFilePath); From 8b2942c2795d2371aea0dacfddd2b58a66752c58 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Nov 2015 20:30:40 +0800 Subject: [PATCH 471/738] Optimize remote.require('electron') --- atom/browser/api/lib/exports/electron.coffee | 3 +++ atom/browser/lib/rpc-server.coffee | 18 ++++++++++++++++-- atom/common/api/lib/exports/electron.coffee | 2 +- atom/renderer/api/lib/remote.coffee | 19 ++++++++++++++++++- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/lib/exports/electron.coffee b/atom/browser/api/lib/exports/electron.coffee index a09a6441c3f8..6f70e6b38b36 100644 --- a/atom/browser/api/lib/exports/electron.coffee +++ b/atom/browser/api/lib/exports/electron.coffee @@ -1,6 +1,9 @@ # Import common modules. module.exports = require '../../../../common/api/lib/exports/electron' +v8Util = process.atomBinding 'v8_util' +v8Util.setHiddenValue module.exports, 'electronModule', true + Object.defineProperties module.exports, # Browser side modules, please sort with alphabet order. app: diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 3479f30f0b53..5c67026debf2 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -1,5 +1,7 @@ -{ipcMain} = require 'electron' path = require 'path' + +electron = require 'electron' +{ipcMain} = electron objectsRegistry = require './objects-registry' v8Util = process.atomBinding 'v8_util' @@ -14,7 +16,11 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta.type = 'array' if Array.isArray value meta.type = 'error' if value instanceof Error meta.type = 'date' if value instanceof Date - meta.type = 'promise' if value? and value.constructor.name is 'Promise' + meta.type = 'promise' if value?.constructor.name is 'Promise' + + # require('electron'). + if meta.type is 'object' and v8Util.getHiddenValue value, 'electronModule' + meta.type = 'electronModule' # Treat simple objects as value. if optimizeSimpleObject and meta.type is 'object' and v8Util.getHiddenValue value, 'simple' @@ -43,6 +49,8 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta.members = plainObjectToMeta value else if meta.type is 'date' meta.value = value.getTime() + else if meta.type is 'electronModule' + meta.members = (name for name of value) else meta.type = 'value' meta.value = value @@ -122,6 +130,12 @@ ipcMain.on 'ATOM_BROWSER_REQUIRE', (event, module) -> catch e event.returnValue = exceptionToMeta e +ipcMain.on 'ATOM_BROWSER_GET_BUILTIN', (event, module) -> + try + event.returnValue = valueToMeta event.sender, electron[module] + catch e + event.returnValue = exceptionToMeta e + ipcMain.on 'ATOM_BROWSER_GLOBAL', (event, name) -> try event.returnValue = valueToMeta event.sender, global[name] diff --git a/atom/common/api/lib/exports/electron.coffee b/atom/common/api/lib/exports/electron.coffee index 26e8ce2f1835..7bcb23a2ca4d 100644 --- a/atom/common/api/lib/exports/electron.coffee +++ b/atom/common/api/lib/exports/electron.coffee @@ -4,7 +4,7 @@ Object.defineProperties exports, # Must be enumerable, otherwise it woulde be invisible to remote module. enumerable: true get: -> require '../clipboard' - crashRepoter: + crashReporter: enumerable: true get: -> require '../crash-reporter' nativeImage: diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index 9faed14bf5cd..09e7dcdcb574 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -18,7 +18,7 @@ wrapArgs = (args, visited=[]) -> type: 'array', value: wrapArgs(value, visited) else if Buffer.isBuffer value type: 'buffer', value: Array::slice.call(value, 0) - else if value? and value.constructor.name is 'Promise' + else if value?.constructor.name is 'Promise' type: 'promise', then: valueToMeta(value.then.bind(value)) else if value? and typeof value is 'object' and v8Util.getHiddenValue value, 'atomId' type: 'remote-object', id: v8Util.getHiddenValue value, 'atomId' @@ -49,6 +49,15 @@ metaToValue = (meta) -> when 'date' then new Date(meta.value) when 'exception' throw new Error("#{meta.message}\n#{meta.stack}") + when 'electronModule' + # require('electron'). + ret = {} + for member in meta.members + do (member) -> + Object.defineProperty ret, member, + enumerable: true + get: -> exports.getBuiltin member + ret else if meta.type is 'function' # A shadow class to represent the remote function object. @@ -135,6 +144,14 @@ exports.require = (module) -> meta = ipcRenderer.sendSync 'ATOM_BROWSER_REQUIRE', module moduleCache[module] = metaToValue meta +# Alias to remote.require('electron').xxx. +builtinCache = {} +exports.getBuiltin = (module) -> + return builtinCache[module] if builtinCache[module]? + + meta = ipcRenderer.sendSync 'ATOM_BROWSER_GET_BUILTIN', module + builtinCache[module] = metaToValue meta + # Get current BrowserWindow object. windowCache = null exports.getCurrentWindow = -> From eac2e7cc614d4e98e2828921f63d55f7b5e2c85c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Nov 2015 21:20:09 +0800 Subject: [PATCH 472/738] docs: Update codes in docs to use require('electron') --- docs/README.md | 30 +++++++++---------- docs/api/app.md | 2 +- docs/api/browser-window.md | 13 +------- docs/api/chrome-command-line-switches.md | 2 +- docs/api/clipboard.md | 5 +--- docs/api/content-tracing.md | 2 +- docs/api/crash-reporter.md | 4 +-- docs/api/dialog.md | 6 ++-- docs/api/frameless-window.md | 5 ++-- docs/api/global-shortcut.md | 5 ++-- docs/api/ipc-main.md | 4 +-- docs/api/menu.md | 10 +++---- docs/api/native-image.md | 29 +++++++++--------- docs/api/power-monitor.md | 6 ++-- docs/api/power-save-blocker.md | 4 +-- docs/api/protocol.md | 7 +++-- docs/api/remote.md | 18 ++++++----- docs/api/screen.md | 21 ++++++------- docs/api/session.md | 4 +-- docs/api/shell.md | 2 +- docs/api/synopsis.md | 9 +++--- docs/api/tray.md | 7 +++-- docs/api/web-contents.md | 14 ++++----- docs/api/web-frame.md | 4 +-- docs/api/web-view-tag.md | 8 ++--- docs/tutorial/application-packaging.md | 6 ++-- .../desktop-environment-integration.md | 13 ++++---- docs/tutorial/devtools-extension.md | 5 ++-- docs/tutorial/online-offline-events.md | 18 ++++++----- docs/tutorial/quick-start.md | 7 +++-- docs/tutorial/using-pepper-flash-plugin.md | 17 ----------- docs/tutorial/using-selenium-and-webdriver.md | 4 +-- 32 files changed, 134 insertions(+), 157 deletions(-) diff --git a/docs/README.md b/docs/README.md index fb5c64a8f17e..208ff8bf47b6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -31,32 +31,32 @@ ### Modules for the Main Process: * [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](api/ipc-main.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) -* [web-contents](api/web-contents.md) -* [tray](api/tray.md) +* [webContents](api/web-contents.md) +* [Tray](api/tray.md) ### Modules for the Renderer Process (Web Page): -* [ipc-renderer](api/ipc-renderer.md) +* [ipcRenderer](api/ipc-renderer.md) * [remote](api/remote.md) -* [web-frame](api/web-frame.md) +* [webFrame](api/web-frame.md) ### Modules for Both Processes: * [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) diff --git a/docs/api/app.md b/docs/api/app.md index fdb9f9980592..1edc40fb89ae 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -6,7 +6,7 @@ The following example shows how to quit the application when the last window is closed: ```javascript -var app = require('app'); +const app = require('electron').app; app.on('window-all-closed', function() { app.quit(); }); diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 0499b6355a00..670c814c741d 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -4,7 +4,7 @@ The `BrowserWindow` class gives you the ability to create a browser window. For example: ```javascript -var BrowserWindow = require('browser-window'); +const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({ width: 800, height: 600, show: false }); win.on('closed', function() { @@ -291,11 +291,8 @@ Remove the DevTools extension whose name is `name`. Objects created with `new BrowserWindow` have the following properties: ```javascript -var BrowserWindow = require('browser-window'); - // In this example `win` is our instance var win = new BrowserWindow({ width: 800, height: 600 }); - ``` ### `win.webContents` @@ -316,14 +313,6 @@ Objects created with `new BrowserWindow` have the following instance methods: **Note:** Some methods are only available on specific operating systems and are labeled as such. -```javascript -var BrowserWindow = require('browser-window'); - -// In this example `win` is our instance -var win = new BrowserWindow({ width: 800, height: 600 }); - -``` - ### `win.destroy()` Force closing the window, the `unload` and `beforeunload` event won't be emitted diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index 96dffb963135..d163a726d40e 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -6,7 +6,7 @@ them in your app's main script before the [ready][ready] event of [app][app] module is emitted: ```javascript -var app = require('app'); +const app = require('electron').app; app.commandLine.appendSwitch('remote-debugging-port', '8315'); app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1'); diff --git a/docs/api/clipboard.md b/docs/api/clipboard.md index a99605baea18..7cb5b840bc1c 100644 --- a/docs/api/clipboard.md +++ b/docs/api/clipboard.md @@ -4,7 +4,7 @@ The `clipboard` module provides methods to perform copy and paste operations. The following example shows how to write a string to the clipboard: ```javascript -var clipboard = require('clipboard'); +const clipboard = require('electron').clipboard; clipboard.writeText('Example String'); ``` @@ -12,7 +12,6 @@ On X Window systems, there is also a selection clipboard. To manipulate it you need to pass `selection` to each method: ```javascript -var clipboard = require('clipboard'); clipboard.writeText('Example String', 'selection'); console.log(clipboard.readText('selection')); ``` @@ -82,7 +81,6 @@ Returns an array of supported formats for the clipboard `type`. Returns whether the clipboard supports the format of specified `data`. ```javascript -var clipboard = require('clipboard'); console.log(clipboard.has('

selection

')); ``` @@ -102,7 +100,6 @@ Reads `data` from the clipboard. * `type` String (optional) ```javascript -var clipboard = require('clipboard'); clipboard.write({text: 'test', html: "test"}); ``` Writes `data` to the clipboard. diff --git a/docs/api/content-tracing.md b/docs/api/content-tracing.md index 2e05fc67668f..734e2c47cfb4 100644 --- a/docs/api/content-tracing.md +++ b/docs/api/content-tracing.md @@ -6,7 +6,7 @@ so you need to open `chrome://tracing/` in a Chrome browser and load the generated file to view the result. ```javascript -var contentTracing = require('content-tracing'); +const contentTracing = require('electron').contentTracing; contentTracing.startRecording('*', contentTracing.DEFAULT_OPTIONS, function() { console.log('Tracing started'); diff --git a/docs/api/crash-reporter.md b/docs/api/crash-reporter.md index 64a3b2cf748d..8127c9bc1c93 100644 --- a/docs/api/crash-reporter.md +++ b/docs/api/crash-reporter.md @@ -6,7 +6,7 @@ The following is an example of automatically submitting a crash report to a remote server: ```javascript -var crashReporter = require('crash-reporter'); +const crashReporter = require('electron').crashReporter; crashReporter.start({ productName: 'YourName', @@ -62,7 +62,7 @@ The crash reporter will send the following data to the `submitUrl` as `POST`: * `ver` String - The version of Electron. * `platform` String - e.g. 'win32'. * `process_type` String - e.g. 'renderer'. -* `guid` String - e.g. '5e1286fc-da97-479e-918b-6bfb0c3d1c72' +* `guid` String - e.g. '5e1286fc-da97-479e-918b-6bfb0c3d1c72' * `_version` String - The version in `package.json`. * `_productName` String - The product name in the `crashReporter` `options` object. diff --git a/docs/api/dialog.md b/docs/api/dialog.md index 6acfb79884e3..884fb7c07327 100644 --- a/docs/api/dialog.md +++ b/docs/api/dialog.md @@ -8,7 +8,7 @@ An example of showing a dialog to select multiple files and directories: ```javascript var win = ...; // BrowserWindow in which to show the dialog -var dialog = require('dialog'); +const dialog = require('electron').dialog; console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]})); ``` @@ -114,6 +114,6 @@ will be passed via `callback(response)`. Displays a modal dialog that shows an error message. This API can be called safely before the `ready` event the `app` module emits, -it is usually used to report errors in early stage of startup. If called -before the app `ready`event on Linux, the message will be emitted to stderr, +it is usually used to report errors in early stage of startup. If called +before the app `ready`event on Linux, the message will be emitted to stderr, and no GUI dialog will appear. diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index 707a928f9db6..e70749f2894c 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -9,7 +9,7 @@ To create a frameless window, you need to set `frame` to `false` in ```javascript -var BrowserWindow = require('browser-window'); +const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({ width: 800, height: 600, frame: false }); ``` @@ -23,8 +23,7 @@ the window controls ("traffic lights") for standard window actions. You can do so by specifying the new `title-bar-style` option: ```javascript -var BrowserWindow = require('browser-window'); -var win = new BrowserWindow({ width: 800, height: 600, 'title-bar-style': 'hidden' }); +var win = new BrowserWindow({ 'title-bar-style': 'hidden' }); ``` ## Transparent window diff --git a/docs/api/global-shortcut.md b/docs/api/global-shortcut.md index c9dfb194529a..a0f069d7f1c5 100644 --- a/docs/api/global-shortcut.md +++ b/docs/api/global-shortcut.md @@ -9,8 +9,9 @@ not have the keyboard focus. You should not use this module until the `ready` event of the app module is emitted. ```javascript -var app = require('app'); -var globalShortcut = require('global-shortcut'); +const electron = require('electron'); +const app = electron.app; +const globalShortcut = electron.globalShortcut; app.on('ready', function() { // Register a 'ctrl+x' shortcut listener. diff --git a/docs/api/ipc-main.md b/docs/api/ipc-main.md index f74c70426a5c..cdbc0ce34eec 100644 --- a/docs/api/ipc-main.md +++ b/docs/api/ipc-main.md @@ -19,7 +19,7 @@ processes: ```javascript // In main process. -var ipcMain = require('ipc-main'); +const ipcMain = require('electron').ipcMain; ipcMain.on('asynchronous-message', function(event, arg) { console.log(arg); // prints "ping" event.sender.send('asynchronous-reply', 'pong'); @@ -33,7 +33,7 @@ ipcMain.on('synchronous-message', function(event, arg) { ```javascript // In renderer process (web page). -var ipcRenderer = require('ipc-renderer'); +const ipcRenderer = require('electron').ipcRenderer; console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong" ipcRenderer.on('asynchronous-reply', function(event, arg) { diff --git a/docs/api/menu.md b/docs/api/menu.md index cabd04ca8550..c947f36d4790 100644 --- a/docs/api/menu.md +++ b/docs/api/menu.md @@ -16,9 +16,9 @@ the user right clicks the page: ```html diff --git a/docs/api/tray.md b/docs/api/tray.md index 47f02c5478fa..ff4310308a86 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -4,9 +4,10 @@ A `Tray` represents an icon in an operating system's notification area, it is usually attached with a context menu. ```javascript -var app = require('app'); -var Menu = require('menu'); -var Tray = require('tray'); +const electron = require('electron'); +const app = electron.app; +const Menu = electron.Menu; +const Tray = electron.Tray; var appIcon = null; app.on('ready', function(){ diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index d62706b2ba9a..aff5752ab55f 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -8,7 +8,7 @@ the [`BrowserWindow`](browser-window.md) object. An example of accessing the `webContents` object: ```javascript -var BrowserWindow = require('browser-window'); +const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({width: 800, height: 1500}); win.loadUrl("http://github.com"); @@ -211,17 +211,15 @@ e.g. the `http://` or `file://`. ### `webContents.getUrl()` -```javascript -var BrowserWindow = require('browser-window'); +Returns URL of the current web page. +```javascript var win = new BrowserWindow({width: 800, height: 600}); win.loadUrl("http://github.com"); var currentUrl = win.webContents.getUrl(); ``` -Returns URL of the current web page. - ### `webContents.getTitle()` Returns the title of the current web page. @@ -445,8 +443,8 @@ By default, an empty `options` will be regarded as: ``` ```javascript -var BrowserWindow = require('browser-window'); -var fs = require('fs'); +const BrowserWindow = require('electron').BrowserWindow; +const fs = require('fs'); var win = new BrowserWindow({width: 800, height: 600}); win.loadUrl("http://github.com"); @@ -538,7 +536,7 @@ app.on('ready', function() { diff --git a/docs/api/web-frame.md b/docs/api/web-frame.md index 33597543b773..c9cfb48f3437 100644 --- a/docs/api/web-frame.md +++ b/docs/api/web-frame.md @@ -6,7 +6,7 @@ web page. An example of zooming current page to 200%. ```javascript -var webFrame = require('web-frame'); +var webFrame = require('electron').webFrame; webFrame.setZoomFactor(2); ``` @@ -59,7 +59,7 @@ whether the word passed is correctly spelled. An example of using [node-spellchecker][spellchecker] as provider: ```javascript -require('web-frame').setSpellCheckProvider("en-US", true, { +webFrame.setSpellCheckProvider("en-US", true, { spellCheck: function(text) { return !(require('spellchecker').isMisspelled(text)); } diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 9a0e0be33b36..a12ec447138f 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -515,7 +515,7 @@ The following example code opens the new url in system's default browser. ```javascript webview.addEventListener('new-window', function(e) { - require('shell').openExternal(e.url); + require('electron').shell.openExternal(e.url); }); ``` @@ -555,9 +555,9 @@ webview.send('ping'); ```javascript // In guest page. -var ipc = require('ipc'); -ipc.on('ping', function() { - ipc.sendToHost('pong'); +var ipcRenderer = require('electron').ipcRenderer; +ipcRenderer.on('ping', function() { + ipcRenderer.sendToHost('pong'); }); ``` diff --git a/docs/tutorial/application-packaging.md b/docs/tutorial/application-packaging.md index 0cf3a6b596f4..7c1ea773e2ff 100644 --- a/docs/tutorial/application-packaging.md +++ b/docs/tutorial/application-packaging.md @@ -51,14 +51,14 @@ $ asar list /path/to/example.asar Read a file in the `asar` archive: ```javascript -var fs = require('fs'); +const fs = require('fs'); fs.readFileSync('/path/to/example.asar/file.txt'); ``` List all files under the root of the archive: ```javascript -var fs = require('fs'); +const fs = require('fs'); fs.readdirSync('/path/to/example.asar'); ``` @@ -71,7 +71,7 @@ require('/path/to/example.asar/dir/module.js'); You can also display a web page in an `asar` archive with `BrowserWindow`: ```javascript -var BrowserWindow = require('browser-window'); +const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({width: 800, height: 600}); win.loadUrl('file:///path/to/example.asar/static/index.html'); ``` diff --git a/docs/tutorial/desktop-environment-integration.md b/docs/tutorial/desktop-environment-integration.md index 39f74ff10771..7c4807d8f4d4 100644 --- a/docs/tutorial/desktop-environment-integration.md +++ b/docs/tutorial/desktop-environment-integration.md @@ -86,7 +86,6 @@ To add a file to recent documents, you can use the [app.addRecentDocument][addrecentdocument] API: ```javascript -var app = require('app'); app.addRecentDocument('/Users/USERNAME/Desktop/work.type'); ``` @@ -125,8 +124,10 @@ To set your custom dock menu, you can use the `app.dock.setMenu` API, which is only available on OS X: ```javascript -var app = require('app'); -var Menu = require('menu'); +const electron = require('electron'); +const app = electron.app; +const Menu = electron.Menu; + var dockMenu = Menu.buildFromTemplate([ { label: 'New Window', click: function() { console.log('New Window'); } }, { label: 'New Window with Settings', submenu: [ @@ -172,7 +173,6 @@ To set user tasks for your application, you can use [app.setUserTasks][setusertaskstasks] API: ```javascript -var app = require('app'); app.setUserTasks([ { program: process.execPath, @@ -220,8 +220,9 @@ You can use [BrowserWindow.setThumbarButtons][setthumbarbuttons] to set thumbnail toolbar in your application: ```javascript -var BrowserWindow = require('browser-window'); -var path = require('path'); +const BrowserWindow = require('electron').BrowserWindow; +const path = require('path'); + var win = new BrowserWindow({ width: 800, height: 600 diff --git a/docs/tutorial/devtools-extension.md b/docs/tutorial/devtools-extension.md index 8a2144be6966..258fb41947ff 100644 --- a/docs/tutorial/devtools-extension.md +++ b/docs/tutorial/devtools-extension.md @@ -24,14 +24,15 @@ Then you can load the extension in Electron by opening DevTools in any window, and running the following code in the DevTools console: ```javascript -require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools/shells/chrome'); +const BrowserWindow = require('electron').remote.require('electron').BrowserWindow; +BrowserWindow.addDevToolsExtension('/some-directory/react-devtools/shells/chrome'); ``` To unload the extension, you can call the `BrowserWindow.removeDevToolsExtension` API with its name and it will not load the next time you open the DevTools: ```javascript -require('remote').require('browser-window').removeDevToolsExtension('React Developer Tools'); +BrowserWindow.removeDevToolsExtension('React Developer Tools'); ``` ## Format of DevTools Extension diff --git a/docs/tutorial/online-offline-events.md b/docs/tutorial/online-offline-events.md index 46d659e07d05..6e031282b55a 100644 --- a/docs/tutorial/online-offline-events.md +++ b/docs/tutorial/online-offline-events.md @@ -6,10 +6,11 @@ using standard HTML5 APIs, as shown in the following example. _main.js_ ```javascript -var app = require('app'); -var BrowserWindow = require('browser-window'); -var onlineStatusWindow; +const electron = require('electron'); +const app = electron.app; +const BrowserWindow = electron.BrowserWindow; +var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); @@ -45,11 +46,12 @@ to the main process and handled as needed, as shown in the following example. _main.js_ ```javascript -var app = require('app'); -var ipcMain = require('ipc-main'); -var BrowserWindow = require('browser-window'); -var onlineStatusWindow; +const electron = require('electron'); +const app = electron.app; +const ipcMain = electron.ipcMain; +const BrowserWindow = electron.BrowserWindow; +var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); @@ -67,7 +69,7 @@ _online-status.html_ - + + + ``` To run your app, read [Run your app](../tutorial/quick-start.md#run-your-app). + +## Destructuring assignment + +If you are using CoffeeScript or Babel, you can also use +[destructuring assignment][desctructuring-assignment] to make it easier to use +built-in modules: + +```javascript +const {app, BrowserWindow} = require('electron') +``` + +However if you are using plain JavaScript, you have to wait until Chrome fully +supports ES6. + +## Disable old styles of using built-in modules + +Before v0.35.0, all built-in modules have to be used in the form of +`require('module-name')`, though it has [many disadvantages][issue-387], we are +still supporting it for compatibility with old apps. + +To disable the old styles completely, you can set the +`ELECTRON_HIDE_INTERNAL_MODULES` environment variable: + +```javascript +process.env.ELECTRON_HIDE_INTERNAL_MODULES = 'true' +``` + +Or call the `hideInternalModules` API: + +```javascript +require('electron').hideInternalModules() +``` + +[gui]: https://en.wikipedia.org/wiki/Graphical_user_interface +[main-process]: ../tutorial/quick-start.md#the-main-process +[desctructuring-assignment]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment +[issue-387]: https://github.com/atom/electron/issues/387 From edd807d2271634dbe1228f13863a034e5801ed29 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Nov 2015 22:56:18 +0800 Subject: [PATCH 476/738] Fix a typo --- atom/browser/api/lib/app.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 0113e90a1a1f..3494a6e6e431 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -9,10 +9,10 @@ app = bindings.app app.__proto__ = EventEmitter.prototype app.setApplicationMenu = (menu) -> - electron.menu.setApplicationMenu menu + electron.Menu.setApplicationMenu menu app.getApplicationMenu = -> - electron.menu.getApplicationMenu() + electron.Menu.getApplicationMenu() app.commandLine = appendSwitch: bindings.appendSwitch, From ce6a7c7d088eb0dc387a99c6ed74fd9ee839a0eb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Nov 2015 23:02:39 +0800 Subject: [PATCH 477/738] spec: Disable old APIs in tests --- script/test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/script/test.py b/script/test.py index 28aeac9dc1ff..7f75d3113d69 100755 --- a/script/test.py +++ b/script/test.py @@ -16,6 +16,9 @@ PRODUCT_NAME = atom_gyp()['product_name%'] def main(): os.chdir(SOURCE_ROOT) + # Disable old APIs + os.environ['ELECTRON_HIDE_INTERNAL_MODULES'] = 'true' + config = 'D' if len(sys.argv) == 2 and sys.argv[1] == '-R': config = 'R' From d072e612823bdf342b519c866e09c55269b0cadf Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 5 Nov 2015 19:36:36 +0530 Subject: [PATCH 478/738] session: api to allow handling certificate verification --- atom/browser/api/atom_api_app.cc | 15 ---- atom/browser/api/atom_api_session.cc | 7 ++ atom/browser/atom_browser_context.cc | 5 ++ atom/browser/atom_browser_context.h | 1 + atom/browser/atom_cert_verifier.cc | 84 +++++++++++++++++++ atom/browser/atom_cert_verifier.h | 47 +++++++++++ atom/browser/browser.cc | 10 +++ atom/browser/browser.h | 4 + atom/browser/browser_observer.h | 11 +++ .../native_mate_converters/net_converter.cc | 19 +++++ .../native_mate_converters/net_converter.h | 8 ++ docs/api/app.md | 4 +- docs/api/session.md | 31 +++++++ filenames.gypi | 2 + 14 files changed, 231 insertions(+), 17 deletions(-) create mode 100644 atom/browser/atom_cert_verifier.cc create mode 100644 atom/browser/atom_cert_verifier.h diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 1c5c2c04f145..e4d9c9ab6460 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -61,21 +61,6 @@ struct Converter { }; #endif -template<> -struct Converter> { - static v8::Local ToV8( - v8::Isolate* isolate, - const scoped_refptr& val) { - mate::Dictionary dict(isolate, v8::Object::New(isolate)); - std::string encoded_data; - net::X509Certificate::GetPEMEncoded( - val->os_cert_handle(), &encoded_data); - dict.Set("data", encoded_data); - dict.Set("issuerName", val->issuer().GetDisplayName()); - return dict.GetHandle(); - } -}; - } // namespace mate diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 0ec9c05ed84e..f94d879fcc15 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -13,9 +13,11 @@ #include "atom/browser/api/save_page_handler.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" +#include "atom/browser/browser.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" +#include "atom/common/native_mate_converters/net_converter.h" #include "atom/common/node_includes.h" #include "base/files/file_path.h" #include "base/prefs/pref_service.h" @@ -365,6 +367,7 @@ v8::Local Session::Cookies(v8::Isolate* isolate) { mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( v8::Isolate* isolate) { + auto browser = base::Unretained(Browser::Get()); return mate::ObjectTemplateBuilder(isolate) .SetMethod("resolveProxy", &Session::ResolveProxy) .SetMethod("clearCache", &Session::ClearCache) @@ -373,6 +376,10 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( .SetMethod("setDownloadPath", &Session::SetDownloadPath) .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation) .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation) + .SetMethod("setCertificateVerifier", + base::Bind(&Browser::SetCertificateVerifier, browser)) + .SetMethod("removeCertificateVerifier", + base::Bind(&Browser::RemoveCertificateVerifier, browser)) .SetProperty("cookies", &Session::Cookies); } diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index 6cfb160489fc..bfb506e8e246 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -5,6 +5,7 @@ #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" +#include "atom/browser/atom_cert_verifier.h" #include "atom/browser/atom_download_manager_delegate.h" #include "atom/browser/atom_ssl_config_service.h" #include "atom/browser/browser.h" @@ -158,6 +159,10 @@ content::BrowserPluginGuestManager* AtomBrowserContext::GetGuestManager() { return guest_manager_.get(); } +net::CertVerifier* AtomBrowserContext::CreateCertVerifier() { + return new AtomCertVerifier; +} + net::SSLConfigService* AtomBrowserContext::CreateSSLConfigService() { return new AtomSSLConfigService; } diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index aafa092442bc..81f9533c9c5e 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -27,6 +27,7 @@ class AtomBrowserContext : public brightray::BrowserContext { content::URLRequestInterceptorScopedVector* interceptors) override; net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory( const base::FilePath& base_path) override; + net::CertVerifier* CreateCertVerifier() override; net::SSLConfigService* CreateSSLConfigService() override; bool AllowNTLMCredentialsForDomain(const GURL& auth_origin) override; diff --git a/atom/browser/atom_cert_verifier.cc b/atom/browser/atom_cert_verifier.cc new file mode 100644 index 000000000000..d8d1cb112dc2 --- /dev/null +++ b/atom/browser/atom_cert_verifier.cc @@ -0,0 +1,84 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/atom_cert_verifier.h" + +#include "atom/browser/browser.h" +#include "atom/common/native_mate_converters/net_converter.h" +#include "content/public/browser/browser_thread.h" +#include "net/base/net_errors.h" +#include "net/cert/x509_certificate.h" + +using content::BrowserThread; + +namespace atom { + +namespace { + +void RunResult(const net::CompletionCallback& callback, bool success) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + int result = net::OK; + if (!success) + result = net::ERR_FAILED; + + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(callback, result)); +} + +} // namespace + +AtomCertVerifier::AtomCertVerifier() { + Browser::Get()->AddObserver(this); + default_cert_verifier_.reset(net::CertVerifier::CreateDefault()); +} + +AtomCertVerifier::~AtomCertVerifier() { + Browser::Get()->RemoveObserver(this); +} + +int AtomCertVerifier::Verify( + net::X509Certificate* cert, + const std::string& hostname, + const std::string& ocsp_response, + int flags, + net::CRLSet* crl_set, + net::CertVerifyResult* verify_result, + const net::CompletionCallback& callback, + scoped_ptr* out_req, + const net::BoundNetLog& net_log) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (callback.is_null() || !verify_result || hostname.empty()) + return net::ERR_INVALID_ARGUMENT; + + if (!handler_.is_null()) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(handler_, hostname, + make_scoped_refptr(cert), + base::Bind(&RunResult, callback))); + return net::ERR_IO_PENDING; + } + + return default_cert_verifier_->Verify(cert, hostname, ocsp_response, + flags, crl_set, verify_result, + callback, out_req, net_log); +} + +bool AtomCertVerifier::SupportsOCSPStapling() { + if (handler_.is_null()) + return default_cert_verifier_->SupportsOCSPStapling(); + return false; +} + +void AtomCertVerifier::OnSetCertificateVerifier( + const CertificateVerifier& handler) { + handler_ = handler; +} + +void AtomCertVerifier::OnRemoveCertificateVerifier() { + handler_.Reset(); +} + +} // namespace atom diff --git a/atom/browser/atom_cert_verifier.h b/atom/browser/atom_cert_verifier.h new file mode 100644 index 000000000000..a9e16e268837 --- /dev/null +++ b/atom/browser/atom_cert_verifier.h @@ -0,0 +1,47 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_ATOM_CERT_VERIFIER_H_ +#define ATOM_BROWSER_ATOM_CERT_VERIFIER_H_ + +#include + +#include "atom/browser/browser_observer.h" +#include "net/cert/cert_verifier.h" + +namespace atom { + +class AtomCertVerifier : public net::CertVerifier, + public BrowserObserver { + public: + AtomCertVerifier(); + ~AtomCertVerifier() override; + + // net::CertVerifier: + int Verify(net::X509Certificate* cert, + const std::string& hostname, + const std::string& ocsp_response, + int flags, + net::CRLSet* crl_set, + net::CertVerifyResult* verify_result, + const net::CompletionCallback& callback, + scoped_ptr* out_req, + const net::BoundNetLog& net_log) override; + bool SupportsOCSPStapling() override; + + protected: + void OnSetCertificateVerifier(const CertificateVerifier& handler) override; + void OnRemoveCertificateVerifier() override; + + private: + scoped_ptr default_cert_verifier_; + + CertificateVerifier handler_; + + DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_ATOM_CERT_VERIFIER_H_ diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 57741786520d..2e743ec7535a 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -156,6 +156,16 @@ void Browser::RequestLogin(LoginHandler* login_handler) { FOR_EACH_OBSERVER(BrowserObserver, observers_, OnLogin(login_handler)); } +void Browser::SetCertificateVerifier(const CertificateVerifier& handler) { + FOR_EACH_OBSERVER(BrowserObserver, + observers_, + OnSetCertificateVerifier(handler)); +} + +void Browser::RemoveCertificateVerifier() { + FOR_EACH_OBSERVER(BrowserObserver, observers_, OnRemoveCertificateVerifier()); +} + void Browser::NotifyAndShutdown() { if (is_shutdown_) return; diff --git a/atom/browser/browser.h b/atom/browser/browser.h index e20db080b67a..04278f1b2711 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -135,6 +135,10 @@ class Browser : public WindowListObserver { // Request basic auth login. void RequestLogin(LoginHandler* login_handler); + // Set.remove the ceritificate verifier provided by the user. + void SetCertificateVerifier(const CertificateVerifier& handler); + void RemoveCertificateVerifier(); + void AddObserver(BrowserObserver* obs) { observers_.AddObserver(obs); } diff --git a/atom/browser/browser_observer.h b/atom/browser/browser_observer.h index 7dccbfbac3c5..679a29746324 100644 --- a/atom/browser/browser_observer.h +++ b/atom/browser/browser_observer.h @@ -7,6 +7,7 @@ #include +#include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "content/public/browser/client_certificate_delegate.h" @@ -16,12 +17,19 @@ class WebContents; namespace net { class SSLCertRequestInfo; +class X509Certificate; } namespace atom { class LoginHandler; +// A callback specialisation used by AtomCertVerifier during verification. +using CertificateVerifier = + base::Callback, + const base::Callback&)>; + class BrowserObserver { public: // The browser is about to close all windows. @@ -62,6 +70,9 @@ class BrowserObserver { // The browser requests HTTP login. virtual void OnLogin(LoginHandler* login_handler) {} + virtual void OnSetCertificateVerifier(const CertificateVerifier& handler) {} + virtual void OnRemoveCertificateVerifier() {} + protected: virtual ~BrowserObserver() {} }; diff --git a/atom/common/native_mate_converters/net_converter.cc b/atom/common/native_mate_converters/net_converter.cc index 4796d962660a..4749a4fedfc2 100644 --- a/atom/common/native_mate_converters/net_converter.cc +++ b/atom/common/native_mate_converters/net_converter.cc @@ -4,7 +4,11 @@ #include "atom/common/native_mate_converters/net_converter.h" +#include + +#include "atom/common/node_includes.h" #include "native_mate/dictionary.h" +#include "net/cert/x509_certificate.h" #include "net/url_request/url_request.h" namespace mate { @@ -31,4 +35,19 @@ v8::Local Converter::ToV8( return mate::ConvertToV8(isolate, dict); } +// static +v8::Local Converter>::ToV8( + v8::Isolate* isolate, const scoped_refptr& val) { + mate::Dictionary dict(isolate, v8::Object::New(isolate)); + std::string encoded_data; + net::X509Certificate::GetPEMEncoded( + val->os_cert_handle(), &encoded_data); + auto buffer = node::Buffer::Copy(isolate, + encoded_data.data(), + encoded_data.size()).ToLocalChecked(); + dict.Set("data", buffer); + dict.Set("issuerName", val->issuer().GetDisplayName()); + return dict.GetHandle(); +} + } // namespace mate diff --git a/atom/common/native_mate_converters/net_converter.h b/atom/common/native_mate_converters/net_converter.h index 352c613eaabb..b11c55929b98 100644 --- a/atom/common/native_mate_converters/net_converter.h +++ b/atom/common/native_mate_converters/net_converter.h @@ -5,11 +5,13 @@ #ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_ #define ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_ +#include "base/memory/ref_counted.h" #include "native_mate/converter.h" namespace net { class AuthChallengeInfo; class URLRequest; +class X509Certificate; } namespace mate { @@ -26,6 +28,12 @@ struct Converter { const net::AuthChallengeInfo* val); }; +template<> +struct Converter> { + static v8::Local ToV8(v8::Isolate* isolate, + const scoped_refptr& val); +}; + } // namespace mate #endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_ diff --git a/docs/api/app.md b/docs/api/app.md index fdb9f9980592..ce377d915dac 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -139,8 +139,8 @@ Returns: * `webContents` [WebContents](web-contents.md) * `url` URL * `certificateList` [Objects] - * `data` PEM encoded data - * `issuerName` Issuer's Common Name + * `data` Buffer - PEM encoded data + * `issuerName` String - Issuer's Common Name * `callback` Function Emitted when a client certificate is requested. diff --git a/docs/api/session.md b/docs/api/session.md index 25db92b73b25..c0f1e8fa7955 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -220,3 +220,34 @@ window.webContents.session.enableNetworkEmulation({offline: true}); Disables any network emulation already active for the `session`. Resets to the original network configuration. + +### `session.setCertificateVerifier(handler)` + +* `handler` Function + * `hostname` String + * `certificate` Object + * `data` Buffer - PEM encoded data + * `issuerName` String + * `callback` Function + +Sets the certificate verifier for the `session`, will be called +whenever a server certificate verification is requested by the +network layer with `hostname`, `certificate` and `callback`. +`callback` should be called with a boolean response to +indicate continuation or cancellation of the request. + +```js +var handler = function(hostname, certificate, callback) { + if (hostname == "github.com") { + // verification logic + callback(true) + } + callback(false) +} + +window.webContents.session.setCertificateVerifier(handler) +``` + +### `session.removeCertificateVerifier()` + +Removes the certificate verifier provided for the `session`. diff --git a/filenames.gypi b/filenames.gypi index 4dc709c5ec57..9618a962cd97 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -128,6 +128,8 @@ 'atom/browser/atom_download_manager_delegate.h', 'atom/browser/atom_browser_main_parts.cc', 'atom/browser/atom_browser_main_parts.h', + 'atom/browser/atom_cert_verifier.cc', + 'atom/browser/atom_cert_verifier.h', 'atom/browser/atom_browser_main_parts_mac.mm', 'atom/browser/atom_browser_main_parts_posix.cc', 'atom/browser/atom_javascript_dialog_manager.cc', From 3d5437e0a45b884d850ff125d38c0c49edc4d86f Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 13 Nov 2015 02:36:38 +0530 Subject: [PATCH 479/738] tracing: fix docs and allow null values in file path conversion fromv8 --- atom/common/native_mate_converters/file_path_converter.h | 3 +++ docs/api/content-tracing.md | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/atom/common/native_mate_converters/file_path_converter.h b/atom/common/native_mate_converters/file_path_converter.h index 468f506de8a3..7df1289e243b 100644 --- a/atom/common/native_mate_converters/file_path_converter.h +++ b/atom/common/native_mate_converters/file_path_converter.h @@ -21,6 +21,9 @@ struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Local val, base::FilePath* out) { + if (val->IsNull()) + return true; + base::FilePath::StringType path; if (Converter::FromV8(isolate, val, &path)) { *out = base::FilePath(path); diff --git a/docs/api/content-tracing.md b/docs/api/content-tracing.md index 2e05fc67668f..9fc335b3bc18 100644 --- a/docs/api/content-tracing.md +++ b/docs/api/content-tracing.md @@ -6,9 +6,14 @@ so you need to open `chrome://tracing/` in a Chrome browser and load the generated file to view the result. ```javascript -var contentTracing = require('content-tracing'); +const contentTracing = require('content-tracing'); -contentTracing.startRecording('*', contentTracing.DEFAULT_OPTIONS, function() { +const options = { + categoryFilter: '*', + traceOptions: 'record-until-full,enable-sampling' +} + +contentTracing.startRecording(options, function() { console.log('Tracing started'); setTimeout(function() { From bb439c5f1c1a6a4af88f80067bc7eac262c11dff Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 13 Nov 2015 02:43:21 +0530 Subject: [PATCH 480/738] browser: check window liveness before setting title --- atom/browser/native_window.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 8027fdfa4c1c..ba5dad74f523 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -512,7 +512,7 @@ void NativeWindow::TitleWasSet(content::NavigationEntry* entry, FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnPageTitleUpdated(&prevent_default, text)); - if (!prevent_default) + if (!prevent_default && !is_closed_) SetTitle(text); } From 37e6e6fab78ed0fdb1885301359350cfcb8ffe07 Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 13 Nov 2015 01:25:23 +0530 Subject: [PATCH 481/738] emit verify-certificate event for handling verification --- atom/browser/api/atom_api_session.cc | 30 ++++- atom/browser/api/atom_api_session.h | 7 ++ atom/browser/atom_cert_verifier.cc | 159 +++++++++++++++++++++------ atom/browser/atom_cert_verifier.h | 125 +++++++++++++++++++-- atom/browser/browser.cc | 10 +- atom/browser/browser.h | 7 +- atom/browser/browser_observer.h | 13 +-- docs/api/session.md | 55 ++++----- 8 files changed, 313 insertions(+), 93 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index f94d879fcc15..ecb8bba3a3c2 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -239,12 +239,24 @@ void SetProxyInIO(net::URLRequestContextGetter* getter, RunCallbackInUI(callback); } +void PassVerificationResult( + scoped_refptr request, + bool success) { + int result = net::OK; + if (!success) + result = net::ERR_FAILED; + request->ContinueWithResult(result); +} + } // namespace Session::Session(AtomBrowserContext* browser_context) : browser_context_(browser_context) { AttachAsUserData(browser_context); + // Observe Browser to get certificate verification notification. + Browser::Get()->AddObserver(this); + // Observe DownloadManger to get download notifications. content::BrowserContext::GetDownloadManager(browser_context)-> AddObserver(this); @@ -253,9 +265,22 @@ Session::Session(AtomBrowserContext* browser_context) Session::~Session() { content::BrowserContext::GetDownloadManager(browser_context())-> RemoveObserver(this); + Browser::Get()->RemoveObserver(this); Destroy(); } +void Session::OnCertVerification( + const scoped_refptr& request) { + bool prevent_default = Emit( + "verify-certificate", + request->hostname(), + request->certificate(), + base::Bind(&PassVerificationResult, request)); + + if (!prevent_default) + request->ContinueWithResult(net::ERR_IO_PENDING); +} + void Session::OnDownloadCreated(content::DownloadManager* manager, content::DownloadItem* item) { auto web_contents = item->GetWebContents(); @@ -367,7 +392,6 @@ v8::Local Session::Cookies(v8::Isolate* isolate) { mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( v8::Isolate* isolate) { - auto browser = base::Unretained(Browser::Get()); return mate::ObjectTemplateBuilder(isolate) .SetMethod("resolveProxy", &Session::ResolveProxy) .SetMethod("clearCache", &Session::ClearCache) @@ -376,10 +400,6 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( .SetMethod("setDownloadPath", &Session::SetDownloadPath) .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation) .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation) - .SetMethod("setCertificateVerifier", - base::Bind(&Browser::SetCertificateVerifier, browser)) - .SetMethod("removeCertificateVerifier", - base::Bind(&Browser::RemoveCertificateVerifier, browser)) .SetProperty("cookies", &Session::Cookies); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 39712f6c8486..e6ce5a5842db 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -8,6 +8,8 @@ #include #include "atom/browser/api/trackable_object.h" +#include "atom/browser/atom_cert_verifier.h" +#include "atom/browser/browser_observer.h" #include "content/public/browser/download_manager.h" #include "native_mate/handle.h" #include "net/base/completion_callback.h" @@ -34,6 +36,7 @@ class AtomBrowserContext; namespace api { class Session: public mate::TrackableObject, + public BrowserObserver, public content::DownloadManager::Observer { public: using ResolveProxyCallback = base::Callback; @@ -52,6 +55,10 @@ class Session: public mate::TrackableObject, explicit Session(AtomBrowserContext* browser_context); ~Session(); + // BrowserObserver: + void OnCertVerification( + const scoped_refptr&) override; + // content::DownloadManager::Observer: void OnDownloadCreated(content::DownloadManager* manager, content::DownloadItem* item) override; diff --git a/atom/browser/atom_cert_verifier.cc b/atom/browser/atom_cert_verifier.cc index d8d1cb112dc2..f5afdd35719b 100644 --- a/atom/browser/atom_cert_verifier.cc +++ b/atom/browser/atom_cert_verifier.cc @@ -6,36 +6,108 @@ #include "atom/browser/browser.h" #include "atom/common/native_mate_converters/net_converter.h" +#include "base/callback_helpers.h" +#include "base/sha1.h" +#include "base/stl_util.h" #include "content/public/browser/browser_thread.h" #include "net/base/net_errors.h" -#include "net/cert/x509_certificate.h" using content::BrowserThread; namespace atom { -namespace { - -void RunResult(const net::CompletionCallback& callback, bool success) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - int result = net::OK; - if (!success) - result = net::ERR_FAILED; - - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(callback, result)); +AtomCertVerifier::RequestParams::RequestParams( + const net::SHA1HashValue cert_fingerprint, + const net::SHA1HashValue ca_fingerprint, + const std::string& hostname_arg, + const std::string& ocsp_response_arg, + int flags_arg) + : hostname(hostname_arg), + ocsp_response(ocsp_response_arg), + flags(flags_arg) { + hash_values.reserve(3); + net::SHA1HashValue ocsp_hash; + base::SHA1HashBytes( + reinterpret_cast(ocsp_response.data()), + ocsp_response.size(), ocsp_hash.data); + hash_values.push_back(ocsp_hash); + hash_values.push_back(cert_fingerprint); + hash_values.push_back(ca_fingerprint); } -} // namespace +bool AtomCertVerifier::RequestParams::operator<( + const RequestParams& other) const { + if (flags != other.flags) + return flags < other.flags; + if (hostname != other.hostname) + return hostname < other.hostname; + return std::lexicographical_compare( + hash_values.begin(), + hash_values.end(), + other.hash_values.begin(), + other.hash_values.end(), + net::SHA1HashValueLessThan()); +} + +void AtomCertVerifier::CertVerifyRequest::RunResult(int result) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + for (auto& callback : callbacks_) + callback.Run(result); + cert_verifier_->RemoveRequest(this); + Release(); +} + +void AtomCertVerifier::CertVerifyRequest::DelegateToDefaultVerifier() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + int rv = cert_verifier_->default_cert_verifier()->Verify( + certificate_.get(), + key_.hostname, + key_.ocsp_response, + key_.flags, + crl_set_.get(), + verify_result_, + base::Bind(&CertVerifyRequest::RunResult, + weak_ptr_factory_.GetWeakPtr()), + &new_out_req_, + net_log_); + + if (rv != net::ERR_IO_PENDING && !callbacks_.empty()) { + for (auto& callback : callbacks_) + callback.Run(rv); + cert_verifier_->RemoveRequest(this); + Release(); + } +} + +void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (handled_) + return; + + handled_ = true; + + if (result != net::ERR_IO_PENDING) { + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&CertVerifyRequest::RunResult, + weak_ptr_factory_.GetWeakPtr(), + result)); + return; + } + + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&CertVerifyRequest::DelegateToDefaultVerifier, + weak_ptr_factory_.GetWeakPtr())); +} AtomCertVerifier::AtomCertVerifier() { - Browser::Get()->AddObserver(this); default_cert_verifier_.reset(net::CertVerifier::CreateDefault()); } AtomCertVerifier::~AtomCertVerifier() { - Browser::Get()->RemoveObserver(this); } int AtomCertVerifier::Verify( @@ -53,32 +125,57 @@ int AtomCertVerifier::Verify( if (callback.is_null() || !verify_result || hostname.empty()) return net::ERR_INVALID_ARGUMENT; - if (!handler_.is_null()) { + const RequestParams key(cert->fingerprint(), + cert->ca_fingerprint(), + hostname, + ocsp_response, + flags); + + CertVerifyRequest* request = FindRequest(key); + + if (!request) { + request = new CertVerifyRequest(this, + key, + cert, + crl_set, + verify_result, + out_req, + net_log); + requests_.insert(make_scoped_refptr(request)); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(handler_, hostname, - make_scoped_refptr(cert), - base::Bind(&RunResult, callback))); - return net::ERR_IO_PENDING; + base::Bind(&Browser::RequestCertVerification, + base::Unretained(Browser::Get()), + make_scoped_refptr(request))); } - return default_cert_verifier_->Verify(cert, hostname, ocsp_response, - flags, crl_set, verify_result, - callback, out_req, net_log); + request->AddCompletionCallback(callback); + + return net::ERR_IO_PENDING; } bool AtomCertVerifier::SupportsOCSPStapling() { - if (handler_.is_null()) - return default_cert_verifier_->SupportsOCSPStapling(); - return false; + return true; } -void AtomCertVerifier::OnSetCertificateVerifier( - const CertificateVerifier& handler) { - handler_ = handler; +AtomCertVerifier::CertVerifyRequest* AtomCertVerifier::FindRequest( + const RequestParams& key) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + auto it = std::lower_bound(requests_.begin(), + requests_.end(), + key, + CertVerifyRequestToRequestParamsComparator()); + if (it != requests_.end() && !(key < (*it)->key())) + return (*it).get(); + return nullptr; } -void AtomCertVerifier::OnRemoveCertificateVerifier() { - handler_.Reset(); +void AtomCertVerifier::RemoveRequest(CertVerifyRequest* request) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + bool erased = requests_.erase(request) == 1; + DCHECK(erased); } } // namespace atom diff --git a/atom/browser/atom_cert_verifier.h b/atom/browser/atom_cert_verifier.h index a9e16e268837..27e530074d02 100644 --- a/atom/browser/atom_cert_verifier.h +++ b/atom/browser/atom_cert_verifier.h @@ -5,19 +5,108 @@ #ifndef ATOM_BROWSER_ATOM_CERT_VERIFIER_H_ #define ATOM_BROWSER_ATOM_CERT_VERIFIER_H_ +#include #include +#include -#include "atom/browser/browser_observer.h" +#include "base/memory/ref_counted.h" +#include "net/base/hash_value.h" #include "net/cert/cert_verifier.h" +#include "net/cert/crl_set.h" +#include "net/cert/x509_certificate.h" +#include "net/log/net_log.h" namespace atom { -class AtomCertVerifier : public net::CertVerifier, - public BrowserObserver { +class AtomCertVerifier : public net::CertVerifier { public: + struct RequestParams { + RequestParams( + const net::SHA1HashValue cert_fingerprint, + const net::SHA1HashValue ca_fingerprint, + const std::string& hostname_arg, + const std::string& ocsp_response, + int flags); + ~RequestParams() {} + + bool operator<(const RequestParams& other) const; + + std::string hostname; + std::string ocsp_response; + int flags; + std::vector hash_values; + }; + + class CertVerifyRequest + : public net::CertVerifier::Request, + public base::RefCountedThreadSafe { + public: + CertVerifyRequest( + AtomCertVerifier* cert_verifier, + const RequestParams& key, + scoped_refptr cert, + scoped_refptr crl_set, + net::CertVerifyResult* verify_result, + scoped_ptr* out_req, + const net::BoundNetLog& net_log) + : cert_verifier_(cert_verifier), + key_(key), + certificate_(cert), + crl_set_(crl_set), + verify_result_(verify_result), + out_req_(out_req), + net_log_(net_log), + handled_(false), + weak_ptr_factory_(this) { + out_req_->reset(this); + new_out_req_.reset(new net::CertVerifier::Request()); + } + + ~CertVerifyRequest() { + out_req_->reset(); + } + + void RunResult(int result); + void DelegateToDefaultVerifier(); + void ContinueWithResult(int result); + + void AddCompletionCallback(net::CompletionCallback callback) { + callbacks_.push_back(callback); + } + + const RequestParams key() const { return key_; } + + std::string hostname() const { return key_.hostname; } + + scoped_refptr certificate() const { + return certificate_; + } + + private: + friend class base::RefCountedThreadSafe; + + AtomCertVerifier* cert_verifier_; + const RequestParams key_; + + scoped_refptr certificate_; + scoped_refptr crl_set_; + net::CertVerifyResult* verify_result_; + scoped_ptr* out_req_; + scoped_ptr new_out_req_; + const net::BoundNetLog net_log_; + + std::vector callbacks_; + bool handled_; + + base::WeakPtrFactory weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(CertVerifyRequest); + }; + AtomCertVerifier(); ~AtomCertVerifier() override; + protected: // net::CertVerifier: int Verify(net::X509Certificate* cert, const std::string& hostname, @@ -30,14 +119,34 @@ class AtomCertVerifier : public net::CertVerifier, const net::BoundNetLog& net_log) override; bool SupportsOCSPStapling() override; - protected: - void OnSetCertificateVerifier(const CertificateVerifier& handler) override; - void OnRemoveCertificateVerifier() override; + net::CertVerifier* default_cert_verifier() const { + return default_cert_verifier_.get(); + } private: - scoped_ptr default_cert_verifier_; + CertVerifyRequest* FindRequest(const RequestParams& key); + void RemoveRequest(CertVerifyRequest* request); - CertificateVerifier handler_; + struct CertVerifyRequestToRequestParamsComparator { + bool operator()(const scoped_refptr request, + const RequestParams& key) const { + return request->key() < key; + } + }; + + struct CertVerifyRequestComparator { + bool operator()(const scoped_refptr req1, + const scoped_refptr req2) const { + return req1->key() < req2->key(); + } + }; + + using ActiveRequestSet = + std::set, + CertVerifyRequestComparator>; + ActiveRequestSet requests_; + + scoped_ptr default_cert_verifier_; DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier); }; diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 2e743ec7535a..a3e1f0247cff 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -7,6 +7,7 @@ #include #include "atom/browser/atom_browser_main_parts.h" +#include "atom/browser/atom_cert_verifier.h" #include "atom/browser/native_window.h" #include "atom/browser/window_list.h" #include "base/message_loop/message_loop.h" @@ -156,14 +157,11 @@ void Browser::RequestLogin(LoginHandler* login_handler) { FOR_EACH_OBSERVER(BrowserObserver, observers_, OnLogin(login_handler)); } -void Browser::SetCertificateVerifier(const CertificateVerifier& handler) { +void Browser::RequestCertVerification( + const scoped_refptr& request) { FOR_EACH_OBSERVER(BrowserObserver, observers_, - OnSetCertificateVerifier(handler)); -} - -void Browser::RemoveCertificateVerifier() { - FOR_EACH_OBSERVER(BrowserObserver, observers_, OnRemoveCertificateVerifier()); + OnCertVerification(request)); } void Browser::NotifyAndShutdown() { diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 04278f1b2711..b0ac7d272130 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -29,6 +29,7 @@ class MenuModel; namespace atom { +class AtomCertVerifier; class LoginHandler; // This class is used for control application-wide operations. @@ -135,9 +136,9 @@ class Browser : public WindowListObserver { // Request basic auth login. void RequestLogin(LoginHandler* login_handler); - // Set.remove the ceritificate verifier provided by the user. - void SetCertificateVerifier(const CertificateVerifier& handler); - void RemoveCertificateVerifier(); + // Request Server Certificate Verification. + void RequestCertVerification( + const scoped_refptr& request); void AddObserver(BrowserObserver* obs) { observers_.AddObserver(obs); diff --git a/atom/browser/browser_observer.h b/atom/browser/browser_observer.h index 679a29746324..75f63d85e2b0 100644 --- a/atom/browser/browser_observer.h +++ b/atom/browser/browser_observer.h @@ -7,7 +7,7 @@ #include -#include "base/callback.h" +#include "atom/browser/atom_cert_verifier.h" #include "base/memory/scoped_ptr.h" #include "content/public/browser/client_certificate_delegate.h" @@ -24,12 +24,6 @@ namespace atom { class LoginHandler; -// A callback specialisation used by AtomCertVerifier during verification. -using CertificateVerifier = - base::Callback, - const base::Callback&)>; - class BrowserObserver { public: // The browser is about to close all windows. @@ -70,8 +64,9 @@ class BrowserObserver { // The browser requests HTTP login. virtual void OnLogin(LoginHandler* login_handler) {} - virtual void OnSetCertificateVerifier(const CertificateVerifier& handler) {} - virtual void OnRemoveCertificateVerifier() {} + // The browser requests Server Certificate Verification. + virtual void OnCertVerification( + const scoped_refptr& request) {} protected: virtual ~BrowserObserver() {} diff --git a/docs/api/session.md b/docs/api/session.md index c0f1e8fa7955..928128cca32c 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -34,6 +34,30 @@ session.on('will-download', function(event, item, webContents) { }); ``` +### Event: 'verify-certificate' + +* `event` Event +* `hostname` String +* `certificate` Object + * `data` Buffer - PEM encoded data + * `issuerName` String +* `callback` Function + +Fired whenever a server certificate verification is requested by the +network layer with `hostname`, `certificate` and `callback`. +`callback` should be called with a boolean response to +indicate continuation or cancellation of the request. + +```js +session.on('verify-certificate', function(event, hostname, certificate, callback) { + if (hostname == "github.com") { + // verification logic + callback(true); + } + callback(false); +}); +``` + ## Methods The `session` object has the following methods: @@ -220,34 +244,3 @@ window.webContents.session.enableNetworkEmulation({offline: true}); Disables any network emulation already active for the `session`. Resets to the original network configuration. - -### `session.setCertificateVerifier(handler)` - -* `handler` Function - * `hostname` String - * `certificate` Object - * `data` Buffer - PEM encoded data - * `issuerName` String - * `callback` Function - -Sets the certificate verifier for the `session`, will be called -whenever a server certificate verification is requested by the -network layer with `hostname`, `certificate` and `callback`. -`callback` should be called with a boolean response to -indicate continuation or cancellation of the request. - -```js -var handler = function(hostname, certificate, callback) { - if (hostname == "github.com") { - // verification logic - callback(true) - } - callback(false) -} - -window.webContents.session.setCertificateVerifier(handler) -``` - -### `session.removeCertificateVerifier()` - -Removes the certificate verifier provided for the `session`. From 852500e5faade74d7cf41f257150af7f6c752a63 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 09:38:22 +0800 Subject: [PATCH 482/738] Fix a few places using old style require --- atom/browser/api/lib/auto-updater/auto-updater-win.coffee | 4 ++-- atom/common/api/lib/clipboard.coffee | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee index a9a61d8efe3f..12ebedaaf71c 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee @@ -1,6 +1,6 @@ -app = require 'app' -url = require 'url' +{app} = require 'electron' {EventEmitter} = require 'events' +url = require 'url' squirrelUpdate = require './squirrel-update-win' diff --git a/atom/common/api/lib/clipboard.coffee b/atom/common/api/lib/clipboard.coffee index b337f7195079..0ea97d86ba81 100644 --- a/atom/common/api/lib/clipboard.coffee +++ b/atom/common/api/lib/clipboard.coffee @@ -1,6 +1,6 @@ if process.platform is 'linux' and process.type is 'renderer' {remote} = require 'electron' # On Linux we could not access clipboard in renderer process. - module.exports = remote.require 'clipboard' + module.exports = remote.getBuiltin 'clipboard' else module.exports = process.atomBinding 'clipboard' From bfaa50a79ea2c28c7a0c71fde17efd048ed6eaff Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 13 Nov 2015 07:44:05 +0530 Subject: [PATCH 483/738] retrieve download directory using on linux --- atom/browser/api/atom_api_app.cc | 17 ++++++++++++++++- docs/api/app.md | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 1c5c2c04f145..d6d961a08dc4 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -22,6 +22,7 @@ #include "base/command_line.h" #include "base/environment.h" #include "base/files/file_path.h" +#include "base/nix/xdg_util.h" #include "base/path_service.h" #include "brightray/browser/brightray_paths.h" #include "content/public/browser/client_certificate_delegate.h" @@ -155,6 +156,17 @@ void PassLoginInformation(scoped_refptr login_handler, login_handler->CancelAuth(); } +bool GetUserDownloadsDirectory(base::FilePath* path) { +#if defined(OS_LINUX) + *path = base::nix::GetXDGUserDirectory("DOWNLOAD", "Downloads"); + return true; +#elif defined(OS_MACOSX) + return false; +#elif defined(OS_WIN) + return false; +#endif +} + } // namespace App::App() { @@ -272,8 +284,11 @@ base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) { int key = GetPathConstant(name); if (key >= 0) succeed = PathService::Get(key, &path); - if (!succeed) + if (!succeed) { + if (name == "downloads" && GetUserDownloadsDirectory(&path)) + return path; args->ThrowError("Failed to get path"); + } return path; } diff --git a/docs/api/app.md b/docs/api/app.md index fdb9f9980592..4282b2d133ac 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -241,6 +241,7 @@ You can request the following paths by the name: * `userDesktop` The current user's Desktop directory. * `exe` The current executable file. * `module` The `libchromiumcontent` library. +* `downloads` User's download directory. ### `app.setPath(name, path)` From f2439cefd0dba89df02993011ac46dd32a1f79a6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 10:58:10 +0800 Subject: [PATCH 484/738] linux: Don't throw error when using autoUpdater Fix #3194. --- atom/browser/api/lib/auto-updater.coffee | 10 ++++------ ...o-updater-mac.coffee => auto-updater-native.coffee} | 0 filenames.gypi | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) rename atom/browser/api/lib/auto-updater/{auto-updater-mac.coffee => auto-updater-native.coffee} (100%) diff --git a/atom/browser/api/lib/auto-updater.coffee b/atom/browser/api/lib/auto-updater.coffee index 41b78a00d7e0..d5e69e2a5c2e 100644 --- a/atom/browser/api/lib/auto-updater.coffee +++ b/atom/browser/api/lib/auto-updater.coffee @@ -1,7 +1,5 @@ -switch process.platform - when 'win32' - module.exports = require './auto-updater/auto-updater-win' - when 'darwin' - module.exports = require './auto-updater/auto-updater-mac' +module.exports = + if process.platform is 'win32' + require './auto-updater/auto-updater-win' else - throw new Error('auto-updater is not implemented on this platform') + require './auto-updater/auto-updater-native' diff --git a/atom/browser/api/lib/auto-updater/auto-updater-mac.coffee b/atom/browser/api/lib/auto-updater/auto-updater-native.coffee similarity index 100% rename from atom/browser/api/lib/auto-updater/auto-updater-mac.coffee rename to atom/browser/api/lib/auto-updater/auto-updater-native.coffee diff --git a/filenames.gypi b/filenames.gypi index de7ee26c5e41..658c8e76b6b0 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -10,7 +10,7 @@ 'coffee_sources': [ 'atom/browser/api/lib/app.coffee', 'atom/browser/api/lib/auto-updater.coffee', - 'atom/browser/api/lib/auto-updater/auto-updater-mac.coffee', + 'atom/browser/api/lib/auto-updater/auto-updater-native.coffee', 'atom/browser/api/lib/auto-updater/auto-updater-win.coffee', 'atom/browser/api/lib/auto-updater/squirrel-update-win.coffee', 'atom/browser/api/lib/browser-window.coffee', From 78934dceb9dee799b07aedd8c3bdc1ddf42cae6c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 12:22:08 +0800 Subject: [PATCH 485/738] Cleanup and docs for the --js-flags --- atom/browser/javascript_environment.cc | 17 +++++++---------- docs/api/chrome-command-line-switches.md | 9 +++++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/atom/browser/javascript_environment.cc b/atom/browser/javascript_environment.cc index ae4f8e55e76e..dc27cedee56f 100644 --- a/atom/browser/javascript_environment.cc +++ b/atom/browser/javascript_environment.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#include - #include "atom/browser/javascript_environment.h" +#include + #include "base/command_line.h" +#include "content/public/common/content_switches.h" #include "gin/array_buffer.h" #include "gin/v8_initializer.h" @@ -30,17 +31,13 @@ bool JavascriptEnvironment::Initialize() { v8::V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1); } - const std::string js_flags_switch = "js-flags"; - - if (cmd->HasSwitch(js_flags_switch)) { - const char *js_flags_value = - (cmd->GetSwitchValueASCII(js_flags_switch)).c_str(); - v8::V8::SetFlagsFromString(js_flags_value, strlen(js_flags_value)); - } + // --js-flags. + std::string js_flags = cmd->GetSwitchValueASCII(switches::kJavaScriptFlags); + if (!js_flags.empty()) + v8::V8::SetFlagsFromString(js_flags.c_str(), js_flags.size()); gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, gin::ArrayBufferAllocator::SharedInstance()); - return true; } diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index d163a726d40e..c1adf3c425f8 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -31,6 +31,15 @@ Disables the disk cache for HTTP requests. Enables remote debugging over HTTP on the specified `port`. +## --js-flags=`flags` + +Specifies the flags passed to JS engine. It has to be passed when starting +Electron if you want to enable the `flags` in the main process. + +```bash +$ electron --js-flags="--harmony_proxies --harmony_collections" your-app +``` + ## --proxy-server=`address:port` Use a specified proxy server, which overrides the system setting. This switch From 83ae9f8d71007944b9f9e5b631740ea7a416e1b9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 12:37:12 +0800 Subject: [PATCH 486/738] Import the chrome_paths code --- .../chrome/common/chrome_constants.cc | 68 ++ chromium_src/chrome/common/chrome_constants.h | 50 ++ chromium_src/chrome/common/chrome_paths.cc | 610 ++++++++++++++++++ chromium_src/chrome/common/chrome_paths.h | 152 +++++ .../chrome/common/chrome_paths_internal.h | 112 ++++ .../chrome/common/chrome_paths_linux.cc | 145 +++++ .../chrome/common/chrome_paths_mac.mm | 252 ++++++++ .../chrome/common/chrome_paths_win.cc | 122 ++++ filenames.gypi | 8 + 9 files changed, 1519 insertions(+) create mode 100644 chromium_src/chrome/common/chrome_constants.cc create mode 100644 chromium_src/chrome/common/chrome_constants.h create mode 100644 chromium_src/chrome/common/chrome_paths.cc create mode 100644 chromium_src/chrome/common/chrome_paths.h create mode 100644 chromium_src/chrome/common/chrome_paths_internal.h create mode 100644 chromium_src/chrome/common/chrome_paths_linux.cc create mode 100644 chromium_src/chrome/common/chrome_paths_mac.mm create mode 100644 chromium_src/chrome/common/chrome_paths_win.cc diff --git a/chromium_src/chrome/common/chrome_constants.cc b/chromium_src/chrome/common/chrome_constants.cc new file mode 100644 index 000000000000..1e7bd33a9658 --- /dev/null +++ b/chromium_src/chrome/common/chrome_constants.cc @@ -0,0 +1,68 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_version.h" + +namespace chrome { + +// filenames +const base::FilePath::CharType kCacheDirname[] = FPL("Cache"); +const base::FilePath::CharType kChannelIDFilename[] = FPL("Origin Bound Certs"); +const base::FilePath::CharType kCookieFilename[] = FPL("Cookies"); +const base::FilePath::CharType kCRLSetFilename[] = + FPL("Certificate Revocation Lists"); +const base::FilePath::CharType kCustomDictionaryFileName[] = + FPL("Custom Dictionary.txt"); +const base::FilePath::CharType kExtensionActivityLogFilename[] = + FPL("Extension Activity"); +const base::FilePath::CharType kExtensionsCookieFilename[] = + FPL("Extension Cookies"); +const base::FilePath::CharType kFirstRunSentinel[] = FPL("First Run"); +const base::FilePath::CharType kGCMStoreDirname[] = FPL("GCM Store"); +const base::FilePath::CharType kLocalStateFilename[] = FPL("Local State"); +const base::FilePath::CharType kLocalStorePoolName[] = FPL("LocalStorePool"); +const base::FilePath::CharType kMediaCacheDirname[] = FPL("Media Cache"); +const base::FilePath::CharType kNetworkPersistentStateFilename[] = + FPL("Network Persistent State"); +const base::FilePath::CharType kOfflinePageArchviesDirname[] = + FPL("Offline Pages/archives"); +const base::FilePath::CharType kOfflinePageMetadataDirname[] = + FPL("Offline Pages/metadata"); +const base::FilePath::CharType kPreferencesFilename[] = FPL("Preferences"); +const base::FilePath::CharType kProtectedPreferencesFilenameDeprecated[] = + FPL("Protected Preferences"); +const base::FilePath::CharType kReadmeFilename[] = FPL("README"); +const base::FilePath::CharType kResetPromptMementoFilename[] = + FPL("Reset Prompt Memento"); +const base::FilePath::CharType kSafeBrowsingBaseFilename[] = + FPL("Safe Browsing"); +const base::FilePath::CharType kSecurePreferencesFilename[] = + FPL("Secure Preferences"); +const base::FilePath::CharType kServiceStateFileName[] = FPL("Service State"); +const base::FilePath::CharType kSingletonCookieFilename[] = + FPL("SingletonCookie"); +const base::FilePath::CharType kSingletonLockFilename[] = FPL("SingletonLock"); +const base::FilePath::CharType kSingletonSocketFilename[] = + FPL("SingletonSocket"); +const base::FilePath::CharType kSupervisedUserSettingsFilename[] = + FPL("Managed Mode Settings"); +const base::FilePath::CharType kThemePackFilename[] = FPL("Cached Theme.pak"); +const base::FilePath::CharType kThemePackMaterialDesignFilename[] = + FPL("Cached Theme Material Design.pak"); +const base::FilePath::CharType kWebAppDirname[] = FPL("Web Applications"); + +// File name of the Pepper Flash plugin on different platforms. +const base::FilePath::CharType kPepperFlashPluginFilename[] = +#if defined(OS_MACOSX) + FPL("PepperFlashPlayer.plugin"); +#elif defined(OS_WIN) + FPL("pepflashplayer.dll"); +#else // OS_LINUX, etc. + FPL("libpepflashplayer.so"); +#endif + +} // namespace chrome + +#undef FPL diff --git a/chromium_src/chrome/common/chrome_constants.h b/chromium_src/chrome/common/chrome_constants.h new file mode 100644 index 000000000000..e36eeeeff413 --- /dev/null +++ b/chromium_src/chrome/common/chrome_constants.h @@ -0,0 +1,50 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// A handful of resource-like constants related to the Chrome application. + +#ifndef CHROME_COMMON_CHROME_CONSTANTS_H_ +#define CHROME_COMMON_CHROME_CONSTANTS_H_ + +#include "base/files/file_path.h" + +namespace chrome { + +// filenames +extern const base::FilePath::CharType kCacheDirname[]; +extern const base::FilePath::CharType kChannelIDFilename[]; +extern const base::FilePath::CharType kCookieFilename[]; +extern const base::FilePath::CharType kCRLSetFilename[]; +extern const base::FilePath::CharType kCustomDictionaryFileName[]; +extern const base::FilePath::CharType kExtensionActivityLogFilename[]; +extern const base::FilePath::CharType kExtensionsCookieFilename[]; +extern const base::FilePath::CharType kFirstRunSentinel[]; +extern const base::FilePath::CharType kGCMStoreDirname[]; +extern const base::FilePath::CharType kLocalStateFilename[]; +extern const base::FilePath::CharType kLocalStorePoolName[]; +extern const base::FilePath::CharType kMediaCacheDirname[]; +extern const base::FilePath::CharType kNetworkPersistentStateFilename[]; +extern const base::FilePath::CharType kOfflinePageArchviesDirname[]; +extern const base::FilePath::CharType kOfflinePageMetadataDirname[]; +extern const base::FilePath::CharType kPreferencesFilename[]; +extern const base::FilePath::CharType kProtectedPreferencesFilenameDeprecated[]; +extern const base::FilePath::CharType kReadmeFilename[]; +extern const base::FilePath::CharType kResetPromptMementoFilename[]; +extern const base::FilePath::CharType kSafeBrowsingBaseFilename[]; +extern const base::FilePath::CharType kSecurePreferencesFilename[]; +extern const base::FilePath::CharType kServiceStateFileName[]; +extern const base::FilePath::CharType kSingletonCookieFilename[]; +extern const base::FilePath::CharType kSingletonLockFilename[]; +extern const base::FilePath::CharType kSingletonSocketFilename[]; +extern const base::FilePath::CharType kSupervisedUserSettingsFilename[]; +extern const base::FilePath::CharType kThemePackFilename[]; +extern const base::FilePath::CharType kThemePackMaterialDesignFilename[]; +extern const base::FilePath::CharType kWebAppDirname[]; + +// File name of the Pepper Flash plugin on different platforms. +extern const base::FilePath::CharType kPepperFlashPluginFilename[]; + +} // namespace chrome + +#endif // CHROME_COMMON_CHROME_CONSTANTS_H_ diff --git a/chromium_src/chrome/common/chrome_paths.cc b/chromium_src/chrome/common/chrome_paths.cc new file mode 100644 index 000000000000..d8a32446fe9e --- /dev/null +++ b/chromium_src/chrome/common/chrome_paths.cc @@ -0,0 +1,610 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/chrome_paths.h" + +#include "base/files/file_util.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/mac/bundle_locations.h" +#include "base/path_service.h" +#include "base/strings/string_util.h" +#include "base/sys_info.h" +#include "base/threading/thread_restrictions.h" +#include "base/version.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths_internal.h" + +#if defined(OS_ANDROID) +#include "base/android/path_utils.h" +#include "base/base_paths_android.h" +// ui/base must only be used on Android. See BUILD.gn for dependency info. +#include "ui/base/ui_base_paths.h" // nogncheck +#endif + +#if defined(OS_MACOSX) +#include "base/mac/foundation_util.h" +#endif + +#if defined(OS_WIN) +#include "base/win/registry.h" +#endif + +namespace { + +// The Pepper Flash plugins are in a directory with this name. +const base::FilePath::CharType kPepperFlashBaseDirectory[] = + FILE_PATH_LITERAL("PepperFlash"); + +#if defined(OS_MACOSX) && !defined(OS_IOS) +const base::FilePath::CharType kPepperFlashSystemBaseDirectory[] = + FILE_PATH_LITERAL("Internet Plug-Ins/PepperFlashPlayer"); +const base::FilePath::CharType kFlashSystemBaseDirectory[] = + FILE_PATH_LITERAL("Internet Plug-Ins"); +const base::FilePath::CharType kFlashSystemPluginName[] = + FILE_PATH_LITERAL("Flash Player.plugin"); +#endif + +const base::FilePath::CharType kInternalNaClPluginFileName[] = + FILE_PATH_LITERAL("internal-nacl-plugin"); + +#if defined(OS_LINUX) +// The path to the external extension .json files. +// /usr/share seems like a good choice, see: http://www.pathname.com/fhs/ +const base::FilePath::CharType kFilepathSinglePrefExtensions[] = +#if defined(GOOGLE_CHROME_BUILD) + FILE_PATH_LITERAL("/usr/share/google-chrome/extensions"); +#else + FILE_PATH_LITERAL("/usr/share/chromium/extensions"); +#endif // defined(GOOGLE_CHROME_BUILD) + +// The path to the hint file that tells the pepper plugin loader +// where it can find the latest component updated flash. +const base::FilePath::CharType kComponentUpdatedFlashHint[] = + FILE_PATH_LITERAL("latest-component-updated-flash"); +#endif // defined(OS_LINUX) + +static base::LazyInstance + g_invalid_specified_user_data_dir = LAZY_INSTANCE_INITIALIZER; + +// Gets the path for internal plugins. +bool GetInternalPluginsDirectory(base::FilePath* result) { +#if defined(OS_MACOSX) && !defined(OS_IOS) + // If called from Chrome, get internal plugins from a subdirectory of the + // framework. + if (base::mac::AmIBundled()) { + *result = chrome::GetFrameworkBundlePath(); + DCHECK(!result->empty()); + *result = result->Append("Internet Plug-Ins"); + return true; + } + // In tests, just look in the module directory (below). +#endif + + // The rest of the world expects plugins in the module directory. + return PathService::Get(base::DIR_MODULE, result); +} + +#if defined(OS_WIN) +// Gets the Flash path if installed on the system. |is_npapi| determines whether +// to return the NPAPI of the PPAPI version of the system plugin. +bool GetSystemFlashFilename(base::FilePath* out_path, bool is_npapi) { + const wchar_t kNpapiFlashRegistryRoot[] = + L"SOFTWARE\\Macromedia\\FlashPlayerPlugin"; + const wchar_t kPepperFlashRegistryRoot[] = + L"SOFTWARE\\Macromedia\\FlashPlayerPepper"; + const wchar_t kFlashPlayerPathValueName[] = L"PlayerPath"; + + base::win::RegKey path_key( + HKEY_LOCAL_MACHINE, + is_npapi ? kNpapiFlashRegistryRoot : kPepperFlashRegistryRoot, KEY_READ); + base::string16 path_str; + if (FAILED(path_key.ReadValue(kFlashPlayerPathValueName, &path_str))) + return false; + + *out_path = base::FilePath(path_str); + return true; +} +#endif + +} // namespace + +namespace chrome { + +bool PathProvider(int key, base::FilePath* result) { + // Some keys are just aliases... + switch (key) { + case chrome::DIR_APP: + return PathService::Get(base::DIR_MODULE, result); + case chrome::DIR_LOGS: +#ifdef NDEBUG + // Release builds write to the data dir + return PathService::Get(chrome::DIR_USER_DATA, result); +#else + // Debug builds write next to the binary (in the build tree) +#if defined(OS_MACOSX) + if (!PathService::Get(base::DIR_EXE, result)) + return false; + if (base::mac::AmIBundled()) { + // If we're called from chrome, dump it beside the app (outside the + // app bundle), if we're called from a unittest, we'll already + // outside the bundle so use the exe dir. + // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium. + *result = result->DirName(); + *result = result->DirName(); + *result = result->DirName(); + } + return true; +#else + return PathService::Get(base::DIR_EXE, result); +#endif // defined(OS_MACOSX) +#endif // NDEBUG + case chrome::FILE_RESOURCE_MODULE: + return PathService::Get(base::FILE_MODULE, result); + } + + // Assume that we will not need to create the directory if it does not exist. + // This flag can be set to true for the cases where we want to create it. + bool create_dir = false; + + base::FilePath cur; + switch (key) { + case chrome::DIR_USER_DATA: + if (!GetDefaultUserDataDirectory(&cur)) { + NOTREACHED(); + return false; + } + create_dir = true; + break; + case chrome::DIR_USER_DOCUMENTS: + if (!GetUserDocumentsDirectory(&cur)) + return false; + create_dir = true; + break; + case chrome::DIR_USER_MUSIC: + if (!GetUserMusicDirectory(&cur)) + return false; + break; + case chrome::DIR_USER_PICTURES: + if (!GetUserPicturesDirectory(&cur)) + return false; + break; + case chrome::DIR_USER_VIDEOS: + if (!GetUserVideosDirectory(&cur)) + return false; + break; + case chrome::DIR_DEFAULT_DOWNLOADS_SAFE: +#if defined(OS_WIN) || defined(OS_LINUX) + if (!GetUserDownloadsDirectorySafe(&cur)) + return false; + break; +#else + // Fall through for all other platforms. +#endif + case chrome::DIR_DEFAULT_DOWNLOADS: +#if defined(OS_ANDROID) + if (!base::android::GetDownloadsDirectory(&cur)) + return false; +#else + if (!GetUserDownloadsDirectory(&cur)) + return false; + // Do not create the download directory here, we have done it twice now + // and annoyed a lot of users. +#endif + break; + case chrome::DIR_CRASH_DUMPS: +#if defined(OS_CHROMEOS) + // ChromeOS uses a separate directory. See http://crosbug.com/25089 + cur = base::FilePath("/var/log/chrome"); +#elif defined(OS_ANDROID) + if (!base::android::GetCacheDirectory(&cur)) + return false; +#else + // The crash reports are always stored relative to the default user data + // directory. This avoids the problem of having to re-initialize the + // exception handler after parsing command line options, which may + // override the location of the app's profile directory. + if (!GetDefaultUserDataDirectory(&cur)) + return false; +#endif +#if defined(OS_MACOSX) + cur = cur.Append(FILE_PATH_LITERAL("Crashpad")); +#else + cur = cur.Append(FILE_PATH_LITERAL("Crash Reports")); +#endif + create_dir = true; + break; +#if defined(OS_WIN) + case chrome::DIR_WATCHER_DATA: + // The watcher data is always stored relative to the default user data + // directory. This allows the watcher to be initialized before + // command-line options have been parsed. + if (!GetDefaultUserDataDirectory(&cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("Diagnostics")); + break; +#endif + case chrome::DIR_RESOURCES: +#if defined(OS_MACOSX) + cur = base::mac::FrameworkBundlePath(); + cur = cur.Append(FILE_PATH_LITERAL("Resources")); +#else + if (!PathService::Get(chrome::DIR_APP, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("resources")); +#endif + break; + case chrome::DIR_INSPECTOR: + if (!PathService::Get(chrome::DIR_RESOURCES, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("inspector")); + break; + case chrome::DIR_APP_DICTIONARIES: +#if defined(OS_POSIX) + // We can't write into the EXE dir on Linux, so keep dictionaries + // alongside the safe browsing database in the user data dir. + // And we don't want to write into the bundle on the Mac, so push + // it to the user data dir there also. + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; +#else + if (!PathService::Get(base::DIR_EXE, &cur)) + return false; +#endif + cur = cur.Append(FILE_PATH_LITERAL("Dictionaries")); + create_dir = true; + break; + case chrome::DIR_INTERNAL_PLUGINS: + if (!GetInternalPluginsDirectory(&cur)) + return false; + break; + case chrome::DIR_PEPPER_FLASH_PLUGIN: + if (!GetInternalPluginsDirectory(&cur)) + return false; + cur = cur.Append(kPepperFlashBaseDirectory); + break; + case chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(kPepperFlashBaseDirectory); + break; + case chrome::FILE_PEPPER_FLASH_SYSTEM_PLUGIN: +#if defined(OS_WIN) + if (!GetSystemFlashFilename(&cur, false)) + return false; +#elif defined(OS_MACOSX) && !defined(OS_IOS) + if (!GetLocalLibraryDirectory(&cur)) + return false; + cur = cur.Append(kPepperFlashSystemBaseDirectory); + cur = cur.Append(chrome::kPepperFlashPluginFilename); +#else + // Chrome on iOS does not supports PPAPI binaries, return false. + // TODO(wfh): If Adobe release PPAPI binaries for Linux, add support here. + return false; +#endif + break; + case chrome::FILE_FLASH_SYSTEM_PLUGIN: +#if defined(OS_WIN) + if (!GetSystemFlashFilename(&cur, true)) + return false; +#elif defined(OS_MACOSX) && !defined(OS_IOS) + if (!GetLocalLibraryDirectory(&cur)) + return false; + cur = cur.Append(kFlashSystemBaseDirectory); + cur = cur.Append(kFlashSystemPluginName); +#else + // Chrome on other platforms does not supports system NPAPI binaries. + return false; +#endif + break; + case chrome::FILE_LOCAL_STATE: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(chrome::kLocalStateFilename); + break; + case chrome::FILE_RECORDED_SCRIPT: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("script.log")); + break; + case chrome::FILE_PEPPER_FLASH_PLUGIN: + if (!PathService::Get(chrome::DIR_PEPPER_FLASH_PLUGIN, &cur)) + return false; + cur = cur.Append(chrome::kPepperFlashPluginFilename); + break; + // TODO(teravest): Remove this case once the internal NaCl plugin is gone. + // We currently need a path here to look up whether the plugin is disabled + // and what its permissions are. + case chrome::FILE_NACL_PLUGIN: + if (!GetInternalPluginsDirectory(&cur)) + return false; + cur = cur.Append(kInternalNaClPluginFileName); + break; + // PNaCl is currenly installable via the component updater or by being + // simply built-in. DIR_PNACL_BASE is used as the base directory for + // installation via component updater. DIR_PNACL_COMPONENT will be + // the final location of pnacl, which is a subdir of DIR_PNACL_BASE. + case chrome::DIR_PNACL_BASE: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("pnacl")); + break; + // Where PNaCl files are ultimately located. The default finds the files + // inside the InternalPluginsDirectory / build directory, as if it + // was shipped along with chrome. The value can be overridden + // if it is installed via component updater. + case chrome::DIR_PNACL_COMPONENT: +#if defined(OS_MACOSX) + // PNaCl really belongs in the InternalPluginsDirectory but actually + // copying it there would result in the files also being shipped, which + // we don't want yet. So for now, just find them in the directory where + // they get built. + if (!PathService::Get(base::DIR_EXE, &cur)) + return false; + if (base::mac::AmIBundled()) { + // If we're called from chrome, it's beside the app (outside the + // app bundle), if we're called from a unittest, we'll already be + // outside the bundle so use the exe dir. + // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium. + cur = cur.DirName(); + cur = cur.DirName(); + cur = cur.DirName(); + } +#else + if (!GetInternalPluginsDirectory(&cur)) + return false; +#endif + cur = cur.Append(FILE_PATH_LITERAL("pnacl")); + break; +#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) +#if defined(WIDEVINE_CDM_IS_COMPONENT) + case chrome::DIR_COMPONENT_WIDEVINE_CDM: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("WidevineCDM")); + break; +#endif // defined(WIDEVINE_CDM_IS_COMPONENT) + // TODO(xhwang): FILE_WIDEVINE_CDM_ADAPTER has different meanings. + // In the component case, this is the source adapter. Otherwise, it is the + // actual Pepper module that gets loaded. + case chrome::FILE_WIDEVINE_CDM_ADAPTER: + if (!GetInternalPluginsDirectory(&cur)) + return false; + cur = cur.AppendASCII(kWidevineCdmAdapterFileName); + break; +#endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) + case chrome::FILE_RESOURCES_PACK: +#if defined(OS_MACOSX) && !defined(OS_IOS) + if (base::mac::AmIBundled()) { + cur = base::mac::FrameworkBundlePath(); + cur = cur.Append(FILE_PATH_LITERAL("Resources")) + .Append(FILE_PATH_LITERAL("resources.pak")); + break; + } +#elif defined(OS_ANDROID) + if (!PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &cur)) + return false; +#else + // If we're not bundled on mac or Android, resources.pak should be next + // to the binary (e.g., for unit tests). + if (!PathService::Get(base::DIR_MODULE, &cur)) + return false; +#endif + cur = cur.Append(FILE_PATH_LITERAL("resources.pak")); + break; + case chrome::DIR_RESOURCES_EXTENSION: + if (!PathService::Get(base::DIR_MODULE, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("resources")) + .Append(FILE_PATH_LITERAL("extension")); + break; +#if defined(OS_CHROMEOS) + case chrome::DIR_CHROMEOS_WALLPAPERS: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("wallpapers")); + break; + case chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("wallpaper_thumbnails")); + break; + case chrome::DIR_CHROMEOS_CUSTOM_WALLPAPERS: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("custom_wallpapers")); + break; +#endif +#if defined(ENABLE_SUPERVISED_USERS) +#if defined(OS_LINUX) + case chrome::DIR_SUPERVISED_USERS_DEFAULT_APPS: + if (!PathService::Get(chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("managed_users")); + break; +#endif + case chrome::DIR_SUPERVISED_USER_INSTALLED_WHITELISTS: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("SupervisedUserInstalledWhitelists")); + break; +#endif + // The following are only valid in the development environment, and + // will fail if executed from an installed executable (because the + // generated path won't exist). + case chrome::DIR_GEN_TEST_DATA: +#if defined(OS_ANDROID) + // On Android, our tests don't have permission to write to DIR_MODULE. + // gtest/test_runner.py pushes data to external storage. + if (!PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE, &cur)) + return false; +#else + if (!PathService::Get(base::DIR_MODULE, &cur)) + return false; +#endif + cur = cur.Append(FILE_PATH_LITERAL("test_data")); + if (!base::PathExists(cur)) // We don't want to create this. + return false; + break; + case chrome::DIR_TEST_DATA: + if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("chrome")); + cur = cur.Append(FILE_PATH_LITERAL("test")); + cur = cur.Append(FILE_PATH_LITERAL("data")); + if (!base::PathExists(cur)) // We don't want to create this. + return false; + break; + case chrome::DIR_TEST_TOOLS: + if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("chrome")); + cur = cur.Append(FILE_PATH_LITERAL("tools")); + cur = cur.Append(FILE_PATH_LITERAL("test")); + if (!base::PathExists(cur)) // We don't want to create this + return false; + break; +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) + case chrome::DIR_POLICY_FILES: { +#if defined(GOOGLE_CHROME_BUILD) + cur = base::FilePath(FILE_PATH_LITERAL("/etc/opt/chrome/policies")); +#else + cur = base::FilePath(FILE_PATH_LITERAL("/etc/chromium/policies")); +#endif + break; + } +#endif +#if defined(OS_MACOSX) && !defined(OS_IOS) + case chrome::DIR_USER_LIBRARY: { + if (!GetUserLibraryDirectory(&cur)) + return false; + if (!base::PathExists(cur)) // We don't want to create this. + return false; + break; + } + case chrome::DIR_USER_APPLICATIONS: { + if (!GetUserApplicationsDirectory(&cur)) + return false; + if (!base::PathExists(cur)) // We don't want to create this. + return false; + break; + } +#endif +#if defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(CHROMIUM_BUILD)) || \ + (defined(OS_MACOSX) && !defined(OS_IOS)) + case chrome::DIR_USER_EXTERNAL_EXTENSIONS: { + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("External Extensions")); + break; + } +#endif +#if defined(OS_LINUX) + case chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS: { + cur = base::FilePath(kFilepathSinglePrefExtensions); + break; + } +#endif + case chrome::DIR_EXTERNAL_EXTENSIONS: +#if defined(OS_MACOSX) && !defined(OS_IOS) + if (!chrome::GetGlobalApplicationSupportDirectory(&cur)) + return false; + + cur = cur.Append(FILE_PATH_LITERAL("Google")) + .Append(FILE_PATH_LITERAL("Chrome")) + .Append(FILE_PATH_LITERAL("External Extensions")); + create_dir = false; +#else + if (!PathService::Get(base::DIR_MODULE, &cur)) + return false; + + cur = cur.Append(FILE_PATH_LITERAL("extensions")); + create_dir = true; +#endif + break; + + case chrome::DIR_DEFAULT_APPS: +#if defined(OS_MACOSX) + cur = base::mac::FrameworkBundlePath(); + cur = cur.Append(FILE_PATH_LITERAL("Default Apps")); +#else + if (!PathService::Get(chrome::DIR_APP, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("default_apps")); +#endif + break; + +#if defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS)) + case chrome::DIR_NATIVE_MESSAGING: +#if defined(OS_MACOSX) +#if defined(GOOGLE_CHROME_BUILD) + cur = base::FilePath(FILE_PATH_LITERAL( + "/Library/Google/Chrome/NativeMessagingHosts")); +#else + cur = base::FilePath(FILE_PATH_LITERAL( + "/Library/Application Support/Chromium/NativeMessagingHosts")); +#endif +#else // defined(OS_MACOSX) +#if defined(GOOGLE_CHROME_BUILD) + cur = base::FilePath(FILE_PATH_LITERAL( + "/etc/opt/chrome/native-messaging-hosts")); +#else + cur = base::FilePath(FILE_PATH_LITERAL( + "/etc/chromium/native-messaging-hosts")); +#endif +#endif // !defined(OS_MACOSX) + break; + + case chrome::DIR_USER_NATIVE_MESSAGING: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("NativeMessagingHosts")); + break; +#endif // defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS)) +#if !defined(OS_ANDROID) + case chrome::DIR_GLOBAL_GCM_STORE: + if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) + return false; + cur = cur.Append(kGCMStoreDirname); + break; +#endif // !defined(OS_ANDROID) +#if defined(OS_LINUX) + case chrome::FILE_COMPONENT_FLASH_HINT: + if (!PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, + &cur)) { + return false; + } + cur = cur.Append(kComponentUpdatedFlashHint); + break; +#endif // defined(OS_LINUX) + + default: + return false; + } + + // TODO(bauerb): http://crbug.com/259796 + base::ThreadRestrictions::ScopedAllowIO allow_io; + if (create_dir && !base::PathExists(cur) && + !base::CreateDirectory(cur)) + return false; + + *result = cur; + return true; +} + +// This cannot be done as a static initializer sadly since Visual Studio will +// eliminate this object file if there is no direct entry point into it. +void RegisterPathProvider() { + PathService::RegisterProvider(PathProvider, PATH_START, PATH_END); +} + +void SetInvalidSpecifiedUserDataDir(const base::FilePath& user_data_dir) { + g_invalid_specified_user_data_dir.Get() = user_data_dir; +} + +const base::FilePath& GetInvalidSpecifiedUserDataDir() { + return g_invalid_specified_user_data_dir.Get(); +} + +} // namespace chrome diff --git a/chromium_src/chrome/common/chrome_paths.h b/chromium_src/chrome/common/chrome_paths.h new file mode 100644 index 000000000000..581fdc06f7c1 --- /dev/null +++ b/chromium_src/chrome/common/chrome_paths.h @@ -0,0 +1,152 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_COMMON_CHROME_PATHS_H__ +#define CHROME_COMMON_CHROME_PATHS_H__ + +#include "build/build_config.h" + +namespace base { +class FilePath; +} + +// This file declares path keys for the chrome module. These can be used with +// the PathService to access various special directories and files. + +namespace chrome { + +enum { + PATH_START = 1000, + + DIR_APP = PATH_START, // Directory where dlls and data reside. + DIR_LOGS, // Directory where logs should be written. + DIR_USER_DATA, // Directory where user data can be written. + DIR_CRASH_DUMPS, // Directory where crash dumps are written. +#if defined(OS_WIN) + DIR_WATCHER_DATA, // Directory where the Chrome watcher stores + // data. +#endif + DIR_RESOURCES, // Directory containing separate file resources + // used by Chrome at runtime. + DIR_INSPECTOR, // Directory where web inspector is located. + DIR_APP_DICTIONARIES, // Directory where the global dictionaries are. + DIR_USER_DOCUMENTS, // Directory for a user's "My Documents". + DIR_USER_MUSIC, // Directory for a user's music. + DIR_USER_PICTURES, // Directory for a user's pictures. + DIR_USER_VIDEOS, // Directory for a user's videos. + DIR_DEFAULT_DOWNLOADS_SAFE, // Directory for a user's + // "My Documents/Downloads", (Windows) or + // "Downloads". (Linux) + DIR_DEFAULT_DOWNLOADS, // Directory for a user's downloads. + DIR_INTERNAL_PLUGINS, // Directory where internal plugins reside. +#if defined(OS_POSIX) && !defined(OS_MACOSX) + DIR_POLICY_FILES, // Directory for system-wide read-only + // policy files that allow sys-admins + // to set policies for chrome. This directory + // contains subdirectories. +#endif +#if defined(OS_MACOSX) && !defined(OS_IOS) + DIR_USER_APPLICATIONS, // ~/Applications + DIR_USER_LIBRARY, // ~/Library +#endif +#if defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(CHROMIUM_BUILD)) || \ + (defined(OS_MACOSX) && !defined(OS_IOS)) + DIR_USER_EXTERNAL_EXTENSIONS, // Directory for per-user external extensions + // on Chrome Mac and Chromium Linux. + // On Chrome OS, this path is used for OEM + // customization. Getting this path does not + // create it. +#endif + +#if defined(OS_LINUX) + DIR_STANDALONE_EXTERNAL_EXTENSIONS, // Directory for 'per-extension' + // definition manifest files that + // describe extensions which are to be + // installed when chrome is run. +#endif + DIR_EXTERNAL_EXTENSIONS, // Directory where installer places .crx files. + + DIR_DEFAULT_APPS, // Directory where installer places .crx files + // to be installed when chrome is first run. + DIR_PEPPER_FLASH_PLUGIN, // Directory to the bundled Pepper Flash plugin, + // containing the plugin and the manifest. + DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, // Base directory of the Pepper + // Flash plugins downloaded by the + // component updater. + FILE_RESOURCE_MODULE, // Full path and filename of the module that + // contains embedded resources (version, + // strings, images, etc.). + FILE_LOCAL_STATE, // Path and filename to the file in which + // machine/installation-specific state is saved. + FILE_RECORDED_SCRIPT, // Full path to the script.log file that + // contains recorded browser events for + // playback. + FILE_PEPPER_FLASH_PLUGIN, // Full path to the bundled Pepper Flash plugin + // file. + FILE_PEPPER_FLASH_SYSTEM_PLUGIN, // Full path to the system version of the + // Pepper Flash plugin, downloadable from + // Adobe website. Querying this path might + // succeed no matter the file exists or not. + FILE_FLASH_SYSTEM_PLUGIN, // Full path to the system version of NPAPI + // Flash plugin, downloadable from Adobe + // website. Querying this path might succeed no + // matter the file exists or not. + FILE_NACL_PLUGIN, // Full path to the internal NaCl plugin file. + DIR_PNACL_BASE, // Full path to the base dir for PNaCl. + DIR_PNACL_COMPONENT, // Full path to the latest PNaCl version + // (subdir of DIR_PNACL_BASE). + DIR_COMPONENT_WIDEVINE_CDM, // Directory that contains component-updated + // Widevine CDM files. + FILE_WIDEVINE_CDM_ADAPTER, // Full path to the Widevine CDM adapter file. + FILE_RESOURCES_PACK, // Full path to the .pak file containing + // binary data (e.g., html files and images + // used by internal pages). + DIR_RESOURCES_EXTENSION, // Full path to extension resources. +#if defined(OS_CHROMEOS) + DIR_CHROMEOS_WALLPAPERS, // Directory where downloaded chromeos + // wallpapers reside. + DIR_CHROMEOS_WALLPAPER_THUMBNAILS, // Directory where downloaded chromeos + // wallpaper thumbnails reside. + DIR_CHROMEOS_CUSTOM_WALLPAPERS, // Directory where custom wallpapers + // reside. +#endif + DIR_SUPERVISED_USERS_DEFAULT_APPS, // Directory where installer places .crx + // files to be installed when managed user + // session starts. + DIR_SUPERVISED_USER_INSTALLED_WHITELISTS, // Directory where sanitized + // supervised user whitelists are + // installed. +#if defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS)) + DIR_NATIVE_MESSAGING, // System directory where native messaging host + // manifest files are stored. + DIR_USER_NATIVE_MESSAGING, // Directory with Native Messaging Hosts + // installed per-user. +#endif +#if !defined(OS_ANDROID) + DIR_GLOBAL_GCM_STORE, // Directory where the global GCM instance + // stores its data. +#endif + + // Valid only in development environment; TODO(darin): move these + DIR_GEN_TEST_DATA, // Directory where generated test data resides. + DIR_TEST_DATA, // Directory where unit test data resides. + DIR_TEST_TOOLS, // Directory where unit test tools reside. +#if defined(OS_LINUX) + FILE_COMPONENT_FLASH_HINT, // A file in a known location that points to + // the component updated flash plugin. +#endif // defined(OS_LINUX) + + PATH_END +}; + +// Call once to register the provider for the path keys defined above. +void RegisterPathProvider(); + +// Get or set the invalid user data dir that was originally specified. +void SetInvalidSpecifiedUserDataDir(const base::FilePath& user_data_dir); +const base::FilePath& GetInvalidSpecifiedUserDataDir(); + +} // namespace chrome + +#endif // CHROME_COMMON_CHROME_PATHS_H__ diff --git a/chromium_src/chrome/common/chrome_paths_internal.h b/chromium_src/chrome/common/chrome_paths_internal.h new file mode 100644 index 000000000000..ae1cd623d773 --- /dev/null +++ b/chromium_src/chrome/common/chrome_paths_internal.h @@ -0,0 +1,112 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_COMMON_CHROME_PATHS_INTERNAL_H_ +#define CHROME_COMMON_CHROME_PATHS_INTERNAL_H_ + +#include + +#include "build/build_config.h" + +#if defined(OS_MACOSX) +#if defined(__OBJC__) +@class NSBundle; +#else +class NSBundle; +#endif +#endif + +namespace base { +class FilePath; +} + +namespace chrome { + +// Get the path to the user's data directory, regardless of whether +// DIR_USER_DATA has been overridden by a command-line option. +bool GetDefaultUserDataDirectory(base::FilePath* result); + +// Get the path to the user's cache directory. This is normally the +// same as the profile directory, but on Linux it can also be +// $XDG_CACHE_HOME and on Mac it can be under ~/Library/Caches. +// Note that the Chrome cache directories are actually subdirectories +// of this directory, with names like "Cache" and "Media Cache". +// This will always fill in |result| with a directory, sometimes +// just |profile_dir|. +void GetUserCacheDirectory(const base::FilePath& profile_dir, base::FilePath* result); + +// Get the path to the user's documents directory. +bool GetUserDocumentsDirectory(base::FilePath* result); + +#if defined(OS_WIN) || defined(OS_LINUX) +// Gets the path to a safe default download directory for a user. +bool GetUserDownloadsDirectorySafe(base::FilePath* result); +#endif + +// Get the path to the user's downloads directory. +bool GetUserDownloadsDirectory(base::FilePath* result); + +// Gets the path to the user's music directory. +bool GetUserMusicDirectory(base::FilePath* result); + +// Gets the path to the user's pictures directory. +bool GetUserPicturesDirectory(base::FilePath* result); + +// Gets the path to the user's videos directory. +bool GetUserVideosDirectory(base::FilePath* result); + +#if defined(OS_MACOSX) && !defined(OS_IOS) +// The "versioned directory" is a directory in the browser .app bundle. It +// contains the bulk of the application, except for the things that the system +// requires be located at spepcific locations. The versioned directory is +// in the .app at Contents/Versions/w.x.y.z. +base::FilePath GetVersionedDirectory(); + +// This overrides the directory returned by |GetVersionedDirectory()|, to be +// used when |GetVersionedDirectory()| can't automatically determine the proper +// location. This is the case when the browser didn't load itself but by, e.g., +// the app mode loader. This should be called before |ChromeMain()|. This takes +// ownership of the object |path| and the caller must not delete it. +void SetOverrideVersionedDirectory(const base::FilePath* path); + +// Most of the application is further contained within the framework. The +// framework bundle is located within the versioned directory at a specific +// path. The only components in the versioned directory not included in the +// framework are things that also depend on the framework, such as the helper +// app bundle. +base::FilePath GetFrameworkBundlePath(); + +// Get the local library directory. +bool GetLocalLibraryDirectory(base::FilePath* result); + +// Get the user library directory. +bool GetUserLibraryDirectory(base::FilePath* result); + +// Get the user applications directory. +bool GetUserApplicationsDirectory(base::FilePath* result); + +// Get the global Application Support directory (under /Library/). +bool GetGlobalApplicationSupportDirectory(base::FilePath* result); + +// Returns the NSBundle for the outer browser application, even when running +// inside the helper. In unbundled applications, such as tests, returns nil. +NSBundle* OuterAppBundle(); + +// Get the user data directory for the Chrome browser bundle at |bundle|. +// |bundle| should be the same value that would be returned from +[NSBundle +// mainBundle] if Chrome were launched normaly. This is used by app shims, +// which run from a bundle which isn't Chrome itself, but which need access to +// the user data directory to connect to a UNIX-domain socket therein. +// Returns false if there was a problem fetching the app data directory. +bool GetUserDataDirectoryForBrowserBundle(NSBundle* bundle, + base::FilePath* result); + +#endif // OS_MACOSX && !OS_IOS + +// Checks if the |process_type| has the rights to access the profile. +bool ProcessNeedsProfileDir(const std::string& process_type); + +} // namespace chrome + +#endif // CHROME_COMMON_CHROME_PATHS_INTERNAL_H_ diff --git a/chromium_src/chrome/common/chrome_paths_linux.cc b/chromium_src/chrome/common/chrome_paths_linux.cc new file mode 100644 index 000000000000..91348fec4808 --- /dev/null +++ b/chromium_src/chrome/common/chrome_paths_linux.cc @@ -0,0 +1,145 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/chrome_paths_internal.h" + +#include "base/base_paths.h" +#include "base/environment.h" +#include "base/files/file_util.h" +#include "base/memory/scoped_ptr.h" +#include "base/nix/xdg_util.h" +#include "base/path_service.h" +#include "chrome/common/chrome_paths.h" + +namespace chrome { + +using base::nix::GetXDGDirectory; +using base::nix::GetXDGUserDirectory; +using base::nix::kDotConfigDir; +using base::nix::kXdgConfigHomeEnvVar; + +namespace { + +const char kDownloadsDir[] = "Downloads"; +const char kMusicDir[] = "Music"; +const char kPicturesDir[] = "Pictures"; +const char kVideosDir[] = "Videos"; + +// Generic function for GetUser{Music,Pictures,Video}Directory. +bool GetUserMediaDirectory(const std::string& xdg_name, + const std::string& fallback_name, + base::FilePath* result) { +#if defined(OS_CHROMEOS) + // No local media directories on CrOS. + return false; +#else + *result = GetXDGUserDirectory(xdg_name.c_str(), fallback_name.c_str()); + + base::FilePath home; + PathService::Get(base::DIR_HOME, &home); + if (*result != home) { + base::FilePath desktop; + if (!PathService::Get(base::DIR_USER_DESKTOP, &desktop)) + return false; + if (*result != desktop) { + return true; + } + } + + *result = home.Append(fallback_name); + return true; +#endif +} + +} // namespace + +// See http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html +// for a spec on where config files go. The net effect for most +// systems is we use ~/.config/chromium/ for Chromium and +// ~/.config/google-chrome/ for official builds. +// (This also helps us sidestep issues with other apps grabbing ~/.chromium .) +bool GetDefaultUserDataDirectory(base::FilePath* result) { + scoped_ptr env(base::Environment::Create()); + base::FilePath config_dir(GetXDGDirectory(env.get(), + kXdgConfigHomeEnvVar, + kDotConfigDir)); +#if defined(GOOGLE_CHROME_BUILD) + *result = config_dir.Append("google-chrome"); +#else + *result = config_dir.Append("chromium"); +#endif + return true; +} + +void GetUserCacheDirectory(const base::FilePath& profile_dir, + base::FilePath* result) { + // See http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + // for a spec on where cache files go. Our rule is: + // - if the user-data-dir in the standard place, + // use same subdirectory of the cache directory. + // (this maps ~/.config/google-chrome to ~/.cache/google-chrome as well + // as the same thing for ~/.config/chromium) + // - otherwise, use the profile dir directly. + + // Default value in cases where any of the following fails. + *result = profile_dir; + + scoped_ptr env(base::Environment::Create()); + + base::FilePath cache_dir; + if (!PathService::Get(base::DIR_CACHE, &cache_dir)) + return; + base::FilePath config_dir(GetXDGDirectory(env.get(), + kXdgConfigHomeEnvVar, + kDotConfigDir)); + + if (!config_dir.AppendRelativePath(profile_dir, &cache_dir)) + return; + + *result = cache_dir; +} + +bool GetUserDocumentsDirectory(base::FilePath* result) { + *result = GetXDGUserDirectory("DOCUMENTS", "Documents"); + return true; +} + +bool GetUserDownloadsDirectorySafe(base::FilePath* result) { + base::FilePath home; + PathService::Get(base::DIR_HOME, &home); + *result = home.Append(kDownloadsDir); + return true; +} + +bool GetUserDownloadsDirectory(base::FilePath* result) { + *result = GetXDGUserDirectory("DOWNLOAD", kDownloadsDir); + return true; +} + +// We respect the user's preferred pictures location, unless it is +// ~ or their desktop directory, in which case we default to ~/Music. +bool GetUserMusicDirectory(base::FilePath* result) { + return GetUserMediaDirectory("MUSIC", kMusicDir, result); +} + +// We respect the user's preferred pictures location, unless it is +// ~ or their desktop directory, in which case we default to ~/Pictures. +bool GetUserPicturesDirectory(base::FilePath* result) { + return GetUserMediaDirectory("PICTURES", kPicturesDir, result); +} + +// We respect the user's preferred pictures location, unless it is +// ~ or their desktop directory, in which case we default to ~/Videos. +bool GetUserVideosDirectory(base::FilePath* result) { + return GetUserMediaDirectory("VIDEOS", kVideosDir, result); +} + +bool ProcessNeedsProfileDir(const std::string& process_type) { + // For now we have no reason to forbid this on Linux as we don't + // have the roaming profile troubles there. Moreover the Linux breakpad needs + // profile dir access in all process if enabled on Linux. + return true; +} + +} // namespace chrome diff --git a/chromium_src/chrome/common/chrome_paths_mac.mm b/chromium_src/chrome/common/chrome_paths_mac.mm new file mode 100644 index 000000000000..09cf13bfe122 --- /dev/null +++ b/chromium_src/chrome/common/chrome_paths_mac.mm @@ -0,0 +1,252 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/chrome_paths_internal.h" + +#import +#include + +#include + +#include "base/base_paths.h" +#include "base/logging.h" +#import "base/mac/foundation_util.h" +#import "base/mac/scoped_nsautorelease_pool.h" +#include "base/memory/scoped_ptr.h" +#include "base/path_service.h" +#include "chrome/common/chrome_constants.h" + +namespace { + +#if !defined(OS_IOS) +const base::FilePath* g_override_versioned_directory = NULL; + +// Return a retained (NOT autoreleased) NSBundle* as the internal +// implementation of chrome::OuterAppBundle(), which should be the only +// caller. +NSBundle* OuterAppBundleInternal() { + base::mac::ScopedNSAutoreleasePool pool; + + if (!base::mac::AmIBundled()) { + // If unbundled (as in a test), there's no app bundle. + return nil; + } + + if (!base::mac::IsBackgroundOnlyProcess()) { + // Shortcut: in the browser process, just return the main app bundle. + return [[NSBundle mainBundle] retain]; + } + + // From C.app/Contents/Versions/1.2.3.4, go up three steps to get to C.app. + base::FilePath versioned_dir = chrome::GetVersionedDirectory(); + base::FilePath outer_app_dir = versioned_dir.DirName().DirName().DirName(); + const char* outer_app_dir_c = outer_app_dir.value().c_str(); + NSString* outer_app_dir_ns = [NSString stringWithUTF8String:outer_app_dir_c]; + + return [[NSBundle bundleWithPath:outer_app_dir_ns] retain]; +} +#endif // !defined(OS_IOS) + +char* ProductDirNameForBundle(NSBundle* chrome_bundle) { + const char* product_dir_name = NULL; +#if !defined(OS_IOS) + base::mac::ScopedNSAutoreleasePool pool; + + NSString* product_dir_name_ns = + [chrome_bundle objectForInfoDictionaryKey:@"CrProductDirName"]; + product_dir_name = [product_dir_name_ns fileSystemRepresentation]; +#else + DCHECK(!chrome_bundle); +#endif + + if (!product_dir_name) { +#if defined(GOOGLE_CHROME_BUILD) + product_dir_name = "Google/Chrome"; +#else + product_dir_name = "Chromium"; +#endif + } + + // Leaked, but the only caller initializes a static with this result, so it + // only happens once, and that's OK. + return strdup(product_dir_name); +} + +// ProductDirName returns the name of the directory inside +// ~/Library/Application Support that should hold the product application +// data. This can be overridden by setting the CrProductDirName key in the +// outer browser .app's Info.plist. The default is "Google/Chrome" for +// officially-branded builds, and "Chromium" for unbranded builds. For the +// official canary channel, the Info.plist will have CrProductDirName set +// to "Google/Chrome Canary". +std::string ProductDirName() { +#if defined(OS_IOS) + static const char* product_dir_name = ProductDirNameForBundle(nil); +#else + // Use OuterAppBundle() to get the main app's bundle. This key needs to live + // in the main app's bundle because it will be set differently on the canary + // channel, and the autoupdate system dictates that there can be no + // differences between channels within the versioned directory. This would + // normally use base::mac::FrameworkBundle(), but that references the + // framework bundle within the versioned directory. Ordinarily, the profile + // should not be accessed from non-browser processes, but those processes do + // attempt to get the profile directory, so direct them to look in the outer + // browser .app's Info.plist for the CrProductDirName key. + static const char* product_dir_name = + ProductDirNameForBundle(chrome::OuterAppBundle()); +#endif + return std::string(product_dir_name); +} + +bool GetDefaultUserDataDirectoryForProduct(const std::string& product_dir, + base::FilePath* result) { + bool success = false; + if (result && PathService::Get(base::DIR_APP_DATA, result)) { + *result = result->Append(product_dir); + success = true; + } + return success; +} + +} // namespace + +namespace chrome { + +bool GetDefaultUserDataDirectory(base::FilePath* result) { + return GetDefaultUserDataDirectoryForProduct(ProductDirName(), result); +} + +bool GetUserDocumentsDirectory(base::FilePath* result) { + return base::mac::GetUserDirectory(NSDocumentDirectory, result); +} + +void GetUserCacheDirectory(const base::FilePath& profile_dir, + base::FilePath* result) { + // If the profile directory is under ~/Library/Application Support, + // use a suitable cache directory under ~/Library/Caches. For + // example, a profile directory of ~/Library/Application + // Support/Google/Chrome/MyProfileName would use the cache directory + // ~/Library/Caches/Google/Chrome/MyProfileName. + + // Default value in cases where any of the following fails. + *result = profile_dir; + + base::FilePath app_data_dir; + if (!PathService::Get(base::DIR_APP_DATA, &app_data_dir)) + return; + base::FilePath cache_dir; + if (!PathService::Get(base::DIR_CACHE, &cache_dir)) + return; + if (!app_data_dir.AppendRelativePath(profile_dir, &cache_dir)) + return; + + *result = cache_dir; +} + +bool GetUserDownloadsDirectory(base::FilePath* result) { + return base::mac::GetUserDirectory(NSDownloadsDirectory, result); +} + +bool GetUserMusicDirectory(base::FilePath* result) { + return base::mac::GetUserDirectory(NSMusicDirectory, result); +} + +bool GetUserPicturesDirectory(base::FilePath* result) { + return base::mac::GetUserDirectory(NSPicturesDirectory, result); +} + +bool GetUserVideosDirectory(base::FilePath* result) { + return base::mac::GetUserDirectory(NSMoviesDirectory, result); +} + +#if !defined(OS_IOS) + +base::FilePath GetVersionedDirectory() { + if (g_override_versioned_directory) + return *g_override_versioned_directory; + + // Start out with the path to the running executable. + base::FilePath path; + PathService::Get(base::FILE_EXE, &path); + + // One step up to MacOS, another to Contents. + path = path.DirName().DirName(); + DCHECK_EQ(path.BaseName().value(), "Contents"); + + if (base::mac::IsBackgroundOnlyProcess()) { + // path identifies the helper .app's Contents directory in the browser + // .app's versioned directory. Go up two steps to get to the browser + // .app's versioned directory. + path = path.DirName().DirName(); + DCHECK_EQ(path.BaseName().value(), kChromeVersion); + } else { + // Go into the versioned directory. + path = path.Append("Versions").Append(kChromeVersion); + } + + return path; +} + +void SetOverrideVersionedDirectory(const base::FilePath* path) { + if (path != g_override_versioned_directory) { + delete g_override_versioned_directory; + g_override_versioned_directory = path; + } +} + +base::FilePath GetFrameworkBundlePath() { + // It's tempting to use +[NSBundle bundleWithIdentifier:], but it's really + // slow (about 30ms on 10.5 and 10.6), despite Apple's documentation stating + // that it may be more efficient than +bundleForClass:. +bundleForClass: + // itself takes 1-2ms. Getting an NSBundle from a path, on the other hand, + // essentially takes no time at all, at least when the bundle has already + // been loaded as it will have been in this case. The FilePath operations + // needed to compute the framework's path are also effectively free, so that + // is the approach that is used here. NSBundle is also documented as being + // not thread-safe, and thread safety may be a concern here. + + // The framework bundle is at a known path and name from the browser .app's + // versioned directory. + return GetVersionedDirectory().Append(kFrameworkName); +} + +bool GetLocalLibraryDirectory(base::FilePath* result) { + return base::mac::GetLocalDirectory(NSLibraryDirectory, result); +} + +bool GetUserLibraryDirectory(base::FilePath* result) { + return base::mac::GetUserDirectory(NSLibraryDirectory, result); +} + +bool GetUserApplicationsDirectory(base::FilePath* result) { + return base::mac::GetUserDirectory(NSApplicationDirectory, result); +} + +bool GetGlobalApplicationSupportDirectory(base::FilePath* result) { + return base::mac::GetLocalDirectory(NSApplicationSupportDirectory, result); +} + +NSBundle* OuterAppBundle() { + // Cache this. Foundation leaks it anyway, and this should be the only call + // to OuterAppBundleInternal(). + static NSBundle* bundle = OuterAppBundleInternal(); + return bundle; +} + +bool GetUserDataDirectoryForBrowserBundle(NSBundle* bundle, + base::FilePath* result) { + scoped_ptr + product_dir_name(ProductDirNameForBundle(bundle)); + return GetDefaultUserDataDirectoryForProduct(product_dir_name.get(), result); +} + +#endif // !defined(OS_IOS) + +bool ProcessNeedsProfileDir(const std::string& process_type) { + // For now we have no reason to forbid this on other MacOS as we don't + // have the roaming profile troubles there. + return true; +} + +} // namespace chrome diff --git a/chromium_src/chrome/common/chrome_paths_win.cc b/chromium_src/chrome/common/chrome_paths_win.cc new file mode 100644 index 000000000000..18073ca04759 --- /dev/null +++ b/chromium_src/chrome/common/chrome_paths_win.cc @@ -0,0 +1,122 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/chrome_paths_internal.h" + +#include +#include +#include +#include +#include + +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/win/metro.h" +#include "base/win/scoped_co_mem.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/installer/util/browser_distribution.h" +#include "components/nacl/common/nacl_switches.h" + +namespace chrome { + +namespace { + +// Generic function to call SHGetFolderPath(). +bool GetUserDirectory(int csidl_folder, base::FilePath* result) { + // We need to go compute the value. It would be nice to support paths + // with names longer than MAX_PATH, but the system functions don't seem + // to be designed for it either, with the exception of GetTempPath + // (but other things will surely break if the temp path is too long, + // so we don't bother handling it. + wchar_t path_buf[MAX_PATH]; + path_buf[0] = 0; + if (FAILED(SHGetFolderPath(NULL, csidl_folder, NULL, + SHGFP_TYPE_CURRENT, path_buf))) { + return false; + } + *result = base::FilePath(path_buf); + return true; +} + +} // namespace + +bool GetDefaultUserDataDirectory(base::FilePath* result) { + if (!PathService::Get(base::DIR_LOCAL_APP_DATA, result)) + return false; + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + *result = result->Append(dist->GetInstallSubDir()); + *result = result->Append(chrome::kUserDataDirname); + return true; +} + +void GetUserCacheDirectory(const base::FilePath& profile_dir, + base::FilePath* result) { + // This function does more complicated things on Mac/Linux. + *result = profile_dir; +} + +bool GetUserDocumentsDirectory(base::FilePath* result) { + return GetUserDirectory(CSIDL_MYDOCUMENTS, result); +} + +// Return a default path for downloads that is safe. +// We just use 'Downloads' under DIR_USER_DOCUMENTS. Localizing +// 'downloads' is not a good idea because Chrome's UI language +// can be changed. +bool GetUserDownloadsDirectorySafe(base::FilePath* result) { + if (!GetUserDocumentsDirectory(result)) + return false; + + *result = result->Append(L"Downloads"); + return true; +} + +// On Vista and higher, use the downloads known folder. Since it can be +// relocated to point to a "dangerous" folder, callers should validate that the +// returned path is not dangerous before using it. +bool GetUserDownloadsDirectory(base::FilePath* result) { + typedef HRESULT (WINAPI *GetKnownFolderPath)( + REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR*); + GetKnownFolderPath f = reinterpret_cast( + GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHGetKnownFolderPath")); + base::win::ScopedCoMem path_buf; + if (f && SUCCEEDED(f(FOLDERID_Downloads, 0, NULL, &path_buf))) { + *result = base::FilePath(std::wstring(path_buf)); + return true; + } + return GetUserDownloadsDirectorySafe(result); +} + +bool GetUserMusicDirectory(base::FilePath* result) { + return GetUserDirectory(CSIDL_MYMUSIC, result); +} + +bool GetUserPicturesDirectory(base::FilePath* result) { + return GetUserDirectory(CSIDL_MYPICTURES, result); +} + +bool GetUserVideosDirectory(base::FilePath* result) { + return GetUserDirectory(CSIDL_MYVIDEO, result); +} + +bool ProcessNeedsProfileDir(const std::string& process_type) { + // On windows we don't want subprocesses other than the browser process and + // service processes to be able to use the profile directory because if it + // lies on a network share the sandbox will prevent us from accessing it. + + if (process_type.empty() || process_type == switches::kServiceProcess) + return true; + +#if !defined(DISABLE_NACL) + if (process_type == switches::kNaClBrokerProcess || + process_type == switches::kNaClLoaderProcess) { + return true; + } +#endif + + return false; +} + +} // namespace chrome diff --git a/filenames.gypi b/filenames.gypi index 658c8e76b6b0..0e91dd21e16d 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -419,6 +419,14 @@ 'chromium_src/chrome/browser/ui/views/color_chooser_aura.h', 'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc', 'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h', + 'chromium_src/chrome/common/chrome_constants.cc', + 'chromium_src/chrome/common/chrome_constants.h', + 'chromium_src/chrome/common/chrome_paths.cc', + 'chromium_src/chrome/common/chrome_paths.h', + 'chromium_src/chrome/common/chrome_paths_internal.h', + 'chromium_src/chrome/common/chrome_paths_linux.cc', + 'chromium_src/chrome/common/chrome_paths_mac.mm', + 'chromium_src/chrome/common/chrome_paths_win.cc', 'chromium_src/chrome/common/chrome_utility_messages.h', 'chromium_src/chrome/common/pref_names.cc', 'chromium_src/chrome/common/pref_names.h', From 05d2e431debde75edd84d83b357fb7b3a6eea9c7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 13:03:00 +0800 Subject: [PATCH 487/738] Fix building on OS X --- chromium_src/chrome/common/chrome_constants.cc | 8 +++++++- chromium_src/chrome/common/chrome_constants.h | 8 ++++++++ chromium_src/chrome/common/chrome_paths_mac.mm | 3 +-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/chromium_src/chrome/common/chrome_constants.cc b/chromium_src/chrome/common/chrome_constants.cc index 1e7bd33a9658..43a6ccdc7cb4 100644 --- a/chromium_src/chrome/common/chrome_constants.cc +++ b/chromium_src/chrome/common/chrome_constants.cc @@ -3,10 +3,16 @@ // found in the LICENSE file. #include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_version.h" + +#define FPL FILE_PATH_LITERAL namespace chrome { +#if defined(OS_MACOSX) +const base::FilePath::CharType kFrameworkName[] = + FPL(ATOM_PRODUCT_NAME " Framework.framework"); +#endif // OS_MACOSX + // filenames const base::FilePath::CharType kCacheDirname[] = FPL("Cache"); const base::FilePath::CharType kChannelIDFilename[] = FPL("Origin Bound Certs"); diff --git a/chromium_src/chrome/common/chrome_constants.h b/chromium_src/chrome/common/chrome_constants.h index e36eeeeff413..2df506ac5d59 100644 --- a/chromium_src/chrome/common/chrome_constants.h +++ b/chromium_src/chrome/common/chrome_constants.h @@ -11,6 +11,14 @@ namespace chrome { +#if defined(OS_MACOSX) +// NOTE: if you change the value of kFrameworkName, please don't forget to +// update components/test/run_all_unittests.cc as well. +// TODO(tfarina): Remove the comment above, when you fix components to use plist +// on Mac. +extern const base::FilePath::CharType kFrameworkName[]; +#endif // OS_MACOSX + // filenames extern const base::FilePath::CharType kCacheDirname[]; extern const base::FilePath::CharType kChannelIDFilename[]; diff --git a/chromium_src/chrome/common/chrome_paths_mac.mm b/chromium_src/chrome/common/chrome_paths_mac.mm index 09cf13bfe122..4a4eb87dc254 100644 --- a/chromium_src/chrome/common/chrome_paths_mac.mm +++ b/chromium_src/chrome/common/chrome_paths_mac.mm @@ -179,10 +179,9 @@ base::FilePath GetVersionedDirectory() { // .app's versioned directory. Go up two steps to get to the browser // .app's versioned directory. path = path.DirName().DirName(); - DCHECK_EQ(path.BaseName().value(), kChromeVersion); } else { // Go into the versioned directory. - path = path.Append("Versions").Append(kChromeVersion); + path = path.Append("Frameworks"); } return path; From d3caea91b073b1c38117135c7e720b2a7deef047 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 13:05:16 +0800 Subject: [PATCH 488/738] Add paths from chrome_paths --- atom/app/atom_main_delegate.cc | 3 +++ atom/browser/api/atom_api_app.cc | 30 +++++++++++++----------------- docs/api/app.md | 8 ++++++-- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 3bc1ac497082..80283131069d 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -16,6 +16,7 @@ #include "base/debug/stack_trace.h" #include "base/environment.h" #include "base/logging.h" +#include "chrome/common/chrome_paths.h" #include "content/public/common/content_switches.h" #include "ui/base/resource/resource_bundle.h" @@ -79,6 +80,8 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { if (enable_stack_dumping) base::debug::EnableInProcessStackDumping(); + chrome::RegisterPathProvider(); + return brightray::MainDelegate::BasicStartupComplete(exit_code); } diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index d6d961a08dc4..e1fa03af5fbd 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -22,9 +22,9 @@ #include "base/command_line.h" #include "base/environment.h" #include "base/files/file_path.h" -#include "base/nix/xdg_util.h" #include "base/path_service.h" #include "brightray/browser/brightray_paths.h" +#include "chrome/common/chrome_paths.h" #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/gpu_data_manager.h" #include "content/public/common/content_switches.h" @@ -100,12 +100,22 @@ int GetPathConstant(const std::string& name) { return base::DIR_HOME; else if (name == "temp") return base::DIR_TEMP; - else if (name == "userDesktop") + else if (name == "userDesktop" || name == "desktop") return base::DIR_USER_DESKTOP; else if (name == "exe") return base::FILE_EXE; else if (name == "module") return base::FILE_MODULE; + else if (name == "documents") + return chrome::DIR_USER_DOCUMENTS; + else if (name == "downloads") + return chrome::DIR_DEFAULT_DOWNLOADS; + else if (name == "music") + return chrome::DIR_USER_MUSIC; + else if (name == "pictures") + return chrome::DIR_USER_PICTURES; + else if (name == "videos") + return chrome::DIR_USER_VIDEOS; else return -1; } @@ -156,17 +166,6 @@ void PassLoginInformation(scoped_refptr login_handler, login_handler->CancelAuth(); } -bool GetUserDownloadsDirectory(base::FilePath* path) { -#if defined(OS_LINUX) - *path = base::nix::GetXDGUserDirectory("DOWNLOAD", "Downloads"); - return true; -#elif defined(OS_MACOSX) - return false; -#elif defined(OS_WIN) - return false; -#endif -} - } // namespace App::App() { @@ -284,11 +283,8 @@ base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) { int key = GetPathConstant(name); if (key >= 0) succeed = PathService::Get(key, &path); - if (!succeed) { - if (name == "downloads" && GetUserDownloadsDirectory(&path)) - return path; + if (!succeed) args->ThrowError("Failed to get path"); - } return path; } diff --git a/docs/api/app.md b/docs/api/app.md index b145ce7f01d4..9d10bbb835c5 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -238,10 +238,14 @@ You can request the following paths by the name: * `userData` The directory for storing your app's configuration files, which by default it is the `appData` directory appended with your app's name. * `temp` Temporary directory. -* `userDesktop` The current user's Desktop directory. * `exe` The current executable file. * `module` The `libchromiumcontent` library. -* `downloads` User's download directory. +* `desktop` The current user's Desktop directory. +* `documents` Directory for a user's "My Documents". +* `downloads` Directory for a user's downloads. +* `music` Directory for a user's music. +* `pictures` Directory for a user's pictures. +* `videos` Directory for a user's videos. ### `app.setPath(name, path)` From fdc19f2d3a16e703fbcc6985a4a98673a0292936 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 13:23:13 +0800 Subject: [PATCH 489/738] Fix building on Windows --- .../chrome/common/chrome_paths_win.cc | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/chromium_src/chrome/common/chrome_paths_win.cc b/chromium_src/chrome/common/chrome_paths_win.cc index 18073ca04759..37f4ec2b05bd 100644 --- a/chromium_src/chrome/common/chrome_paths_win.cc +++ b/chromium_src/chrome/common/chrome_paths_win.cc @@ -15,9 +15,6 @@ #include "base/win/metro.h" #include "base/win/scoped_co_mem.h" #include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/installer/util/browser_distribution.h" -#include "components/nacl/common/nacl_switches.h" namespace chrome { @@ -43,12 +40,7 @@ bool GetUserDirectory(int csidl_folder, base::FilePath* result) { } // namespace bool GetDefaultUserDataDirectory(base::FilePath* result) { - if (!PathService::Get(base::DIR_LOCAL_APP_DATA, result)) - return false; - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - *result = result->Append(dist->GetInstallSubDir()); - *result = result->Append(chrome::kUserDataDirname); - return true; + return PathService::Get(base::DIR_LOCAL_APP_DATA, result); } void GetUserCacheDirectory(const base::FilePath& profile_dir, @@ -106,16 +98,9 @@ bool ProcessNeedsProfileDir(const std::string& process_type) { // service processes to be able to use the profile directory because if it // lies on a network share the sandbox will prevent us from accessing it. - if (process_type.empty() || process_type == switches::kServiceProcess) + if (process_type.empty()) return true; -#if !defined(DISABLE_NACL) - if (process_type == switches::kNaClBrokerProcess || - process_type == switches::kNaClLoaderProcess) { - return true; - } -#endif - return false; } From 860c46b3c1fb05aae557971a17adbed9601e151c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 13:58:31 +0800 Subject: [PATCH 490/738] Separate options from switches On Windows the case sensitivity of command line switches are ignored, so --nodeIntegraion will become --nodeintegration. We should separate options from switches so we use "nodeIntegraion" in options, while passing "--node-integration" in command line. --- atom/browser/api/atom_api_window.cc | 14 +++---- atom/browser/native_window.cc | 38 +++++++++---------- atom/browser/native_window_mac.mm | 18 ++++----- atom/browser/native_window_views.cc | 20 +++++----- atom/browser/web_contents_preferences.cc | 48 ++++++++++++++---------- atom/common/options_switches.cc | 31 +++++++++++---- atom/common/options_switches.h | 22 ++++++++++- atom/renderer/lib/init.coffee | 4 +- 8 files changed, 119 insertions(+), 76 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 048a8eff1df9..61f43f9aac38 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -127,16 +127,16 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) { // Use options.webPreferences to create WebContents. mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate); - options.Get(switches::kWebPreferences, &web_preferences); + options.Get(options::kWebPreferences, &web_preferences); // Be compatible with old options which are now in web_preferences. v8::Local value; - if (options.Get(switches::kNodeIntegration, &value)) - web_preferences.Set(switches::kNodeIntegration, value); - if (options.Get(switches::kPreloadScript, &value)) - web_preferences.Set(switches::kPreloadScript, value); - if (options.Get(switches::kZoomFactor, &value)) - web_preferences.Set(switches::kZoomFactor, value); + if (options.Get(options::kNodeIntegration, &value)) + web_preferences.Set(options::kNodeIntegration, value); + if (options.Get(options::kPreloadScript, &value)) + web_preferences.Set(options::kPreloadScript, value); + if (options.Get(options::kZoomFactor, &value)) + web_preferences.Set(options::kZoomFactor, value); // Creates the WebContents used by BrowserWindow. auto web_contents = WebContents::Create(isolate, web_preferences); diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index ba5dad74f523..ad7a6c4b0654 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -56,16 +56,16 @@ NativeWindow::NativeWindow( aspect_ratio_(0.0), inspectable_web_contents_(inspectable_web_contents), weak_factory_(this) { - options.Get(switches::kFrame, &has_frame_); - options.Get(switches::kTransparent, &transparent_); - options.Get(switches::kEnableLargerThanScreen, &enable_larger_than_screen_); + options.Get(options::kFrame, &has_frame_); + options.Get(options::kTransparent, &transparent_); + options.Get(options::kEnableLargerThanScreen, &enable_larger_than_screen_); // Tell the content module to initialize renderer widget with transparent // mode. ui::GpuSwitchingManager::SetTransparent(transparent_); // Read icon before window is created. - options.Get(switches::kIcon, &icon_); + options.Get(options::kIcon, &icon_); WindowList::AddWindow(this); } @@ -91,25 +91,25 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { // Setup window from options. int x = -1, y = -1; bool center; - if (options.Get(switches::kX, &x) && options.Get(switches::kY, &y)) { + if (options.Get(options::kX, &x) && options.Get(options::kY, &y)) { SetPosition(gfx::Point(x, y)); - } else if (options.Get(switches::kCenter, ¢er) && center) { + } else if (options.Get(options::kCenter, ¢er) && center) { Center(); } // On Linux and Window we may already have maximum size defined. extensions::SizeConstraints size_constraints(GetContentSizeConstraints()); int min_height = 0, min_width = 0; - if (options.Get(switches::kMinHeight, &min_height) | - options.Get(switches::kMinWidth, &min_width)) { + if (options.Get(options::kMinHeight, &min_height) | + options.Get(options::kMinWidth, &min_width)) { size_constraints.set_minimum_size(gfx::Size(min_width, min_height)); } int max_height = INT_MAX, max_width = INT_MAX; - if (options.Get(switches::kMaxHeight, &max_height) | - options.Get(switches::kMaxWidth, &max_width)) { + if (options.Get(options::kMaxHeight, &max_height) | + options.Get(options::kMaxWidth, &max_width)) { size_constraints.set_maximum_size(gfx::Size(max_width, max_height)); } bool use_content_size = false; - options.Get(switches::kUseContentSize, &use_content_size); + options.Get(options::kUseContentSize, &use_content_size); if (use_content_size) { SetContentSizeConstraints(size_constraints); } else { @@ -117,39 +117,39 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { } #if defined(OS_WIN) || defined(USE_X11) bool resizable; - if (options.Get(switches::kResizable, &resizable)) { + if (options.Get(options::kResizable, &resizable)) { SetResizable(resizable); } #endif bool top; - if (options.Get(switches::kAlwaysOnTop, &top) && top) { + if (options.Get(options::kAlwaysOnTop, &top) && top) { SetAlwaysOnTop(true); } #if defined(OS_MACOSX) || defined(OS_WIN) bool fullscreen; - if (options.Get(switches::kFullscreen, &fullscreen) && fullscreen) { + if (options.Get(options::kFullscreen, &fullscreen) && fullscreen) { SetFullScreen(true); } #endif bool skip; - if (options.Get(switches::kSkipTaskbar, &skip) && skip) { + if (options.Get(options::kSkipTaskbar, &skip) && skip) { SetSkipTaskbar(skip); } bool kiosk; - if (options.Get(switches::kKiosk, &kiosk) && kiosk) { + if (options.Get(options::kKiosk, &kiosk) && kiosk) { SetKiosk(kiosk); } std::string color; - if (options.Get(switches::kBackgroundColor, &color)) { + if (options.Get(options::kBackgroundColor, &color)) { SetBackgroundColor(color); } std::string title("Electron"); - options.Get(switches::kTitle, &title); + options.Get(options::kTitle, &title); SetTitle(title); // Then show it. bool show = true; - options.Get(switches::kShow, &show); + options.Get(options::kShow, &show); if (show) Show(); } diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 28c8a5ae59a0..b129ded6f85e 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -320,8 +320,8 @@ NativeWindowMac::NativeWindowMac( is_kiosk_(false), attention_request_id_(0) { int width = 800, height = 600; - options.Get(switches::kWidth, &width); - options.Get(switches::kHeight, &height); + options.Get(options::kWidth, &width); + options.Get(options::kHeight, &height); NSRect main_screen_rect = [[[NSScreen screens] objectAtIndex:0] frame]; NSRect cocoa_bounds = NSMakeRect( @@ -331,14 +331,14 @@ NativeWindowMac::NativeWindowMac( height); bool useStandardWindow = true; - options.Get(switches::kStandardWindow, &useStandardWindow); + options.Get(options::kStandardWindow, &useStandardWindow); bool resizable = true; - options.Get(switches::kResizable, &resizable); + options.Get(options::kResizable, &resizable); // New title bar styles are available in Yosemite or newer std::string titleBarStyle; if (base::mac::IsOSYosemiteOrLater()) - options.Get(switches::kTitleBarStyle, &titleBarStyle); + options.Get(options::kTitleBarStyle, &titleBarStyle); NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask; @@ -394,23 +394,23 @@ NativeWindowMac::NativeWindowMac( // On OS X the initial window size doesn't include window frame. bool use_content_size = false; - options.Get(switches::kUseContentSize, &use_content_size); + options.Get(options::kUseContentSize, &use_content_size); if (!has_frame() || !use_content_size) SetSize(gfx::Size(width, height)); // Enable the NSView to accept first mouse event. bool acceptsFirstMouse = false; - options.Get(switches::kAcceptFirstMouse, &acceptsFirstMouse); + options.Get(options::kAcceptFirstMouse, &acceptsFirstMouse); [window_ setAcceptsFirstMouse:acceptsFirstMouse]; // Disable auto-hiding cursor. bool disableAutoHideCursor = false; - options.Get(switches::kDisableAutoHideCursor, &disableAutoHideCursor); + options.Get(options::kDisableAutoHideCursor, &disableAutoHideCursor); [window_ setDisableAutoHideCursor:disableAutoHideCursor]; // Disable fullscreen button when 'fullscreen' is specified to false. bool fullscreen; - if (!(options.Get(switches::kFullscreen, &fullscreen) && + if (!(options.Get(options::kFullscreen, &fullscreen) && !fullscreen)) { NSUInteger collectionBehavior = [window_ collectionBehavior]; collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary; diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 876058789d0f..c12ae1986c64 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -132,13 +132,13 @@ NativeWindowViews::NativeWindowViews( keyboard_event_handler_(new views::UnhandledKeyboardEventHandler), use_content_size_(false), resizable_(true) { - options.Get(switches::kTitle, &title_); - options.Get(switches::kAutoHideMenuBar, &menu_bar_autohide_); + options.Get(options::kTitle, &title_); + options.Get(options::kAutoHideMenuBar, &menu_bar_autohide_); #if defined(OS_WIN) // On Windows we rely on the CanResize() to indicate whether window can be // resized, and it should be set before window is created. - options.Get(switches::kResizable, &resizable_); + options.Get(options::kResizable, &resizable_); #endif if (enable_larger_than_screen()) @@ -150,8 +150,8 @@ NativeWindowViews::NativeWindowViews( gfx::Size(), gfx::Size(INT_MAX / 10, INT_MAX / 10))); int width = 800, height = 600; - options.Get(switches::kWidth, &width); - options.Get(switches::kHeight, &height); + options.Get(options::kWidth, &width); + options.Get(options::kHeight, &height); gfx::Rect bounds(0, 0, width, height); widget_size_ = bounds.size(); @@ -187,7 +187,7 @@ NativeWindowViews::NativeWindowViews( window_->Init(params); bool fullscreen = false; - options.Get(switches::kFullscreen, &fullscreen); + options.Get(options::kFullscreen, &fullscreen); #if defined(USE_X11) // Start monitoring window states. @@ -195,7 +195,7 @@ NativeWindowViews::NativeWindowViews( // Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set. bool use_dark_theme = false; - if (options.Get(switches::kDarkTheme, &use_dark_theme) && use_dark_theme) { + if (options.Get(options::kDarkTheme, &use_dark_theme) && use_dark_theme) { XDisplay* xdisplay = gfx::GetXDisplay(); XChangeProperty(xdisplay, GetAcceleratedWidget(), XInternAtom(xdisplay, "_GTK_THEME_VARIANT", False), @@ -209,7 +209,7 @@ NativeWindowViews::NativeWindowViews( // to manually set the _NET_WM_STATE. std::vector<::Atom> state_atom_list; bool skip_taskbar = false; - if (options.Get(switches::kSkipTaskbar, &skip_taskbar) && skip_taskbar) { + if (options.Get(options::kSkipTaskbar, &skip_taskbar) && skip_taskbar) { state_atom_list.push_back(GetAtom("_NET_WM_STATE_SKIP_TASKBAR")); } @@ -223,7 +223,7 @@ NativeWindowViews::NativeWindowViews( // Set the _NET_WM_WINDOW_TYPE. std::string window_type; - if (options.Get(switches::kType, &window_type)) + if (options.Get(options::kType, &window_type)) SetWindowType(GetAcceleratedWidget(), window_type); #endif @@ -274,7 +274,7 @@ NativeWindowViews::NativeWindowViews( gfx::Size size = bounds.size(); if (has_frame() && - options.Get(switches::kUseContentSize, &use_content_size_) && + options.Get(options::kUseContentSize, &use_content_size_) && use_content_size_) size = ContentSizeToWindowSize(size); diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 2adb77211b27..188de4d1bfe7 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -25,13 +25,23 @@ namespace atom { namespace { // Array of available web runtime features. -const char* kWebRuntimeFeatures[] = { - switches::kExperimentalFeatures, - switches::kExperimentalCanvasFeatures, - switches::kOverlayScrollbars, - switches::kOverlayFullscreenVideo, - switches::kSharedWorker, - switches::kPageVisibility, +struct FeaturePair { + const char* name; + const char* cmd; +}; +FeaturePair kWebRuntimeFeatures[] = { + { options::kExperimentalFeatures, + switches::kExperimentalFeatures }, + { options::kExperimentalCanvasFeatures, + switches::kExperimentalCanvasFeatures }, + { options::kOverlayScrollbars, + switches::kOverlayScrollbars }, + { options::kOverlayFullscreenVideo, + switches::kOverlayFullscreenVideo }, + { options::kSharedWorker, + switches::kSharedWorker }, + { options::kPageVisibility, + switches::kPageVisibility }, }; } // namespace @@ -69,7 +79,7 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( bool b; #if defined(OS_WIN) // Check if DirectWrite is disabled. - if (web_preferences.GetBoolean(switches::kDirectWrite, &b) && !b) + if (web_preferences.GetBoolean(options::kDirectWrite, &b) && !b) command_line->AppendSwitch(::switches::kDisableDirectWrite); #endif @@ -80,17 +90,17 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( // This set of options are not availabe in WebPreferences, so we have to pass // them via command line and enable them in renderer procss. for (size_t i = 0; i < arraysize(kWebRuntimeFeatures); ++i) { - const char* feature = kWebRuntimeFeatures[i]; - if (web_preferences.GetBoolean(feature, &b)) - command_line->AppendSwitchASCII(feature, b ? "true" : "false"); + const auto& feature = kWebRuntimeFeatures[i]; + if (web_preferences.GetBoolean(feature.name, &b)) + command_line->AppendSwitchASCII(feature.cmd, b ? "true" : "false"); } // Check if we have node integration specified. bool node_integration = true; - web_preferences.GetBoolean(switches::kNodeIntegration, &node_integration); + web_preferences.GetBoolean(options::kNodeIntegration, &node_integration); // Be compatible with old API of "node-integration" option. std::string old_token; - if (web_preferences.GetString(switches::kNodeIntegration, &old_token) && + if (web_preferences.GetString(options::kNodeIntegration, &old_token) && old_token != "disable") node_integration = true; command_line->AppendSwitchASCII(switches::kNodeIntegration, @@ -98,12 +108,12 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( // The preload script. base::FilePath::StringType preload; - if (web_preferences.GetString(switches::kPreloadScript, &preload)) { + if (web_preferences.GetString(options::kPreloadScript, &preload)) { if (base::FilePath(preload).IsAbsolute()) command_line->AppendSwitchNative(switches::kPreloadScript, preload); else LOG(ERROR) << "preload script must have absolute path."; - } else if (web_preferences.GetString(switches::kPreloadUrl, &preload)) { + } else if (web_preferences.GetString(options::kPreloadUrl, &preload)) { // Translate to file path if there is "preload-url" option. base::FilePath preload_path; if (net::FileURLToFilePath(GURL(preload), &preload_path)) @@ -114,15 +124,14 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( // The zoom factor. double zoom_factor = 1.0; - if (web_preferences.GetDouble(switches::kZoomFactor, &zoom_factor) && + if (web_preferences.GetDouble(options::kZoomFactor, &zoom_factor) && zoom_factor != 1.0) command_line->AppendSwitchASCII(switches::kZoomFactor, base::DoubleToString(zoom_factor)); // --guest-instance-id, which is used to identify guest WebContents. int guest_instance_id; - if (web_preferences.GetInteger(switches::kGuestInstanceID, - &guest_instance_id)) + if (web_preferences.GetInteger(options::kGuestInstanceID, &guest_instance_id)) command_line->AppendSwitchASCII(switches::kGuestInstanceID, base::IntToString(guest_instance_id)); } @@ -152,8 +161,7 @@ void WebContentsPreferences::OverrideWebkitPrefs( prefs->allow_displaying_insecure_content = !b; prefs->allow_running_insecure_content = !b; } - if (self->web_preferences_.GetBoolean("allowDisplayingInsecureContent", - &b)) + if (self->web_preferences_.GetBoolean("allowDisplayingInsecureContent", &b)) prefs->allow_displaying_insecure_content = b; if (self->web_preferences_.GetBoolean("allowRunningInsecureContent", &b)) prefs->allow_running_insecure_content = b; diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 9b3b50b4bf31..1d375ba0fc4e 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -6,7 +6,7 @@ namespace atom { -namespace switches { +namespace options { const char kTitle[] = "title"; const char kIcon[] = "icon"; @@ -85,6 +85,12 @@ const char kNodeIntegration[] = "nodeIntegration"; // Instancd ID of guest WebContents. const char kGuestInstanceID[] = "guestInstanceId"; +// Set page visiblity to always visible. +const char kPageVisibility[] = "pageVisibility"; + +// Enable DirectWrite on Windows. +const char kDirectWrite[] = "directWrite"; + // Web runtime features. const char kExperimentalFeatures[] = "experimentalFeatures"; const char kExperimentalCanvasFeatures[] = "experimentalCanvasFeatures"; @@ -92,6 +98,10 @@ const char kOverlayScrollbars[] = "overlayScrollbars"; const char kOverlayFullscreenVideo[] = "overlayFullscreenVideo"; const char kSharedWorker[] = "sharedWorker"; +} // namespace options + +namespace switches { + // Enable plugins. const char kEnablePlugins[] = "enable-plugins"; @@ -101,12 +111,6 @@ const char kPpapiFlashPath[] = "ppapi-flash-path"; // Ppapi Flash version. const char kPpapiFlashVersion[] = "ppapi-flash-version"; -// Set page visiblity to always visible. -const char kPageVisibility[] = "page-visibility"; - -// Enable DirectWrite on Windows. -const char kDirectWrite[] = "direct-write"; - // Path to client certificate. const char kClientCertificate[] = "client-certificate"; @@ -126,6 +130,19 @@ const char kCipherSuiteBlacklist[] = "cipher-suite-blacklist"; // The browser process app model ID const char kAppUserModelId[] = "app-user-model-id"; +// The command line switch versions of the options. +const char kZoomFactor[] = "zoom-factor"; +const char kPreloadScript[] = "preload"; +const char kPreloadUrl[] = "preload-url"; +const char kNodeIntegration[] = "node-integration"; +const char kGuestInstanceID[] = "guest-instance-id"; +const char kExperimentalFeatures[] = "experimental-features"; +const char kExperimentalCanvasFeatures[] = "experimental-canvas-features"; +const char kOverlayScrollbars[] = "overlay-scrollbars"; +const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video"; +const char kSharedWorker[] = "shared-worker"; +const char kPageVisibility[] = "page-visiblity"; + } // namespace switches } // namespace atom diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 9f171836f653..7f262fb0f721 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -7,7 +7,7 @@ namespace atom { -namespace switches { +namespace options { extern const char kTitle[]; extern const char kIcon[]; @@ -41,6 +41,7 @@ extern const char kBackgroundColor[]; extern const char kWebPreferences[]; // WebPreferences. +extern const char kDirectWrite[]; extern const char kZoomFactor[]; extern const char kPreloadScript[]; extern const char kPreloadUrl[]; @@ -52,9 +53,14 @@ extern const char kOverlayScrollbars[]; extern const char kOverlayFullscreenVideo[]; extern const char kSharedWorker[]; extern const char kPageVisibility[]; -extern const char kDirectWrite[]; + +} // namespace options + // Following are actually command line switches, should be moved to other files. + +namespace switches { + extern const char kEnablePlugins[]; extern const char kPpapiFlashPath[]; extern const char kPpapiFlashVersion[]; @@ -65,6 +71,18 @@ extern const char kSSLVersionFallbackMin[]; extern const char kCipherSuiteBlacklist[]; extern const char kAppUserModelId[]; +extern const char kZoomFactor[]; +extern const char kPreloadScript[]; +extern const char kPreloadUrl[]; +extern const char kNodeIntegration[]; +extern const char kGuestInstanceID[]; +extern const char kExperimentalFeatures[]; +extern const char kExperimentalCanvasFeatures[]; +extern const char kOverlayScrollbars[]; +extern const char kOverlayFullscreenVideo[]; +extern const char kSharedWorker[]; +extern const char kPageVisibility[]; + } // namespace switches } // namespace atom diff --git a/atom/renderer/lib/init.coffee b/atom/renderer/lib/init.coffee index b7155c1cc55a..d9f104f8d4fc 100644 --- a/atom/renderer/lib/init.coffee +++ b/atom/renderer/lib/init.coffee @@ -27,10 +27,10 @@ v8Util.setHiddenValue global, 'ipc', new events.EventEmitter # Process command line arguments. nodeIntegration = 'false' for arg in process.argv - if arg.indexOf('--guestInstanceId=') == 0 + if arg.indexOf('--guest-instance-id=') == 0 # This is a guest web view. process.guestInstanceId = parseInt arg.substr(arg.indexOf('=') + 1) - else if arg.indexOf('--nodeIntegration=') == 0 + else if arg.indexOf('--node-integration=') == 0 nodeIntegration = arg.substr arg.indexOf('=') + 1 else if arg.indexOf('--preload=') == 0 preloadScript = arg.substr arg.indexOf('=') + 1 From 9ac87e844a08e5131c1e327e616eb19ddfb79948 Mon Sep 17 00:00:00 2001 From: Sunny Date: Fri, 13 Nov 2015 15:41:20 +0800 Subject: [PATCH 491/738] Fix node_bindings link in Simplified Chinese document translation --- docs/development/atom-shell-vs-node-webkit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/atom-shell-vs-node-webkit.md b/docs/development/atom-shell-vs-node-webkit.md index c1fffa304ab5..4431a54eacee 100644 --- a/docs/development/atom-shell-vs-node-webkit.md +++ b/docs/development/atom-shell-vs-node-webkit.md @@ -35,7 +35,7 @@ __3. Node Integration__ In NW.js, the Node integration in web pages requires patching Chromium to work, while in Electron we chose a different way to integrate the libuv loop with each platform's message loop to avoid hacking Chromium. See the -[`node_bindings`](../../atom/common/) code for how that was done. +[`node_bindings`](../../../atom/common/) code for how that was done. __4. Multi-context__ From fbb8e61958c8950455883e2a4ae12088ba030a12 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 16:03:40 +0800 Subject: [PATCH 492/738] Replace "Url" in API names with "URL" --- atom/browser/api/atom_api_auto_updater.cc | 2 +- atom/browser/api/atom_api_cookies.cc | 6 +- atom/browser/api/atom_api_download_item.cc | 6 +- atom/browser/api/atom_api_download_item.h | 2 +- atom/browser/api/atom_api_protocol.cc | 4 +- atom/browser/api/atom_api_web_contents.cc | 4 +- atom/browser/api/lib/app.coffee | 3 +- atom/browser/api/lib/auto-updater.coffee | 9 +- .../lib/auto-updater/auto-updater-win.coffee | 12 +-- .../auto-updater/squirrel-update-win.coffee | 8 +- atom/browser/api/lib/browser-window.coffee | 8 +- .../api/lib/navigation-controller.coffee | 20 ++-- atom/browser/api/lib/web-contents.coffee | 8 +- atom/browser/atom_access_token_store.cc | 6 +- atom/browser/default_app/default_app.js | 2 +- atom/browser/lib/guest-view-manager.coffee | 4 +- atom/browser/lib/guest-window-manager.coffee | 8 +- .../browser/net/url_request_async_asar_job.cc | 4 +- atom/browser/net/url_request_async_asar_job.h | 6 +- atom/browser/web_contents_preferences.cc | 2 +- atom/common/api/atom_api_native_image.cc | 5 +- atom/common/api/lib/crash-reporter.coffee | 19 ++-- atom/common/api/lib/native-image.coffee | 8 +- atom/common/options_switches.cc | 4 +- atom/common/options_switches.h | 4 +- atom/common/platform_util_win.cc | 4 +- atom/renderer/api/atom_api_web_frame.cc | 10 +- atom/renderer/api/atom_api_web_frame.h | 2 +- atom/renderer/api/lib/web-frame.coffee | 10 +- atom/renderer/lib/override.coffee | 4 +- .../lib/web-view/guest-view-internal.coffee | 6 +- .../lib/web-view/web-view-attributes.coffee | 8 +- atom/renderer/lib/web-view/web-view.coffee | 91 ++++++++++--------- docs/api/auto-updater.md | 6 +- docs/api/browser-window.md | 6 +- docs/api/crash-reporter.md | 6 +- docs/api/download-item.md | 2 +- docs/api/native-image.md | 8 +- docs/api/remote.md | 2 +- docs/api/session.md | 6 +- docs/api/synopsis.md | 2 +- docs/api/web-contents.md | 30 +++--- docs/api/web-frame.md | 6 +- docs/api/web-view-tag.md | 14 +-- docs/tutorial/application-packaging.md | 2 +- docs/tutorial/online-offline-events.md | 4 +- docs/tutorial/quick-start.md | 2 +- docs/tutorial/using-pepper-flash-plugin.md | 2 +- spec/api-browser-window-spec.coffee | 34 +++---- spec/api-clipboard-spec.coffee | 4 +- spec/api-crash-reporter-spec.coffee | 4 +- spec/api-ipc-spec.coffee | 2 +- spec/api-session-spec.coffee | 8 +- spec/asar-spec.coffee | 4 +- spec/chromium-spec.coffee | 4 +- spec/fixtures/api/crash.html | 2 +- spec/static/main.js | 4 +- 57 files changed, 251 insertions(+), 212 deletions(-) diff --git a/atom/browser/api/atom_api_auto_updater.cc b/atom/browser/api/atom_api_auto_updater.cc index 1c80f73f7a7d..1a02a54d4533 100644 --- a/atom/browser/api/atom_api_auto_updater.cc +++ b/atom/browser/api/atom_api_auto_updater.cc @@ -81,7 +81,7 @@ void AutoUpdater::OnWindowAllClosed() { mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) - .SetMethod("setFeedUrl", &auto_updater::AutoUpdater::SetFeedURL) + .SetMethod("setFeedURL", &auto_updater::AutoUpdater::SetFeedURL) .SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates) .SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall); } diff --git a/atom/browser/api/atom_api_cookies.cc b/atom/browser/api/atom_api_cookies.cc index 4f989eff7275..a3b2c37c9acd 100644 --- a/atom/browser/api/atom_api_cookies.cc +++ b/atom/browser/api/atom_api_cookies.cc @@ -204,7 +204,7 @@ void Cookies::GetCookiesOnIOThread(scoped_ptr filter, Passed(&filter), callback))) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&RunGetCookiesCallbackOnUIThread, isolate(), - "Url is not valid", net::CookieList(), callback)); + "URL is not valid", net::CookieList(), callback)); } } @@ -229,7 +229,7 @@ void Cookies::Remove(const mate::Dictionary& details, error_message = "Details(url, name) of removing cookie are required."; } if (error_message.empty() && !url.is_valid()) { - error_message = "Url is not valid."; + error_message = "URL is not valid."; } if (!error_message.empty()) { RunRemoveCookiesCallbackOnUIThread(isolate(), error_message, callback); @@ -261,7 +261,7 @@ void Cookies::Set(const base::DictionaryValue& options, GURL gurl(url); if (error_message.empty() && !gurl.is_valid()) { - error_message = "Url is not valid."; + error_message = "URL is not valid."; } if (!error_message.empty()) { diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index 691cfbfef594..7dd271304a43 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -103,7 +103,7 @@ int64 DownloadItem::GetTotalBytes() { return download_item_->GetTotalBytes(); } -const GURL& DownloadItem::GetUrl() { +const GURL& DownloadItem::GetURL() { return download_item_->GetURL(); } @@ -116,7 +116,7 @@ bool DownloadItem::HasUserGesture() { } std::string DownloadItem::GetFilename() { - return base::UTF16ToUTF8(net::GenerateFileName(GetUrl(), + return base::UTF16ToUTF8(net::GenerateFileName(GetURL(), GetContentDisposition(), std::string(), download_item_->GetSuggestedFilename(), @@ -152,7 +152,7 @@ mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder( .SetMethod("cancel", &DownloadItem::Cancel) .SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes) .SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes) - .SetMethod("getUrl", &DownloadItem::GetUrl) + .SetMethod("getURL", &DownloadItem::GetURL) .SetMethod("getMimeType", &DownloadItem::GetMimeType) .SetMethod("hasUserGesture", &DownloadItem::HasUserGesture) .SetMethod("getFilename", &DownloadItem::GetFilename) diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h index 14074a4bed0d..955801cd9940 100644 --- a/atom/browser/api/atom_api_download_item.h +++ b/atom/browser/api/atom_api_download_item.h @@ -49,7 +49,7 @@ class DownloadItem : public mate::EventEmitter, bool HasUserGesture(); std::string GetFilename(); std::string GetContentDisposition(); - const GURL& GetUrl(); + const GURL& GetURL(); void SetSavePath(const base::FilePath& path); private: diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index e76f26f0d4f5..b1ad7981377a 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -37,7 +37,7 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( .SetMethod("registerBufferProtocol", &Protocol::RegisterProtocol) .SetMethod("registerFileProtocol", - &Protocol::RegisterProtocol) + &Protocol::RegisterProtocol) .SetMethod("registerHttpProtocol", &Protocol::RegisterProtocol) .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol) @@ -47,7 +47,7 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( .SetMethod("interceptBufferProtocol", &Protocol::InterceptProtocol) .SetMethod("interceptFileProtocol", - &Protocol::InterceptProtocol) + &Protocol::InterceptProtocol) .SetMethod("interceptHttpProtocol", &Protocol::InterceptProtocol) .SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol); diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index d67794a91aeb..601a4ba63f13 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1003,8 +1003,8 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("isAlive", &WebContents::IsAlive, true) .SetMethod("getId", &WebContents::GetID) .SetMethod("equal", &WebContents::Equal) - .SetMethod("_loadUrl", &WebContents::LoadURL) - .SetMethod("_getUrl", &WebContents::GetURL) + .SetMethod("_loadURL", &WebContents::LoadURL) + .SetMethod("_getURL", &WebContents::GetURL) .SetMethod("getTitle", &WebContents::GetTitle) .SetMethod("isLoading", &WebContents::IsLoading) .SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse) diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 3494a6e6e431..f8d3cedd38f9 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -63,10 +63,11 @@ wrapDownloadItem = (downloadItem) -> # downloadItem is an EventEmitter. downloadItem.__proto__ = EventEmitter.prototype # Deprecated. - deprecate.property downloadItem, 'url', 'getUrl' + deprecate.property downloadItem, 'url', 'getURL' deprecate.property downloadItem, 'filename', 'getFilename' deprecate.property downloadItem, 'mimeType', 'getMimeType' deprecate.property downloadItem, 'hasUserGesture', 'hasUserGesture' + deprecate.rename downloadItem, 'getUrl', 'getURL' downloadItemBindings._setWrapDownloadItem wrapDownloadItem # Only one App object pemitted. diff --git a/atom/browser/api/lib/auto-updater.coffee b/atom/browser/api/lib/auto-updater.coffee index d5e69e2a5c2e..28df59fbc3db 100644 --- a/atom/browser/api/lib/auto-updater.coffee +++ b/atom/browser/api/lib/auto-updater.coffee @@ -1,5 +1,12 @@ -module.exports = +{deprecate} = require 'electron' + +autoUpdater = if process.platform is 'win32' require './auto-updater/auto-updater-win' else require './auto-updater/auto-updater-native' + +# Deprecated. +deprecate.rename autoUpdater, 'setFeedUrl', 'setFeedURL' + +module.exports = autoUpdater diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee index 12ebedaaf71c..e7cb194ffcf4 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.coffee +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.coffee @@ -9,28 +9,28 @@ class AutoUpdater extends EventEmitter squirrelUpdate.processStart() app.quit() - setFeedUrl: (updateUrl) -> - @updateUrl = updateUrl + setFeedURL: (updateURL) -> + @updateURL = updateURL checkForUpdates: -> - return @emitError 'Update URL is not set' unless @updateUrl + return @emitError 'Update URL is not set' unless @updateURL return @emitError 'Can not find Squirrel' unless squirrelUpdate.supported() @emit 'checking-for-update' - squirrelUpdate.download @updateUrl, (error, update) => + squirrelUpdate.download @updateURL, (error, update) => return @emitError error if error? return @emit 'update-not-available' unless update? @emit 'update-available' - squirrelUpdate.update @updateUrl, (error) => + squirrelUpdate.update @updateURL, (error) => return @emitError error if error? {releaseNotes, version} = update # Following information is not available on Windows, so fake them. date = new Date - url = @updateUrl + url = @updateURL @emit 'update-downloaded', {}, releaseNotes, version, date, url, => @quitAndInstall() diff --git a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee index ed302124e52e..ee914c4fa827 100644 --- a/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee +++ b/atom/browser/api/lib/auto-updater/squirrel-update-win.coffee @@ -41,8 +41,8 @@ exports.processStart = (callback) -> spawnUpdate ['--processStart', exeName], true, -> # Download the releases specified by the URL and write new results to stdout. -exports.download = (updateUrl, callback) -> - spawnUpdate ['--download', updateUrl], false, (error, stdout) -> +exports.download = (updateURL, callback) -> + spawnUpdate ['--download', updateURL], false, (error, stdout) -> return callback(error) if error? try @@ -55,8 +55,8 @@ exports.download = (updateUrl, callback) -> callback null, update # Update the application to the latest remote version specified by URL. -exports.update = (updateUrl, callback) -> - spawnUpdate ['--update', updateUrl], false, callback +exports.update = (updateURL, callback) -> + spawnUpdate ['--update', updateURL], false, callback # Is the Update.exe installed with the current application? exports.supported = -> diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 3cefa1bf60ce..9947bc1a50ba 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -69,7 +69,8 @@ BrowserWindow.fromDevToolsWebContents = (webContents) -> return window for window in windows when window.devToolsWebContents?.equal webContents # Helpers. -BrowserWindow::loadUrl = -> @webContents.loadUrl.apply @webContents, arguments +BrowserWindow::loadURL = -> @webContents.loadURL.apply @webContents, arguments +BrowserWindow::getURL = -> @webContents.getURL() BrowserWindow::reload = -> @webContents.reload.apply @webContents, arguments BrowserWindow::send = -> @webContents.send.apply @webContents, arguments BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments @@ -80,14 +81,12 @@ BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContent BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker() # Deprecated. -deprecate.rename BrowserWindow, 'restart', 'reload' deprecate.member BrowserWindow, 'undo', 'webContents' deprecate.member BrowserWindow, 'redo', 'webContents' deprecate.member BrowserWindow, 'cut', 'webContents' deprecate.member BrowserWindow, 'copy', 'webContents' deprecate.member BrowserWindow, 'paste', 'webContents' deprecate.member BrowserWindow, 'selectAll', 'webContents' -deprecate.member BrowserWindow, 'getUrl', 'webContents' deprecate.member BrowserWindow, 'reloadIgnoringCache', 'webContents' deprecate.member BrowserWindow, 'getPageTitle', 'webContents' deprecate.member BrowserWindow, 'isLoading', 'webContents' @@ -97,5 +96,8 @@ deprecate.member BrowserWindow, 'isCrashed', 'webContents' deprecate.member BrowserWindow, 'executeJavaScriptInDevTools', 'webContents' deprecate.member BrowserWindow, 'print', 'webContents' deprecate.member BrowserWindow, 'printToPDF', 'webContents' +deprecate.rename BrowserWindow, 'restart', 'reload' +deprecate.rename BrowserWindow, 'loadUrl', 'loadURL' +deprecate.rename BrowserWindow, 'getUrl', 'getURL' module.exports = BrowserWindow diff --git a/atom/browser/api/lib/navigation-controller.coffee b/atom/browser/api/lib/navigation-controller.coffee index 88b1ed30ddd3..7d276e57e31a 100644 --- a/atom/browser/api/lib/navigation-controller.coffee +++ b/atom/browser/api/lib/navigation-controller.coffee @@ -9,7 +9,7 @@ ipcMain.on 'ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', (event, method, args...) -> # JavaScript implementation of Chromium's NavigationController. # Instead of relying on Chromium for history control, we compeletely do history -# control on user land, and only rely on WebContents.loadUrl for navigation. +# control on user land, and only rely on WebContents.loadURL for navigation. # This helps us avoid Chromium's various optimizations so we can ensure renderer # process is restarted everytime. class NavigationController @@ -17,9 +17,9 @@ class NavigationController @clearHistory() # webContents may have already navigated to a page. - if @webContents._getUrl() + if @webContents._getURL() @currentIndex++ - @history.push @webContents._getUrl() + @history.push @webContents._getURL() @webContents.on 'navigation-entry-commited', (event, url, inPage, replaceEntry) => if @inPageIndex > -1 and not inPage @@ -42,12 +42,12 @@ class NavigationController @currentIndex++ @history.push url - loadUrl: (url, options={}) -> + loadURL: (url, options={}) -> @pendingIndex = -1 - @webContents._loadUrl url, options + @webContents._loadURL url, options @webContents.emit 'load-url', url, options - getUrl: -> + getURL: -> if @currentIndex is -1 '' else @@ -59,7 +59,7 @@ class NavigationController reload: -> @pendingIndex = @currentIndex - @webContents._loadUrl @getUrl(), {} + @webContents._loadURL @getURL(), {} reloadIgnoringCache: -> @webContents._reloadIgnoringCache() # Rely on WebContents to clear cache. @@ -89,7 +89,7 @@ class NavigationController if @inPageIndex > -1 and @pendingIndex >= @inPageIndex @webContents._goBack() else - @webContents._loadUrl @history[@pendingIndex], {} + @webContents._loadURL @history[@pendingIndex], {} goForward: -> return unless @canGoForward() @@ -97,12 +97,12 @@ class NavigationController if @inPageIndex > -1 and @pendingIndex >= @inPageIndex @webContents._goForward() else - @webContents._loadUrl @history[@pendingIndex], {} + @webContents._loadURL @history[@pendingIndex], {} goToIndex: (index) -> return unless @canGoToIndex index @pendingIndex = index - @webContents._loadUrl @history[@pendingIndex], {} + @webContents._loadURL @history[@pendingIndex], {} goToOffset: (offset) -> return unless @canGoToOffset offset diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index b3b1e7ed9fa4..1a224c7416f5 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -1,5 +1,5 @@ {EventEmitter} = require 'events' -{ipcMain, NavigationController, Menu} = require 'electron' +{deprecate, ipcMain, NavigationController, Menu} = require 'electron' binding = process.atomBinding 'web_contents' @@ -45,7 +45,7 @@ wrapWebContents = (webContents) -> # Make sure webContents.executeJavaScript would run the code only when the # web contents has been loaded. webContents.executeJavaScript = (code, hasUserGesture=false) -> - if @getUrl() and not @isLoading() + if @getURL() and not @isLoading() @_executeJavaScript code, hasUserGesture else webContents.once 'did-finish-load', @_executeJavaScript.bind(this, code, hasUserGesture) @@ -70,6 +70,10 @@ wrapWebContents = (webContents) -> menu = Menu.buildFromTemplate params.menu menu.popup params.x, params.y + # Deprecated. + deprecate.rename webContents, 'loadUrl', 'loadURL' + deprecate.rename webContents, 'getUrl', 'getURL' + webContents.printToPDF = (options, callback) -> printingSetting = pageRage: [] diff --git a/atom/browser/atom_access_token_store.cc b/atom/browser/atom_access_token_store.cc index 3d254f060188..adf2f5061cb0 100644 --- a/atom/browser/atom_access_token_store.cc +++ b/atom/browser/atom_access_token_store.cc @@ -18,7 +18,7 @@ namespace { // Notice that we just combined the api key with the url together here, because // if we use the standard {url: key} format Chromium would override our key with // the predefined one in common.gypi of libchromiumcontent, which is empty. -const char* kGeolocationProviderUrl = +const char* kGeolocationProviderURL = "https://www.googleapis.com/geolocation/v1/geolocate?key=" GOOGLEAPIS_API_KEY; @@ -35,11 +35,11 @@ void AtomAccessTokenStore::LoadAccessTokens( const LoadAccessTokensCallbackType& callback) { AccessTokenSet access_token_set; - // Equivelent to access_token_set[kGeolocationProviderUrl]. + // Equivelent to access_token_set[kGeolocationProviderURL]. // Somehow base::string16 is causing compilation errors when used in a pair // of std::map on Linux, this can work around it. std::pair token_pair; - token_pair.first = GURL(kGeolocationProviderUrl); + token_pair.first = GURL(kGeolocationProviderURL); access_token_set.insert(token_pair); auto browser_context = AtomBrowserMainParts::Get()->browser_context(); diff --git a/atom/browser/default_app/default_app.js b/atom/browser/default_app/default_app.js index 6a94db4836f8..2ec765d0d691 100644 --- a/atom/browser/default_app/default_app.js +++ b/atom/browser/default_app/default_app.js @@ -16,6 +16,6 @@ app.on('ready', function() { autoHideMenuBar: true, useContentSize: true, }); - mainWindow.loadUrl('file://' + __dirname + '/index.html'); + mainWindow.loadURL('file://' + __dirname + '/index.html'); mainWindow.focus(); }); diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index 4a33b281c9dc..e6be05a907bf 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -79,7 +79,7 @@ createGuest = (embedder, params) -> opts = {} opts.httpReferrer = params.httpreferrer if params.httpreferrer opts.userAgent = params.useragent if params.useragent - @loadUrl params.src, opts + @loadURL params.src, opts if params.allowtransparency? @setAllowTransparency params.allowtransparency @@ -122,7 +122,7 @@ attachGuest = (embedder, elementInstanceId, guestInstanceId, params) -> nodeIntegration: params.nodeintegration ? false plugins: params.plugins webSecurity: !params.disablewebsecurity - webPreferences.preloadUrl = params.preload if params.preload + webPreferences.preloadURL = params.preload if params.preload webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest, webPreferences guest.attachParams = params diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index c602d370bac0..c311e01cf487 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -27,11 +27,11 @@ mergeBrowserWindowOptions = (embedder, options) -> createGuest = (embedder, url, frameName, options) -> guest = frameToGuest[frameName] if frameName and guest? - guest.loadUrl url + guest.loadURL url return guest.id guest = new BrowserWindow(options) - guest.loadUrl url + guest.loadURL url # Remember the embedder, will be used by window.opener methods. v8Util.setHiddenValue guest.webContents, 'embedder', embedder @@ -74,12 +74,12 @@ ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestId, met ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, message, targetOrigin) -> guestContents = BrowserWindow.fromId(guestId)?.webContents - if guestContents?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*' + if guestContents?.getURL().indexOf(targetOrigin) is 0 or targetOrigin is '*' guestContents.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, targetOrigin ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, guestId, message, targetOrigin, sourceOrigin) -> embedder = v8Util.getHiddenValue event.sender, 'embedder' - if embedder?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*' + if embedder?.getURL().indexOf(targetOrigin) is 0 or targetOrigin is '*' embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, sourceOrigin ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) -> diff --git a/atom/browser/net/url_request_async_asar_job.cc b/atom/browser/net/url_request_async_asar_job.cc index ba0189e5f6e0..303bfc0170d9 100644 --- a/atom/browser/net/url_request_async_asar_job.cc +++ b/atom/browser/net/url_request_async_asar_job.cc @@ -6,13 +6,13 @@ namespace atom { -UrlRequestAsyncAsarJob::UrlRequestAsyncAsarJob( +URLRequestAsyncAsarJob::URLRequestAsyncAsarJob( net::URLRequest* request, net::NetworkDelegate* network_delegate) : JsAsker(request, network_delegate) { } -void UrlRequestAsyncAsarJob::StartAsync(scoped_ptr options) { +void URLRequestAsyncAsarJob::StartAsync(scoped_ptr options) { base::FilePath::StringType file_path; if (options->IsType(base::Value::TYPE_DICTIONARY)) { static_cast(options.get())->GetString( diff --git a/atom/browser/net/url_request_async_asar_job.h b/atom/browser/net/url_request_async_asar_job.h index 748b96d84d28..df1aed350b8b 100644 --- a/atom/browser/net/url_request_async_asar_job.h +++ b/atom/browser/net/url_request_async_asar_job.h @@ -11,15 +11,15 @@ namespace atom { // Like URLRequestAsarJob, but asks the JavaScript handler for file path. -class UrlRequestAsyncAsarJob : public JsAsker { +class URLRequestAsyncAsarJob : public JsAsker { public: - UrlRequestAsyncAsarJob(net::URLRequest*, net::NetworkDelegate*); + URLRequestAsyncAsarJob(net::URLRequest*, net::NetworkDelegate*); // JsAsker: void StartAsync(scoped_ptr options) override; private: - DISALLOW_COPY_AND_ASSIGN(UrlRequestAsyncAsarJob); + DISALLOW_COPY_AND_ASSIGN(URLRequestAsyncAsarJob); }; } // namespace atom diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 188de4d1bfe7..83145368c5fe 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -113,7 +113,7 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( command_line->AppendSwitchNative(switches::kPreloadScript, preload); else LOG(ERROR) << "preload script must have absolute path."; - } else if (web_preferences.GetString(options::kPreloadUrl, &preload)) { + } else if (web_preferences.GetString(options::kPreloadURL, &preload)) { // Translate to file path if there is "preload-url" option. base::FilePath preload_path; if (net::FileURLToFilePath(GURL(preload), &preload_path)) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index df6c14dab350..e0f0940a7420 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -168,7 +168,8 @@ mate::ObjectTemplateBuilder NativeImage::GetObjectTemplateBuilder( template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) .SetMethod("toPng", &NativeImage::ToPNG) .SetMethod("toJpeg", &NativeImage::ToJPEG) - .SetMethod("toDataUrl", &NativeImage::ToDataURL) + .SetMethod("toDataURL", &NativeImage::ToDataURL) + .SetMethod("toDataUrl", &NativeImage::ToDataURL) // deprecated. .SetMethod("isEmpty", &NativeImage::IsEmpty) .SetMethod("getSize", &NativeImage::GetSize) .SetMethod("setTemplateImage", &NativeImage::SetTemplateImage) @@ -309,7 +310,7 @@ void Initialize(v8::Local exports, v8::Local unused, dict.SetMethod("createEmpty", &atom::api::NativeImage::CreateEmpty); dict.SetMethod("createFromPath", &atom::api::NativeImage::CreateFromPath); dict.SetMethod("createFromBuffer", &atom::api::NativeImage::CreateFromBuffer); - dict.SetMethod("createFromDataUrl", + dict.SetMethod("createFromDataURL", &atom::api::NativeImage::CreateFromDataURL); } diff --git a/atom/common/api/lib/crash-reporter.coffee b/atom/common/api/lib/crash-reporter.coffee index 873fc1848c59..0713da99daef 100644 --- a/atom/common/api/lib/crash-reporter.coffee +++ b/atom/common/api/lib/crash-reporter.coffee @@ -1,14 +1,21 @@ -binding = process.atomBinding 'crash_reporter' fs = require 'fs' os = require 'os' path = require 'path' {spawn} = require 'child_process' +electron = require 'electron' +binding = process.atomBinding 'crash_reporter' + class CrashReporter start: (options={}) -> - {@productName, companyName, submitUrl, autoSubmit, ignoreSystemCrashHandler, extra} = options + {@productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra} = options + + # Deprecated. + {deprecate} = electron + if options.submitUrl + submitURL ?= options.submitUrl + deprecate.warn 'submitUrl', 'submitURL' - electron = require 'electron' {app} = if process.type is 'browser' electron @@ -17,7 +24,7 @@ class CrashReporter @productName ?= app.getName() companyName ?= 'GitHub, Inc' - submitUrl ?= 'http://54.249.141.255:1127/post' + submitURL ?= 'http://54.249.141.255:1127/post' autoSubmit ?= true ignoreSystemCrashHandler ?= false extra ?= {} @@ -26,11 +33,11 @@ class CrashReporter extra._companyName ?= companyName extra._version ?= app.getVersion() - start = => binding.start @productName, companyName, submitUrl, autoSubmit, ignoreSystemCrashHandler, extra + start = => binding.start @productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra if process.platform is 'win32' args = [ - "--reporter-url=#{submitUrl}" + "--reporter-url=#{submitURL}" "--application-name=#{@productName}" "--v=1" ] diff --git a/atom/common/api/lib/native-image.coffee b/atom/common/api/lib/native-image.coffee index c3cbb60ef030..2bdfd494f44b 100644 --- a/atom/common/api/lib/native-image.coffee +++ b/atom/common/api/lib/native-image.coffee @@ -1 +1,7 @@ -module.exports = process.atomBinding 'native_image' +{deprecate} = require 'electron' +nativeImage = process.atomBinding 'native_image' + +# Deprecated. +deprecate.rename nativeImage, 'createFromDataUrl', 'createFromDataURL' + +module.exports = nativeImage diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 1d375ba0fc4e..1124cfba4bac 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -77,7 +77,7 @@ const char kZoomFactor[] = "zoomFactor"; const char kPreloadScript[] = "preload"; // Like --preload, but the passed argument is an URL. -const char kPreloadUrl[] = "preloadUrl"; +const char kPreloadURL[] = "preloadURL"; // Enable the node integration. const char kNodeIntegration[] = "nodeIntegration"; @@ -133,7 +133,7 @@ const char kAppUserModelId[] = "app-user-model-id"; // The command line switch versions of the options. const char kZoomFactor[] = "zoom-factor"; const char kPreloadScript[] = "preload"; -const char kPreloadUrl[] = "preload-url"; +const char kPreloadURL[] = "preload-url"; const char kNodeIntegration[] = "node-integration"; const char kGuestInstanceID[] = "guest-instance-id"; const char kExperimentalFeatures[] = "experimental-features"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 7f262fb0f721..cd52c97597c9 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -44,7 +44,7 @@ extern const char kWebPreferences[]; extern const char kDirectWrite[]; extern const char kZoomFactor[]; extern const char kPreloadScript[]; -extern const char kPreloadUrl[]; +extern const char kPreloadURL[]; extern const char kNodeIntegration[]; extern const char kGuestInstanceID[]; extern const char kExperimentalFeatures[]; @@ -73,7 +73,7 @@ extern const char kAppUserModelId[]; extern const char kZoomFactor[]; extern const char kPreloadScript[]; -extern const char kPreloadUrl[]; +extern const char kPreloadURL[]; extern const char kNodeIntegration[]; extern const char kGuestInstanceID[]; extern const char kExperimentalFeatures[]; diff --git a/atom/common/platform_util_win.cc b/atom/common/platform_util_win.cc index 87f45e5cb2d4..cca392952e65 100644 --- a/atom/common/platform_util_win.cc +++ b/atom/common/platform_util_win.cc @@ -307,8 +307,8 @@ bool OpenExternal(const GURL& url) { // "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in // ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6 // support URLS of 2083 chars in length, 2K is safe." - const size_t kMaxUrlLength = 2048; - if (escaped_url.length() > kMaxUrlLength) { + const size_t kMaxURLLength = 2048; + if (escaped_url.length() > kMaxURLLength) { NOTREACHED(); return false; } diff --git a/atom/renderer/api/atom_api_web_frame.cc b/atom/renderer/api/atom_api_web_frame.cc index 69613043043d..e9b2b03055e6 100644 --- a/atom/renderer/api/atom_api_web_frame.cc +++ b/atom/renderer/api/atom_api_web_frame.cc @@ -98,7 +98,7 @@ void WebFrame::RegisterURLSchemeAsSecure(const std::string& scheme) { blink::WebString::fromUTF8(scheme)); } -void WebFrame::RegisterURLSchemeAsBypassingCsp(const std::string& scheme) { +void WebFrame::RegisterURLSchemeAsBypassingCSP(const std::string& scheme) { // Register scheme to bypass pages's Content Security Policy. blink::WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy( blink::WebString::fromUTF8(scheme)); @@ -129,11 +129,11 @@ mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder( &WebFrame::RegisterElementResizeCallback) .SetMethod("attachGuest", &WebFrame::AttachGuest) .SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider) - .SetMethod("registerUrlSchemeAsSecure", + .SetMethod("registerURLSchemeAsSecure", &WebFrame::RegisterURLSchemeAsSecure) - .SetMethod("registerUrlSchemeAsBypassingCsp", - &WebFrame::RegisterURLSchemeAsBypassingCsp) - .SetMethod("registerUrlSchemeAsPrivileged", + .SetMethod("registerURLSchemeAsBypassingCSP", + &WebFrame::RegisterURLSchemeAsBypassingCSP) + .SetMethod("registerURLSchemeAsPrivileged", &WebFrame::RegisterURLSchemeAsPrivileged); } diff --git a/atom/renderer/api/atom_api_web_frame.h b/atom/renderer/api/atom_api_web_frame.h index a3dec6cb7689..95a5a82a313d 100644 --- a/atom/renderer/api/atom_api_web_frame.h +++ b/atom/renderer/api/atom_api_web_frame.h @@ -57,7 +57,7 @@ class WebFrame : public mate::Wrappable { v8::Local provider); void RegisterURLSchemeAsSecure(const std::string& scheme); - void RegisterURLSchemeAsBypassingCsp(const std::string& scheme); + void RegisterURLSchemeAsBypassingCSP(const std::string& scheme); void RegisterURLSchemeAsPrivileged(const std::string& scheme); // mate::Wrappable: diff --git a/atom/renderer/api/lib/web-frame.coffee b/atom/renderer/api/lib/web-frame.coffee index 6525730e86f1..53564c615ca4 100644 --- a/atom/renderer/api/lib/web-frame.coffee +++ b/atom/renderer/api/lib/web-frame.coffee @@ -1 +1,9 @@ -module.exports = process.atomBinding('web_frame').webFrame +{deprecate} = require 'electron' +{webFrame} = process.atomBinding 'web_frame' + +# Deprecated. +deprecate.rename webFrame, 'registerUrlSchemeAsSecure', 'registerURLSchemeAsSecure' +deprecate.rename webFrame, 'registerUrlSchemeAsBypassingCSP', 'registerURLSchemeAsBypassingCSP' +deprecate.rename webFrame, 'registerUrlSchemeAsPrivileged', 'registerURLSchemeAsPrivileged' + +module.exports = webFrame diff --git a/atom/renderer/lib/override.coffee b/atom/renderer/lib/override.coffee index d12952a1b831..a3a2f9ac62da 100644 --- a/atom/renderer/lib/override.coffee +++ b/atom/renderer/lib/override.coffee @@ -2,7 +2,7 @@ # Helper function to resolve relative url. a = window.top.document.createElement 'a' -resolveUrl = (url) -> +resolveURL = (url) -> a.href = url a.href @@ -55,7 +55,7 @@ window.open = (url, frameName='', features='') -> options.height ?= 600 # Resolve relative urls. - url = resolveUrl url + url = resolveURL url (options[name] = parseInt(options[name], 10) if options[name]?) for name in ints diff --git a/atom/renderer/lib/web-view/guest-view-internal.coffee b/atom/renderer/lib/web-view/guest-view-internal.coffee index a01a994b5bf9..61a93d8cb6e3 100644 --- a/atom/renderer/lib/web-view/guest-view-internal.coffee +++ b/atom/renderer/lib/web-view/guest-view-internal.coffee @@ -5,14 +5,14 @@ requestId = 0 WEB_VIEW_EVENTS = 'load-commit': ['url', 'isMainFrame'] 'did-finish-load': [] - 'did-fail-load': ['errorCode', 'errorDescription', 'validatedUrl'] + 'did-fail-load': ['errorCode', 'errorDescription', 'validatedURL'] 'did-frame-finish-load': ['isMainFrame'] 'did-start-loading': [] 'did-stop-loading': [] - 'did-get-response-details': ['status', 'newUrl', 'originalUrl', + 'did-get-response-details': ['status', 'newURL', 'originalURL', 'httpResponseCode', 'requestMethod', 'referrer', 'headers'] - 'did-get-redirect-request': ['oldUrl', 'newUrl', 'isMainFrame'] + 'did-get-redirect-request': ['oldURL', 'newURL', 'isMainFrame'] 'dom-ready': [] 'console-message': ['level', 'message', 'line', 'sourceId'] 'new-window': ['url', 'frameName', 'disposition', 'options'] diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index 48e57ea95aaf..7760b400ce17 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -6,7 +6,7 @@ webViewConstants = require './web-view-constants' # Helper function to resolve url set in attribute. a = document.createElement 'a' -resolveUrl = (url) -> +resolveURL = (url) -> a.href = url a.href @@ -116,7 +116,7 @@ class SrcAttribute extends WebViewAttribute getValue: -> if @webViewImpl.webviewNode.hasAttribute @name - resolveUrl @webViewImpl.webviewNode.getAttribute(@name) + resolveURL @webViewImpl.webviewNode.getAttribute(@name) else '' @@ -178,7 +178,7 @@ class SrcAttribute extends WebViewAttribute if useragent then opts.userAgent = useragent guestContents = remote.getGuestWebContents(@webViewImpl.guestInstanceId) - guestContents.loadUrl @getValue(), opts + guestContents.loadURL @getValue(), opts # Attribute specifies HTTP referrer. class HttpReferrerAttribute extends WebViewAttribute @@ -197,7 +197,7 @@ class PreloadAttribute extends WebViewAttribute getValue: -> return '' unless @webViewImpl.webviewNode.hasAttribute @name - preload = resolveUrl @webViewImpl.webviewNode.getAttribute(@name) + preload = resolveURL @webViewImpl.webviewNode.getAttribute(@name) protocol = preload.substr 0, 5 unless protocol is 'file:' console.error webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 204889de79e9..5e3f7d6bae56 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -1,4 +1,4 @@ -{webFrame, remote} = require 'electron' +{deprecate, webFrame, remote} = require 'electron' v8Util = process.atomBinding 'v8_util' guestViewInternal = require './guest-view-internal' @@ -252,49 +252,49 @@ registerWebViewElement = -> # Public-facing API methods. methods = [ - "getUrl" - "getTitle" - "isLoading" - "isWaitingForResponse" - "stop" - "reload" - "reloadIgnoringCache" - "canGoBack" - "canGoForward" - "canGoToOffset" - "clearHistory" - "goBack" - "goForward" - "goToIndex" - "goToOffset" - "isCrashed" - "setUserAgent" - "getUserAgent" - "executeJavaScript" - "insertCSS" - "openDevTools" - "closeDevTools" - "isDevToolsOpened" - "inspectElement" - "setAudioMuted" - "isAudioMuted" - "undo" - "redo" - "cut" - "copy" - "paste" - "pasteAndMatchStyle" - "delete" - "selectAll" - "unselect" - "replace" - "replaceMisspelling" - "send" - "getId" - "inspectServiceWorker" - "print" - "printToPDF" - "sendInputEvent" + 'getURL' + 'getTitle' + 'isLoading' + 'isWaitingForResponse' + 'stop' + 'reload' + 'reloadIgnoringCache' + 'canGoBack' + 'canGoForward' + 'canGoToOffset' + 'clearHistory' + 'goBack' + 'goForward' + 'goToIndex' + 'goToOffset' + 'isCrashed' + 'setUserAgent' + 'getUserAgent' + 'executeJavaScript' + 'insertCSS' + 'openDevTools' + 'closeDevTools' + 'isDevToolsOpened' + 'inspectElement' + 'setAudioMuted' + 'isAudioMuted' + 'undo' + 'redo' + 'cut' + 'copy' + 'paste' + 'pasteAndMatchStyle' + 'delete' + 'selectAll' + 'unselect' + 'replace' + 'replaceMisspelling' + 'send' + 'getId' + 'inspectServiceWorker' + 'print' + 'printToPDF' + 'sendInputEvent' ] # Forward proto.foo* method calls to WebViewImpl.foo*. @@ -304,6 +304,9 @@ registerWebViewElement = -> internal.webContents[m] args... proto[m] = createHandler m for m in methods + # Deprecated. + deprecate.rename proto, 'getUrl', 'getURL' + window.WebView = webFrame.registerEmbedderCustomElement 'webview', prototype: proto diff --git a/docs/api/auto-updater.md b/docs/api/auto-updater.md index eb0ea3752995..fa4f92cb936d 100644 --- a/docs/api/auto-updater.md +++ b/docs/api/auto-updater.md @@ -67,7 +67,7 @@ Returns: * `releaseNotes` String * `releaseName` String * `releaseDate` Date -* `updateUrl` String +* `updateURL` String Emitted when an update has been downloaded. @@ -77,7 +77,7 @@ On Windows only `releaseName` is available. The `autoUpdater` object has the following methods: -### `autoUpdater.setFeedUrl(url)` +### `autoUpdater.setFeedURL(url)` * `url` String @@ -86,7 +86,7 @@ once it is set. ### `autoUpdater.checkForUpdates()` -Asks the server whether there is an update. You must call `setFeedUrl` before +Asks the server whether there is an update. You must call `setFeedURL` before using this API. ### `autoUpdater.quitAndInstall()` diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 670c814c741d..3b293e99621c 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -11,7 +11,7 @@ win.on('closed', function() { win = null; }); -win.loadUrl('https://github.com'); +win.loadURL('https://github.com'); win.show(); ``` @@ -613,9 +613,9 @@ Same as `webContents.print([options])` Same as `webContents.printToPDF(options, callback)` -### `win.loadUrl(url[, options])` +### `win.loadURL(url[, options])` -Same as `webContents.loadUrl(url[, options])`. +Same as `webContents.loadURL(url[, options])`. ### `win.reload()` diff --git a/docs/api/crash-reporter.md b/docs/api/crash-reporter.md index 8127c9bc1c93..6c66a855f753 100644 --- a/docs/api/crash-reporter.md +++ b/docs/api/crash-reporter.md @@ -11,7 +11,7 @@ const crashReporter = require('electron').crashReporter; crashReporter.start({ productName: 'YourName', companyName: 'YourCompany', - submitUrl: 'https://your-domain.com/url-to-submit', + submitURL: 'https://your-domain.com/url-to-submit', autoSubmit: true }); ``` @@ -26,7 +26,7 @@ The `crash-reporter` module has the following methods: * `productName` String, default: Electron. * `companyName` String, default: GitHub, Inc. -* `submitUrl` String, default: http://54.249.141.255:1127/post. +* `submitURL` String, default: http://54.249.141.255:1127/post. * URL that crash reports will be sent to as POST. * `autoSubmit` Boolean, default: `true`. * Send the crash report without user interaction. @@ -57,7 +57,7 @@ ID. ## crash-reporter Payload -The crash reporter will send the following data to the `submitUrl` as `POST`: +The crash reporter will send the following data to the `submitURL` as `POST`: * `ver` String - The version of Electron. * `platform` String - e.g. 'win32'. diff --git a/docs/api/download-item.md b/docs/api/download-item.md index 53cd56cca9e5..756353b8ba3d 100644 --- a/docs/api/download-item.md +++ b/docs/api/download-item.md @@ -66,7 +66,7 @@ Resumes the download that has been paused. Cancels the download operation. -### `downloadItem.getUrl()` +### `downloadItem.getURL()` Returns a `String` represents the origin url where the item is downloaded from. diff --git a/docs/api/native-image.md b/docs/api/native-image.md index 74dc7a68fad9..c08788965a74 100644 --- a/docs/api/native-image.md +++ b/docs/api/native-image.md @@ -103,11 +103,11 @@ Creates a new `nativeImage` instance from a file located at `path`. Creates a new `nativeImage` instance from `buffer`. The default `scaleFactor` is 1.0. -### `nativeImage.createFromDataUrl(dataUrl)` +### `nativeImage.createFromDataURL(dataURL)` -* `dataUrl` String +* `dataURL` String -Creates a new `nativeImage` instance from `dataUrl`. +Creates a new `nativeImage` instance from `dataURL`. ## Instance Methods @@ -129,7 +129,7 @@ Returns a [Buffer][buffer] that contains the image's `PNG` encoded data. Returns a [Buffer][buffer] that contains the image's `JPEG` encoded data. -### `image.toDataUrl()` +### `image.toDataURL()` Returns the data URL of the image. diff --git a/docs/api/remote.md b/docs/api/remote.md index 6eaa206465aa..d6aca3ec2617 100644 --- a/docs/api/remote.md +++ b/docs/api/remote.md @@ -16,7 +16,7 @@ const remote = require('electron').remote; const BrowserWindow = remote.require('electron').BrowserWindow; var win = new BrowserWindow({ width: 800, height: 600 }); -win.loadUrl('https://github.com'); +win.loadURL('https://github.com'); ``` **Note:** for the reverse (access the renderer process from the main process), diff --git a/docs/api/session.md b/docs/api/session.md index 0fa72585b94e..c3a3c91eea93 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -8,7 +8,7 @@ instance of `BrowserWindow`. For example: const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({ width: 800, height: 600 }); -win.loadUrl("http://github.com"); +win.loadURL("http://github.com"); var session = win.webContents.session ``` @@ -28,7 +28,7 @@ Calling `event.preventDefault()` will cancel the download. ```javascript session.on('will-download', function(event, item, webContents) { event.preventDefault(); - require('request')(item.getUrl(), function(data) { + require('request')(item.getURL(), function(data) { require('fs').writeFileSync('/somewhere', data); }); }); @@ -47,7 +47,7 @@ const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({ width: 800, height: 600 }); -win.loadUrl('https://github.com'); +win.loadURL('https://github.com'); win.webContents.on('did-finish-load', function() { // Query all cookies. diff --git a/docs/api/synopsis.md b/docs/api/synopsis.md index f6c161b6963a..4cacf52cabd7 100644 --- a/docs/api/synopsis.md +++ b/docs/api/synopsis.md @@ -25,7 +25,7 @@ var window = null; app.on('ready', function() { window = new BrowserWindow({width: 800, height: 600}); - window.loadUrl('https://github.com'); + window.loadURL('https://github.com'); }); ``` diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index aff5752ab55f..917e0670590c 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -11,7 +11,7 @@ the [`BrowserWindow`](browser-window.md) object. An example of accessing the const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({width: 800, height: 1500}); -win.loadUrl("http://github.com"); +win.loadURL("http://github.com"); var webContents = win.webContents; ``` @@ -32,7 +32,7 @@ Returns: * `event` Event * `errorCode` Integer * `errorDescription` String -* `validatedUrl` String +* `validatedURL` String This event is like `did-finish-load` but emitted when the load failed or was cancelled, e.g. `window.stop()` is invoked. @@ -61,8 +61,8 @@ Returns: * `event` Event * `status` Boolean -* `newUrl` String -* `originalUrl` String +* `newURL` String +* `originalURL` String * `httpResponseCode` Integer * `requestMethod` String * `referrer` String @@ -76,8 +76,8 @@ Emitted when details regarding a requested resource are available. Returns: * `event` Event -* `oldUrl` String -* `newUrl` String +* `oldURL` String +* `newURL` String * `isMainFrame` Boolean * `httpResponseCode` Integer * `requestMethod` String @@ -99,7 +99,7 @@ Emitted when the document in the given frame is loaded. Returns: * `event` Event -* `favicons` Array - Array of Urls +* `favicons` Array - Array of URLs Emitted when page receives favicon urls. @@ -133,7 +133,7 @@ Emitted when a user or the page wants to start navigation. It can happen when th `window.location` object is changed or a user clicks a link in the page. This event will not emit when the navigation is started programmatically with -APIs like `webContents.loadUrl` and `webContents.back`. +APIs like `webContents.loadURL` and `webContents.back`. Calling `event.preventDefault()` will prevent the navigation. @@ -198,7 +198,7 @@ Returns the `session` object used by this webContents. See [session documentation](session.md) for this object's methods. -### `webContents.loadUrl(url[, options])` +### `webContents.loadURL(url[, options])` * `url` URL * `options` Object (optional), properties: @@ -209,15 +209,15 @@ See [session documentation](session.md) for this object's methods. Loads the `url` in the window, the `url` must contain the protocol prefix, e.g. the `http://` or `file://`. -### `webContents.getUrl()` +### `webContents.getURL()` Returns URL of the current web page. ```javascript var win = new BrowserWindow({width: 800, height: 600}); -win.loadUrl("http://github.com"); +win.loadURL("http://github.com"); -var currentUrl = win.webContents.getUrl(); +var currentURL = win.webContents.getURL(); ``` ### `webContents.getTitle()` @@ -447,7 +447,7 @@ const BrowserWindow = require('electron').BrowserWindow; const fs = require('fs'); var win = new BrowserWindow({width: 800, height: 600}); -win.loadUrl("http://github.com"); +win.loadURL("http://github.com"); win.webContents.on("did-finish-load", function() { // Use default printing options @@ -524,7 +524,7 @@ An example of sending messages from the main process to the renderer process: var window = null; app.on('ready', function() { window = new BrowserWindow({width: 800, height: 600}); - window.loadUrl('file://' + __dirname + '/index.html'); + window.loadURL('file://' + __dirname + '/index.html'); window.webContents.on('did-finish-load', function() { window.webContents.send('ping', 'whoooooooh!'); }); @@ -660,7 +660,7 @@ when the DevTools has been closed. Returns true if the process of saving page has been initiated successfully. ```javascript -win.loadUrl('https://github.com'); +win.loadURL('https://github.com'); win.webContents.on('did-finish-load', function() { win.webContents.savePage('/tmp/test.html', 'HTMLComplete', function(error) { diff --git a/docs/api/web-frame.md b/docs/api/web-frame.md index c9cfb48f3437..38c5e30db43f 100644 --- a/docs/api/web-frame.md +++ b/docs/api/web-frame.md @@ -66,7 +66,7 @@ webFrame.setSpellCheckProvider("en-US", true, { }); ``` -### `webFrame.registerUrlSchemeAsSecure(scheme)` +### `webFrame.registerURLSchemeAsSecure(scheme)` * `scheme` String @@ -76,14 +76,14 @@ Secure schemes do not trigger mixed content warnings. For example, `https` and `data` are secure schemes because they cannot be corrupted by active network attackers. -### `webFrame.registerUrlSchemeAsBypassingCsp(scheme)` +### `webFrame.registerURLSchemeAsBypassingCSP(scheme)` * `scheme` String Resources will be loaded from this `scheme` regardless of the current page's Content Security Policy. -### `webFrame.registerUrlSchemeAsPrivileged(scheme)` +### `webFrame.registerURLSchemeAsPrivileged(scheme)` * `scheme` String diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index a12ec447138f..25b0e399465d 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -170,7 +170,7 @@ webview.addEventListener("dom-ready", function() { }); ``` -### `.getUrl()` +### `.getURL()` Returns URL of guest page. @@ -402,7 +402,7 @@ Returns: * `errorCode` Integer * `errorDescription` String -* `validatedUrl` String +* `validatedURL` String This event is like `did-finish-load`, but fired when the load failed or was cancelled, e.g. `window.stop()` is invoked. @@ -428,8 +428,8 @@ Corresponds to the points in time when the spinner of the tab stops spinning. Returns: * `status` Boolean -* `newUrl` String -* `originalUrl` String +* `newURL` String +* `originalURL` String * `httpResponseCode` Integer * `requestMethod` String * `referrer` String @@ -442,8 +442,8 @@ Fired when details regarding a requested resource is available. Returns: -* `oldUrl` String -* `newUrl` String +* `oldURL` String +* `newURL` String * `isMainFrame` Boolean Fired when a redirect was received while requesting a resource. @@ -466,7 +466,7 @@ url. Returns: -* `favicons` Array - Array of Urls. +* `favicons` Array - Array of URLs. Fired when page receives favicon urls. diff --git a/docs/tutorial/application-packaging.md b/docs/tutorial/application-packaging.md index 7c1ea773e2ff..45973e49eaa9 100644 --- a/docs/tutorial/application-packaging.md +++ b/docs/tutorial/application-packaging.md @@ -73,7 +73,7 @@ You can also display a web page in an `asar` archive with `BrowserWindow`: ```javascript const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({width: 800, height: 600}); -win.loadUrl('file:///path/to/example.asar/static/index.html'); +win.loadURL('file:///path/to/example.asar/static/index.html'); ``` ### Web API diff --git a/docs/tutorial/online-offline-events.md b/docs/tutorial/online-offline-events.md index 6e031282b55a..d143118e0158 100644 --- a/docs/tutorial/online-offline-events.md +++ b/docs/tutorial/online-offline-events.md @@ -13,7 +13,7 @@ const BrowserWindow = electron.BrowserWindow; var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ``` @@ -54,7 +54,7 @@ const BrowserWindow = electron.BrowserWindow; var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ipcMain.on('online-status-changed', function(event, status) { diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index 7c55340f75e2..4c61413436dd 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -105,7 +105,7 @@ app.on('ready', function() { mainWindow = new BrowserWindow({width: 800, height: 600}); // and load the index.html of the app. - mainWindow.loadUrl('file://' + __dirname + '/index.html'); + mainWindow.loadURL('file://' + __dirname + '/index.html'); // Open the DevTools. mainWindow.webContents.openDevTools(); diff --git a/docs/tutorial/using-pepper-flash-plugin.md b/docs/tutorial/using-pepper-flash-plugin.md index 4cbbb519f4c2..a9918b220ac0 100644 --- a/docs/tutorial/using-pepper-flash-plugin.md +++ b/docs/tutorial/using-pepper-flash-plugin.md @@ -36,7 +36,7 @@ app.on('ready', function() { 'plugins': true } }); - mainWindow.loadUrl('file://' + __dirname + '/index.html'); + mainWindow.loadURL('file://' + __dirname + '/index.html'); // Something else }); ``` diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 055cd8ed3468..00437ae412ba 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -31,14 +31,14 @@ describe 'browser-window module', -> fs.unlinkSync(test) assert.equal String(content), 'unload' done() - w.loadUrl 'file://' + path.join(fixtures, 'api', 'unload.html') + w.loadURL 'file://' + path.join(fixtures, 'api', 'unload.html') it 'should emit beforeunload handler', (done) -> w.on 'onbeforeunload', -> done() w.webContents.on 'did-finish-load', -> w.close() - w.loadUrl 'file://' + path.join(fixtures, 'api', 'beforeunload-false.html') + w.loadURL 'file://' + path.join(fixtures, 'api', 'beforeunload-false.html') describe 'window.close()', -> it 'should emit unload handler', (done) -> @@ -48,23 +48,23 @@ describe 'browser-window module', -> fs.unlinkSync(test) assert.equal String(content), 'close' done() - w.loadUrl 'file://' + path.join(fixtures, 'api', 'close.html') + w.loadURL 'file://' + path.join(fixtures, 'api', 'close.html') it 'should emit beforeunload handler', (done) -> w.on 'onbeforeunload', -> done() - w.loadUrl 'file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html') + w.loadURL 'file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html') - describe 'BrowserWindow.loadUrl(url)', -> + describe 'BrowserWindow.loadURL(url)', -> it 'should emit did-start-loading event', (done) -> w.webContents.on 'did-start-loading', -> done() - w.loadUrl 'about:blank' + w.loadURL 'about:blank' it 'should emit did-fail-load event', (done) -> w.webContents.on 'did-fail-load', -> done() - w.loadUrl 'file://a.txt' + w.loadURL 'file://a.txt' describe 'BrowserWindow.show()', -> it 'should focus on window', -> @@ -214,7 +214,7 @@ describe 'browser-window module', -> show: false webPreferences: preload: preload - w.loadUrl 'file://' + path.join(fixtures, 'api', 'preload.html') + w.loadURL 'file://' + path.join(fixtures, 'api', 'preload.html') describe '"node-integration" option', -> it 'disables node integration when specified to false', (done) -> @@ -228,28 +228,28 @@ describe 'browser-window module', -> webPreferences: preload: preload nodeIntegration: false - w.loadUrl 'file://' + path.join(fixtures, 'api', 'blank.html') + w.loadURL 'file://' + path.join(fixtures, 'api', 'blank.html') describe 'beforeunload handler', -> it 'returning true would not prevent close', (done) -> w.on 'closed', -> done() - 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', (done) -> w.on 'closed', -> done() - 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', (done) -> w.on 'onbeforeunload', -> done() - w.loadUrl 'file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html') + w.loadURL 'file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html') it 'returning empty string would prevent close', (done) -> w.on 'onbeforeunload', -> done() - 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', -> return if isCI and process.platform is 'darwin' @@ -259,7 +259,7 @@ describe 'browser-window module', -> assert.equal url, 'http://host/' assert.equal frameName, 'host' done() - w.loadUrl "file://#{fixtures}/pages/window-open.html" + w.loadURL "file://#{fixtures}/pages/window-open.html" it 'emits when link with target is called', (done) -> w.webContents.once 'new-window', (e, url, frameName) -> @@ -267,7 +267,7 @@ describe 'browser-window module', -> assert.equal url, 'http://host/' assert.equal frameName, 'target' done() - w.loadUrl "file://#{fixtures}/pages/target-name.html" + w.loadURL "file://#{fixtures}/pages/target-name.html" describe 'maximize event', -> return if isCI @@ -296,7 +296,7 @@ describe 'browser-window module', -> xdescribe 'beginFrameSubscription method', -> it 'subscribes frame updates', (done) -> - w.loadUrl "file://#{fixtures}/api/blank.html" + w.loadURL "file://#{fixtures}/api/blank.html" w.webContents.beginFrameSubscription (data) -> assert.notEqual data.length, 0 w.webContents.endFrameSubscription() @@ -321,4 +321,4 @@ describe 'browser-window module', -> fs.rmdirSync savePageDir done() - w.loadUrl "file://#{fixtures}/pages/save_page/index.html" + w.loadURL "file://#{fixtures}/pages/save_page/index.html" diff --git a/spec/api-clipboard-spec.coffee b/spec/api-clipboard-spec.coffee index b02eb855be09..19da3fc75f1b 100644 --- a/spec/api-clipboard-spec.coffee +++ b/spec/api-clipboard-spec.coffee @@ -11,7 +11,7 @@ describe 'clipboard module', -> p = path.join fixtures, 'assets', 'logo.png' i = nativeImage.createFromPath p clipboard.writeImage p - assert.equal clipboard.readImage().toDataUrl(), i.toDataUrl() + assert.equal clipboard.readImage().toDataURL(), i.toDataURL() describe 'clipboard.readText()', -> it 'returns unicode string correctly', -> @@ -49,4 +49,4 @@ describe 'clipboard module', -> clipboard.write {text: "test", html: 'Hi', image: p} assert.equal clipboard.readText(), text assert.equal clipboard.readHtml(), markup - assert.equal clipboard.readImage().toDataUrl(), i.toDataUrl() + assert.equal clipboard.readImage().toDataURL(), i.toDataURL() diff --git a/spec/api-crash-reporter-spec.coffee b/spec/api-crash-reporter-spec.coffee index 281a1a77ae48..676dbf9d6929 100644 --- a/spec/api-crash-reporter-spec.coffee +++ b/spec/api-crash-reporter-spec.coffee @@ -55,5 +55,5 @@ describe 'crash-reporter module', -> pathname: path.join fixtures, 'api', 'crash.html' search: "?port=#{port}" if process.platform is 'darwin' - crashReporter.start {'submitUrl': 'http://127.0.0.1:' + port} - w.loadUrl url + crashReporter.start {'submitURL': 'http://127.0.0.1:' + port} + w.loadURL url diff --git a/spec/api-ipc-spec.coffee b/spec/api-ipc-spec.coffee index 1e6ee8f8447f..a8d2a65cdef7 100644 --- a/spec/api-ipc-spec.coffee +++ b/spec/api-ipc-spec.coffee @@ -86,7 +86,7 @@ describe 'ipc module', -> event.returnValue = null w.destroy() done() - w.loadUrl 'file://' + path.join(fixtures, 'api', 'send-sync-message.html') + w.loadURL 'file://' + path.join(fixtures, 'api', 'send-sync-message.html') describe 'remote listeners', -> it 'can be added and removed correctly', -> diff --git a/spec/api-session-spec.coffee b/spec/api-session-spec.coffee index f544dff4c34e..bf91bdd6fc77 100644 --- a/spec/api-session-spec.coffee +++ b/spec/api-session-spec.coffee @@ -23,7 +23,7 @@ describe 'session module', -> server.listen 0, '127.0.0.1', -> {port} = server.address() - w.loadUrl "#{url}:#{port}" + w.loadURL "#{url}:#{port}" w.webContents.on 'did-finish-load', -> w.webContents.session.cookies.get {url: url}, (error, list) -> return done(error) if error @@ -64,7 +64,7 @@ describe 'session module', -> ipcMain.removeAllListeners 'count' assert not count done() - w.loadUrl 'file://' + path.join(fixtures, 'api', 'localstorage.html') + w.loadURL 'file://' + path.join(fixtures, 'api', 'localstorage.html') w.webContents.on 'did-finish-load', -> options = origin: "file://", @@ -91,7 +91,7 @@ describe 'session module', -> downloadServer.listen 0, '127.0.0.1', -> {port} = downloadServer.address() ipcRenderer.sendSync 'set-download-option', false - w.loadUrl "#{url}:#{port}" + w.loadURL "#{url}:#{port}" ipcRenderer.once 'download-done', (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) -> assert.equal state, 'completed' assert.equal filename, 'mock.pdf' @@ -108,7 +108,7 @@ describe 'session module', -> downloadServer.listen 0, '127.0.0.1', -> {port} = downloadServer.address() ipcRenderer.sendSync 'set-download-option', true - w.loadUrl "#{url}:#{port}/" + w.loadURL "#{url}:#{port}/" ipcRenderer.once 'download-done', (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) -> assert.equal state, 'cancelled' assert.equal filename, 'mock.pdf' diff --git a/spec/asar-spec.coffee b/spec/asar-spec.coffee index f84fb0599156..ad480a582525 100644 --- a/spec/asar-spec.coffee +++ b/spec/asar-spec.coffee @@ -453,7 +453,7 @@ describe 'asar package', -> ipcMain.once 'dirname', (event, dirname) -> assert.equal dirname, path.dirname(p) done() - w.loadUrl u + w.loadURL u it 'loads script tag in html', (done) -> after -> @@ -463,7 +463,7 @@ describe 'asar package', -> w = new BrowserWindow(show: false, width: 400, height: 400) p = path.resolve fixtures, 'asar', 'script.asar', 'index.html' u = url.format protocol: 'file', slashed: true, pathname: p - w.loadUrl u + w.loadURL u ipcMain.once 'ping', (event, message) -> assert.equal message, 'pong' done() diff --git a/spec/chromium-spec.coffee b/spec/chromium-spec.coffee index ebd7b36dc1a3..435f7bbbe3e5 100644 --- a/spec/chromium-spec.coffee +++ b/spec/chromium-spec.coffee @@ -43,7 +43,7 @@ describe 'chromium feature', -> w.webContents.on 'ipc-message', (event, args) -> assert.deepEqual args, ['hidden', true] done() - w.loadUrl url + w.loadURL url describe 'navigator.webkitGetUserMedia', -> it 'calls its callbacks', (done) -> @@ -96,7 +96,7 @@ describe 'chromium feature', -> w.webContents.on 'ipc-message', (event, args) -> assert.deepEqual args, ['opener', null] done() - w.loadUrl url + w.loadURL url it 'is not null for window opened by window.open', (done) -> listener = (event) -> diff --git a/spec/fixtures/api/crash.html b/spec/fixtures/api/crash.html index 30494849373d..c1fb621426af 100644 --- a/spec/fixtures/api/crash.html +++ b/spec/fixtures/api/crash.html @@ -6,7 +6,7 @@ var crashReporter = require('electron').crashReporter; crashReporter.start({ productName: 'Zombies', companyName: 'Umbrella Corporation', - submitUrl: 'http://127.0.0.1:' + port, + submitURL: 'http://127.0.0.1:' + port, autoSubmit: true, ignoreSystemCrashHandler: true, extra: { diff --git a/spec/static/main.js b/spec/static/main.js index e071474f9a94..be3690cd9e7d 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -67,7 +67,7 @@ app.on('ready', function() { javascript: true // Test whether web-preferences crashes. }, }); - window.loadUrl('file://' + __dirname + '/index.html'); + window.loadURL('file://' + __dirname + '/index.html'); window.on('unresponsive', function() { var chosen = dialog.showMessageBox(window, { type: 'warning', @@ -88,7 +88,7 @@ app.on('ready', function() { item.on('done', function(e, state) { window.webContents.send('download-done', state, - item.getUrl(), + item.getURL(), item.getMimeType(), item.getReceivedBytes(), item.getTotalBytes(), From e8ffd24e4e12d33c739dc4c0953efe288699fd60 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 16:41:33 +0800 Subject: [PATCH 493/738] Rename the "clicked" event to "click" in Tray --- atom/browser/api/atom_api_tray.cc | 8 ++++---- atom/browser/api/lib/browser-window.coffee | 2 +- atom/browser/api/lib/tray.coffee | 14 ++++++++++---- atom/common/api/lib/deprecate.coffee | 7 +++++-- docs/api/tray.md | 12 ++++++------ 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index 0c24240f223c..d3c5931ad6da 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -44,21 +44,21 @@ mate::Wrappable* Tray::New(v8::Isolate* isolate, const gfx::Image& image) { void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) { v8::Locker locker(isolate()); v8::HandleScope handle_scope(isolate()); - EmitCustomEvent("clicked", + EmitCustomEvent("click", ModifiersToObject(isolate(), modifiers), bounds); } void Tray::OnDoubleClicked(const gfx::Rect& bounds, int modifiers) { v8::Locker locker(isolate()); v8::HandleScope handle_scope(isolate()); - EmitCustomEvent("double-clicked", + EmitCustomEvent("double-click", ModifiersToObject(isolate(), modifiers), bounds); } void Tray::OnRightClicked(const gfx::Rect& bounds, int modifiers) { v8::Locker locker(isolate()); v8::HandleScope handle_scope(isolate()); - EmitCustomEvent("right-clicked", + EmitCustomEvent("right-click", ModifiersToObject(isolate(), modifiers), bounds); } @@ -67,7 +67,7 @@ void Tray::OnBalloonShow() { } void Tray::OnBalloonClicked() { - Emit("balloon-clicked"); + Emit("balloon-click"); } void Tray::OnBalloonClosed() { diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 9947bc1a50ba..99921372f14c 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -1,7 +1,7 @@ {app, ipcMain, deprecate} = require 'electron' {EventEmitter} = require 'events' -BrowserWindow = process.atomBinding('window').BrowserWindow +{BrowserWindow} = process.atomBinding 'window' BrowserWindow::__proto__ = EventEmitter.prototype BrowserWindow::_init = -> diff --git a/atom/browser/api/lib/tray.coffee b/atom/browser/api/lib/tray.coffee index 41cfc96d3f56..db26ab5b7ed1 100644 --- a/atom/browser/api/lib/tray.coffee +++ b/atom/browser/api/lib/tray.coffee @@ -1,13 +1,19 @@ +{deprecate} = require 'electron' {EventEmitter} = require 'events' -{Tray} = process.atomBinding 'tray' +{Tray} = process.atomBinding 'tray' Tray::__proto__ = EventEmitter.prototype +Tray::_init = -> + # Deprecated. + deprecate.rename this, 'popContextMenu', 'popUpContextMenu' + deprecate.event this, 'clicked', 'click' + deprecate.event this, 'double-clicked', 'double-click' + deprecate.event this, 'right-clicked', 'right-click' + deprecate.event this, 'balloon-clicked', 'balloon-click' + Tray::setContextMenu = (menu) -> @_setContextMenu menu @menu = menu # Keep a strong reference of menu. -# Keep compatibility with old APIs. -Tray::popContextMenu = Tray::popUpContextMenu - module.exports = Tray diff --git a/atom/common/api/lib/deprecate.coffee b/atom/common/api/lib/deprecate.coffee index 070a9feb6aab..1daf5e4714fd 100644 --- a/atom/common/api/lib/deprecate.coffee +++ b/atom/common/api/lib/deprecate.coffee @@ -42,12 +42,15 @@ deprecate.property = (object, property, method) -> # Deprecate an event. deprecate.event = (emitter, oldName, newName, fn) -> warned = false - emitter.on newName, -> + emitter.on newName, (args...) -> if @listenerCount(oldName) > 0 # there is listeners for old API. unless warned or process.noDeprecation warned = true deprecate.warn "'#{oldName}' event", "'#{newName}' event" - fn.apply this, arguments + if fn? + fn.apply this, arguments + else + @emit oldName, args... # Print deprecate warning. deprecate.warn = (oldName, newName) -> diff --git a/docs/api/tray.md b/docs/api/tray.md index ff4310308a86..47936ab15e60 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -31,10 +31,10 @@ __Platform limitations:__ * On Linux distributions that only have app indicator support, you have to 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 `clicked` event is ignored. +* When app indicator is used on Linux, the `click` event is ignored. If you want to keep exact same behaviors on all platforms, you should not -rely on the `clicked` event and always attach a context menu to the tray icon. +rely on the `click` event and always attach a context menu to the tray icon. ## Class: Tray @@ -53,7 +53,7 @@ The `Tray` module emits the following events: **Note:** Some events are only available on specific operating systems and are labeled as such. -### Event: 'clicked' +### Event: 'click' * `event` Event * `altKey` Boolean @@ -70,7 +70,7 @@ Emitted when the tray icon is clicked. __Note:__ The `bounds` payload is only implemented on OS X and Windows. -### Event: 'right-clicked' _OS X_ _Windows_ +### Event: 'right-click' _OS X_ _Windows_ * `event` Event * `altKey` Boolean @@ -85,7 +85,7 @@ __Note:__ The `bounds` payload is only implemented on OS X and Windows. Emitted when the tray icon is right clicked. -### Event: 'double-clicked' _OS X_ _Windows_ +### Event: 'double-click' _OS X_ _Windows_ * `event` Event * `altKey` Boolean @@ -104,7 +104,7 @@ Emitted when the tray icon is double clicked. Emitted when the tray balloon shows. -### Event: 'balloon-clicked' _Windows_ +### Event: 'balloon-click' _Windows_ Emitted when the tray balloon is clicked. From e76a7f7b7d662ebcd7d6a441e1dfc39118638775 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 21:52:05 +0800 Subject: [PATCH 494/738] Fix typo, tray => Tray --- atom/browser/api/lib/exports/electron.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/api/lib/exports/electron.coffee b/atom/browser/api/lib/exports/electron.coffee index 6f70e6b38b36..768224d95796 100644 --- a/atom/browser/api/lib/exports/electron.coffee +++ b/atom/browser/api/lib/exports/electron.coffee @@ -45,7 +45,7 @@ Object.defineProperties module.exports, screen: enumerable: true get: -> require '../screen' - tray: + Tray: enumerable: true get: -> require '../tray' # The internal modules, invisible unless you know their names. From 9bf0a8647e86c10df4b21bfdca4168ca1c89235a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 21:52:27 +0800 Subject: [PATCH 495/738] Make it easier to use remote --- atom/renderer/api/lib/remote.coffee | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index 09e7dcdcb574..a38d6ec0bf42 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -134,6 +134,19 @@ ipcRenderer.on 'ATOM_RENDERER_CALLBACK', (event, id, args) -> ipcRenderer.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) -> callbacksRegistry.remove id +# List all built-in modules in browser process. +# NB(zcbenz): We should probably send an sync message to browser process to get +# them, but that would slow down the startup speed. +browserModules = + ['app', 'autoUpdater', 'BrowserWindow', 'contentTracing', 'dialog', + 'globalShortcut', 'ipcMain', 'Menu', 'MenuItem', 'powerMonitor', + 'powerSaveBlocker', 'protocol', 'Tray', 'clipboard', 'crashReporter', + 'nativeImage', 'screen', 'shell'] +# And add a helper receiver for each one. +for name in browserModules + do (name) -> + Object.defineProperty exports, name, get: -> exports.getBuiltin name + # 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) From 099278855c3067521a4c5f5988379f38ca4a6405 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 21:54:56 +0800 Subject: [PATCH 496/738] Simplify how remote.require('electron') is optimized --- atom/browser/api/lib/exports/electron.coffee | 3 --- atom/browser/lib/rpc-server.coffee | 6 ------ atom/renderer/api/lib/remote.coffee | 12 +++--------- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/atom/browser/api/lib/exports/electron.coffee b/atom/browser/api/lib/exports/electron.coffee index 768224d95796..f0c3b87c987b 100644 --- a/atom/browser/api/lib/exports/electron.coffee +++ b/atom/browser/api/lib/exports/electron.coffee @@ -1,9 +1,6 @@ # Import common modules. module.exports = require '../../../../common/api/lib/exports/electron' -v8Util = process.atomBinding 'v8_util' -v8Util.setHiddenValue module.exports, 'electronModule', true - Object.defineProperties module.exports, # Browser side modules, please sort with alphabet order. app: diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 5c67026debf2..df6d4f1f94ec 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -18,10 +18,6 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta.type = 'date' if value instanceof Date meta.type = 'promise' if value?.constructor.name is 'Promise' - # require('electron'). - if meta.type is 'object' and v8Util.getHiddenValue value, 'electronModule' - meta.type = 'electronModule' - # Treat simple objects as value. if optimizeSimpleObject and meta.type is 'object' and v8Util.getHiddenValue value, 'simple' meta.type = 'value' @@ -49,8 +45,6 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) -> meta.members = plainObjectToMeta value else if meta.type is 'date' meta.value = value.getTime() - else if meta.type is 'electronModule' - meta.members = (name for name of value) else meta.type = 'value' meta.value = value diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index a38d6ec0bf42..e177ea4bb6b4 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -49,15 +49,6 @@ metaToValue = (meta) -> when 'date' then new Date(meta.value) when 'exception' throw new Error("#{meta.message}\n#{meta.stack}") - when 'electronModule' - # require('electron'). - ret = {} - for member in meta.members - do (member) -> - Object.defineProperty ret, member, - enumerable: true - get: -> exports.getBuiltin member - ret else if meta.type is 'function' # A shadow class to represent the remote function object. @@ -157,6 +148,9 @@ exports.require = (module) -> meta = ipcRenderer.sendSync 'ATOM_BROWSER_REQUIRE', module moduleCache[module] = metaToValue meta +# Optimize require('electron'). +moduleCache.electron = exports + # Alias to remote.require('electron').xxx. builtinCache = {} exports.getBuiltin = (module) -> From b925ac00566b29b2410bf9f05a556a667db944f0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 22:15:16 +0800 Subject: [PATCH 497/738] Send sync message to get list of modules --- atom/browser/lib/rpc-server.coffee | 3 +++ atom/renderer/api/lib/remote.coffee | 8 +------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index df6d4f1f94ec..6cbc5ffc1fd5 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -206,3 +206,6 @@ ipcMain.on 'ATOM_BROWSER_GUEST_WEB_CONTENTS', (event, guestInstanceId) -> event.returnValue = valueToMeta event.sender, guestViewManager.getGuest(guestInstanceId) catch e event.returnValue = exceptionToMeta e + +ipcMain.on 'ATOM_BROWSER_LIST_MODULES', (event) -> + event.returnValue = (name for name of electron) diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index e177ea4bb6b4..48cdd937fb07 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -126,13 +126,7 @@ ipcRenderer.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) -> callbacksRegistry.remove id # List all built-in modules in browser process. -# NB(zcbenz): We should probably send an sync message to browser process to get -# them, but that would slow down the startup speed. -browserModules = - ['app', 'autoUpdater', 'BrowserWindow', 'contentTracing', 'dialog', - 'globalShortcut', 'ipcMain', 'Menu', 'MenuItem', 'powerMonitor', - 'powerSaveBlocker', 'protocol', 'Tray', 'clipboard', 'crashReporter', - 'nativeImage', 'screen', 'shell'] +browserModules = ipcRenderer.sendSync 'ATOM_BROWSER_LIST_MODULES' # And add a helper receiver for each one. for name in browserModules do (name) -> From 94e24abb998d73545b4a2eedf3872b5e13763d0f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 22:22:25 +0800 Subject: [PATCH 498/738] Use the new style remote module in Electron --- atom/common/api/lib/clipboard.coffee | 3 +-- atom/common/api/lib/crash-reporter.coffee | 6 +----- atom/renderer/api/lib/screen.coffee | 2 +- atom/renderer/lib/inspector.coffee | 4 ++-- atom/renderer/lib/override.coffee | 6 ++---- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/atom/common/api/lib/clipboard.coffee b/atom/common/api/lib/clipboard.coffee index 0ea97d86ba81..a3a6d555fe5c 100644 --- a/atom/common/api/lib/clipboard.coffee +++ b/atom/common/api/lib/clipboard.coffee @@ -1,6 +1,5 @@ if process.platform is 'linux' and process.type is 'renderer' - {remote} = require 'electron' # On Linux we could not access clipboard in renderer process. - module.exports = remote.getBuiltin 'clipboard' + module.exports = require('electron').remote.clipboard else module.exports = process.atomBinding 'clipboard' diff --git a/atom/common/api/lib/crash-reporter.coffee b/atom/common/api/lib/crash-reporter.coffee index 0713da99daef..bd98ae2a4277 100644 --- a/atom/common/api/lib/crash-reporter.coffee +++ b/atom/common/api/lib/crash-reporter.coffee @@ -16,11 +16,7 @@ class CrashReporter submitURL ?= options.submitUrl deprecate.warn 'submitUrl', 'submitURL' - {app} = - if process.type is 'browser' - electron - else - electron.remote.require 'electron' + {app} = if process.type is 'browser' then electron else electron.remote @productName ?= app.getName() companyName ?= 'GitHub, Inc' diff --git a/atom/renderer/api/lib/screen.coffee b/atom/renderer/api/lib/screen.coffee index b70aa55b5708..9eecd49dc5bf 100644 --- a/atom/renderer/api/lib/screen.coffee +++ b/atom/renderer/api/lib/screen.coffee @@ -1 +1 @@ -module.exports = require('electron').remote.require('electron').screen +module.exports = require('electron').remote.screen diff --git a/atom/renderer/lib/inspector.coffee b/atom/renderer/lib/inspector.coffee index 34c6876fc274..d5ddfd72e486 100644 --- a/atom/renderer/lib/inspector.coffee +++ b/atom/renderer/lib/inspector.coffee @@ -33,7 +33,7 @@ convertToMenuTemplate = (items) -> createMenu = (x, y, items, document) -> {remote} = require 'electron' - {Menu} = remote.require 'electron' + {Menu} = remote menu = Menu.buildFromTemplate convertToMenuTemplate(items) # The menu is expected to show asynchronously. @@ -43,7 +43,7 @@ createMenu = (x, y, items, document) -> showFileChooserDialog = (callback) -> {remote} = require 'electron' - {dialog} = remote.require 'electron' + {dialog} = remote files = dialog.showOpenDialog {} callback pathToHtml5FileObject files[0] if files? diff --git a/atom/renderer/lib/override.coffee b/atom/renderer/lib/override.coffee index a3a2f9ac62da..0b60ce0d6686 100644 --- a/atom/renderer/lib/override.coffee +++ b/atom/renderer/lib/override.coffee @@ -67,19 +67,17 @@ window.open = (url, frameName='', features='') -> # Use the dialog API to implement alert(). window.alert = (message, title='') -> - dialog = remote.require 'dialog' buttons = ['OK'] message = message.toString() - dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons} + remote.dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons} # Alert should always return undefined. return # And the confirm(). window.confirm = (message, title='') -> - dialog = remote.require 'dialog' buttons = ['OK', 'Cancel'] cancelId = 1 - not dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons, cancelId} + not remote.dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons, cancelId} # But we do not support prompt(). window.prompt = -> From 5cacf79bc5ceb82a793b2cc3916f0a8ee4fc14ae Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 13 Nov 2015 22:34:00 +0800 Subject: [PATCH 499/738] docs: Document the new style of remote module --- docs/api/menu.md | 4 ++-- docs/api/remote.md | 11 ++++++++++- docs/api/synopsis.md | 2 +- docs/tutorial/devtools-extension.md | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/docs/api/menu.md b/docs/api/menu.md index c947f36d4790..1d819682160b 100644 --- a/docs/api/menu.md +++ b/docs/api/menu.md @@ -17,8 +17,8 @@ the user right clicks the page: diff --git a/docs/tutorial/devtools-extension.md b/docs/tutorial/devtools-extension.md index 258fb41947ff..7c7ea7d64a24 100644 --- a/docs/tutorial/devtools-extension.md +++ b/docs/tutorial/devtools-extension.md @@ -24,7 +24,7 @@ Then you can load the extension in Electron by opening DevTools in any window, and running the following code in the DevTools console: ```javascript -const BrowserWindow = require('electron').remote.require('electron').BrowserWindow; +const BrowserWindow = require('electron').remote.BrowserWindow; BrowserWindow.addDevToolsExtension('/some-directory/react-devtools/shells/chrome'); ``` From 2a7f874373c44d1606cbabe2c921763732fca87c Mon Sep 17 00:00:00 2001 From: Robo Date: Sat, 14 Nov 2015 02:25:23 +0530 Subject: [PATCH 500/738] browser: fix reloadignoringcache api --- atom/browser/api/atom_api_web_contents.cc | 5 ----- atom/browser/api/lib/navigation-controller.coffee | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 601a4ba63f13..1c3334e93669 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -658,10 +658,6 @@ void WebContents::Stop() { web_contents()->Stop(); } -void WebContents::ReloadIgnoringCache() { - web_contents()->GetController().ReloadIgnoringCache(false); -} - void WebContents::GoBack() { atom::AtomBrowserClient::SuppressRendererProcessRestartForOnce(); web_contents()->GetController().GoBack(); @@ -1009,7 +1005,6 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("isLoading", &WebContents::IsLoading) .SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse) .SetMethod("_stop", &WebContents::Stop) - .SetMethod("_reloadIgnoringCache", &WebContents::ReloadIgnoringCache) .SetMethod("_goBack", &WebContents::GoBack) .SetMethod("_goForward", &WebContents::GoForward) .SetMethod("_goToOffset", &WebContents::GoToOffset) diff --git a/atom/browser/api/lib/navigation-controller.coffee b/atom/browser/api/lib/navigation-controller.coffee index 7d276e57e31a..d0c539a99db5 100644 --- a/atom/browser/api/lib/navigation-controller.coffee +++ b/atom/browser/api/lib/navigation-controller.coffee @@ -62,8 +62,8 @@ class NavigationController @webContents._loadURL @getURL(), {} reloadIgnoringCache: -> - @webContents._reloadIgnoringCache() # Rely on WebContents to clear cache. - @reload() + @pendingIndex = @currentIndex + @webContents._loadURL @getURL(), {extraHeaders: "pragma: no-cache\n"} canGoBack: -> @getActiveIndex() > 0 From e2959ed3fc4199ec9815bb8cf605d4ae23246029 Mon Sep 17 00:00:00 2001 From: Robo Date: Sat, 14 Nov 2015 12:09:18 +0530 Subject: [PATCH 501/738] add docs --- docs/api/web-contents.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 917e0670590c..1c73c5713fa1 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -207,7 +207,13 @@ See [session documentation](session.md) for this object's methods. * `extraHeaders` String - Extra headers separated by "\n" Loads the `url` in the window, the `url` must contain the protocol prefix, -e.g. the `http://` or `file://`. +e.g. the `http://` or `file://`. If the load should bypass http cache then +use the `pragma` header to achieve it. + +```javascript +const options = {"extraHeaders" : "pragma: no-cache\n"} +webContents.loadURL(url, options) +``` ### `webContents.getURL()` From 9f9436d6dc46dd5f583bd66fc6a30d6f4ca928eb Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Sat, 14 Nov 2015 23:59:38 +0100 Subject: [PATCH 502/738] Moved scope creation before the allocation of the buffer in `FrameSubscriber` --- atom/browser/api/frame_subscriber.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index 526769f9cd6c..cf0eae14a9a8 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -38,6 +38,9 @@ void FrameSubscriber::OnFrameDelivered( if (!result) 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; v8::MaybeLocal buffer = node::Buffer::New(isolate_, rgb_arr_size); @@ -56,8 +59,6 @@ void FrameSubscriber::OnFrameDelivered( rect.width() * 4, media::YV12); - v8::Locker locker(isolate_); - v8::HandleScope handle_scope(isolate_); callback_.Run(buffer.ToLocalChecked()); } From c1373d7480c48036fed38297770751f5944482ed Mon Sep 17 00:00:00 2001 From: Eddie Zaneski Date: Sun, 15 Nov 2015 10:48:09 -0500 Subject: [PATCH 503/738] Fix typo in notifications example docs --- docs/tutorial/desktop-environment-integration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/desktop-environment-integration.md b/docs/tutorial/desktop-environment-integration.md index 7c4807d8f4d4..6e570ee71f92 100644 --- a/docs/tutorial/desktop-environment-integration.md +++ b/docs/tutorial/desktop-environment-integration.md @@ -16,7 +16,7 @@ the [HTML5 Notification API](https://notifications.spec.whatwg.org/), using the currently running operating system's native notification APIs to display it. ```javascript -var myNotificiation = new Notification('Title', { +var myNotification = new Notification('Title', { body: 'Lorem Ipsum Dolor Sit Amet' }); From 42a3771f98a8ba657d15e62dbbb972e68b063735 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Mon, 16 Nov 2015 08:30:08 +0900 Subject: [PATCH 504/738] Small change --- docs-translations/ko-KR/tutorial/quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 5c2cc80f4060..942b133f2a35 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -181,7 +181,7 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/ ### 미리 작성된 앱 실행하기 -[`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) 저장소를 클론하면 이 가이드에서 작성한 예제 앱을 바로 실행해 볼 수 있습니다. +[`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) 저장소를 클론하면 이 문서에서 작성한 예제 앱을 바로 실행해 볼 수 있습니다. **참고**: 이 예제를 실행시키려면 [Git](https://git-scm.com)과 [Node.js](https://nodejs.org/en/download/)가 필요합니다. (CLI에서 실행 가능한 [npm](https://npmjs.org)이 있어야 합니다) From ad776887da5e8fe6115cb6e2f4e48d76564f02b9 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Mon, 16 Nov 2015 08:34:41 +0900 Subject: [PATCH 505/738] Update README.md --- README-ko.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README-ko.md b/README-ko.md index c8a3e6c59fb7..a0d1a9d3438f 100644 --- a/README-ko.md +++ b/README-ko.md @@ -8,16 +8,17 @@ :zap: *프레임워크 이름이 Atom Shell에서 Electron으로 변경되었습니다* :zap: -Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. 이 프레임워크는 [Node.js](https://nodejs.org) 와 -[Chromium](http://www.chromium.org)을 기반으로 만들어 졌으며 [Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다. +Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. +이 프레임워크는 [Node.js](https://nodejs.org/) 와 [Chromium](http://www.chromium.org)을 기반으로 만들어 졌으며 +[Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다. Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서 [@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요. -이 프로젝트는 기여자 규약 1.2를 준수합니다. 이 프로젝트에 참여할 때 코드를 유지해야 합니다. 받아들일 수 없는 행동은 atom@github.com로 보고 하십시오. +이 프로젝트는 [기여자 규약 1.2](http://contributor-covenant.org/version/1/2/0/)를 준수합니다. 이 프로젝트에 참여할 때 코드를 유지해야 합니다. 받아들일 수 없는 행위를 발견했을 경우 atom@github.com로 보고 하십시오. ## 다운로드 -Linux, Windows, Mac용으로 미리 빌드된 Electron 바이너리와 디버그 심볼이 준비되어 있습니다. [releases](https://github.com/atom/electron/releases) 페이지에서 받아 볼 수 있습니다. +Linux, Windows, OS X 용으로 미리 빌드된 Electron 바이너리와 디버그 심볼이 준비되어 있습니다. [releases](https://github.com/atom/electron/releases) 페이지에서 받아 볼 수 있습니다. 또한 [`npm`](https://docs.npmjs.com/)을 통해 미리 빌드된 Electron 바이너리를 받을 수도 있습니다: @@ -55,7 +56,7 @@ Electron을 빌드 하는 방법과 프로젝트에 기여하는 방법도 문 다음 링크를 통해 커뮤니티에 질문을 올리거나 토론을 나눌 수 있습니다: -- Atom 포럼의 [`electron`](http://discuss.atom.io/category/electron) 카테고리 +- Atom 포럼의 [`electron`](http://discuss.atom.io/c/electron) 카테고리 - Freenode 채팅의 `#atom-shell` 채널 - Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널 From e12e119381ab1170c8394f62bb26cccce6703bf1 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Mon, 16 Nov 2015 12:15:21 +0900 Subject: [PATCH 506/738] Update as upstream * Update as upstream * Fix typos * Improve grammar --- docs-translations/ko-KR/README.md | 30 +++--- docs-translations/ko-KR/api/app.md | 8 +- docs-translations/ko-KR/api/auto-updater.md | 6 +- .../ko-KR/api/chrome-command-line-switches.md | 13 ++- docs-translations/ko-KR/api/clipboard.md | 5 +- .../ko-KR/api/content-tracing.md | 9 +- docs-translations/ko-KR/api/crash-reporter.md | 8 +- docs-translations/ko-KR/api/dialog.md | 2 +- docs-translations/ko-KR/api/download-item.md | 101 ++++++++++++++++++ .../ko-KR/api/frameless-window.md | 6 +- .../ko-KR/api/global-shortcut.md | 5 +- docs-translations/ko-KR/api/ipc-main.md | 12 +-- docs-translations/ko-KR/api/menu.md | 10 +- docs-translations/ko-KR/api/native-image.md | 33 +++--- docs-translations/ko-KR/api/power-monitor.md | 4 +- .../ko-KR/api/power-save-blocker.md | 4 +- docs-translations/ko-KR/api/protocol.md | 7 +- docs-translations/ko-KR/api/remote.md | 21 +++- docs-translations/ko-KR/api/screen.md | 7 +- docs-translations/ko-KR/api/session.md | 6 +- docs-translations/ko-KR/api/shell.md | 2 +- docs-translations/ko-KR/api/synopsis.md | 59 +++++++--- docs-translations/ko-KR/api/tray.md | 25 ++--- docs-translations/ko-KR/api/web-frame.md | 16 ++- docs-translations/ko-KR/api/web-view-tag.md | 20 ++-- .../ko-KR/tutorial/application-packaging.md | 24 ++--- .../desktop-environment-integration.md | 15 +-- .../ko-KR/tutorial/devtools-extension.md | 5 +- .../ko-KR/tutorial/online-offline-events.md | 22 ++-- .../ko-KR/tutorial/quick-start.md | 9 +- .../tutorial/using-pepper-flash-plugin.md | 19 +--- .../tutorial/using-selenium-and-webdriver.md | 4 +- 32 files changed, 340 insertions(+), 177 deletions(-) create mode 100644 docs-translations/ko-KR/api/download-item.md diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index 73df16241528..c4c771194954 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -31,32 +31,32 @@ ### 메인 프로세스에서 사용할 수 있는 모듈: * [app](api/app.md) -* [auto-updater](api/auto-updater.md) -* [browser-window (0% 번역됨)](api/browser-window.md) -* [content-tracing](api/content-tracing.md) +* [autoUpdater](api/auto-updater.md) +* [BrowserWindow (0% 번역됨)](api/browser-window.md) +* [contentTracing](api/content-tracing.md) * [dialog](api/dialog.md) -* [global-shortcut](api/global-shortcut.md) -* [ipc-main](api/ipc-main.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) -* [web-contents (0% 번역됨)](api/web-contents.md) -* [tray](api/tray.md) +* [webContents (0% 번역됨)](api/web-contents.md) +* [Tray](api/tray.md) ### 랜더러 프로세스에서 사용할 수 있는 모듈 (웹 페이지): -* [ipc-renderer](api/ipc-renderer.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) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index f5e8e8d96b96..e37642743099 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -5,7 +5,7 @@ 밑의 예제는 마지막 윈도우창가 종료되었을 때, 어플리케이션을 종료시키는 예제입니다: ```javascript -var app = require('app'); +const app = require('electron').app; app.on('window-all-closed', function() { app.quit(); }); @@ -240,6 +240,12 @@ GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입 * `userDesktop` - 현재 사용자의 데스트탑 디렉터리. * `exe` - 현재 실행중인 Electron 바이너리 파일. * `module` - `libchromiumcontent` 라이브러리. +* `desktop` - 사용자의 데스크탑 디렉터리. +* `documents` - 사용자의 "내 문서" 디렉터리. +* `downloads` - 사용자의 다운로드 디렉터리. +* `music` - 사용자의 음악 디렉터리. +* `pictures` - 사용자의 사진 디렉터리. +* `videos` - 사용자의 동영상 디렉터리. ### `app.setPath(name, path)` diff --git a/docs-translations/ko-KR/api/auto-updater.md b/docs-translations/ko-KR/api/auto-updater.md index f12d04042ef2..1b0d9c032ccc 100644 --- a/docs-translations/ko-KR/api/auto-updater.md +++ b/docs-translations/ko-KR/api/auto-updater.md @@ -62,7 +62,7 @@ Returns: * `releaseNotes` String * `releaseName` String * `releaseDate` Date -* `updateUrl` String +* `updateURL` String 업데이트의 다운로드가 완료되었을 때 발생하는 이벤트입니다. @@ -70,7 +70,7 @@ Returns: `autoUpdater` 객체에서 사용할 수 있는 메서드입니다: -### `autoUpdater.setFeedUrl(url)` +### `autoUpdater.setFeedURL(url)` * `url` String @@ -78,7 +78,7 @@ Returns: ### `autoUpdater.checkForUpdates()` -서버에 새로운 업데이트가 있는지 요청을 보내 확인합니다. API를 사용하기 전에 `setFeedUrl`를 호출해야 합니다. +서버에 새로운 업데이트가 있는지 요청을 보내 확인합니다. API를 사용하기 전에 `setFeedURL`를 호출해야 합니다. ### `autoUpdater.quitAndInstall()` diff --git a/docs-translations/ko-KR/api/chrome-command-line-switches.md b/docs-translations/ko-KR/api/chrome-command-line-switches.md index aea9c49a1021..216d402c41e9 100644 --- a/docs-translations/ko-KR/api/chrome-command-line-switches.md +++ b/docs-translations/ko-KR/api/chrome-command-line-switches.md @@ -5,7 +5,7 @@ 어플리케이션 내부에서 스위치들을 추가할 수 있습니다: ```javascript -var app = require('app'); +const app = require('electron').app; app.commandLine.appendSwitch('remote-debugging-port', '8315'); app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1'); @@ -28,7 +28,16 @@ HTTP 요청 캐시를 비활성화 합니다. ## --remote-debugging-port=`port` -지정한 `port`에 HTTP기반의 리모트 디버거를 활성화 시킵니다. (개발자 콘솔) +지정한 `port`에 HTTP 기반의 리모트 디버거를 활성화 시킵니다. (개발자 콘솔) + +## --js-flags=`flags` + +JS 엔진에 지정한 플래그를 전달합니다. +`flags`를 메인 프로세스에서 활성화하고자 한다면, Electron이 시작되기 전에 스위치를 전달해야 합니다. + +```bash +$ electron --js-flags="--harmony_proxies --harmony_collections" your-app +``` ## --proxy-server=`address:port` diff --git a/docs-translations/ko-KR/api/clipboard.md b/docs-translations/ko-KR/api/clipboard.md index 080078274e01..01f1945856f3 100644 --- a/docs-translations/ko-KR/api/clipboard.md +++ b/docs-translations/ko-KR/api/clipboard.md @@ -3,14 +3,13 @@ `clipboard` 모듈은 복사/붙여넣기 작업을 수행하는 방법을 제공합니다. 다음 예제는 클립보드에 문자열을 씁니다: ```javascript -var clipboard = require('clipboard'); +const clipboard = require('electron').clipboard; clipboard.writeText('Example String'); ``` X Window 시스템에선 selection 클립보드도 존재합니다. 이를 사용하려면 인자 뒤에 `selection` 문자열을 같이 지정해주어야 합니다: ```javascript -var clipboard = require('clipboard'); clipboard.writeText('Example String', 'selection'); console.log(clipboard.readText('selection')); ``` @@ -78,7 +77,6 @@ console.log(clipboard.readText('selection')); 클립보드가 지정한 `data`의 형식을 지원하는지 확인합니다. ```javascript -var clipboard = require('clipboard'); console.log(clipboard.has('

selection

')); ``` @@ -98,7 +96,6 @@ console.log(clipboard.has('

selection

')); * `type` String (optional) ```javascript -var clipboard = require('clipboard'); clipboard.write({text: 'test', html: "test"}); ``` diff --git a/docs-translations/ko-KR/api/content-tracing.md b/docs-translations/ko-KR/api/content-tracing.md index 08221fbc7076..f5f8b03d294a 100644 --- a/docs-translations/ko-KR/api/content-tracing.md +++ b/docs-translations/ko-KR/api/content-tracing.md @@ -4,9 +4,14 @@ 이 모듈은 웹 인터페이스를 포함하고 있지 않으며 크롬 브라우저에서 `chrome://tracing/` 페이지를 열어 생성된 파일을 로드하면 결과를 볼 수 있습니다. ```javascript -var contentTracing = require('content-tracing'); +const contentTracing = require('electron').contentTracing; -contentTracing.startRecording('*', contentTracing.DEFAULT_OPTIONS, function() { +const options = { + categoryFilter: '*', + traceOptions: 'record-until-full,enable-sampling' +}; + +contentTracing.startRecording(options, function() { console.log('Tracing started'); setTimeout(function() { diff --git a/docs-translations/ko-KR/api/crash-reporter.md b/docs-translations/ko-KR/api/crash-reporter.md index 88cd3b82f301..a5d29551571e 100644 --- a/docs-translations/ko-KR/api/crash-reporter.md +++ b/docs-translations/ko-KR/api/crash-reporter.md @@ -5,12 +5,12 @@ 다음 예제는 윈격 서버에 어플리케이션 크래시 정보를 자동으로 보고하는 예제입니다: ```javascript -var crashReporter = require('crash-reporter'); +const crashReporter = require('electron').crashReporter; crashReporter.start({ productName: 'YourName', companyName: 'YourCompany', - submitUrl: 'https://your-domain.com/url-to-submit', + submitURL: 'https://your-domain.com/url-to-submit', autoSubmit: true }); ``` @@ -25,7 +25,7 @@ crashReporter.start({ * `productName` String, 기본값: Electron * `companyName` String, 기본값: GitHub, Inc -* `submitUrl` String, 기본값: http://54.249.141.255:1127/post +* `submitURL` String, 기본값: http://54.249.141.255:1127/post * 크래시 리포트는 POST 방식으로 이 URL로 전송됩니다. * `autoSubmit` Boolean, 기본값: true * true로 지정할 경우 유저의 승인 없이 자동으로 오류를 보고합니다. @@ -52,7 +52,7 @@ crashReporter.start({ ## crash-reporter 업로드 형식 -Crash Reporter는 다음과 같은 데이터를 `submitUrl`에 `POST` 방식으로 전송합니다: +Crash Reporter는 다음과 같은 데이터를 `submitURL`에 `POST` 방식으로 전송합니다: * `ver` String - Electron의 버전 * `platform` String - 예시 'win32' diff --git a/docs-translations/ko-KR/api/dialog.md b/docs-translations/ko-KR/api/dialog.md index 08530c054797..e7e81240da0f 100644 --- a/docs-translations/ko-KR/api/dialog.md +++ b/docs-translations/ko-KR/api/dialog.md @@ -7,7 +7,7 @@ ```javascript var win = ...; // 대화 상자를 사용할 BrowserWindow 객체 -var dialog = require('dialog'); +const dialog = require('electron').dialog; console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]})); ``` diff --git a/docs-translations/ko-KR/api/download-item.md b/docs-translations/ko-KR/api/download-item.md new file mode 100644 index 000000000000..756353b8ba3d --- /dev/null +++ b/docs-translations/ko-KR/api/download-item.md @@ -0,0 +1,101 @@ +# DownloadItem + +`DownloadItem` is an EventEmitter represents a download item in Electron. It +is used in `will-download` event of `Session` module, and allows users to +control the download item. + +```javascript +// In the main process. +win.webContents.session.on('will-download', function(event, item, webContents) { + // Set the save path, making Electron not to prompt a save dialog. + item.setSavePath('/tmp/save.pdf'); + console.log(item.getMimeType()); + console.log(item.getFilename()); + console.log(item.getTotalBytes()); + item.on('updated', function() { + console.log('Received bytes: ' + item.getReceivedBytes()); + }); + item.on('done', function(e, state) { + if (state == "completed") { + console.log("Download successfully"); + } else { + console.log("Download is cancelled or interrupted that can't be resumed"); + } + }); +``` + +## Events + +### Event: 'updated' + +Emits when the `downloadItem` gets updated. + +### Event: 'done' + +* `event` Event +* `state` String + * `completed` - The download completed successfully. + * `cancelled` - The download has been cancelled. + * `interrupted` - An error broke the connection with the file server. + +Emits when the download is in a terminal state. This includes a completed +download, a cancelled download(via `downloadItem.cancel()`), and interrupted +download that can't be resumed. + +## Methods + +The `downloadItem` object has the following methods: + +### `downloadItem.setSavePath(path)` + +* `path` String - Set the save file path of the download item. + +The API is only available in session's `will-download` callback function. +If user doesn't set the save path via the API, Electron will use the original +routine to determine the save path(Usually prompts a save dialog). + +### `downloadItem.pause()` + +Pauses the download. + +### `downloadItem.resume()` + +Resumes the download that has been paused. + +### `downloadItem.cancel()` + +Cancels the download operation. + +### `downloadItem.getURL()` + +Returns a `String` represents the origin url where the item is downloaded from. + +### `downloadItem.getMimeType()` + +Returns a `String` represents the mime type. + +### `downloadItem.hasUserGesture()` + +Returns a `Boolean` indicates whether the download has user gesture. + +### `downloadItem.getFilename()` + +Returns a `String` represents the file name of the download item. + +**Note:** The file name is not always the same as the actual one saved in local +disk. If user changes the file name in a prompted download saving dialog, the +actual name of saved file will be different. + +### `downloadItem.getTotalBytes()` + +Returns a `Integer` represents the total size in bytes of the download item. +If the size is unknown, it returns 0. + +### `downloadItem.getReceivedBytes()` + +Returns a `Integer` represents the received bytes of the download item. + +### `downloadItem.getContentDisposition()` + +Returns a `String` represents the Content-Disposition field from the response +header. diff --git a/docs-translations/ko-KR/api/frameless-window.md b/docs-translations/ko-KR/api/frameless-window.md index 28662c311ba2..decc0217ed1e 100644 --- a/docs-translations/ko-KR/api/frameless-window.md +++ b/docs-translations/ko-KR/api/frameless-window.md @@ -9,7 +9,7 @@ Frameless Window는 [테두리](https://developer.mozilla.org/en-US/docs/Glossar Frameless Window를 만드려면 [BrowserWindow](browser-window.md) 객체의 `options`에서 `frame` 옵션을 `false`로 지정하면 됩니다: ```javascript -var BrowserWindow = require('browser-window'); +const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({ width: 800, height: 600, frame: false }); ``` @@ -20,8 +20,8 @@ OS X 10.10 Yosemite 이후의 최신 버전부터는 테두리가 없는 창을 옵션을 통해 제목만 숨기고 창 구성 요소("흔히 신호등으로 알고 있는")의 기능과 창 크기를 그대로 유지할 수 있습니다: ```javascript -var BrowserWindow = require('browser-window'); -var win = new BrowserWindow({ width: 800, height: 600, 'title-bar-style': 'hidden' }); +var win = new BrowserWindow({ 'title-bar-style': 'hidden' }); +``` ## 투명한 창 만들기 diff --git a/docs-translations/ko-KR/api/global-shortcut.md b/docs-translations/ko-KR/api/global-shortcut.md index f000a3bdb6a4..2120f73cc5cb 100644 --- a/docs-translations/ko-KR/api/global-shortcut.md +++ b/docs-translations/ko-KR/api/global-shortcut.md @@ -7,8 +7,9 @@ 이 모듈은 `app` 모듈의 `ready` 이벤트 이전에 사용할 수 없습니다. ```javascript -var app = require('app'); -var globalShortcut = require('global-shortcut'); +const electron = require('electron'); +const app = electron.app; +const globalShortcut = electron.globalShortcut; app.on('ready', function() { // 'ctrl+x' 단축키를 리스너에 등록합니다. diff --git a/docs-translations/ko-KR/api/ipc-main.md b/docs-translations/ko-KR/api/ipc-main.md index cecbf980e720..fae8aa4d5cf6 100644 --- a/docs-translations/ko-KR/api/ipc-main.md +++ b/docs-translations/ko-KR/api/ipc-main.md @@ -16,25 +16,25 @@ ```javascript // 메인 프로세스 -var ipc = require('ipc'); +const ipcMain = require('electron').ipcMain; ipc.on('asynchronous-message', function(event, arg) { - console.log(arg); // prints "ping" + console.log(arg); // "ping" 출력 event.sender.send('asynchronous-reply', 'pong'); }); ipc.on('synchronous-message', function(event, arg) { - console.log(arg); // prints "ping" + console.log(arg); // "ping" 출력 event.returnValue = 'pong'; }); ``` ```javascript // 랜더러 프로세스 (웹 페이지) -var ipc = require('ipc'); -console.log(ipc.sendSync('synchronous-message', 'ping')); // prints "pong" +const ipcRenderer = require('electron').ipcRenderer; +console.log(ipc.sendSync('synchronous-message', 'ping')); // "pong" 출력 ipc.on('asynchronous-reply', function(arg) { - console.log(arg); // prints "pong" + console.log(arg); // "pong" 출력 }); ipc.send('asynchronous-message', 'ping'); ``` diff --git a/docs-translations/ko-KR/api/menu.md b/docs-translations/ko-KR/api/menu.md index 56b7f4a198e5..d55fa807a362 100644 --- a/docs-translations/ko-KR/api/menu.md +++ b/docs-translations/ko-KR/api/menu.md @@ -11,9 +11,9 @@ ```html - + + + ``` 어플리케이션을 실행하려면 [앱 실행하기](../tutorial/quick-start.md#앱 실행하기) 문서를 참고하기 바랍니다. + +## 분리 할당 + +만약 CoffeeScript나 Babel을 사용하고 있다면, 빌트인 모듈을 사용할 때 +[분리 할당][desctructuring-assignment]을 통해 직관적으로 사용할 수 있습니다: + +```javascript +const {app, BrowserWindow} = require('electron') +``` + +아직 플레인 자바스크립트를 쓰고 있다면, Chrome이 ES6를 완전히 지원하기 전까지 기다려야 합니다. + +## 이전 스타일의 빌트인 모듈 비활성화 + +v0.35.0 이전 버전에선 빌트인 모듈이 모두 `require('module-name')`같은 형식으로 사용되었습니다. +하지만 [많은 단점][issue-387]이 있기 때문에 현재 변경되었습니다. +하지만 오래된 앱의 호환성 유지를 위해 아직 구 버전 API를 지원하고 있습니다. + +완벽하게 모든 구 버전 API를 비활성화하려면 `ELECTRON_HIDE_INTERNAL_MODULES` 환경 변수를 설정하면 됩니다: + +```javascript +process.env.ELECTRON_HIDE_INTERNAL_MODULES = 'true' +``` + +또는 `hideInternalModules` API를 사용해도 됩니다: + +```javascript +require('electron').hideInternalModules() +``` + +[gui]: https://en.wikipedia.org/wiki/Graphical_user_interface +[main-process]: ../tutorial/quick-start.md#메인-프로세스 +[desctructuring-assignment]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment +[issue-387]: https://github.com/atom/electron/issues/387 \ No newline at end of file diff --git a/docs-translations/ko-KR/api/tray.md b/docs-translations/ko-KR/api/tray.md index 22fec3089e69..96722bb2409e 100644 --- a/docs-translations/ko-KR/api/tray.md +++ b/docs-translations/ko-KR/api/tray.md @@ -3,9 +3,10 @@ `Tray`는 OS의 알림 영역에 아이콘을 표시합니다. 보통 컨텍스트 메뉴(context menu)를 같이 사용합니다. ```javascript -var app = require('app'); -var Menu = require('menu'); -var Tray = require('tray'); +const electron = require('electron'); +const app = electron.app; +const Menu = electron.Menu; +const Tray = electron.Tray; var appIcon = null; app.on('ready', function(){ @@ -29,7 +30,7 @@ __플랫폼별 한계:__ * 앱 알림 표시기는 컨텍스트 메뉴를 가지고 있을 때만 보입니다. * Linux에서 앱 알림 표시기가 사용될 경우, `clicked` 이벤트는 무시됩니다. -이러한 이유로 Tray API가 모든 플랫폼에서 똑같이 작동하게 하고 싶다면 `clicked` 이벤트에 의존해선 안됩니다. +이러한 이유로 Tray API가 모든 플랫폼에서 똑같이 작동하게 하고 싶다면 `click` 이벤트에 의존해선 안됩니다. 그리고 언제나 컨텍스트 메뉴를 포함해야 합니다. ## Class: Tray @@ -48,7 +49,7 @@ __플랫폼별 한계:__ **참고:** 몇가지 이벤트는 특정한 플랫폼에서만 작동합니다. -### Event: 'clicked' +### Event: 'click' * `event` Event * `altKey` Boolean @@ -65,7 +66,7 @@ __플랫폼별 한계:__ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다. -### Event: 'right-clicked' _OS X_ _Windows_ +### Event: 'right-click' _OS X_ _Windows_ * `event` Event * `altKey` Boolean @@ -80,7 +81,7 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다. 트레이 아이콘을 오른쪽 클릭될 때 호출 됩니다. -### Event: 'double-clicked' _OS X_ _Windows_ +### Event: 'double-click' _OS X_ _Windows_ * `event` Event * `altKey` Boolean @@ -97,15 +98,15 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다. ### Event: 'balloon-show' _Windows_ -알림풍선이 보여질 때 발생하는 이벤트입니다. +풍선 팝업이 보여질 때 발생하는 이벤트입니다. -### Event: 'balloon-clicked' _Windows_ +### Event: 'balloon-click' _Windows_ -알림풍선이 클릭될 때 발생하는 이벤트입니다. +풍선 팝업이 클릭될 때 발생하는 이벤트입니다. ### Event: 'balloon-closed' _Windows_ -알림풍선이 시간이 지나 사라지거나 유저가 클릭하여 닫을 때 발생하는 이벤트입니다. +풍선 팝업이 시간이 지나 사라지거나 유저가 클릭하여 닫을 때 발생하는 이벤트입니다. ### Event: 'drop' _OS X_ @@ -177,7 +178,7 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다. * `title` String * `content` String -트레이에 알림풍선을 생성합니다. +트레이에 풍선 팝업을 생성합니다. ### `Tray.popContextMenu([position])` _OS X_ _Windows_ diff --git a/docs-translations/ko-KR/api/web-frame.md b/docs-translations/ko-KR/api/web-frame.md index d09114e559c8..5b94a9a6ad71 100644 --- a/docs-translations/ko-KR/api/web-frame.md +++ b/docs-translations/ko-KR/api/web-frame.md @@ -5,7 +5,7 @@ 다음 예제는 현재 페이지를 200% 줌 합니다: ```javascript -var webFrame = require('web-frame'); +var webFrame = require('electron').webFrame; webFrame.setZoomFactor(2); ``` @@ -55,14 +55,14 @@ Input field나 text area에 철자 검사(spell checking) 제공자를 설정합 [node-spellchecker][spellchecker]를 철자 검사 제공자로 사용하는 예제입니다: ```javascript -require('web-frame').setSpellCheckProvider("en-US", true, { +webFrame.setSpellCheckProvider("en-US", true, { spellCheck: function(text) { return !(require('spellchecker').isMisspelled(text)); } }); ``` -### `webFrame.registerUrlSchemeAsSecure(scheme)` +### `webFrame.registerURLSchemeAsSecure(scheme)` * `scheme` String @@ -70,10 +70,16 @@ require('web-frame').setSpellCheckProvider("en-US", true, { 보안 스킴은 혼합된 컨텐츠 경고를 발생시키지 않습니다. 예를 들어 `https` 와 `data`는 네트워크 공격자로부터 손상될 가능성이 없기 때문에 보안 스킴이라고 할 수 있습니다. -### `webFrame.registerUrlSchemeAsBypassingCsp(scheme)` +### `webFrame.registerURLSchemeAsBypassingCSP(scheme)` * `scheme` String -현재 페이지 컨텐츠의 보안 정책에 상관없이 이 `scheme`로부터 리소스가 로드됩니다. +현재 페이지 컨텐츠의 보안 정책에 상관없이 `scheme`로부터 리소스가 로드됩니다. + +### `webFrame.registerURLSchemeAsPrivileged(scheme)` + + * `scheme` String + +보안 `scheme`를 지정합니다. 리소스와 ServiceWorker 설정에 대해 보안 정책을 우회합니다. [spellchecker]: https://github.com/atom/node-spellchecker diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index bb9a1305c8a9..eb40151a234d 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -156,7 +156,7 @@ webview.addEventListener("dom-ready", function() { }); ``` -### `.getUrl()` +### `.getURL()` 페이지의 URL을 반환합니다. @@ -376,7 +376,7 @@ Returns: * `errorCode` Integer * `errorDescription` String -* `validatedUrl` String +* `validatedURL` String `did-finish-load`와 비슷합니다. 하지만 이 이벤트는 `window.stop()`과 같은 무언가로 인해 로드에 실패했을 때 발생하는 이벤트입니다. @@ -401,8 +401,8 @@ Returns: Returns: * `status` Boolean -* `newUrl` String -* `originalUrl` String +* `newURL` String +* `originalURL` String * `httpResponseCode` Integer * `requestMethod` String * `referrer` String @@ -415,8 +415,8 @@ Returns: Returns: -* `oldUrl` String -* `newUrl` String +* `oldURL` String +* `newURL` String * `isMainFrame` Boolean 리소스를 요청하고 받는 도중에 리다이렉트가 생기면 발생하는 이벤트입니다. @@ -484,7 +484,7 @@ Returns: ```javascript webview.addEventListener('new-window', function(e) { - require('shell').openExternal(e.url); + require('electron').shell.openExternal(e.url); }); ``` @@ -522,9 +522,9 @@ webview.send('ping'); ```javascript // In guest page. -var ipc = require('ipc'); -ipc.on('ping', function() { - ipc.sendToHost('pong'); +var ipcRenderer = require('electron').ipcRenderer; +ipcRenderer.on('ping', function() { + ipcRenderer.sendToHost('pong'); }); ``` diff --git a/docs-translations/ko-KR/tutorial/application-packaging.md b/docs-translations/ko-KR/tutorial/application-packaging.md index d7a96dbb4b43..9a5e3dfb20e2 100644 --- a/docs-translations/ko-KR/tutorial/application-packaging.md +++ b/docs-translations/ko-KR/tutorial/application-packaging.md @@ -47,14 +47,14 @@ $ asar list /path/to/example.asar `asar` 아카이브에선 다음과 같이 파일을 읽을 수 있습니다: ```javascript -var fs = require('fs'); +const fs = require('fs'); fs.readFileSync('/path/to/example.asar/file.txt'); ``` 아카이브 내의 루트 디렉터리를 리스팅합니다: ```javascript -var fs = require('fs'); +const fs = require('fs'); fs.readdirSync('/path/to/example.asar'); ``` @@ -67,9 +67,9 @@ require('/path/to/example.asar/dir/module.js'); `BrowserWindow` 클래스를 이용해 원하는 웹 페이지도 표시할 수 있습니다: ```javascript -var BrowserWindow = require('browser-window'); +const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({width: 800, height: 600}); -win.loadUrl('file:///path/to/example.asar/static/index.html'); +win.loadURL('file:///path/to/example.asar/static/index.html'); ``` ### Web API @@ -90,8 +90,8 @@ $.get('file:///path/to/example.asar/file.txt', function(data) { ### `asar` 아카이브를 일반 파일로 취급하기 -`asar` 아카이브의 체크섬(checksum)등을 검사하기 위해선 `asar` 아카이브를 파일 그대로 읽어들여야 할 필요가 있습니다. -이 작업을 하기 위해 `original-fs`라고 하는 빌트인 모듈을 `fs` 모듈 대신에 사용할 수 있습니다. +`asar` 아카이브의 체크섬(checksum)을 검사하는 작업등을 하기 위해선 `asar` 아카이브를 파일 그대로 읽어야 합니다. +이러한 작업을 하기 위해 `original-fs` 빌트인 모듈을 `fs` 모듈 대신에 사용할 수 있습니다. 이 모듈은 `asar` 지원이 빠져있습니다. 즉 파일 그대로를 읽어들입니다: ```javascript @@ -112,13 +112,13 @@ originalFs.readFileSync('/path/to/example.asar'); `asar` 아카이브는 디렉터리처럼 사용할 수 있도록 구현되었지만 그것은 실제 파일시스템의 디렉터리가 아닌 가상의 디렉터리입니다. 그런 이유로 몇몇 API에서 지원하는 `cwd` 옵션을 `asar` 아카이브 안의 디렉터리 경로로 지정하면 나중에 문제가 발생할 수 있습니다. -### 특정 API로 인한 예외적인 압축 해제 +### 특정 API로 인한 예외적인 아카이브 압축 해제 많은 `fs` API가 `asar` 아카이브의 압축을 해제하지 않고 바로 아카이브를 읽거나 정보를 가져올 수 있으나 -몇몇 API는 시스템의 실제 파일의 경로를 기반으로 작동하므로 이 API들을 사용할 땐 Electron은 -이 API가 원할하게 작동할 수 있도록 하기 위해 임시경로에 해당 파일들의 압축을 해제합니다. 이 작업은 약간의 오버헤드를 불러 일으킬 수 있습니다. +몇몇 API는 시스템의 실제 파일의 경로를 기반으로 작동하므로 Electron은 API가 원할하게 작동할 수 있도록 +임시 경로에 해당되는 파일의 압축을 해제합니다. 이 작업은 약간의 오버헤드를 불러 일으킬 수 있습니다. -해당하는 API 메서드는 다음과 같습니다: +위 예외에 해당하는 API 메서드는 다음과 같습니다: * `child_process.execFile` * `fs.open` @@ -127,7 +127,7 @@ originalFs.readFileSync('/path/to/example.asar'); ### `fs.stat`의 잘못된 스테이터스 정보 -`fs.stat` 로 부터 반환되는 `Stats` 객체와 비슷한 API들은 `asar` 아카이브를 타겟으로 할 경우 예측된 디렉터리 피일 정보를 가집니다. +`fs.stat` 로 부터 반환되는 `Stats` 객체와 비슷한 API들은 `asar` 아카이브를 타겟으로 할 경우 예측된 디렉터리 파일 정보를 가집니다. 왜냐하면 아카이브의 디렉터리 경로는 실제 파일시스템에 존재하지 않기 때문입니다. 그러한 이유로 파일 크기와 파일 타입 등을 확인할 때 `Stats` 객체를 신뢰해선 안됩니다. @@ -145,6 +145,6 @@ $ asar pack app app.asar --unpack *.node 커맨드를 실행한 후 같은 디렉터리에 `app.asar` 파일 외에 `app.asar.unpacked` 폴더가 같이 생성됩니다. 이 폴더안에 unpack 옵션에서 설정한 파일들이 압축이 풀린 상태로 포함되어 있습니다. -유저에게 어플리케이션을 배포할 때 반드시 해당 폴더도 같이 배포하여야합니다. +사용자에게 어플리케이션을 배포할 때 반드시 해당 폴더도 같이 배포해야 합니다. [asar]: https://github.com/atom/asar diff --git a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md index 1212cbb9c433..fe0a6450bc11 100644 --- a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md +++ b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md @@ -28,7 +28,7 @@ myNotification.onclick = function () { * Windows 10에선 "아무 문제 없이 잘" 작동합니다. * Windows 8.1과 8에선 [Application User Model ID][app-user-model-id]로 바로가기를 만들어 놔야 합니다. 이 바로가기는 반드시 시작 화면에 설치되어 있어야 합니다. 참고로 반드시 시작 화면에 고정 할 필요는 없습니다. -* Windows 7과 그 이하 버전은 데스크톱 알림을 지원하지 않습니다. 혹시 "풍선 알림" 기능을 찾는다면 [Tray API](tray-balloon)를 사용하세요. +* Windows 7과 그 이하 버전은 데스크톱 알림을 지원하지 않습니다. 혹시 "풍선 팝업 알림" 기능을 찾는다면 [Tray API](tray-balloon)를 사용하세요. 이미지를 데스크톱 알림에 사용하려면 알림 옵션의 `icon` 속성에 로컬 이미지 파일(`png` 권장)을 지정하면 됩니다. 데스크톱 알림은 잘못된 경로를 지정하거나 `http/https` 기반의 URL을 지정해도 이미지가 보이지 않을 뿐 정상 작동합니다. @@ -70,7 +70,6 @@ __어플리케이션 dock menu:__ 파일을 최근 문서에 추가하려면 [app.addRecentDocument][addrecentdocument] API를 사용할 수 있습니다: ```javascript -var app = require('app'); app.addRecentDocument('/Users/USERNAME/Desktop/work.type'); ``` @@ -104,8 +103,10 @@ __Terminal.app의 dock menu:__ 커스텀 dock menu를 설정하려면 `app.dock.setMenu` API를 사용하면 됩니다. OS X에서만 사용 가능합니다: ```javascript -var app = require('app'); -var Menu = require('menu'); +const electron = require('electron'); +const app = electron.app; +const Menu = electron.Menu; + var dockMenu = Menu.buildFromTemplate([ { label: 'New Window', click: function() { console.log('New Window'); } }, { label: 'New Window with Settings', submenu: [ @@ -144,7 +145,6 @@ OS X의 dock menu(진짜 메뉴)와는 달리 Windows의 사용자 작업은 어 사용자 작업을 설정하려면 [app.setUserTasks][setusertaskstasks] 메서드를 통해 구현할 수 있습니다: ```javascript -var app = require('app'); app.setUserTasks([ { program: process.execPath, @@ -187,8 +187,9 @@ __Windows Media Player의 섬네일 툴바:__ [BrowserWindow.setThumbarButtons][setthumbarbuttons] API를 통해 어플리케이션에 섬네일 툴바를 설정할 수 있습니다: ```javascript -var BrowserWindow = require('browser-window'); -var path = require('path'); +const BrowserWindow = require('electron').BrowserWindow; +const path = require('path'); + var win = new BrowserWindow({ width: 800, height: 600 diff --git a/docs-translations/ko-KR/tutorial/devtools-extension.md b/docs-translations/ko-KR/tutorial/devtools-extension.md index 659c769dde34..04b592955cdc 100644 --- a/docs-translations/ko-KR/tutorial/devtools-extension.md +++ b/docs-translations/ko-KR/tutorial/devtools-extension.md @@ -22,13 +22,14 @@ $ git clone --recursive https://github.com/facebook/react-devtools.git 그리고 개발자 콘솔에서 다음 코드를 입력하면 확장 기능을 로드할 수 있습니다: ```javascript -require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools/shells/chrome'); +const BrowserWindow = require('electron').remote.BrowserWindow; +BrowserWindow.addDevToolsExtension('/some-directory/react-devtools/shells/chrome'); ``` 확장 기능을 언로드 하고 콘솔을 다시 열 때 해당 확장 기능이 로드되지 않도록 하려면 `BrowserWindow.removeDevToolsExtension` API를 사용하면 됩니다: ```javascript -require('remote').require('browser-window').removeDevToolsExtension('React Developer Tools'); +BrowserWindow.removeDevToolsExtension('React Developer Tools'); ``` ## 개발자 콘솔 확장 기능의 구성 형식 diff --git a/docs-translations/ko-KR/tutorial/online-offline-events.md b/docs-translations/ko-KR/tutorial/online-offline-events.md index 5950d40525e2..0b989516a6ab 100644 --- a/docs-translations/ko-KR/tutorial/online-offline-events.md +++ b/docs-translations/ko-KR/tutorial/online-offline-events.md @@ -5,13 +5,14 @@ _main.js_ ```javascript -var app = require('app'); -var BrowserWindow = require('browser-window'); -var onlineStatusWindow; +const electron = require('electron'); +const app = electron.app; +const BrowserWindow = electron.BrowserWindow; +var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ``` @@ -43,14 +44,15 @@ _online-status.html_ _main.js_ ```javascript -var app = require('app'); -var ipcMain = require('ipc-main'); -var BrowserWindow = require('browser-window'); -var onlineStatusWindow; +const electron = require('electron'); +const app = electron.app; +const ipcMain = electron.ipcMain; +const BrowserWindow = electron.BrowserWindow; +var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ipcMain.on('online-status-changed', function(event, status) { @@ -65,7 +67,7 @@ _online-status.html_ + + +``` + +### `webContents.enableDeviceEmulation(parameters)` + +`parameters` Object, properties: + +* `screenPosition` String - 에뮬레이트 할 화면 종료를 지정합니다 + (default: `desktop`) + * `desktop` + * `mobile` +* `screenSize` Object - 에뮬레이트 화면의 크기를 지정합니다 (screenPosition == mobile) + * `width` Integer - 에뮬레이트 화면의 너비를 지정합니다 + * `height` Integer - 에뮬레이트 화면의 높이를 지정합니다 +* `viewPosition` Object - 화면에서 뷰의 위치 + (screenPosition == mobile) (default: `{x: 0, y: 0}`) + * `x` Integer - 좌상단 모서리로부터의 x 축의 오프셋 + * `y` Integer - 좌상단 모서리로부터의 y 축의 오프셋 +* `deviceScaleFactor` Integer - 디바이스의 스케일 팩터(scale factor)를 지정합니다. + (0일 경우 기본 디바이스 스케일 팩터를 기본으로 사용합니다) (default: `0`) +* `viewSize` Object - 에뮬레이트 된 뷰의 크기를 지정합니다 (빈 값은 오버라이드 하지 않는 다는 + 것을 의미합니다) + * `width` Integer - 에뮬레이트 된 뷰의 너비를 지정합니다 + * `height` Integer - 에뮬레이트 된 뷰의 높이를 지정합니다 +* `fitToView` Boolean - 에뮬레이트의 뷰가 사용 가능한 공간에 맞추어 스케일 다운 될지 여부를 + 지정합니다 (기본값: `false`) +* `offset` Object - 사용 가능한 공간에서 에뮬레이트 된 뷰의 오프셋을 지정합니다 + (fit to view 모드 외에서) (기본값: `{x: 0, y: 0}`) + * `x` Float - 좌상단 모서리에서 x 축의 오프셋을 지정합니다 + * `y` Float - 좌상단 모서리에서 y 축의 오프셋을 지정합니다 +* `scale` Float - 사용 가능한 공간에서 에뮬레이드 된 뷰의 스케일 (fit to view 모드 외에서) + (기본값: `1`) + +주어진 파라미터로 디바이스 에뮬레이션을 사용합니다. + +### `webContents.disableDeviceEmulation()` + +`webContents.enableDeviceEmulation`로 사용가능해진 디바이스 에뮬레이선을 비활성화 합니다. + +### `webContents.sendInputEvent(event)` + +* `event` Object + * `type` String (**required**) - 이벤트의 타입. 다음 값들이 가능합니다. `mouseDown`, + `mouseUp`, `mouseEnter`, `mouseLeave`, `contextMenu`, `mouseWheel`, + `keyDown`, `keyUp`, `char`. + * `modifiers` Array - 이벤트의 수정자(modifier)들에 대한 배열. 다음 값들을 포함 할 수 + 있습니다. `shift`, `control`, `alt`, `meta`, `isKeypad`, `isAutoRepeat`, + `leftButtonDown`, `middleButtonDown`, `rightButtonDown`, `capsLock`, + `numLock`, `left`, `right`. + +input `event`를 페이지로 보냅니다. + +키보드 이벤트들에 대해서는 `event` 객체는 다음 속성들을 추가적으로 가지고 있습니다: + +* `keyCode` String (**required**) - 키보드 이벤트로 보낼 수 있는 단일 캐릭터. 모든 UTF-8가 + 사용 가능합니다. + +마우스 이벤트들에 대해서는 `event` 객체는 다음 속성들을 추가적으로 가지고 있습니다: + +* `x` Integer (**required**) +* `y` Integer (**required**) +* `button` String - 눌린 버튼. 다음 값들이 가능합니다. `left`, `middle`, `right` +* `globalX` Integer +* `globalY` Integer +* `movementX` Integer +* `movementY` Integer +* `clickCount` Integer + +`mouseWheel` 이벤트에 대해서는 `event` 객체는 다음 속성들을 추가적으로 가지고 있습니다: + +* `deltaX` Integer +* `deltaY` Integer +* `wheelTicksX` Integer +* `wheelTicksY` Integer +* `accelerationRatioX` Integer +* `accelerationRatioY` Integer +* `hasPreciseScrollingDeltas` Boolean +* `canScroll` Boolean + +### `webContents.beginFrameSubscription(callback)` + +* `callback` Function + +프레젠테이션 이벤트들과 캡쳐된 프레임들에 대한 구독을 시작하면 `callback`이 프레젠테이션 이벤트가 +발생할 때 `callback(frameBuffer)`과 같은 형식으로 호출됩니다. + +`frameBuffer`는 raw 픽셀 데이터를 포함한 `Buffer`입니다. 대부분의 기계에서 픽셀 데이터는 32bit +BGRA 포맷으로 효율적으로 저장됩니다. 하지만 실제 재프리젠테이션은 프로세서의 endianness에 의존성을 +가지고 있습니다(대부분의 현재 프로세스들은 little-endian입니다. big-endian 프로세서들를 가진 +기계들에서 data는 32bit ARGB format입니다). + +### `webContents.endFrameSubscription()` + +프레임 프레젠테이션 이벤트들에 대한 구독을 중지합니다. + +## Instance Properties + +`WebContents`객체들은 다음 속성들을 가지고 있습니다: + +### `webContents.devToolsWebContents` + +이 `WebContents`에 대한 DevTools의 `WebContents`를 가져옵니다. + +**Note:** 사용자가 절대로 이 객체를 저장해서는 안됩니다. 그럴경우 DevTools가 닫혔을 때, `null`이 +될 수도 있습니다. + +### `webContents.savePage(fullPath, saveType, callback)` + +* `fullPath` String - 전체 파일 경로. +* `saveType` String - 저장 타입을 지정합니다. + * `HTMLOnly` - 페이지의 HTML만 저장합니다. + * `HTMLComplete` - 페이지의 완성된 HTML을 저장합니다. + * `MHTML` - 페이지의 완성된 HTML을 MHTML로 저장합니다. +* `callback` Function - `function(error) {}`. + * `error` Error + +만약 페이지를 저장하는 프로세스가 성공적으로 끝났을 경우 true를 반환합니다. + +```javascript +win.loadURL('https://github.com'); + +win.webContents.on('did-finish-load', function() { + win.webContents.savePage('/tmp/test.html', 'HTMLComplete', function(error) { + if (!error) + console.log("Save page successfully"); + }); +}); +``` From 5995451366af07debb53d30765e042cd34c2e7ae Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Tue, 17 Nov 2015 16:49:08 +0900 Subject: [PATCH 529/738] Add missing translations --- docs-translations/ko-KR/api/menu-item.md | 29 ++++++++++++------------ 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/docs-translations/ko-KR/api/menu-item.md b/docs-translations/ko-KR/api/menu-item.md index e4c5c677676d..fc5539c8cdf1 100644 --- a/docs-translations/ko-KR/api/menu-item.md +++ b/docs-translations/ko-KR/api/menu-item.md @@ -25,11 +25,10 @@ * `id` String - 현재 메뉴 아이템에 대해 유일키를 지정합니다. 이 키는 이후 `position` 옵션에서 사용할 수 있습니다. * `position` String - 미리 지정한 `id`를 이용하여 메뉴 아이템의 위치를 세밀하게 조정합니다. -When creating menu items, it is recommended to specify `role` instead of -manually implementing the behavior if there is matching action, so menu can have -best native experience. +메뉴 아이템을 생성할 때, 매칭되는 액션이 있다면 수동으로 직접 구현하는 대신 `role`을 설정하여, +고유 OS 경험을 최대한 살릴 것을 권장합니다. -The `role` property can have following values: +`role` 속성은 다음 값을 가질 수 있습니다.: * `undo` * `redo` @@ -37,16 +36,16 @@ The `role` property can have following values: * `copy` * `paste` * `selectall` -* `minimize` - Minimize current window -* `close` - Close current window +* `minimize` - 현재 윈도우를 최소화 합니다. +* `close` - 현재 윈도우를 닫습니다. -On OS X `role` can also have following additional values: +OS X에서 `role`은 다음 값을 추가로 가질 수 있습니다. -* `about` - Map to the `orderFrontStandardAboutPanel` action -* `hide` - Map to the `hide` action -* `hideothers` - Map to the `hideOtherApplications` action -* `unhide` - Map to the `unhideAllApplications` action -* `front` - Map to the `arrangeInFront` action -* `window` - The submenu is a "Window" menu -* `help` - The submenu is a "Help" menu -* `services` - The submenu is a "Services" menu +* `about` - `orderFrontStandardAboutPanel` 액션에 매핑합니다. +* `hide` - `hide` 액션에 매핑합니다. +* `hideothers` - `hideOtherApplications` 액션에 매핑합니다. +* `unhide` - `unhideAllApplications` 액션에 매핑합니다. +* `front` - `arrangeInFront` 액션에 매핑합니다. +* `window` - 부메뉴가 "Window" 메뉴입니다. +* `help` - 부메뉴가 "Help" 메뉴입니다. +* `services` - 부메뉴가 "Services" 메뉴입니다. From 855c1ead008377dab4ecca20d5589099c807ab45 Mon Sep 17 00:00:00 2001 From: Moises lopes ferreira Date: Fri, 13 Nov 2015 11:35:13 -0200 Subject: [PATCH 530/738] Portuguese translation of coding-style.md --- .../pt-BR/development/coding-style.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 docs-translations/pt-BR/development/coding-style.md diff --git a/docs-translations/pt-BR/development/coding-style.md b/docs-translations/pt-BR/development/coding-style.md new file mode 100644 index 000000000000..f3b4d6d58f37 --- /dev/null +++ b/docs-translations/pt-BR/development/coding-style.md @@ -0,0 +1,29 @@ +# Estilo de Codificação + +Estas são as diretrizes de estilo para codificar no Electron. + +## C++ and Python + +Para C ++ e Python, seguimos os padrões do projeto Chromium [Estilo de Codificação](http://www.chromium.org/developers/coding-style). Há também um +script `script/cpplint.py` para verificar se todos os arquivos estão em conformidade. + +A versão Python que estamos usando agora é a Python 2.7. + +O código C ++ usa do Chromium's um monte de tipos e abstrações, por isso é recomendada para se familiarizar com eles. Um bom lugar para começar com a documentação do Chromium's [Important Abstractions and Data Structures](https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures). O documento menciona alguns tipos especiais, com escopo tipos (que automaticamente libera sua memória quando sai do escopo), registrando mecanismos etc. + +## CoffeeScript + +For CoffeeScript, we follow GitHub's [Style +Guide](https://github.com/styleguide/javascript) and the following rules: + +Para CoffeeScript, seguimos o estilo do GitHub [Guia de Estilo] (https://github.com/styleguide/javascript) com as seguintes regras: + +* Os arquivos devem **NÃO DEVEM** com nova linha no final, porque queremos corresponder aos padrões de estilo Google. + +* Os nomes dos arquivos devem ser concatenados com o `-` em vez de`_`, por exemplo, `file-name.coffee` em vez de`file_name.coffee`, porque no [github/atom](https://github.com/github/atom) os nomes dos módulos são geralmente em o formulário `module-name`. Esta regra só se aplica aos arquivos com extensão `.coffee`. +* +## API Names + +Ao criar uma nova API, devemos preferencialmente utilizar métodos getters e setters em vez de +estilo de uma função do jQuery. Por exemplo, `.getText()` e `.setText(text)` utilize `.text([text])`. Existe uma +[discussão](https://github.com/atom/electron/issues/46) sobre este assunto. From 217311ef213ba1347506cd165b30447fd789f130 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 17 Nov 2015 19:00:33 +0800 Subject: [PATCH 531/738] No need to use weak reference Ref-counting manages everything. --- atom/browser/api/atom_api_session.cc | 5 +---- atom/browser/atom_cert_verifier.cc | 8 +++----- atom/browser/atom_cert_verifier.h | 5 +---- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 07b9b68a94d7..579b64bf4a7d 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -241,10 +241,7 @@ void SetProxyInIO(net::URLRequestContextGetter* getter, void PassVerificationResult( scoped_refptr request, bool success) { - int result = net::OK; - if (!success) - result = net::ERR_FAILED; - request->ContinueWithResult(result); + request->ContinueWithResult(success ? net::OK : net::ERR_FAILED); } } // namespace diff --git a/atom/browser/atom_cert_verifier.cc b/atom/browser/atom_cert_verifier.cc index e56e611faa81..0ff0d1e4a547 100644 --- a/atom/browser/atom_cert_verifier.cc +++ b/atom/browser/atom_cert_verifier.cc @@ -66,8 +66,7 @@ void AtomCertVerifier::CertVerifyRequest::DelegateToDefaultVerifier() { key_.flags, crl_set_.get(), verify_result_, - base::Bind(&CertVerifyRequest::RunResult, - weak_ptr_factory_.GetWeakPtr()), + base::Bind(&CertVerifyRequest::RunResult, this), out_req_, net_log_); @@ -86,15 +85,14 @@ void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) { if (result != net::ERR_IO_PENDING) { BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(&CertVerifyRequest::RunResult, - weak_ptr_factory_.GetWeakPtr(), + this, result)); return; } BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&CertVerifyRequest::DelegateToDefaultVerifier, - weak_ptr_factory_.GetWeakPtr())); + base::Bind(&CertVerifyRequest::DelegateToDefaultVerifier, this)); } AtomCertVerifier::AtomCertVerifier() diff --git a/atom/browser/atom_cert_verifier.h b/atom/browser/atom_cert_verifier.h index e5560ff82fe4..50446dd38bd2 100644 --- a/atom/browser/atom_cert_verifier.h +++ b/atom/browser/atom_cert_verifier.h @@ -55,8 +55,7 @@ class AtomCertVerifier : public net::CertVerifier { verify_result_(verify_result), out_req_(out_req), net_log_(net_log), - handled_(false), - weak_ptr_factory_(this) { + handled_(false) { } void RunResult(int result); @@ -91,8 +90,6 @@ class AtomCertVerifier : public net::CertVerifier { std::vector callbacks_; bool handled_; - base::WeakPtrFactory weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(CertVerifyRequest); }; From 37f355724a4557e8af4e3d9e62ff5633b16dedfb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 17 Nov 2015 19:03:09 +0800 Subject: [PATCH 532/738] Move AtomCertVerifier to atom/browser/net --- atom/browser/api/atom_api_session.h | 2 +- atom/browser/atom_browser_context.cc | 2 +- atom/browser/{ => net}/atom_cert_verifier.cc | 2 +- atom/browser/{ => net}/atom_cert_verifier.h | 6 +++--- filenames.gypi | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) rename atom/browser/{ => net}/atom_cert_verifier.cc (99%) rename atom/browser/{ => net}/atom_cert_verifier.h (96%) diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 05d67b8842ef..db72558db473 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -8,7 +8,7 @@ #include #include "atom/browser/api/trackable_object.h" -#include "atom/browser/atom_cert_verifier.h" +#include "atom/browser/net/atom_cert_verifier.h" #include "content/public/browser/download_manager.h" #include "native_mate/handle.h" #include "net/base/completion_callback.h" diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index b1092757ae48..ab3ab1bd139e 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -5,10 +5,10 @@ #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" -#include "atom/browser/atom_cert_verifier.h" #include "atom/browser/atom_download_manager_delegate.h" #include "atom/browser/atom_ssl_config_service.h" #include "atom/browser/browser.h" +#include "atom/browser/net/atom_cert_verifier.h" #include "atom/browser/net/atom_url_request_job_factory.h" #include "atom/browser/net/asar/asar_protocol_handler.h" #include "atom/browser/net/http_protocol_handler.h" diff --git a/atom/browser/atom_cert_verifier.cc b/atom/browser/net/atom_cert_verifier.cc similarity index 99% rename from atom/browser/atom_cert_verifier.cc rename to atom/browser/net/atom_cert_verifier.cc index 0ff0d1e4a547..65e558280822 100644 --- a/atom/browser/atom_cert_verifier.cc +++ b/atom/browser/net/atom_cert_verifier.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#include "atom/browser/atom_cert_verifier.h" +#include "atom/browser/net/atom_cert_verifier.h" #include "atom/browser/browser.h" #include "atom/common/native_mate_converters/net_converter.h" diff --git a/atom/browser/atom_cert_verifier.h b/atom/browser/net/atom_cert_verifier.h similarity index 96% rename from atom/browser/atom_cert_verifier.h rename to atom/browser/net/atom_cert_verifier.h index 50446dd38bd2..52b6fb5303e6 100644 --- a/atom/browser/atom_cert_verifier.h +++ b/atom/browser/net/atom_cert_verifier.h @@ -2,8 +2,8 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#ifndef ATOM_BROWSER_ATOM_CERT_VERIFIER_H_ -#define ATOM_BROWSER_ATOM_CERT_VERIFIER_H_ +#ifndef ATOM_BROWSER_NET_ATOM_CERT_VERIFIER_H_ +#define ATOM_BROWSER_NET_ATOM_CERT_VERIFIER_H_ #include #include @@ -159,4 +159,4 @@ class AtomCertVerifier : public net::CertVerifier { } // namespace atom -#endif // ATOM_BROWSER_ATOM_CERT_VERIFIER_H_ +#endif // ATOM_BROWSER_NET_ATOM_CERT_VERIFIER_H_ diff --git a/filenames.gypi b/filenames.gypi index fd8856abd4d0..92e0a2c204fb 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -131,8 +131,6 @@ 'atom/browser/atom_download_manager_delegate.h', 'atom/browser/atom_browser_main_parts.cc', 'atom/browser/atom_browser_main_parts.h', - 'atom/browser/atom_cert_verifier.cc', - 'atom/browser/atom_cert_verifier.h', 'atom/browser/atom_browser_main_parts_mac.mm', 'atom/browser/atom_browser_main_parts_posix.cc', 'atom/browser/atom_javascript_dialog_manager.cc', @@ -175,6 +173,8 @@ 'atom/browser/net/asar/asar_protocol_handler.h', 'atom/browser/net/asar/url_request_asar_job.cc', 'atom/browser/net/asar/url_request_asar_job.h', + 'atom/browser/net/atom_cert_verifier.cc', + 'atom/browser/net/atom_cert_verifier.h', 'atom/browser/net/atom_url_request_job_factory.cc', 'atom/browser/net/atom_url_request_job_factory.h', 'atom/browser/net/http_protocol_handler.cc', From ea1e4160eace08e8fb216af6a6413baaa7577520 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 17 Nov 2015 19:05:38 +0800 Subject: [PATCH 533/738] Move AtomSSLConfigService to atom/browser/net --- atom/browser/atom_browser_context.cc | 2 +- atom/browser/{ => net}/atom_ssl_config_service.cc | 2 +- atom/browser/{ => net}/atom_ssl_config_service.h | 6 +++--- filenames.gypi | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) rename atom/browser/{ => net}/atom_ssl_config_service.cc (97%) rename atom/browser/{ => net}/atom_ssl_config_service.h (76%) diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index ab3ab1bd139e..08c799962728 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -6,9 +6,9 @@ #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/atom_download_manager_delegate.h" -#include "atom/browser/atom_ssl_config_service.h" #include "atom/browser/browser.h" #include "atom/browser/net/atom_cert_verifier.h" +#include "atom/browser/net/atom_ssl_config_service.h" #include "atom/browser/net/atom_url_request_job_factory.h" #include "atom/browser/net/asar/asar_protocol_handler.h" #include "atom/browser/net/http_protocol_handler.h" diff --git a/atom/browser/atom_ssl_config_service.cc b/atom/browser/net/atom_ssl_config_service.cc similarity index 97% rename from atom/browser/atom_ssl_config_service.cc rename to atom/browser/net/atom_ssl_config_service.cc index 0a47067b0a68..2b3143e93cb4 100644 --- a/atom/browser/atom_ssl_config_service.cc +++ b/atom/browser/net/atom_ssl_config_service.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#include "atom/browser/atom_ssl_config_service.h" +#include "atom/browser/net/atom_ssl_config_service.h" #include #include diff --git a/atom/browser/atom_ssl_config_service.h b/atom/browser/net/atom_ssl_config_service.h similarity index 76% rename from atom/browser/atom_ssl_config_service.h rename to atom/browser/net/atom_ssl_config_service.h index 3fa91c62c438..2e3ac4f6c597 100644 --- a/atom/browser/atom_ssl_config_service.h +++ b/atom/browser/net/atom_ssl_config_service.h @@ -2,8 +2,8 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#ifndef ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_ -#define ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_ +#ifndef ATOM_BROWSER_NET_ATOM_SSL_CONFIG_SERVICE_H_ +#define ATOM_BROWSER_NET_ATOM_SSL_CONFIG_SERVICE_H_ #include "net/ssl/ssl_config_service.h" @@ -25,4 +25,4 @@ class AtomSSLConfigService : public net::SSLConfigService { } // namespace atom -#endif // ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_ +#endif // ATOM_BROWSER_NET_ATOM_SSL_CONFIG_SERVICE_H_ diff --git a/filenames.gypi b/filenames.gypi index 92e0a2c204fb..7e1f3e1827e0 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -141,8 +141,6 @@ 'atom/browser/atom_resource_dispatcher_host_delegate.h', 'atom/browser/atom_speech_recognition_manager_delegate.cc', 'atom/browser/atom_speech_recognition_manager_delegate.h', - 'atom/browser/atom_ssl_config_service.cc', - 'atom/browser/atom_ssl_config_service.h', 'atom/browser/bridge_task_runner.cc', 'atom/browser/bridge_task_runner.h', 'atom/browser/browser.cc', @@ -175,6 +173,8 @@ 'atom/browser/net/asar/url_request_asar_job.h', 'atom/browser/net/atom_cert_verifier.cc', 'atom/browser/net/atom_cert_verifier.h', + 'atom/browser/net/atom_ssl_config_service.cc', + 'atom/browser/net/atom_ssl_config_service.h', 'atom/browser/net/atom_url_request_job_factory.cc', 'atom/browser/net/atom_url_request_job_factory.h', 'atom/browser/net/http_protocol_handler.cc', From e3517b701e0f1d18a965cb8f67888baddb8645ce Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 17 Nov 2015 19:44:55 +0800 Subject: [PATCH 534/738] Create a new CertVerifierRequest for each request It greatly simplifies the code. --- atom/browser/api/atom_api_session.cc | 3 +- atom/browser/net/atom_cert_verifier.cc | 129 ++++--------------------- atom/browser/net/atom_cert_verifier.h | 105 ++++++-------------- 3 files changed, 48 insertions(+), 189 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 579b64bf4a7d..3ac36abf5318 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -267,7 +267,7 @@ void Session::RequestCertVerification( bool prevent_default = Emit( "verify-certificate", request->hostname(), - request->certificate(), + make_scoped_refptr(request->cert()), base::Bind(&PassVerificationResult, request)); if (!prevent_default) @@ -294,6 +294,7 @@ bool Session::IsDestroyed() const { } void Session::Destroy() { + browser_context_->cert_verifier()->SetDelegate(nullptr); browser_context_ = nullptr; } diff --git a/atom/browser/net/atom_cert_verifier.cc b/atom/browser/net/atom_cert_verifier.cc index 65e558280822..dcfe29afddad 100644 --- a/atom/browser/net/atom_cert_verifier.cc +++ b/atom/browser/net/atom_cert_verifier.cc @@ -6,74 +6,15 @@ #include "atom/browser/browser.h" #include "atom/common/native_mate_converters/net_converter.h" -#include "base/sha1.h" -#include "base/stl_util.h" #include "content/public/browser/browser_thread.h" #include "net/base/net_errors.h" +#include "net/cert/crl_set.h" +#include "net/cert/x509_certificate.h" using content::BrowserThread; namespace atom { -AtomCertVerifier::RequestParams::RequestParams( - const net::SHA1HashValue cert_fingerprint, - const net::SHA1HashValue ca_fingerprint, - const std::string& hostname_arg, - const std::string& ocsp_response_arg, - int flags_arg) - : hostname(hostname_arg), - ocsp_response(ocsp_response_arg), - flags(flags_arg) { - hash_values.reserve(3); - net::SHA1HashValue ocsp_hash; - base::SHA1HashBytes( - reinterpret_cast(ocsp_response.data()), - ocsp_response.size(), ocsp_hash.data); - hash_values.push_back(ocsp_hash); - hash_values.push_back(cert_fingerprint); - hash_values.push_back(ca_fingerprint); -} - -bool AtomCertVerifier::RequestParams::operator<( - const RequestParams& other) const { - if (flags != other.flags) - return flags < other.flags; - if (hostname != other.hostname) - return hostname < other.hostname; - return std::lexicographical_compare( - hash_values.begin(), - hash_values.end(), - other.hash_values.begin(), - other.hash_values.end(), - net::SHA1HashValueLessThan()); -} - -void AtomCertVerifier::CertVerifyRequest::RunResult(int result) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - for (auto& callback : callbacks_) - callback.Run(result); - cert_verifier_->RemoveRequest(this); -} - -void AtomCertVerifier::CertVerifyRequest::DelegateToDefaultVerifier() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - int rv = cert_verifier_->default_cert_verifier()->Verify( - certificate_.get(), - key_.hostname, - key_.ocsp_response, - key_.flags, - crl_set_.get(), - verify_result_, - base::Bind(&CertVerifyRequest::RunResult, this), - out_req_, - net_log_); - - if (rv != net::ERR_IO_PENDING) - RunResult(rv); -} - void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -84,9 +25,7 @@ void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) { if (result != net::ERR_IO_PENDING) { BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&CertVerifyRequest::RunResult, - this, - result)); + base::Bind(callback_, result)); return; } @@ -95,6 +34,15 @@ void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) { base::Bind(&CertVerifyRequest::DelegateToDefaultVerifier, this)); } +void AtomCertVerifier::CertVerifyRequest::DelegateToDefaultVerifier() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + int result = cert_verifier_->default_cert_verifier_->Verify( + cert_.get(), hostname_, ocsp_response_, flags_, crl_set_.get(), + verify_result_, callback_, out_req_, net_log_); + if (result != net::ERR_IO_PENDING) + callback_.Run(result); +} + AtomCertVerifier::AtomCertVerifier() : delegate_(nullptr) { default_cert_verifier_.reset(net::CertVerifier::CreateDefault()); @@ -118,32 +66,13 @@ int AtomCertVerifier::Verify( if (callback.is_null() || !verify_result || hostname.empty() || !delegate_) return net::ERR_INVALID_ARGUMENT; - const RequestParams key(cert->fingerprint(), - cert->ca_fingerprint(), - hostname, - ocsp_response, - flags); - - CertVerifyRequest* request = FindRequest(key); - - if (!request) { - request = new CertVerifyRequest(this, - key, - cert, - crl_set, - verify_result, - out_req, - net_log); - requests_.insert(make_scoped_refptr(request)); - - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&Delegate::RequestCertVerification, - base::Unretained(delegate_), - make_scoped_refptr(request))); - } - - request->AddCompletionCallback(callback); - + CertVerifyRequest* request = new CertVerifyRequest( + this, cert, hostname, ocsp_response, flags, crl_set, verify_result, + callback, out_req, net_log); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&Delegate::RequestCertVerification, + base::Unretained(delegate_), + make_scoped_refptr(request))); return net::ERR_IO_PENDING; } @@ -151,24 +80,4 @@ bool AtomCertVerifier::SupportsOCSPStapling() { return true; } -AtomCertVerifier::CertVerifyRequest* AtomCertVerifier::FindRequest( - const RequestParams& key) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - auto it = std::lower_bound(requests_.begin(), - requests_.end(), - key, - CertVerifyRequestToRequestParamsComparator()); - if (it != requests_.end() && !(key < (*it)->key())) - return (*it).get(); - return nullptr; -} - -void AtomCertVerifier::RemoveRequest(CertVerifyRequest* request) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - bool erased = requests_.erase(request) == 1; - DCHECK(erased); -} - } // namespace atom diff --git a/atom/browser/net/atom_cert_verifier.h b/atom/browser/net/atom_cert_verifier.h index 52b6fb5303e6..02c2444cd7a4 100644 --- a/atom/browser/net/atom_cert_verifier.h +++ b/atom/browser/net/atom_cert_verifier.h @@ -5,89 +5,64 @@ #ifndef ATOM_BROWSER_NET_ATOM_CERT_VERIFIER_H_ #define ATOM_BROWSER_NET_ATOM_CERT_VERIFIER_H_ -#include #include -#include #include "base/memory/ref_counted.h" -#include "net/base/hash_value.h" #include "net/cert/cert_verifier.h" -#include "net/cert/crl_set.h" -#include "net/cert/x509_certificate.h" -#include "net/log/net_log.h" namespace atom { class AtomCertVerifier : public net::CertVerifier { public: - struct RequestParams { - RequestParams( - const net::SHA1HashValue cert_fingerprint, - const net::SHA1HashValue ca_fingerprint, - const std::string& hostname_arg, - const std::string& ocsp_response, - int flags); - ~RequestParams() {} - - bool operator<(const RequestParams& other) const; - - std::string hostname; - std::string ocsp_response; - int flags; - std::vector hash_values; - }; - class CertVerifyRequest : public base::RefCountedThreadSafe { public: - CertVerifyRequest( - AtomCertVerifier* cert_verifier, - const RequestParams& key, - scoped_refptr cert, - scoped_refptr crl_set, - net::CertVerifyResult* verify_result, - scoped_ptr* out_req, - const net::BoundNetLog& net_log) + CertVerifyRequest(AtomCertVerifier* cert_verifier, + net::X509Certificate* cert, + const std::string& hostname, + const std::string& ocsp_response, + int flags, + net::CRLSet* crl_set, + net::CertVerifyResult* verify_result, + const net::CompletionCallback& callback, + scoped_ptr* out_req, + const net::BoundNetLog& net_log) : cert_verifier_(cert_verifier), - key_(key), - certificate_(cert), + cert_(cert), + hostname_(hostname), + ocsp_response_(ocsp_response), + flags_(flags), crl_set_(crl_set), verify_result_(verify_result), + callback_(callback), out_req_(out_req), net_log_(net_log), handled_(false) { } - void RunResult(int result); - void DelegateToDefaultVerifier(); void ContinueWithResult(int result); - void AddCompletionCallback(net::CompletionCallback callback) { - callbacks_.push_back(callback); - } - - const RequestParams key() const { return key_; } - - std::string hostname() const { return key_.hostname; } - - scoped_refptr certificate() const { - return certificate_; - } + const std::string& hostname() const { return hostname_; } + net::X509Certificate* cert() const { return cert_.get(); } private: friend class base::RefCountedThreadSafe; ~CertVerifyRequest() {} - AtomCertVerifier* cert_verifier_; - const RequestParams key_; + void DelegateToDefaultVerifier(); - scoped_refptr certificate_; + AtomCertVerifier* cert_verifier_; + + scoped_refptr cert_; + std::string hostname_; + std::string ocsp_response_; + int flags_; scoped_refptr crl_set_; net::CertVerifyResult* verify_result_; + net::CompletionCallback callback_; scoped_ptr* out_req_; - const net::BoundNetLog net_log_; + const net::BoundNetLog& net_log_; - std::vector callbacks_; bool handled_; DISALLOW_COPY_AND_ASSIGN(CertVerifyRequest); @@ -95,7 +70,6 @@ class AtomCertVerifier : public net::CertVerifier { class Delegate { public: - Delegate() {} virtual ~Delegate() {} // Called on UI thread. @@ -123,35 +97,10 @@ class AtomCertVerifier : public net::CertVerifier { const net::BoundNetLog& net_log) override; bool SupportsOCSPStapling() override; - net::CertVerifier* default_cert_verifier() const { - return default_cert_verifier_.get(); - } - private: - CertVerifyRequest* FindRequest(const RequestParams& key); - void RemoveRequest(CertVerifyRequest* request); - - struct CertVerifyRequestToRequestParamsComparator { - bool operator()(const scoped_refptr request, - const RequestParams& key) const { - return request->key() < key; - } - }; - - struct CertVerifyRequestComparator { - bool operator()(const scoped_refptr req1, - const scoped_refptr req2) const { - return req1->key() < req2->key(); - } - }; - - using ActiveRequestSet = - std::set, - CertVerifyRequestComparator>; - ActiveRequestSet requests_; + friend class CertVerifyRequest; Delegate* delegate_; - scoped_ptr default_cert_verifier_; DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier); From ebe66daa56c0926d004aa1769ad77e18fd044394 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 17 Nov 2015 21:36:36 +0800 Subject: [PATCH 535/738] Emit verify-certificate only when default verifier fails --- atom/browser/api/atom_api_session.cc | 5 ++- atom/browser/net/atom_cert_verifier.cc | 62 +++++++++++++++----------- atom/browser/net/atom_cert_verifier.h | 51 +++++++-------------- docs/api/session.md | 15 ++++--- 4 files changed, 65 insertions(+), 68 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 3ac36abf5318..c75bf9dd0bcc 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -266,11 +266,12 @@ void Session::RequestCertVerification( const scoped_refptr& request) { bool prevent_default = Emit( "verify-certificate", - request->hostname(), - make_scoped_refptr(request->cert()), + request->args().hostname, + request->args().cert, base::Bind(&PassVerificationResult, request)); if (!prevent_default) + // Tell the request to use the result of default verifier. request->ContinueWithResult(net::ERR_IO_PENDING); } diff --git a/atom/browser/net/atom_cert_verifier.cc b/atom/browser/net/atom_cert_verifier.cc index dcfe29afddad..0f94e4fe2ad2 100644 --- a/atom/browser/net/atom_cert_verifier.cc +++ b/atom/browser/net/atom_cert_verifier.cc @@ -15,6 +15,9 @@ using content::BrowserThread; namespace atom { +AtomCertVerifier::CertVerifyRequest::~CertVerifyRequest() { +} + void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -22,25 +25,10 @@ void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) { return; handled_ = true; - - if (result != net::ERR_IO_PENDING) { - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(callback_, result)); - return; - } - BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&CertVerifyRequest::DelegateToDefaultVerifier, this)); -} - -void AtomCertVerifier::CertVerifyRequest::DelegateToDefaultVerifier() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - int result = cert_verifier_->default_cert_verifier_->Verify( - cert_.get(), hostname_, ocsp_response_, flags_, crl_set_.get(), - verify_result_, callback_, out_req_, net_log_); - if (result != net::ERR_IO_PENDING) - callback_.Run(result); + base::Bind(args_.callback, + result == net::ERR_IO_PENDING ? result_ : result)); } AtomCertVerifier::AtomCertVerifier() @@ -66,18 +54,42 @@ int AtomCertVerifier::Verify( if (callback.is_null() || !verify_result || hostname.empty() || !delegate_) return net::ERR_INVALID_ARGUMENT; - CertVerifyRequest* request = new CertVerifyRequest( - this, cert, hostname, ocsp_response, flags, crl_set, verify_result, - callback, out_req, net_log); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&Delegate::RequestCertVerification, - base::Unretained(delegate_), - make_scoped_refptr(request))); - return net::ERR_IO_PENDING; + VerifyArgs args = { cert, hostname, callback }; + int result = default_cert_verifier_->Verify( + cert, hostname, ocsp_response, flags, crl_set, verify_result, + base::Bind(&AtomCertVerifier::OnDefaultVerificationResult, + base::Unretained(this), args), + out_req, net_log); + if (result != net::OK && result != net::ERR_IO_PENDING) { + // The default verifier fails immediately. + VerifyCertificateFromDelegate(args, result); + return net::ERR_IO_PENDING; + } + + return result; } bool AtomCertVerifier::SupportsOCSPStapling() { return true; } +void AtomCertVerifier::VerifyCertificateFromDelegate( + const VerifyArgs& args, int result) { + CertVerifyRequest* request = new CertVerifyRequest(this, result, args); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&Delegate::RequestCertVerification, + base::Unretained(delegate_), + make_scoped_refptr(request))); +} + +void AtomCertVerifier::OnDefaultVerificationResult( + const VerifyArgs& args, int result) { + if (result == net::OK) { + args.callback.Run(result); + return; + } + + VerifyCertificateFromDelegate(args, result); +} + } // namespace atom diff --git a/atom/browser/net/atom_cert_verifier.h b/atom/browser/net/atom_cert_verifier.h index 02c2444cd7a4..8736db0f8723 100644 --- a/atom/browser/net/atom_cert_verifier.h +++ b/atom/browser/net/atom_cert_verifier.h @@ -14,55 +14,35 @@ namespace atom { class AtomCertVerifier : public net::CertVerifier { public: + struct VerifyArgs { + scoped_refptr cert; + const std::string& hostname; + net::CompletionCallback callback; + }; + class CertVerifyRequest : public base::RefCountedThreadSafe { public: CertVerifyRequest(AtomCertVerifier* cert_verifier, - net::X509Certificate* cert, - const std::string& hostname, - const std::string& ocsp_response, - int flags, - net::CRLSet* crl_set, - net::CertVerifyResult* verify_result, - const net::CompletionCallback& callback, - scoped_ptr* out_req, - const net::BoundNetLog& net_log) + int result, + const VerifyArgs& args) : cert_verifier_(cert_verifier), - cert_(cert), - hostname_(hostname), - ocsp_response_(ocsp_response), - flags_(flags), - crl_set_(crl_set), - verify_result_(verify_result), - callback_(callback), - out_req_(out_req), - net_log_(net_log), + result_(result), + args_(args), handled_(false) { } void ContinueWithResult(int result); - const std::string& hostname() const { return hostname_; } - net::X509Certificate* cert() const { return cert_.get(); } + const VerifyArgs& args() const { return args_; } private: friend class base::RefCountedThreadSafe; - ~CertVerifyRequest() {} - - void DelegateToDefaultVerifier(); + ~CertVerifyRequest(); AtomCertVerifier* cert_verifier_; - - scoped_refptr cert_; - std::string hostname_; - std::string ocsp_response_; - int flags_; - scoped_refptr crl_set_; - net::CertVerifyResult* verify_result_; - net::CompletionCallback callback_; - scoped_ptr* out_req_; - const net::BoundNetLog& net_log_; - + int result_; + VerifyArgs args_; bool handled_; DISALLOW_COPY_AND_ASSIGN(CertVerifyRequest); @@ -100,6 +80,9 @@ class AtomCertVerifier : public net::CertVerifier { private: friend class CertVerifyRequest; + void VerifyCertificateFromDelegate(const VerifyArgs& args, int result); + void OnDefaultVerificationResult(const VerifyArgs& args, int result); + Delegate* delegate_; scoped_ptr default_cert_verifier_; diff --git a/docs/api/session.md b/docs/api/session.md index 210d58753519..cd802f34b20a 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -21,7 +21,7 @@ var session = win.webContents.session * `item` [DownloadItem](download-item.md) * `webContents` [WebContents](web-contents.md) -Fired when Electron is about to download `item` in `webContents`. +Emitted when Electron is about to download `item` in `webContents`. Calling `event.preventDefault()` will cancel the download. @@ -43,18 +43,19 @@ session.on('will-download', function(event, item, webContents) { * `issuerName` String * `callback` Function -Fired whenever a server certificate verification is requested by the -network layer with `hostname`, `certificate` and `callback`. -`callback` should be called with a boolean response to -indicate continuation or cancellation of the request. +Emitted when failed to verify the `certificate` for `hostname`, to trust the +certificate you should prevent the default behavior with +`event.preventDefault()` and call `callback(true)`. ```js session.on('verify-certificate', function(event, hostname, certificate, callback) { if (hostname == "github.com") { - // verification logic + // Verification logic. + event.preventDefault(); callback(true); + } else { + callback(false); } - callback(false); }); ``` From 961ee5a4d914e9195ef731c86d6f3b28295c7590 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 17 Nov 2015 21:41:36 +0800 Subject: [PATCH 536/738] Rename verify-certificate to untrusted-certificate --- atom/browser/api/atom_api_session.cc | 2 +- docs/api/session.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index c75bf9dd0bcc..6527f67ab3f1 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -265,7 +265,7 @@ Session::~Session() { void Session::RequestCertVerification( const scoped_refptr& request) { bool prevent_default = Emit( - "verify-certificate", + "untrusted-certificate", request->args().hostname, request->args().cert, base::Bind(&PassVerificationResult, request)); diff --git a/docs/api/session.md b/docs/api/session.md index cd802f34b20a..e385e222d529 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -34,7 +34,7 @@ session.on('will-download', function(event, item, webContents) { }); ``` -### Event: 'verify-certificate' +### Event: 'untrusted-certificate' * `event` Event * `hostname` String From 247a0a8ae2c5ce6a7c257112d87ad869dd9a2078 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 02:12:40 +0900 Subject: [PATCH 537/738] Add BrowserWindow translation --- docs-translations/ko-KR/README.md | 4 +- docs-translations/ko-KR/api/browser-window.md | 704 ++++++++++++++++++ 2 files changed, 706 insertions(+), 2 deletions(-) create mode 100644 docs-translations/ko-KR/api/browser-window.md diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index b2082b0d2e7a..34826f9d3403 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -32,7 +32,7 @@ * [app](api/app.md) * [autoUpdater](api/auto-updater.md) -* [BrowserWindow (0% 번역됨)](api/browser-window.md) +* [BrowserWindow (20% 번역됨 - 작업중)](api/browser-window.md) * [contentTracing](api/content-tracing.md) * [dialog](api/dialog.md) * [globalShortcut](api/global-shortcut.md) @@ -43,7 +43,7 @@ * [powerSaveBlocker](api/power-save-blocker.md) * [protocol](api/protocol.md) * [session](api/session.md) -* [webContents (0% 번역됨)](api/web-contents.md) +* [webContents](api/web-contents.md) * [Tray](api/tray.md) ### 랜더러 프로세스에서 사용할 수 있는 모듈 (웹 페이지): diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md new file mode 100644 index 000000000000..30165e858519 --- /dev/null +++ b/docs-translations/ko-KR/api/browser-window.md @@ -0,0 +1,704 @@ +# BrowserWindow + +`BrowserWindow` 클래스는 브라우저 창(윈도우 창)을 만드는 역할을 담당합니다. + +다음 예제는 윈도우 창을 생성합니다: + +```javascript +const BrowserWindow = require('electron').BrowserWindow; + +var win = new BrowserWindow({ width: 800, height: 600, show: false }); +win.on('closed', function() { + win = null; +}); + +win.loadURL('https://github.com'); +win.show(); +``` + +또한 [Frameless Window](frameless-window.md) API를 사용하여 창 테두리가 없는 윈도우 창을 생성할 수 있습니다. + +## Class: BrowserWindow + +`BrowserWindow`는 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속받은 클래스 입니다. + +`BrowserWindow`는 `options`를 통해 네이티브 속성을 포함한 새로운 윈도우 창을 생성합니다. + +### `new BrowserWindow(options)` + +`options` 객체에서 사용할 수 있는 속성들: + +* `width` Integer - 윈도우 창의 가로 너비. +* `height` Integer - 윈도우 창의 세로 높이. +* `x` Integer - 화면을 기준으로 창 좌측을 오프셋 한 위치. +* `y` Integer - 화면을 기준으로 창 상단을 오프셋 한 위치. +* `useContentSize` Boolean - `width`와 `height`를 웹 페이지의 크기로 사용합니다. + 이 속성을 사용하면 웹 페이지의 크기에 윈도우 프레임 크기가 추가되므로 실제 창은 조금 더 커질 수 있습니다. +* `center` Boolean - 윈도우 창을 화면 정 중앙에 위치시킵니다. +* `minWidth` Integer - 윈도우 창의 최소 가로 너비. +* `minHeight` Integer - 윈도우 창의 최소 세로 높이. +* `maxWidth` Integer - 윈도우 창의 최대 가로 너비. +* `maxHeight` Integer - 윈도우 창의 최대 세로 높이. +* `resizable` Boolean - 윈도우 창의 크기를 재조정 할 수 있는지 여부. +* `alwaysOnTop` Boolean - 윈도우 창이 언제나 다른 창들 위에 유지되는지 여부. +* `fullscreen` Boolean - 윈도우 창의 전체화면 활성화 여부. + `false`로 지정했을 경우 OS X에선 전체화면 버튼이 숨겨지거나 비활성화됩니다. +* `skipTaskbar` Boolean - 작업 표시줄 어플리케이션 아이콘 표시 여부. +* `kiosk` Boolean - Kiosk(키오스크) 모드. +* `title` String - 기본 윈도우 창 제목. +* `icon` [NativeImage](native-image.md) - 윈도우 아이콘, 생략하면 실행 파일의 아이콘이 대신 사용됩니다. +* `show` Boolean - 윈도우가 생성되면 보여줄지 여부. +* `frame` Boolean - `false`로 지정하면 창을 [Frameless Window](frameless-window.md) 형태로 생성합니다. +* `acceptFirstMouse` Boolean - 윈도우가 비활성화 상태일 때 내부 컨텐츠 클릭 시 활성화 되는 동시에 단일 mouse-down 이벤트를 발생시킬지 여부. +* `disableAutoHideCursor` Boolean - 파이핑중 자동으로 커서를 숨길지 여부. +* `autoHideMenuBar` Boolean - `Alt`를 누르지 않는 한 어플리케이션 메뉴바를 숨길지 여부. +* `enableLargerThanScreen` Boolean - 윈도우 창 크기가 화면 크기보다 크게 재조정 될 수 있는지 여부. +* `backgroundColor` String - 16진수로 표현된 윈도우의 배경 색. `#66CD00` 또는 `#FFF`가 사용될 수 있습니다. + 이 속성은 Linux와 Windows에만 구현되어 있습니다. +* `darkTheme` Boolean - 설정에 상관 없이 무조건 어두운 윈도우 테마를 사용합니다. 몇몇 GTK+3 데스크톱 환경에서만 작동합니다. +* `transparent` Boolean - 윈도우 창을 [투명화](frameless-window.md)합니다. +* `type` String - 윈도우 창 종류를 지정합니다. + 사용할 수 있는 창 종류는 `desktop`, `dock`, `toolbar`, `splash`, `notification`와 같습니다. + 이 속성은 Linux에서만 작동합니다. +* `standardWindow` Boolean - OS X의 표준 윈도우를 텍스쳐 윈도우 대신 사용합니다. 기본 값은 `true`입니다. +* `titleBarStyle` String, OS X - 윈도우 타이틀 바 스타일을 지정합니다. 이 속성은 OS X 10.10 Yosemite 이후 버전만 지원합니다. + 다음 3가지 종류의 값을 사용할 수 있습니다: + * `default` 또는 미지정: 표준 Mac 회색 불투명 스타일을 사용합니다. + * `hidden`: 타이틀 바를 숨기고 컨텐츠 전체를 윈도우 크기에 맞춥니다. + 타이틀 바는 없어지지만 표준 창 컨트롤 ("신호등 버튼")은 왼쪽 상단에 유지됩니다. + * `hidden-inset`: `hidden` 타이틀 바 속성과 함께 신호등 버튼이 윈도우 모서리로부터 약간 더 안쪽으로 들어가도록합니다. +* `webPreferences` Object - 웹 페이지 기능을 설정합니다. 사용할 수 있는 속성은 다음과 같습니다: + * `nodeIntegration` Boolean - node(node.js) 통합 여부. 기본값은 `true`입니다. + * `preload` String - 스크립트를 지정하면 페이지 내의 다른 스크립트가 작동하기 전에 로드됩니다. + 여기서 지정한 스크립트는 페이지의 node 통합 활성화 여부에 상관없이 언제나 모든 node API에 접근할 수 있습니다. + 그리고 `preload` 스크립트의 경로는 절대 경로로 지정해야 합니다. + * `partition` String - 페이지에서 사용할 세션을 지정합니다. 만약 `partition`이 + `persist:`로 시작하면 페이지는 지속성 세션을 사용하며 다른 모든 앱 내의 페이지에서 같은 `partition`을 사용할 수 있습니다. + 만약 `persist:` 접두어로 시작하지 않으면 페이지는 인-메모리 세션을 사용합니다. 여러 페이지에서 같은 `partition`을 지정하면 + 같은 세션을 공유할 수 있습니다. `partition`을 지정하지 않으면 어플리케이션의 기본 세션이 사용됩니다. + * `zoomFactor` Number - 페이지의 기본 줌 값을 지정합니다. 예를 들어 `300%`를 표현하려면 `3.0`으로 지정합니다. + * `javascript` Boolean + * `webSecurity` Boolean - `false`로 지정하면 same-origin 정책을 비활성화합니다. (이 속성은 보통 사람에 의해 웹 사이트를 테스트할 때 사용합니다) + 그리고 `allowDisplayingInsecureContent`와 `allowRunningInsecureContent`이 사용자로부터 `true`로 지정되지 않은 경우 `true`로 지정합니다. + * `allowDisplayingInsecureContent` Boolean - https 페이지에서 http URL에서 로드한 이미지 같은 리소스를 표시할 수 있도록 허용합니다. + * `allowRunningInsecureContent` Boolean - https 페이지에서 http URL에서 로드한 JavaScript와 CSS 또는 플러그인을 실행시킬 수 있도록 허용합니다. + * `images` Boolean + * `java` Boolean + * `textAreasAreResizable` Boolean + * `webgl` Boolean + * `webaudio` Boolean + * `plugins` Boolean - 어떤 플러그인이 활성화되어야 하는지 지정합니다. + * `experimentalFeatures` Boolean + * `experimentalCanvasFeatures` Boolean + * `overlayScrollbars` Boolean + * `overlayFullscreenVideo` Boolean + * `sharedWorker` Boolean + * `directWrite` Boolean - Windows에서 폰트 랜더링을 위해 DirectWrite를 사용하는지를 지정합니다. + * `pageVisibility` Boolean - 현재 윈도우의 가시성을 반영하는 대신 페이지가 visible 또는 hidden 중 지정된 상태를 계속 유지하도록 합니다. + 이 속성을 `true`로 지정하면 DOM 타이머의 스로틀링을 방지할 수 있습니다. + +## Events + +`BrowserWindow` 객체는 다음과 같은 이벤트를 발생시킵니다: + +**참고:** 몇몇 이벤트는 라벨에 특정한 OS에서만 작동합니다. + +### Event: 'page-title-updated' + +Returns: + +* `event` Event + +문서의 제목이 변경될 때 발생하는 이벤트 입니다. +`event.preventDefault()`를 호출하여 네이티브 윈도우의 제목이 변경되는 것을 방지할 수 있습니다. + +### Event: 'close' + +Returns: + +* `event` Event + +Emitted when the window is going to be closed. It's emitted before the +`beforeunload` and `unload` event of the DOM. Calling `event.preventDefault()` +will cancel the close. + +Usually you would want to use the `beforeunload` handler to decide whether the +window should be closed, which will also be called when the window is +reloaded. In Electron, returning an empty string or `false` would cancel the +close. For example: + +```javascript +window.onbeforeunload = function(e) { + console.log('I do not want to be closed'); + + // Unlike usual browsers, in which a string should be returned and the user is + // prompted to confirm the page unload, Electron gives developers more options. + // Returning empty string or false would prevent the unloading now. + // You can also use the dialog API to let the user confirm closing the application. + e.returnValue = false; +}; +``` + +### Event: 'closed' + +Emitted when the window is closed. After you have received this event you should +remove the reference to the window and avoid using it anymore. + +### Event: 'unresponsive' + +Emitted when the web page becomes unresponsive. + +### Event: 'responsive' + +Emitted when the unresponsive web page becomes responsive again. + +### Event: 'blur' + +Emitted when the window loses focus. + +### Event: 'focus' + +Emitted when the window gains focus. + +### Event: 'maximize' + +Emitted when window is maximized. + +### Event: 'unmaximize' + +Emitted when the window exits from maximized state. + +### Event: 'minimize' + +Emitted when the window is minimized. + +### Event: 'restore' + +Emitted when the window is restored from minimized state. + +### Event: 'resize' + +Emitted when the window is getting resized. + +### Event: 'move' + +Emitted when the window is getting moved to a new position. + +__Note__: On OS X this event is just an alias of `moved`. + +### Event: 'moved' _OS X_ + +Emitted once when the window is moved to a new position. + +### Event: 'enter-full-screen' + +Emitted when the window enters full screen state. + +### Event: 'leave-full-screen' + +Emitted when the window leaves full screen state. + +### Event: 'enter-html-full-screen' + +Emitted when the window enters full screen state triggered by html api. + +### Event: 'leave-html-full-screen' + +Emitted when the window leaves full screen state triggered by html api. + +### Event: 'app-command': + +Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) +is invoked. These are typically related to keyboard media keys or browser +commands, as well as the "Back" button built into some mice on Windows. + +```js +someWindow.on('app-command', function(e, cmd) { + // Navigate the window back when the user hits their mouse back button + if (cmd === 'browser-backward' && someWindow.webContents.canGoBack()) { + someWindow.webContents.goBack(); + } +}); +``` + +## Methods + +`BrowserWindow` 객체는 다음과 같은 메서드를 가지고 있습니다: + +### `BrowserWindow.getAllWindows()` + +Returns an array of all opened browser windows. + +### `BrowserWindow.getFocusedWindow()` + +Returns the window that is focused in this application. + +### `BrowserWindow.fromWebContents(webContents)` + +* `webContents` [WebContents](web-contents.md) + +Find a window according to the `webContents` it owns. + +### `BrowserWindow.fromId(id)` + +* `id` Integer + +Find a window according to its ID. + +### `BrowserWindow.addDevToolsExtension(path)` + +* `path` String + +Adds DevTools extension located at `path`, and returns extension's name. + +The extension will be remembered so you only need to call this API once, this +API is not for programming use. + +### `BrowserWindow.removeDevToolsExtension(name)` + +* `name` String + +Remove the DevTools extension whose name is `name`. + +## Instance Properties + +Objects created with `new BrowserWindow` have the following properties: + +```javascript +// In this example `win` is our instance +var win = new BrowserWindow({ width: 800, height: 600 }); +``` + +### `win.webContents` + +The `WebContents` object this window owns, all web page related events and +operations will be done via it. + +See the [`webContents` documentation](web-contents.md) for its methods and +events. + +### `win.id` + +The unique ID of this window. + +## Instance Methods + +Objects created with `new BrowserWindow` have the following instance methods: + +**Note:** Some methods are only available on specific operating systems and are labeled as such. + +### `win.destroy()` + +Force closing the window, the `unload` and `beforeunload` event won't be emitted +for the web page, and `close` event will also not be emitted +for this window, but it guarantees the `closed` event will be emitted. + +You should only use this method when the renderer process (web page) has +crashed. + +### `win.close()` + +Try to close the window, this has the same effect with user manually clicking +the close button of the window. The web page may cancel the close though, see +the [close event](#event-close). + +### `win.focus()` + +Focus on the window. + +### `win.isFocused()` + +Returns a boolean, whether the window is focused. + +### `win.show()` + +Shows and gives focus to the window. + +### `win.showInactive()` + +Shows the window but doesn't focus on it. + +### `win.hide()` + +Hides the window. + +### `win.isVisible()` + +Returns a boolean, whether the window is visible to the user. + +### `win.maximize()` + +Maximizes the window. + +### `win.unmaximize()` + +Unmaximizes the window. + +### `win.isMaximized()` + +Returns a boolean, whether the window is maximized. + +### `win.minimize()` + +Minimizes the window. On some platforms the minimized window will be shown in +the Dock. + +### `win.restore()` + +Restores the window from minimized state to its previous state. + +### `win.isMinimized()` + +Returns a boolean, whether the window is minimized. + +### `win.setFullScreen(flag)` + +* `flag` Boolean + +Sets whether the window should be in fullscreen mode. + +### `win.isFullScreen()` + +Returns a boolean, whether the window is in fullscreen mode. + +### `win.setAspectRatio(aspectRatio[, extraSize])` _OS X_ + +* `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: + * `width` Integer + * `height` Integer + +This will have a window maintain an aspect ratio. The extra size allows a +developer to have space, specified in pixels, not included within the aspect +ratio calculations. This API already takes into account the difference between a +window's size and its content size. + +Consider a normal window with an HD video player and associated controls. +Perhaps there are 15 pixels of controls on the left edge, 25 pixels of controls +on the right edge and 50 pixels of controls below the player. In order to +maintain a 16:9 aspect ratio (standard aspect ratio for HD @1920x1080) within +the player itself we would call this function with arguments of 16/9 and +[ 40, 50 ]. The second argument doesn't care where the extra width and height +are within the content view--only that they exist. Just sum any extra width and +height areas you have within the overall content view. + +### `win.setBounds(options)` + +`options` Object, properties: + +* `x` Integer +* `y` Integer +* `width` Integer +* `height` Integer + +Resizes and moves the window to `width`, `height`, `x`, `y`. + +### `win.getBounds()` + +Returns an object that contains window's width, height, x and y values. + +### `win.setSize(width, height)` + +* `width` Integer +* `height` Integer + +Resizes the window to `width` and `height`. + +### `win.getSize()` + +Returns an array that contains window's width and height. + +### `win.setContentSize(width, height)` + +* `width` Integer +* `height` Integer + +Resizes the window's client area (e.g. the web page) to `width` and `height`. + +### `win.getContentSize()` + +Returns an array that contains window's client area's width and height. + +### `win.setMinimumSize(width, height)` + +* `width` Integer +* `height` Integer + +Sets the minimum size of window to `width` and `height`. + +### `win.getMinimumSize()` + +Returns an array that contains window's minimum width and height. + +### `win.setMaximumSize(width, height)` + +* `width` Integer +* `height` Integer + +Sets the maximum size of window to `width` and `height`. + +### `win.getMaximumSize()` + +Returns an array that contains window's maximum width and height. + +### `win.setResizable(resizable)` + +* `resizable` Boolean + +Sets whether the window can be manually resized by user. + +### `win.isResizable()` + +Returns whether the window can be manually resized by user. + +### `win.setAlwaysOnTop(flag)` + +* `flag` Boolean + +Sets whether the window should show always on top of other windows. After +setting this, the window is still a normal window, not a toolbox window which +can not be focused on. + +### `win.isAlwaysOnTop()` + +Returns whether the window is always on top of other windows. + +### `win.center()` + +Moves window to the center of the screen. + +### `win.setPosition(x, y)` + +* `x` Integer +* `y` Integer + +Moves window to `x` and `y`. + +### `win.getPosition()` + +Returns an array that contains window's current position. + +### `win.setTitle(title)` + +* `title` String + +Changes the title of native window to `title`. + +### `win.getTitle()` + +Returns the title of the native window. + +**Note:** The title of web page can be different from the title of the native +window. + +### `win.flashFrame(flag)` + +* `flag` Boolean + +Starts or stops flashing the window to attract user's attention. + +### `win.setSkipTaskbar(skip)` + +* `skip` Boolean + +Makes the window not show in the taskbar. + +### `win.setKiosk(flag)` + +* `flag` Boolean + +Enters or leaves the kiosk mode. + +### `win.isKiosk()` + +Returns whether the window is in kiosk mode. + +### `win.hookWindowMessage(message, callback)` _WINDOWS_ + +* `message` Integer +* `callback` Function + +Hooks a windows message. The `callback` is called when +the message is received in the WndProc. + +### `win.isWindowMessageHooked(message)` _WINDOWS_ + +* `message` Integer + +Returns `true` or `false` depending on whether the message is hooked. + +### `win.unhookWindowMessage(message)` _WINDOWS_ + +* `message` Integer + +Unhook the window message. + +### `win.unhookAllWindowMessages()` _WINDOWS_ + +Unhooks all of the window messages. + +### `win.setRepresentedFilename(filename)` _OS X_ + +* `filename` String + +Sets the pathname of the file the window represents, and the icon of the file +will show in window's title bar. + +### `win.getRepresentedFilename()` _OS X_ + +Returns the pathname of the file the window represents. + +### `win.setDocumentEdited(edited)` _OS X_ + +* `edited` Boolean + +Specifies whether the window’s document has been edited, and the icon in title +bar will become grey when set to `true`. + +### `win.isDocumentEdited()` _OS X_ + +Whether the window's document has been edited. + +### `win.focusOnWebView()` + +### `win.blurWebView()` + +### `win.capturePage([rect, ]callback)` + +* `rect` Object (optional)- The area of page to be captured, properties: + * `x` Integer + * `y` Integer + * `width` Integer + * `height` Integer +* `callback` Function + +Captures a snapshot of the page within `rect`. Upon completion `callback` will +be called with `callback(image)`. The `image` is an instance of +[NativeImage](native-image.md) that stores data of the snapshot. Omitting +`rect` will capture the whole visible page. + +### `win.print([options])` + +Same as `webContents.print([options])` + +### `win.printToPDF(options, callback)` + +Same as `webContents.printToPDF(options, callback)` + +### `win.loadURL(url[, options])` + +Same as `webContents.loadURL(url[, options])`. + +### `win.reload()` + +Same as `webContents.reload`. + +### `win.setMenu(menu)` _Linux_ _Windows_ + +* `menu` Menu + +Sets the `menu` as the window's menu bar, setting it to `null` will remove the +menu bar. + +### `win.setProgressBar(progress)` + +* `progress` Double + +Sets progress value in progress bar. Valid range is [0, 1.0]. + +Remove progress bar when progress < 0; +Change to indeterminate mode when progress > 1. + +On Linux platform, only supports Unity desktop environment, you need to specify +the `*.desktop` file name to `desktopName` field in `package.json`. By default, +it will assume `app.getName().desktop`. + +### `win.setOverlayIcon(overlay, description)` _Windows 7+_ + +* `overlay` [NativeImage](native-image.md) - the icon to display on the bottom +right corner of the taskbar icon. If this parameter is `null`, the overlay is +cleared +* `description` String - a description that will be provided to Accessibility +screen readers + +Sets a 16px overlay onto the current taskbar icon, usually used to convey some +sort of application status or to passively notify the user. + + +### `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 + +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 +whether the thumbnail has been added successfully. + +The number of buttons in thumbnail toolbar should be no greater than 7 due to +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. + +### `win.showDefinitionForSelection()` _OS X_ + +Shows pop-up dictionary that searches the selected word on the page. + +### `win.setAutoHideMenuBar(hide)` + +* `hide` Boolean + +Sets whether the window menu bar should hide itself automatically. Once set the +menu bar will only show when users press the single `Alt` key. + +If the menu bar is already visible, calling `setAutoHideMenuBar(true)` won't +hide it immediately. + +### `win.isMenuBarAutoHide()` + +Returns whether menu bar automatically hides itself. + +### `win.setMenuBarVisibility(visible)` + +* `visible` Boolean + +Sets whether the menu bar should be visible. If the menu bar is auto-hide, users +can still bring up the menu bar by pressing the single `Alt` key. + +### `win.isMenuBarVisible()` + +Returns whether the menu bar is visible. + +### `win.setVisibleOnAllWorkspaces(visible)` + +* `visible` Boolean + +Sets whether the window should be visible on all workspaces. + +**Note:** This API does nothing on Windows. + +### `win.isVisibleOnAllWorkspaces()` + +Returns whether the window is visible on all workspaces. + +**Note:** This API always returns false on Windows. From b4eca40d07fbbe7165c8623b268144349e159814 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 03:09:51 +0900 Subject: [PATCH 538/738] Improve grammar * Improve grammar * Standardize docs * Fix typos --- docs-translations/ko-KR/README.md | 2 +- .../ko-KR/api/chrome-command-line-switches.md | 2 +- docs-translations/ko-KR/api/menu-item.md | 29 ++-- docs-translations/ko-KR/api/web-contents.md | 136 +++++++++--------- docs-translations/ko-KR/api/web-view-tag.md | 8 +- .../ko-KR/tutorial/debugging-main-process.md | 2 +- .../ko-KR/tutorial/devtools-extension.md | 10 +- .../ko-KR/tutorial/quick-start.md | 2 +- 8 files changed, 95 insertions(+), 96 deletions(-) diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index 34826f9d3403..39b9367d0ecf 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -7,7 +7,7 @@ * [네이티브 Node 모듈 사용하기](tutorial/using-native-node-modules.md) * [메인 프로세스 디버깅하기](tutorial/debugging-main-process.md) * [Selenium 과 WebDriver 사용하기](tutorial/using-selenium-and-webdriver.md) -* [개발자 콘솔 확장기능](tutorial/devtools-extension.md) +* [개발자 도구 확장 기능](tutorial/devtools-extension.md) * [Pepper 플래시 플러그인 사용하기](tutorial/using-pepper-flash-plugin.md) ## 튜토리얼 diff --git a/docs-translations/ko-KR/api/chrome-command-line-switches.md b/docs-translations/ko-KR/api/chrome-command-line-switches.md index 216d402c41e9..d3aa5dd6411b 100644 --- a/docs-translations/ko-KR/api/chrome-command-line-switches.md +++ b/docs-translations/ko-KR/api/chrome-command-line-switches.md @@ -28,7 +28,7 @@ HTTP 요청 캐시를 비활성화 합니다. ## --remote-debugging-port=`port` -지정한 `port`에 HTTP 기반의 리모트 디버거를 활성화 시킵니다. (개발자 콘솔) +지정한 `port`에 HTTP 기반의 리모트 디버거를 활성화 시킵니다. (개발자 도구) ## --js-flags=`flags` diff --git a/docs-translations/ko-KR/api/menu-item.md b/docs-translations/ko-KR/api/menu-item.md index fc5539c8cdf1..b17d3b9ec391 100644 --- a/docs-translations/ko-KR/api/menu-item.md +++ b/docs-translations/ko-KR/api/menu-item.md @@ -1,6 +1,6 @@ # MenuItem -`menu-item` 모듈은 어플리케이션 또는 컨텍스트 [`menu`](menu.md)에 아이템을 추가할 수 있도록 관련 클래스를 제공합니다. +`menu-item` 모듈은 어플리케이션 또는 컨텍스트 [`menu`](menu.md)에 항목 아이템을 추가할 수 있도록 관련 클래스를 제공합니다. [`menu`](menu.md)에서 예제를 확인할 수 있습니다. @@ -25,10 +25,9 @@ * `id` String - 현재 메뉴 아이템에 대해 유일키를 지정합니다. 이 키는 이후 `position` 옵션에서 사용할 수 있습니다. * `position` String - 미리 지정한 `id`를 이용하여 메뉴 아이템의 위치를 세밀하게 조정합니다. -메뉴 아이템을 생성할 때, 매칭되는 액션이 있다면 수동으로 직접 구현하는 대신 `role`을 설정하여, -고유 OS 경험을 최대한 살릴 것을 권장합니다. +메뉴 아이템을 생성할 때, 다음 목록과 일치하는 표준 동작은 수동으로 직접 구현하는 대신 `role` 속성을 지정하여 고유 OS 경험을 최대한 살릴 수 있습니다. -`role` 속성은 다음 값을 가질 수 있습니다.: +`role` 속성은 다음 값을 가질 수 있습니다: * `undo` * `redo` @@ -36,16 +35,16 @@ * `copy` * `paste` * `selectall` -* `minimize` - 현재 윈도우를 최소화 합니다. -* `close` - 현재 윈도우를 닫습니다. +* `minimize` - 현재 윈도우를 최소화합니다 +* `close` - 현재 윈도우를 닫습니다 -OS X에서 `role`은 다음 값을 추가로 가질 수 있습니다. +OS X에서의 `role`은 다음 값을 추가로 가질 수 있습니다: -* `about` - `orderFrontStandardAboutPanel` 액션에 매핑합니다. -* `hide` - `hide` 액션에 매핑합니다. -* `hideothers` - `hideOtherApplications` 액션에 매핑합니다. -* `unhide` - `unhideAllApplications` 액션에 매핑합니다. -* `front` - `arrangeInFront` 액션에 매핑합니다. -* `window` - 부메뉴가 "Window" 메뉴입니다. -* `help` - 부메뉴가 "Help" 메뉴입니다. -* `services` - 부메뉴가 "Services" 메뉴입니다. +* `about` - 매핑된 `orderFrontStandardAboutPanel` 액션 +* `hide` - 매핑된 `hide` 액션 +* `hideothers` - 매핑된 `hideOtherApplications` 액션 +* `unhide` - 매핑된 `unhideAllApplications` 액션 +* `front` - 매핑된 `arrangeInFront` 액션 +* `window` - 부 메뉴를 가지는 "Window" 메뉴 +* `help` - 부 메뉴를 가지는 "Help" 메뉴 +* `services` - 부 메뉴를 가지는 "Services" 메뉴 diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index 355e019e9c9b..89c5a4a767f0 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -1,9 +1,8 @@ # webContents -`webContents`는 -[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)입니다. +`webContents`는 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속받았습니다. -웹페이지의 렌더링과 관리를 책임지며 [`BrowserWindow`](browser-window.md)의 속성입니다. 다음은 `webContents` 객체를 접근하는 예입니다: +웹 페이지의 렌더링과 관리를 책임지며 [`BrowserWindow`](browser-window.md)의 속성입니다. 다음은 `webContents` 객체에 접근하는 예제입니다: ```javascript const BrowserWindow = require('electron').BrowserWindow; @@ -20,7 +19,7 @@ var webContents = win.webContents; ### Event: 'did-finish-load' -네비게이션이 끝났을 때 발생하는 이벤트입니다. 즉, 탭의 스피너가 멈추고 `onload` 이벤트가 발생했을 때를 얘기합니다. +탐색 작업이 끝났을 때 발생하는 이벤트입니다. 브라우저의 탭의 스피너가 멈추고 `onload` 이벤트가 발생했을 때를 말합니다. ### Event: 'did-fail-load' @@ -31,8 +30,8 @@ Returns: * `errorDescription` String * `validatedURL` String -이 이벤트는 `did-finish-load`와 비슷하나, 로드가 실패했거나 취소되었을 때도 발생합니다. 예를들면 `window.stop()`이 실행되었을 때 발생합니다. -모든 에러 코드들의 목록과 설명은 [여기](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h)서 확인 가능합니다. +이 이벤트는 `did-finish-load`와 비슷하나, 로드가 실패했거나 취소되었을 때 발생합니다. 예를 들면 `window.stop()`이 실행되었을 때 발생합니다. +발생할 수 있는 전체 에러 코드의 목록과 설명은 [여기](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h)서 확인할 수 있습니다. ### Event: 'did-frame-finish-load' @@ -41,15 +40,15 @@ Returns: * `event` Event * `isMainFrame` Boolean -프레임(Frame)이 네비게이션을 끝냈을 때 발생하는 이벤트입니다. +프레임(Frame)이 탐색을 끝냈을 때 발생하는 이벤트입니다. ### Event: 'did-start-loading' -탭의 스피너가 회전을 시작한 시점과 같습니다. +브라우저 탭의 스피너가 회전을 시작한 때와 같은 시점에 대응하는 이벤트입니다. ### Event: 'did-stop-loading' -탭의 스피너가 회전을 멈추었을 떄의 시점과 같습니다. +브라우저 탭의 스피너가 회전을 멈추었을 때와 같은 시점에 대응하는 이벤트입니다. ### Event: 'did-get-response-details' @@ -64,7 +63,7 @@ Returns: * `referrer` String * `headers` Object -요청한 리소스의 정보가 존재할 때 발생하는 이벤트입니다. +요청한 리소스에 관련된 자세한 정보를 사용할 수 있을 때 발생하는 이벤트입니다. `status`는 리소스를 다운로드하기 위한 소켓 연결을 나타냅니다. ### Event: 'did-get-redirect-request' @@ -80,7 +79,7 @@ Returns: * `referrer` String * `headers` Object -리소스를 요청할 때 리다이렉트 응답을 받았을 때 발생하는 이벤트입니다. +리소스를 요청하는 동안에 리다이렉트 응답을 받았을 때 발생하는 이벤트입니다. ### Event: 'dom-ready' @@ -95,9 +94,9 @@ Returns: Returns: * `event` Event -* `favicons` Array - Array of URLs +* `favicons` Array - URL 배열 -페이지가 favicon을 받았을 때 발생하는 이벤트입니다. +페이지가 favicon(파비콘) URL을 받았을 때 발생하는 이벤트입니다. ### Event: 'new-window' @@ -108,14 +107,14 @@ Returns: * `frameName` String * `disposition` String - `default`, `foreground-tab`, `background-tab`, `new-window`, `other`중 하나일 수 있습니다. -* `options` Object - 새로운 `BrowserWindow`를 만들 때 사용되는 옵션들입니다. +* `options` Object - 새로운 `BrowserWindow` 객체를 만들 때 사용되는 옵션 객체입니다. 페이지가 `url`에 대하여 새로운 윈도우를 열기위해 요청한 경우 발생하는 이벤트입니다. -`window.open`이나 ``과 같은 외부 링크 등에 의해 요청될 수 있습니다. +`window.open`이나 ``과 같은 외부 링크에 의해 요청될 수 있습니다. -기본값으로 `BrowserWindow`는 `url`로 생성됩니다. +기본값으로 `BrowserWindow`는 `url`을 기반으로 생성됩니다. -`event.preventDefault()`를 호출하면 새로운 창을 만드는 것을 방지할 수 있습니다. +`event.preventDefault()`를 호출하면 새로운 창이 생성되는 것을 방지할 수 있습니다. ### Event: 'will-navigate' @@ -124,13 +123,13 @@ Returns: * `event` Event * `url` String -사용자 또는 페이지가 새로운 네비게이션을 원할 때 발생하는 이벤트입니다. +사용자 또는 페이지가 새로운 페이지로 이동할 때 발생하는 이벤트입니다. `window.location` 객체가 변경되거나 사용자가 페이지의 링크를 클릭했을 때 발생합니다. 이 이벤트는 `webContents.loadURL`과 `webContents.back` 같은 API를 이용하여 프로그램적으로 -시작된 네비게이션에 대해서는 발생하지 않습니다. +시작된 탐색에 대해서는 발생하지 않습니다. -`event.preventDefault()`를 호출하면 네비게이션을 방지할 수 있습니다. +`event.preventDefault()`를 호출하면 탐색을 방지할 수 있습니다. ### Event: 'crashed' @@ -152,15 +151,15 @@ Returns: ### Event: 'devtools-opened' -DevTools가 열렸을 때 발생되는 이벤트입니다. +개발자 도구가 열렸을 때 발생되는 이벤트입니다. ### Event: 'devtools-closed' -DevTools가 닫혔을 때 발생되는 이벤트입니다. +개발자 도구가 닫혔을 때 발생되는 이벤트입니다. ### Event: 'devtools-focused' -DevTools에 포커스가 가거나 DevTools가 열렸을 때 발생되는 이벤트입니다. +개발자 도구에 포커스가 가거나 개발자 도구가 열렸을 때 발생되는 이벤트입니다. ### Event: 'login' @@ -185,13 +184,13 @@ Returns: ## Instance Methods -`webContents`객체는 다음과 같은 인스턴스 메소드들을 가지고 있습니다. +`webContents`객체는 다음과 같은 인스턴스 메서드들을 가지고 있습니다. ### `webContents.session` webContents에서 사용되는 `session`객체를 반환합니다. -[session 문서](session.md)에서 이 객체의 메소드들을 확인할 수 있습니다. +[session](session.md) 문서에서 이 객체의 메서드들을 확인할 수 있습니다. ### `webContents.loadURL(url[, options])` @@ -229,7 +228,7 @@ var currentURL = win.webContents.getURL(); ### `webContents.stop()` -대기중인 네비게이션들을 모두 멈춥니다. +대기중인 탐색 작업을 모두 멈춥니다. ### `webContents.reload()` @@ -237,11 +236,11 @@ var currentURL = win.webContents.getURL(); ### `webContents.reloadIgnoringCache()` -현재 페이지를 캐시를 무시한채로 새로고침합니다. +현재 웹 페이지의 캐시를 무시한 채로 새로고침합니다. ### `webContents.canGoBack()` -브라우저가 이전의 웹 페이지로 돌아갈 수 있는지 여부를 반환합니다. +브라우저가 이전 웹 페이지로 돌아갈 수 있는지 여부를 반환합니다. ### `webContents.canGoForward()` @@ -255,7 +254,7 @@ var currentURL = win.webContents.getURL(); ### `webContents.clearHistory()` -네비게이션 기록을 삭제합니다. +탐색 기록을 삭제합니다. ### `webContents.goBack()` @@ -269,13 +268,13 @@ var currentURL = win.webContents.getURL(); * `index` Integer -브라우저가 지정된 절대 웹 페이지 인덱스로 네비게이트하게 합니다. +브라우저가 지정된 절대 웹 페이지 인덱스로 탐색하게 합니다. ### `webContents.goToOffset(offset)` * `offset` Integer -"current entry"에서 지정된 offset으로 네비게이트 합니다. +"current entry"에서 지정된 offset으로 탐색합니다. ### `webContents.isCrashed()` @@ -285,27 +284,27 @@ var currentURL = win.webContents.getURL(); * `userAgent` String -현재의 웹 페이지의 유저 에이전트를 오버라이드 합니다. +현재 웹 페이지의 유저 에이전트를 덮어씌웁니다. ### `webContents.getUserAgent()` -현재 웹 페이지의 유저 에이전트 `String`을 반환합니다. +현재 웹 페이지의 유저 에이전트 문자열을 반환합니다. ### `webContents.insertCSS(css)` * `css` String -Injects CSS into the current web page. +CSS 코드를 현재 웹 페이지에 삽입합니다. ### `webContents.executeJavaScript(code[, userGesture])` * `code` String * `userGesture` Boolean (optional) -페이지에서 코드를 실행합니다. +페이지에서 자바스크립트 코드를 실행합니다. -브라우저 윈도우에서 `requestFullScreen`와 같은 몇몇 HTML API들은 사용자의 행동으로만 호출될 수 -있습니다. `userGesture`를 `true`로 설정하면 이런 제약을 무시할 수 있습니다. +기본적으로 `requestFullScreen`와 같은 몇몇 HTML API들은 사용자의 조작에 의해서만 호출될 수 있습니다. +`userGesture`를 `true`로 설정하면 이러한 제약을 무시할 수 있습니다. ### `webContents.setAudioMuted(muted)` @@ -319,64 +318,64 @@ Injects CSS into the current web page. ### `webContents.undo()` -웹 페이지에서 `undo` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `undo` 편집 커맨드를 실행합니다. ### `webContents.redo()` -웹 페이지에서 `redo` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `redo` 편집 커맨드를 실행합니다. ### `webContents.cut()` -웹 페이지에서 `cut` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `cut` 편집 커맨드를 실행합니다. ### `webContents.copy()` -웹 페이지에서 `copy` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `copy` 편집 커맨드를 실행합니다. ### `webContents.paste()` -웹 페이지에서 `paste` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `paste` 편집 커맨드를 실행합니다. ### `webContents.pasteAndMatchStyle()` -웹 페이지에서 `pasteAndMatchStyle` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `pasteAndMatchStyle` 편집 커맨드를 실행합니다. ### `webContents.delete()` -웹 페이지에서 `delete` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `delete` 편집 커맨드를 실행합니다. ### `webContents.selectAll()` -웹 페이지에서 `selectAll` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `selectAll` 편집 커맨드를 실행합니다. ### `webContents.unselect()` -웹 페이지에서 `unselect` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `unselect` 편집 커맨드를 실행합니다. ### `webContents.replace(text)` * `text` String -웹 페이지에서 `replace` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `replace` 편집 커맨드를 실행합니다. ### `webContents.replaceMisspelling(text)` * `text` String -웹 페이지에서 `replaceMisspelling` 에디팅 커맨드를 실행합니다. +웹 페이지에서 `replaceMisspelling` 편집 커맨드를 실행합니다. ### `webContents.hasServiceWorker(callback)` * `callback` Function -ServiceWorker가 등록되어있는지 확인하고 `callback`에 대한 응답으로 boolean을 반환합니다. +ServiceWorker가 등록되어있는지 확인하고 `callback`에 대한 응답으로 boolean 값을 반환합니다. ### `webContents.unregisterServiceWorker(callback)` * `callback` Function -ServiceWorker가 존재하면 모두 등록을 해제하고 JS promise가 만족될 때 `callback`에 대한 -응답으로 boolean을 반환하거나 JS promise가 만족되지 않을 때 false를 반환합니다. +ServiceWorker가 존재하면 모두 등록을 해제하고 JS Promise가 만족될 때 `callback`에 대한 +응답으로 boolean을 반환하거나 JS Promise가 만족되지 않을 때 `false`를 반환합니다. ### `webContents.print([options])` @@ -392,8 +391,8 @@ ServiceWorker가 존재하면 모두 등록을 해제하고 JS promise가 만족 웹 페이지에서 `window.print()`를 호출하는 것은 `webContents.print({silent: false, printBackground: false})`를 호출하는 것과 같습니다. -**Note:** 윈도우즈에서 print API는 `pdf.dll`에 의존합니다. 당신의 어플리케이션이 print 기능을 -필요로 하지 않는다면 바이너리 크기를 줄이기 위해 `pdf.dll`을 삭제하셔도 안전합니다. +**Note:** Windows에서의 프린터 API는 `pdf.dll`에 의존합니다. +어플리케이션이 print 기능을 사용하지 않는 경우 전체 바이너리 크기를 줄이기 위해 `pdf.dll`을 삭제해도 됩니다. ### `webContents.printToPDF(options, callback)` @@ -456,18 +455,18 @@ win.webContents.on("did-finish-load", function() { * `path` String -특정 경로를 DevTools의 워크스페이스에 추가합니다. +특정 경로를 개발자 도구의 워크스페이스에 추가합니다. ### `webContents.removeWorkSpace(path)` * `path` String -특정 경로를 DevTools의 워크스페이스에서 제거합니다. +특정 경로를 개발자 도구의 워크스페이스에서 제거합니다. ### `webContents.openDevTools([options])` * `options` Object (optional). Properties: - * `detach` Boolean - 새 창에서 DevTools를 엽니다. + * `detach` Boolean - 새 창에서 개발자 도구를 엽니다. 개발자 도구를 엽니다. @@ -538,18 +537,18 @@ app.on('ready', function() { `parameters` Object, properties: * `screenPosition` String - 에뮬레이트 할 화면 종료를 지정합니다 - (default: `desktop`) + (기본값: `desktop`) * `desktop` * `mobile` * `screenSize` Object - 에뮬레이트 화면의 크기를 지정합니다 (screenPosition == mobile) * `width` Integer - 에뮬레이트 화면의 너비를 지정합니다 * `height` Integer - 에뮬레이트 화면의 높이를 지정합니다 * `viewPosition` Object - 화면에서 뷰의 위치 - (screenPosition == mobile) (default: `{x: 0, y: 0}`) + (screenPosition == mobile) (기본값: `{x: 0, y: 0}`) * `x` Integer - 좌상단 모서리로부터의 x 축의 오프셋 * `y` Integer - 좌상단 모서리로부터의 y 축의 오프셋 * `deviceScaleFactor` Integer - 디바이스의 스케일 팩터(scale factor)를 지정합니다. - (0일 경우 기본 디바이스 스케일 팩터를 기본으로 사용합니다) (default: `0`) + (0일 경우 기본 디바이스 스케일 팩터를 기본으로 사용합니다) (기본값: `0`) * `viewSize` Object - 에뮬레이트 된 뷰의 크기를 지정합니다 (빈 값은 오버라이드 하지 않는 다는 것을 의미합니다) * `width` Integer - 에뮬레이트 된 뷰의 너비를 지정합니다 @@ -572,20 +571,22 @@ app.on('ready', function() { ### `webContents.sendInputEvent(event)` * `event` Object - * `type` String (**required**) - 이벤트의 타입. 다음 값들이 가능합니다. `mouseDown`, + * `type` String (**required**) - 이벤트의 타입. 다음 값들을 사용할 수 있습니다: `mouseDown`, `mouseUp`, `mouseEnter`, `mouseLeave`, `contextMenu`, `mouseWheel`, `keyDown`, `keyUp`, `char`. * `modifiers` Array - 이벤트의 수정자(modifier)들에 대한 배열. 다음 값들을 포함 할 수 - 있습니다. `shift`, `control`, `alt`, `meta`, `isKeypad`, `isAutoRepeat`, + 있습니다: `shift`, `control`, `alt`, `meta`, `isKeypad`, `isAutoRepeat`, `leftButtonDown`, `middleButtonDown`, `rightButtonDown`, `capsLock`, `numLock`, `left`, `right`. -input `event`를 페이지로 보냅니다. +Input `event`를 웹 페이지로 전송합니다. -키보드 이벤트들에 대해서는 `event` 객체는 다음 속성들을 추가적으로 가지고 있습니다: +키보드 이벤트들에 대해서는 `event` 객체는 다음 속성들을 추가로 가지고 있습니다: -* `keyCode` String (**required**) - 키보드 이벤트로 보낼 수 있는 단일 캐릭터. 모든 UTF-8가 - 사용 가능합니다. +* `keyCode` String (**required**) - 키보드 이벤트로 보내지는 문자. + 단일 UTF-8 문자를 사용할 수 있고 이벤트를 발생시키는 다음 키 중 하나를 포함할 수 있습니다: + `enter`, `backspace`, `delete`, `tab`, `escape`, `control`, `alt`, `shift`, `end`, + `home`, `insert`, `left`, `up`, `right`, `down`, `pageUp`, `pageDown`, `printScreen` 마우스 이벤트들에 대해서는 `event` 객체는 다음 속성들을 추가적으로 가지고 있습니다: @@ -631,10 +632,9 @@ BGRA 포맷으로 효율적으로 저장됩니다. 하지만 실제 재프리젠 ### `webContents.devToolsWebContents` -이 `WebContents`에 대한 DevTools의 `WebContents`를 가져옵니다. +이 `WebContents`에 대한 개발자 도구의 `WebContents`를 가져옵니다. -**Note:** 사용자가 절대로 이 객체를 저장해서는 안됩니다. 그럴경우 DevTools가 닫혔을 때, `null`이 -될 수도 있습니다. +**Note:** 사용자가 절대로 이 객체를 저장해서는 안 됩니다. 개발자 도구가 닫혔을 때, `null`이 반환될 수 있습니다. ### `webContents.savePage(fullPath, saveType, callback)` diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index eb40151a234d..7b3d259fdfc7 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -256,15 +256,15 @@ webview.addEventListener("dom-ready", function() { ### `.openDevTools()` -페이지에 대한 개발자 콘솔을 엽니다. +페이지에 대한 개발자 도구를 엽니다. ### `.closeDevTools()` -페이지에 대한 개발자 콘솔을 닫습니다. +페이지에 대한 개발자 도구를 닫습니다. ### `.isDevToolsOpened()` -페이지에 대한 개발자 콘솔이 열려있는지 확인합니다. 불린 값을 반환합니다. +페이지에 대한 개발자 도구가 열려있는지 확인합니다. 불린 값을 반환합니다. ### `.inspectElement(x, y)` @@ -275,7 +275,7 @@ webview.addEventListener("dom-ready", function() { ### `.inspectServiceWorker()` -Service worker에 대한 개발자 콘솔을 엽니다. +Service worker에 대한 개발자 도구를 엽니다. ### `.undo()` diff --git a/docs-translations/ko-KR/tutorial/debugging-main-process.md b/docs-translations/ko-KR/tutorial/debugging-main-process.md index c11f3db04f3a..b03e2542dcd3 100644 --- a/docs-translations/ko-KR/tutorial/debugging-main-process.md +++ b/docs-translations/ko-KR/tutorial/debugging-main-process.md @@ -1,6 +1,6 @@ # 메인 프로세스 디버깅하기 -브라우저 창의 개발자 콘솔은 웹 페이지 같은 랜더러 프로세스의 스크립트만 디버깅이 가능합니다. +브라우저 창의 개발자 도구는 웹 페이지 같은 랜더러 프로세스의 스크립트만 디버깅이 가능합니다. 대신 Electron은 메인 프로세스의 디버깅을 위해 `--debug` 과 `--debug-brk` 스위치들을 제공합니다. ## 커맨드 라인 스위치(command line switches) diff --git a/docs-translations/ko-KR/tutorial/devtools-extension.md b/docs-translations/ko-KR/tutorial/devtools-extension.md index 04b592955cdc..05ec3893ead0 100644 --- a/docs-translations/ko-KR/tutorial/devtools-extension.md +++ b/docs-translations/ko-KR/tutorial/devtools-extension.md @@ -1,8 +1,8 @@ -# 개발자 콘솔 확장 +# 개발자 도구 확장 기능 어플리케이션의 디버깅을 쉽게 하기 위해 Electron은 기본적으로 [Chrome DevTools Extension][devtools-extension]을 지원합니다. -개발자 콘솔 확장 기능은 간단하게 사용할 확장 기능 플러그인의 소스 코드를 다운로드한 후 `BrowserWindow.addDevToolsExtension` API를 이용하여 +개발자 도구 확장 기능은 간단하게 사용할 확장 기능 플러그인의 소스 코드를 다운로드한 후 `BrowserWindow.addDevToolsExtension` API를 이용하여 어플리케이션 내에 로드할 수 있습니다. 한가지 주의할 점은 확장 기능 사용시 창이 생성될 때 마다 일일이 해당 API를 호출할 필요는 없습니다. ** 주의: 현재 React DevTools은 작동하지 않습니다. https://github.com/atom/electron/issues/915 이슈를 참고하세요! ** @@ -19,7 +19,7 @@ $ git clone --recursive https://github.com/facebook/react-devtools.git [`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md) 를 통해 확장 기능을 개발하는 방법을 알아볼 수 있습니다. -그리고 개발자 콘솔에서 다음 코드를 입력하면 확장 기능을 로드할 수 있습니다: +그리고 개발자 도구에서 다음 코드를 입력하면 확장 기능을 로드할 수 있습니다: ```javascript const BrowserWindow = require('electron').remote.BrowserWindow; @@ -32,9 +32,9 @@ BrowserWindow.addDevToolsExtension('/some-directory/react-devtools/shells/chrome BrowserWindow.removeDevToolsExtension('React Developer Tools'); ``` -## 개발자 콘솔 확장 기능의 구성 형식 +## 개발자 도구 확장 기능의 구성 형식 -모든 개발자 콘솔 확장은 완벽히 Chrome 브라우저를 위해 작성되었기 때문에 Electron에서도 로드할 수 있습니다. +모든 개발자 도구 확장은 완벽히 Chrome 브라우저를 위해 작성되었기 때문에 Electron에서도 로드할 수 있습니다. 하지만 반드시 확장 기능은 소스 코드 디렉터리(폴더) 형태여야 합니다. 그래서 `crx` 등의 포맷으로 패키징된 확장 기능의 경우 사용자가 직접 해당 패키지의 압축을 풀어서 로드하지 않는 이상 Electron에서 해당 확장 기능의 압축을 풀 방법이 없습니다. diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 2c1aa5f9837e..dea6a343e6bf 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -93,7 +93,7 @@ app.on('ready', function() { // 그리고 현재 디렉터리의 index.html을 로드합니다. mainWindow.loadURL('file://' + __dirname + '/index.html'); - // 개발자 콘솔을 엽니다. + // 개발자 도구를 엽니다. mainWindow.webContents.openDevTools(); // 창이 닫히면 호출됩니다. From c21d7b537a9621b93dc2e42e1102a258d02613ff Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 03:40:58 +0900 Subject: [PATCH 539/738] Update as upstream --- docs-translations/ko-KR/api/app.md | 4 ++-- docs-translations/ko-KR/api/session.md | 24 +++++++++++++++++++++ docs-translations/ko-KR/api/web-contents.md | 19 ++++++++++------ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index d5fa007618a8..51e88c534ff4 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -140,8 +140,8 @@ Returns: * `webContents` [WebContents](web-contents.md) * `url` URL * `certificateList` [Objects] - * `data` PEM으로 인코딩된 데이터 - * `issuerName` 발급자의 공통 이름 + * `data` Buffer - PEM으로 인코딩된 데이터 + * `issuerName` String - 발급자의 공통 이름 * `callback` Function 사용자 인증이 요청되었을 때 발생하는 이벤트 입니다. diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index ad7ceaced4fc..749ca6efbb0f 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -33,6 +33,30 @@ session.on('will-download', function(event, item, webContents) { }); ``` +### Event: 'untrusted-certificate' + +* `event` Event +* `hostname` String +* `certificate` Object + * `data` Buffer - PEM encoded data + * `issuerName` String +* `callback` Function + +`hostname`에 대한 `certificate`의 유효성 검증이 실패했을 때 발생하는 이벤트 입니다. +인증서를 신뢰한다면 `event.preventDefault()` 와 `callback(true)`를 호출하여 기본 동작을 방지해야 합니다. + +```javascript +session.on('verify-certificate', function(event, hostname, certificate, callback) { + if (hostname == "github.com") { + // verification logic. + event.preventDefault(); + callback(true); + } else { + callback(false); + } +}); +``` + ## Methods `session` 객체는 다음과 같은 메서드와 속성을 가지고 있습니다: diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index 89c5a4a767f0..3193527f9c79 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -200,8 +200,13 @@ webContents에서 사용되는 `session`객체를 반환합니다. * `userAgent` String - 요청을 시작한 유저 에이전트. * `extraHeaders` String - "\n"로 구분된 Extra 헤더들. -윈도우에 `url`을 로드합니다. `url`은 `http://` or `file://`과 같은 프로토콜 접두사를 -가지고 있어야 합니다. +윈도우에 웹 페이지 `url`을 로드합니다. `url`은 `http://` or `file://`과 같은 프로토콜 접두사를 가지고 있어야 합니다. +만약 반드시 http 캐시를 사용하지 않고 로드해야 하는 경우 `pragma` 헤더를 사용할 수 있습니다. + +```javascript +const options = {"extraHeaders" : "pragma: no-cache\n"} +webContents.loadURL(url, options) +``` ### `webContents.getURL()` @@ -573,7 +578,7 @@ app.on('ready', function() { * `event` Object * `type` String (**required**) - 이벤트의 타입. 다음 값들을 사용할 수 있습니다: `mouseDown`, `mouseUp`, `mouseEnter`, `mouseLeave`, `contextMenu`, `mouseWheel`, - `keyDown`, `keyUp`, `char`. + `mouseMove`, `keyDown`, `keyUp`, `char`. * `modifiers` Array - 이벤트의 수정자(modifier)들에 대한 배열. 다음 값들을 포함 할 수 있습니다: `shift`, `control`, `alt`, `meta`, `isKeypad`, `isAutoRepeat`, `leftButtonDown`, `middleButtonDown`, `rightButtonDown`, `capsLock`, @@ -581,14 +586,14 @@ app.on('ready', function() { Input `event`를 웹 페이지로 전송합니다. -키보드 이벤트들에 대해서는 `event` 객체는 다음 속성들을 추가로 가지고 있습니다: +키보드 이벤트들에 대해서는 `event` 객체는 다음 속성들을 사용할 수 있습니다: -* `keyCode` String (**required**) - 키보드 이벤트로 보내지는 문자. +* `keyCode` Char or String (**required**) - 키보드 이벤트로 보내지는 문자. 단일 UTF-8 문자를 사용할 수 있고 이벤트를 발생시키는 다음 키 중 하나를 포함할 수 있습니다: `enter`, `backspace`, `delete`, `tab`, `escape`, `control`, `alt`, `shift`, `end`, `home`, `insert`, `left`, `up`, `right`, `down`, `pageUp`, `pageDown`, `printScreen` -마우스 이벤트들에 대해서는 `event` 객체는 다음 속성들을 추가적으로 가지고 있습니다: +마우스 이벤트들에 대해서는 `event` 객체는 다음 속성들을 사용할 수 있습니다: * `x` Integer (**required**) * `y` Integer (**required**) @@ -599,7 +604,7 @@ Input `event`를 웹 페이지로 전송합니다. * `movementY` Integer * `clickCount` Integer -`mouseWheel` 이벤트에 대해서는 `event` 객체는 다음 속성들을 추가적으로 가지고 있습니다: +`mouseWheel` 이벤트에 대해서는 `event` 객체는 다음 속성들을 사용할 수 있습니다: * `deltaX` Integer * `deltaY` Integer From 9c69416e322ca62930956030540a3cedf582a006 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Tue, 17 Nov 2015 13:43:55 -0800 Subject: [PATCH 540/738] Fix sizing of Mac OS X tray icon after image change - Consolidate logic that applies view dimensions into a function - Use `NSVariableStatusItemLength` instead of trying to sync status item width - Use modern Obj-C syntax `@[], @{}` in a few places - Recompute view bounds after updating image in `setImage:` --- atom/browser/ui/tray_icon_cocoa.mm | 50 ++++++++++++++++-------------- docs/api/tray.md | 3 +- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index 34ca4e9a9112..0527681cd3ec 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -40,15 +40,9 @@ const CGFloat kVerticalTitleMargin = 2; trayIcon_ = icon; isHighlightEnable_ = YES; - // Get the initial size. - NSStatusBar* statusBar = [NSStatusBar systemStatusBar]; - NSRect frame = NSMakeRect(0, 0, [self fullWidth], [statusBar thickness]); - - if ((self = [super initWithFrame:frame])) { + if ((self = [super initWithFrame: CGRectZero])) { // Setup the image view. - NSRect iconFrame = frame; - iconFrame.size.width = [self iconWidth]; - image_view_.reset([[NSImageView alloc] initWithFrame:iconFrame]); + image_view_.reset([[NSImageView alloc] initWithFrame: CGRectZero]); [image_view_ setImageScaling:NSImageScaleNone]; [image_view_ setImageAlignment:NSImageAlignCenter]; [self addSubview:image_view_]; @@ -56,17 +50,27 @@ const CGFloat kVerticalTitleMargin = 2; // Unregister image_view_ as a dragged destination, allows its parent view // (StatusItemView) handle dragging events. [image_view_ unregisterDraggedTypes]; - NSArray* types = [NSArray arrayWithObjects:NSFilenamesPboardType, nil]; - [self registerForDraggedTypes:types]; + [self registerForDraggedTypes: @[NSFilenamesPboardType]]; // Create the status item. - statusItem_.reset([[[NSStatusBar systemStatusBar] - statusItemWithLength:NSWidth(frame)] retain]); + NSStatusItem * item = [[NSStatusBar systemStatusBar] + statusItemWithLength:NSVariableStatusItemLength]; + statusItem_.reset([item retain]); [statusItem_ setView:self]; + + // Finalize setup by sizing our views + [self updateDimensions]; } return self; } +- (void)updateDimensions { + NSStatusBar * bar = [NSStatusBar systemStatusBar]; + [image_view_ setFrame: NSMakeRect(0, 0, [self iconWidth], [bar thickness])]; + [self setFrame: NSMakeRect(0, 0, [self fullWidth], [bar thickness])]; + [self setNeedsDisplay:YES]; +} + - (void)removeItem { [[NSStatusBar systemStatusBar] removeStatusItem:statusItem_]; statusItem_.reset(); @@ -81,9 +85,7 @@ const CGFloat kVerticalTitleMargin = 2; // Draw background. BOOL highlight = [self shouldHighlight]; CGFloat thickness = [[statusItem_ statusBar] thickness]; - NSRect statusItemBounds = NSMakeRect(0, 0, [statusItem_ length], thickness); - [statusItem_ drawStatusBarBackgroundInRect:statusItemBounds - withHighlight:highlight]; + [statusItem_ drawStatusBarBackgroundInRect:self.bounds withHighlight:highlight]; // Make use of NSImageView to draw the image, which can correctly draw // template image under dark menu bar. @@ -157,10 +159,10 @@ const CGFloat kVerticalTitleMargin = 2; NSColor* foregroundColor = highlight ? [NSColor whiteColor] : [NSColor colorWithRed:0.265625 green:0.25390625 blue:0.234375 alpha:1.0]; - return [NSDictionary dictionaryWithObjectsAndKeys: - font, NSFontAttributeName, - foregroundColor, NSForegroundColorAttributeName, - nil]; + return @{ + NSFontAttributeName: font, + NSForegroundColorAttributeName: foregroundColor + }; } - (NSDictionary*)titleAttributes { @@ -169,7 +171,7 @@ const CGFloat kVerticalTitleMargin = 2; - (void)setImage:(NSImage*)image { image_.reset([image copy]); - [self setNeedsDisplay:YES]; + [self updateDimensions]; } - (void)setAlternateImage:(NSImage*)image { @@ -181,12 +183,12 @@ const CGFloat kVerticalTitleMargin = 2; } - (void)setTitle:(NSString*)title { - if (title.length > 0) + if (title.length > 0) { title_.reset([title copy]); - else + } else { title_.reset(); - [statusItem_ setLength:[self fullWidth]]; - [self setNeedsDisplay:YES]; + } + [self updateDimensions]; } - (void)setMenuController:(AtomMenuController*)menu { diff --git a/docs/api/tray.md b/docs/api/tray.md index 528705acb325..7e84ad202bb4 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -158,7 +158,8 @@ Sets the title displayed aside of the tray icon in the status bar. * `highlight` Boolean -Sets whether the tray icon is highlighted when it is clicked. +Sets whether the tray icon's background becomes highlighted (in blue) +when the tray icon is clicked. Defaults to true. ### `Tray.displayBalloon(options)` _Windows_ From 57aecbc415bb19c07f31802e0913c809e5c7e1a3 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 07:09:10 +0900 Subject: [PATCH 541/738] Small changes --- docs-translations/ko-KR/api/menu-item.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs-translations/ko-KR/api/menu-item.md b/docs-translations/ko-KR/api/menu-item.md index b17d3b9ec391..dfcc4fcb2413 100644 --- a/docs-translations/ko-KR/api/menu-item.md +++ b/docs-translations/ko-KR/api/menu-item.md @@ -40,11 +40,11 @@ OS X에서의 `role`은 다음 값을 추가로 가질 수 있습니다: -* `about` - 매핑된 `orderFrontStandardAboutPanel` 액션 -* `hide` - 매핑된 `hide` 액션 -* `hideothers` - 매핑된 `hideOtherApplications` 액션 -* `unhide` - 매핑된 `unhideAllApplications` 액션 -* `front` - 매핑된 `arrangeInFront` 액션 +* `about` - `orderFrontStandardAboutPanel` 액션에 대응 +* `hide` - `hide` 액션에 대응 +* `hideothers` - `hideOtherApplications` 액션에 대응 +* `unhide` - `unhideAllApplications` 액션에 대응 +* `front` - `arrangeInFront` 액션에 대응 * `window` - 부 메뉴를 가지는 "Window" 메뉴 * `help` - 부 메뉴를 가지는 "Help" 메뉴 * `services` - 부 메뉴를 가지는 "Services" 메뉴 From 7cc965b178c44b6e0e7117032f04549bb25ec718 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 09:21:38 +0900 Subject: [PATCH 542/738] Translate docs --- docs-translations/ko-KR/README.md | 2 +- docs-translations/ko-KR/api/browser-window.md | 69 ++++++++++--------- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index 39b9367d0ecf..a6328586b5de 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -32,7 +32,7 @@ * [app](api/app.md) * [autoUpdater](api/auto-updater.md) -* [BrowserWindow (20% 번역됨 - 작업중)](api/browser-window.md) +* [BrowserWindow (30% 번역됨 - 작업중)](api/browser-window.md) * [contentTracing](api/content-tracing.md) * [dialog](api/dialog.md) * [globalShortcut](api/global-shortcut.md) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 30165e858519..10dc0a8ff101 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -118,103 +118,104 @@ Returns: * `event` Event -Emitted when the window is going to be closed. It's emitted before the -`beforeunload` and `unload` event of the DOM. Calling `event.preventDefault()` -will cancel the close. +윈도우가 닫히기 시작할 때 발생하는 이벤트입니다. +이 이벤트는 DOM의 `beforeunload` 와 `unload` 이벤트가 호출되기 전에 발생합니다. +`event.preventDefault()`를 호출하여 윈도우 종료를 취소할 수 있습니다. -Usually you would want to use the `beforeunload` handler to decide whether the -window should be closed, which will also be called when the window is -reloaded. In Electron, returning an empty string or `false` would cancel the -close. For example: +보통 창을 닫아야 할지 결정하기 위해 `beforeunload` 이벤트를 사용하려고 할 것입니다. +이 이벤트는 윈도우 컨텐츠를 새로고칠 때도 발생합니다. +Electron에선 빈 문자열 또는 `false`를 전달할 경우 윈도우 종료를 취소합니다. + +예시는 다음과 같습니다: ```javascript window.onbeforeunload = function(e) { console.log('I do not want to be closed'); - // Unlike usual browsers, in which a string should be returned and the user is - // prompted to confirm the page unload, Electron gives developers more options. - // Returning empty string or false would prevent the unloading now. - // You can also use the dialog API to let the user confirm closing the application. + // 반드시 문자열을 반환해야 하고 사용자에게 페이지 언로드에 대한 확인 창을 보여주는 보통의 브라우저와는 달리 + // Electron은 개발자에게 더 많은 옵션을 제공합니다. + // 빈 문자열을 반환하거나 false를 반환하면 페이지 언로드를 방지합니다. + // 또한 dialog API를 통해 사용자에게 어플리케이션을 종료할지에 대한 확인 창을 보여줄 수도 있습니다. e.returnValue = false; }; ``` ### Event: 'closed' -Emitted when the window is closed. After you have received this event you should -remove the reference to the window and avoid using it anymore. +윈도우 종료가 완료된 경우 발생하는 이벤트입니다. +이 이벤트가 발생했을 경우 반드시 윈도우 창의 레퍼런스가 더 이상 사용되지 않도록 제거해야 합니다. ### Event: 'unresponsive' -Emitted when the web page becomes unresponsive. +웹 페이지가 응답하지 않을 때 발생하는 이벤트입니다. ### Event: 'responsive' -Emitted when the unresponsive web page becomes responsive again. +응답하지 않는 웹 페이지가 다시 응답하기 시작했을 때 발생하는 이벤트입니다. ### Event: 'blur' -Emitted when the window loses focus. +윈도우가 포커스를 잃었을 떄 발생하는 이벤트입니다. ### Event: 'focus' -Emitted when the window gains focus. +윈도우가 포커스를 가졌을 때 발생하는 이벤트입니다. ### Event: 'maximize' -Emitted when window is maximized. +윈도우가 최대화됐을 때 발생하는 이벤트입니다. ### Event: 'unmaximize' -Emitted when the window exits from maximized state. +윈도우의 최대화 상태가 해제되었을 때 발생하는 이벤트입니다. ### Event: 'minimize' -Emitted when the window is minimized. +윈도우가 최소화됐을 때 발생하는 이벤트입니다. ### Event: 'restore' -Emitted when the window is restored from minimized state. +윈도우가 최소화 상태에서 복구되었을 때 발생하는 이벤트입니다. ### Event: 'resize' -Emitted when the window is getting resized. +윈도우의 크기가 재조정될 때 발생하는 이벤트입니다. ### Event: 'move' -Emitted when the window is getting moved to a new position. +윈도우가 새로운 위치로 이동될 때 발생하는 이벤트입니다. -__Note__: On OS X this event is just an alias of `moved`. +__참고__: OS X에선 이 이벤트가 그저 `moved` 이벤트의 별칭(alias)으로 사용됩니다. ### Event: 'moved' _OS X_ -Emitted once when the window is moved to a new position. +윈도우가 새로운 위치로 이동되었을 때 발생하는 이벤트입니다. (한 번만) ### Event: 'enter-full-screen' -Emitted when the window enters full screen state. +윈도우가 풀 스크린 모드로 진입할 때 발생하는 이벤트입니다. ### Event: 'leave-full-screen' -Emitted when the window leaves full screen state. +윈도우가 풀 스크린 모드에서 해제될 때 발생하는 이벤트입니다. ### Event: 'enter-html-full-screen' -Emitted when the window enters full screen state triggered by html api. +윈도우가 HTML API에 의해 풀 스크린 모드로 진입할 때 발생하는 이벤트입니다. ### Event: 'leave-html-full-screen' -Emitted when the window leaves full screen state triggered by html api. +윈도우가 HTML API에 의해 풀 스크린 모드에서 해제될 때 발생하는 이벤트입니다. ### Event: 'app-command': -Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) -is invoked. These are typically related to keyboard media keys or browser -commands, as well as the "Back" button built into some mice on Windows. +[App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)가 호출됐을 때 발생하는 이벤트입니다. +이 이벤트는 일반적으로 키보드 미디어 키 또는 브라우저 커맨드(기본 동작 키)에 관련되어 있습니다. +예를 들어 Windows에서 작동하는 몇몇 마우스는 "뒤로가기" 같은 동작을 포함하고 있습니다. -```js +```javascript someWindow.on('app-command', function(e, cmd) { - // Navigate the window back when the user hits their mouse back button + // 마우스의 뒤로가기 버튼을 눌렀을 때 뒤로가기 탐색을 실행합니다 if (cmd === 'browser-backward' && someWindow.webContents.canGoBack()) { someWindow.webContents.goBack(); } From 0dd14ad204d9951f63a0c4b24e5c511a5a82b807 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 09:36:14 +0900 Subject: [PATCH 543/738] 'app-command' event is only available in Windows --- docs/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 3b293e99621c..80b7a5f35271 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -232,7 +232,7 @@ Emitted when the window enters full screen state triggered by html api. Emitted when the window leaves full screen state triggered by html api. -### Event: 'app-command': +### Event: 'app-command' __Windows__ Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) is invoked. These are typically related to keyboard media keys or browser From 0e8ab0688d00e476c0baa9b74ce5c5cfc3d37de2 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 09:43:28 +0900 Subject: [PATCH 544/738] Fix wrong markdown --- docs/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 80b7a5f35271..e5fcfb9003ae 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -232,7 +232,7 @@ Emitted when the window enters full screen state triggered by html api. Emitted when the window leaves full screen state triggered by html api. -### Event: 'app-command' __Windows__ +### Event: 'app-command' _Windows_ Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) is invoked. These are typically related to keyboard media keys or browser From d129aa9085ce71e8de21abd489f0e218c18891fe Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 09:50:14 +0900 Subject: [PATCH 545/738] Update as upstream --- docs-translations/ko-KR/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 10dc0a8ff101..1046f8bd5ca7 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -207,7 +207,7 @@ __참고__: OS X에선 이 이벤트가 그저 `moved` 이벤트의 별칭(alias 윈도우가 HTML API에 의해 풀 스크린 모드에서 해제될 때 발생하는 이벤트입니다. -### Event: 'app-command': +### Event: 'app-command' _Windows_ [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)가 호출됐을 때 발생하는 이벤트입니다. 이 이벤트는 일반적으로 키보드 미디어 키 또는 브라우저 커맨드(기본 동작 키)에 관련되어 있습니다. From 1022179a1ff78c9622538ec150517ffcedffb78c Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Tue, 17 Nov 2015 17:36:37 -0800 Subject: [PATCH 546/738] Improve exception messages from remote calls Spent a while tracking down `Error processing argument -1`, caused by a missing param (`app.exit()` now takes an exit code.) Improve the rpc-server so that it prints the function name when possible, so it's much easier to identify which remote call is causing the error. --- atom/browser/lib/rpc-server.coffee | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index ae4b161674bd..830b966f04a2 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -103,13 +103,25 @@ unwrapArgs = (sender, args) -> # Call a function and send reply asynchronously if it's a an asynchronous # style function and the caller didn't pass a callback. callFunction = (event, func, caller, args) -> - if v8Util.getHiddenValue(func, 'asynchronous') and typeof args[args.length - 1] isnt 'function' - args.push (ret) -> + funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous') + funcPassedCallback = args[args.length - 1] is 'function' + + try + if funcMarkedAsync and not funcPassedCallback + args.push (ret) -> + event.returnValue = valueToMeta event.sender, ret, true + func.apply caller, args + else + ret = func.apply caller, args event.returnValue = valueToMeta event.sender, ret, true - func.apply caller, args - else - ret = func.apply caller, args - event.returnValue = valueToMeta event.sender, ret, true + catch e + # Catch functions thrown further down in function invocation and wrap + # them with the function name so it's easier to trace things like + # `Error processing argument -1.` + funcName = func.name ? "anonymous" + throw new Error("Could not call remote function `#{funcName}`. + Check that the function signature is correct. + Underlying error: #{e.message}") # Send by BrowserWindow when its render view is deleted. process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) -> From c2eddb20f7c75473e30f45d6f495131df3a24831 Mon Sep 17 00:00:00 2001 From: "Howard.Zuo" Date: Wed, 18 Nov 2015 09:37:45 +0800 Subject: [PATCH 547/738] use loadURL since loadUrl is deprecated --- docs-translations/es/tutorial/quick-start.md | 4 ++-- docs-translations/jp/quick-start.md | 2 +- docs-translations/pt-BR/tutorial/quick-start.md | 14 +++++++------- docs-translations/zh-CN/tutorial/quick-start.md | 2 +- docs-translations/zh-TW/tutorial/quick-start.md | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs-translations/es/tutorial/quick-start.md b/docs-translations/es/tutorial/quick-start.md index 3db92177ca24..ee1127eb0269 100644 --- a/docs-translations/es/tutorial/quick-start.md +++ b/docs-translations/es/tutorial/quick-start.md @@ -2,7 +2,7 @@ ## Introducción -Electron permite la creación de aplicaciones de escritorio utilizando JavaScript puro, a través de un runtime con APIs nativas. Puedes verlo como una variante de io.js, enfocado en aplicaciones de escritorio, en vez de servidores web. +Electron permite la creación de aplicaciones de escritorio utilizando JavaScript puro, a través de un runtime con APIs nativas. Puedes verlo como una variante de io.js, enfocado en aplicaciones de escritorio, en vez de servidores web. Esto no significa que Electron sea un binding de librerías GUI para JavaScript. Electron utiliza páginas web como su GUI, por lo cual puedes verlo como un navegador Chromium mínimo, @@ -94,7 +94,7 @@ app.on('ready', function() { mainWindow = new BrowserWindow({width: 800, height: 600}); // cargar el index.html de nuestra aplicación. - mainWindow.loadUrl('file://' + __dirname + '/index.html'); + mainWindow.loadURL('file://' + __dirname + '/index.html'); // Desplegar devtools. mainWindow.openDevTools(); diff --git a/docs-translations/jp/quick-start.md b/docs-translations/jp/quick-start.md index aa26a8a55ab0..9a929ff84dc4 100644 --- a/docs-translations/jp/quick-start.md +++ b/docs-translations/jp/quick-start.md @@ -74,7 +74,7 @@ app.on('ready', function() { mainWindow = new BrowserWindow({width: 800, height: 600}); // and load the index.html of the app. - mainWindow.loadUrl('file://' + __dirname + '/index.html'); + mainWindow.loadURL('file://' + __dirname + '/index.html'); // Open the devtools. mainWindow.openDevTools(); diff --git a/docs-translations/pt-BR/tutorial/quick-start.md b/docs-translations/pt-BR/tutorial/quick-start.md index 3ec71961a92b..f9883144c825 100644 --- a/docs-translations/pt-BR/tutorial/quick-start.md +++ b/docs-translations/pt-BR/tutorial/quick-start.md @@ -5,13 +5,13 @@ um runtime com APIs ricas e nativas. Você pode ver isso como uma variação do runtime do io.js que é focado em aplicações desktop em vez de web servers. Isso não significa que o Electron é uma ligação em JavaScript para blibliotécas -de interface gráfica (GUI). Em vez disso, Electron usa páginas web como +de interface gráfica (GUI). Em vez disso, Electron usa páginas web como interface gráfica, então você pode ver isso também como um navegador Chromium mínimo, controlado por JavaScript. ### Processo Principal -No Electron, o processo que executa o script principal (main) do `package.json` +No Electron, o processo que executa o script principal (main) do `package.json` é chamado __processo principal__. O script que roda no processo principal pode mostrar uma GUI criando páginas web. @@ -38,7 +38,7 @@ correspondentes. Cada processo renderizador é isolado e toma conta de sua respectiva página web. Nas páginas web, chamar APIs nativas relacionadas à GUI não é permitido porque -gerênciar recursos de GUI em páginas web é muito perigoso e torna fácil o vazamento de +gerênciar recursos de GUI em páginas web é muito perigoso e torna fácil o vazamento de recursos. Se você quer realizar operações com GUI em páginas web, o processo renderizador da página web deve se comunicar com o processo principal para requisitar que o processo principal realize estas operações. @@ -71,7 +71,7 @@ com isso: } ``` -__Nota__: Se o campo `main` não estiver presente no `package.jso`, o Electron irá +__Nota__: Se o campo `main` não estiver presente no `package.jso`, o Electron irá tentar carregar um `index.js` O `main.js` deve criar as janelas e os manipuladores de eventos do sistema, um típico @@ -85,7 +85,7 @@ var BrowserWindow = require('browser-window'); // Módulo para criar uma janela require('crash-reporter').start(); // Mantenha uma referência global para o objeto window, se você não o fizer, -// a janela será fechada automaticamente quando o objeto JavaScript for +// a janela será fechada automaticamente quando o objeto JavaScript for // coletado pelo garbage collector. var mainWindow = null; @@ -106,7 +106,7 @@ app.on('ready', function() { mainWindow = new BrowserWindow({width: 800, height: 600}); // e carrega o index.html do app. - mainWindow.loadUrl('file://' + __dirname + '/index.html'); + mainWindow.loadURL('file://' + __dirname + '/index.html'); // Abre os DevTools. mainWindow.openDevTools(); @@ -187,6 +187,6 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/ ### Executar como uma distribuição -Depois de terminar seu app, você pode criar uma distribuição seguindo o guia +Depois de terminar seu app, você pode criar uma distribuição seguindo o guia [Application Distribution](./application-distribution.md) e então executar o app empacotado. diff --git a/docs-translations/zh-CN/tutorial/quick-start.md b/docs-translations/zh-CN/tutorial/quick-start.md index 165c30142e72..906db8f4458b 100644 --- a/docs-translations/zh-CN/tutorial/quick-start.md +++ b/docs-translations/zh-CN/tutorial/quick-start.md @@ -68,7 +68,7 @@ app.on('ready', function() { mainWindow = new BrowserWindow({width: 800, height: 600}); // 加载应用的 index.html - mainWindow.loadUrl('file://' + __dirname + '/index.html'); + mainWindow.loadURL('file://' + __dirname + '/index.html'); // 打开开发工具 mainWindow.openDevTools(); diff --git a/docs-translations/zh-TW/tutorial/quick-start.md b/docs-translations/zh-TW/tutorial/quick-start.md index 068138587f1d..18c62c5e75ce 100644 --- a/docs-translations/zh-TW/tutorial/quick-start.md +++ b/docs-translations/zh-TW/tutorial/quick-start.md @@ -85,7 +85,7 @@ app.on('ready', function() {   mainWindow = new BrowserWindow({width: 800, height: 600});   // 載入應用程式的 index.html -  mainWindow.loadUrl('file://' + __dirname + '/index.html'); +  mainWindow.loadURL('file://' + __dirname + '/index.html');   // 打開開發者工具   mainWindow.webContents.openDevTools(); @@ -174,4 +174,4 @@ $ git clone https://github.com/atom/electron-quick-start $ cd electron-quick-start # Install dependencies and run the app $ npm install && npm start -``` \ No newline at end of file +``` From 9a0dc3bfd76604b983d4cfdff227da91895b0be1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 18 Nov 2015 10:07:03 +0800 Subject: [PATCH 548/738] Add Delegate for AtomBrowserClient --- atom/browser/api/atom_api_app.cc | 45 +++++++++++++++-------------- atom/browser/api/atom_api_app.h | 10 +++++-- atom/browser/atom_browser_client.cc | 11 ++++--- atom/browser/atom_browser_client.h | 5 ++++ atom/browser/browser.cc | 13 --------- atom/browser/browser.h | 6 ---- atom/browser/browser_observer.h | 17 ----------- 7 files changed, 41 insertions(+), 66 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index df28829c46a4..b1efea5c45d3 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -154,11 +154,14 @@ void PassLoginInformation(scoped_refptr login_handler, } // namespace App::App() { + static_cast(AtomBrowserClient::Get())->set_delegate(this); Browser::Get()->AddObserver(this); content::GpuDataManager::GetInstance()->AddObserver(this); } App::~App() { + static_cast(AtomBrowserClient::Get())->set_delegate( + nullptr); Browser::Get()->RemoveObserver(this); content::GpuDataManager::GetInstance()->RemoveObserver(this); } @@ -212,27 +215,6 @@ void App::OnFinishLaunching() { Emit("ready"); } -void App::OnSelectCertificate( - content::WebContents* web_contents, - net::SSLCertRequestInfo* cert_request_info, - scoped_ptr delegate) { - std::shared_ptr - shared_delegate(delegate.release()); - bool prevent_default = - Emit("select-certificate", - api::WebContents::CreateFrom(isolate(), web_contents), - cert_request_info->host_and_port.ToString(), - cert_request_info->client_certs, - base::Bind(&OnClientCertificateSelected, - isolate(), - shared_delegate)); - - // Default to first certificate from the platform store. - if (!prevent_default) - shared_delegate->ContinueWithCertificate( - cert_request_info->client_certs[0].get()); -} - void App::OnLogin(LoginHandler* login_handler) { // Convert the args explicitly since they will be passed for twice. v8::Locker locker(isolate()); @@ -258,6 +240,27 @@ void App::OnLogin(LoginHandler* login_handler) { login_handler->CancelAuth(); } +void App::SelectClientCertificate( + content::WebContents* web_contents, + net::SSLCertRequestInfo* cert_request_info, + scoped_ptr delegate) { + std::shared_ptr + shared_delegate(delegate.release()); + bool prevent_default = + Emit("select-certificate", + api::WebContents::CreateFrom(isolate(), web_contents), + cert_request_info->host_and_port.ToString(), + cert_request_info->client_certs, + base::Bind(&OnClientCertificateSelected, + isolate(), + shared_delegate)); + + // Default to first certificate from the platform store. + if (!prevent_default) + shared_delegate->ContinueWithCertificate( + cert_request_info->client_certs[0].get()); +} + void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) { Emit("gpu-process-crashed"); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 683093d886c9..c3793cd54267 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -8,6 +8,7 @@ #include #include "atom/browser/api/event_emitter.h" +#include "atom/browser/atom_browser_client.h" #include "atom/browser/browser_observer.h" #include "atom/common/native_mate_converters/callback.h" #include "chrome/browser/process_singleton.h" @@ -26,7 +27,8 @@ namespace atom { namespace api { -class App : public mate::EventEmitter, +class App : public AtomBrowserClient::Delegate, + public mate::EventEmitter, public BrowserObserver, public content::GpuDataManagerObserver { public: @@ -46,11 +48,13 @@ class App : public mate::EventEmitter, void OnActivate(bool has_visible_windows) override; void OnWillFinishLaunching() override; void OnFinishLaunching() override; - void OnSelectCertificate( + void OnLogin(LoginHandler* login_handler) override; + + // content::ContentBrowserClient: + void SelectClientCertificate( content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, scoped_ptr delegate) override; - void OnLogin(LoginHandler* login_handler) override; // content::GpuDataManagerObserver: void OnGpuProcessCrashed(base::TerminationStatus exit_code) override; diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 4969ce47a679..7049f4896c12 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -14,7 +14,6 @@ #include "atom/browser/atom_quota_permission_context.h" #include "atom/browser/atom_resource_dispatcher_host_delegate.h" #include "atom/browser/atom_speech_recognition_manager_delegate.h" -#include "atom/browser/browser.h" #include "atom/browser/native_window.h" #include "atom/browser/web_contents_preferences.h" #include "atom/browser/window_list.h" @@ -88,7 +87,7 @@ void AtomBrowserClient::SetCustomSchemes( g_custom_schemes = JoinString(schemes, ','); } -AtomBrowserClient::AtomBrowserClient() { +AtomBrowserClient::AtomBrowserClient() : delegate_(nullptr) { } AtomBrowserClient::~AtomBrowserClient() { @@ -222,10 +221,10 @@ void AtomBrowserClient::SelectClientCertificate( return; } - if (!cert_request_info->client_certs.empty()) - Browser::Get()->ClientCertificateSelector(web_contents, - cert_request_info, - delegate.Pass()); + if (!cert_request_info->client_certs.empty() && delegate_) { + delegate_->SelectClientCertificate( + web_contents, cert_request_info, delegate.Pass()); + } } void AtomBrowserClient::ResourceDispatcherHostCreated() { diff --git a/atom/browser/atom_browser_client.h b/atom/browser/atom_browser_client.h index ee4700456cc6..25849e92d4f7 100644 --- a/atom/browser/atom_browser_client.h +++ b/atom/browser/atom_browser_client.h @@ -31,6 +31,9 @@ class AtomBrowserClient : public brightray::BrowserClient, AtomBrowserClient(); virtual ~AtomBrowserClient(); + using Delegate = content::ContentBrowserClient; + void set_delegate(Delegate* delegate) { delegate_ = delegate; } + // Don't force renderer process to restart for once. static void SuppressRendererProcessRestartForOnce(); // Custom schemes to be registered to standard. @@ -74,6 +77,8 @@ class AtomBrowserClient : public brightray::BrowserClient, scoped_ptr resource_dispatcher_host_delegate_; + Delegate* delegate_; + DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient); }; diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 57741786520d..c77f359760c9 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -10,8 +10,6 @@ #include "atom/browser/native_window.h" #include "atom/browser/window_list.h" #include "base/message_loop/message_loop.h" -#include "content/public/browser/client_certificate_delegate.h" -#include "net/ssl/ssl_cert_request_info.h" namespace atom { @@ -141,17 +139,6 @@ void Browser::DidFinishLaunching() { FOR_EACH_OBSERVER(BrowserObserver, observers_, OnFinishLaunching()); } -void Browser::ClientCertificateSelector( - content::WebContents* web_contents, - net::SSLCertRequestInfo* cert_request_info, - scoped_ptr delegate) { - FOR_EACH_OBSERVER(BrowserObserver, - observers_, - OnSelectCertificate(web_contents, - cert_request_info, - delegate.Pass())); -} - void Browser::RequestLogin(LoginHandler* login_handler) { FOR_EACH_OBSERVER(BrowserObserver, observers_, OnLogin(login_handler)); } diff --git a/atom/browser/browser.h b/atom/browser/browser.h index e20db080b67a..e46624b158df 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -126,12 +126,6 @@ class Browser : public WindowListObserver { void WillFinishLaunching(); void DidFinishLaunching(); - // Called when client certificate is required. - void ClientCertificateSelector( - content::WebContents* web_contents, - net::SSLCertRequestInfo* cert_request_info, - scoped_ptr delegate); - // Request basic auth login. void RequestLogin(LoginHandler* login_handler); diff --git a/atom/browser/browser_observer.h b/atom/browser/browser_observer.h index 7dccbfbac3c5..f6d76bc13fb3 100644 --- a/atom/browser/browser_observer.h +++ b/atom/browser/browser_observer.h @@ -7,17 +7,6 @@ #include -#include "base/memory/scoped_ptr.h" -#include "content/public/browser/client_certificate_delegate.h" - -namespace content { -class WebContents; -} - -namespace net { -class SSLCertRequestInfo; -} - namespace atom { class LoginHandler; @@ -53,12 +42,6 @@ class BrowserObserver { virtual void OnWillFinishLaunching() {} virtual void OnFinishLaunching() {} - // The browser requires client certificate. - virtual void OnSelectCertificate( - content::WebContents* web_contents, - net::SSLCertRequestInfo* cert_request_info, - scoped_ptr delegate) {} - // The browser requests HTTP login. virtual void OnLogin(LoginHandler* login_handler) {} From 341341bf28178481cfc17262395d94f7af7f5c98 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 18 Nov 2015 10:10:21 +0800 Subject: [PATCH 549/738] Rename select-certificate to select-client-certificate --- atom/browser/api/atom_api_app.cc | 2 +- atom/browser/api/lib/app.coffee | 1 + docs/api/app.md | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index b1efea5c45d3..95db0c61ed7f 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -247,7 +247,7 @@ void App::SelectClientCertificate( std::shared_ptr shared_delegate(delegate.release()); bool prevent_default = - Emit("select-certificate", + Emit("select-client-certificate", api::WebContents::CreateFrom(isolate(), web_contents), cert_request_info->host_and_port.ToString(), cert_request_info->client_certs, diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index f8d3cedd38f9..44efaa240652 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -52,6 +52,7 @@ deprecate.event app, 'finish-launching', 'ready', -> @emit 'finish-launching' deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) -> @emit 'activate-with-no-open-windows' if not hasVisibleWindows +deprecate.event app, 'select-certificate', 'select-client-certificate' # Wrappers for native classes. wrapSession = (session) -> diff --git a/docs/api/app.md b/docs/api/app.md index e1a4cbf964e3..4ff90f3e5785 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -131,7 +131,7 @@ Returns: Emitted when a new [browserWindow](browser-window.md) is created. -### Event: 'select-certificate' +### Event: 'select-client-certificate' Returns: @@ -151,7 +151,7 @@ and `callback` needs to be called with an entry filtered from the list. Using certificate from the store. ```javascript -app.on('select-certificate', function(event, host, url, list, callback) { +app.on('select-client-certificate', function(event, webContents, url, list, callback) { event.preventDefault(); callback(list[0]); }) From 74e8c8d6a59503c9cf9319bf8aa8249e85fd1d68 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 11:28:03 +0900 Subject: [PATCH 550/738] Translate docs, small changes --- docs-translations/ko-KR/README.md | 2 +- docs-translations/ko-KR/api/browser-window.md | 74 +++++++++---------- docs-translations/ko-KR/api/web-contents.md | 4 +- 3 files changed, 37 insertions(+), 43 deletions(-) diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index a6328586b5de..6899c91c32fa 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -32,7 +32,7 @@ * [app](api/app.md) * [autoUpdater](api/auto-updater.md) -* [BrowserWindow (30% 번역됨 - 작업중)](api/browser-window.md) +* [BrowserWindow (50% 번역됨 - 작업중)](api/browser-window.md) * [contentTracing](api/content-tracing.md) * [dialog](api/dialog.md) * [globalShortcut](api/global-shortcut.md) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 1046f8bd5ca7..df2d8b4572e1 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -228,139 +228,133 @@ someWindow.on('app-command', function(e, cmd) { ### `BrowserWindow.getAllWindows()` -Returns an array of all opened browser windows. +열려있는 모든 브라우저 윈도우의 배열을 반환합니다. ### `BrowserWindow.getFocusedWindow()` -Returns the window that is focused in this application. +어플리케이션에서 포커스된 윈도우를 반환합니다. ### `BrowserWindow.fromWebContents(webContents)` * `webContents` [WebContents](web-contents.md) -Find a window according to the `webContents` it owns. +`webContents`를 소유하고 있는 윈도우를 찾습니다. ### `BrowserWindow.fromId(id)` * `id` Integer -Find a window according to its ID. +ID에 해당하는 윈도우를 찾습니다. ### `BrowserWindow.addDevToolsExtension(path)` * `path` String -Adds DevTools extension located at `path`, and returns extension's name. +`path`에 있는 개발자 도구 확장 기능을 추가합니다. 그리고 확장 기능의 이름을 반환합니다. -The extension will be remembered so you only need to call this API once, this -API is not for programming use. +확장 기능은 기억됩니다. 따라서 API는 단 한 번만 호출되어야 합니다. +이 API는 실제 프로그램 작성에 사용할 수 없습니다. ### `BrowserWindow.removeDevToolsExtension(name)` * `name` String -Remove the DevTools extension whose name is `name`. +`name`에 해당하는 개발자 도구 확장 기능을 제거합니다. ## Instance Properties -Objects created with `new BrowserWindow` have the following properties: +`new BrowserWindow`로 생성한 객체는 다음과 같은 속성을 가지고 있습니다: ```javascript -// In this example `win` is our instance +// `win`은 BrowserWindow의 인스턴스입니다 var win = new BrowserWindow({ width: 800, height: 600 }); ``` ### `win.webContents` -The `WebContents` object this window owns, all web page related events and -operations will be done via it. +윈도우의 `WebContents` 객체입니다. 모든 웹 페이지와 관련된 이벤트와 작업이 이 객체를 통해 수행됩니다. -See the [`webContents` documentation](web-contents.md) for its methods and -events. +메서드나 이벤트에 대한 자세한 내용은 [`webContents` 문서](web-contents.md)를 참고하세요. ### `win.id` -The unique ID of this window. +윈도우의 유일 ID입니다. ## Instance Methods -Objects created with `new BrowserWindow` have the following instance methods: +`new BrowserWindow`로 생성한 객체는 다음과 같은 메서드들을 가지고 있습니다: -**Note:** Some methods are only available on specific operating systems and are labeled as such. +**참고:** 몇몇 메서드들은 라벨에서 특정한 운영체제 시스템에서만 작동합니다. ### `win.destroy()` -Force closing the window, the `unload` and `beforeunload` event won't be emitted -for the web page, and `close` event will also not be emitted -for this window, but it guarantees the `closed` event will be emitted. +윈도우를 강제로 닫습니다. 웹 페이지의 `unload` 와 `beforeunload` 이벤트는 일어나지 않습니다. +또한 이 윈도우의 `close`도 일어나지 않습니다. 하지만 `closed` 이벤트는 반드시 발생함을 보장합니다. -You should only use this method when the renderer process (web page) has -crashed. +이 메서드는 렌더러 프로세스가 예기치 않게 크래시가 일어났을 경우에만 사용해야 합니다. ### `win.close()` -Try to close the window, this has the same effect with user manually clicking -the close button of the window. The web page may cancel the close though, see -the [close event](#event-close). +윈도우의 종료를 시도합니다. 이 메서드는 사용자가 윈도우의 닫기 버튼을 클릭했을 때와 같은 효과를 냅니다. +웹 페이지는 로드가 취소되고 종료됩니다. 자세한 내용은 [close 이벤트](#event-close)를 참고하세요. ### `win.focus()` -Focus on the window. +윈도우에 포커스를 맞춥니다. ### `win.isFocused()` -Returns a boolean, whether the window is focused. +윈도우가 포커스 되었는지 여부를 반환합니다. ### `win.show()` -Shows and gives focus to the window. +윈도우를 표시하고 포커스합니다. ### `win.showInactive()` -Shows the window but doesn't focus on it. +윈도우를 표시만 하고 포커스하지 않습니다. ### `win.hide()` -Hides the window. +윈도우를 숨깁니다. ### `win.isVisible()` -Returns a boolean, whether the window is visible to the user. +윈도우가 사용자에게 표시되고 있는지 여부를 반환합니다. ### `win.maximize()` -Maximizes the window. +윈도우를 최대화 시킵니다. ### `win.unmaximize()` -Unmaximizes the window. +윈도우 최대화를 취소합니다. ### `win.isMaximized()` -Returns a boolean, whether the window is maximized. +윈도우가 최대화 되어있는지 여부를 반환합니다. ### `win.minimize()` -Minimizes the window. On some platforms the minimized window will be shown in -the Dock. +윈도우를 최소화 시킵니다. 어떤 플랫폼은 최소화된 윈도우가 Dock에 표시됩니다. ### `win.restore()` -Restores the window from minimized state to its previous state. +최소화된 윈도우를 이전 상태로 되돌립니다. ### `win.isMinimized()` -Returns a boolean, whether the window is minimized. +윈도우가 최소화 되었는지 여부를 반환합니다. ### `win.setFullScreen(flag)` * `flag` Boolean -Sets whether the window should be in fullscreen mode. +윈도우의 전체화면 상태를 지정합니다. ### `win.isFullScreen()` -Returns a boolean, whether the window is in fullscreen mode. +윈도우가 전체화면 모드 상태인지 여부를 반환합니다. ### `win.setAspectRatio(aspectRatio[, extraSize])` _OS X_ diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index 3193527f9c79..c1452f063791 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -190,7 +190,7 @@ Returns: webContents에서 사용되는 `session`객체를 반환합니다. -[session](session.md) 문서에서 이 객체의 메서드들을 확인할 수 있습니다. +[session 문서](session.md)에서 이 객체의 메서드들을 확인할 수 있습니다. ### `webContents.loadURL(url[, options])` @@ -283,7 +283,7 @@ var currentURL = win.webContents.getURL(); ### `webContents.isCrashed()` -렌더러 프로세스가 예기치 않게 종료되었는지 여부를 반환합니다. +렌더러 프로세스가 예기치 않게 종료 되었는지 여부를 반환합니다. ### `webContents.setUserAgent(userAgent)` From e432abfb4272c9822bad5ac1ac157f9a99aa755b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 18 Nov 2015 10:39:25 +0800 Subject: [PATCH 551/738] Add certificate-error event --- atom/browser/api/atom_api_app.cc | 53 +++++++++++++++++++--------- atom/browser/api/atom_api_app.h | 12 +++++++ atom/browser/api/atom_api_session.cc | 19 ---------- atom/browser/api/atom_api_session.h | 4 --- atom/browser/api/lib/app.coffee | 6 ++++ atom/browser/atom_browser_client.cc | 20 +++++++++++ atom/browser/atom_browser_client.h | 12 +++++++ 7 files changed, 87 insertions(+), 39 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 95db0c61ed7f..73f4b3927728 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -17,6 +17,7 @@ #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/net_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" +#include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/node_includes.h" #include "atom/common/options_switches.h" #include "base/command_line.h" @@ -27,6 +28,7 @@ #include "chrome/common/chrome_paths.h" #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/gpu_data_manager.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/common/content_switches.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" @@ -216,30 +218,49 @@ void App::OnFinishLaunching() { } void App::OnLogin(LoginHandler* login_handler) { - // Convert the args explicitly since they will be passed for twice. v8::Locker locker(isolate()); v8::HandleScope handle_scope(isolate()); - auto web_contents = - WebContents::CreateFrom(isolate(), login_handler->GetWebContents()); - auto request = mate::ConvertToV8(isolate(), login_handler->request()); - auto auth_info = mate::ConvertToV8(isolate(), login_handler->auth_info()); - auto callback = mate::ConvertToV8( - isolate(), + bool prevent_default = Emit( + "login", + WebContents::CreateFrom(isolate(), login_handler->GetWebContents()), + login_handler->request(), + login_handler->auth_info(), base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler))); - bool prevent_default = - Emit("login", web_contents, request, auth_info, callback); - - // Also pass it to WebContents. - if (!prevent_default) - prevent_default = - web_contents->Emit("login", request, auth_info, callback); - // Default behavior is to always cancel the auth. if (!prevent_default) login_handler->CancelAuth(); } +void App::AllowCertificateError( + int pid, + int fid, + int cert_error, + const net::SSLInfo& ssl_info, + const GURL& request_url, + content::ResourceType resource_type, + bool overridable, + bool strict_enforcement, + bool expired_previous_decision, + const base::Callback& callback, + content::CertificateRequestResultType* request) { + auto rfh = content::RenderFrameHost::FromID(pid, fid); + auto web_contents = content::WebContents::FromRenderFrameHost(rfh); + + v8::Locker locker(isolate()); + v8::HandleScope handle_scope(isolate()); + bool prevent_default = Emit("certificate-error", + WebContents::CreateFrom(isolate(), web_contents), + request_url, + cert_error, + ssl_info.cert, + callback); + + // Deny the certificate by default. + if (!prevent_default) + *request = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY; +} + void App::SelectClientCertificate( content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, @@ -248,7 +269,7 @@ void App::SelectClientCertificate( shared_delegate(delegate.release()); bool prevent_default = Emit("select-client-certificate", - api::WebContents::CreateFrom(isolate(), web_contents), + WebContents::CreateFrom(isolate(), web_contents), cert_request_info->host_and_port.ToString(), cert_request_info->client_certs, base::Bind(&OnClientCertificateSelected, diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index c3793cd54267..ee7e02079125 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -51,6 +51,18 @@ class App : public AtomBrowserClient::Delegate, void OnLogin(LoginHandler* login_handler) override; // content::ContentBrowserClient: + void AllowCertificateError( + int render_process_id, + int render_frame_id, + int cert_error, + const net::SSLInfo& ssl_info, + const GURL& request_url, + content::ResourceType resource_type, + bool overridable, + bool strict_enforcement, + bool expired_previous_decision, + const base::Callback& callback, + content::CertificateRequestResultType* request) override; void SelectClientCertificate( content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 6527f67ab3f1..3510a21668e9 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -238,12 +238,6 @@ void SetProxyInIO(net::URLRequestContextGetter* getter, RunCallbackInUI(callback); } -void PassVerificationResult( - scoped_refptr request, - bool success) { - request->ContinueWithResult(success ? net::OK : net::ERR_FAILED); -} - } // namespace Session::Session(AtomBrowserContext* browser_context) @@ -262,19 +256,6 @@ Session::~Session() { Destroy(); } -void Session::RequestCertVerification( - const scoped_refptr& request) { - bool prevent_default = Emit( - "untrusted-certificate", - request->args().hostname, - request->args().cert, - base::Bind(&PassVerificationResult, request)); - - if (!prevent_default) - // Tell the request to use the result of default verifier. - request->ContinueWithResult(net::ERR_IO_PENDING); -} - void Session::OnDownloadCreated(content::DownloadManager* manager, content::DownloadItem* item) { auto web_contents = item->GetWebContents(); diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index db72558db473..ebcfc45223db 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -54,10 +54,6 @@ class Session: public mate::TrackableObject, explicit Session(AtomBrowserContext* browser_context); ~Session(); - // AtomCertVerifier::Delegate: - void RequestCertVerification( - const scoped_refptr&) override; - // content::DownloadManager::Observer: void OnDownloadCreated(content::DownloadManager* manager, content::DownloadItem* item) override; diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 44efaa240652..3db4582abc7c 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -38,6 +38,12 @@ app.getAppPath = -> # Helpers. app.resolveProxy = (url, callback) -> @defaultSession.resolveProxy url, callback +# Routes the events to webContents. +for name in ['login', 'certificate-error', 'select-client-certificate'] + do (name) -> + app.on name, (event, webContents, args...) -> + webContents.emit name, event, args... + # Deprecated. {deprecate} = electron app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', -> diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 7049f4896c12..38fdc0e19f9e 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -207,6 +207,26 @@ content::QuotaPermissionContext* return new AtomQuotaPermissionContext; } +void AtomBrowserClient::AllowCertificateError( + int render_process_id, + int render_frame_id, + int cert_error, + const net::SSLInfo& ssl_info, + const GURL& request_url, + content::ResourceType resource_type, + bool overridable, + bool strict_enforcement, + bool expired_previous_decision, + const base::Callback& callback, + content::CertificateRequestResultType* request) { + if (delegate_) { + delegate_->AllowCertificateError( + render_process_id, render_frame_id, cert_error, ssl_info, request_url, + resource_type, overridable, strict_enforcement, + expired_previous_decision, callback, request); + } +} + void AtomBrowserClient::SelectClientCertificate( content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, diff --git a/atom/browser/atom_browser_client.h b/atom/browser/atom_browser_client.h index 25849e92d4f7..75e17494593b 100644 --- a/atom/browser/atom_browser_client.h +++ b/atom/browser/atom_browser_client.h @@ -57,6 +57,18 @@ class AtomBrowserClient : public brightray::BrowserClient, int child_process_id) override; void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override; content::QuotaPermissionContext* CreateQuotaPermissionContext() override; + void AllowCertificateError( + int render_process_id, + int render_frame_id, + int cert_error, + const net::SSLInfo& ssl_info, + const GURL& request_url, + content::ResourceType resource_type, + bool overridable, + bool strict_enforcement, + bool expired_previous_decision, + const base::Callback& callback, + content::CertificateRequestResultType* request) override; void SelectClientCertificate( content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, From 3af4a40860a2c048a07712a5b692bd9655efaac9 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 11:43:16 +0900 Subject: [PATCH 552/738] Translation docs --- docs-translations/ko-KR/api/browser-window.md | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index df2d8b4572e1..95780bc74ed2 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -388,92 +388,91 @@ height areas you have within the overall content view. * `width` Integer * `height` Integer -Resizes and moves the window to `width`, `height`, `x`, `y`. +윈도우를 지정한 `width`, `height`, `x`, `y`로 크기 재조정 및 이동합니다. ### `win.getBounds()` -Returns an object that contains window's width, height, x and y values. +윈도우의 width, height, x, y 값을 가지는 객체를 반환합니다. ### `win.setSize(width, height)` * `width` Integer * `height` Integer -Resizes the window to `width` and `height`. +`width`와 `height` 값으로 윈도우 크기를 재조정합니다. (너비, 높이) ### `win.getSize()` -Returns an array that contains window's width and height. +윈도우의 너비, 높이값을 가지는 배열을 반환합니다. ### `win.setContentSize(width, height)` * `width` Integer * `height` Integer -Resizes the window's client area (e.g. the web page) to `width` and `height`. +윈도우 클라이언트 영역(웹 페이지)의 크기를 `width`, `height`로 재조정합니다. ### `win.getContentSize()` -Returns an array that contains window's client area's width and height. +윈도우 클라이언트 영역의 너비, 높이 크기를 배열로 반환합니다. ### `win.setMinimumSize(width, height)` * `width` Integer * `height` Integer -Sets the minimum size of window to `width` and `height`. +윈도우의 최소 `width`, `height` 크기를 지정합니다. ### `win.getMinimumSize()` -Returns an array that contains window's minimum width and height. +윈도우의 최소 너비, 높이 크기를 배열로 반환합니다. ### `win.setMaximumSize(width, height)` * `width` Integer * `height` Integer -Sets the maximum size of window to `width` and `height`. +윈도우의 최대 `width`, `height` 크기를 지정합니다. ### `win.getMaximumSize()` -Returns an array that contains window's maximum width and height. +윈도우의 최대 너비, 높이 크기를 배열로 반환합니다. ### `win.setResizable(resizable)` * `resizable` Boolean -Sets whether the window can be manually resized by user. +윈도우의 크기가 사용자에 의해 재조정될 수 있는지를 지정합니다. ### `win.isResizable()` -Returns whether the window can be manually resized by user. +윈도우의 크기가 사용자에 의해 재조정될 수 있는지 여부를 반환합니다. ### `win.setAlwaysOnTop(flag)` * `flag` Boolean -Sets whether the window should show always on top of other windows. After -setting this, the window is still a normal window, not a toolbox window which -can not be focused on. +윈도우가 언제나 다른 윈도우들 위에 표시되는지 여부를 지정합니다. +이 설정을 활성화 하면 윈도우는 포커스 될 수 없는 툴박스 윈도우가 아닌 일반 윈도우로 유지됩니다. ### `win.isAlwaysOnTop()` -Returns whether the window is always on top of other windows. +윈도우가 언제나 다른 윈도우들 위에 표시되는지 여부를 반환합니다. ### `win.center()` -Moves window to the center of the screen. +윈도우를 화면 정 중앙으로 이동합니다. ### `win.setPosition(x, y)` * `x` Integer * `y` Integer -Moves window to `x` and `y`. +윈도우의 위치를 `x`, `y`로 이동합니다. ### `win.getPosition()` -Returns an array that contains window's current position. +윈도우의 현재 위치를 배열로 반환합니다. ### `win.setTitle(title)` From c5bfac196914218ff98d2a45bc6287641594deea Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 18 Nov 2015 11:17:08 +0800 Subject: [PATCH 553/738] Add session.setCertificateVerifyProc --- atom/browser/api/atom_api_session.cc | 15 +++++- atom/browser/api/atom_api_session.h | 3 +- atom/browser/net/atom_cert_verifier.cc | 74 ++++++++++---------------- atom/browser/net/atom_cert_verifier.h | 61 ++++----------------- 4 files changed, 51 insertions(+), 102 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 3510a21668e9..2a2c7b2fff35 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -13,6 +13,7 @@ #include "atom/browser/api/save_page_handler.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" +#include "atom/browser/net/atom_cert_verifier.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" @@ -243,7 +244,6 @@ void SetProxyInIO(net::URLRequestContextGetter* getter, Session::Session(AtomBrowserContext* browser_context) : browser_context_(browser_context) { AttachAsUserData(browser_context); - browser_context->cert_verifier()->SetDelegate(this); // Observe DownloadManger to get download notifications. content::BrowserContext::GetDownloadManager(browser_context)-> @@ -276,7 +276,6 @@ bool Session::IsDestroyed() const { } void Session::Destroy() { - browser_context_->cert_verifier()->SetDelegate(nullptr); browser_context_ = nullptr; } @@ -358,6 +357,17 @@ void Session::DisableNetworkEmulation() { base::Passed(&conditions))); } +void Session::SetCertVerifyProc(v8::Local val, mate::Arguments* args) { + AtomCertVerifier::VerifyProc proc; + if (val.IsEmpty() || + !(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &proc))) { + args->ThrowError("Must pass null or function"); + return; + } + + browser_context_->cert_verifier()->SetVerifyProc(proc); +} + v8::Local Session::Cookies(v8::Isolate* isolate) { if (cookies_.IsEmpty()) { auto handle = atom::api::Cookies::Create(isolate, browser_context()); @@ -376,6 +386,7 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( .SetMethod("setDownloadPath", &Session::SetDownloadPath) .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation) .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation) + .SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc) .SetProperty("cookies", &Session::Cookies); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index ebcfc45223db..01dc0a408a8c 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -8,7 +8,6 @@ #include #include "atom/browser/api/trackable_object.h" -#include "atom/browser/net/atom_cert_verifier.h" #include "content/public/browser/download_manager.h" #include "native_mate/handle.h" #include "net/base/completion_callback.h" @@ -35,7 +34,6 @@ class AtomBrowserContext; namespace api { class Session: public mate::TrackableObject, - public AtomCertVerifier::Delegate, public content::DownloadManager::Observer { public: using ResolveProxyCallback = base::Callback; @@ -74,6 +72,7 @@ class Session: public mate::TrackableObject, void SetDownloadPath(const base::FilePath& path); void EnableNetworkEmulation(const mate::Dictionary& options); void DisableNetworkEmulation(); + void SetCertVerifyProc(v8::Local proc, mate::Arguments* args); v8::Local Cookies(v8::Isolate* isolate); // Cached object for cookies API. diff --git a/atom/browser/net/atom_cert_verifier.cc b/atom/browser/net/atom_cert_verifier.cc index 0f94e4fe2ad2..3633d805fb5b 100644 --- a/atom/browser/net/atom_cert_verifier.cc +++ b/atom/browser/net/atom_cert_verifier.cc @@ -15,30 +15,31 @@ using content::BrowserThread; namespace atom { -AtomCertVerifier::CertVerifyRequest::~CertVerifyRequest() { -} +namespace { -void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - if (handled_) - return; - - handled_ = true; +void OnResult( + net::CertVerifyResult* verify_result, + const net::CompletionCallback& callback, + bool result) { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(args_.callback, - result == net::ERR_IO_PENDING ? result_ : result)); + base::Bind(callback, result ? net::OK : net::ERR_FAILED)); } +} // namespace + AtomCertVerifier::AtomCertVerifier() - : delegate_(nullptr) { - default_cert_verifier_.reset(net::CertVerifier::CreateDefault()); + : default_cert_verifier_(net::CertVerifier::CreateDefault()) { } AtomCertVerifier::~AtomCertVerifier() { } +void AtomCertVerifier::SetVerifyProc(const VerifyProc& proc) { + base::AutoLock auto_lock(lock_); + verify_proc_ = proc; +} + int AtomCertVerifier::Verify( net::X509Certificate* cert, const std::string& hostname, @@ -51,45 +52,26 @@ int AtomCertVerifier::Verify( const net::BoundNetLog& net_log) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (callback.is_null() || !verify_result || hostname.empty() || !delegate_) - return net::ERR_INVALID_ARGUMENT; - - VerifyArgs args = { cert, hostname, callback }; - int result = default_cert_verifier_->Verify( - cert, hostname, ocsp_response, flags, crl_set, verify_result, - base::Bind(&AtomCertVerifier::OnDefaultVerificationResult, - base::Unretained(this), args), - out_req, net_log); - if (result != net::OK && result != net::ERR_IO_PENDING) { - // The default verifier fails immediately. - VerifyCertificateFromDelegate(args, result); - return net::ERR_IO_PENDING; + VerifyProc proc; + { + base::AutoLock auto_lock(lock_); + proc = verify_proc_; } - return result; + if (proc.is_null()) + return default_cert_verifier_->Verify( + cert, hostname, ocsp_response, flags, crl_set, verify_result, callback, + out_req, net_log); + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(proc, hostname, make_scoped_refptr(cert), + base::Bind(OnResult, verify_result, callback))); + return net::ERR_IO_PENDING; } bool AtomCertVerifier::SupportsOCSPStapling() { return true; } -void AtomCertVerifier::VerifyCertificateFromDelegate( - const VerifyArgs& args, int result) { - CertVerifyRequest* request = new CertVerifyRequest(this, result, args); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&Delegate::RequestCertVerification, - base::Unretained(delegate_), - make_scoped_refptr(request))); -} - -void AtomCertVerifier::OnDefaultVerificationResult( - const VerifyArgs& args, int result) { - if (result == net::OK) { - args.callback.Run(result); - return; - } - - VerifyCertificateFromDelegate(args, result); -} - } // namespace atom diff --git a/atom/browser/net/atom_cert_verifier.h b/atom/browser/net/atom_cert_verifier.h index 8736db0f8723..796ae2849bda 100644 --- a/atom/browser/net/atom_cert_verifier.h +++ b/atom/browser/net/atom_cert_verifier.h @@ -8,61 +8,22 @@ #include #include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" #include "net/cert/cert_verifier.h" namespace atom { class AtomCertVerifier : public net::CertVerifier { public: - struct VerifyArgs { - scoped_refptr cert; - const std::string& hostname; - net::CompletionCallback callback; - }; - - class CertVerifyRequest - : public base::RefCountedThreadSafe { - public: - CertVerifyRequest(AtomCertVerifier* cert_verifier, - int result, - const VerifyArgs& args) - : cert_verifier_(cert_verifier), - result_(result), - args_(args), - handled_(false) { - } - - void ContinueWithResult(int result); - - const VerifyArgs& args() const { return args_; } - - private: - friend class base::RefCountedThreadSafe; - ~CertVerifyRequest(); - - AtomCertVerifier* cert_verifier_; - int result_; - VerifyArgs args_; - bool handled_; - - DISALLOW_COPY_AND_ASSIGN(CertVerifyRequest); - }; - - class Delegate { - public: - virtual ~Delegate() {} - - // Called on UI thread. - virtual void RequestCertVerification( - const scoped_refptr& request) {} - }; - AtomCertVerifier(); virtual ~AtomCertVerifier(); - void SetDelegate(Delegate* delegate) { - delegate_ = delegate; - } + using VerifyProc = + base::Callback, + const base::Callback&)>; + + void SetVerifyProc(const VerifyProc& proc); protected: // net::CertVerifier: @@ -78,12 +39,8 @@ class AtomCertVerifier : public net::CertVerifier { bool SupportsOCSPStapling() override; private: - friend class CertVerifyRequest; - - void VerifyCertificateFromDelegate(const VerifyArgs& args, int result); - void OnDefaultVerificationResult(const VerifyArgs& args, int result); - - Delegate* delegate_; + base::Lock lock_; + VerifyProc verify_proc_; scoped_ptr default_cert_verifier_; DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier); From 9ca022c98a30788d2074a585128b7df8106c6c7b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 18 Nov 2015 11:35:26 +0800 Subject: [PATCH 554/738] docs: Update the certificate APIs --- atom/browser/api/atom_api_app.cc | 2 +- docs/api/app.md | 29 ++++++++++++++++++++ docs/api/session.md | 46 +++++++++++++++----------------- docs/api/web-contents.md | 33 +++++++++++++++++++++++ 4 files changed, 84 insertions(+), 26 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 73f4b3927728..28c3b4c15983 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -252,7 +252,7 @@ void App::AllowCertificateError( bool prevent_default = Emit("certificate-error", WebContents::CreateFrom(isolate(), web_contents), request_url, - cert_error, + net::ErrorToString(cert_error), ssl_info.cert, callback); diff --git a/docs/api/app.md b/docs/api/app.md index 4ff90f3e5785..d7850c4cb92c 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -131,6 +131,35 @@ Returns: Emitted when a new [browserWindow](browser-window.md) is created. +### Event: 'certificate-error' + +Returns: + +* `event` Event +* `webContents` [WebContents](web-contents.md) +* `url` URL +* `error` String - The error code +* `certificate` Object + * `data` Buffer - PEM encoded data + * `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)`. + +```javascript +session.on('certificate-error', function(event, webContents, url, error, certificate, callback) { + if (url == "https://github.com") { + // Verification logic. + event.preventDefault(); + callback(true); + } else { + callback(false); + } +}); +``` + ### Event: 'select-client-certificate' Returns: diff --git a/docs/api/session.md b/docs/api/session.md index e385e222d529..450be7b08e11 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -34,31 +34,6 @@ session.on('will-download', function(event, item, webContents) { }); ``` -### Event: 'untrusted-certificate' - -* `event` Event -* `hostname` String -* `certificate` Object - * `data` Buffer - PEM encoded data - * `issuerName` String -* `callback` Function - -Emitted when failed to verify the `certificate` for `hostname`, to trust the -certificate you should prevent the default behavior with -`event.preventDefault()` and call `callback(true)`. - -```js -session.on('verify-certificate', function(event, hostname, certificate, callback) { - if (hostname == "github.com") { - // Verification logic. - event.preventDefault(); - callback(true); - } else { - callback(false); - } -}); -``` - ## Methods The `session` object has the following methods: @@ -245,3 +220,24 @@ window.webContents.session.enableNetworkEmulation({offline: true}); Disables any network emulation already active for the `session`. Resets to the original network configuration. + +### `session.setCertificateVerifyProc(proc)` + +* `proc` Function + +Sets the certificate verify proc for `session`, the `proc` will be called with +`proc(hostname, certificate, callback)` whenever a server certificate +verification is requested. Calling `callback(true)` accepts the certificate, +calling `callback(false)` rejects it. + +Calling `setCertificateVerifyProc(null)` will revert back to default certificate +verify proc. + +```javascript +myWindow.webContents.session.setCertificateVerifyProc(function(hostname, cert, callback) { + if (hostname == 'github.com') + callback(true); + else + callback(false); +}); +``` diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 0988d25276f4..be22d947c752 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -167,6 +167,39 @@ Emitted when DevTools is closed. Emitted when DevTools is focused / opened. +### Event: 'certificate-error' + +Returns: + +* `event` Event +* `url` URL +* `error` String - The error code +* `certificate` Object + * `data` Buffer - PEM encoded data + * `issuerName` String +* `callback` Function + +Emitted when failed to verify the `certificate` for `url`. + +The usage is the same with [the `certificate-error` event of +`app`](app.md#event-certificate-error). + +### Event: 'select-client-certificate' + +Returns: + +* `event` Event +* `url` URL +* `certificateList` [Objects] + * `data` Buffer - PEM encoded data + * `issuerName` String - Issuer's Common Name +* `callback` Function + +Emitted when a client certificate is requested. + +The usage is the same with [the `select-client-certificate` event of +`app`](app.md#event-select-client-certificate). + ### Event: 'login' Returns: From 47d7f2c0503231054a80a5c2a3769cf01ddcfbbb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 18 Nov 2015 11:45:15 +0800 Subject: [PATCH 555/738] Fix cpplint warning --- atom/browser/api/atom_api_session.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 2a2c7b2fff35..27e1521f3d3f 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -357,10 +357,10 @@ void Session::DisableNetworkEmulation() { base::Passed(&conditions))); } -void Session::SetCertVerifyProc(v8::Local val, mate::Arguments* args) { +void Session::SetCertVerifyProc(v8::Local val, + mate::Arguments* args) { AtomCertVerifier::VerifyProc proc; - if (val.IsEmpty() || - !(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &proc))) { + if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &proc))) { args->ThrowError("Must pass null or function"); return; } From 25e5c385561e7ebf625f7534c024b78239f41b26 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 12:45:33 +0900 Subject: [PATCH 556/738] Small changes --- docs-translations/ko-KR/api/browser-window.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 95780bc74ed2..f34830bede3a 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -472,19 +472,19 @@ height areas you have within the overall content view. ### `win.getPosition()` -윈도우의 현재 위치를 배열로 반환합니다. +윈도우의 위치를 배열로 반환합니다. ### `win.setTitle(title)` * `title` String -Changes the title of native window to `title`. +`title`을 네이티브 윈도우의 제목으로 지정합니다. ### `win.getTitle()` -Returns the title of the native window. +윈도우의 제목을 반환합니다. -**Note:** The title of web page can be different from the title of the native +**참고:** The title of web page can be different from the title of the native window. ### `win.flashFrame(flag)` @@ -689,10 +689,10 @@ Returns whether the menu bar is visible. Sets whether the window should be visible on all workspaces. -**Note:** This API does nothing on Windows. +**참고:** 이 API는 Windows에서 아무 일도 하지 않습니다. ### `win.isVisibleOnAllWorkspaces()` Returns whether the window is visible on all workspaces. -**Note:** This API always returns false on Windows. +**참고:** 이 API는 Windows에서 언제나 false를 반환합니다. From bcdd0952f8decce11bf30723422142cf624e3440 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 18 Nov 2015 17:56:50 +0800 Subject: [PATCH 557/738] docs: Fix typo --- docs/api/protocol.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/protocol.md b/docs/api/protocol.md index 0f854a2bb2f2..5f34165fa84a 100644 --- a/docs/api/protocol.md +++ b/docs/api/protocol.md @@ -103,7 +103,7 @@ Registers a protocol of `scheme` that will send a `String` as a response. The Registers a protocol of `scheme` that will send an HTTP request as a response. The `callback` should be called with an object that has the `url`, `method`, -`referer`, and `session` properties. +`referrer`, and `session` properties. By default the HTTP request will reuse the current session. If you want the request to have a different session you should set `session` to `null`. From 6892f0d2d4b8a04b1debe7c81b49bf78b32bd3c8 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 22:14:24 +0900 Subject: [PATCH 558/738] Add missed translation --- docs-translations/ko-KR/api/session.md | 33 +++++++++++--------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index 749ca6efbb0f..5df45f4ac216 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -181,25 +181,20 @@ proxy-uri-list = [","] proxy-uri = ["://"][":"] 예시: - "http=foopy:80;ftp=foopy2" -- use HTTP proxy "foopy:80" for http:// - URLs, and HTTP proxy "foopy2:80" for - ftp:// URLs. - "foopy:80" -- use HTTP proxy "foopy:80" for all URLs. - "foopy:80,bar,direct://" -- use HTTP proxy "foopy:80" for all URLs, - failing over to "bar" if "foopy:80" is - unavailable, and after that using no - proxy. - "socks4://foopy" -- use SOCKS v4 proxy "foopy:1080" for all - URLs. - "http=foopy,socks5://bar.com -- use HTTP proxy "foopy" for http URLs, - and fail over to the SOCKS5 proxy - "bar.com" if "foopy" is unavailable. - "http=foopy,direct:// -- use HTTP proxy "foopy" for http URLs, - and use no proxy if "foopy" is - unavailable. - "http=foopy;socks=foopy2 -- use HTTP proxy "foopy" for http URLs, - and use socks4://foopy2 for all other - URLs. + "http=foopy:80;ftp=foopy2" -- http:// URL에 "foopy:80" HTTP 프록시를 사용합니다. + "foopy2:80" 는 ftp:// URL에 사용됩니다. + "foopy:80" -- 모든 URL에 "foopy:80" 프록시를 사용합니다. + "foopy:80,bar,direct://" -- 모든 URL에 "foopy:80" HTTP 프록시를 사용합니다. + 문제가 발생하여 "foopy:80"를 사용할 수 없는 경우 "bar"를 대신 사용하여 + 장애를 복구하며 그 다음 문제가 생긴 경우 프록시를 사용하지 않습니다. + "socks4://foopy" -- 모든 URL에 "foopy:1000" SOCKS v4 프록시를 사용합니다. + "http=foopy,socks5://bar.com -- http:// URL에 "foopy" HTTP 프록시를 사용합니다. + 문제가 발생하여 "foopy"를 사용할 수 없는 경우 SOCKS5 "bar.com" + 프록시를 대신 사용합니다. + "http=foopy,direct:// -- http:// URL에 "foopy" HTTP 프록시를 사용합니다. + 그리고 문제가 발생하여 "foopy"를 사용할 수 없는 경우 프록시를 사용하지 않습니다. + "http=foopy;socks=foopy2 -- http:// URL에 "foopy" HTTP 프록시를 사용합니다. + 그리고 "socks4://foopy2" 프록시를 다른 모든 URL에 사용합니다. ``` ### `session.setDownloadPath(path)` From 250575719d82a2a851a837dcfb7aaca68acd659f Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 23:32:47 +0900 Subject: [PATCH 559/738] Translate docs --- docs-translations/ko-KR/api/browser-window.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index f34830bede3a..06b6543fe6e0 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -484,38 +484,36 @@ height areas you have within the overall content view. 윈도우의 제목을 반환합니다. -**참고:** The title of web page can be different from the title of the native -window. +**참고:** 웹 페이지의 제목과 네이티브 윈도우의 제목은 서로 다를 수 있습니다. ### `win.flashFrame(flag)` * `flag` Boolean -Starts or stops flashing the window to attract user's attention. +사용자가 윈도우에 관심을 가질 수 있도록 창을 깜빡이거나 이를 중지합니다. ### `win.setSkipTaskbar(skip)` * `skip` Boolean -Makes the window not show in the taskbar. +어플리케이션 아이콘을 작업 표시줄에 보이지 않도록 설정합니다. ### `win.setKiosk(flag)` * `flag` Boolean -Enters or leaves the kiosk mode. +Kiosk(키오스크) 모드를 설정합니다. ### `win.isKiosk()` -Returns whether the window is in kiosk mode. +현재 윈도우가 kiosk 모드인지 여부를 반환합니다. ### `win.hookWindowMessage(message, callback)` _WINDOWS_ * `message` Integer * `callback` Function -Hooks a windows message. The `callback` is called when -the message is received in the WndProc. +Windows 메시지를 후킹합니다. `callback`은 WndProc에서 메시지를 받았을 때 호출됩니다. ### `win.isWindowMessageHooked(message)` _WINDOWS_ From 0c2d769b8a96364552a9e48311adf23cdc06e4ae Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 23:35:36 +0900 Subject: [PATCH 560/738] Fix platform label to uppercase --- docs/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index e5fcfb9003ae..ca9b621cd835 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -232,7 +232,7 @@ Emitted when the window enters full screen state triggered by html api. Emitted when the window leaves full screen state triggered by html api. -### Event: 'app-command' _Windows_ +### Event: 'app-command' _WINDOWS_ Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) is invoked. These are typically related to keyboard media keys or browser From 9db4af4cf32c1867d2461f9f084149df944f36d1 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 23:36:20 +0900 Subject: [PATCH 561/738] Fix platform label to uppercase (ko) --- docs-translations/ko-KR/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 06b6543fe6e0..3db59f38e637 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -207,7 +207,7 @@ __참고__: OS X에선 이 이벤트가 그저 `moved` 이벤트의 별칭(alias 윈도우가 HTML API에 의해 풀 스크린 모드에서 해제될 때 발생하는 이벤트입니다. -### Event: 'app-command' _Windows_ +### Event: 'app-command' _WINDOWS_ [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)가 호출됐을 때 발생하는 이벤트입니다. 이 이벤트는 일반적으로 키보드 미디어 키 또는 브라우저 커맨드(기본 동작 키)에 관련되어 있습니다. From cc5a4f1dfeb6a5c2faba6951d2b803db348a214c Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 18 Nov 2015 23:42:03 +0900 Subject: [PATCH 562/738] Update as upstream --- docs-translations/ko-KR/api/tray.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/tray.md b/docs-translations/ko-KR/api/tray.md index 96722bb2409e..7a883b026797 100644 --- a/docs-translations/ko-KR/api/tray.md +++ b/docs-translations/ko-KR/api/tray.md @@ -169,7 +169,8 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다. * `highlight` Boolean -트레이 아이콘을 클릭했을 때 하이라이트 될지 설정합니다. +트레이 아이콘이 클릭됐을 때 아이콘의 배경이 파란색으로 하이라이트 될지 여부를 지정합니다. +기본값은 true입니다. ### `Tray.displayBalloon(options)` _Windows_ From f0d2bc87e81f90a775d54a82f5faeab50afa0c32 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 19 Nov 2015 02:50:04 +0900 Subject: [PATCH 563/738] Add translation, improve grammar --- docs-translations/ko-KR/api/browser-window.md | 94 +++++++++---------- docs-translations/ko-KR/api/web-contents.md | 2 +- 2 files changed, 46 insertions(+), 50 deletions(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 3db59f38e637..eb68c8c8e716 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -304,7 +304,7 @@ var win = new BrowserWindow({ width: 800, height: 600 }); ### `win.isFocused()` -윈도우가 포커스 되었는지 여부를 반환합니다. +윈도우가 포커스되었는지 여부를 반환합니다. ### `win.show()` @@ -344,7 +344,7 @@ var win = new BrowserWindow({ width: 800, height: 600 }); ### `win.isMinimized()` -윈도우가 최소화 되었는지 여부를 반환합니다. +윈도우가 최소화되었는지 여부를 반환합니다. ### `win.setFullScreen(flag)` @@ -513,45 +513,43 @@ Kiosk(키오스크) 모드를 설정합니다. * `message` Integer * `callback` Function -Windows 메시지를 후킹합니다. `callback`은 WndProc에서 메시지를 받았을 때 호출됩니다. +Windows 메시지 훅을 등록합니다. `callback`은 WndProc에서 메시지를 받았을 때 호출됩니다. ### `win.isWindowMessageHooked(message)` _WINDOWS_ * `message` Integer -Returns `true` or `false` depending on whether the message is hooked. +지정한 메시지가 후킹됬는지 여부를 반환합니다. ### `win.unhookWindowMessage(message)` _WINDOWS_ * `message` Integer -Unhook the window message. +지정한 메시지 훅을 등록 해제합니다. ### `win.unhookAllWindowMessages()` _WINDOWS_ -Unhooks all of the window messages. +모든 메시지 훅을 등록 해제합니다. ### `win.setRepresentedFilename(filename)` _OS X_ * `filename` String -Sets the pathname of the file the window represents, and the icon of the file -will show in window's title bar. +윈도우 대표 파일의 경로명을 설정합니다. 파일의 아이콘이 윈도우 타이틀 바에 표시됩니다. ### `win.getRepresentedFilename()` _OS X_ -Returns the pathname of the file the window represents. +윈도우 대표 파일의 경로명을 반환합니다. ### `win.setDocumentEdited(edited)` _OS X_ * `edited` Boolean -Specifies whether the window’s document has been edited, and the icon in title -bar will become grey when set to `true`. +윈도우의 문서가 변경되었는지 여부를 설정합니다. 그리고 `true`로 설정했을 때 타이틀 바의 아이콘이 회색으로 표시됩니다. ### `win.isDocumentEdited()` _OS X_ -Whether the window's document has been edited. +윈도우의 문서가 변경되었는지 여부를 반환합니다. ### `win.focusOnWebView()` @@ -559,69 +557,65 @@ 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)- 캡쳐할 페이지의 영역. 사용할 수 있는 속성은 다음과 같습니다: * `x` Integer * `y` Integer * `width` Integer * `height` Integer * `callback` Function -Captures a snapshot of the page within `rect`. Upon completion `callback` will -be called with `callback(image)`. The `image` is an instance of -[NativeImage](native-image.md) that stores data of the snapshot. Omitting -`rect` will capture the whole visible page. +페이지의 스크린샷을 `rect`에 설정한 만큼 캡처합니다. +캡처가 완료되면 `callback`이 `callback(image)` 형식으로 호출됩니다. +`image`는 [NativeImage](native-image.md)의 인스턴스이며 스크린샷 데이터를 담고있습니다. +`rect`를 생략하면 페이지 전체를 캡처합니다. ### `win.print([options])` -Same as `webContents.print([options])` +`webContents.print([options])` API와 같습니다. ### `win.printToPDF(options, callback)` -Same as `webContents.printToPDF(options, callback)` +`webContents.printToPDF(options, callback)` API와 같습니다. ### `win.loadURL(url[, options])` -Same as `webContents.loadURL(url[, options])`. +`webContents.loadURL(url[, options])` API와 같습니다. ### `win.reload()` -Same as `webContents.reload`. +`webContents.reload` API와 같습니다. ### `win.setMenu(menu)` _Linux_ _Windows_ * `menu` Menu -Sets the `menu` as the window's menu bar, setting it to `null` will remove the -menu bar. +지정한 `menu`를 윈도우의 메뉴로 설정합니다 `null`을 설정하면 메뉴를 제거합니다. ### `win.setProgressBar(progress)` * `progress` Double -Sets progress value in progress bar. Valid range is [0, 1.0]. +작업 표시줄에 표시되고 있는 어플리케이션 아이콘에 진행 상태를 표시합니다. [0, 1.0] 사이의 값을 지정할 수 있습니다. -Remove progress bar when progress < 0; -Change to indeterminate mode when progress > 1. +진행 상태가 < 0 이 되면 진행 상태 표시를 제거합니다. +진행 상태가 > 1 이 되면 불확정 상태 표시로 전환합니다. -On Linux platform, only supports Unity desktop environment, you need to specify -the `*.desktop` file name to `desktopName` field in `package.json`. By default, -it will assume `app.getName().desktop`. +Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. +그리고 이 기능을 사용하려면 `*.desktop` 파일을 생성한 후 `package.json`의 `desktopName` 필드에 파일 이름을 지정해야 합니다. +기본적으로 `app.getName().desktop`을 통해 접근합니다. ### `win.setOverlayIcon(overlay, description)` _Windows 7+_ -* `overlay` [NativeImage](native-image.md) - the icon to display on the bottom -right corner of the taskbar icon. If this parameter is `null`, the overlay is -cleared -* `description` String - a description that will be provided to Accessibility -screen readers - -Sets a 16px overlay onto the current taskbar icon, usually used to convey some -sort of application status or to passively notify the user. +* `overlay` [NativeImage](native-image.md) - 작업 표시줄 아이콘의 우측 하단에 표시될 아이콘입니다. +`null`로 지정하면 빈 오버레이가 사용됩니다 +* `description` String - 접근성 설정에 의한 스크린 리더에 제공될 설명입니다 +현재 작업 표시줄 아이콘에 16px 크기의 오버레이를 지정합니다. +보통 이 기능은 어플리케이션의 여러 상태를 사용자에게 소극적으로 알리기 위한 방법으로 사용됩니다. ### `win.setThumbarButtons(buttons)` _Windows 7+_ -`buttons` Array of `button` Objects: +`buttons` `button` 객체의 배열: `button` Object, properties: @@ -654,43 +648,45 @@ array to clean the buttons. ### `win.showDefinitionForSelection()` _OS X_ -Shows pop-up dictionary that searches the selected word on the page. +페이지의 선택된 단어에 대한 사전 검색 결과 팝업을 표시합니다. ### `win.setAutoHideMenuBar(hide)` * `hide` Boolean -Sets whether the window menu bar should hide itself automatically. Once set the -menu bar will only show when users press the single `Alt` key. +메뉴 막대 자동 숨김 기능을 활성화 합니다. +숨겨진 메뉴는 사용자가 `Alt` 키를 단일 입력했을 때만 표시됩니다. -If the menu bar is already visible, calling `setAutoHideMenuBar(true)` won't -hide it immediately. +메뉴 막대가 이미 표시되고 있을 때 `setAutoHideMenuBar(true)`를 호출한다고 해서 메뉴가 즉시 숨겨지지는 않습니다. ### `win.isMenuBarAutoHide()` -Returns whether menu bar automatically hides itself. +메뉴 막대 자동 숨김 상태인지 여부를 반환합니다. ### `win.setMenuBarVisibility(visible)` * `visible` Boolean -Sets whether the menu bar should be visible. If the menu bar is auto-hide, users -can still bring up the menu bar by pressing the single `Alt` key. +메뉴 막대의 표시 여부를 설정합니다. +만약 메뉴 막대 자동 숨김 상태라면 여전히 사용자가 `Alt` 키를 입력하여 메뉴 막대를 표시되도록 할 수 있습니다. + +**역주:** 기본 메뉴 막대를 완전히 없애려면 `win.setMenu(null)`을 호출해야 합니다. +단순히 이 API를 사용하면 여전히 메뉴에 등록된 핫 키가 작동합니다. ### `win.isMenuBarVisible()` -Returns whether the menu bar is visible. +메뉴 막대가 표시되고 있는지 여부를 반환합니다. ### `win.setVisibleOnAllWorkspaces(visible)` * `visible` Boolean -Sets whether the window should be visible on all workspaces. +윈도우가 모든 워크스페이스에서 보여질지 여부를 설정합니다. **참고:** 이 API는 Windows에서 아무 일도 하지 않습니다. ### `win.isVisibleOnAllWorkspaces()` -Returns whether the window is visible on all workspaces. +윈도우가 모든 워크스페이스에서 보여질지 여부를 반환합니다. **참고:** 이 API는 Windows에서 언제나 false를 반환합니다. diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index c1452f063791..1bad5b47e863 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -283,7 +283,7 @@ var currentURL = win.webContents.getURL(); ### `webContents.isCrashed()` -렌더러 프로세스가 예기치 않게 종료 되었는지 여부를 반환합니다. +렌더러 프로세스가 예기치 않게 종료되었는지 여부를 반환합니다. ### `webContents.setUserAgent(userAgent)` From 70c7abbbfeb0b1f2aba88e58e069152d801a4203 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 19 Nov 2015 02:51:27 +0900 Subject: [PATCH 564/738] Small changes --- docs-translations/ko-KR/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index eb68c8c8e716..6d5cdf1659af 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -670,7 +670,7 @@ array to clean the buttons. 메뉴 막대의 표시 여부를 설정합니다. 만약 메뉴 막대 자동 숨김 상태라면 여전히 사용자가 `Alt` 키를 입력하여 메뉴 막대를 표시되도록 할 수 있습니다. -**역주:** 기본 메뉴 막대를 완전히 없애려면 `win.setMenu(null)`을 호출해야 합니다. +**역주:** 기본 메뉴 막대를 완전히 없애려면 `win.setMenu(null)`를 호출해야 합니다. 단순히 이 API를 사용하면 여전히 메뉴에 등록된 핫 키가 작동합니다. ### `win.isMenuBarVisible()` From e2cd0578f3c32a935c9477f3fa2b4d4aae64fcb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Galv=C3=A3o?= Date: Wed, 18 Nov 2015 18:13:48 +0000 Subject: [PATCH 565/738] web-view-tag.md: small typo correction ('the' position swap) --- docs/api/web-view-tag.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 25b0e399465d..47a3050a0429 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -262,7 +262,7 @@ Injects CSS into the guest page. * `code` String * `userGesture` Boolean - Default `false`. -Evaluates `code` in page. If `userGesture` is set, it will the create user +Evaluates `code` in page. If `userGesture` is set, it will create the user gesture context in the page. HTML APIs like `requestFullScreen`, which require user action, can take advantage of this option for automation. From 82e2da1d9a289fe5003fc9c85de7a880c2601093 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 19 Nov 2015 03:53:10 +0900 Subject: [PATCH 566/738] Translate docs --- docs-translations/ko-KR/api/browser-window.md | 59 ++++++++----------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 6d5cdf1659af..554119a0a1e8 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -43,7 +43,7 @@ win.show(); * `alwaysOnTop` Boolean - 윈도우 창이 언제나 다른 창들 위에 유지되는지 여부. * `fullscreen` Boolean - 윈도우 창의 전체화면 활성화 여부. `false`로 지정했을 경우 OS X에선 전체화면 버튼이 숨겨지거나 비활성화됩니다. -* `skipTaskbar` Boolean - 작업 표시줄 어플리케이션 아이콘 표시 여부. +* `skipTaskbar` Boolean - 작업표시줄 어플리케이션 아이콘 표시 여부. * `kiosk` Boolean - Kiosk(키오스크) 모드. * `title` String - 기본 윈도우 창 제목. * `icon` [NativeImage](native-image.md) - 윈도우 아이콘, 생략하면 실행 파일의 아이콘이 대신 사용됩니다. @@ -496,7 +496,7 @@ height areas you have within the overall content view. * `skip` Boolean -어플리케이션 아이콘을 작업 표시줄에 보이지 않도록 설정합니다. +어플리케이션 아이콘을 작업표시줄에 보이지 않도록 설정합니다. ### `win.setKiosk(flag)` @@ -557,7 +557,7 @@ Windows 메시지 훅을 등록합니다. `callback`은 WndProc에서 메시지 ### `win.capturePage([rect, ]callback)` -* `rect` Object (optional)- 캡쳐할 페이지의 영역. 사용할 수 있는 속성은 다음과 같습니다: +* `rect` Object (optional) - 캡쳐할 페이지의 영역. 사용할 수 있는 속성은 다음과 같습니다: * `x` Integer * `y` Integer * `width` Integer @@ -595,7 +595,7 @@ Windows 메시지 훅을 등록합니다. `callback`은 WndProc에서 메시지 * `progress` Double -작업 표시줄에 표시되고 있는 어플리케이션 아이콘에 진행 상태를 표시합니다. [0, 1.0] 사이의 값을 지정할 수 있습니다. +작업표시줄에 표시되고 있는 어플리케이션 아이콘에 진행 상태를 표시합니다. [0, 1.0] 사이의 값을 지정할 수 있습니다. 진행 상태가 < 0 이 되면 진행 상태 표시를 제거합니다. 진행 상태가 > 1 이 되면 불확정 상태 표시로 전환합니다. @@ -606,45 +606,38 @@ Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. ### `win.setOverlayIcon(overlay, description)` _Windows 7+_ -* `overlay` [NativeImage](native-image.md) - 작업 표시줄 아이콘의 우측 하단에 표시될 아이콘입니다. +* `overlay` [NativeImage](native-image.md) - 작업표시줄 아이콘의 우측 하단에 표시될 아이콘입니다. `null`로 지정하면 빈 오버레이가 사용됩니다 * `description` String - 접근성 설정에 의한 스크린 리더에 제공될 설명입니다 -현재 작업 표시줄 아이콘에 16px 크기의 오버레이를 지정합니다. +현재 작업표시줄 아이콘에 16px 크기의 오버레이를 지정합니다. 보통 이 기능은 어플리케이션의 여러 상태를 사용자에게 소극적으로 알리기 위한 방법으로 사용됩니다. ### `win.setThumbarButtons(buttons)` _Windows 7+_ -`buttons` `button` 객체의 배열: +`buttons` - `button` 객체의 배열: -`button` Object, properties: +`button` 객체는 다음과 같은 속성을 가지고 있습니다: -* `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. +* `icon` [NativeImage](native-image.md) - 미리보기 툴바에 보여질 아이콘. +* `tooltip` String (optional) - 버튼의 툴팁 텍스트. +* `flags` Array (optional) - 버튼의 특정 동작 및 상태 제어. 기본적으로 `enabled`이 사용됩니다. + 이 속성은 다음 문자열들을 포함할 수 있습니다: + * `enabled` - 사용자가 사용할 수 있도록 버튼이 활성화 됩니다. + * `disabled` - 버튼이 비활성화 됩니다. 버튼은 표시되지만 시각적인 상태는 사용자의 동작에 응답하지 않는 + 비활성화 상태로 표시됩니다. + * `dismissonclick` - 버튼이 클릭되면 작업표시줄 버튼의 미리보기(flyout)가 즉시 종료됩니다. + * `nobackground` - 버튼의 테두리를 표시하지 않습니다. 이미지에만 사용할 수 있습니다. + * `hidden` - 버튼을 사용자에게 표시되지 않도록 숨깁니다. + * `noninteractive` - 버튼은 활성화되어 있지만 반응이 제거되며 버튼을 눌러도 눌려지지 않은 상태를 유지합니다. + 이 값은 버튼을 알림의 용도로 사용하기 위해 만들어졌습니다. * `click` - Function -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 -whether the thumbnail has been added successfully. +윈도우 작업표시줄 버튼 레이아웃의 미리보기 이미지 영역에 미리보기 툴바와 버튼 세트를 지정합니다. +반환되는 `Boolean` 값은 미리보기 툴바가 성공적으로 추가됬는지를 알려줍니다. -The number of buttons in thumbnail toolbar should be no greater than 7 due to -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. +미리보기 이미지 영역의 제한된 크기로 인해 미리보기 툴바에 추가될 수 있는 최대 버튼의 개수는 7개이며 이 이상 추가될 수 없습니다. +플랫폼의 제약으로 인해 미리보기 툴바는 한 번 설정되면 삭제할 수 없습니다. 하지만 이 API에 빈 배열을 전달하여 버튼들을 제거할 수 있습니다. ### `win.showDefinitionForSelection()` _OS X_ @@ -681,12 +674,12 @@ array to clean the buttons. * `visible` Boolean -윈도우가 모든 워크스페이스에서 보여질지 여부를 설정합니다. +윈도우가 모든 워크스페이스에서 표시될지 여부를 설정합니다. **참고:** 이 API는 Windows에서 아무 일도 하지 않습니다. ### `win.isVisibleOnAllWorkspaces()` -윈도우가 모든 워크스페이스에서 보여질지 여부를 반환합니다. +윈도우가 모든 워크스페이스에서 표시될지 여부를 반환합니다. **참고:** 이 API는 Windows에서 언제나 false를 반환합니다. From ef64a211a2b3aeef6cdebbd01fd65ebdde63435d Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 19 Nov 2015 04:01:50 +0900 Subject: [PATCH 567/738] Standardize platform labels --- docs-translations/ko-KR/api/browser-window.md | 10 +++++----- docs/api/browser-window.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 554119a0a1e8..62b01d1f6c4d 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -207,7 +207,7 @@ __참고__: OS X에선 이 이벤트가 그저 `moved` 이벤트의 별칭(alias 윈도우가 HTML API에 의해 풀 스크린 모드에서 해제될 때 발생하는 이벤트입니다. -### Event: 'app-command' _WINDOWS_ +### Event: 'app-command' _Windows_ [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)가 호출됐을 때 발생하는 이벤트입니다. 이 이벤트는 일반적으로 키보드 미디어 키 또는 브라우저 커맨드(기본 동작 키)에 관련되어 있습니다. @@ -508,26 +508,26 @@ Kiosk(키오스크) 모드를 설정합니다. 현재 윈도우가 kiosk 모드인지 여부를 반환합니다. -### `win.hookWindowMessage(message, callback)` _WINDOWS_ +### `win.hookWindowMessage(message, callback)` _Windows_ * `message` Integer * `callback` Function Windows 메시지 훅을 등록합니다. `callback`은 WndProc에서 메시지를 받았을 때 호출됩니다. -### `win.isWindowMessageHooked(message)` _WINDOWS_ +### `win.isWindowMessageHooked(message)` _Windows_ * `message` Integer 지정한 메시지가 후킹됬는지 여부를 반환합니다. -### `win.unhookWindowMessage(message)` _WINDOWS_ +### `win.unhookWindowMessage(message)` _Windows_ * `message` Integer 지정한 메시지 훅을 등록 해제합니다. -### `win.unhookAllWindowMessages()` _WINDOWS_ +### `win.unhookAllWindowMessages()` _Windows_ 모든 메시지 훅을 등록 해제합니다. diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index ca9b621cd835..17f57a5a703c 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -232,7 +232,7 @@ Emitted when the window enters full screen state triggered by html api. Emitted when the window leaves full screen state triggered by html api. -### Event: 'app-command' _WINDOWS_ +### Event: 'app-command' _Windows_ Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) is invoked. These are typically related to keyboard media keys or browser @@ -541,7 +541,7 @@ Enters or leaves the kiosk mode. Returns whether the window is in kiosk mode. -### `win.hookWindowMessage(message, callback)` _WINDOWS_ +### `win.hookWindowMessage(message, callback)` _Windows_ * `message` Integer * `callback` Function @@ -549,19 +549,19 @@ Returns whether the window is in kiosk mode. Hooks a windows message. The `callback` is called when the message is received in the WndProc. -### `win.isWindowMessageHooked(message)` _WINDOWS_ +### `win.isWindowMessageHooked(message)` _Windows_ * `message` Integer Returns `true` or `false` depending on whether the message is hooked. -### `win.unhookWindowMessage(message)` _WINDOWS_ +### `win.unhookWindowMessage(message)` _Windows_ * `message` Integer Unhook the window message. -### `win.unhookAllWindowMessages()` _WINDOWS_ +### `win.unhookAllWindowMessages()` _Windows_ Unhooks all of the window messages. From f581730516b4810e6a3e06516b413146a309f2d1 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Wed, 18 Nov 2015 21:06:06 +0200 Subject: [PATCH 568/738] Update browser-window.md Changed the description of the preload key to make it clear you need to provide an absolute file path and not a file url. Also mentioned that it's possible to reintroduce Node globals when node integration is off and referenced the example from process.md (related to https://github.com/atom/electron/issues/254#issuecomment-157769756). --- docs/api/browser-window.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index e5fcfb9003ae..48373b313e94 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -86,8 +86,12 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. is `true`. * `preload` String - Specifies a script that will be loaded before other scripts run in the page. This script will always have access to node APIs - no matter whether node integration is turned on for the page, and the path - of `preload` script has to be absolute path. + no matter whether node integration is turned on or off. The value should + be the absolute file path to the script. + + When node integration is turned off, the preload script can reintroduce + Node global symbols back to the global scope. See example + [here](process.md#event-loaded). * `partition` String - Sets the session used by the page. If `partition` starts with `persist:`, the page will use a persistent session available to all pages in the app with the same `partition`. if there is no `persist:` From e4803e6f972fb3a648ff5c1657af23d9f372d365 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 19 Nov 2015 05:12:38 +0900 Subject: [PATCH 569/738] Translate docs --- docs-translations/ko-KR/README.md | 2 +- docs-translations/ko-KR/api/browser-window.md | 26 +++++++------------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index 6899c91c32fa..d70894f8a96a 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -32,7 +32,7 @@ * [app](api/app.md) * [autoUpdater](api/auto-updater.md) -* [BrowserWindow (50% 번역됨 - 작업중)](api/browser-window.md) +* [BrowserWindow](api/browser-window.md) * [contentTracing](api/content-tracing.md) * [dialog](api/dialog.md) * [globalShortcut](api/global-shortcut.md) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 62b01d1f6c4d..02ae9eb66049 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -358,26 +358,20 @@ var win = new BrowserWindow({ width: 800, height: 600 }); ### `win.setAspectRatio(aspectRatio[, extraSize])` _OS X_ -* `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: +* `aspectRatio` 유지하려 하는 컨텐츠 뷰 일부의 종횡비 +* `extraSize` Object (optional) - 종횡비를 유지하는 동안 포함되지 않을 엑스트라 크기. 사용 가능한 속성: * `width` Integer * `height` Integer -This will have a window maintain an aspect ratio. The extra size allows a -developer to have space, specified in pixels, not included within the aspect -ratio calculations. This API already takes into account the difference between a -window's size and its content size. +이 메서드는 윈도우의 종횡비를 유지하는 기능을 수행합니다. +엑스트라 크기는 개발자가 픽셀로 특정한 공간이 있을 때 종횡비 계산에서 제외됩니다. +이 API는 윈도우의 크기와 컨텐츠 사이즈의 차이를 이미 고려하고 있습니다. -Consider a normal window with an HD video player and associated controls. -Perhaps there are 15 pixels of controls on the left edge, 25 pixels of controls -on the right edge and 50 pixels of controls below the player. In order to -maintain a 16:9 aspect ratio (standard aspect ratio for HD @1920x1080) within -the player itself we would call this function with arguments of 16/9 and -[ 40, 50 ]. The second argument doesn't care where the extra width and height -are within the content view--only that they exist. Just sum any extra width and -height areas you have within the overall content view. +일반 윈도우에서 작동하는 HD 비디오 플레이어와 관련된 컨트롤을 고려합니다. +만약 15 픽셀의 컨트롤이 왼쪽 가장자리에 있고 25 픽셀의 컨트롤이 오른쪽 가장자리에 있으며 50 픽셀의 컨트롤이 플레이어 밑에 있을 때 +플레이어 자체가 16:9 종횡비(HD의 표준 종횡비는 @1920x1080)를 유지하기 위해선 이 함수를 16/9, [ 40, 50 ] 인수와 함께 호출해야 합니다. +두번째 인수 엑스트라 크기는 존재하는 크기만 관여하고 컨텐츠 뷰 내의 크기는 관여하지 않습니다. +그저 전체 컨텐츠 뷰 내에 있는 모든 엑스트라 너비, 높이 영역이 합해집니다. ### `win.setBounds(options)` From b7ae9d33376e980e365b17dac6562442b0fc5386 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Thu, 19 Nov 2015 02:11:32 +0200 Subject: [PATCH 570/738] Update ipc-renderer.md Removed duplication. --- docs/api/ipc-renderer.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/api/ipc-renderer.md b/docs/api/ipc-renderer.md index e591f9e0bca2..01f0bb3a83dd 100644 --- a/docs/api/ipc-renderer.md +++ b/docs/api/ipc-renderer.md @@ -37,11 +37,10 @@ send arbitrary arguments. The main process handles it by listening for the * `arg` (optional) Send an event to the main process synchronously via a `channel`, you can also -send arbitrary arguments. The main process handles it by listening for the -`channel` event with `ipcMain`. +send arbitrary arguments. -The main process handles it by listening for the `channel` event with `ipc` and -replies by setting the `event.returnValue`. +The main process handles it by listening for the `channel` event with +`ipcMain` 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. From 0232b77ce3243a0f00b601f73b1a7073fcde0236 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 19 Nov 2015 09:32:44 +0900 Subject: [PATCH 571/738] Cleanup docs, Improve grammar --- README-ko.md | 35 ++++++++----- .../development/atom-shell-vs-node-webkit.md | 35 ++++++++----- .../development/build-instructions-linux.md | 43 +++++++++------- .../development/build-instructions-osx.md | 8 +-- .../development/build-instructions-windows.md | 38 +++++++++----- .../development/build-system-overview.md | 51 ++++++++++++------- docs-translations/ko-KR/styleguide.md | 49 +++++++++++------- 7 files changed, 163 insertions(+), 96 deletions(-) diff --git a/README-ko.md b/README-ko.md index a0d1a9d3438f..d35ba87f62b7 100644 --- a/README-ko.md +++ b/README-ko.md @@ -8,19 +8,26 @@ :zap: *프레임워크 이름이 Atom Shell에서 Electron으로 변경되었습니다* :zap: -Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. -이 프레임워크는 [Node.js](https://nodejs.org/) 와 [Chromium](http://www.chromium.org)을 기반으로 만들어 졌으며 -[Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다. +Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 +어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. 이 프레임워크는 +[Node.js](https://nodejs.org/)와 [Chromium](http://www.chromium.org)을 기반으로 +만들어졌으며 [Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다. -Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서 [@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요. +Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서 +[@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요. -이 프로젝트는 [기여자 규약 1.2](http://contributor-covenant.org/version/1/2/0/)를 준수합니다. 이 프로젝트에 참여할 때 코드를 유지해야 합니다. 받아들일 수 없는 행위를 발견했을 경우 atom@github.com로 보고 하십시오. +이 프로젝트는 [기여자 규약 1.2](http://contributor-covenant.org/version/1/2/0/)을 +준수합니다. 따라서 이 프로젝트의 개발에 참여하려면 이 계약을 지켜야 합니다. +받아들일 수 없는 행위를 발견했을 경우 atom@github.com로 보고 하십시오. ## 다운로드 -Linux, Windows, OS X 용으로 미리 빌드된 Electron 바이너리와 디버그 심볼이 준비되어 있습니다. [releases](https://github.com/atom/electron/releases) 페이지에서 받아 볼 수 있습니다. +Linux, Windows, OS X 용으로 미리 빌드된 Electron 바이너리와 디버그 심볼이 준비되어 +있습니다. [releases](https://github.com/atom/electron/releases) 페이지에서 +받아 볼 수 있습니다. -또한 [`npm`](https://docs.npmjs.com/)을 통해 미리 빌드된 Electron 바이너리를 받을 수도 있습니다: +또한 [`npm`](https://docs.npmjs.com/)을 통해 미리 빌드된 Electron 바이너리를 +설치할 수도 있습니다: ```sh # $PATH에 `electron` 커맨드를 등록하고 전역에 설치합니다. @@ -36,8 +43,9 @@ npm install electron-prebuilt --save-dev ## 참조 문서 -[Docs](https://github.com/atom/electron/tree/master/docs/README.md)에 개발 가이드와 API 레퍼런스가 있습니다. -Electron을 빌드 하는 방법과 프로젝트에 기여하는 방법도 문서에 포함되어 있으니 참고하시기 바랍니다. +[Docs](https://github.com/atom/electron/tree/master/docs/README.md)에 개발 지침과 +API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝트에 기여하는법 또한 문서에 +포함되어 있으니 참고하시기 바랍니다. ## 참조 문서 (번역) @@ -50,14 +58,17 @@ Electron을 빌드 하는 방법과 프로젝트에 기여하는 방법도 문 ## 시작하기 -[`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) 저장소를 클론하여 Electron을 간단히 접해볼 수 있습니다. +[`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) +저장소를 클론하여 Electron을 간단히 접해볼 수 있습니다. ## 커뮤니티 다음 링크를 통해 커뮤니티에 질문을 올리거나 토론을 나눌 수 있습니다: - Atom 포럼의 [`electron`](http://discuss.atom.io/c/electron) 카테고리 -- Freenode 채팅의 `#atom-shell` 채널 +- Freenode 채팅의 `#atom-shell` 채널 - Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널 -[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트엔 커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 한번 참고해 보시기 바랍니다. +[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에 +커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 +한번 참고해 보시기 바랍니다. diff --git a/docs-translations/ko-KR/development/atom-shell-vs-node-webkit.md b/docs-translations/ko-KR/development/atom-shell-vs-node-webkit.md index 23aa31bfe4ed..e7dd017fd720 100644 --- a/docs-translations/ko-KR/development/atom-shell-vs-node-webkit.md +++ b/docs-translations/ko-KR/development/atom-shell-vs-node-webkit.md @@ -3,35 +3,46 @@ __참고: Electron은 Atom Shell의 새로운 이름입니다.__ NW.js 처럼 Electron은 JavaScript와 HTML 그리고 Node 통합 환경을 제공함으로써 -웹 페이지에서 저 수준 시스템에 접근할 수 있도록 하여 웹 기반 데스크탑 어플리케이션을 작성할 수 있도록 하는 프레임워크 입니다. +웹 페이지에서 저 수준 시스템에 접근할 수 있도록 하여 웹 기반 데스크탑 어플리케이션을 +작성할 수 있도록 하는 프레임워크 입니다. 하지만 Electron과 NW.js는 근본적인 개발흐름의 차이도 있습니다: __1. 어플리케이션의 엔트리 포인트__ NW.js에선 어플리케이션의 엔트리 포인트로 웹 페이지를 사용합니다. -`package.json`내의 main 필드에 메인 웹 페이지(index.html) URL을 지정하면 어플리케이션의 메인 윈도우로 열리게 됩니다. +`package.json`내의 main 필드에 메인 웹 페이지(index.html) URL을 지정하면 +어플리케이션의 메인 윈도우로 열리게 됩니다. -Electron에선 JavaScript를 엔트리 포인트로 사용합니다. URL을 직접 제공하는 대신 API를 사용하여 직접 브라우저 창과 HTML 파일을 로드할 수 있습니다. -또한 윈도우의 종료시기를 결정하는 이벤트를 리스닝해야합니다. +Electron에선 JavaScript를 엔트리 포인트로 사용합니다. URL을 직접 제공하는 대신 API를 +사용하여 직접 브라우저 창과 HTML 파일을 로드할 수 있습니다. 또한 윈도우의 종료시기를 +결정하는 이벤트를 리스닝해야합니다. -Electron은 Node.js 런타임과 비슷하게 작동합니다. Electron의 API는 저수준이기에 브라우저 테스팅을 위해 [PhantomJS](http://phantomjs.org/)를 사용할 수도 있습니다. +Electron은 Node.js 런타임과 비슷하게 작동합니다. Electron의 API는 저수준이기에 +브라우저 테스팅을 위해 [PhantomJS](http://phantomjs.org/)를 사용할 수도 있습니다. __2. 빌드 시스템__ -Electron은 Chromium의 모든것을 빌드하는 복잡성을 피하기 위해 [libchromiumcontent](https://github.com/brightray/libchromiumcontent)를 사용하여 -Chromium의 Content API에 접근합니다. libchromiumcontent은 단일 공유 라이브러리이고 Chromium Content 모듈과 종속성 라이브러리들을 포함합니다. -유저는 Electron을 빌드 하기 위해 높은 사양의 빌드용 컴퓨터를 구비할 필요가 없습니다. +Electron은 Chromium의 모든것을 빌드하는 복잡성을 피하기 위해 +[libchromiumcontent](https://github.com/brightray/libchromiumcontent)를 사용하여 +Chromium의 Content API에 접근합니다. libchromiumcontent은 단일 공유 라이브러리이고 +Chromium Content 모듈과 종속성 라이브러리들을 포함합니다. 유저는 Electron을 빌드 하기 +위해 높은 사양의 빌드용 컴퓨터를 구비할 필요가 없습니다. __3. Node 통합__ -NW.js는 웹 페이지에서 require를 사용할 수 있도록 Chromium을 패치했습니다. 한편 Electron은 Chromium의 해킹을 방지하기 위해 libuv loop와 각 플랫폼의 메시지 루프에 통합하는 등의 다른 방법을 채택하였습니다. -[`node_bindings`][node-bindings] 코드를 보면 이 부분이 어떻게 구현됬는지를 알 수 있습니다. +NW.js는 웹 페이지에서 require를 사용할 수 있도록 Chromium을 패치했습니다. +한편 Electron은 Chromium의 해킹을 방지하기 위해 libuv loop와 각 플랫폼의 +메시지 루프에 통합하는 다른 방법을 채택하였습니다. +[`node_bindings`][node-bindings]의 코드를 보면 이 부분이 어떻게 구현됬는지를 +알 수 있습니다. __4. 다중 컨텍스트__ -만약 NW.js를 사용해본적이 있다면 Node context와 Web context의 개념을 잘 알고 있을겁니다. 이 개념은 NW.js가 구현된 방식에 따라 만들어졌습니다. +만약 NW.js를 사용해본 적이 있다면 Node context와 Web context의 개념을 잘 알고 있을 +겁니다. 이러한 개념은 NW.js가 구현되기 위해 만들어졌습니다. -Node의 [다중 컨텍스트](http://strongloop.com/strongblog/whats-new-node-js-v0-12-multiple-context-execution/)를 사용할 경우 Electron은 웹 페이지에서 새로운 JavaScript 컨텍스트를 생성하지 않습니다. +Node의 [다중 컨텍스트](http://strongloop.com/strongblog/whats-new-node-js-v0-12-multiple-context-execution/)를 +사용하기 때문에 Electron은 웹 페이지의 새로운 JavaScript 컨텍스트를 생성하지 않습니다. [node-bindings]: https://github.com/atom/electron/tree/master/atom/common diff --git a/docs-translations/ko-KR/development/build-instructions-linux.md b/docs-translations/ko-KR/development/build-instructions-linux.md index cb254a80596d..7a6a476400a0 100644 --- a/docs-translations/ko-KR/development/build-instructions-linux.md +++ b/docs-translations/ko-KR/development/build-instructions-linux.md @@ -4,10 +4,14 @@ ## 빌드전 요구사양 -* Python 2.7.x. 몇몇 CentOS와 같은 배포판들은 아직도 Python 2.6.x 버전을 사용합니다. 그래서 `python -V`를 통해 버전을 확인해 줄 필요가 있습니다. -* Node.js v0.12.x. Node를 설치하는 방법은 여러가지가 있습니다. 그중 하나는 [Node.js](http://nodejs.org) 사이트에서 소스코드를 받아 빌드하는 방법입니다. - 이렇게 하면 Node를 일반 유저로 홈 디렉터리에 설치할 수 있습니다. 또는 [NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories)에서 소스 파일을 받아올 수 있습니다. - 자세한 내용은 [Node.js 설치 방법](https://github.com/joyent/node/wiki/Installation) 을 참고하세요. +* Python 2.7.x. 몇몇 CentOS와 같은 배포판들은 아직도 Python 2.6.x 버전을 사용합니다. + 그래서 먼저 `python -V`를 통해 버전을 확인할 필요가 있습니다. +* Node.js v0.12.x. Node를 설치하는 방법은 여러 가지가 있습니다. 먼저, + [Node.js](http://nodejs.org) 사이트에서 소스코드를 받아 빌드하는 방법입니다. + 이렇게 하면 Node를 일반 유저로 홈 디렉터리에 설치할 수 있습니다. 다른 방법으로는 + [NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories)에서 + 소스 파일을 받아와 설치할 수 있습니다. 자세한 내용은 [Node.js 설치 방법](https://github.com/joyent/node/wiki/Installation)을 + 참고하세요. * Clang 3.4 또는 최신 버전 * GTK+ 와 libnotify의 개발용 헤더 @@ -28,13 +32,14 @@ $ sudo yum install clang dbus-devel gtk2-devel libnotify-devel libgnome-keyring- alsa-lib-devel libXrandr-devel GConf2-devel nss-devel ``` -다른 배포판의 경우 pacman 같은 패키지 매니저를 통해 패키지를 설치 할 수 있습니다. 패키지의 이름은 대부분 위 예시와 비슷할 것입니다. -또는 소스코드를 내려받아 직접 빌드하는 방법도 있습니다. +다른 배포판의 경우 pacman 같은 패키지 매니저를 통해 패키지를 설치 할 수 있습니다. +패키지의 이름은 대부분 위 예시와 비슷할 것입니다. 또는 소스코드를 내려받아 +직접 빌드하는 방법도 있습니다. ## 가상머신을 사용하여 빌드 하는 경우 -만약 Electron을 가상머신으로 빌드 할 계획이라면 해당 가상머신의 스토리지를 최소 25GB 이상을 확보해 놓아야 합니다. - +만약 Electron을 가상머신으로 빌드 할 계획이라면 해당 가상머신의 스토리지를 +최소 25GB 이상을 확보해 놓아야 합니다. ## 코드 가져오기 @@ -44,10 +49,11 @@ $ git clone https://github.com/atom/electron.git ## 부트 스트랩 -부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 프로젝트 파일을 생성합니다. -스크립트가 정상적으로 작동하기 위해선 Python 2.7.x 버전이 필요합니다. -아마 다운로드 작업이 상당히 많은 시간을 소요할 것입니다. -참고로 Electron은 빌드 툴체인으로 `ninja`를 사용하므로 `Makefile`은 생성되지 않습니다. +부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 +프로젝트 파일을 생성합니다. 스크립트가 정상적으로 작동하기 위해선 +Python 2.7.x 버전이 필요합니다. 아마 다운로드 작업이 상당히 많은 시간을 +소요할 것입니다. 참고로 Electron은 빌드 툴체인으로 `ninja`를 사용하므로 +`Makefile`은 생성되지 않습니다. ```bash $ cd electron @@ -63,7 +69,8 @@ $ sudo apt-get install libc6-dev-armhf-cross linux-libc-dev-armhf-cross \ g++-arm-linux-gnueabihf ``` -그리고 `bootstrap.py` 스크립트의 `--target_arch` 파라미터에 `arm` 또는 `ia32` 아키텍쳐를 지정하여 크로스 컴파일 할 수 있습니다: +그리고 `bootstrap.py` 스크립트의 `--target_arch` 파라미터에 `arm` 또는 `ia32` +아키텍쳐를 지정하여 크로스 컴파일 할 수 있습니다: ```bash $ ./script/bootstrap.py -v --target_arch=arm @@ -77,16 +84,18 @@ $ ./script/bootstrap.py -v --target_arch=arm $ ./script/build.py ``` -이 스크립트는 `out/R` 디렉터리에 크기가 매우 큰 Electron 실행 파일을 배치합니다. 파일 크기는 1.3GB를 초과합니다. -이러한 문제가 발생하는 이유는 Release 타겟 바이너리가 디버그 심볼을 포함하기 때문입니다. -파일 크기를 줄이려면 `create-dist.py` 스크립트를 실행하세요: +이 스크립트는 `out/R` 디렉터리에 크기가 매우 큰 Electron 실행 파일을 배치합니다. +파일 크기는 1.3GB를 초과합니다. 이러한 문제가 발생하는 이유는 Release 타겟 바이너리가 +디버그 심볼을 포함하기 때문입니다. 파일 크기를 줄이려면 +`create-dist.py` 스크립트를 실행하세요: ```bash $ ./script/create-dist.py ``` 이 스크립트는 매우 작은 배포판을 `dist` 디렉터리에 생성합니다. -create-dist.py 스크립트를 실행한 이후부턴 1.3GB를 초과하는 공간을 차지하는 `out/R` 폴더의 바이너리는 삭제해도 됩니다. +create-dist.py 스크립트를 실행한 이후부턴 1.3GB를 초과하는 공간을 차지하는 +`out/R` 폴더의 바이너리는 삭제해도 됩니다. 또는 `Debug` 타겟만 빌드 할 수 있습니다: diff --git a/docs-translations/ko-KR/development/build-instructions-osx.md b/docs-translations/ko-KR/development/build-instructions-osx.md index 4951b975ae33..222d4fc31c4e 100644 --- a/docs-translations/ko-KR/development/build-instructions-osx.md +++ b/docs-translations/ko-KR/development/build-instructions-osx.md @@ -20,8 +20,9 @@ $ git clone https://github.com/atom/electron.git ## 부트 스트랩 -부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 프로젝트 파일을 생성합니다. -참고로 Electron은 빌드 툴체인으로 `ninja`를 사용하므로 Xcode 프로젝트는 생성되지 않습니다. +부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 +프로젝트 파일을 생성합니다. 참고로 Electron은 빌드 툴체인으로 `ninja`를 사용하므로 +Xcode 프로젝트는 생성되지 않습니다. ```bash $ cd electron @@ -46,7 +47,8 @@ $ ./script/build.py -c D ## 32비트 지원 -Electron은 현재 OS X 64비트만 지원하고 있습니다. 그리고 앞으로도 OS X 32비트는 지원할 계획이 없습니다. +Electron은 현재 OS X 64비트만 지원하고 있습니다. 그리고 앞으로도 OS X 32비트는 +지원할 계획이 없습니다. ## 테스트 diff --git a/docs-translations/ko-KR/development/build-instructions-windows.md b/docs-translations/ko-KR/development/build-instructions-windows.md index fa165ca153ac..69811ac388f7 100644 --- a/docs-translations/ko-KR/development/build-instructions-windows.md +++ b/docs-translations/ko-KR/development/build-instructions-windows.md @@ -11,14 +11,18 @@ * [Git](http://git-scm.com) 현재 사용하고 있는 PC에 Windows를 설치하지 않았다면 [modern.ie](https://www.modern.ie/en-us/virtualization-tools#downloads)에서 -사용 기한이 정해져있는 무료 가상머신 버전의 Windows를 받아 Electron을 빌드하는 방법도 있습니다. +사용 기한이 정해져있는 무료 가상머신 버전의 Windows를 받아 Electron을 +빌드하는 방법도 있습니다. -Electron은 모든 빌드를 command-line 스크립트를 통해 빌드합니다. 따라서 빌드에 Visual Studio를 사용할 수 없습니다. -하지만 여전히 Electron을 개발할 땐 아무 에디터나 사용할 수 있습니다. 빠른 시일내에 Visual Studio를 이용한 빌드도 지원할 계획입니다. +Electron은 모든 빌드를 command-line 스크립트를 통해 빌드합니다. 따라서 빌드에 +Visual Studio를 사용할 수 없습니다. 하지만 여전히 Electron을 개발할 땐 아무 에디터나 +사용할 수 있습니다. 빠른 시일내에 Visual Studio를 이용한 빌드도 지원할 계획입니다. -**참고:** Visual Studio가 직접 빌드에 사용되지 않더라도 IDE와 같이 제공된 빌드 툴체인이 빌드에 **필수적으로** 사용되므로 여전히 필요합니다. +**참고:** Visual Studio가 직접 빌드에 사용되지 않더라도 IDE와 같이 제공된 +빌드 툴체인이 빌드에 **반드시** 사용되므로 여전히 필요합니다. -**참고:** Visual Studio 2015는 사용할 수 없습니다. MSVS **2013**을 사용하고 있는지 확인해주세요. +**참고:** Visual Studio 2015는 사용할 수 없습니다. +MSVS **2013** 을 사용하고 있는지 확인해주세요. ## 코드 가져오기 @@ -28,8 +32,9 @@ $ git clone https://github.com/atom/electron.git ## 부트 스트랩 -부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 프로젝트 파일을 생성합니다. -참고로 Electron은 빌드 툴체인으로 `ninja`를 사용하므로 Visual Studio 프로젝트는 생성되지 않습니다. +부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 +프로젝트 파일을 생성합니다. 참고로 Electron은 빌드 툴체인으로 `ninja`를 사용하므로 +Visual Studio 프로젝트는 생성되지 않습니다. ```powershell $ cd electron @@ -50,11 +55,13 @@ $ python script\build.py $ python script\build.py -c D ``` -빌드가 모두 끝나면 `out/D` (디버그 타겟) 또는 `out/R` (릴리즈 타겟) 디렉터리에서 `electron.exe` 실행 파일을 찾을 수 있습니다. +빌드가 모두 끝나면 `out/D` (디버그 타겟) 또는 `out/R` (릴리즈 타겟) 디렉터리에서 +`electron.exe` 실행 파일을 찾을 수 있습니다. ## 64비트 빌드 -64비트를 타겟으로 빌드 하려면 부트스트랩 스크립트를 실행할 때 `--target_arch=x64` 인자를 같이 넘겨주면 됩니다: +64비트를 타겟으로 빌드 하려면 부트스트랩 스크립트를 실행할 때 +`--target_arch=x64` 인자를 같이 넘겨주면 됩니다: ```powershell $ python script\bootstrap.py -v --target_arch=x64 @@ -76,8 +83,8 @@ $ python script\cpplint.py $ python script\test.py ``` -테스트 실행시 `runas`와 같은 네이티브 모듈을 포함하는데 이 모듈은 디버그 빌드에서 같이 사용할 수 없습니다. -하지만 여전히 릴리즈 빌드에선 사용할 수 있습니다. +테스트 실행시 `runas`와 같은 네이티브 모듈을 포함하는데 이 모듈은 디버그 빌드에서 +같이 사용할 수 없습니다. 하지만 여전히 릴리즈 빌드에선 사용할 수 있습니다. 릴리즈 빌드로 테스트를 실행하려면 다음 커맨드를 사용하면 됩니다: @@ -89,7 +96,8 @@ $ python script\test.py -R ### Command xxxx not found -만약 `Command xxxx not found`와 같은 형식의 에러가 발생했다면 `VS2012 Command Prompt` 콘솔로 빌드 스크립트를 실행해볼 필요가 있습니다. +만약 `Command xxxx not found`와 같은 형식의 에러가 발생했다면 +`VS2012 Command Prompt` 콘솔로 빌드 스크립트를 실행해볼 필요가 있습니다. ### Fatal internal compiler error: C1001 @@ -97,7 +105,8 @@ Visual Studio가 업데이트까지 완벽하게 설치된 최신버전인지 ### Assertion failed: ((handle))->activecnt >= 0 -Cygwin에서 빌드 할 경우 `bootstrap.py` 스크립트가 다음의 에러와 함께 빌드에 실패할 수 있습니다: +Cygwin에서 빌드 할 경우 `bootstrap.py` 스크립트가 다음의 에러와 함께 빌드에 +실패할 수 있습니다: ``` Assertion failed: ((handle))->activecnt >= 0, file src\win\pipe.c, line 1430 @@ -136,4 +145,5 @@ $ mkdir ~\AppData\Roaming\npm ### node-gyp is not recognized as an internal or external command -Git Bash로 빌드 했을 때 이러한 에러가 발생할 수 있습니다. 반드시 PowerShell이나 VS2012 Command Prompt에서 빌드를 진행해야 합니다. +Git Bash로 빌드 했을 때 이러한 에러가 발생할 수 있습니다. 반드시 PowerShell이나 +VS2012 Command Prompt에서 빌드를 진행해야 합니다. diff --git a/docs-translations/ko-KR/development/build-system-overview.md b/docs-translations/ko-KR/development/build-system-overview.md index 34f93a8881bd..0c35d04d7bd7 100644 --- a/docs-translations/ko-KR/development/build-system-overview.md +++ b/docs-translations/ko-KR/development/build-system-overview.md @@ -9,31 +9,39 @@ Electron을 빌드 할 때 `gyp` 파일들은 다음과 같은 규칙을 따릅 * `atom.gyp`는 Electron의 빌드 과정 자체를 정의합니다. * `common.gypi`는 Node가 Chromium과 함께 빌드될 수 있도록 조정한 빌드 설정입니다. -* `vendor/brightray/brightray.gyp`는 `brightray`의 빌드 과정을 정의하고 Chromium과의 링킹에 대한 기본적인 설정을 포함합니다. +* `vendor/brightray/brightray.gyp`는 `brightray`의 빌드 과정을 정의하고 + Chromium 링킹에 대한 기본적인 설정을 포함합니다. * `vendor/brightray/brightray.gypi`는 빌드에 대한 일반적인 설정이 포함되어 있습니다. ## 구성요소 빌드 -Chromium은 꽤나 큰 프로젝트입니다. 이 때문에 최종 링킹 작업은 상당한 시간이 소요될 수 있습니다. -이 문제는 보통 개발을 어렵게 만듭니다. 우리는 이 문제를 해결하기 위해 Chromium의 "component build" 방식을 도입했습니다. -이는 각각의 컴포넌트를 각각 따로 분리하여 공유 라이브러리로 빌드 합니다. 하지만 이 방식을 사용하면 링킹 작업은 매우 빨라지지만 파일 크기와 성능이 느려집니다. +Chromium은 꽤나 큰 프로젝트입니다. 이러한 이유로 인해 최종 링킹 작업은 상당한 시간이 +소요될 수 있습니다. 보통 이런 문제는 개발을 어렵게 만듭니다. 우리는 이 문제를 해결하기 +위해 Chromium의 "component build" 방식을 도입했습니다. 이는 각각의 컴포넌트를 +각각 따로 분리하여 공유 라이브러리로 빌드 합니다. 하지만 이 빌드 방식을 사용하면 +링킹 작업은 매우 빨라지지만 실행 파일 크기가 커지고 성능이 저하됩니다. -Electron도 상당히 비슷한 접근을 했습니다: -`Debug`빌드 시 바이너리는 공유 라이브러리 버전의 Chromium 컴포넌트를 사용해서 링크 속도를 높이고 -`Release`빌드 시엔 정적 라이브러리 버전의 컴포넌트를 사용합니다. -이렇게 각 빌드의 단점을 상호 보완하여 디버그 시 빌드 속도는 향상되고 배포판 빌드 시 공유 라이브러리의 단점은 제거했습니다. +Electron도 이러한 방식에 상당히 비슷한 접근을 했습니다: +`Debug` 빌드 시 바이너리는 공유 라이브러리 버전의 Chromium 컴포넌트를 사용함으로써 +링크 속도를 높이고, `Release` 빌드 시 정적 라이브러리 버전의 컴포넌트를 사용합니다. +이렇게 각 빌드의 단점을 상호 보완하여 디버그 시 빌드 속도는 향상되고 배포판 빌드의 +공유 라이브러리의 단점은 개선했습니다. ## 부트스트랩 최소화 Prebuilt된 모든 Chromium 바이너리들은 부트스트랩 스크립트가 실행될 때 다운로드됩니다. -기본적으로 공유 라이브러리와 정적 라이브러리 모두 다운로드되며 최종 전체 파일 크기는 플랫폼에 따라 800MB에서 2GB까지 차지합니다. +기본적으로 공유 라이브러리와 정적 라이브러리 모두 다운로드되며 최종 전체 파일 크기는 +플랫폼에 따라 800MB에서 2GB까지 차지합니다. 기본적으로 (`libchromiumcontent`)는 Amazon Web Service를 통해 다운로드 됩니다. -만약 `LIBCHROMIUMCONTENT_MIRROR` 환경 변수가 설정되어 있으면 부트스트랩은 해당 링크를 사용하여 바이너리를 다운로드 합니다. -[libchromiumcontent-qiniu-mirror](https://github.com/hokein/libchromiumcontent-qiniu-mirror)는 libchromiumcontent의 미러입니다. -만약 AWS에 접근할 수 없다면 `export LIBCHROMIUMCONTENT_MIRROR=http://7xk3d2.dl1.z0.glb.clouddn.com/`를 통해 다운로드 할 수 있습니다. +만약 `LIBCHROMIUMCONTENT_MIRROR` 환경 변수가 설정되어 있으면 부트스트랩은 해당 링크를 +사용하여 바이너리를 다운로드 합니다. [libchromiumcontent-qiniu-mirror](https://github.com/hokein/libchromiumcontent-qiniu-mirror)는 +libchromiumcontent의 미러입니다. 만약 AWS에 접근할 수 없다면 +`export LIBCHROMIUMCONTENT_MIRROR=http://7xk3d2.dl1.z0.glb.clouddn.com/` 미러를 +통해 다운로드 할 수 있습니다. -만약 빠르게 Electron의 개발 또는 테스트만 하고 싶다면 `--dev` 플래그를 추가하여 공유 라이브러리만 다운로드할 수 있습니다: +만약 빠르게 Electron의 개발 또는 테스트만 하고 싶다면 `--dev` 플래그를 추가하여 +공유 라이브러리만 다운로드할 수 있습니다: ```bash $ ./script/bootstrap.py --dev @@ -43,14 +51,19 @@ $ ./script/build.py -c D ## 프로젝트 생성 (two-phrase) Electron은 `Release`와 `Debug` 빌드가 서로 다른 라이브러리 링크 방식을 사용합니다. -하지만 `gyp`는 따로 빌드 설정을 분리하여 라이브러리 링크 방식을 정의하는 것을 지원하지 않습니다. +하지만 `gyp`는 따로 빌드 설정을 분리하여 라이브러리 링크 방식을 정의하는 방법을 +지원하지 않습니다. -이 문제를 해결하기 위해 Electron은 링크 설정을 제어하는 `gyp` 변수 `libchromiumcontent_component`를 사용하고 `gyp`를 실행할 때 단 하나의 타겟만 생성합니다. +이 문제를 해결하기 위해 Electron은 링크 설정을 제어하는 `gyp` 변수 +`libchromiumcontent_component`를 사용하고 `gyp`를 실행할 때 +단 하나의 타겟만을 생성합니다. ## 타겟 이름 -많은 프로젝트에서 타겟 이름을 `Release` 와 `Debug`를 사용하는데 반해 Electron은 `R`과 `D`를 대신 사용합니다. -이유는 가끔 알 수 없는 이유(randomly)로 `Release` 와 `Debug` 중 하나만 빌드 설정에 정의되어 있을때 `gyp`가 크래시를 일으키는데 -전술한 바와 같이 Electron은 한번에 한개의 타겟만을 생성할 수 있기 때문입니다. +많은 프로젝트에서 타겟 이름을 `Release` 와 `Debug`를 사용하는데 반해 Electron은 +`R`과 `D`를 대신 사용합니다. 이유는 가끔 알 수 없는 이유(randomly)로 +`Release` 와 `Debug` 중 하나만 빌드 설정에 정의되어 있을때 `gyp`가 크래시를 일으키는데 +이유는 앞서 말한 바와 같이 Electron은 한번에 한개의 타겟만을 생성할 수 있기 때문입니다. -이 문제는 개발자에게만 영향을 미칩니다. 만약 단순히 Electron을 rebranding 하기 위해 빌드 한다면 이 문제에 신경 쓸 필요가 없습니다. +이 문제는 개발자에게만 영향을 미칩니다. 만약 단순히 Electron을 rebranding 하기 위해 +빌드 하는 것이라면 이 문제에 신경 쓸 필요가 없습니다. diff --git a/docs-translations/ko-KR/styleguide.md b/docs-translations/ko-KR/styleguide.md index 92b68e345505..7318c7e3b403 100644 --- a/docs-translations/ko-KR/styleguide.md +++ b/docs-translations/ko-KR/styleguide.md @@ -1,22 +1,28 @@ # Electron 문서 스타일 가이드 -[Electron 문서 읽기](#electron-문서-읽기) 와 [Electron 문서 작성하기](#electron-문서-작성하기) 중 이해가 필요한 부분을 찾아 참고하세요: +[Electron 문서 읽기](#electron-문서-읽기) 와 +[Electron 문서 작성하기](#electron-문서-작성하기) 중 이해가 필요한 부분을 찾아 +참고하세요: ## Electron 문서 작성하기 Electron 문서를 작성하는 규칙은 다음과 같습니다. - `h1` 제목은 페이지당 한 개만 사용할 수 있습니다. -- 코드 블럭에서 터미널 언어 선택시 `cmd` 대신 `bash`를 사용합니다. (syntax highlighter를 사용하기 위해서) -- 문서의 `h1` 제목은 반드시 현재 객체 이름과 같게 해야 합니다. (예시: `browser-window` → `BrowserWindow`) - - 하이픈(-)으로 구분되었던 어떻게 되었던 간에 예시와 같이 작성합니다. -- 헤더 밑에 헤더를 바로 사용하지 않습니다. 한 줄이라도 좋으니 헤더와 헤더 사이에 설명 추가합니다. -- 메서드 헤더는 `code` 틱으로 표시합니다. +- 코드 블럭에서 터미널 언어 선택시 `cmd` 대신 `bash`를 사용합니다. + (syntax highlighter를 사용하기 위해서) +- 문서의 `h1` 제목은 반드시 현재 객체 이름과 같게 해야 합니다. + (예시: `browser-window` → `BrowserWindow`) + - 하이픈(-)으로 구분되었건 다르게 구분되었건 예시와 같이 작성합니다. +- 헤더 밑에 헤더를 바로 사용하지 않습니다. 한 줄이라도 좋으니 헤더와 헤더 사이에 + 설명을 추가합니다. +- 메서드 헤더는 `code backtick` 으로 표시합니다. - 이벤트 헤더는 한 '따옴표'로 표시합니다. -- 리스트를 2 단계 이상 중첩하지 않습니다. (안타깝게도 markdown 랜더러가 지원하지 않습니다) -- 섹션에 대한 제목을 추가합니다: Events, Class 메서드 그리고 인스턴스 메서드등. +- 리스트를 2 단계 이상 중첩하지 않습니다. (안타깝게도 markdown 랜더러가 이를 + 지원하지 않습니다) +- 섹션에 대한 제목을 추가합니다. Events, Class 메서드 그리고 인스턴스 메서드 등 - 어떤 '것'의 사용 결과를 설명할 때 '될 것입니다' 형식을 사용하여 설명합니다. -- 이벤트와 메서드에는 `h3` 헤더를 사용합니다. +- 이벤트와 메서드를 표기할 땐 `h3` 헤더를 사용합니다. - 선택적 인수는 `function (required[, optional])` 형식으로 작성합니다. - 선택적 인수는 목록에서 호출되면 표시합니다. - 문장의 길이는 한 줄당 80 칸을 유지합니다. @@ -30,11 +36,13 @@ Electron 문서를 작성하는 규칙은 다음과 같습니다. 아직 번역되지 않은 언어를 추가하려면 (일부분 포함): -- 언어의 약어(예: en, ja, ko등)로 서브 디렉터리를 만듭니다. -- 서브 디렉터리에 `docs` 디렉터리를 복사합니다. 파일 이름과 디렉터리 구조는 모두 유지합니다. +- 언어의 약어(예: en-US, ja-JP, ko-KR)로 서브 디렉터리를 만듭니다. +- 서브 디렉터리에 `docs` 디렉터리를 복사합니다. 파일 이름과 디렉터리 구조는 + 모두 유지합니다. - 문서를 번역합니다. -- `README.md`에 번역한 문서의 링크를 추가하고 업데이트 합니다. -- 메인 Electron의 [README](https://github.com/atom/electron#documentation-translations)에 번역된 디렉터리의 링크를 추가합니다. +- 언어 디렉터리 내의 `README.md`에 번역한 문서의 링크를 추가합니다. +- 메인(upstream) Electron의 [README](https://github.com/atom/electron#documentation-translations)에 + 번역된 언어 디렉터리의 링크를 추가합니다. ## Electron 문서 읽기 @@ -42,7 +50,8 @@ Electron 문서 구조를 이해하는 데 참고할 수 있는 유용한 도움 ### Methods -[Method](https://developer.mozilla.org/en-US/docs/Glossary/Method) 문서의 예제입니다: +[Method](https://developer.mozilla.org/en-US/docs/Glossary/Method) 문서의 +예제입니다: --- @@ -53,8 +62,8 @@ Electron 문서 구조를 이해하는 데 참고할 수 있는 유용한 도움 --- -메서드 이름은 인수가 무엇을 받는지에 따라 결정됩니다. 선택적 인수는 브라켓([, ])으로 묶어 -이 인수가 다른 인수뒤에서 선택적으로 사용될 수 있다는 것을 표시합니다. +메서드 이름은 인수가 무엇을 받는지에 따라 결정됩니다. 선택적 인수는 브라켓([, ])으로 +묶어 이 인수가 다른 인수뒤에서 선택적으로 사용될 수 있다는 것을 표시합니다. 메서드 이름 하단에선 각 인수에 대해 자세한 설명을 합니다. 인수의 타입은 일반적인 타입 중 하나를 받거나: @@ -62,7 +71,8 @@ Electron 문서 구조를 이해하는 데 참고할 수 있는 유용한 도움 [`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) -와 같은 일반적으로 쓰이는 타입 중 하나를 받거나 Electron의 [`webContent`](api/web-content.md)같은 커스텀 타입을 받습니다. +와 같은 일반적으로 쓰이는 타입 중 하나를 받거나 Electron의 +[`webContent`](api/web-content.md)같은 커스텀 타입을 받습니다. ### Events @@ -78,8 +88,9 @@ Returns: --- -이벤트는 `.on` 리스너 메서드로 사용할 수 있습니다. 만약 이벤트에서 값을 반환한다면 문서에서 표시된 대로 -일정한 타입의 값을 반환합니다. 이벤트를 처리하거나 응답하려 한다면 다음과 같이 사용할 수 있습니다: +이벤트는 `.on` 리스너 메서드로 사용할 수 있습니다. 만약 이벤트에서 값을 반환한다면 +문서에서 표시된 대로 일정한 타입의 값을 반환합니다. 이벤트를 처리하거나 응답하려 한다면 +다음과 같이 사용할 수 있습니다: ```javascript Alarm.on('wake-up', function(time) { From ba5f8aa09683e34b265a4503436b58b120be78e7 Mon Sep 17 00:00:00 2001 From: Kevin Ramsunder Date: Wed, 18 Nov 2015 20:04:16 -0500 Subject: [PATCH 572/738] mac-app-store-submission-guide.md: typo correction --- docs/tutorial/mac-app-store-submission-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md index 4dc6f900a167..43b2d9a0a49b 100644 --- a/docs/tutorial/mac-app-store-submission-guide.md +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -7,7 +7,7 @@ limitations of the MAS build. ## How to Submit Your App The following steps introduce a simple way to submit your app to Mac App Store. -However, these steps do not ensure sure your app will be approved by Apple; you +However, these steps do not ensure your app will be approved by Apple; you still need to read Apple's [Submitting Your App][submitting-your-app] guide on how to meet the Mac App Store requirements. From c63121c2f65f86f0b070690ab47396d1356f413f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Nov 2015 13:49:50 +0800 Subject: [PATCH 573/738] Update libchromiumcontent Backport https://codereview.chromium.org/1324513002. --- 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 047ecf4faa76..2fb841acf35c 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '464aff2398f619b1d4d91b9187de69803919dca2' +LIBCHROMIUMCONTENT_COMMIT = '17a4337f7948a45b5ea4b8f391df152ba8db5979' PLATFORM = { 'cygwin': 'win32', From 2c06afad6ad3765ff7e55373196038498b38ae89 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Nov 2015 15:10:33 +0800 Subject: [PATCH 574/738] Upload the dSYM symbols --- script/create-dist.py | 21 ++++++++++++++++++--- script/upload.py | 6 ++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/script/create-dist.py b/script/create-dist.py index d79d963c12ab..29f81ebd8579 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +import glob import os import re import shutil @@ -168,6 +169,11 @@ def create_symbols(): dump_symbols = os.path.join(SOURCE_ROOT, 'script', 'dump-symbols.py') execute([sys.executable, dump_symbols, destination]) + if PLATFORM == 'darwin': + dsyms = glob.glob(os.path.join(OUT_DIR, '*.dSYM')) + for dsym in dsyms: + shutil.copytree(dsym, os.path.join(DIST_DIR, os.path.basename(dsym))) + def create_dist_zip(): dist_name = '{0}-{1}-{2}-{3}.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION, @@ -203,12 +209,21 @@ def create_symbols_zip(): ATOM_SHELL_VERSION, get_platform_key(), get_target_arch()) - zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name) + zip_file = os.path.join(DIST_DIR, dist_name) + licenses = ['LICENSE', 'LICENSES.chromium.html', 'version'] with scoped_cwd(DIST_DIR): - files = ['LICENSE', 'LICENSES.chromium.html', 'version'] dirs = ['{0}.breakpad.syms'.format(PROJECT_NAME)] - make_zip(zip_file, files, dirs) + make_zip(zip_file, licenses, dirs) + + if PLATFORM == 'darwin': + dsym_name = '{0}-{1}-{2}-{3}-dsym.zip'.format(PROJECT_NAME, + ATOM_SHELL_VERSION, + get_platform_key(), + get_target_arch()) + with scoped_cwd(DIST_DIR): + dsyms = glob.glob('*.dSYM') + make_zip(os.path.join(DIST_DIR, dsym_name), licenses, dsyms) if __name__ == '__main__': diff --git a/script/upload.py b/script/upload.py index 318bbb594a11..c021d743a82e 100755 --- a/script/upload.py +++ b/script/upload.py @@ -31,6 +31,10 @@ SYMBOLS_NAME = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION, get_platform_key(), get_target_arch()) +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()) @@ -82,6 +86,8 @@ def main(): # Upload atom-shell with GitHub Releases API. upload_atom_shell(github, release, os.path.join(DIST_DIR, DIST_NAME)) upload_atom_shell(github, release, os.path.join(DIST_DIR, SYMBOLS_NAME)) + if PLATFORM == 'darwin': + upload_atom_shell(github, release, os.path.join(DIST_DIR, DSYM_NAME)) # Upload chromedriver and mksnapshot for minor version update. if parse_version(args.version)[2] == '0': From d427ae10301be73844deea427f144e94bf457e94 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Thu, 19 Nov 2015 00:39:45 -0800 Subject: [PATCH 575/738] Support the "desktop" window type on Mac OS X Adds the desktop window type referenced in https://github.com/atom/electron/issues/2899 for compatiblity with the linux version. Note that on Mac OS X, the desktop window cannot receive input events (seems to be a limitation of being behind the desktop). In this diff I also removed the `standardWindow` option from the docs, in favor of an additional `textured` value for window `type` on Mac OS X. The old `standardWindow` option continues to work, but seemed more confusing. If this seems like a bad idea, I can revert that change. --- atom/browser/native_window_mac.mm | 34 +++++++++++++++++++++++++++++-- docs/api/browser-window.md | 19 +++++++++-------- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index b129ded6f85e..5564f9116e4b 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -211,6 +211,8 @@ bool ScopedDisableResize::disable_resize_ = false; } @property BOOL acceptsFirstMouse; @property BOOL disableAutoHideCursor; +@property BOOL disableKeyOrMainWindow; + - (void)setShell:(atom::NativeWindowMac*)shell; - (void)setEnableLargerThanScreen:(bool)enable; @end @@ -257,6 +259,16 @@ bool ScopedDisableResize::disable_resize_ = false; return [children filteredArrayUsingPredicate:predicate]; } +- (BOOL)canBecomeMainWindow +{ + return !self.disableKeyOrMainWindow; +} + +- (BOOL)canBecomeKeyWindow +{ + return !self.disableKeyOrMainWindow; +} + @end @interface ControlRegionView : NSView @@ -330,8 +342,6 @@ NativeWindowMac::NativeWindowMac( width, height); - bool useStandardWindow = true; - options.Get(options::kStandardWindow, &useStandardWindow); bool resizable = true; options.Get(options::kResizable, &resizable); @@ -340,6 +350,17 @@ NativeWindowMac::NativeWindowMac( if (base::mac::IsOSYosemiteOrLater()) options.Get(options::kTitleBarStyle, &titleBarStyle); + std::string windowType; + options.Get(options::kType, &windowType); + + bool useStandardWindow = true; + // eventually deprecate separate "standardWindow" option in favor of + // standard / textured window types + options.Get(options::kStandardWindow, &useStandardWindow); + if (windowType == "textured") { + useStandardWindow = false; + } + NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask; if (!useStandardWindow || transparent() || !has_frame()) { @@ -371,6 +392,15 @@ NativeWindowMac::NativeWindowMac( [window_ setBackgroundColor:[NSColor clearColor]]; } + if (windowType == "desktop") { + [window_ setLevel:kCGDesktopWindowLevel - 1]; + [window_ setDisableKeyOrMainWindow: YES]; + [window_ setCollectionBehavior: + (NSWindowCollectionBehaviorCanJoinAllSpaces | + NSWindowCollectionBehaviorStationary | + NSWindowCollectionBehaviorIgnoresCycle)]; + } + // Remove non-transparent corners, see http://git.io/vfonD. if (!has_frame()) [window_ setOpaque:NO]; diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index f9b2a53ff595..a78531277e9e 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -66,11 +66,14 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `darkTheme` Boolean - Forces using dark theme for the window, only works on some GTK+3 desktop environments. * `transparent` Boolean - Makes the window [transparent](frameless-window.md). -* `type` String - Specifies the type of the window, possible types are - `desktop`, `dock`, `toolbar`, `splash`, `notification`. This only works on - Linux. -* `standardWindow` Boolean - Uses the OS X's standard window instead of the - textured window. Defaults to `true`. +* `type` String - Specifies the type of the window, which applies + additional platform-specific properties. + - On Linux, possible types are `desktop`, `dock`, `toolbar`, `splash`, `notification`. + - On Mac OS X: + - `textured`: Adds metal gradient appearance (NSTexturedBackgroundWindowMask) + - `desktop`: Places the window at the desktop background window level (kCGDesktopWindowLevel - 1). + Note that the window will not receive focus, keyboard or mouse events, but + you can use `globalShortcut` to receive input sparingly. * `titleBarStyle` String, OS X - specifies the style of window title bar. This option is supported on OS X 10.10 Yosemite and newer. There are three possible values: @@ -86,11 +89,11 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. is `true`. * `preload` String - Specifies a script that will be loaded before other scripts run in the page. This script will always have access to node APIs - no matter whether node integration is turned on or off. The value should + no matter whether node integration is turned on or off. The value should be the absolute file path to the script. - When node integration is turned off, the preload script can reintroduce - Node global symbols back to the global scope. See example + When node integration is turned off, the preload script can reintroduce + Node global symbols back to the global scope. See example [here](process.md#event-loaded). * `partition` String - Sets the session used by the page. If `partition` starts with `persist:`, the page will use a persistent session available to From 9a20b33d97c6131506170621ee132646424ceeab Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Nov 2015 17:08:16 +0800 Subject: [PATCH 576/738] Add isDestroyed method for classes with destroy method --- atom/browser/api/atom_api_tray.cc | 1 + atom/browser/api/atom_api_web_contents.cc | 8 ++------ atom/browser/api/atom_api_web_contents.h | 1 - atom/browser/api/atom_api_window.cc | 6 +----- atom/browser/api/atom_api_window.h | 1 - 5 files changed, 4 insertions(+), 13 deletions(-) diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index d3c5931ad6da..5e32657f008a 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -161,6 +161,7 @@ void Tray::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { mate::ObjectTemplateBuilder(isolate, prototype) .SetMethod("destroy", &Tray::Destroy, true) + .SetMethod("isDestroyed", &Tray::IsDestroyed, true) .SetMethod("setImage", &Tray::SetImage) .SetMethod("setPressedImage", &Tray::SetPressedImage) .SetMethod("setToolTip", &Tray::SetToolTip) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 1c3334e93669..066ca9cc7b65 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -604,10 +604,6 @@ void WebContents::Destroy() { } } -bool WebContents::IsAlive() const { - return web_contents() != NULL; -} - int WebContents::GetID() const { return web_contents()->GetRenderProcessHost()->GetID(); } @@ -996,7 +992,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( if (template_.IsEmpty()) template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) .SetMethod("destroy", &WebContents::Destroy, true) - .SetMethod("isAlive", &WebContents::IsAlive, true) + .SetMethod("isDestroyed", &WebContents::IsDestroyed, true) .SetMethod("getId", &WebContents::GetID) .SetMethod("equal", &WebContents::Equal) .SetMethod("_loadURL", &WebContents::LoadURL) @@ -1066,7 +1062,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( } bool WebContents::IsDestroyed() const { - return !IsAlive(); + return !web_contents(); } AtomBrowserContext* WebContents::GetBrowserContext() const { diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index ae231cd3c61d..568a563e2c84 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -57,7 +57,6 @@ class WebContents : public mate::TrackableObject, // mate::TrackableObject: void Destroy() override; - bool IsAlive() const; int GetID() const; bool Equal(const WebContents* web_contents) const; void LoadURL(const GURL& url, const mate::Dictionary& options); diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 61f43f9aac38..7f5b78a79780 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -284,10 +284,6 @@ void Window::Close() { window_->Close(); } -bool Window::IsClosed() { - return window_->IsClosed(); -} - void Window::Focus() { window_->Focus(true); } @@ -622,8 +618,8 @@ void Window::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { mate::ObjectTemplateBuilder(isolate, prototype) .SetMethod("destroy", &Window::Destroy, true) + .SetMethod("isDestroyed", &Window::IsDestroyed, true) .SetMethod("close", &Window::Close) - .SetMethod("isClosed", &Window::IsClosed) .SetMethod("focus", &Window::Focus) .SetMethod("isFocused", &Window::IsFocused) .SetMethod("show", &Window::Show) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 1c582551cc93..4161584206a7 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -89,7 +89,6 @@ class Window : public mate::TrackableObject, // APIs for NativeWindow. void Close(); - bool IsClosed(); void Focus(); bool IsFocused(); void Show(); From 47d7d49d192e79770c2dd4b73e2279a199d450cd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Nov 2015 20:47:11 +0800 Subject: [PATCH 577/738] Add session module --- atom/browser/api/lib/app.coffee | 6 ------ atom/browser/api/lib/exports/electron.coffee | 3 +++ atom/browser/api/lib/session.coffee | 17 +++++++++++++++++ atom/browser/api/lib/web-contents.coffee | 2 +- filenames.gypi | 1 + 5 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 atom/browser/api/lib/session.coffee diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 3db4582abc7c..9f9f5811d76a 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -2,7 +2,6 @@ electron = require 'electron' {EventEmitter} = require 'events' bindings = process.atomBinding 'app' -sessionBindings = process.atomBinding 'session' downloadItemBindings = process.atomBinding 'download_item' app = bindings.app @@ -61,11 +60,6 @@ deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVis deprecate.event app, 'select-certificate', 'select-client-certificate' # Wrappers for native classes. -wrapSession = (session) -> - # session is an EventEmitter. - session.__proto__ = EventEmitter.prototype -sessionBindings._setWrapSession wrapSession - wrapDownloadItem = (downloadItem) -> # downloadItem is an EventEmitter. downloadItem.__proto__ = EventEmitter.prototype diff --git a/atom/browser/api/lib/exports/electron.coffee b/atom/browser/api/lib/exports/electron.coffee index f0c3b87c987b..3f7d9b1a13fe 100644 --- a/atom/browser/api/lib/exports/electron.coffee +++ b/atom/browser/api/lib/exports/electron.coffee @@ -42,6 +42,9 @@ Object.defineProperties module.exports, screen: enumerable: true get: -> require '../screen' + session: + enumerable: true + get: -> require '../session' Tray: enumerable: true get: -> require '../tray' diff --git a/atom/browser/api/lib/session.coffee b/atom/browser/api/lib/session.coffee new file mode 100644 index 000000000000..e0fc7b6e0bca --- /dev/null +++ b/atom/browser/api/lib/session.coffee @@ -0,0 +1,17 @@ +{EventEmitter} = require 'events' + +bindings = process.atomBinding 'session' + +PERSIST_PERFIX = 'persist:' + +exports.fromPartition = (partition='') -> + if partition.startsWith PERSIST_PERFIX + bindings.fromPartition partition.substr(PERSIST_PERFIX.length), false + else + bindings.fromPartition partition, true + +wrapSession = (session) -> + # session is an EventEmitter. + session.__proto__ = EventEmitter.prototype + +bindings._setWrapSession wrapSession diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index 1a224c7416f5..335928dcea81 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -1,5 +1,5 @@ {EventEmitter} = require 'events' -{deprecate, ipcMain, NavigationController, Menu} = require 'electron' +{deprecate, ipcMain, session, NavigationController, Menu} = require 'electron' binding = process.atomBinding 'web_contents' diff --git a/filenames.gypi b/filenames.gypi index 7e1f3e1827e0..7157079178ee 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -26,6 +26,7 @@ 'atom/browser/api/lib/power-monitor.coffee', 'atom/browser/api/lib/power-save-blocker.coffee', 'atom/browser/api/lib/protocol.coffee', + 'atom/browser/api/lib/session.coffee', 'atom/browser/api/lib/screen.coffee', 'atom/browser/api/lib/tray.coffee', 'atom/browser/api/lib/web-contents.coffee', From 1392873cbc2c522877448cec2990c73517f29912 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Nov 2015 21:03:42 +0800 Subject: [PATCH 578/738] Add session.defaultSession and remove app.defaultSession The latter has never been a public API, no need to keep it. --- atom/browser/api/atom_api_app.cc | 18 +----------------- atom/browser/api/atom_api_app.h | 3 --- atom/browser/api/lib/app.coffee | 10 +++++----- atom/browser/api/lib/browser-window.coffee | 4 +++- atom/browser/api/lib/session.coffee | 6 ++++++ 5 files changed, 15 insertions(+), 26 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 28c3b4c15983..697d6eca6aab 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -206,14 +206,6 @@ void App::OnWillFinishLaunching() { } void App::OnFinishLaunching() { - // Create the defaultSession. - v8::Locker locker(isolate()); - v8::HandleScope handle_scope(isolate()); - auto browser_context = static_cast( - AtomBrowserMainParts::Get()->browser_context()); - auto handle = Session::CreateFrom(isolate(), browser_context); - default_session_.Reset(isolate(), handle.ToV8()); - Emit("ready"); } @@ -325,13 +317,6 @@ std::string App::GetLocale() { return l10n_util::GetApplicationLocale(""); } -v8::Local App::DefaultSession(v8::Isolate* isolate) { - if (default_session_.IsEmpty()) - return v8::Null(isolate); - else - return v8::Local::New(isolate, default_session_); -} - bool App::MakeSingleInstance( const ProcessSingleton::NotificationCallback& callback) { if (process_singleton_.get()) @@ -382,8 +367,7 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( .SetMethod("allowNTLMCredentialsForAllDomains", &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) - .SetMethod("makeSingleInstance", &App::MakeSingleInstance) - .SetProperty("defaultSession", &App::DefaultSession); + .SetMethod("makeSingleInstance", &App::MakeSingleInstance); } // static diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index ee7e02079125..a6f99d65e0af 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -87,9 +87,6 @@ class App : public AtomBrowserClient::Delegate, bool MakeSingleInstance( const ProcessSingleton::NotificationCallback& callback); std::string GetLocale(); - v8::Local DefaultSession(v8::Isolate* isolate); - - v8::Global default_session_; scoped_ptr process_singleton_; diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 9f9f5811d76a..c2116fb7bca4 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -1,4 +1,4 @@ -electron = require 'electron' +{deprecate, session, Menu} = require 'electron' {EventEmitter} = require 'events' bindings = process.atomBinding 'app' @@ -8,10 +8,10 @@ app = bindings.app app.__proto__ = EventEmitter.prototype app.setApplicationMenu = (menu) -> - electron.Menu.setApplicationMenu menu + Menu.setApplicationMenu menu app.getApplicationMenu = -> - electron.Menu.getApplicationMenu() + Menu.getApplicationMenu() app.commandLine = appendSwitch: bindings.appendSwitch, @@ -35,7 +35,8 @@ app.getAppPath = -> appPath # Helpers. -app.resolveProxy = (url, callback) -> @defaultSession.resolveProxy url, callback +app.resolveProxy = (url, callback) -> + session.defaultSession.resolveProxy url, callback # Routes the events to webContents. for name in ['login', 'certificate-error', 'select-client-certificate'] @@ -44,7 +45,6 @@ for name in ['login', 'certificate-error', 'select-client-certificate'] webContents.emit name, event, args... # Deprecated. -{deprecate} = electron app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', -> @getPath 'home' app.getDataPath = deprecate 'app.getDataPath', 'app.getPath', -> diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 99921372f14c..4cdffae87a60 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -1,10 +1,12 @@ -{app, ipcMain, deprecate} = require 'electron' +{ipcMain, deprecate} = require 'electron' {EventEmitter} = require 'events' {BrowserWindow} = process.atomBinding 'window' BrowserWindow::__proto__ = EventEmitter.prototype BrowserWindow::_init = -> + {app} = require 'electron' # avoid recursive require. + # Simulate the application menu on platforms other than OS X. if process.platform isnt 'darwin' menu = app.getApplicationMenu() diff --git a/atom/browser/api/lib/session.coffee b/atom/browser/api/lib/session.coffee index e0fc7b6e0bca..6abfe7925e69 100644 --- a/atom/browser/api/lib/session.coffee +++ b/atom/browser/api/lib/session.coffee @@ -4,12 +4,18 @@ bindings = process.atomBinding 'session' PERSIST_PERFIX = 'persist:' +# Returns the Session from |partition| string. exports.fromPartition = (partition='') -> if partition.startsWith PERSIST_PERFIX bindings.fromPartition partition.substr(PERSIST_PERFIX.length), false else bindings.fromPartition partition, true +# Returns the default session. +Object.defineProperty exports, 'defaultSession', + enumerable: true + get: -> exports.fromPartition '' + wrapSession = (session) -> # session is an EventEmitter. session.__proto__ = EventEmitter.prototype From dd8ef33e42e46bf5d80776b77ab457d1761bbc33 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Nov 2015 21:10:50 +0800 Subject: [PATCH 579/738] docs: webContents.savePage is placed at wrong place --- docs/api/web-contents.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index be22d947c752..2b2efb7d47ba 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -678,17 +678,6 @@ is in 32bit ARGB format). End subscribing for frame presentation events. -## Instance Properties - -`WebContents` objects also have the following properties: - -### `webContents.devToolsWebContents` - -Get the `WebContents` of DevTools for this `WebContents`. - -**Note:** Users should never store this object because it may become `null` -when the DevTools has been closed. - ### `webContents.savePage(fullPath, saveType, callback)` * `fullPath` String - The full file path. @@ -711,3 +700,14 @@ win.webContents.on('did-finish-load', function() { }); }); ``` + +## Instance Properties + +`WebContents` objects also have the following properties: + +### `webContents.devToolsWebContents` + +Get the `WebContents` of DevTools for this `WebContents`. + +**Note:** Users should never store this object because it may become `null` +when the DevTools has been closed. From 44c562ebd9ec14a421b85dd63967bae2f3166373 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Nov 2015 21:31:39 +0800 Subject: [PATCH 580/738] docs: New session methods --- docs/api/session.md | 79 +++++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 21 deletions(-) diff --git a/docs/api/session.md b/docs/api/session.md index 450be7b08e11..b921fc4839bd 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -1,8 +1,10 @@ # session -The `session` object is a property of [`webContents`](web-contents.md) which is -a property of [`BrowserWindow`](browser-window.md). You can access it through an -instance of `BrowserWindow`. For example: +The `session` module can be used to create new `Session` objects. + +You can also access the `session` of existing pages by using the `session` +property of [`webContents`](web-contents.md) which is a property of +[`BrowserWindow`](browser-window.md). ```javascript const BrowserWindow = require('electron').BrowserWindow; @@ -10,12 +12,47 @@ const BrowserWindow = require('electron').BrowserWindow; var win = new BrowserWindow({ width: 800, height: 600 }); win.loadURL("http://github.com"); -var session = win.webContents.session +var ses = win.webContents.session ``` -## Events +## Methods -### Event: 'will-download' +The `session` module has the following methods: + +### session.fromPartition(partition) + +* `partition` String + +Returns a new `Session` instance from `partition` string. + +If `partition` starts with `persist:`, the page will use a persistent session +available to all pages in the app with the same `partition`. if there is no +`persist:` prefix, the page will use an in-memory session. If the `partition` is +empty then default session of the app will be returned. + +## Properties + +The `session` module has the following properties: + +### session.defaultSession + +Returns the default session object of the app. + +## Class: Session + +You can create a `Session` object in the `session` module: + +```javascript +const session = require('electron').session; + +var ses = session.fromPartition('persist:name'); +``` + +### Instance Events + +The following events are available on instances of `Session`: + +#### Event: 'will-download' * `event` Event * `item` [DownloadItem](download-item.md) @@ -34,11 +71,11 @@ session.on('will-download', function(event, item, webContents) { }); ``` -## Methods +### Instance Methods -The `session` object has the following methods: +The following methods are available on instances of `Session`: -### `session.cookies` +#### `ses.cookies` The `cookies` gives you ability to query and modify cookies. For example: @@ -74,7 +111,7 @@ win.webContents.on('did-finish-load', function() { }); ``` -### `session.cookies.get(details, callback)` +#### `ses.cookies.get(details, callback)` `details` Object, properties: @@ -102,7 +139,7 @@ win.webContents.on('did-finish-load', function() { the number of seconds since the UNIX epoch. Not provided for session cookies. -### `session.cookies.set(details, callback)` +#### `ses.cookies.set(details, callback)` `details` Object, properties: @@ -121,23 +158,23 @@ win.webContents.on('did-finish-load', function() { * `callback` Function - function(error) * `error` Error -### `session.cookies.remove(details, callback)` +#### `ses.cookies.remove(details, callback)` -* `details` Object, proprties: +* `details` Object * `url` String - The URL associated with the cookie * `name` String - The name of cookie to remove * `callback` Function - function(error) * `error` Error -### `session.clearCache(callback)` +#### `ses.clearCache(callback)` * `callback` Function - Called when operation is done Clears the session’s HTTP cache. -### `session.clearStorageData([options, ]callback)` +#### `ses.clearStorageData([options, ]callback)` -* `options` Object (optional), proprties: +* `options` Object (optional) * `origin` String - Should follow `window.location.origin`’s representation `scheme://host:port`. * `storages` Array - The types of storages to clear, can contain: @@ -149,7 +186,7 @@ Clears the session’s HTTP cache. Clears the data of web storages. -### `session.setProxy(config, callback)` +#### `ses.setProxy(config, callback)` * `config` String * `callback` Function - Called when operation is done. @@ -187,14 +224,14 @@ proxy-uri = ["://"][":"] URLs. ``` -### `session.setDownloadPath(path)` +#### `ses.setDownloadPath(path)` * `path` String - The download location Sets download saving directory. By default, the download directory will be the `Downloads` under the respective app folder. -### `session.enableNetworkEmulation(options)` +#### `ses.enableNetworkEmulation(options)` * `options` Object * `offline` Boolean - Whether to emulate network outage. @@ -216,12 +253,12 @@ window.webContents.session.enableNetworkEmulation({ window.webContents.session.enableNetworkEmulation({offline: true}); ``` -### `session.disableNetworkEmulation` +#### `ses.disableNetworkEmulation()` Disables any network emulation already active for the `session`. Resets to the original network configuration. -### `session.setCertificateVerifyProc(proc)` +#### `ses.setCertificateVerifyProc(proc)` * `proc` Function From 08c13cf446d509c79770e8ad635f7d4b339092bb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Nov 2015 21:32:46 +0800 Subject: [PATCH 581/738] Deprecate app.resolveProxy There is now a public API to get default session, this helper is no longer necessary. --- atom/browser/api/lib/app.coffee | 6 ++---- docs/api/app.md | 8 -------- docs/api/session.md | 8 ++++++++ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index c2116fb7bca4..a2fdb847e1c5 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -34,10 +34,6 @@ app.setAppPath = (path) -> app.getAppPath = -> appPath -# Helpers. -app.resolveProxy = (url, callback) -> - session.defaultSession.resolveProxy url, callback - # Routes the events to webContents. for name in ['login', 'certificate-error', 'select-client-certificate'] do (name) -> @@ -51,6 +47,8 @@ app.getDataPath = deprecate 'app.getDataPath', 'app.getPath', -> @getPath 'userData' app.setDataPath = deprecate 'app.setDataPath', 'app.setPath', (path) -> @setPath 'userData', path +app.resolveProxy = deprecate 'app.resolveProxy', 'session.defaultSession.resolveProxy', (url, callback) -> + session.defaultSession.resolveProxy url, callback deprecate.rename app, 'terminate', 'quit' deprecate.event app, 'finish-launching', 'ready', -> setImmediate => # give default app a chance to setup default menu. diff --git a/docs/api/app.md b/docs/api/app.md index d7850c4cb92c..a1d87d2fe993 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -311,14 +311,6 @@ preferred over `name` by Electron. Returns the current application locale. -### `app.resolveProxy(url, callback)` - -* `url` URL -* `callback` Function - -Resolves the proxy information for `url`. The `callback` will be called with -`callback(proxy)` when the request is performed. - ### `app.addRecentDocument(path)` _OS X_ _Windows_ * `path` String diff --git a/docs/api/session.md b/docs/api/session.md index b921fc4839bd..a69c5939ed65 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -224,6 +224,14 @@ proxy-uri = ["://"][":"] URLs. ``` +### `ses.resolveProxy(url, callback)` + +* `url` URL +* `callback` Function + +Resolves the proxy information for `url`. The `callback` will be called with +`callback(proxy)` when the request is performed. + #### `ses.setDownloadPath(path)` * `path` String - The download location From 611f87d17f3fa80529e667199de112954c8d9982 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Nov 2015 21:42:22 +0800 Subject: [PATCH 582/738] spec: Use session.defaultSession in tests --- spec/api-session-spec.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/api-session-spec.coffee b/spec/api-session-spec.coffee index bf91bdd6fc77..6d0a8ac167c0 100644 --- a/spec/api-session-spec.coffee +++ b/spec/api-session-spec.coffee @@ -4,7 +4,7 @@ path = require 'path' fs = require 'fs' {ipcRenderer, remote} = require 'electron' -{app, ipcMain, BrowserWindow} = remote.require 'electron' +{app, ipcMain, session, BrowserWindow} = remote describe 'session module', -> @timeout 10000 @@ -35,9 +35,9 @@ describe 'session module', -> done('Can not find cookie') it 'should over-write the existent cookie', (done) -> - app.defaultSession.cookies.set {url: url, name: '1', value: '1'}, (error) -> + session.defaultSession.cookies.set {url: url, name: '1', value: '1'}, (error) -> return done(error) if error - app.defaultSession.cookies.get {url: url}, (error, list) -> + session.defaultSession.cookies.get {url: url}, (error, list) -> return done(error) if error for cookie in list when cookie.name is '1' if cookie.value is '1' @@ -47,11 +47,11 @@ describe 'session module', -> done('Can not find cookie') it 'should remove cookies', (done) -> - app.defaultSession.cookies.set {url: url, name: '2', value: '2'}, (error) -> + session.defaultSession.cookies.set {url: url, name: '2', value: '2'}, (error) -> return done(error) if error - app.defaultSession.cookies.remove {url: url, name: '2'}, (error) -> + session.defaultSession.cookies.remove {url: url, name: '2'}, (error) -> return done(error) if error - app.defaultSession.cookies.get {url: url}, (error, list) -> + session.defaultSession.cookies.get {url: url}, (error, list) -> return done(error) if error for cookie in list when cookie.name is '2' return done('Cookie not deleted') From 1b464c82e1e99dce6d95f0ac302d601c8e268b3d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 19 Nov 2015 21:48:45 +0800 Subject: [PATCH 583/738] docs: Put webContents.session under Properties --- docs/api/web-contents.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 2b2efb7d47ba..a716bdc593a7 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -225,12 +225,6 @@ The usage is the same with [the `login` event of `app`](app.md#event-login). The `webContents` object has the following instance methods: -### `webContents.session` - -Returns the `session` object used by this webContents. - -See [session documentation](session.md) for this object's methods. - ### `webContents.loadURL(url[, options])` * `url` URL @@ -705,6 +699,10 @@ win.webContents.on('did-finish-load', function() { `WebContents` objects also have the following properties: +### `webContents.session` + +Returns the [session](session.md) object used by this webContents. + ### `webContents.devToolsWebContents` Get the `WebContents` of DevTools for this `WebContents`. From f2472274b7604dda90bdf122a2c2718539484268 Mon Sep 17 00:00:00 2001 From: Sota Yamashita Date: Thu, 19 Nov 2015 22:52:37 +0900 Subject: [PATCH 584/738] Rename quick-start.md -> tutorial/quick-start.md --- docs-translations/jp/{ => tutorial}/quick-start.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs-translations/jp/{ => tutorial}/quick-start.md (100%) diff --git a/docs-translations/jp/quick-start.md b/docs-translations/jp/tutorial/quick-start.md similarity index 100% rename from docs-translations/jp/quick-start.md rename to docs-translations/jp/tutorial/quick-start.md From bee1af3264df67583b44cc99d3c7715f78019fa6 Mon Sep 17 00:00:00 2001 From: Sota Yamashita Date: Thu, 19 Nov 2015 22:54:01 +0900 Subject: [PATCH 585/738] Create README.md --- docs-translations/jp/READE.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs-translations/jp/READE.md diff --git a/docs-translations/jp/READE.md b/docs-translations/jp/READE.md new file mode 100644 index 000000000000..32b14b0fdd2b --- /dev/null +++ b/docs-translations/jp/READE.md @@ -0,0 +1,3 @@ +# チュートリアル + +* [クイックスタート](tutorial/quick-start.md) From fd3b8ad62304d74b76ddba6d50ea08cd03663151 Mon Sep 17 00:00:00 2001 From: Sota Yamashita Date: Thu, 19 Nov 2015 22:54:40 +0900 Subject: [PATCH 586/738] Rename: READE.md -> README.md --- docs-translations/jp/{READE.md => README.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs-translations/jp/{READE.md => README.md} (100%) diff --git a/docs-translations/jp/READE.md b/docs-translations/jp/README.md similarity index 100% rename from docs-translations/jp/READE.md rename to docs-translations/jp/README.md From eca98b85fcbabcca9ccb265287cf665da830753f Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 20 Nov 2015 02:25:44 +0900 Subject: [PATCH 587/738] Cleanup docs, fix typos --- README-ko.md | 20 +-- .../development/atom-shell-vs-node-webkit.md | 19 ++- .../development/build-instructions-linux.md | 31 ++-- .../development/build-instructions-osx.md | 10 +- .../development/build-instructions-windows.md | 42 +++--- .../development/build-system-overview.md | 28 ++-- .../ko-KR/development/coding-style.md | 36 +++-- .../development/setting-up-symbol-server.md | 36 +++-- .../source-code-directory-structure.md | 31 ++-- docs-translations/ko-KR/styleguide.md | 23 ++- .../tutorial/application-distribution.md | 59 ++++---- .../ko-KR/tutorial/application-packaging.md | 61 ++++---- .../ko-KR/tutorial/debugging-main-process.md | 17 ++- .../desktop-environment-integration.md | 138 +++++++++++------- .../ko-KR/tutorial/devtools-extension.md | 42 ++++-- .../mac-app-store-submission-guide.md | 39 ++--- .../ko-KR/tutorial/online-offline-events.md | 11 +- .../ko-KR/tutorial/quick-start.md | 70 +++++---- .../ko-KR/tutorial/supported-platforms.md | 16 +- .../tutorial/using-native-node-modules.md | 33 +++-- .../tutorial/using-pepper-flash-plugin.md | 8 +- .../tutorial/using-selenium-and-webdriver.md | 33 +++-- 22 files changed, 463 insertions(+), 340 deletions(-) diff --git a/README-ko.md b/README-ko.md index d35ba87f62b7..606d4e973e3e 100644 --- a/README-ko.md +++ b/README-ko.md @@ -8,8 +8,8 @@ :zap: *프레임워크 이름이 Atom Shell에서 Electron으로 변경되었습니다* :zap: -Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 -어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. 이 프레임워크는 +Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 +Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. [Node.js](https://nodejs.org/)와 [Chromium](http://www.chromium.org)을 기반으로 만들어졌으며 [Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다. @@ -17,17 +17,17 @@ Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서 [@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요. 이 프로젝트는 [기여자 규약 1.2](http://contributor-covenant.org/version/1/2/0/)을 -준수합니다. 따라서 이 프로젝트의 개발에 참여하려면 이 계약을 지켜야 합니다. -받아들일 수 없는 행위를 발견했을 경우 atom@github.com로 보고 하십시오. +준수합니다. 따라서 이 프로젝트의 개발에 참여하려면 이 계약을 지켜야 합니다. 받아들일 수 +없는 행위를 발견했을 경우 atom@github.com로 보고 하십시오. ## 다운로드 Linux, Windows, OS X 용으로 미리 빌드된 Electron 바이너리와 디버그 심볼이 준비되어 -있습니다. [releases](https://github.com/atom/electron/releases) 페이지에서 -받아 볼 수 있습니다. +있습니다. [releases](https://github.com/atom/electron/releases) 페이지에서 받아 볼 +수 있습니다. -또한 [`npm`](https://docs.npmjs.com/)을 통해 미리 빌드된 Electron 바이너리를 -설치할 수도 있습니다: +또한 [`npm`](https://docs.npmjs.com/)을 통해 미리 빌드된 Electron 바이너리를 설치할 +수도 있습니다: ```sh # $PATH에 `electron` 커맨드를 등록하고 전역에 설치합니다. @@ -70,5 +70,5 @@ API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝 - Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널 [awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에 -커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 -한번 참고해 보시기 바랍니다. +커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 한번 참고해 보시기 +바랍니다. diff --git a/docs-translations/ko-KR/development/atom-shell-vs-node-webkit.md b/docs-translations/ko-KR/development/atom-shell-vs-node-webkit.md index e7dd017fd720..22e8e3756469 100644 --- a/docs-translations/ko-KR/development/atom-shell-vs-node-webkit.md +++ b/docs-translations/ko-KR/development/atom-shell-vs-node-webkit.md @@ -2,17 +2,17 @@ __참고: Electron은 Atom Shell의 새로운 이름입니다.__ -NW.js 처럼 Electron은 JavaScript와 HTML 그리고 Node 통합 환경을 제공함으로써 -웹 페이지에서 저 수준 시스템에 접근할 수 있도록 하여 웹 기반 데스크탑 어플리케이션을 +NW.js 처럼 Electron은 JavaScript와 HTML 그리고 Node 통합 환경을 제공함으로써 웹 +페이지에서 저 수준 시스템에 접근할 수 있도록 하여 웹 기반 데스크탑 어플리케이션을 작성할 수 있도록 하는 프레임워크 입니다. 하지만 Electron과 NW.js는 근본적인 개발흐름의 차이도 있습니다: __1. 어플리케이션의 엔트리 포인트__ -NW.js에선 어플리케이션의 엔트리 포인트로 웹 페이지를 사용합니다. -`package.json`내의 main 필드에 메인 웹 페이지(index.html) URL을 지정하면 -어플리케이션의 메인 윈도우로 열리게 됩니다. +NW.js에선 어플리케이션의 엔트리 포인트로 웹 페이지를 사용합니다. `package.json`내의 +main 필드에 메인 웹 페이지(index.html) URL을 지정하면 어플리케이션의 메인 윈도우로 +열리게 됩니다. Electron에선 JavaScript를 엔트리 포인트로 사용합니다. URL을 직접 제공하는 대신 API를 사용하여 직접 브라우저 창과 HTML 파일을 로드할 수 있습니다. 또한 윈도우의 종료시기를 @@ -31,11 +31,10 @@ Chromium Content 모듈과 종속성 라이브러리들을 포함합니다. 유 __3. Node 통합__ -NW.js는 웹 페이지에서 require를 사용할 수 있도록 Chromium을 패치했습니다. -한편 Electron은 Chromium의 해킹을 방지하기 위해 libuv loop와 각 플랫폼의 -메시지 루프에 통합하는 다른 방법을 채택하였습니다. -[`node_bindings`][node-bindings]의 코드를 보면 이 부분이 어떻게 구현됬는지를 -알 수 있습니다. +NW.js는 웹 페이지에서 require를 사용할 수 있도록 Chromium을 패치했습니다. 한편 +Electron은 Chromium의 해킹을 방지하기 위해 libuv loop와 각 플랫폼의 메시지 루프에 +통합하는 다른 방법을 채택하였습니다. [`node_bindings`][node-bindings]의 코드를 보면 +이 부분이 어떻게 구현됬는지 알 수 있습니다. __4. 다중 컨텍스트__ diff --git a/docs-translations/ko-KR/development/build-instructions-linux.md b/docs-translations/ko-KR/development/build-instructions-linux.md index 7a6a476400a0..c4f161fa56a2 100644 --- a/docs-translations/ko-KR/development/build-instructions-linux.md +++ b/docs-translations/ko-KR/development/build-instructions-linux.md @@ -38,8 +38,8 @@ $ sudo yum install clang dbus-devel gtk2-devel libnotify-devel libgnome-keyring- ## 가상머신을 사용하여 빌드 하는 경우 -만약 Electron을 가상머신으로 빌드 할 계획이라면 해당 가상머신의 스토리지를 -최소 25GB 이상을 확보해 놓아야 합니다. +만약 Electron을 가상머신으로 빌드 할 계획이라면 해당 가상머신의 스토리지를 최소 25GB +이상 확보해 놓아야 합니다. ## 코드 가져오기 @@ -49,11 +49,10 @@ $ git clone https://github.com/atom/electron.git ## 부트 스트랩 -부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 -프로젝트 파일을 생성합니다. 스크립트가 정상적으로 작동하기 위해선 -Python 2.7.x 버전이 필요합니다. 아마 다운로드 작업이 상당히 많은 시간을 -소요할 것입니다. 참고로 Electron은 빌드 툴체인으로 `ninja`를 사용하므로 -`Makefile`은 생성되지 않습니다. +부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 프로젝트 +파일을 생성합니다. 스크립트가 정상적으로 작동하기 위해선 Python 2.7.x 버전이 +필요합니다. 아마 다운로드 작업이 상당히 많은 시간을 소요할 것입니다. 참고로 Electron은 +`ninja`를 빌드 툴체인으로 사용하므로 `Makefile`은 생성되지 않습니다. ```bash $ cd electron @@ -84,18 +83,18 @@ $ ./script/bootstrap.py -v --target_arch=arm $ ./script/build.py ``` -이 스크립트는 `out/R` 디렉터리에 크기가 매우 큰 Electron 실행 파일을 배치합니다. -파일 크기는 1.3GB를 초과합니다. 이러한 문제가 발생하는 이유는 Release 타겟 바이너리가 -디버그 심볼을 포함하기 때문입니다. 파일 크기를 줄이려면 -`create-dist.py` 스크립트를 실행하세요: +이 스크립트는 `out/R` 디렉터리에 크기가 매우 큰 Electron 실행 파일을 배치합니다. 파일 +크기는 1.3GB를 초과합니다. 이러한 문제가 발생하는 이유는 Release 타겟 바이너리가 +디버그 심볼을 포함하기 때문입니다. 파일 크기를 줄이려면 `create-dist.py` 스크립트를 +실행하세요: ```bash $ ./script/create-dist.py ``` -이 스크립트는 매우 작은 배포판을 `dist` 디렉터리에 생성합니다. -create-dist.py 스크립트를 실행한 이후부턴 1.3GB를 초과하는 공간을 차지하는 -`out/R` 폴더의 바이너리는 삭제해도 됩니다. +이 스크립트는 매우 작은 배포판을 `dist` 디렉터리에 생성합니다. create-dist.py +스크립트를 실행한 이후부턴 1.3GB에 육박하는 공간을 차지하는 `out/R` 폴더의 바이너리는 +삭제해도 됩니다. 또는 `Debug` 타겟만 빌드 할 수 있습니다: @@ -119,8 +118,8 @@ $ ./script/clean.py ## libtinfo.so.5 동적 링크 라이브러리를 로드하는 도중 에러가 발생할 경우 -미리 빌드된 `clang`은 `libtinfo.so.5`로 링크를 시도합니다. -따라서 플랫폼에 따라 적당한 `libncurses` symlink를 추가하세요: +미리 빌드된 `clang`은 `libtinfo.so.5`로 링크를 시도합니다. 따라서 플랫폼에 따라 +적당한 `libncurses` symlink를 추가하세요: ```bash $ sudo ln -s /usr/lib/libncurses.so.5 /usr/lib/libtinfo.so.5 diff --git a/docs-translations/ko-KR/development/build-instructions-osx.md b/docs-translations/ko-KR/development/build-instructions-osx.md index 222d4fc31c4e..9e2a76d31045 100644 --- a/docs-translations/ko-KR/development/build-instructions-osx.md +++ b/docs-translations/ko-KR/development/build-instructions-osx.md @@ -20,9 +20,9 @@ $ git clone https://github.com/atom/electron.git ## 부트 스트랩 -부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 -프로젝트 파일을 생성합니다. 참고로 Electron은 빌드 툴체인으로 `ninja`를 사용하므로 -Xcode 프로젝트는 생성되지 않습니다. +부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 프로젝트 +파일을 생성합니다. 참고로 Electron은 `ninja`를 빌드 툴체인으로 사용하므로 Xcode +프로젝트는 생성되지 않습니다. ```bash $ cd electron @@ -47,8 +47,8 @@ $ ./script/build.py -c D ## 32비트 지원 -Electron은 현재 OS X 64비트만 지원하고 있습니다. 그리고 앞으로도 OS X 32비트는 -지원할 계획이 없습니다. +Electron은 현재 OS X 64비트만 지원하고 있습니다. 그리고 앞으로도 OS X 32비트는 지원할 +계획이 없습니다. ## 테스트 diff --git a/docs-translations/ko-KR/development/build-instructions-windows.md b/docs-translations/ko-KR/development/build-instructions-windows.md index 69811ac388f7..13bbf47a3a76 100644 --- a/docs-translations/ko-KR/development/build-instructions-windows.md +++ b/docs-translations/ko-KR/development/build-instructions-windows.md @@ -11,18 +11,18 @@ * [Git](http://git-scm.com) 현재 사용하고 있는 PC에 Windows를 설치하지 않았다면 [modern.ie](https://www.modern.ie/en-us/virtualization-tools#downloads)에서 -사용 기한이 정해져있는 무료 가상머신 버전의 Windows를 받아 Electron을 -빌드하는 방법도 있습니다. +사용 기한이 정해져있는 무료 가상머신 버전의 Windows를 받아 Electron을 빌드하는 방법도 +있습니다. -Electron은 모든 빌드를 command-line 스크립트를 통해 빌드합니다. 따라서 빌드에 -Visual Studio를 사용할 수 없습니다. 하지만 여전히 Electron을 개발할 땐 아무 에디터나 -사용할 수 있습니다. 빠른 시일내에 Visual Studio를 이용한 빌드도 지원할 계획입니다. +Electron은 모든 빌드를 command-line 스크립트를 통해 빌드합니다. 따라서 빌드에 Visual +Studio를 사용할 수 없습니다. 하지만 여전히 Electron을 개발할 땐 어떤 에디터든 사용이 +가능합니다. 그리고 빠른 시일내에 Visual Studio를 이용한 빌드도 지원할 계획입니다. -**참고:** Visual Studio가 직접 빌드에 사용되지 않더라도 IDE와 같이 제공된 -빌드 툴체인이 빌드에 **반드시** 사용되므로 여전히 필요합니다. +**참고:** Visual Studio가 직접 빌드에 사용되지 않더라도 IDE와 같이 제공된 빌드 +툴체인이 빌드에 **반드시** 사용되므로 여전히 필요합니다. -**참고:** Visual Studio 2015는 사용할 수 없습니다. -MSVS **2013** 을 사용하고 있는지 확인해주세요. +**참고:** Visual Studio 2015는 사용할 수 없습니다 MSVS **2013** 을 사용하고 있는지 +확인해주세요. ## 코드 가져오기 @@ -32,9 +32,9 @@ $ git clone https://github.com/atom/electron.git ## 부트 스트랩 -부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 -프로젝트 파일을 생성합니다. 참고로 Electron은 빌드 툴체인으로 `ninja`를 사용하므로 -Visual Studio 프로젝트는 생성되지 않습니다. +부트스트랩 스크립트는 필수적인 빌드 종속성 라이브러리들을 모두 다운로드하고 프로젝트 +파일을 생성합니다. 참고로 Electron은 `ninja`를 빌드 툴체인으로 사용하므로 Visual +Studio 프로젝트는 생성되지 않습니다. ```powershell $ cd electron @@ -60,8 +60,8 @@ $ python script\build.py -c D ## 64비트 빌드 -64비트를 타겟으로 빌드 하려면 부트스트랩 스크립트를 실행할 때 -`--target_arch=x64` 인자를 같이 넘겨주면 됩니다: +64비트를 타겟으로 빌드 하려면 부트스트랩 스크립트를 실행할 때 `--target_arch=x64` +인자를 같이 넘겨주면 됩니다: ```powershell $ python script\bootstrap.py -v --target_arch=x64 @@ -83,8 +83,8 @@ $ python script\cpplint.py $ python script\test.py ``` -테스트 실행시 `runas`와 같은 네이티브 모듈을 포함하는데 이 모듈은 디버그 빌드에서 -같이 사용할 수 없습니다. 하지만 여전히 릴리즈 빌드에선 사용할 수 있습니다. +테스트 실행시 `runas`와 같은 네이티브 모듈을 포함하는데 이 모듈은 디버그 빌드에서 같이 +사용할 수 없습니다. 하지만 여전히 릴리즈 빌드에선 사용할 수 있습니다. 릴리즈 빌드로 테스트를 실행하려면 다음 커맨드를 사용하면 됩니다: @@ -105,8 +105,8 @@ Visual Studio가 업데이트까지 완벽하게 설치된 최신버전인지 ### Assertion failed: ((handle))->activecnt >= 0 -Cygwin에서 빌드 할 경우 `bootstrap.py` 스크립트가 다음의 에러와 함께 빌드에 -실패할 수 있습니다: +Cygwin에서 빌드 할 경우 `bootstrap.py` 스크립트가 다음의 에러와 함께 빌드에 실패할 수 +있습니다: ``` Assertion failed: ((handle))->activecnt >= 0, file src\win\pipe.c, line 1430 @@ -123,9 +123,9 @@ Traceback (most recent call last): subprocess.CalledProcessError: Command '['npm.cmd', 'install']' returned non-zero exit status 3 ``` -이 버그는 Cygwin Python과 Win32 Node를 같이 사용할 때 발생합니다. -부트스트랩 스크립트에서 Win32 Python을 사용함으로써 이 문제를 해결할 수 있습니다. -`C:\Python27` 디렉터리에 Python이 설치되었다는 가정하에 다음 명령을 실행하면 됩니다: +이 버그는 Cygwin Python과 Win32 Node를 같이 사용할 때 발생합니다. 부트스트랩 +스크립트에서 Win32 Python을 사용함으로써 이 문제를 해결할 수 있습니다. `C:\Python27` +디렉터리에 Python이 설치되었다는 가정하에 다음 명령을 실행하면 됩니다: ```bash $ /cygdrive/c/Python27/python.exe script/bootstrap.py diff --git a/docs-translations/ko-KR/development/build-system-overview.md b/docs-translations/ko-KR/development/build-system-overview.md index 0c35d04d7bd7..71002ff584e4 100644 --- a/docs-translations/ko-KR/development/build-system-overview.md +++ b/docs-translations/ko-KR/development/build-system-overview.md @@ -9,17 +9,17 @@ Electron을 빌드 할 때 `gyp` 파일들은 다음과 같은 규칙을 따릅 * `atom.gyp`는 Electron의 빌드 과정 자체를 정의합니다. * `common.gypi`는 Node가 Chromium과 함께 빌드될 수 있도록 조정한 빌드 설정입니다. -* `vendor/brightray/brightray.gyp`는 `brightray`의 빌드 과정을 정의하고 - Chromium 링킹에 대한 기본적인 설정을 포함합니다. +* `vendor/brightray/brightray.gyp`는 `brightray`의 빌드 과정을 정의하고 Chromium + 링킹에 대한 기본적인 설정을 포함합니다. * `vendor/brightray/brightray.gypi`는 빌드에 대한 일반적인 설정이 포함되어 있습니다. ## 구성요소 빌드 Chromium은 꽤나 큰 프로젝트입니다. 이러한 이유로 인해 최종 링킹 작업은 상당한 시간이 소요될 수 있습니다. 보통 이런 문제는 개발을 어렵게 만듭니다. 우리는 이 문제를 해결하기 -위해 Chromium의 "component build" 방식을 도입했습니다. 이는 각각의 컴포넌트를 -각각 따로 분리하여 공유 라이브러리로 빌드 합니다. 하지만 이 빌드 방식을 사용하면 -링킹 작업은 매우 빨라지지만 실행 파일 크기가 커지고 성능이 저하됩니다. +위해 Chromium의 "component build" 방식을 도입했습니다. 이는 각각의 컴포넌트를 각각 +따로 분리하여 공유 라이브러리로 빌드 합니다. 하지만 이 빌드 방식을 사용하면 링킹 작업은 +매우 빨라지지만 실행 파일 크기가 커지고 성능이 저하됩니다. Electron도 이러한 방식에 상당히 비슷한 접근을 했습니다: `Debug` 빌드 시 바이너리는 공유 라이브러리 버전의 Chromium 컴포넌트를 사용함으로써 @@ -33,15 +33,15 @@ Prebuilt된 모든 Chromium 바이너리들은 부트스트랩 스크립트가 기본적으로 공유 라이브러리와 정적 라이브러리 모두 다운로드되며 최종 전체 파일 크기는 플랫폼에 따라 800MB에서 2GB까지 차지합니다. -기본적으로 (`libchromiumcontent`)는 Amazon Web Service를 통해 다운로드 됩니다. -만약 `LIBCHROMIUMCONTENT_MIRROR` 환경 변수가 설정되어 있으면 부트스트랩은 해당 링크를 +기본적으로 (`libchromiumcontent`)는 Amazon Web Service를 통해 다운로드 됩니다. 만약 +`LIBCHROMIUMCONTENT_MIRROR` 환경 변수가 설정되어 있으면 부트스트랩은 해당 링크를 사용하여 바이너리를 다운로드 합니다. [libchromiumcontent-qiniu-mirror](https://github.com/hokein/libchromiumcontent-qiniu-mirror)는 libchromiumcontent의 미러입니다. 만약 AWS에 접근할 수 없다면 `export LIBCHROMIUMCONTENT_MIRROR=http://7xk3d2.dl1.z0.glb.clouddn.com/` 미러를 통해 다운로드 할 수 있습니다. -만약 빠르게 Electron의 개발 또는 테스트만 하고 싶다면 `--dev` 플래그를 추가하여 -공유 라이브러리만 다운로드할 수 있습니다: +만약 빠르게 Electron의 개발 또는 테스트만 하고 싶다면 `--dev` 플래그를 추가하여 공유 +라이브러리만 다운로드할 수 있습니다: ```bash $ ./script/bootstrap.py --dev @@ -55,15 +55,15 @@ Electron은 `Release`와 `Debug` 빌드가 서로 다른 라이브러리 링크 지원하지 않습니다. 이 문제를 해결하기 위해 Electron은 링크 설정을 제어하는 `gyp` 변수 -`libchromiumcontent_component`를 사용하고 `gyp`를 실행할 때 -단 하나의 타겟만을 생성합니다. +`libchromiumcontent_component`를 사용하고 `gyp`를 실행할 때 단 하나의 타겟만을 +생성합니다. ## 타겟 이름 많은 프로젝트에서 타겟 이름을 `Release` 와 `Debug`를 사용하는데 반해 Electron은 -`R`과 `D`를 대신 사용합니다. 이유는 가끔 알 수 없는 이유(randomly)로 -`Release` 와 `Debug` 중 하나만 빌드 설정에 정의되어 있을때 `gyp`가 크래시를 일으키는데 -이유는 앞서 말한 바와 같이 Electron은 한번에 한개의 타겟만을 생성할 수 있기 때문입니다. +`R`과 `D`를 대신 사용합니다. 이유는 가끔 알 수 없는 이유(randomly)로 `Release` 와 +`Debug` 중 하나만 빌드 설정에 정의되어 있을때 `gyp`가 크래시를 일으키는데 이유는 앞서 +말한 바와 같이 Electron은 한번에 한개의 타겟만을 생성할 수 있기 때문입니다. 이 문제는 개발자에게만 영향을 미칩니다. 만약 단순히 Electron을 rebranding 하기 위해 빌드 하는 것이라면 이 문제에 신경 쓸 필요가 없습니다. diff --git a/docs-translations/ko-KR/development/coding-style.md b/docs-translations/ko-KR/development/coding-style.md index 0dc16ba0ad68..21ee03fd0a1d 100644 --- a/docs-translations/ko-KR/development/coding-style.md +++ b/docs-translations/ko-KR/development/coding-style.md @@ -4,29 +4,35 @@ ## C++과 Python -C++과 Python 스크립트는 Chromium의 [코딩 스타일](http://www.chromium.org/developers/coding-style)을 따릅니다. -파이선 스크립트 `script/cpplint.py`를 사용하여 모든 파일이 해당 코딩스타일에 맞게 코딩 되었는지 확인할 수 있습니다. +C++과 Python 스크립트는 Chromium의 +[코딩 스타일](http://www.chromium.org/developers/coding-style)을 따릅니다. 파이선 +스크립트 `script/cpplint.py`를 사용하여 모든 파일이 해당 코딩스타일에 맞게 코딩 했는지 +확인할 수 있습니다. Python 버전은 2.7을 사용합니다. -C++ 코드는 많은 Chromium의 추상화와 타입을 사용합니다. 따라서 Chromium 코드에 대해 잘 알고 있어야 합니다. -이와 관련하여 시작하기 좋은 장소로 Chromium의 [Important Abstractions and Data Structures] -(https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures) 문서가 있습니다. -이 문서에선 몇가지 특별한 타입과 스코프 타입(스코프 밖으로 나가면 자동으로 메모리에서 할당을 해제합니다. 스마트 포인터로 보시면 됩니다) -그리고 로깅 메커니즘 등을 언급하고 있습니다. +C++ 코드는 많은 Chromium의 추상화와 타입을 사용합니다. 따라서 Chromium 코드에 대해 잘 +알고 있어야 합니다. 이와 관련하여 시작하기 좋은 장소로 Chromium의 +[Important Abstractions and Data Structures](https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures) +문서가 있습니다. 이 문서에선 몇가지 특별한 타입과 스코프 타입(스코프 밖으로 나가면 +자동으로 메모리에서 할당을 해제합니다. 스마트 포인터와 같습니다) 그리고 로깅 메커니즘 +등을 언급하고 있습니다. ## CoffeeScript -CoffeeScript의 경우 GitHub의 [스타일 가이드](https://github.com/styleguide/javascript)를 기본으로 따릅니다. -그리고 다음 규칙을 따릅니다: +CoffeeScript의 경우 GitHub의 +[스타일 가이드](https://github.com/styleguide/javascript)를 기본으로 따릅니다. +그리고 추가로 다음 규칙을 따릅니다: * Google의 코딩 스타일에도 맞추기 위해 파일의 끝에는 **절대** 개행을 삽입해선 안됩니다. -* 파일 이름의 공백은 `_`대신에 `-`을 사용하여야 합니다. 예를 들어 `file_name.coffee`를 -`file-name.coffee`로 고쳐야합니다. 왜냐하면 [github/atom](https://github.com/github/atom) 에서 사용되는 모듈의 이름은 -보통 `module-name`형식이기 때문입니다. 이 규칙은 '.coffee' 파일에만 적용됩니다. +* 파일 이름의 공백은 `_`대신에 `-`을 사용하여야 합니다. 예를 들어 +`file_name.coffee`를 `file-name.coffee`로 고쳐야합니다. 왜냐하면 +[github/atom](https://github.com/github/atom)에서 사용되는 모듈의 이름은 보통 +`module-name` 형식이기 때문입니다. 이 규칙은 '.coffee' 파일에만 적용됩니다. ## API 이름 -새로운 API를 만들 땐 getter, setter스타일 대신 jQuery의 one-function스타일을 사용해야 합니다. 예를 들어 -`.getText()`와 `.setText(text)`대신에 `.text([text])`형식으로 설계하면 됩니다. -포럼에 이 문제에 대한 [논의](https://github.com/atom/electron/issues/46)가 있습니다. +새로운 API를 만들 땐 getter, setter스타일 대신 jQuery의 one-function 스타일을 +사용해야 합니다. 예를 들어 `.getText()`와 `.setText(text)`대신에 `.text([text])` +형식으로 설계하면 됩니다. 포럼에 이 문제에 대한 [논의](https://github.com/atom/electron/issues/46)가 +진행되고 있습니다. diff --git a/docs-translations/ko-KR/development/setting-up-symbol-server.md b/docs-translations/ko-KR/development/setting-up-symbol-server.md index ed43e0fae295..bfd347a4a1b7 100644 --- a/docs-translations/ko-KR/development/setting-up-symbol-server.md +++ b/docs-translations/ko-KR/development/setting-up-symbol-server.md @@ -1,29 +1,36 @@ # 디버거에서 디버그 심볼 서버 설정 -디버그 심볼은 디버깅 세션을 더 좋게 개선해 줍니다. 디버그 심볼은 실행 파일과 동적 링크 라이브러리에서 메서드에 대한 정보를 담고 있으며 명료한 함수 호출 스텍 정보를 제공합니다. -심볼 서버는 유저가 크기가 큰 디버깅용 파일을 필수적으로 다운로드 받지 않고도 디버거가 알맞은 심볼, 바이너리 그리고 소스를 자동적으로 로드할 수 있도록 해줍니다. -서버 사용법은 [Microsoft의 심볼 서버](http://support.microsoft.com/kb/311503)와 비슷합니다. 이 문서를 참조하세요. +디버그 심볼은 디버깅 세션을 더 좋게 개선해 줍니다. 디버그 심볼은 실행 파일과 동적 링크 +라이브러리에서 메서드에 대한 정보를 담고 있으며 명료한 함수 호출 스텍 정보를 제공합니다. +심볼 서버는 유저가 크기가 큰 디버깅용 파일을 필수적으로 다운로드 받지 않고도 디버거가 +알맞은 심볼, 바이너리 그리고 소스를 자동적으로 로드할 수 있도록 해줍니다. 서버 사용법은 +[Microsoft의 심볼 서버](http://support.microsoft.com/kb/311503)와 비슷합니다. +사용법을 알아보려면 이 문서를 참조하세요. -참고로 릴리즈된 Electron 빌드는 자체적으로 많은 최적화가 되어 있는 관계로 경우에 따라 디버깅이 쉽지 않을 수 있습니다. -Inlining, tail call 등의 컴파일러 최적화에 의해 디버거가 모든 변수의 컨텐츠를 보여줄 수 없는 경우도 있고 실행 경로가 이상하게 보여질 수 있습니다. -유일한 해결 방법은 최적화되지 않은 로컬 빌드를 하는 것입니다. +참고로 릴리즈된 Electron 빌드는 자체적으로 많은 최적화가 되어 있는 관계로 경우에 따라 +디버깅이 쉽지 않을 수 있습니다. Inlining, tail call 등 컴파일러 최적화에 의해 디버거가 +모든 변수의 컨텐츠를 보여줄 수 없는 경우도 있고 실행 경로가 이상하게 보여지는 경우도 +있습니다. 유일한 해결 방법은 최적화되지 않은 로컬 빌드를 하는 것입니다. -공식적인 Electron의 심볼 서버의 URL은 http://54.249.141.255:8086/atom-shell/symbols 입니다. -일단 이 URL에 직접적으로 접근할 수는 없습니다: 디버깅 툴에 심볼의 경로를 추가해야합니다. -아래의 예제를 참고하면 로컬 캐시 디렉터리는 서버로부터 중복되지 않게 PDB를 가져오는데 사용됩니다. +공식적인 Electron의 심볼 서버의 URL은 +http://54.249.141.255:8086/atom-shell/symbols 입니다. 일단 이 URL에 직접적으로 +접근할 수는 없습니다: 디버깅 툴에 심볼의 경로를 추가해야합니다. 아래의 예제를 참고하면 +로컬 캐시 디렉터리는 서버로부터 중복되지 않게 PDB를 가져오는데 사용됩니다. `c:\code\symbols` 캐시 디렉터리를 사용중인 OS에 맞춰 적당한 경로로 변경하세요. ## Windbg에서 심볼 서버 사용하기 -Windbg 심볼 경로는 구분자와 *(별) 문자로 설정되어 있습니다. -Electron 심볼 서버만을 사용하려면 심볼 경로의 엔트리를 추가해야 합니다 (__참고:__ `c:\code\symbols` 디렉터리 경로를 PC가 원하는 경로로 수정할 수 있습니다): +Windbg 심볼 경로는 구분자와 `*` 문자로 설정되어 있습니다. Electron 심볼 서버만 +사용하려면 심볼 경로의 엔트리를 추가해야 합니다. (__참고:__ `c:\code\symbols` +디렉터리 경로를 PC가 원하는 경로로 수정할 수 있습니다): ``` SRV*c:\code\symbols\*http://54.249.141.255:8086/atom-shell/symbols ``` -Windbg 메뉴 또는 `.sympath` 커맨드를 이용하여 환경에 `_NT_SYMBOL_PATH` 문자열을 설정합니다. -만약 Microsoft의 심볼서버로 부터 심볼을 받아오려면 다음과 같이 리스팅을 먼저 해야합니다: +Windbg 메뉴 또는 `.sympath` 커맨드를 이용하여 환경에 `_NT_SYMBOL_PATH` 문자열을 +설정합니다. 만약 Microsoft의 심볼서버로 부터 심볼을 받아오려면 다음과 같이 리스팅을 +먼저 해야합니다: ``` SRV*c:\code\symbols\*http://msdl.microsoft.com/download/symbols;SRV*c:\code\symbols\*http://54.249.141.255:8086/atom-shell/symbols @@ -36,7 +43,8 @@ SRV*c:\code\symbols\*http://msdl.microsoft.com/download/symbols;SRV*c:\code\symb ## 문제 해결: Symbols will not load -Windbg에서 다음의 커맨드를 입력하여 왜 심볼이 로드되지 않았는지에 대한 오류 내역을 출력합니다: +Windbg에서 다음의 커맨드를 입력하여 왜 심볼이 로드되지 않았는지에 대한 오류 내역을 +출력합니다: ``` > !sym noisy diff --git a/docs-translations/ko-KR/development/source-code-directory-structure.md b/docs-translations/ko-KR/development/source-code-directory-structure.md index f31d0847db75..e0e172d18b4f 100644 --- a/docs-translations/ko-KR/development/source-code-directory-structure.md +++ b/docs-translations/ko-KR/development/source-code-directory-structure.md @@ -1,8 +1,10 @@ # 소스 코드 디렉터리 구조 -Electron의 소스 코드는 몇 개의 파트로 분리되어 있습니다. 그리고 Chromium의 분리 규칙(separation conventions)을 주로 따르고 있습니다. +Electron의 소스 코드는 몇 개의 파트로 분리되어 있습니다. 그리고 Chromium의 분리 +규칙(separation conventions)을 주로 따르고 있습니다. -이미 [Chromium의 멀티 프로세스 아키텍쳐](http://dev.chromium.org/developers/design-documents/multi-process-architecture)에 익숙해져 있다면 소스 코드를 이해하기 쉬울 것입니다. +이미 [Chromium의 멀티 프로세스 아키텍쳐](http://dev.chromium.org/developers/design-documents/multi-process-architecture)에 +익숙해져 있다면 소스 코드를 이해하기 쉬울 것입니다. ## 소스 코드 구조 @@ -10,8 +12,8 @@ Electron의 소스 코드는 몇 개의 파트로 분리되어 있습니다. 그 Electron ├──atom - Electron의 소스코드. | ├── app - 시스템 엔트리 코드. -| ├── browser - 주 윈도우를 포함한 프론트엔드, UI, 그리고 메인 프로세스에 관련된 것들. -| | | 랜더러와 웹 페이지 관리 관련 코드. +| ├── browser - 주 윈도우를 포함한 프론트엔드, UI, 그리고 메인 프로세스에 관련된 것과 +| | 랜더러와 웹 페이지 관리 관련 코드. | | ├── lib - 메인 프로세스 초기화 코드의 자바스크립트 파트. | | ├── ui - 크로스 플랫폼에 대응하는 UI 구현. | | | ├── cocoa - 코코아 특정 소스 코드. @@ -27,8 +29,8 @@ Electron | | ├── lib - 랜더러 프로세스 초기화 코드의 자바스크립트 파트. | | └── api - 랜더러 프로세스 API들의 구현. | | └── lib - API 구현의 자바스크립트 파트. -| └── common - 메인 프로세스와 랜더러 프로세스에서 공유하는 코드. -| | 유틸리티 함수와 node 메시지 루프를 Chromium의 메시지 루프에 통합시킨 코드도 포함. +| └── common - 메인 프로세스와 랜더러 프로세스에서 공유하는 코드. 유틸리티 함수와 +| node 메시지 루프를 Chromium의 메시지 루프에 통합시킨 코드도 포함. | ├── lib - 공통 자바스크립트 초기화 코드. | └── api - 공통 API들의 구현, Electron의 빌트인 모듈 기초 코드들. | └── lib - API 구현의 자바스크립트 파트. @@ -36,16 +38,21 @@ Electron ├── docs - 참조 문서. ├── spec - 자동화된 테스트. ├── atom.gyp - Electron의 빌드 규칙. -└── common.gypi - 컴파일러 설정 및 `node` 와 `breakpad` 등의 구성요소를 위한 빌드 규칙. +└── common.gypi - 컴파일러 설정 및 `node` 와 `breakpad` 등의 구성요소를 위한 빌드 + 규칙. ``` ## 그외 디렉터리 구조 * **script** - 개발목적으로 사용되는 빌드, 패키징, 테스트, 기타등을 실행하는 스크립트. -* **tools** - gyp 파일에서 사용되는 헬퍼 스크립트 `script`와는 다르게 유저로부터 직접 실행되지 않는 스크립트들을 이곳에 넣습니다. -* **vendor** - 소스코드의 서드파티 종속성 코드 소스 코드 디렉터리가 겹쳐 혼란을 일으킬 수 있기 때문에 - 우리는 `third_party`와 같은 Chromium 소스 코드 디렉터리에서 사용된 폴더 이름을 사용하지 않았습니다. +* **tools** - gyp 파일에서 사용되는 헬퍼 스크립트 `script`와는 다르게 유저로부터 직접 + 실행되지 않는 스크립트들을 이곳에 넣습니다. +* **vendor** - 소스코드의 서드파티 종속성 코드 소스 코드 디렉터리가 겹쳐 혼란을 일으킬 + 수 있기 때문에 `third_party`와 같은 Chromium 소스 코드 디렉터리에서 사용된 폴더 + 이름은 사용하지 않았습니다. * **node_modules** - 빌드에 사용되는 node 서드파티 모듈. * **out** - `ninja`의 임시 출력 디렉터리. -* **dist** - 배포용 바이너리를 빌드할 때 사용하는 `script/create-dist.py` 스크립트로부터 만들어지는 임시 디렉터리. -* **external_binaries** - `gyp` 빌드를 지원하지 않아 따로 다운로드된 서드파티 프레임워크 바이너리들. +* **dist** - 배포용 바이너리를 빌드할 때 사용하는 `script/create-dist.py` + 스크립트로부터 만들어지는 임시 디렉터리. +* **external_binaries** - `gyp` 빌드를 지원하지 않아 따로 다운로드된 서드파티 + 프레임워크 바이너리들. diff --git a/docs-translations/ko-KR/styleguide.md b/docs-translations/ko-KR/styleguide.md index 7318c7e3b403..dd02629c1680 100644 --- a/docs-translations/ko-KR/styleguide.md +++ b/docs-translations/ko-KR/styleguide.md @@ -11,15 +11,15 @@ Electron 문서를 작성하는 규칙은 다음과 같습니다. - `h1` 제목은 페이지당 한 개만 사용할 수 있습니다. - 코드 블럭에서 터미널 언어 선택시 `cmd` 대신 `bash`를 사용합니다. (syntax highlighter를 사용하기 위해서) -- 문서의 `h1` 제목은 반드시 현재 객체 이름과 같게 해야 합니다. - (예시: `browser-window` → `BrowserWindow`) +- 문서의 `h1` 제목은 반드시 현재 객체 이름과 같게 해야 합니다. (`browser-window` → + `BrowserWindow`) - 하이픈(-)으로 구분되었건 다르게 구분되었건 예시와 같이 작성합니다. -- 헤더 밑에 헤더를 바로 사용하지 않습니다. 한 줄이라도 좋으니 헤더와 헤더 사이에 - 설명을 추가합니다. +- 헤더 밑에 헤더를 바로 사용하지 않습니다. 한 줄이라도 좋으니 헤더와 헤더 사이에 설명을 + 추가합니다. - 메서드 헤더는 `code backtick` 으로 표시합니다. - 이벤트 헤더는 한 '따옴표'로 표시합니다. -- 리스트를 2 단계 이상 중첩하지 않습니다. (안타깝게도 markdown 랜더러가 이를 - 지원하지 않습니다) +- 리스트를 2 단계 이상 중첩하지 않습니다. (안타깝게도 markdown 랜더러가 이를 지원하지 + 않습니다) - 섹션에 대한 제목을 추가합니다. Events, Class 메서드 그리고 인스턴스 메서드 등 - 어떤 '것'의 사용 결과를 설명할 때 '될 것입니다' 형식을 사용하여 설명합니다. - 이벤트와 메서드를 표기할 땐 `h3` 헤더를 사용합니다. @@ -37,8 +37,8 @@ Electron 문서를 작성하는 규칙은 다음과 같습니다. 아직 번역되지 않은 언어를 추가하려면 (일부분 포함): - 언어의 약어(예: en-US, ja-JP, ko-KR)로 서브 디렉터리를 만듭니다. -- 서브 디렉터리에 `docs` 디렉터리를 복사합니다. 파일 이름과 디렉터리 구조는 - 모두 유지합니다. +- 서브 디렉터리에 `docs` 디렉터리를 복사합니다. 파일 이름과 디렉터리 구조는 모두 + 유지합니다. - 문서를 번역합니다. - 언어 디렉터리 내의 `README.md`에 번역한 문서의 링크를 추가합니다. - 메인(upstream) Electron의 [README](https://github.com/atom/electron#documentation-translations)에 @@ -65,14 +65,13 @@ Electron 문서 구조를 이해하는 데 참고할 수 있는 유용한 도움 메서드 이름은 인수가 무엇을 받는지에 따라 결정됩니다. 선택적 인수는 브라켓([, ])으로 묶어 이 인수가 다른 인수뒤에서 선택적으로 사용될 수 있다는 것을 표시합니다. -메서드 이름 하단에선 각 인수에 대해 자세한 설명을 합니다. -인수의 타입은 일반적인 타입 중 하나를 받거나: +메서드 이름 하단에선 각 인수에 대해 자세한 설명을 합니다. 인수의 타입은: [`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) -와 같은 일반적으로 쓰이는 타입 중 하나를 받거나 Electron의 -[`webContent`](api/web-content.md)같은 커스텀 타입을 받습니다. +와 같은 일반적으로 쓰이는 타입 중 하나를 받거나 Electron의 [`webContent`](api/web-content.md) +같은 커스텀 타입을 받습니다. ### Events diff --git a/docs-translations/ko-KR/tutorial/application-distribution.md b/docs-translations/ko-KR/tutorial/application-distribution.md index 69269500733a..73839f248b5b 100644 --- a/docs-translations/ko-KR/tutorial/application-distribution.md +++ b/docs-translations/ko-KR/tutorial/application-distribution.md @@ -2,10 +2,9 @@ Electron 어플리케이션을 배포하는 방법은 간단합니다. -먼저 폴더 이름을 `app`로 지정한 후 Electron 리소스 디렉터리에 폴더를 통째로 집어넣기만 하면 됩니다. -리소스 디렉터리는 OS X: `Electron.app/Contents/Resources/` Windows와 Linux: `resources/` 입니다. - -예제: +먼저 폴더 이름을 `app`로 지정한 후 Electron 리소스 디렉터리에 폴더를 통째로 집어넣기만 +하면 됩니다. 리소스 디렉터리는 OS X의 경우: `Electron.app/Contents/Resources/` +Windows와 Linux의 경우: `resources/` 입니다. OS X의 경우: @@ -16,7 +15,7 @@ electron/Electron.app/Contents/Resources/app/ └── index.html ``` -Windows 와 Linux의 경우: +Windows와 Linux의 경우: ```text electron/resources/app @@ -25,16 +24,18 @@ electron/resources/app └── index.html ``` -그리고 `Electron.app`을 실행하면(Linux에선 `electron` Windows에선 `electron.exe`입니다) Electron 앱이 실행시킵니다. -최종 사용자에겐 이 `electron` 폴더(Electron.app)를 배포하면 됩니다. +그리고 `Electron.app`을 실행하면(Linux에선 `electron` Windows에선 `electron.exe` +입니다) Electron 앱이 실행됩니다. 최종 사용자에겐 이 `electron` 폴더(Electron.app)를 +배포하면 됩니다. ## asar로 앱 패키징 하기 -소스파일 전체를 복사해서 배포하는 것과는 별개로 [asar](https://github.com/atom/asar) 아카이브를 통해 -어플리케이션의 소스코드가 사용자에게 노출되는 것을 방지할 수 있습니다. +소스파일 전체를 복사해서 배포하는 것과는 별개로 [asar](https://github.com/atom/asar) +아카이브를 통해 어플리케이션의 소스코드가 사용자에게 노출되는 것을 방지할 수 있습니다. -`asar` 아카이브를 사용할 땐 단순히 `app` 폴더 대신에 어플리케이션을 패키징한 `app.asar` 파일로 대체하면됩니다. -Electron은 자동으로 `app`폴더 대신 asar 아카이브를 기반으로 어플리케이션을 실행합니다. +`asar` 아카이브를 사용할 땐 단순히 `app` 폴더 대신에 어플리케이션을 패키징한 +`app.asar` 파일로 대체하면됩니다. Electron은 자동으로 `app`폴더 대신 asar 아카이브를 +기반으로 어플리케이션을 실행합니다. OS X의 경우: @@ -59,22 +60,25 @@ electron/resources/ ### Windows `electron.exe`을 원하는 이름으로 변경할 수 있습니다. -그리고 [rcedit](https://github.com/atom/rcedit) 또는 [ResEdit](http://www.resedit.net)를 사용하여 아이콘을 변경할 수 있습니다. +그리고 [rcedit](https://github.com/atom/rcedit) 또는 +[ResEdit](http://www.resedit.net)를 사용하여 아이콘을 변경할 수 있습니다. ### OS X -`Electron.app`을 원하는 이름으로 변경할 수 있습니다. 그리고 다음 표시된 어플리케이션 내부 파일에서 -`CFBundleDisplayName`, `CFBundleIdentifier` and `CFBundleName` 필드를 원하는 이름으로 변경해야합니다: +`Electron.app`을 원하는 이름으로 변경할 수 있습니다. 그리고 다음 표시된 어플리케이션 +내부 파일에서 `CFBundleDisplayName`, `CFBundleIdentifier` 그리고 `CFBundleName` +필드를 원하는 이름으로 변경해야 합니다: * `Electron.app/Contents/Info.plist` * `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist` -또한 helper 앱이 프로세스 모니터에 `Electron Helper`로 나오지 않도록 이름을 변경할 수 있습니다. -하지만 반드시 내부 및 모든 helper 앱의 이름을 변경해야 합니다. +또한 helper 앱이 프로세스 모니터에 `Electron Helper`로 나오지 않도록 이름을 +변경할 수 있습니다. 하지만 반드시 내부 및 모든 helper 앱의 이름을 변경해야 합니다. -어플리케이션 아이콘은 `Electron.app/Contents/Resources/atom.icns`을 원하는 아이콘으로 변경하면 됩니다. +어플리케이션 아이콘은 `Electron.app/Contents/Resources/atom.icns`을 원하는 +아이콘으로 변경하면 됩니다. -원하는 이름으로 바꾼 어플리케이션 예제: +어플리케이션 이름을 원하는 이름으로 변경한 예시: ``` MyApp.app/Contents @@ -98,13 +102,14 @@ MyApp.app/Contents ### Linux -실행파일 `electron`의 이름을 원하는 대로 바꿀 수 있습니다. -리눅스 어플리케이션의 아이콘은 [.desktop](https://developer.gnome.org/integration-guide/stable/desktop-files.html.en) 파일을 사용하여 지정할 수 있습니다. +실행파일 `electron`의 이름을 원하는 대로 바꿀 수 있습니다. 리눅스 어플리케이션의 +아이콘은 [.desktop](https://developer.gnome.org/integration-guide/stable/desktop-files.html.en) +파일을 사용하여 지정할 수 있습니다. -### 역주-자동화 +### 역주-자동화 -어플리케이션 배포시 Electron의 리소스를 일일이 수정하는 것은 매우 귀찮고 복잡합니다. -하지만 이 작업을 자동화 시킬 수 있는 몇가지 방법이 있습니다: +어플리케이션 배포시 Electron의 리소스를 일일이 수정하는 것은 매우 반복적이고 복잡합니다. +하지만 이 작업을 자동화 시킬 수 있는 몇가지 방법이 있습니다: * [electron-builder](https://github.com/loopline-systems/electron-builder) * [electron-packager](https://github.com/maxogden/electron-packager) @@ -135,7 +140,9 @@ $ script/build.py -c Release -t myapp ### grunt-build-atom-shell -Electron의 소스코드를 수정하고 다시 빌드하는 작업은 상당히 복잡합니다. -일일이 소스코드를 수정하는 대신 [grunt-build-atom-shell](https://github.com/paulcbetts/grunt-build-atom-shell)을 사용하여 빌드를 자동화 시킬 수 있습니다. +Electron의 소스코드를 수정하고 다시 빌드하는 작업은 상당히 복잡합니다. 일일이 +소스코드를 수정하는 대신 [grunt-build-atom-shell](https://github.com/paulcbetts/grunt-build-atom-shell)을 +사용하여 빌드를 자동화 시킬 수 있습니다. -이 툴을 사용하면 자동으로 `.gyp`파일을 수정하고 다시 빌드합니다. 그리고 어플리케이션의 네이티브 Node 모듈 또한 새로운 실행파일 이름으로 매치 시킵니다. +이 툴을 사용하면 자동으로 `.gyp`파일을 수정하고 다시 빌드합니다. 그리고 어플리케이션의 +네이티브 Node 모듈 또한 새로운 실행파일 이름으로 일치시킵니다. diff --git a/docs-translations/ko-KR/tutorial/application-packaging.md b/docs-translations/ko-KR/tutorial/application-packaging.md index 9a5e3dfb20e2..a04dfebac9a3 100644 --- a/docs-translations/ko-KR/tutorial/application-packaging.md +++ b/docs-translations/ko-KR/tutorial/application-packaging.md @@ -1,7 +1,8 @@ # 어플리케이션 패키징 -Windows에서 일어나는 긴 경로 이름에 대한 [issues](https://github.com/joyent/node/issues/6960)를 완화하고 `require` 속도를 약간 빠르게 하며 -어플리케이션의 리소스와 소스코드를 좋지 않은 사용자로부터 보호하기 위해 어플리케이션을 [asar][asar] 아카이브로 패키징 할 수 있습니다. +Windows에서 일어나는 긴 경로 이름에 대한 [issues](https://github.com/joyent/node/issues/6960)를 +완화하고 `require` 속도를 약간 빠르게 하며 어플리케이션의 리소스와 소스코드를 좋지 않은 +사용자로부터 보호하기 위해 어플리케이션을 [asar][asar] 아카이브로 패키징 할 수 있습니다. ## `asar` 아카이브 생성 @@ -24,13 +25,15 @@ $ asar pack your-app app.asar ## `asar` 아카이브 사용하기 -Electron은 Node.js로 부터 제공된 Node API와 Chromium으로부터 제공된 Web API 두 가지 API를 가지고 있습니다. -따라서 `asar` 아카이브는 두 API 모두 사용할 수 있도록 지원합니다. +Electron은 Node.js로 부터 제공된 Node API와 Chromium으로부터 제공된 Web API 두 가지 +API를 가지고 있습니다. 따라서 `asar` 아카이브는 두 API 모두 사용할 수 있도록 +지원합니다. ### Node API -Electron에선 `fs.readFile`과 `require` 같은 Node API들을 지원하기 위해 `asar` 아카이브가 가상의 디렉터리 구조를 가지도록 -패치했습니다. 그래서 아카이브 내부 리소스들을 정상적인 파일 시스템처럼 접근할 수 있습니다. +Electron에선 `fs.readFile`과 `require` 같은 Node API들을 지원하기 위해 `asar` +아카이브가 가상의 디렉터리 구조를 가지도록 패치했습니다. 그래서 아카이브 내부 +리소스들을 정상적인 파일 시스템처럼 접근할 수 있습니다. 예를 들어 `/path/to`라는 경로에 `example.asar`라는 아카이브가 있다고 가정하면: @@ -90,9 +93,10 @@ $.get('file:///path/to/example.asar/file.txt', function(data) { ### `asar` 아카이브를 일반 파일로 취급하기 -`asar` 아카이브의 체크섬(checksum)을 검사하는 작업등을 하기 위해선 `asar` 아카이브를 파일 그대로 읽어야 합니다. -이러한 작업을 하기 위해 `original-fs` 빌트인 모듈을 `fs` 모듈 대신에 사용할 수 있습니다. -이 모듈은 `asar` 지원이 빠져있습니다. 즉 파일 그대로를 읽어들입니다: +`asar` 아카이브의 체크섬(checksum)을 검사하는 작업등을 하기 위해선 `asar` 아카이브를 +파일 그대로 읽어야 합니다. 이러한 작업을 하기 위해 `original-fs` 빌트인 모듈을 `fs` +모듈 대신에 사용할 수 있습니다. 이 모듈은 `asar` 지원이 빠져있습니다. 즉 파일 그대로를 +읽어들입니다: ```javascript var originalFs = require('original-fs'); @@ -101,22 +105,26 @@ originalFs.readFileSync('/path/to/example.asar'); ## Node API의 한계 -`asar` 아카이브를 Node API가 최대한 디렉터리 구조로 작동하도록 노력해왔지만 여전히 저수준(low-level nature) Node API 때문에 한계가 있습니다. +`asar` 아카이브를 Node API가 최대한 디렉터리 구조로 작동하도록 노력해왔지만 여전히 +저수준(low-level nature) Node API 때문에 한계가 있습니다. ### 아카이브는 읽기 전용입니다 -아카이브는 수정할 수 없으며 기본적으로는 Node API로 파일을 수정할 수 있지만 `asar` 아카이브에선 작동하지 않습니다. +아카이브는 수정할 수 없으며 기본적으로는 Node API로 파일을 수정할 수 있지만 `asar` +아카이브에선 작동하지 않습니다. ### 아카이브 안의 디렉터리를 작업 경로로 설정하면 안됩니다 -`asar` 아카이브는 디렉터리처럼 사용할 수 있도록 구현되었지만 그것은 실제 파일시스템의 디렉터리가 아닌 가상의 디렉터리입니다. -그런 이유로 몇몇 API에서 지원하는 `cwd` 옵션을 `asar` 아카이브 안의 디렉터리 경로로 지정하면 나중에 문제가 발생할 수 있습니다. +`asar` 아카이브는 디렉터리처럼 사용할 수 있도록 구현되었지만 그것은 실제 파일시스템의 +디렉터리가 아닌 가상의 디렉터리입니다. 그런 이유로 몇몇 API에서 지원하는 `cwd` 옵션을 +`asar` 아카이브 안의 디렉터리 경로로 지정하면 나중에 문제가 발생할 수 있습니다. ### 특정 API로 인한 예외적인 아카이브 압축 해제 -많은 `fs` API가 `asar` 아카이브의 압축을 해제하지 않고 바로 아카이브를 읽거나 정보를 가져올 수 있으나 -몇몇 API는 시스템의 실제 파일의 경로를 기반으로 작동하므로 Electron은 API가 원할하게 작동할 수 있도록 -임시 경로에 해당되는 파일의 압축을 해제합니다. 이 작업은 약간의 오버헤드를 불러 일으킬 수 있습니다. +많은 `fs` API가 `asar` 아카이브의 압축을 해제하지 않고 바로 아카이브를 읽거나 정보를 +가져올 수 있으나 몇몇 API는 시스템의 실제 파일의 경로를 기반으로 작동하므로 Electron은 +API가 원할하게 작동할 수 있도록 임시 경로에 해당되는 파일의 압축을 해제합니다. 이 작업은 +약간의 오버헤드를 불러 일으킬 수 있습니다. 위 예외에 해당하는 API 메서드는 다음과 같습니다: @@ -127,24 +135,27 @@ originalFs.readFileSync('/path/to/example.asar'); ### `fs.stat`의 잘못된 스테이터스 정보 -`fs.stat` 로 부터 반환되는 `Stats` 객체와 비슷한 API들은 `asar` 아카이브를 타겟으로 할 경우 예측된 디렉터리 파일 정보를 가집니다. -왜냐하면 아카이브의 디렉터리 경로는 실제 파일시스템에 존재하지 않기 때문입니다. -그러한 이유로 파일 크기와 파일 타입 등을 확인할 때 `Stats` 객체를 신뢰해선 안됩니다. +`fs.stat` 로 부터 반환되는 `Stats` 객체와 비슷한 API들은 `asar` 아카이브를 타겟으로 +할 경우 예측된 디렉터리 파일 정보를 가집니다. 왜냐하면 아카이브의 디렉터리 경로는 실제 +파일 시스템에 존재하지 않기 때문입니다. 그러한 이유로 파일 크기와 +파일 타입 등을 확인할 때 `Stats` 객체를 신뢰해선 안됩니다. ## `asar` 아카이브에 미리 압축 해제된 파일 추가하기 전술한 바와 같이 몇몇 Node API는 호출 시 해당 파일을 임시폴더에 압축을 해제합니다. -이 방법은 성능문제가 발생할 수 있습니다. 그리고 설계상 백신 소프트웨어에서 잘못 진단하여 바이러스로 판단 할 수도 있습니다. +이 방법은 성능문제가 발생할 수 있습니다. 그리고 설계상 백신 소프트웨어에서 잘못 진단하여 +바이러스로 진단 할 수도 있습니다. -이 문제를 해결하려면 `--unpack` 옵션을 활용하여 파일을 압축이 풀려진 상태로 유지해야 합니다. -다음의 예제는 node 네이티브 모듈의 공유 라이브러리를 unpack 상태로 유지합니다: +이 문제를 해결하려면 `--unpack` 옵션을 통해 파일을 압축이 풀려진 상태로 유지해야 합니다. +다음의 예제는 node 네이티브 모듈의 공유 라이브러리를 압축이 풀려진 상태로 유지합니다: ```bash $ asar pack app app.asar --unpack *.node ``` -커맨드를 실행한 후 같은 디렉터리에 `app.asar` 파일 외에 `app.asar.unpacked` 폴더가 같이 생성됩니다. -이 폴더안에 unpack 옵션에서 설정한 파일들이 압축이 풀린 상태로 포함되어 있습니다. -사용자에게 어플리케이션을 배포할 때 반드시 해당 폴더도 같이 배포해야 합니다. +커맨드를 실행한 후 같은 디렉터리에 `app.asar` 파일 외에 `app.asar.unpacked` 폴더가 +같이 생성됩니다. 이 폴더안에 unpack 옵션에서 설정한 파일들이 압축이 풀려진 상태로 +포함되어 있습니다. 사용자에게 어플리케이션을 배포할 때 반드시 해당 폴더도 같이 배포해야 +합니다. [asar]: https://github.com/atom/asar diff --git a/docs-translations/ko-KR/tutorial/debugging-main-process.md b/docs-translations/ko-KR/tutorial/debugging-main-process.md index b03e2542dcd3..32a6bd00f7ae 100644 --- a/docs-translations/ko-KR/tutorial/debugging-main-process.md +++ b/docs-translations/ko-KR/tutorial/debugging-main-process.md @@ -1,7 +1,8 @@ # 메인 프로세스 디버깅하기 -브라우저 창의 개발자 도구는 웹 페이지 같은 랜더러 프로세스의 스크립트만 디버깅이 가능합니다. -대신 Electron은 메인 프로세스의 디버깅을 위해 `--debug` 과 `--debug-brk` 스위치들을 제공합니다. +브라우저 창의 개발자 도구는 웹 페이지 같은 랜더러 프로세스의 스크립트만 디버깅이 +가능합니다. 대신 Electron은 메인 프로세스의 디버깅을 위해 `--debug` 과 `--debug-brk` +스위치들을 제공합니다. ## 커맨드 라인 스위치(command line switches) @@ -9,7 +10,8 @@ ### `--debug=[port]` -이 스위치를 사용하면 Electron은 지정한 `port`에 V8 디버거 프로토콜을 리스닝합니다. 기본 `port`는 `5858` 입니다. +이 스위치를 사용하면 Electron은 지정한 `port`에 V8 디버거 프로토콜을 리스닝합니다. +기본 `port`는 `5858` 입니다. ### `--debug-brk=[port]` @@ -17,9 +19,9 @@ ## node-inspector로 디버깅 하기 -__참고:__ Electron은 node v0.11.13 버전을 사용합니다. -그리고 현재 node-inspector 유틸리티와 호환성 문제가 있습니다. -추가로 node-inspector 콘솔 내에서 메인 프로세스의 `process` 객체를 탐색할 경우 크래시가 발생할 수 있습니다. +__참고:__ Electron은 node v0.11.13 버전을 사용합니다. 그리고 현재 node-inspector +유틸리티와 호환성 문제가 있습니다. 추가로 node-inspector 콘솔 내에서 메인 프로세스의 +`process` 객체를 탐색할 경우 크래시가 발생할 수 있습니다. ### 1. [node-inspector][node-inspector] 서버 시작 @@ -43,6 +45,7 @@ $ electron --debug-brk=5858 your/app ### 3. 디버그 UI 로드 -Chrome 브라우저에서 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858 주소에 접속합니다. (기본포트 또는 지정한 포트로 접속) +Chrome 브라우저에서 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858 주소에 +접속합니다. (기본포트 또는 지정한 포트로 접속) [node-inspector]: https://github.com/node-inspector/node-inspector diff --git a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md index 433a6d5fa5a9..1dc5f6613704 100644 --- a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md +++ b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md @@ -1,15 +1,18 @@ # 데스크톱 환경 통합 -어플리케이션 배포의 대상이 되는 서로 다른 운영체제 시스템의 환경에 맞춰 어플리케이션의 기능을 통합할 수 있습니다. -예를 들어 Windows에선 태스크바의 JumpList에 바로가기를 추가할 수 있고 Mac(OS X)에선 dock 메뉴에 커스텀 메뉴를 추가할 수 있습니다. +어플리케이션 배포의 대상이 되는 서로 다른 운영체제 시스템의 환경에 맞춰 어플리케이션의 +기능을 통합할 수 있습니다. 예를 들어 Windows에선 태스크바의 JumpList에 바로가기를 +추가할 수 있고 Mac(OS X)에선 dock 메뉴에 커스텀 메뉴를 추가할 수 있습니다. -이 문서는 Electron API를 이용하여 각 운영체제 시스템의 기능을 활용하는 방법을 설명합니다. +이 문서는 Electron API를 이용하여 각 운영체제 시스템의 기능을 활용하는 방법을 +설명합니다. ## 데스크톱 알림 (Windows, Linux, OS X) -Windows, Linux, OS X 운영체제 모두 기본적으로 어플리케이션에서 유저에게 알림 보낼 수 있는 방법을 제공합니다. -Electron은 HTML5 Notification API](https://notifications.spec.whatwg.org/)를 통해 개발자가 -편리하게 데스크톱 알림을 사용할 수 있는 기능을 제공합니다. 데스크톱 알림은 운영체제의 네이티브 알림 API를 사용하여 표시합니다. +Windows, Linux, OS X 운영체제 모두 기본적으로 어플리케이션에서 유저에게 알림을 보내는 +방법을 제공합니다. Electron은 [HTML5 Notification API](https://notifications.spec.whatwg.org/)를 +통해 개발자가 편리하게 데스크톱 알림을 사용할 수 있는 기능을 제공합니다. 데스크톱 알림은 +운영체제의 네이티브 알림 API를 사용하여 표시합니다. ```javascript var myNotification = new Notification('Title', { @@ -21,17 +24,21 @@ myNotification.onclick = function () { } ``` -위 코드를 통해 생성한 데스크톱 알림은 각 운영체제 모두 비슷한 사용자 경험을 제공합니다. 하지만 몇 가지 다른 점들이 있습니다. +위 코드를 통해 생성한 데스크톱 알림은 각 운영체제 모두 비슷한 사용자 경험을 제공합니다. +하지만 몇 가지 다른 점들이 있습니다. ### Windows * Windows 10에선 "아무 문제 없이 잘" 작동합니다. -* Windows 8.1과 8에선 [Application User Model ID][app-user-model-id]로 바로가기를 만들어 놔야 합니다. -이 바로가기는 반드시 시작 화면에 설치되어 있어야 합니다. 참고로 반드시 시작 화면에 고정 할 필요는 없습니다. -* Windows 7과 그 이하 버전은 데스크톱 알림을 지원하지 않습니다. 혹시 "풍선 팝업 알림" 기능을 찾는다면 [Tray API](tray-balloon)를 사용하세요. +* Windows 8.1과 8에선 [Application User Model ID][app-user-model-id]로 바로가기를 + 만들어 놔야 합니다. 이 바로가기는 반드시 시작 화면에 설치되어 있어야 합니다. 참고로 + 반드시 시작 화면에 고정 할 필요는 없습니다. +* Windows 7과 그 이하 버전은 데스크톱 알림을 지원하지 않습니다. + 혹시 "풍선 팝업 알림" 기능을 찾는다면 [Tray API](tray-balloon)를 사용하세요. -이미지를 데스크톱 알림에 사용하려면 알림 옵션의 `icon` 속성에 로컬 이미지 파일(`png` 권장)을 지정하면 됩니다. -데스크톱 알림은 잘못된 경로를 지정하거나 `http/https` 기반의 URL을 지정해도 이미지가 보이지 않을 뿐 정상 작동합니다. +이미지를 데스크톱 알림에 사용하려면 알림 옵션의 `icon` 속성에 로컬 이미지 파일 +(`png` 권장)을 지정하면 됩니다. 데스크톱 알림은 잘못된 경로를 지정하거나 `http/https` +기반의 URL을 지정해도 이미지가 보이지 않을 뿐 정상 작동합니다. ```javascript new Notification('Title', { @@ -40,12 +47,14 @@ new Notification('Title', { }); ``` -또한 `body`의 최대 길이는 250자 입니다. Windows 개발팀에선 알림 문자열을 200자 이하로 유지하는 것을 권장합니다. +또한 `body`의 최대 길이는 250자 입니다. Windows 개발팀에선 알림 문자열을 200자 이하로 +유지하는 것을 권장합니다. ### Linux 데스크톱 알림의 구현으로 `libnotify`를 사용합니다. 따라서 [Desktop Notifications Specification][notification-spec]을 -따르는 모든 데스크탑 환경에서 데스크톱 알림 기능을 사용할 수 있습니다. Cinnamon, Enlightenment, Unity, GNOME, KDE등을 지원합니다. +따르는 모든 데스크탑 환경에서 데스크톱 알림 기능을 사용할 수 있습니다. Cinnamon, +Enlightenment, Unity, GNOME, KDE등을 지원합니다. ### OS X @@ -53,11 +62,13 @@ OS X에서의 데스크톱 알림은 아주 직관적입니다. 하지만 데스 [Apple's Human Interface guidelines regarding notifications](https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/NotificationCenter.html) 가이드를 고려해야 합니다. -참고로 데스크롭 알림의 최대 길이는 256 바이트 입니다. 길이가 초과할 경우 초과한 글자가 잘립니다. +참고로 데스크롭 알림의 최대 길이는 256 바이트 입니다. 길이가 초과할 경우 초과한 글자가 +잘립니다. ## 최근 사용한 문서 (Windows & OS X) -알다 싶이 Windows와 OS X는 JumpList 또는 dock 메뉴를 통해 최근 문서 리스트에 쉽게 접근할 수 있습니다. +알다 싶이 Windows와 OS X는 JumpList 또는 dock 메뉴를 통해 최근 문서 리스트에 쉽게 +접근할 수 있습니다. __JumpList:__ @@ -67,13 +78,15 @@ __어플리케이션 dock menu:__ -파일을 최근 문서에 추가하려면 [app.addRecentDocument][addrecentdocument] API를 사용할 수 있습니다: +파일을 최근 문서에 추가하려면 [app.addRecentDocument][addrecentdocument] API를 +사용할 수 있습니다: ```javascript app.addRecentDocument('/Users/USERNAME/Desktop/work.type'); ``` -그리고 [app.clearRecentDocuments][clearrecentdocuments] API로 최근 문서 리스트를 비울 수 있습니다: +그리고 [app.clearRecentDocuments][clearrecentdocuments] API로 최근 문서 리스트를 +비울 수 있습니다: ```javascript app.clearRecentDocuments(); @@ -81,11 +94,13 @@ app.clearRecentDocuments(); ### Windows에서 주의할 점 -이 기능을 Windows에서 사용할 땐 운영체제 시스템에 어플리케이션에서 사용하는 파일 확장자가 등록되어 있어야 합니다. -그렇지 않은 경우 파일을 JumpList에 추가해도 추가되지 않습니다. -어플리케이션 등록에 관련된 API의 모든 내용은 [Application Registration][app-registration]에서 찾아볼 수 있습니다. +이 기능을 Windows에서 사용할 땐 운영체제 시스템에 어플리케이션에서 사용하는 파일 +확장자가 등록되어 있어야 합니다. 그렇지 않은 경우 파일을 JumpList에 추가해도 추가되지 +않습니다. 어플리케이션 등록에 관련된 API의 모든 내용은 [Application Registration][app-registration]에서 +찾아볼 수 있습니다. -유저가 JumpList에서 파일을 클릭할 경우 클릭된 파일의 경로가 커맨드 라인 인자로 추가되어 새로운 인스턴스의 어플리케이션이 실행됩니다. +유저가 JumpList에서 파일을 클릭할 경우 클릭된 파일의 경로가 커맨드 라인 인자로 추가되어 +새로운 인스턴스의 어플리케이션이 실행됩니다. ### OS X에서 주의할 점 @@ -100,7 +115,8 @@ __Terminal.app의 dock menu:__ -커스텀 dock menu를 설정하려면 `app.dock.setMenu` API를 사용하면 됩니다. OS X에서만 사용 가능합니다: +커스텀 dock menu를 설정하려면 `app.dock.setMenu` API를 사용하면 됩니다. +OS X에서만 사용 가능합니다: ```javascript const electron = require('electron'); @@ -123,26 +139,30 @@ app.dock.setMenu(dockMenu); Windows에선 JumpList의 `Tasks` 카테고리에 원하는 작업을 설정할 수 있습니다. MSDN에선 해당 기능을 다음과 같이 설명하고 있습니다: -> 어플리케이션 작업은 프로그램의 기능 그리고 주요사양 두가지를 기반으로 유저의 행동을 예측하여 정의합니다. -> 실행할 필요가 없는 어플리케이션 작업은 작동하지 않을 때 반드시 context-free를 유지해야 합니다. -> 작업은 일반 사용자가 프로그램을 실행하거나 이메일 프로그램으로 이메일을 작성하거나 달력을 불러오고 -> 워드 프로세서로 새 문서를 작성, 특정 모드, 부속 명령으로 프로그램을 실행하는 등의 -> 통계적, 일반적으로 가장 많이 사용되는 작업인지를 고려해야 합니다. -> 어플리케이션 작업은 일반 유저가 필요로 하지 않는 고급 기능을 조잡하게 채우거나 등록과 같은 일회성의 작업을 포함해선 안됩니다. -> 작업에 특별 이벤트 또는 업그레이드 등의 홍보성 작업을 추가하면 안됩니다. +> 어플리케이션 작업은 프로그램의 기능 그리고 주요사양 두가지를 기반으로 유저의 행동을 +> 예측하여 정의합니다. 실행할 필요가 없는 어플리케이션 작업은 작동하지 않을 때 반드시 +> context-free를 유지해야 합니다. 작업은 일반 사용자가 프로그램을 실행하거나 이메일 +> 프로그램으로 이메일을 작성하거나 달력을 불러오고, 워드 프로세서로 새 문서를 작성, +> 특정 모드, 부속 명령으로 프로그램을 실행하는 등의 통계적, 일반적으로 가장 많이 +> 사용되는 작업인지를 고려해야 합니다. 어플리케이션 작업은 일반 유저가 필요로 하지 +> 않는 고급 기능을 조잡하게 채우거나 등록과 같은 일회성의 작업을 포함해선 안됩니다. +> 또한 작업에 특별 이벤트 또는 업그레이드 등의 홍보성 작업을 추가하면 안됩니다. > > 작업 리스트는 가능한 한 정적으로 유지되는 것을 적극 권장합니다. > 이것은 동일한 상태 또는 응용 프로그램의 상태에 관계없이 유지되어야 합니다. -> 작업 목록은 동적으로 변경할 수 있지만 몇몇 유저는 예상하지 못한 작업 목록 변경에 혼동할 수 있다는 점을 고려해야 합니다. +> 작업 목록은 동적으로 변경할 수 있지만 몇몇 유저는 예상하지 못한 작업 목록 변경에 +> 혼란을 일으킬 수 있다는 점을 고려해야 합니다. __Internet Explorer의 작업:__ ![IE](http://i.msdn.microsoft.com/dynimg/IC420539.png) -OS X의 dock menu(진짜 메뉴)와는 달리 Windows의 사용자 작업은 어플리케이션 바로 가기처럼 작동합니다. -유저가 작업을 클릭할 때 설정한 인자와 함께 새로운 어플리케이션이 실행됩니다. +OS X의 dock menu(진짜 메뉴)와는 달리 Windows의 사용자 작업은 어플리케이션 바로 +가기처럼 작동합니다. 유저가 작업을 클릭할 때 설정한 인자와 함께 새로운 어플리케이션이 +실행됩니다. -사용자 작업을 설정하려면 [app.setUserTasks][setusertaskstasks] 메서드를 통해 구현할 수 있습니다: +사용자 작업을 설정하려면 [app.setUserTasks][setusertaskstasks] 메서드를 통해 구현할 +수 있습니다: ```javascript app.setUserTasks([ @@ -157,34 +177,39 @@ app.setUserTasks([ ]); ``` -작업 리스트를 비우려면 간단히 `app.setUserTasks` 메서드의 첫번째 인자에 빈 배열을 넣어 호출하면 됩니다: +작업 리스트를 비우려면 간단히 `app.setUserTasks` 메서드의 첫번째 인자에 빈 배열을 넣어 +호출하면 됩니다: ```javascript app.setUserTasks([]); ``` -사용자 작업 리스트는 어플리케이션이 삭제되지 않는 한 종료되어도 태스크바에 보존됩니다. 이러한 이유로 반드시 프로그램 경로와 아이콘 경로를 지정해야 합니다. +사용자 작업 리스트는 어플리케이션이 삭제되지 않는 한 종료되어도 태스크바에 보존됩니다. +이러한 이유로 반드시 프로그램 경로와 아이콘 경로를 지정해야 합니다. -## 섬네일 툴바 +## 미리보기 툴바 -Windows에선 작업 표시줄의 어플리케이션 선택시 나오는 미리보기에 특정한 섬네일 툴바를 추가할 수 있습니다. -이 기능은 유저가 윈도우를 활성화 하지 않고 특정한 커맨드를 실행시킬 수 있도록 할 수 있습니다. +Windows에선 작업 표시줄의 어플리케이션 선택시 나오는 미리보기에 특정한 미리보기 툴바를 +추가할 수 있습니다. 이 기능은 유저가 윈도우를 활성화 하지 않고 특정한 커맨드를 실행시킬 +수 있도록 할 수 있습니다. MSDN의 설명에 의하면: -> 이 툴바는 표준 툴바의 공통 컨트롤과 비슷한 역할을 합니다. 버튼은 최대 7개 까지 만들 수 있습니다. -> 각 버튼의 구조엔 ID, 이미지, 툴팁, 상태등이 정의되어있습니다. 태스크바에 구조가 전달되면 어플리케이션이 -> 상태에 따라 버튼을 숨기거나, 활성화하거나, 비활성화 할 수 있습니다. +> 이 툴바는 표준 툴바의 공통 컨트롤과 비슷한 역할을 합니다. 버튼은 최대 7개 까지 +> 만들 수 있습니다. 각 버튼의 구조엔 ID, 이미지, 툴팁, 상태 등이 정의되어있습니다. +> 작업표시줄에 구조가 전달되면 어플리케이션이 상태에 따라 버튼을 숨기거나, 활성화하거나, +> 비활성화 할 수 있습니다. > -> 예를 들어, 윈도우 미디어 플레이어는(WMP) 기본적으로 -> 미디어 플레이어가 공통적으로 사용하는 재생, 일시정지, 음소거, 정지등의 컨트롤을 포함하고 있습니다. +> 예를 들어, 윈도우 미디어 플레이어는(WMP) 미디어 플레이어가 공통적으로 사용하는 +> 재생, 일시정지, 음소거, 정지등의 컨트롤을 포함하고 있습니다. -__Windows Media Player의 섬네일 툴바:__ +__Windows Media Player의 미리보기 툴바:__ ![player](https://i-msdn.sec.s-msft.com/dynimg/IC420540.png) -[BrowserWindow.setThumbarButtons][setthumbarbuttons] API를 통해 어플리케이션에 섬네일 툴바를 설정할 수 있습니다: +[BrowserWindow.setThumbarButtons][setthumbarbuttons] API를 통해 어플리케이션에 +미리보기 툴바를 설정할 수 있습니다: ```javascript const BrowserWindow = require('electron').BrowserWindow; @@ -209,7 +234,8 @@ win.setThumbarButtons([ ]); ``` -섬네일 툴바를 비우려면 간단히 `BrowserWindow.setThumbarButtons` API에 빈 배열을 전달하면 됩니다: +미리보기 툴바를 비우려면 간단히 `BrowserWindow.setThumbarButtons` API에 빈 배열을 +전달하면 됩니다: ```javascript win.setThumbarButtons([]); @@ -217,7 +243,8 @@ win.setThumbarButtons([]); ## Unity 런처 숏컷 기능 (Linux) -Unity 환경에선 `.desktop` 파일을 수정함으로써 런처에 새로운 커스텀 엔트리를 추가할 수 있습니다. [Adding Shortcuts to a Launcher][unity-launcher] 가이드를 참고하세요. +Unity 환경에선 `.desktop` 파일을 수정함으로써 런처에 새로운 커스텀 엔트리를 추가할 수 +있습니다. [Adding Shortcuts to a Launcher][unity-launcher] 가이드를 참고하세요. __Audacious의 런처 숏컷:__ @@ -226,7 +253,8 @@ __Audacious의 런처 숏컷:__ ## Taskbar progress 기능 (Windows & Unity) Windows에선 태스크바의 어플리케이션 버튼에 progress bar를 추가할 수 있습니다. -이 기능은 사용자가 어플리케이션의 창을 열지 않고도 어플리케이션의 작업의 상태 정보를 시각적으로 보여줄 수 있도록 해줍니다. +이 기능은 사용자가 어플리케이션의 창을 열지 않고도 어플리케이션의 작업의 상태 정보를 +시각적으로 보여줄 수 있도록 해줍니다. 또한 Unity DE도 런처에 progress bar를 부착할 수 있습니다. @@ -238,7 +266,8 @@ __Unity 런처의 progress bar:__ ![Unity Launcher](https://cloud.githubusercontent.com/assets/639601/5081747/4a0a589e-6f0f-11e4-803f-91594716a546.png) -이 기능은 [BrowserWindow.setProgressBar][setprogressbar] API를 사용하여 구현할 수 있습니다: +이 기능은 [BrowserWindow.setProgressBar][setprogressbar] API를 사용하여 구현할 수 +있습니다: ```javascript var window = new BrowserWindow({...}); @@ -247,14 +276,17 @@ window.setProgressBar(0.5); ## 대표 파일 제시 (OS X) -OS X는 창에서 대표 파일을 설정할 수 있습니다. 타이틀바에서 파일 아이콘이 있고, 사용자가 Command-Click 또는 Control-Click 키를 누를 경우 파일 경로 팝업이 보여집니다. -또한 창의 상태도 지정할 수 있습니다. 쉽게 말해 로드된 문서의 수정여부를 타이틀바 파일 아이콘에 표시할 수 있습니다. +OS X는 창에서 대표 파일을 설정할 수 있습니다. 타이틀바에서 파일 아이콘이 있고, 사용자가 +Command-Click 또는 Control-Click 키를 누를 경우 파일 경로 팝업이 보여집니다. 또한 +창의 상태도 지정할 수 있습니다. 다시 말해 로드된 문서의 수정 여부를 제목의 파일 +아이콘에 표시할 수 있습니다. __대표 파일 팝업 메뉴:__ -대표 파일 관련 API는 [BrowserWindow.setRepresentedFilename][setrepresentedfilename] 과 [BrowserWindow.setDocumentEdited][setdocumentedited]를 사용할 수 있습니다: +대표 파일 관련 API는 [BrowserWindow.setRepresentedFilename][setrepresentedfilename] 과 +[BrowserWindow.setDocumentEdited][setdocumentedited]를 사용할 수 있습니다: ```javascript var window = new BrowserWindow({...}); diff --git a/docs-translations/ko-KR/tutorial/devtools-extension.md b/docs-translations/ko-KR/tutorial/devtools-extension.md index 05ec3893ead0..655c6ed7d5c2 100644 --- a/docs-translations/ko-KR/tutorial/devtools-extension.md +++ b/docs-translations/ko-KR/tutorial/devtools-extension.md @@ -1,13 +1,17 @@ # 개발자 도구 확장 기능 -어플리케이션의 디버깅을 쉽게 하기 위해 Electron은 기본적으로 [Chrome DevTools Extension][devtools-extension]을 지원합니다. +어플리케이션의 디버깅을 쉽게 하기 위해 Electron은 기본적으로 +[Chrome DevTools Extension][devtools-extension]을 지원합니다. -개발자 도구 확장 기능은 간단하게 사용할 확장 기능 플러그인의 소스 코드를 다운로드한 후 `BrowserWindow.addDevToolsExtension` API를 이용하여 -어플리케이션 내에 로드할 수 있습니다. 한가지 주의할 점은 확장 기능 사용시 창이 생성될 때 마다 일일이 해당 API를 호출할 필요는 없습니다. +개발자 도구 확장 기능은 간단하게 사용할 확장 기능 플러그인의 소스 코드를 다운로드한 후 +`BrowserWindow.addDevToolsExtension` API를 통해 어플리케이션 내에 로드할 수 있습니다. +한가지 주의할 점은 확장 기능 사용시 창이 생성될 때 마다 일일이 해당 API를 호출할 필요는 +없습니다. -** 주의: 현재 React DevTools은 작동하지 않습니다. https://github.com/atom/electron/issues/915 이슈를 참고하세요! ** +**주의: 현재 React DevTools은 작동하지 않습니다. https://github.com/atom/electron/issues/915 이슈를 참고하세요!** -다음 예제는 [React DevTools Extension](https://github.com/facebook/react-devtools)을 사용합니다. +다음 예제는 [React DevTools Extension](https://github.com/facebook/react-devtools)을 +사용합니다. 먼저 소스코드를 다운로드 받습니다: @@ -16,8 +20,8 @@ $ cd /some-directory $ git clone --recursive https://github.com/facebook/react-devtools.git ``` -[`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md) -를 통해 확장 기능을 개발하는 방법을 알아볼 수 있습니다. +[`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md)를 +통해 확장 기능을 개발하는 방법을 알아볼 수 있습니다. 그리고 개발자 도구에서 다음 코드를 입력하면 확장 기능을 로드할 수 있습니다: @@ -26,7 +30,8 @@ const BrowserWindow = require('electron').remote.BrowserWindow; BrowserWindow.addDevToolsExtension('/some-directory/react-devtools/shells/chrome'); ``` -확장 기능을 언로드 하고 콘솔을 다시 열 때 해당 확장 기능이 로드되지 않도록 하려면 `BrowserWindow.removeDevToolsExtension` API를 사용하면 됩니다: +확장 기능을 언로드 하고 콘솔을 다시 열 때 해당 확장 기능이 로드되지 않도록 하려면 +`BrowserWindow.removeDevToolsExtension` API를 사용하면 됩니다: ```javascript BrowserWindow.removeDevToolsExtension('React Developer Tools'); @@ -34,20 +39,25 @@ BrowserWindow.removeDevToolsExtension('React Developer Tools'); ## 개발자 도구 확장 기능의 구성 형식 -모든 개발자 도구 확장은 완벽히 Chrome 브라우저를 위해 작성되었기 때문에 Electron에서도 로드할 수 있습니다. -하지만 반드시 확장 기능은 소스 코드 디렉터리(폴더) 형태여야 합니다. 그래서 `crx` 등의 포맷으로 패키징된 확장 기능의 경우 -사용자가 직접 해당 패키지의 압축을 풀어서 로드하지 않는 이상 Electron에서 해당 확장 기능의 압축을 풀 방법이 없습니다. +모든 개발자 도구 확장은 완벽히 Chrome 브라우저를 위해 작성되었기 때문에 Electron에서도 +로드할 수 있습니다. 하지만 반드시 확장 기능은 소스 코드 디렉터리(폴더) 형태여야 합니다. +그래서 `crx` 등의 포맷으로 패키징된 확장 기능의 경우 사용자가 직접 해당 패키지의 압축을 +풀어서 로드하지 않는 이상 Electron에서 해당 확장 기능의 압축을 풀 방법이 없습니다. ## 백그라운드 페이지 -현재 Electron은 Chrome에서 지원하는 백그라운드 페이지(background pages)를 지원하지 않습니다. -몇몇 확장 기능은 이 기능에 의존하는 경우가 있는데, 이 때 해당 확장 기능은 Electron에서 작동하지 않을 수 있습니다. +현재 Electron은 Chrome에서 지원하는 백그라운드 페이지(background pages)를 지원하지 +않습니다. 몇몇 확장 기능은 이 기능에 의존하는 경우가 있는데, 이 때 해당 확장 기능은 +Electron에서 작동하지 않을 수 있습니다. ## `chrome.*` API -몇몇 Chrome 확장 기능은 특정 기능을 사용하기 위해 `chrome.*` API를 사용하는데, 이 API들을 구현하기 위해 노력했지만 안타깝게도 아직 모든 API가 구현되지는 않았습니다. +몇몇 Chrome 확장 기능은 특정 기능을 사용하기 위해 `chrome.*` API를 사용하는데, 이 +API들을 구현하기 위해 노력했지만 안타깝게도 아직 모든 API가 구현되지는 않았습니다. -아직 모든 API가 구현되지 않았기 때문에 확장 기능에서 `chrome.devtools.*` 대신 `chrome.*` API를 사용할 경우 확장 기능이 제대로 작동하지 않을 수 있음을 감안해야 합니다. -만약 문제가 발생할 경우 Electron의 GitHub 저장소에 관련 이슈를 올리면 해당 API를 추가하는데 많은 도움이 됩니다. +아직 모든 API가 구현되지 않았기 때문에 확장 기능에서 `chrome.devtools.*` 대신 +`chrome.*` API를 사용할 경우 확장 기능이 제대로 작동하지 않을 수 있음을 감안해야 합니다. +만약 문제가 발생할 경우 Electron의 GitHub 저장소에 관련 이슈를 올리면 해당 API를 +추가하는데 많은 도움이 됩니다. [devtools-extension]: https://developer.chrome.com/extensions/devtools diff --git a/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md b/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md index 3006808797f7..d0322aa90af4 100644 --- a/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md +++ b/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md @@ -1,24 +1,26 @@ # Mac 앱 스토어 어플리케이션 제출 가이드 -Electron은 v0.34.0 버전부터 앱 패키지를 Mac App Store(MAS)에 제출할 수 있게 되었습니다. -이 가이드는 어플리케이션을 앱 스토어에 등록하는 방법과 빌드의 한계에 대한 설명을 제공합니다. +Electron은 v0.34.0 버전부터 앱 패키지를 Mac App Store(MAS)에 제출할 수 있게 +되었습니다. 이 가이드는 어플리케이션을 앱 스토어에 등록하는 방법과 빌드의 한계에 대한 +설명을 제공합니다. ## 앱 스토어에 어플리케이션을 등록하는 방법 다음 몇 가지 간단한 절차에 따라 앱 스토어에 어플리케이션을 등록하는 방법을 알아봅니다. -한가지, 이 절차는 제출한 앱이 Apple로부터 승인된다는 것을 확신하지 않습니다. -따라서 여전히 Apple의 [Submitting Your App][submitting-your-app] 가이드를 숙지하고 있어야 하며 -앱 스토어 제출 요구 사항을 확실히 인지하고 있어야합니다. +한가지, 이 절차는 제출한 앱이 Apple로부터 승인된다는 것을 확신하지 않습니다. 따라서 +여전히 Apple의 [Submitting Your App][submitting-your-app] 가이드를 숙지하고 있어야 +하며 앱 스토어 제출 요구 사항을 확실히 인지하고 있어야합니다. ### 인증서 취득 -앱 스토어에 어플리케이션을 제출하려면, 먼저 Apple로부터 인증서를 취득해야 합니다. -취득 방법은 웹에서 찾아볼 수 있는 [가이드][nwjs-guide]를 참고하면 됩니다. +앱 스토어에 어플리케이션을 제출하려면, 먼저 Apple로부터 인증서를 취득해야 합니다. 취득 +방법은 웹에서 찾아볼 수 있는 [가이드][nwjs-guide]를 참고하면 됩니다. ### 앱에 서명하기 -Apple로부터 인증서를 취득했다면, [어플리케이션 배포](application-distribution.md) 문서에 따라 어플리케이션을 패키징한 후 어플리케이션에 서명 합니다. -이 절차는 기본적으로 다른 프로그램과 같습니다. 하지만 키는 Electron 종속성 파일에 각각 따로 서명 해야 합니다. +Apple로부터 인증서를 취득했다면, [어플리케이션 배포](application-distribution.md) +문서에 따라 어플리케이션을 패키징한 후 어플리케이션에 서명 합니다. 이 절차는 기본적으로 +다른 프로그램과 같습니다. 하지만 키는 Electron 종속성 파일에 각각 따로 서명 해야 합니다. 첫번째, 다음 두 자격(plist) 파일을 준비합니다. @@ -77,18 +79,20 @@ codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH" ``` -만약 OS X의 샌드박스 개념에 대해 처음 접한다면 Apple의 [Enabling App Sandbox][enable-app-sandbox] 문서를 -참고하여 기본적인 개념을 이해해야 합니다. 그리고 자격(plist) 파일에 어플리케이션에서 요구하는 권한의 키를 추가합니다. +만약 OS X의 샌드박스 개념에 대해 처음 접한다면 Apple의 [Enabling App Sandbox][enable-app-sandbox] +문서를 참고하여 기본적인 개념을 이해해야 합니다. 그리고 자격(plist) 파일에 +어플리케이션에서 요구하는 권한의 키를 추가합니다. ### 어플리케이션을 업로드하고 심사용 앱으로 제출 -어플리케이션 서명을 완료한 후 iTunes Connect에 업로드하기 위해 Application Loader를 사용할 수 있습니다. -참고로 업로드하기 전에 [레코드][create-record]를 만들었는지 확인해야 합니다. -그리고 [심사를 위해 앱을 제출][submit-for-review]할 수 있습니다. +어플리케이션 서명을 완료한 후 iTunes Connect에 업로드하기 위해 Application Loader를 +사용할 수 있습니다. 참고로 업로드하기 전에 [레코드][create-record]를 만들었는지 +확인해야 합니다. 그리고 [심사를 위해 앱을 제출][submit-for-review]할 수 있습니다. ## MAS 빌드의 한계 -모든 어플리케이션 샌드박스에 대한 요구 사항을 충족시키기 위해, 다음 모듈들은 MAS 빌드에서 비활성화됩니다: +모든 어플리케이션 샌드박스에 대한 요구 사항을 충족시키기 위해, 다음 모듈들은 MAS +빌드에서 비활성화됩니다: * `crash-reporter` * `auto-updater` @@ -99,8 +103,9 @@ productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RES * 특정 접근성 기능이 작동하지 않을 수 있습니다. * 어플리케이션이 DNS의 변경을 감지하지 못할 수 있습니다. -또한 어플리케이션 샌드박스 개념으로 인해 어플리케이션에서 접근할 수 있는 리소스는 엄격하게 제한되어 있습니다. -자세한 내용은 [App Sandboxing][app-sandboxing] 문서를 참고하세요. +또한 어플리케이션 샌드박스 개념으로 인해 어플리케이션에서 접근할 수 있는 리소스는 +엄격하게 제한되어 있습니다. 자세한 내용은 [App Sandboxing][app-sandboxing] 문서를 +참고하세요. **역주:** [Mac 앱 배포 가이드 공식 문서](https://developer.apple.com/osx/distribution/kr/) diff --git a/docs-translations/ko-KR/tutorial/online-offline-events.md b/docs-translations/ko-KR/tutorial/online-offline-events.md index 0b989516a6ab..f66e2e2bbb59 100644 --- a/docs-translations/ko-KR/tutorial/online-offline-events.md +++ b/docs-translations/ko-KR/tutorial/online-offline-events.md @@ -1,6 +1,7 @@ # 온라인/오프라인 이벤트 감지 -온라인/오프라인 이벤트는 다음 예제와 같이 랜더러 프로세스에서 표준 HTML5 API를 이용하여 구현할 수 있습니다. +온라인/오프라인 이벤트는 다음 예제와 같이 랜더러 프로세스에서 표준 HTML5 API를 이용하여 +구현할 수 있습니다. _main.js_ @@ -36,10 +37,12 @@ _online-status.html_ ``` -메인 프로세스에서 이 이벤트를 처리할 필요가 있는 경우 이벤트를 메인 프로세스로 보낼 수 있습니다. -메인 프로세스는 `navigator` 객체를 가지고 있지 않기 때문에 이 이벤트를 직접 사용할 수 없습니다. +메인 프로세스에서 이 이벤트를 처리할 필요가 있는 경우 이벤트를 메인 프로세스로 보낼 수 +있습니다. 메인 프로세스는 `navigator` 객체를 가지고 있지 않기 때문에 이 이벤트를 직접 +사용할 수는 없습니다. -대신 다음 예제와 같이 Electron의 inter-process communication(ipc) 유틸리티를 사용하면 이벤트를 메인 프로세스로 전달할 수 있습니다. +대신 다음 예제와 같이 Electron의 inter-process communication(ipc) 유틸리티를 +사용하면 이벤트를 메인 프로세스로 전달할 수 있습니다. _main.js_ diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index dea6a343e6bf..8946f44716f2 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -2,38 +2,46 @@ ## 소개 -Electron은 자바스크립트와 함께 제공된 풍부한 네이티브 API를 사용하여 멋진 데스크탑 어플리케이션을 만들 수 있도록 해주는 프레임워크입니다. -이 프레임워크의 Node.js는 웹 서버 개발이 아닌 데스크탑 어플리케이션 개발에 초점을 맞췄습니다. +Electron은 자바스크립트와 함께 제공된 풍부한 네이티브 API를 사용하여 멋진 데스크탑 +어플리케이션을 만들 수 있도록 해주는 프레임워크입니다. 이 프레임워크의 Node.js는 웹 +서버 개발이 아닌 데스크탑 어플리케이션 개발에 초점을 맞췄습니다. -이 말은 Electron이 GUI 라이브러리의 자바스크립트 바인딩이라는 뜻이 아닙니다. -대신, Electron은 웹 페이지의 GUI를 사용합니다. 쉽게 말해 Electron은 자바스크립트를 사용하여 조작하는 작은 Chromium 브라우저로 볼 수 있습니다. +이 말은 Electron이 GUI 라이브러리의 자바스크립트 바인딩이라는 뜻이 아닙니다. 대신, +Electron은 웹 페이지의 GUI를 사용합니다. 쉽게 말해 Electron은 자바스크립트를 사용하여 +조작하는 작은 Chromium 브라우저로 볼 수 있습니다. ### 메인 프로세스 -Electron은 실행될 때 __메인 프로세스__로 불리는 `package.json`의 `main` 스크립트를 호출합니다. -이 스크립트는 메인 프로세스에서 작동합니다. GUI 컴포넌트를 조작하거나 웹 페이지 창을 생성할 수 있습니다. +Electron은 실행될 때 __메인 프로세스__로 불리는 `package.json`의 `main` 스크립트를 +호출합니다. 이 스크립트는 메인 프로세스에서 작동합니다. GUI 컴포넌트를 조작하거나 웹 +페이지 창을 생성할 수 있습니다. ### 랜더러 프로세스 Electron이 웹페이지를 보여줄 때 Chromium의 multi-processes 구조도 같이 사용됩니다. Electron 프로세스 내에서 작동하는 웹 페이지를 __랜더러 프로세스__ 라고 불립니다. -보통 일반 브라우저의 웹 페이지들은 샌드박스가 적용된 환경에서 작동하며 네이티브 리소스에는 접근할 수 없도록 되어 있습니다. -하지만 Electron은 웹 페이지 내에서 Node.js API를 사용하여 low-level 수준으로 운영체제와 상호작용할 수 있습니다. +보통 일반 브라우저의 웹 페이지들은 샌드박스가 적용된 환경에서 작동하며 네이티브 +리소스에는 접근할 수 없도록 되어 있습니다. 하지만 Electron은 웹 페이지 내에서 Node.js +API를 사용하여 low-level 수준으로 운영체제와 상호작용할 수 있습니다. ### 메인 프로세스와 랜더러 프로세스의 차이점 메인 프로세스는 `BrowserWindow` Class를 사용하여 새로운 창을 만들 수 있습니다. -`BrowserWindow` 인스턴스는 따로 분리된 프로세스에서 랜더링 되며 이 프로세스를 랜더러 프로세스라고 합니다. -`BrowserWindow` 인스턴스가 소멸할 때 그 창의 랜더러 프로세스도 같이 소멸합니다. +`BrowserWindow` 인스턴스는 따로 분리된 프로세스에서 랜더링 되며 이 프로세스를 랜더러 +프로세스라고 합니다. `BrowserWindow` 인스턴스가 소멸할 때 그 창의 랜더러 프로세스도 +같이 소멸합니다. -메인 프로세스는 모든 웹 페이지와 랜더러 프로세스를 관리하며 랜더러 프로세스는 각각의 프로세스에 고립되며 웹 페이지의 작동에만 영향을 끼칩니다. +메인 프로세스는 모든 웹 페이지와 랜더러 프로세스를 관리하며 랜더러 프로세스는 각각의 +프로세스에 고립되며 웹 페이지의 작동에만 영향을 끼칩니다. -웹 페이지 내에선 기본적으로 네이티브 GUI와 관련된 API를 호출할 수 없도록 설계 되어 있습니다. -왜냐하면 웹 페이지 내에서 네이티브 GUI 리소스를 관리하는 것은 보안에 취약하고 리소스를 누수시킬 수 있기 때문입니다. -꼭 웹 페이지 내에서 API를 사용해야 한다면 메인 프로세스에서 그 작업을 처리할 수 있도록 메인 프로세스와 통신을 해야 합니다. +웹 페이지 내에선 기본적으로 네이티브 GUI와 관련된 API를 호출할 수 없도록 설계 되어 +있습니다. 왜냐하면 웹 페이지 내에서 네이티브 GUI 리소스를 관리하는 것은 보안에 취약하고 +리소스를 누수시킬 수 있기 때문입니다. 꼭 웹 페이지 내에서 API를 사용해야 한다면 메인 +프로세스에서 그 작업을 처리할 수 있도록 메인 프로세스와 통신을 해야 합니다. -Electron에는 메인 프로세스와 랜더러 프로세스 사이에 통신을 할 수 있도록 [ipc](../api/ipc-renderer.md) 모듈을 제공하고 있습니다. +Electron에는 메인 프로세스와 랜더러 프로세스 사이에 통신을 할 수 있도록 +[ipc](../api/ipc-renderer.md) 모듈을 제공하고 있습니다. 또는 [remote](../api/remote.md) 모듈을 사용하여 RPC 스타일로 통신할 수도 있습니다. ## 첫번째 Electron 앱 만들기 @@ -47,9 +55,9 @@ your-app/ └── index.html ``` -`package.json`은 node 모듈의 package.json과 같습니다. -그리고 `main` 필드에 스크립트 파일을 지정하면 메인 프로세스의 엔트리 포인트로 사용합니다. -예를 들어 사용할 수 있는 `package.json`은 다음과 같습니다: +`package.json`은 node 모듈의 package.json과 같습니다. 그리고 `main` 필드에 스크립트 +파일을 지정하면 메인 프로세스의 엔트리 포인트로 사용합니다. 예를 들어 사용할 수 있는 +`package.json`은 다음과 같습니다: ```json { @@ -59,9 +67,11 @@ your-app/ } ``` -__알림__: 만약 `main` 필드가 `package.json`에 설정되어 있지 않으면 Electron은 자동으로 같은 디렉터리의 `index.js`를 로드합니다. +__알림__: 만약 `main` 필드가 `package.json`에 설정되어 있지 않으면 Electron은 +자동으로 같은 디렉터리의 `index.js`를 로드합니다. -반드시 `main.js`에서 창을 만들고 시스템 이밴트를 처리해야합니다. 대표적인 예제로 다음과 같이 작성할 수 있습니다: +반드시 `main.js`에서 창을 만들고 시스템 이밴트를 처리해야합니다. 대표적인 예제로 +다음과 같이 작성할 수 있습니다: ```javascript const electron = require('electron'); @@ -126,12 +136,14 @@ app.on('ready', function() { ## 앱 실행하기 -앱을 작성한 후 [어플리케이션 배포](application-distribution.md) 가이드를 따라 앱을 패키징 하고 패키징한 앱을 실행할 수 있습니다. -또한 Electron 실행파일을 다운로드 받아 바로 실행해 볼 수도 있습니다. +앱을 작성한 후 [어플리케이션 배포](application-distribution.md) 가이드를 따라 앱을 +패키징 하고 패키징한 앱을 실행할 수 있습니다. 또한 Electron 실행파일을 다운로드 받아 +바로 실행해 볼 수도 있습니다. ### electron-prebuilt 사용 -`npm`을 통해 `electron-prebuilt` 패키지를 전역에 설치하면 간단한 명령으로 앱을 실행할 수 있습니다. +`npm`을 통해 `electron-prebuilt` 패키지를 전역에 설치하면 간단한 명령으로 앱을 +실행할 수 있습니다. 앱 디렉터리 내에서 다음 명령으로 실행할 수 있습니다: @@ -178,13 +190,17 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/ ### 배포용 실행 파일 만들기 -어플리케이션 작성을 모두 끝냈다면 [어플리케이션 배포](application-distribution.md) 가이드를 통해 제작한 앱을 패키징하고 배포할 수 있습니다. +어플리케이션 작성을 모두 끝냈다면 [어플리케이션 배포](application-distribution.md) +가이드를 통해 제작한 앱을 패키징하고 배포할 수 있습니다. ### 미리 작성된 앱 실행하기 -[`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) 저장소를 클론하면 이 문서에서 작성한 예제 앱을 바로 실행해 볼 수 있습니다. +[`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) +저장소를 클론하면 이 문서에서 작성한 예제 앱을 바로 실행해 볼 수 있습니다. -**참고**: 이 예제를 실행시키려면 [Git](https://git-scm.com)과 [Node.js](https://nodejs.org/en/download/)가 필요합니다. (CLI에서 실행 가능한 [npm](https://npmjs.org)이 있어야 합니다) +**참고**: 이 예제를 실행시키려면 [Git](https://git-scm.com)과 +[Node.js](https://nodejs.org/en/download/)가 필요합니다. (CLI에서 실행 가능한 + [npm](https://npmjs.org)이 있어야 합니다) **역주**: `npm`은 보통 Node.js를 설치하면 자동으로 같이 설치됩니다. @@ -195,4 +211,4 @@ $ git clone https://github.com/atom/electron-quick-start $ cd electron-quick-start # 어플리케이션의 종속성 모듈을 설치한 후 실행합니다 $ npm install && npm start -``` \ No newline at end of file +``` diff --git a/docs-translations/ko-KR/tutorial/supported-platforms.md b/docs-translations/ko-KR/tutorial/supported-platforms.md index 7a35da0c129a..3b3a00d72156 100644 --- a/docs-translations/ko-KR/tutorial/supported-platforms.md +++ b/docs-translations/ko-KR/tutorial/supported-platforms.md @@ -8,18 +8,22 @@ OS X는 64비트 바이너리만 제공됩니다. 그리고 최소 OS X 지원 ### Windows -Windows 7 이후 버전만 지원됩니다. Windows Vista에서도 작동할 수 있지만 아직 모든 작동 테스트가 완료되지 않았습니다. +Windows 7 이후 버전만 지원됩니다. Windows Vista에서도 작동할 수 있지만 아직 모든 작동 +테스트가 완료되지 않았습니다. -윈도우용 바이너리는 `x86`과 `x64` 모두 제공됩니다. 그리고 `ARM` 버전 윈도우는 아직 지원하지 않습니다. (역주: 추후 지원할 가능성이 있습니다) +윈도우용 바이너리는 `x86`과 `x64` 모두 제공됩니다. 그리고 `ARM` 버전 윈도우는 아직 +지원하지 않습니다. (역주: 추후 지원할 가능성이 있습니다) ### Linux Ubuntu 12.04 버전에서 빌드된 `ia32`(`i686`), `x64`(`amd64`) 바이너리가 제공됩니다. -그리고 `arm` 버전 바이너리는 ARM v7 hard-float ABI와 Debian Wheezy용 NEON에 맞춰 제공됩니다. +그리고 `arm` 버전 바이너리는 ARM v7 hard-float ABI와 Debian Wheezy용 NEON에 맞춰 +제공됩니다. -미리 빌드된 바이너리가 배포판에서 작동할 수 있는지 여부는 Electron이 빌드된 플랫폼에서 링크된 라이브러리에 따라 달라집니다. -그래서 현재 Linux 바이너리는 Ubuntu 12.04 버전만 정상적인 작동이 보장됩니다. -하지만 다음 플랫폼들은 미리 빌드된 Electron 바이너리가 정상적으로 작동하는 것을 확인했습니다: +미리 빌드된 바이너리가 배포판에서 작동할 수 있는지 여부는 Electron이 빌드된 플랫폼에서 +링크된 라이브러리에 따라 달라집니다. 그래서 현재 Linux 바이너리는 Ubuntu 12.04 버전만 +정상적인 작동이 보장됩니다. 하지만 다음 플랫폼들은 미리 빌드된 Electron 바이너리가 +정상적으로 작동하는 것을 확인했습니다: * Ubuntu 12.04 이후 버전 * Fedora 21 diff --git a/docs-translations/ko-KR/tutorial/using-native-node-modules.md b/docs-translations/ko-KR/tutorial/using-native-node-modules.md index 45c4811aa1a1..d1c3aa167ad6 100644 --- a/docs-translations/ko-KR/tutorial/using-native-node-modules.md +++ b/docs-translations/ko-KR/tutorial/using-native-node-modules.md @@ -1,17 +1,22 @@ # 네이티브 node 모듈 사용하기 -Electron에선 node.js 네이티브 모듈이 지원됩니다. 하지만 Electron은 공식 node.js의 V8 엔진과는 다른 V8 버전을 사용합니다. -이러한 이유로 네이티브 모듈을 사용하기 위해선 Electron의 V8 버전에 맞춰 네이티브 모듈을 다시 빌드하고 헤더를 변경해야 합니다. +Electron에선 node.js 네이티브 모듈이 지원됩니다. 하지만 Electron은 공식 node.js의 +V8 엔진과는 다른 V8 버전을 사용합니다. 이러한 이유로 네이티브 모듈을 사용하기 위해선 +Electron의 V8 버전에 맞춰 네이티브 모듈을 다시 빌드하고 헤더를 변경해야 합니다. ## 네이티브 node 모듈 호환성 네이티브 모듈은 node.js가 새로운 V8 버전을 사용함으로 인해 작동하지 않을 수 있습니다. -사용하는 네이티브 모듈이 Electron에 맞춰 작동할 수 있도록 하려면 Electron에서 사용하는 node.js의 버전을 확인할 필요가 있습니다. -Electron에서 사용하는 node 버전은 [releases](https://github.com/atom/electron/releases)에서 확인할 수 있으며 -`process.version`을 출력하여 버전을 확인할 수도 있습니다. ([시작하기](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md)의 예제를 참고하세요) +사용하는 네이티브 모듈이 Electron에 맞춰 작동할 수 있도록 하려면 Electron에서 사용하는 +node.js의 버전을 확인할 필요가 있습니다. Electron에서 사용하는 node 버전은 +[releases](https://github.com/atom/electron/releases)에서 확인할 수 있으며 +`process.version`을 출력하여 버전을 확인할 수도 있습니다. +([시작하기](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md)의 +예제를 참고하세요) -혹시 직접 만든 네이티브 모듈이 있다면 [NAN](https://github.com/nodejs/nan/) 모듈을 사용하는 것을 고려해보는 것이 좋습니다. -이 모듈은 다중 버전의 node.js를 지원하기 쉽게 해줍니다. 이를 통해 오래된 모듈을 새 버전의 node.js에 맞게 포팅할 수 있습니다. +혹시 직접 만든 네이티브 모듈이 있다면 [NAN](https://github.com/nodejs/nan/) 모듈을 +사용하는 것을 고려해보는 것이 좋습니다. 이 모듈은 다중 버전의 node.js를 지원하기 쉽게 +만들어 줍니다. 이를 통해 오래된 모듈을 새 버전의 node.js에 맞게 포팅 할 수 있습니다. Electron도 이 모듈을 통해 포팅된 네이티브 모듈을 사용할 수 있습니다. ## 네이티브 모듈을 설치하는 방법 @@ -20,9 +25,11 @@ Electron도 이 모듈을 통해 포팅된 네이티브 모듈을 사용할 수 ### 쉬운 방법 -[`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild) 패키지를 사용하면 빠르고 간단하게 네이티브 모듈을 다시 빌드할 수 있습니다. +[`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild) 패키지를 +사용하면 빠르고 간단하게 네이티브 모듈을 다시 빌드할 수 있습니다. -다음 예제는 `electron-rebuild`를 통해 자동으로 모듈의 헤더를 다운로드하고 네이티브 모듈을 빌드합니다: +다음 예제는 `electron-rebuild`를 통해 자동으로 모듈의 헤더를 다운로드하고 네이티브 +모듈을 빌드합니다: ```sh npm install --save-dev electron-rebuild @@ -49,12 +56,14 @@ HOME=~/.electron-gyp npm install module-name ### `node-gyp`를 이용한 방법 -Node 모듈을 `node-gyp`를 사용하여 Electron을 타겟으로 빌드할 때는 `node-gyp`에 헤더 다운로드 주소와 버전을 알려주어야 합니다: +Node 모듈을 `node-gyp`를 사용하여 Electron을 타겟으로 빌드할 때는 `node-gyp`에 헤더 +다운로드 주소와 버전을 알려주어야 합니다: ```bash $ cd /path-to-module/ $ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=https://atom.io/download/atom-shell ``` -`HOME=~/.electron-gyp`은 변경할 헤더의 위치를 찾습니다. `--target=0.29.1`은 Electron의 버전입니다. -`--dist-url=...`은 헤더를 다운로드 하는 주소입니다. `--arch=x64`는 64비트 시스템을 타겟으로 빌드 한다는 것을 `node-gyp`에게 알려줍니다. +`HOME=~/.electron-gyp`은 변경할 헤더의 위치를 찾습니다. `--target=0.29.1`은 +Electron의 버전입니다. `--dist-url=...`은 헤더를 다운로드 하는 주소입니다. +`--arch=x64`는 64비트 시스템을 타겟으로 빌드 한다는 것을 `node-gyp`에게 알려줍니다. diff --git a/docs-translations/ko-KR/tutorial/using-pepper-flash-plugin.md b/docs-translations/ko-KR/tutorial/using-pepper-flash-plugin.md index cdb6f857cc2e..2f15a3532eea 100644 --- a/docs-translations/ko-KR/tutorial/using-pepper-flash-plugin.md +++ b/docs-translations/ko-KR/tutorial/using-pepper-flash-plugin.md @@ -5,12 +5,14 @@ Pepper 플래시 플러그인을 사용하려면 Pepper 플래시 플러그인 ## 플래시 플러그인 준비하기 -크롬 브라우저의 `chrome://plugins` 페이지에 접속한 후 `세부정보`에서 플래시 플러그인의 위치와 버전을 찾을 수 있습니다. -Electron에서 플래시 플러그인을 지원하기 위해선 이 두 가지를 복사해 와야 합니다. +크롬 브라우저의 `chrome://plugins` 페이지에 접속한 후 `세부정보`에서 플래시 +플러그인의 위치와 버전을 찾을 수 있습니다. Electron에서 플래시 플러그인을 지원하기 +위해선 이 두 가지를 복사해 와야 합니다. ## Electron 스위치 추가 -플러그인을 사용하려면 Electron 커맨드 라인에 `--ppapi-flash-path` 와 `ppapi-flash-version` 플래그를 app의 ready 이벤트가 호출되기 전에 추가해야 합니다. +플러그인을 사용하려면 Electron 커맨드 라인에 `--ppapi-flash-path` 와 +`ppapi-flash-version` 플래그를 app의 ready 이벤트가 호출되기 전에 추가해야 합니다. 그리고 `browser-window`에 `plugins` 스위치도 추가해야합니다. ```javascript 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 ae588348acd2..aba16256cf7f 100644 --- a/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md +++ b/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md @@ -3,17 +3,17 @@ [ChromeDriver - WebDriver for Chrome][chrome-driver]로 부터 인용: > WebDriver는 많은 브라우저에서 웹 앱을 자동적으로 테스트하는 툴입니다. -> 이 툴킷은 웹 페이지를 자동으로 탐색하고 유저 폼을 사용하거나 자바스크립트를 실행하는 등의 작업을 수행할 수 있습니다. -> ChromeDriver는 Chromium의 WebDriver wire 프로토콜 스텐드얼론 서버 구현입니다. -> Chromium 과 WebDriver 팀 멤버에 의해 개발되었습니다. +> 이 툴킷은 웹 페이지를 자동으로 탐색하고 유저 폼을 사용하거나 자바스크립트를 실행하는 +> 등의 작업을 수행할 수 있습니다. ChromeDriver는 Chromium의 WebDriver wire 프로토콜 +> 스텐드얼론 서버 구현입니다. Chromium 과 WebDriver 팀 멤버에 의해 개발되었습니다. -Electron에서 `chromedriver`를 사옹하려면 드라이버에서 Electron을 찾을 수 있도록 해야 하며 -Electron은 Chrome 브라우저와 비슷하다는 점을 기억해야 합니다. +Electron에서 `chromedriver`를 사옹하려면 드라이버에서 Electron을 찾을 수 있도록 해야 +하며 Electron은 Chrome 브라우저와 비슷하다는 점을 기억해야 합니다. ## WebDriverJs 설정하기 -[WebDriverJs](https://code.google.com/p/selenium/wiki/WebDriverJs)는 WebDriver를 사용하여 테스트 할 수 있도록 도와주는 node 패키지입니다. -다음 예제를 참고하세요. +[WebDriverJs](https://code.google.com/p/selenium/wiki/WebDriverJs)는 WebDriver를 +사용하여 테스트 할 수 있도록 도와주는 node 패키지입니다. 다음 예제를 참고하세요. ### 1. 크롬 드라이버 시작 @@ -35,8 +35,9 @@ $ npm install selenium-webdriver ### 3. 크롬 드라이버에 연결 -`selenium-webdriver`를 Electron과 같이 사용하는 방법은 기본적으로 upstream과 같습니다. -한가지 다른점이 있다면 수동으로 크롬 드라이버 연결에 대해 설정하고 Electron 실행파일의 위치를 전달합니다: +`selenium-webdriver`를 Electron과 같이 사용하는 방법은 기본적으로 upstream과 +같습니다. 한가지 다른점이 있다면 수동으로 크롬 드라이버 연결에 대해 설정하고 Electron +실행파일의 위치를 전달합니다: ```javascript const webdriver = require('selenium-webdriver'); @@ -67,7 +68,8 @@ driver.quit(); ## WebdriverIO 설정하기 -[WebdriverIO](http://webdriver.io/)는 웹 드라이버와 함께 테스트를 위해 제공되는 node 패키지입니다. +[WebdriverIO](http://webdriver.io/)는 웹 드라이버와 함께 테스트를 위해 제공되는 +node 패키지입니다. ### 1. 크롬 드라이버 시작 @@ -103,7 +105,7 @@ var options = { }; var client = webdriverio.remote(options); - + client .init() .url('http://google.com') @@ -117,10 +119,11 @@ client ## 작업 환경 -따로 Electron을 다시 빌드하지 않는 경우 간단히 어플리케이션을 Electron의 리소스 디렉터리에 -[배치](application-distribution.md)하여 바로 테스트 할 수 있습니다. +따로 Electron을 다시 빌드하지 않는 경우 간단히 어플리케이션을 Electron의 리소스 +디렉터리에 [배치](application-distribution.md)하여 바로 테스트 할 수 있습니다. -또한, Electron 바이너리의 명령줄 인수에 어플리케이션 폴더를 지정하는 방법으로 실행할 수도 있습니다. -이 방법을 사용하면 어플리케이션 폴더를 Electron의 `resource` 디렉터리로 복사하는 불필요한 과정을 생략할 수 있습니다. +또한, Electron 바이너리의 명령줄 인수에 어플리케이션 폴더를 지정하는 방법으로 실행할 +수도 있습니다. 이 방법을 사용하면 어플리케이션 폴더를 Electron의 `resource` +디렉터리로 복사하는 불필요한 과정을 생략할 수 있습니다. [chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/ From 65c823407dbd792e4227222b83c110422a1fc179 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Thu, 19 Nov 2015 10:04:28 -0800 Subject: [PATCH 588/738] Address feedback --- docs/api/browser-window.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index a78531277e9e..46b7c96ae594 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -68,12 +68,14 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `transparent` Boolean - Makes the window [transparent](frameless-window.md). * `type` String - Specifies the type of the window, which applies additional platform-specific properties. - - On Linux, possible types are `desktop`, `dock`, `toolbar`, `splash`, `notification`. - - On Mac OS X: - - `textured`: Adds metal gradient appearance (NSTexturedBackgroundWindowMask) - - `desktop`: Places the window at the desktop background window level (kCGDesktopWindowLevel - 1). - Note that the window will not receive focus, keyboard or mouse events, but - you can use `globalShortcut` to receive input sparingly. + * On Linux, possible types are `desktop`, `dock`, `toolbar`, `splash`, + `notification`. + * On OS X, possible types are `desktop`, `textured`. The `textured` type adds + metal gradient appearance (NSTexturedBackgroundWindowMask). The `desktop` + type places the window at the desktop background window level + (kCGDesktopWindowLevel - 1). Note that desktop window will not receive focus, + keyboard or mouse events, but you can use `globalShortcut` to receive input + sparingly. * `titleBarStyle` String, OS X - specifies the style of window title bar. This option is supported on OS X 10.10 Yosemite and newer. There are three possible values: From 962134c6126330d1d3b2c5a5362e9fc8e7c2c32f Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 20 Nov 2015 04:46:05 +0900 Subject: [PATCH 589/738] Cleanup docs * Adjust line wrap to 80 * Fix typos * Improve grammar --- docs-translations/ko-KR/api/accelerator.md | 5 +- docs-translations/ko-KR/api/app.md | 123 ++++++---- docs-translations/ko-KR/api/auto-updater.md | 22 +- docs-translations/ko-KR/api/browser-window.md | 213 +++++++++++------- .../ko-KR/api/chrome-command-line-switches.md | 69 +++--- docs-translations/ko-KR/api/clipboard.md | 9 +- .../ko-KR/api/content-tracing.md | 66 +++--- docs-translations/ko-KR/api/crash-reporter.md | 12 +- docs-translations/ko-KR/api/dialog.md | 83 ++++--- docs-translations/ko-KR/api/download-item.md | 23 +- docs-translations/ko-KR/api/file-object.md | 6 +- .../ko-KR/api/frameless-window.md | 68 +++--- .../ko-KR/api/global-shortcut.md | 16 +- docs-translations/ko-KR/api/ipc-main.md | 13 +- docs-translations/ko-KR/api/ipc-renderer.md | 23 +- docs-translations/ko-KR/api/menu-item.md | 24 +- docs-translations/ko-KR/api/menu.md | 77 ++++--- docs-translations/ko-KR/api/native-image.md | 30 ++- docs-translations/ko-KR/api/power-monitor.md | 5 +- .../ko-KR/api/power-save-blocker.md | 34 ++- docs-translations/ko-KR/api/process.md | 15 +- docs-translations/ko-KR/api/protocol.md | 59 +++-- docs-translations/ko-KR/api/remote.md | 80 ++++--- docs-translations/ko-KR/api/screen.md | 8 +- docs-translations/ko-KR/api/session.md | 74 +++--- docs-translations/ko-KR/api/shell.md | 5 +- docs-translations/ko-KR/api/synopsis.md | 34 +-- docs-translations/ko-KR/api/tray.md | 17 +- docs-translations/ko-KR/api/web-contents.md | 119 +++++----- docs-translations/ko-KR/api/web-frame.md | 21 +- docs-translations/ko-KR/api/web-view-tag.md | 101 +++++---- docs-translations/ko-KR/api/window-open.md | 27 ++- .../development/setting-up-symbol-server.md | 2 +- .../ko-KR/tutorial/application-packaging.md | 4 +- .../tutorial/using-selenium-and-webdriver.md | 2 +- 35 files changed, 896 insertions(+), 593 deletions(-) diff --git a/docs-translations/ko-KR/api/accelerator.md b/docs-translations/ko-KR/api/accelerator.md index 9e72543a4cc6..99b549bbb70d 100644 --- a/docs-translations/ko-KR/api/accelerator.md +++ b/docs-translations/ko-KR/api/accelerator.md @@ -10,8 +10,9 @@ Accelerator는 키보드 단축키를 표현하는 문자열입니다, 여러 ## 플랫폼에 관련하여 주의할 점 -Linux와 Windows에서는 `Command`키가 없으므로 작동하지 않습니다. 대신에 `CommandOrControl`을 -사용하면 OS X의 `Command`와 Linux, Windows의 `Control` 모두 지원할 수 있습니다. +Linux와 Windows에서는 `Command`키가 없으므로 작동하지 않습니다. 대신에 +`CommandOrControl`을 사용하면 OS X의 `Command`와 Linux, Windows의 `Control` 모두 +지원할 수 있습니다. `Super`키는 Windows와 Linux 에서는 `윈도우`키를, OS X에서는 `Cmd`키로 맵핑됩니다. diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index 51e88c534ff4..8a6914a80fbc 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -18,9 +18,11 @@ app.on('window-all-closed', function() { ### Event: 'will-finish-launching' 어플리케이션이 기본적인 시작 준비를 마치면 발생하는 이벤트입니다. -Windows, Linux 운영체제에서의 `will-finish-launching` 이벤트는 `ready` 이벤트와 동일합니다. -OS X에서의 이벤트는 `NSApplication`의 `applicationWillFinishLaunching`에 대한 알림으로 표현됩니다. -대개 이곳에서 `open-file`과 `open-url` 이벤트 리스너를 설정하고 crash reporter와 auto updater를 시작합니다. +Windows, Linux 운영체제에서의 `will-finish-launching` 이벤트는 `ready` 이벤트와 +동일합니다. OS X에서의 이벤트는 `NSApplication`의 +`applicationWillFinishLaunching`에 대한 알림으로 표현됩니다. 대개 이곳에서 +`open-file`과 `open-url` 이벤트 리스너를 설정하고 crash reporter와 auto updater를 +시작합니다. 대부분의 경우, 모든 것을 `ready` 이벤트 핸들러로 해결해야 합니다. @@ -35,10 +37,12 @@ Electron이 초기화를 끝냈을 때 발생하는 이벤트입니다. 이 이벤트는 어플리케이션이 완전히 종료되지 않았을 때만 발생합니다. 만약 사용자가 `Cmd + Q`를 입력했거나 개발자가 `app.quit()`를 호출했다면, Electron은 먼저 모든 윈도우 창의 종료를 시도하고 `will-quit` 이벤트를 발생시킵니다. -그리고 `will-quit` 이벤트가 발생했을 땐 `window-all-closed` 이벤트가 발생하지 않습니다. +그리고 `will-quit` 이벤트가 발생했을 땐 `window-all-closed` 이벤트가 발생하지 +않습니다. -**역주:** 이 이벤트는 말 그대로 현재 어플리케이션에서 윈도우 창만 완전히 종료됬을 때 발생하는 이벤트 입니다. - 따라서 어플리케이션을 완전히 종료하려면 이 이벤트에서 `app.quit()`를 호출해 주어야 합니다. +**역주:** 이 이벤트는 말 그대로 현재 어플리케이션에서 윈도우 창만 완전히 종료됬을 때 +발생하는 이벤트 입니다. 따라서 어플리케이션을 완전히 종료하려면 이 이벤트에서 +`app.quit()`를 호출해 주어야 합니다. ### Event: 'before-quit' @@ -59,7 +63,8 @@ Returns: 모든 윈도우 창들이 종료되고 어플리케이션이 종료되기 시작할 때 발생하는 이벤트 입니다. `event.preventDefault()` 호출을 통해 어플리케이션의 종료를 방지할 수 있습니다. -`will-quit` 와 `window-all-closed` 이벤트의 차이점을 확인하려면 `window-all-close` 이벤트의 설명을 참고하세요. +`will-quit` 와 `window-all-closed` 이벤트의 차이점을 확인하려면 `window-all-close` +이벤트의 설명을 참고하세요. ### Event: 'quit' @@ -74,9 +79,11 @@ Returns: 사용자가 어플리케이션을 통해 파일을 열고자 할 때 발생하는 이벤트입니다. -`open-file` 이벤트는 보통 어플리케이션이 열려 있을 때 OS가 파일을 열기 위해 어플리케이션을 재사용할 때 발생합니다. -이 이벤트는 파일을 dock에 떨어트릴 때, 어플리케이션이 실행되기 전에도 발생합니다. -따라서 이 이벤트를 제대로 처리하려면 `open-file` 이벤트 핸들러를 어플리케이션이 시작하기 전에 등록해 놓았는지 확실히 확인해야 합니다. (`ready` 이벤트가 발생하기 전에) +`open-file` 이벤트는 보통 어플리케이션이 열려 있을 때 OS가 파일을 열기 위해 +어플리케이션을 재사용할 때 발생합니다. 이 이벤트는 파일을 dock에 떨어트릴 때, +어플리케이션이 실행되기 전에도 발생합니다. 따라서 이 이벤트를 제대로 처리하려면 +`open-file` 이벤트 핸들러를 어플리케이션이 시작하기 전에 등록해 놓았는지 확실히 +확인해야 합니다. (`ready` 이벤트가 발생하기 전에) 이 이벤트를 처리할 땐 반드시 `event.preventDefault()`를 호출해야 합니다. @@ -148,7 +155,8 @@ Returns: `url`은 클라이언트 인증서를 요청하는 탐색 항목에 해당합니다. 그리고 `callback`은 목록에서 필터링된 항목과 함께 호출될 필요가 있습니다. -이 이벤트에서의 `event.preventDefault()` 호출은 초기 인증 때 저장된 데이터를 사용하는 것을 막습니다. +이 이벤트에서의 `event.preventDefault()` 호출은 초기 인증 때 저장된 데이터를 사용하는 +것을 막습니다. ```javascript app.on('select-certificate', function(event, host, url, list, callback) { @@ -201,10 +209,12 @@ GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입 ### `app.quit()` 모든 윈도우 창 종료를 시도합니다. `before-quit` 이벤트가 먼저 발생합니다. -모든 윈도우 창이 성공적으로 종료되면 `will-quit` 이벤트가 발생하고 기본 동작에 따라 어플리케이션이 종료됩니다. +모든 윈도우 창이 성공적으로 종료되면 `will-quit` 이벤트가 발생하고 기본 동작에 따라 +어플리케이션이 종료됩니다. 이 함수는 모든 `beforeunload`와 `unload` 이벤트 핸들러가 제대로 실행됨을 보장합니다. -`beforeunload` 이벤트 핸들러에서 `false`를 반환했을 때 윈도우 창 종료가 취소 될 수 있습니다. +`beforeunload` 이벤트 핸들러에서 `false`를 반환했을 때 윈도우 창 종료가 취소 될 수 +있습니다. ### `app.exit(exitCode)` @@ -212,7 +222,8 @@ GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입 `exitCode`와 함께 어플리케이션을 즉시 종료합니다. -모든 윈도우 창은 사용자의 동의 여부에 상관없이 즉시 종료되며 `before-quit` 이벤트와 `will-quit` 이벤트가 발생하지 않습니다. +모든 윈도우 창은 사용자의 동의 여부에 상관없이 즉시 종료되며 `before-quit` 이벤트와 +`will-quit` 이벤트가 발생하지 않습니다. ### `app.getAppPath()` @@ -253,39 +264,43 @@ GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입 * `path` String `name`에 대한 특정 디렉터리나 파일의 경로인 `path`를 재정의합니다. -만약 지정한 디렉터리의 경로가 존재하지 않으면 디렉터리가 이 메서드를 통해 새로 생성됩니다. -재정의에 실패했을 땐 `Error`를 반환합니다. +만약 지정한 디렉터리의 경로가 존재하지 않으면 디렉터리가 이 메서드를 통해 새로 +생성됩니다. 재정의에 실패했을 땐 `Error`를 반환합니다. 이 메서드는 `app.getPath`에 정의되어 있는 `name`의 경로만 재정의할 수 있습니다. 기본적으로, 웹 페이지의 쿠키와 캐시는 `userData` 디렉터리에 저장됩니다. -만약 이 위치를 변경하고자 한다면, 반드시 `app` 모듈의 `ready` 이벤트가 발생하기 전에 `userData` 경로를 재정의해야 합니다. +만약 이 위치를 변경하고자 한다면, 반드시 `app` 모듈의 `ready` 이벤트가 발생하기 전에 +`userData` 경로를 재정의해야 합니다. ### `app.getVersion()` 로드된 어플리케이션의 버전을 반환합니다. -만약 `package.json` 파일에서 어플리케이션의 버전을 찾을 수 없는 경우, 현재 번들 또는 실행 파일의 버전을 반환합니다. +만약 `package.json` 파일에서 어플리케이션의 버전을 찾을 수 없는 경우, 현재 번들 또는 +실행 파일의 버전을 반환합니다. ### `app.getName()` `package.json`에서 기술된 현재 어플리케이션의 이름을 반환합니다. -npm 모듈 규칙에 따라 대부분의 경우 `package.json`의 `name` 필드는 소문자 이름을 사용합니다. -하지만 Electron은 `name`대신 `productName` 필드를 주로 사용하기 때문에 반드시 이 필드도 같이 지정해야 합니다. -이 필드는 맨 앞글자가 대문자인 어플리케이션 전체 이름을 지정해야 합니다. +npm 모듈 규칙에 따라 대부분의 경우 `package.json`의 `name` 필드는 소문자 이름을 +사용합니다. 하지만 Electron은 `name`대신 `productName` 필드를 주로 사용하기 때문에 +반드시 이 필드도 같이 지정해야 합니다. 이 필드는 맨 앞글자가 대문자인 어플리케이션 +전체 이름을 지정해야 합니다. ### `app.getLocale()` -현재 어플리케이션의 [로케일](https://ko.wikipedia.org/wiki/%EB%A1%9C%EC%BC%80%EC%9D%BC)을 반환합니다. +현재 어플리케이션의 [로케일](https://ko.wikipedia.org/wiki/%EB%A1%9C%EC%BC%80%EC%9D%BC)을 +반환합니다. ### `app.resolveProxy(url, callback)` * `url` URL * `callback` Function -`url`의 프록시 정보를 해석합니다. -`callback`은 요청이 수행되었을 때 `callback(proxy)` 형태로 호출됩니다. +`url`의 프록시 정보를 해석합니다. `callback`은 요청이 수행되었을 때 +`callback(proxy)` 형태로 호출됩니다. ### `app.addRecentDocument(path)` _OS X_ _Windows_ @@ -293,8 +308,8 @@ npm 모듈 규칙에 따라 대부분의 경우 `package.json`의 `name` 필드 최근 문서 목록에 `path`를 추가합니다. -이 목록은 OS에 의해 관리됩니다. -최근 문서 목록은 Windows의 경우 작업 표시줄에서 찾을 수 있고, OS X의 경우 dock 메뉴에서 찾을 수 있습니다. +이 목록은 OS에 의해 관리됩니다. 최근 문서 목록은 Windows의 경우 작업 표시줄에서 찾을 +수 있고, OS X의 경우 dock 메뉴에서 찾을 수 있습니다. ### `app.clearRecentDocuments()` _OS X_ _Windows_ @@ -317,8 +332,9 @@ Windows에서 사용할 수 있는 JumpList의 [Tasks][tasks] 카테고리에 `t * `iconPath` String - JumpList에 표시될 아이콘의 절대 경로. 아이콘을 포함하고 있는 임의의 리소스 파일을 사용할 수 있습니다. 보통 어플리케이션의 아이콘을 그대로 사용하기 위해 `process.execPath`를 지정합니다. -* `iconIndex` Integer - 아이콘 파일의 인덱스. 만약 아이콘 파일이 두 개 이상의 아이콘을 가지고 있을 경우, - 사용할 아이콘의 인덱스를 이 옵션으로 지정해 주어야 합니다. 단, 아이콘을 하나만 포함하고 있는 경우 0을 지정하면 됩니다. +* `iconIndex` Integer - 아이콘 파일의 인덱스. 만약 아이콘 파일이 두 개 이상의 + 아이콘을 가지고 있을 경우, 사용할 아이콘의 인덱스를 이 옵션으로 지정해 주어야 합니다. + 단, 아이콘을 하나만 포함하고 있는 경우 0을 지정하면 됩니다. ### `app.allowNTLMCredentialsForAllDomains(allow)` @@ -326,33 +342,40 @@ Windows에서 사용할 수 있는 JumpList의 [Tasks][tasks] 카테고리에 `t 항상 동적으로 HTTP NTLM 또는 Negotiate 인증에 자격 증명을 보낼 것인지 설정합니다. -기본적으로 Electron은 "로컬 인터넷" 사이트 URL에서 NTLM/Kerberos 자격 증명만을 보냅니다. (같은 도메인 내에서) -그러나 기업 네트워크가 잘못 구성된 경우 종종 작업에 실패할 수 있습니다. -이때 이 메서드를 통해 모든 URL을 허용할 수 있습니다. +기본적으로 Electron은 "로컬 인터넷" 사이트 URL에서 NTLM/Kerberos 자격 증명만을 +보냅니다. (같은 도메인 내에서) 그러나 기업 네트워크가 잘못 구성된 경우 종종 작업에 +실패할 수 있습니다. 이때 이 메서드를 통해 모든 URL을 허용할 수 있습니다. ### `app.makeSingleInstance(callback)` * `callback` Function 현재 어플리케이션을 **Single Instance Application**으로 만들어줍니다. -이 메서드는 어플리케이션이 여러 번 실행됐을 때 다중 인스턴스가 생성되는 대신 한 개의 주 인스턴스만 유지되도록 만들 수 있습니다. -이때 중복 생성된 인스턴스는 주 인스턴스에 신호를 보내고 종료됩니다. +이 메서드는 어플리케이션이 여러 번 실행됐을 때 다중 인스턴스가 생성되는 대신 한 개의 +주 인스턴스만 유지되도록 만들 수 있습니다. 이때 중복 생성된 인스턴스는 주 인스턴스에 +신호를 보내고 종료됩니다. -`callback`은 주 인스턴스가 생성된 이후 또 다른 인스턴스가 생성됐을 때 `callback(argv, workingDirectory)` 형식으로 호출됩니다. -`argv`는 두 번째 인스턴스의 명령줄 인수이며 `workingDirectory`는 현재 작업중인 디렉터리입니다. -보통 대부분의 어플리케이션은 이러한 콜백이 호출될 때 주 윈도우 창을 포커스하고 최소화되어있으면 창 복구를 실행합니다. +`callback`은 주 인스턴스가 생성된 이후 또 다른 인스턴스가 생성됐을 때 +`callback(argv, workingDirectory)` 형식으로 호출됩니다. `argv`는 두 번째 인스턴스의 +명령줄 인수이며 `workingDirectory`는 현재 작업중인 디렉터리입니다. 보통 대부분의 +어플리케이션은 이러한 콜백이 호출될 때 주 윈도우 창을 포커스하고 최소화되어있으면 창 +복구를 실행합니다. `callback`은 `app`의 `ready` 이벤트가 발생한 후 실행됨을 보장합니다. -이 메서드는 현재 실행된 어플리케이션이 주 인스턴스인 경우 `false`를 반환하고 어플리케이션의 로드가 계속 진행 되도록 합니다. -그리고 두 번째 중복된 인스턴스 생성인 경우 `true`를 반환합니다. (다른 인스턴스에 인수가 전달됬을 때) -이 불리언 값을 통해 중복 생성된 인스턴스는 즉시 종료시켜야 합니다. +이 메서드는 현재 실행된 어플리케이션이 주 인스턴스인 경우 `false`를 반환하고 +어플리케이션의 로드가 계속 진행 되도록 합니다. 그리고 두 번째 중복된 인스턴스 생성인 +경우 `true`를 반환합니다. (다른 인스턴스에 인수가 전달됬을 때) 이 불리언 값을 통해 +중복 생성된 인스턴스는 즉시 종료시켜야 합니다. -OS X에선 사용자가 Finder에서 어플리케이션의 두 번째 인스턴스를 열려고 했을 때 자동으로 **Single Instance**화 하고 `open-file`과 `open-url` 이벤트를 발생시킵니다. -그러나 사용자가 어플리케이션을 CLI 터미널에서 실행하면 운영체제 시스템의 싱글 인스턴스 메커니즘이 무시되며 그대로 중복 실행됩니다. -따라서 OS X에서도 이 메서드를 통해 확실히 중복 실행을 방지하는 것이 좋습니다. +OS X에선 사용자가 Finder에서 어플리케이션의 두 번째 인스턴스를 열려고 했을 때 자동으로 +**Single Instance**화 하고 `open-file`과 `open-url` 이벤트를 발생시킵니다. 그러나 +사용자가 어플리케이션을 CLI 터미널에서 실행하면 운영체제 시스템의 싱글 인스턴스 +메커니즘이 무시되며 그대로 중복 실행됩니다. 따라서 OS X에서도 이 메서드를 통해 확실히 +중복 실행을 방지하는 것이 좋습니다. -다음 예제는 두 번째 인스턴스가 생성되었을 때 중복된 인스턴스를 종료하고 주 어플리케이션 인스턴스의 윈도우 창을 활성화 시키는 예제입니다: +다음 예제는 두 번째 인스턴스가 생성되었을 때 중복된 인스턴스를 종료하고 주 어플리케이션 +인스턴스의 윈도우 창을 활성화 시키는 예제입니다: ```javascript var myWindow = null; @@ -386,8 +409,8 @@ app.on('ready', function() { Chrominum의 명령줄에 스위치를 추가합니다. `value`는 추가적인 값을 뜻하며 옵션입니다. -**참고:** 이 메서드는 `process.argv`에 영향을 주지 않습니다. - 개발자들은 보통 Chrominum의 로우 레벨 수준의 동작을 제어하기 위해 주로 사용합니다. +**참고:** 이 메서드는 `process.argv`에 영향을 주지 않습니다. 개발자들은 보통 +Chrominum의 로우 레벨 수준의 동작을 제어하기 위해 주로 사용합니다. ### `app.commandLine.appendArgument(value)` @@ -397,12 +420,14 @@ Chrominum의 명령줄에 인수를 추가합니다. 인수는 올바르게 인 ### `app.dock.bounce([type])` _OS X_ -* `type` String (optional) - `critical` 또는 `informational`을 지정할 수 있습니다. 기본값은 `informational` 입니다. +* `type` String (optional) - `critical` 또는 `informational`을 지정할 수 있습니다. + 기본값은 `informational` 입니다. -`critical`이 전달되면 dock 아이콘이 어플리케이션이 활성화되거나 요청이 중지되기 전까지 통통 튑니다. +`critical`이 전달되면 dock 아이콘이 어플리케이션이 활성화되거나 요청이 중지되기 전까지 +통통 튑니다. -`informational`이 전달되면 dock 아이콘이 1초만 통통 튑니다. -하지만 어플리케이션이 활성화되거나 요청이 중지되기 전까지 요청은 계속 활성화로 유지 됩니다. +`informational`이 전달되면 dock 아이콘이 1초만 통통 튑니다. 하지만 어플리케이션이 +활성화되거나 요청이 중지되기 전까지 요청은 계속 활성화로 유지 됩니다. 또한 요청을 취소할 때 사용할 수 있는 ID를 반환합니다. diff --git a/docs-translations/ko-KR/api/auto-updater.md b/docs-translations/ko-KR/api/auto-updater.md index 1b0d9c032ccc..04593ee57600 100644 --- a/docs-translations/ko-KR/api/auto-updater.md +++ b/docs-translations/ko-KR/api/auto-updater.md @@ -4,7 +4,8 @@ ## 플랫폼별 참고 사항 -`autoUpdater`는 기본적으로 모든 플랫폼에 대해 같은 API를 제공하지만, 여전히 플랫폼별로 약간씩 다른 점이 있습니다. +`autoUpdater`는 기본적으로 모든 플랫폼에 대해 같은 API를 제공하지만, 여전히 플랫폼별로 +약간씩 다른 점이 있습니다. ### OS X @@ -14,16 +15,18 @@ OS X에선 `auto-updater` 모듈이 [Squirrel.Mac][squirrel-mac]를 기반으로 ### Windows -Windows에선 `auto-updater` 모듈을 사용하기 전에 어플리케이션을 사용자의 장치에 설치해야 합니다. -[grunt-electron-installer][installer]를 사용하여 어플리케이션 인스톨러를 만드는 것을 권장합니다. +Windows에선 `auto-updater` 모듈을 사용하기 전에 어플리케이션을 사용자의 장치에 +설치해야 합니다. [grunt-electron-installer][installer]를 사용하여 어플리케이션 +인스톨러를 만드는 것을 권장합니다. Squirrel로 생성된 인스톨러는 [Application User Model ID][app-user-model-id]와 함께 -`com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`으로 형식화된 바로가기 아이콘을 생성합니다. -`com.squirrel.slack.Slack` 과 `com.squirrel.code.Code`가 그 예시입니다. -`app.setAppUserModelId` API를 통해 어플리케이션 ID를 동일하게 유지해야 합니다. -그렇지 않으면 Windows 작업 표시줄에 어플리케이션을 고정할 때 제대로 적용되지 않을 수 있습니다. +`com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`으로 형식화된 바로가기 아이콘을 +생성합니다. `com.squirrel.slack.Slack` 과 `com.squirrel.code.Code`가 그 예시입니다. +`app.setAppUserModelId` API를 통해 어플리케이션 ID를 동일하게 유지해야 합니다. 그렇지 +않으면 Windows 작업 표시줄에 어플리케이션을 고정할 때 제대로 적용되지 않을 수 있습니다. -서버 사이드 요구 사항 또한 OS X와 다르게 적용됩니다. 자세한 내용은 [Squirrel.Windows][squirrel-windows]를 참고하세요. +서버 사이드 요구 사항 또한 OS X와 다르게 적용됩니다. 자세한 내용은 +[Squirrel.Windows][squirrel-windows]를 참고하세요. ### Linux @@ -78,7 +81,8 @@ Returns: ### `autoUpdater.checkForUpdates()` -서버에 새로운 업데이트가 있는지 요청을 보내 확인합니다. API를 사용하기 전에 `setFeedURL`를 호출해야 합니다. +서버에 새로운 업데이트가 있는지 요청을 보내 확인합니다. API를 사용하기 전에 +`setFeedURL`를 호출해야 합니다. ### `autoUpdater.quitAndInstall()` diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 02ae9eb66049..65c550566802 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -16,13 +16,16 @@ win.loadURL('https://github.com'); win.show(); ``` -또한 [Frameless Window](frameless-window.md) API를 사용하여 창 테두리가 없는 윈도우 창을 생성할 수 있습니다. +또한 [Frameless Window](frameless-window.md) API를 사용하여 창 테두리가 없는 윈도우 +창을 생성할 수 있습니다. ## Class: BrowserWindow -`BrowserWindow`는 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속받은 클래스 입니다. +`BrowserWindow`는 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 +상속받은 클래스 입니다. -`BrowserWindow`는 `options`를 통해 네이티브 속성을 포함한 새로운 윈도우 창을 생성합니다. +`BrowserWindow`는 `options`를 통해 네이티브 속성을 포함한 새로운 윈도우 창을 +생성합니다. ### `new BrowserWindow(options)` @@ -33,7 +36,8 @@ win.show(); * `x` Integer - 화면을 기준으로 창 좌측을 오프셋 한 위치. * `y` Integer - 화면을 기준으로 창 상단을 오프셋 한 위치. * `useContentSize` Boolean - `width`와 `height`를 웹 페이지의 크기로 사용합니다. - 이 속성을 사용하면 웹 페이지의 크기에 윈도우 프레임 크기가 추가되므로 실제 창은 조금 더 커질 수 있습니다. + 이 속성을 사용하면 웹 페이지의 크기에 윈도우 프레임 크기가 추가되므로 실제 창은 조금 + 더 커질 수 있습니다. * `center` Boolean - 윈도우 창을 화면 정 중앙에 위치시킵니다. * `minWidth` Integer - 윈도우 창의 최소 가로 너비. * `minHeight` Integer - 윈도우 창의 최소 세로 높이. @@ -46,42 +50,61 @@ win.show(); * `skipTaskbar` Boolean - 작업표시줄 어플리케이션 아이콘 표시 여부. * `kiosk` Boolean - Kiosk(키오스크) 모드. * `title` String - 기본 윈도우 창 제목. -* `icon` [NativeImage](native-image.md) - 윈도우 아이콘, 생략하면 실행 파일의 아이콘이 대신 사용됩니다. +* `icon` [NativeImage](native-image.md) - 윈도우 아이콘, 생략하면 실행 파일의 + 아이콘이 대신 사용됩니다. * `show` Boolean - 윈도우가 생성되면 보여줄지 여부. -* `frame` Boolean - `false`로 지정하면 창을 [Frameless Window](frameless-window.md) 형태로 생성합니다. -* `acceptFirstMouse` Boolean - 윈도우가 비활성화 상태일 때 내부 컨텐츠 클릭 시 활성화 되는 동시에 단일 mouse-down 이벤트를 발생시킬지 여부. +* `frame` Boolean - `false`로 지정하면 창을 [Frameless Window](frameless-window.md) + 형태로 생성합니다. +* `acceptFirstMouse` Boolean - 윈도우가 비활성화 상태일 때 내부 컨텐츠 클릭 시 + 활성화 되는 동시에 단일 mouse-down 이벤트를 발생시킬지 여부. * `disableAutoHideCursor` Boolean - 파이핑중 자동으로 커서를 숨길지 여부. -* `autoHideMenuBar` Boolean - `Alt`를 누르지 않는 한 어플리케이션 메뉴바를 숨길지 여부. -* `enableLargerThanScreen` Boolean - 윈도우 창 크기가 화면 크기보다 크게 재조정 될 수 있는지 여부. -* `backgroundColor` String - 16진수로 표현된 윈도우의 배경 색. `#66CD00` 또는 `#FFF`가 사용될 수 있습니다. +* `autoHideMenuBar` Boolean - `Alt`를 누르지 않는 한 어플리케이션 메뉴바를 숨길지 + 여부. +* `enableLargerThanScreen` Boolean - 윈도우 창 크기가 화면 크기보다 크게 재조정 될 + 수 있는지 여부. +* `backgroundColor` String - 16진수로 표현된 윈도우의 배경 색. `#66CD00` 또는 + `#FFF`가 사용될 수 있습니다. 이 속성은 Linux와 Windows에만 구현되어 있습니다. -* `darkTheme` Boolean - 설정에 상관 없이 무조건 어두운 윈도우 테마를 사용합니다. 몇몇 GTK+3 데스크톱 환경에서만 작동합니다. +* `darkTheme` Boolean - 설정에 상관 없이 무조건 어두운 윈도우 테마를 사용합니다. + 몇몇 GTK+3 데스크톱 환경에서만 작동합니다. * `transparent` Boolean - 윈도우 창을 [투명화](frameless-window.md)합니다. * `type` String - 윈도우 창 종류를 지정합니다. - 사용할 수 있는 창 종류는 `desktop`, `dock`, `toolbar`, `splash`, `notification`와 같습니다. - 이 속성은 Linux에서만 작동합니다. -* `standardWindow` Boolean - OS X의 표준 윈도우를 텍스쳐 윈도우 대신 사용합니다. 기본 값은 `true`입니다. -* `titleBarStyle` String, OS X - 윈도우 타이틀 바 스타일을 지정합니다. 이 속성은 OS X 10.10 Yosemite 이후 버전만 지원합니다. - 다음 3가지 종류의 값을 사용할 수 있습니다: + 사용할 수 있는 창 종류는 `desktop`, `dock`, `toolbar`, `splash`, + `notification`와 같습니다. 이 속성은 Linux에서만 작동합니다. +* `standardWindow` Boolean - OS X의 표준 윈도우를 텍스쳐 윈도우 대신 사용합니다. + 기본 값은 `true`입니다. +* `titleBarStyle` String, OS X - 윈도우 타이틀 바 스타일을 지정합니다. 이 속성은 + OS X 10.10 Yosemite 이후 버전만 지원합니다. 다음 3가지 종류의 값을 사용할 수 + 있습니다: * `default` 또는 미지정: 표준 Mac 회색 불투명 스타일을 사용합니다. * `hidden`: 타이틀 바를 숨기고 컨텐츠 전체를 윈도우 크기에 맞춥니다. 타이틀 바는 없어지지만 표준 창 컨트롤 ("신호등 버튼")은 왼쪽 상단에 유지됩니다. - * `hidden-inset`: `hidden` 타이틀 바 속성과 함께 신호등 버튼이 윈도우 모서리로부터 약간 더 안쪽으로 들어가도록합니다. -* `webPreferences` Object - 웹 페이지 기능을 설정합니다. 사용할 수 있는 속성은 다음과 같습니다: + * `hidden-inset`: `hidden` 타이틀 바 속성과 함께 신호등 버튼이 윈도우 모서리로부터 + 약간 더 안쪽으로 들어가도록합니다. +* `webPreferences` Object - 웹 페이지 기능을 설정합니다. 사용할 수 있는 속성은 + 다음과 같습니다: * `nodeIntegration` Boolean - node(node.js) 통합 여부. 기본값은 `true`입니다. - * `preload` String - 스크립트를 지정하면 페이지 내의 다른 스크립트가 작동하기 전에 로드됩니다. - 여기서 지정한 스크립트는 페이지의 node 통합 활성화 여부에 상관없이 언제나 모든 node API에 접근할 수 있습니다. - 그리고 `preload` 스크립트의 경로는 절대 경로로 지정해야 합니다. + * `preload` String - 스크립트를 지정하면 페이지 내의 다른 스크립트가 작동하기 전에 + 로드됩니다. 여기서 지정한 스크립트는 페이지의 node 통합 활성화 여부에 상관없이 + 언제나 모든 node API에 접근할 수 있습니다. 그리고 `preload` 스크립트의 경로는 + 절대 경로로 지정해야 합니다. * `partition` String - 페이지에서 사용할 세션을 지정합니다. 만약 `partition`이 - `persist:`로 시작하면 페이지는 지속성 세션을 사용하며 다른 모든 앱 내의 페이지에서 같은 `partition`을 사용할 수 있습니다. - 만약 `persist:` 접두어로 시작하지 않으면 페이지는 인-메모리 세션을 사용합니다. 여러 페이지에서 같은 `partition`을 지정하면 - 같은 세션을 공유할 수 있습니다. `partition`을 지정하지 않으면 어플리케이션의 기본 세션이 사용됩니다. - * `zoomFactor` Number - 페이지의 기본 줌 값을 지정합니다. 예를 들어 `300%`를 표현하려면 `3.0`으로 지정합니다. + `persist:`로 시작하면 페이지는 지속성 세션을 사용하며 다른 모든 앱 내의 + 페이지에서 같은 `partition`을 사용할 수 있습니다. 만약 `persist:` 접두어로 + 시작하지 않으면 페이지는 인-메모리 세션을 사용합니다. 여러 페이지에서 같은 + `partition`을 지정하면 같은 세션을 공유할 수 있습니다. `partition`을 지정하지 + 않으면 어플리케이션의 기본 세션이 사용됩니다. + * `zoomFactor` Number - 페이지의 기본 줌 값을 지정합니다. 예를 들어 `300%`를 + 표현하려면 `3.0`으로 지정합니다. * `javascript` Boolean - * `webSecurity` Boolean - `false`로 지정하면 same-origin 정책을 비활성화합니다. (이 속성은 보통 사람에 의해 웹 사이트를 테스트할 때 사용합니다) - 그리고 `allowDisplayingInsecureContent`와 `allowRunningInsecureContent`이 사용자로부터 `true`로 지정되지 않은 경우 `true`로 지정합니다. - * `allowDisplayingInsecureContent` Boolean - https 페이지에서 http URL에서 로드한 이미지 같은 리소스를 표시할 수 있도록 허용합니다. - * `allowRunningInsecureContent` Boolean - https 페이지에서 http URL에서 로드한 JavaScript와 CSS 또는 플러그인을 실행시킬 수 있도록 허용합니다. + * `webSecurity` Boolean - `false`로 지정하면 same-origin 정책을 비활성화합니다. + (이 속성은 보통 사람에 의해 웹 사이트를 테스트할 때 사용합니다) 그리고 + `allowDisplayingInsecureContent`와 `allowRunningInsecureContent`이 + 사용자로부터 `true`로 지정되지 않은 경우 `true`로 지정합니다. + * `allowDisplayingInsecureContent` Boolean - https 페이지에서 http URL에서 + 로드한 이미지 같은 리소스를 표시할 수 있도록 허용합니다. + * `allowRunningInsecureContent` Boolean - https 페이지에서 http URL에서 로드한 + JavaScript와 CSS 또는 플러그인을 실행시킬 수 있도록 허용합니다. * `images` Boolean * `java` Boolean * `textAreasAreResizable` Boolean @@ -93,9 +116,11 @@ win.show(); * `overlayScrollbars` Boolean * `overlayFullscreenVideo` Boolean * `sharedWorker` Boolean - * `directWrite` Boolean - Windows에서 폰트 랜더링을 위해 DirectWrite를 사용하는지를 지정합니다. - * `pageVisibility` Boolean - 현재 윈도우의 가시성을 반영하는 대신 페이지가 visible 또는 hidden 중 지정된 상태를 계속 유지하도록 합니다. - 이 속성을 `true`로 지정하면 DOM 타이머의 스로틀링을 방지할 수 있습니다. + * `directWrite` Boolean - Windows에서 폰트 랜더링을 위해 DirectWrite를 + 사용하는지를 지정합니다. + * `pageVisibility` Boolean - 현재 윈도우의 가시성을 반영하는 대신 페이지가 + visible 또는 hidden 중 지정된 상태를 계속 유지하도록 합니다. 이 속성을 `true`로 + 지정하면 DOM 타이머의 스로틀링을 방지할 수 있습니다. ## Events @@ -109,8 +134,8 @@ Returns: * `event` Event -문서의 제목이 변경될 때 발생하는 이벤트 입니다. -`event.preventDefault()`를 호출하여 네이티브 윈도우의 제목이 변경되는 것을 방지할 수 있습니다. +문서의 제목이 변경될 때 발생하는 이벤트 입니다. `event.preventDefault()`를 호출하여 +네이티브 윈도우의 제목이 변경되는 것을 방지할 수 있습니다. ### Event: 'close' @@ -132,18 +157,19 @@ Electron에선 빈 문자열 또는 `false`를 전달할 경우 윈도우 종료 window.onbeforeunload = function(e) { console.log('I do not want to be closed'); - // 반드시 문자열을 반환해야 하고 사용자에게 페이지 언로드에 대한 확인 창을 보여주는 보통의 브라우저와는 달리 - // Electron은 개발자에게 더 많은 옵션을 제공합니다. + // 반드시 문자열을 반환해야 하고 사용자에게 페이지 언로드에 대한 확인 창을 보여주는 + // 보통의 브라우저와는 달리 Electron은 개발자에게 더 많은 옵션을 제공합니다. // 빈 문자열을 반환하거나 false를 반환하면 페이지 언로드를 방지합니다. - // 또한 dialog API를 통해 사용자에게 어플리케이션을 종료할지에 대한 확인 창을 보여줄 수도 있습니다. + // 또한 dialog API를 통해 사용자에게 어플리케이션을 종료할지에 대한 확인 창을 + // 보여줄 수도 있습니다. e.returnValue = false; }; ``` ### Event: 'closed' -윈도우 종료가 완료된 경우 발생하는 이벤트입니다. -이 이벤트가 발생했을 경우 반드시 윈도우 창의 레퍼런스가 더 이상 사용되지 않도록 제거해야 합니다. +윈도우 종료가 완료된 경우 발생하는 이벤트입니다. 이 이벤트가 발생했을 경우 반드시 +윈도우 창의 레퍼런스가 더 이상 사용되지 않도록 제거해야 합니다. ### Event: 'unresponsive' @@ -209,9 +235,10 @@ __참고__: OS X에선 이 이벤트가 그저 `moved` 이벤트의 별칭(alias ### Event: 'app-command' _Windows_ -[App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)가 호출됐을 때 발생하는 이벤트입니다. -이 이벤트는 일반적으로 키보드 미디어 키 또는 브라우저 커맨드(기본 동작 키)에 관련되어 있습니다. -예를 들어 Windows에서 작동하는 몇몇 마우스는 "뒤로가기" 같은 동작을 포함하고 있습니다. +[App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)가 +호출됐을 때 발생하는 이벤트입니다. 이 이벤트는 일반적으로 키보드 미디어 키 또는 +브라우저 커맨드(기본 동작 키)에 관련되어 있습니다. 예를 들어 Windows에서 작동하는 +몇몇 마우스는 "뒤로가기" 같은 동작을 포함하고 있습니다. ```javascript someWindow.on('app-command', function(e, cmd) { @@ -272,9 +299,11 @@ var win = new BrowserWindow({ width: 800, height: 600 }); ### `win.webContents` -윈도우의 `WebContents` 객체입니다. 모든 웹 페이지와 관련된 이벤트와 작업이 이 객체를 통해 수행됩니다. +윈도우의 `WebContents` 객체입니다. 모든 웹 페이지와 관련된 이벤트와 작업이 이 객체를 +통해 수행됩니다. -메서드나 이벤트에 대한 자세한 내용은 [`webContents` 문서](web-contents.md)를 참고하세요. +메서드나 이벤트에 대한 자세한 내용은 [`webContents` 문서](web-contents.md)를 +참고하세요. ### `win.id` @@ -288,15 +317,17 @@ var win = new BrowserWindow({ width: 800, height: 600 }); ### `win.destroy()` -윈도우를 강제로 닫습니다. 웹 페이지의 `unload` 와 `beforeunload` 이벤트는 일어나지 않습니다. -또한 이 윈도우의 `close`도 일어나지 않습니다. 하지만 `closed` 이벤트는 반드시 발생함을 보장합니다. +윈도우를 강제로 닫습니다. 웹 페이지의 `unload` 와 `beforeunload` 이벤트는 일어나지 +않습니다. 또한 이 윈도우의 `close`도 일어나지 않습니다. 하지만 `closed` 이벤트는 +반드시 발생함을 보장합니다. 이 메서드는 렌더러 프로세스가 예기치 않게 크래시가 일어났을 경우에만 사용해야 합니다. ### `win.close()` -윈도우의 종료를 시도합니다. 이 메서드는 사용자가 윈도우의 닫기 버튼을 클릭했을 때와 같은 효과를 냅니다. -웹 페이지는 로드가 취소되고 종료됩니다. 자세한 내용은 [close 이벤트](#event-close)를 참고하세요. +윈도우의 종료를 시도합니다. 이 메서드는 사용자가 윈도우의 닫기 버튼을 클릭했을 때와 +같은 효과를 냅니다. 웹 페이지는 로드가 취소되고 종료됩니다. 자세한 내용은 +[close 이벤트](#event-close)를 참고하세요. ### `win.focus()` @@ -359,19 +390,22 @@ var win = new BrowserWindow({ width: 800, height: 600 }); ### `win.setAspectRatio(aspectRatio[, extraSize])` _OS X_ * `aspectRatio` 유지하려 하는 컨텐츠 뷰 일부의 종횡비 -* `extraSize` Object (optional) - 종횡비를 유지하는 동안 포함되지 않을 엑스트라 크기. 사용 가능한 속성: +* `extraSize` Object (optional) - 종횡비를 유지하는 동안 포함되지 않을 엑스트라 크기. + 사용 가능한 속성: * `width` Integer * `height` Integer -이 메서드는 윈도우의 종횡비를 유지하는 기능을 수행합니다. -엑스트라 크기는 개발자가 픽셀로 특정한 공간이 있을 때 종횡비 계산에서 제외됩니다. -이 API는 윈도우의 크기와 컨텐츠 사이즈의 차이를 이미 고려하고 있습니다. +이 메서드는 윈도우의 종횡비를 유지하는 기능을 수행합니다. 엑스트라 크기는 개발자가 +픽셀로 특정한 공간이 있을 때 종횡비 계산에서 제외됩니다. 이 API는 윈도우의 크기와 +컨텐츠 사이즈의 차이를 이미 고려하고 있습니다. 일반 윈도우에서 작동하는 HD 비디오 플레이어와 관련된 컨트롤을 고려합니다. -만약 15 픽셀의 컨트롤이 왼쪽 가장자리에 있고 25 픽셀의 컨트롤이 오른쪽 가장자리에 있으며 50 픽셀의 컨트롤이 플레이어 밑에 있을 때 -플레이어 자체가 16:9 종횡비(HD의 표준 종횡비는 @1920x1080)를 유지하기 위해선 이 함수를 16/9, [ 40, 50 ] 인수와 함께 호출해야 합니다. -두번째 인수 엑스트라 크기는 존재하는 크기만 관여하고 컨텐츠 뷰 내의 크기는 관여하지 않습니다. -그저 전체 컨텐츠 뷰 내에 있는 모든 엑스트라 너비, 높이 영역이 합해집니다. +만약 15 픽셀의 컨트롤이 왼쪽 가장자리에 있고 25 픽셀의 컨트롤이 오른쪽 가장자리에 +있으며 50 픽셀의 컨트롤이 플레이어 밑에 있을 때 플레이어 자체가 16:9 종횡비(HD의 표준 +종횡비는 @1920x1080)를 유지하기 위해선 이 함수를 16/9, [ 40, 50 ] 인수와 함께 +호출해야 합니다. 두번째 인수 엑스트라 크기는 존재하는 크기만 관여하고 컨텐츠 뷰 내의 +크기는 관여하지 않습니다. 그저 전체 컨텐츠 뷰 내에 있는 모든 엑스트라 너비, 높이 영역이 +합해집니다. ### `win.setBounds(options)` @@ -446,8 +480,8 @@ var win = new BrowserWindow({ width: 800, height: 600 }); * `flag` Boolean -윈도우가 언제나 다른 윈도우들 위에 표시되는지 여부를 지정합니다. -이 설정을 활성화 하면 윈도우는 포커스 될 수 없는 툴박스 윈도우가 아닌 일반 윈도우로 유지됩니다. +윈도우가 언제나 다른 윈도우들 위에 표시되는지 여부를 지정합니다. 이 설정을 활성화 하면 +윈도우는 포커스 될 수 없는 툴박스 윈도우가 아닌 일반 윈도우로 유지됩니다. ### `win.isAlwaysOnTop()` @@ -539,7 +573,8 @@ Windows 메시지 훅을 등록합니다. `callback`은 WndProc에서 메시지 * `edited` Boolean -윈도우의 문서가 변경되었는지 여부를 설정합니다. 그리고 `true`로 설정했을 때 타이틀 바의 아이콘이 회색으로 표시됩니다. +윈도우의 문서가 변경되었는지 여부를 설정합니다. 그리고 `true`로 설정했을 때 타이틀 바의 +아이콘이 회색으로 표시됩니다. ### `win.isDocumentEdited()` _OS X_ @@ -551,17 +586,17 @@ Windows 메시지 훅을 등록합니다. `callback`은 WndProc에서 메시지 ### `win.capturePage([rect, ]callback)` -* `rect` Object (optional) - 캡쳐할 페이지의 영역. 사용할 수 있는 속성은 다음과 같습니다: +* `rect` Object (optional) - 캡쳐할 페이지의 영역. + 사용할 수 있는 속성은 다음과 같습니다: * `x` Integer * `y` Integer * `width` Integer * `height` Integer * `callback` Function -페이지의 스크린샷을 `rect`에 설정한 만큼 캡처합니다. -캡처가 완료되면 `callback`이 `callback(image)` 형식으로 호출됩니다. -`image`는 [NativeImage](native-image.md)의 인스턴스이며 스크린샷 데이터를 담고있습니다. -`rect`를 생략하면 페이지 전체를 캡처합니다. +페이지의 스크린샷을 `rect`에 설정한 만큼 캡처합니다. 캡처가 완료되면 `callback`이 +`callback(image)` 형식으로 호출됩니다. `image`는 [NativeImage](native-image.md)의 +인스턴스이며 스크린샷 데이터를 담고있습니다. `rect`를 생략하면 페이지 전체를 캡처합니다. ### `win.print([options])` @@ -589,23 +624,24 @@ Windows 메시지 훅을 등록합니다. `callback`은 WndProc에서 메시지 * `progress` Double -작업표시줄에 표시되고 있는 어플리케이션 아이콘에 진행 상태를 표시합니다. [0, 1.0] 사이의 값을 지정할 수 있습니다. +작업표시줄에 표시되고 있는 어플리케이션 아이콘에 진행 상태를 표시합니다. [0, 1.0] +사이의 값을 지정할 수 있습니다. 진행 상태가 < 0 이 되면 진행 상태 표시를 제거합니다. 진행 상태가 > 1 이 되면 불확정 상태 표시로 전환합니다. -Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. -그리고 이 기능을 사용하려면 `*.desktop` 파일을 생성한 후 `package.json`의 `desktopName` 필드에 파일 이름을 지정해야 합니다. -기본적으로 `app.getName().desktop`을 통해 접근합니다. +Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. 그리고 이 기능을 사용하려면 +`*.desktop` 파일을 생성한 후 `package.json`의 `desktopName` 필드에 파일 이름을 +지정해야 합니다. 기본적으로 `app.getName().desktop`을 통해 접근합니다. ### `win.setOverlayIcon(overlay, description)` _Windows 7+_ -* `overlay` [NativeImage](native-image.md) - 작업표시줄 아이콘의 우측 하단에 표시될 아이콘입니다. -`null`로 지정하면 빈 오버레이가 사용됩니다 +* `overlay` [NativeImage](native-image.md) - 작업표시줄 아이콘의 우측 하단에 표시될 +아이콘입니다. `null`로 지정하면 빈 오버레이가 사용됩니다 * `description` String - 접근성 설정에 의한 스크린 리더에 제공될 설명입니다 -현재 작업표시줄 아이콘에 16px 크기의 오버레이를 지정합니다. -보통 이 기능은 어플리케이션의 여러 상태를 사용자에게 소극적으로 알리기 위한 방법으로 사용됩니다. +현재 작업표시줄 아이콘에 16px 크기의 오버레이를 지정합니다. 보통 이 기능은 +어플리케이션의 여러 상태를 사용자에게 소극적으로 알리기 위한 방법으로 사용됩니다. ### `win.setThumbarButtons(buttons)` _Windows 7+_ @@ -615,23 +651,27 @@ Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. * `icon` [NativeImage](native-image.md) - 미리보기 툴바에 보여질 아이콘. * `tooltip` String (optional) - 버튼의 툴팁 텍스트. -* `flags` Array (optional) - 버튼의 특정 동작 및 상태 제어. 기본적으로 `enabled`이 사용됩니다. - 이 속성은 다음 문자열들을 포함할 수 있습니다: +* `flags` Array (optional) - 버튼의 특정 동작 및 상태 제어. 기본적으로 `enabled`이 + 사용됩니다. 이 속성은 다음 문자열들을 포함할 수 있습니다: * `enabled` - 사용자가 사용할 수 있도록 버튼이 활성화 됩니다. - * `disabled` - 버튼이 비활성화 됩니다. 버튼은 표시되지만 시각적인 상태는 사용자의 동작에 응답하지 않는 - 비활성화 상태로 표시됩니다. - * `dismissonclick` - 버튼이 클릭되면 작업표시줄 버튼의 미리보기(flyout)가 즉시 종료됩니다. + * `disabled` - 버튼이 비활성화 됩니다. 버튼은 표시되지만 시각적인 상태는 사용자의 + 동작에 응답하지 않는 비활성화 상태로 표시됩니다. + * `dismissonclick` - 버튼이 클릭되면 작업표시줄 버튼의 미리보기(flyout)가 즉시 + 종료됩니다. * `nobackground` - 버튼의 테두리를 표시하지 않습니다. 이미지에만 사용할 수 있습니다. * `hidden` - 버튼을 사용자에게 표시되지 않도록 숨깁니다. - * `noninteractive` - 버튼은 활성화되어 있지만 반응이 제거되며 버튼을 눌러도 눌려지지 않은 상태를 유지합니다. - 이 값은 버튼을 알림의 용도로 사용하기 위해 만들어졌습니다. + * `noninteractive` - 버튼은 활성화되어 있지만 반응이 제거되며 버튼을 눌러도 + 눌려지지 않은 상태를 유지합니다. 이 값은 버튼을 알림의 용도로 사용하기 위해 + 만들어졌습니다. * `click` - Function -윈도우 작업표시줄 버튼 레이아웃의 미리보기 이미지 영역에 미리보기 툴바와 버튼 세트를 지정합니다. -반환되는 `Boolean` 값은 미리보기 툴바가 성공적으로 추가됬는지를 알려줍니다. +윈도우 작업표시줄 버튼 레이아웃의 미리보기 이미지 영역에 미리보기 툴바와 버튼 세트를 +지정합니다. 반환되는 `Boolean` 값은 미리보기 툴바가 성공적으로 추가됬는지를 알려줍니다. -미리보기 이미지 영역의 제한된 크기로 인해 미리보기 툴바에 추가될 수 있는 최대 버튼의 개수는 7개이며 이 이상 추가될 수 없습니다. -플랫폼의 제약으로 인해 미리보기 툴바는 한 번 설정되면 삭제할 수 없습니다. 하지만 이 API에 빈 배열을 전달하여 버튼들을 제거할 수 있습니다. +미리보기 이미지 영역의 제한된 크기로 인해 미리보기 툴바에 추가될 수 있는 최대 버튼의 +개수는 7개이며 이 이상 추가될 수 없습니다. 플랫폼의 제약으로 인해 미리보기 툴바는 한 번 +설정되면 삭제할 수 없습니다. 하지만 이 API에 빈 배열을 전달하여 버튼들을 제거할 수 +있습니다. ### `win.showDefinitionForSelection()` _OS X_ @@ -644,7 +684,8 @@ Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. 메뉴 막대 자동 숨김 기능을 활성화 합니다. 숨겨진 메뉴는 사용자가 `Alt` 키를 단일 입력했을 때만 표시됩니다. -메뉴 막대가 이미 표시되고 있을 때 `setAutoHideMenuBar(true)`를 호출한다고 해서 메뉴가 즉시 숨겨지지는 않습니다. +메뉴 막대가 이미 표시되고 있을 때 `setAutoHideMenuBar(true)`를 호출한다고 해서 +메뉴가 즉시 숨겨지지는 않습니다. ### `win.isMenuBarAutoHide()` @@ -654,8 +695,8 @@ Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. * `visible` Boolean -메뉴 막대의 표시 여부를 설정합니다. -만약 메뉴 막대 자동 숨김 상태라면 여전히 사용자가 `Alt` 키를 입력하여 메뉴 막대를 표시되도록 할 수 있습니다. +메뉴 막대의 표시 여부를 설정합니다. 만약 메뉴 막대 자동 숨김 상태라면 여전히 사용자가 +`Alt` 키를 입력하여 메뉴 막대를 표시되도록 할 수 있습니다. **역주:** 기본 메뉴 막대를 완전히 없애려면 `win.setMenu(null)`를 호출해야 합니다. 단순히 이 API를 사용하면 여전히 메뉴에 등록된 핫 키가 작동합니다. diff --git a/docs-translations/ko-KR/api/chrome-command-line-switches.md b/docs-translations/ko-KR/api/chrome-command-line-switches.md index d3aa5dd6411b..3c825b1abb13 100644 --- a/docs-translations/ko-KR/api/chrome-command-line-switches.md +++ b/docs-translations/ko-KR/api/chrome-command-line-switches.md @@ -1,8 +1,9 @@ # 크롬 명령줄 스위치 지원 -크롬 명령줄(Command-Line) 스위치는 크롬 브라우저에서 제공되는 추가 옵션이며 Electron에서도 지원합니다. -[app][app]의 [ready][ready]이벤트가 작동하기 전에 [app.commandLine.appendSwitch][append-switch] API를 사용하면 -어플리케이션 내부에서 스위치들을 추가할 수 있습니다: +크롬 명령줄(Command-Line) 스위치는 크롬 브라우저에서 제공되는 추가 옵션이며 +Electron에서도 지원합니다. [app][app]의 [ready][ready]이벤트가 작동하기 전에 +[app.commandLine.appendSwitch][append-switch] API를 사용하면 어플리케이션 내부에서 +스위치를 추가할 수 있습니다: ```javascript const app = require('electron').app; @@ -32,8 +33,8 @@ HTTP 요청 캐시를 비활성화 합니다. ## --js-flags=`flags` -JS 엔진에 지정한 플래그를 전달합니다. -`flags`를 메인 프로세스에서 활성화하고자 한다면, Electron이 시작되기 전에 스위치를 전달해야 합니다. +JS 엔진에 지정한 플래그를 전달합니다. `flags`를 메인 프로세스에서 활성화하고자 한다면, +Electron이 시작되기 전에 스위치를 전달해야 합니다. ```bash $ electron --js-flags="--harmony_proxies --harmony_collections" your-app @@ -41,11 +42,12 @@ $ electron --js-flags="--harmony_proxies --harmony_collections" your-app ## --proxy-server=`address:port` -시스템 설정의 프록시 서버를 무시하고 지정한 서버로 연결합니다. HTTP와 HTTPS 요청에만 적용됩니다. +시스템 설정의 프록시 서버를 무시하고 지정한 서버로 연결합니다. HTTP와 HTTPS 요청에만 +적용됩니다. -시스템 프록시 서버 설정을 무시하고 지정한 서버로 연결합니다. -이 스위치는 HTTP와 HTTPS 그리고 WebSocket 요청에만 적용됩니다. -그리고 모든 프록시 서버가 HTTPS가 WebSocket 요청을 지원하지 않고 있을 수 있으므로 사용시 주의해야 합니다. +시스템 프록시 서버 설정을 무시하고 지정한 서버로 연결합니다. 이 스위치는 HTTP와 HTTPS +그리고 WebSocket 요청에만 적용됩니다. 그리고 모든 프록시 서버가 HTTPS가 WebSocket +요청을 지원하지 않고 있을 수 있으므로 사용시 주의해야 합니다. ## --proxy-pac-url=`url` @@ -53,7 +55,8 @@ $ electron --js-flags="--harmony_proxies --harmony_collections" your-app ## --no-proxy-server -프록시 서버를 사용하지 않습니다. 다른 프록시 서버 플래그 및 설정을 무시하고 언제나 직접 연결을 사용합니다. +프록시 서버를 사용하지 않습니다. 다른 프록시 서버 플래그 및 설정을 무시하고 언제나 직접 +연결을 사용합니다. ## --host-rules=`rules` @@ -61,24 +64,21 @@ Hostname 맵핑 규칙을 설정합니다. (`,`로 구분) 예시: -* `MAP * 127.0.0.1` Forces all hostnames to be mapped to 127.0.0.1 -* `MAP *.google.com proxy` Forces all google.com subdomains to be resolved to - "proxy". -* `MAP test.com [::1]:77` Forces "test.com" to resolve to IPv6 loopback. Will - also force the port of the resulting socket address to be 77. -* `MAP * baz, EXCLUDE www.google.com` Remaps everything to "baz", except for - "www.google.com". - -이 맵핑은 네트워크 요청시의 endpoint를 지정합니다. (TCP 연결과 직접 연결의 호스트 resolver, http 프록시 연결의 `CONNECT`, `SOCKS` 프록시 연결의 endpoint 호스트) +* `MAP * 127.0.0.1` 강제적으로 모든 호스트네임을 127.0.0.1로 맵핑합니다 +* `MAP *.google.com proxy` 강제적으로 모든 google.com의 서브도메인을 "proxy"로 + 연결합니다 +* `MAP test.com [::1]:77` 강제적으로 "test.com"을 IPv6 루프백으로 연결합니다. + 소켓 주소의 포트 또한 77로 고정됩니다. +* `MAP * baz, EXCLUDE www.google.com` "www.google.com"을 제외한 모든 것들을 + "baz"로 맵핑합니다. + +이 맵핑은 네트워크 요청시의 endpoint를 지정합니다. (TCP 연결과 직접 연결의 호스트 +resolver, http 프록시 연결의 `CONNECT`, `SOCKS` 프록시 연결의 endpoint 호스트) ## --host-resolver-rules=`rules` `--host-rules` 플래그와 비슷하지만 이 플래그는 host resolver에만 적용됩니다. -[app]: app.md -[append-switch]: app.md#appcommandlineappendswitchswitch-value -[ready]: app.md#event-ready - ## --ignore-certificate-errors 인증서 에러를 무시합니다. @@ -97,7 +97,8 @@ Net log 이벤트를 활성화하고 `path`에 로그를 기록합니다. ## --ssl-version-fallback-min=`version` -TLS fallback에서 사용할 SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", "tls1.2") +TLS fallback에서 사용할 SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", +"tls1.2") ## --cipher-suite-blacklist=`cipher_suites` @@ -107,21 +108,29 @@ SSL 암호화를 비활성화할 대상 목록을 지정합니다. (`,`로 구 Chromium의 로그를 콘솔에 출력합니다. -이 스위치는 어플리케이션이 로드되기 전에 분석 되므로 `app.commandLine.appendSwitch` 메서드에선 사용할 수 없습니다. -하지만 `ELECTRON_ENABLE_LOGGING` 환경 변수를 설정하면 본 스위치를 지정한 것과 같은 효과를 낼 수 있습니다. +이 스위치는 어플리케이션이 로드되기 전에 분석 되므로 `app.commandLine.appendSwitch` +메서드에선 사용할 수 없습니다. 하지만 `ELECTRON_ENABLE_LOGGING` 환경 변수를 설정하면 +본 스위치를 지정한 것과 같은 효과를 낼 수 있습니다. ## --v=`log_level` -기본 V-logging 최대 활성화 레벨을 지정합니다. 기본값은 0입니다. 기본적으로 양수를 레벨로 사용합니다. +기본 V-logging 최대 활성화 레벨을 지정합니다. 기본값은 0입니다. 기본적으로 양수를 +레벨로 사용합니다. 이 스위치는 `--enable-logging` 스위치를 같이 지정해야 작동합니다. ## --vmodule=`pattern` `--v` 옵션에 전달된 값을 덮어쓰고 모듈당 최대 V-logging 레벨을 지정합니다. -예를 들어 `my_module=2,foo*=3`는 `my_module.*`, `foo*.*`와 같은 파일 이름 패턴을 가진 모든 소스 코드들의 로깅 레벨을 각각 2와 3으로 설정합니다. +예를 들어 `my_module=2,foo*=3`는 `my_module.*`, `foo*.*`와 같은 파일 이름 패턴을 +가진 모든 소스 코드들의 로깅 레벨을 각각 2와 3으로 설정합니다. -또한 슬래시(`/`) 또는 백슬래시(`\`)를 포함하는 패턴은 지정한 경로에 대해 패턴을 테스트 합니다. -예를 들어 `*/foo/bar/*=2` 표현식은 `foo/bar` 디렉터리 안의 모든 소스 코드의 로깅 레벨을 2로 지정합니다. +또한 슬래시(`/`) 또는 백슬래시(`\`)를 포함하는 패턴은 지정한 경로에 대해 패턴을 테스트 +합니다. 예를 들어 `*/foo/bar/*=2` 표현식은 `foo/bar` 디렉터리 안의 모든 소스 코드의 +로깅 레벨을 2로 지정합니다. 이 스위치는 `--enable-logging` 스위치를 같이 지정해야 작동합니다. + +[app]: app.md +[append-switch]: app.md#appcommandlineappendswitchswitch-value +[ready]: app.md#event-ready diff --git a/docs-translations/ko-KR/api/clipboard.md b/docs-translations/ko-KR/api/clipboard.md index 01f1945856f3..2a0c98da2c09 100644 --- a/docs-translations/ko-KR/api/clipboard.md +++ b/docs-translations/ko-KR/api/clipboard.md @@ -1,13 +1,15 @@ # clipboard -`clipboard` 모듈은 복사/붙여넣기 작업을 수행하는 방법을 제공합니다. 다음 예제는 클립보드에 문자열을 씁니다: +`clipboard` 모듈은 복사/붙여넣기 작업을 수행하는 방법을 제공합니다. 다음 예제는 +클립보드에 문자열을 씁니다: ```javascript const clipboard = require('electron').clipboard; clipboard.writeText('Example String'); ``` -X Window 시스템에선 selection 클립보드도 존재합니다. 이를 사용하려면 인자 뒤에 `selection` 문자열을 같이 지정해주어야 합니다: +X Window 시스템에선 selection 클립보드도 존재합니다. 이를 사용하려면 인자 뒤에 +`selection` 문자열을 같이 지정해주어야 합니다: ```javascript clipboard.writeText('Example String', 'selection'); @@ -18,7 +20,8 @@ console.log(clipboard.readText('selection')); `clipboard` 모듈은 다음과 같은 메서드를 가지고 있습니다: -**참고:** Experimental 마크가 붙은 API는 실험적인 기능이며 차후 최신 버전에서 제거될 수 있습니다. +**참고:** Experimental 마크가 붙은 API는 실험적인 기능이며 차후 최신 버전에서 제거될 +수 있습니다. ### `clipboard.readText([type])` diff --git a/docs-translations/ko-KR/api/content-tracing.md b/docs-translations/ko-KR/api/content-tracing.md index f5f8b03d294a..ed73ce319f68 100644 --- a/docs-translations/ko-KR/api/content-tracing.md +++ b/docs-translations/ko-KR/api/content-tracing.md @@ -1,7 +1,9 @@ # contentTracing -`content-tracing` 모듈은 Chromium 컨텐츠 모듈단에서 생성된 데이터를 수집하고 추적하는데 사용됩니다. -이 모듈은 웹 인터페이스를 포함하고 있지 않으며 크롬 브라우저에서 `chrome://tracing/` 페이지를 열어 생성된 파일을 로드하면 결과를 볼 수 있습니다. +`content-tracing` 모듈은 Chromium 컨텐츠 모듈단에서 생성된 데이터를 수집하고 +추적하는데 사용됩니다. 이 모듈은 웹 인터페이스를 포함하고 있지 않으며 크롬 +브라우저에서 `chrome://tracing/` 페이지를 열어 생성된 파일을 로드하면 결과를 볼 수 +있습니다. ```javascript const contentTracing = require('electron').contentTracing; @@ -32,7 +34,8 @@ contentTracing.startRecording(options, function() { 카테고리 그룹 세트를 가져옵니다. 카테고리 그룹은 도달된 코드 경로를 변경할 수 있습니다. -모든 child 프로세스가 `getCategories` 요청을 승인하면 `callback`이 한 번 호출되며 인자에 카테고리 그룹의 배열이 전달됩니다. +모든 child 프로세스가 `getCategories` 요청을 승인하면 `callback`이 한 번 호출되며 +인자에 카테고리 그룹의 배열이 전달됩니다. ### `contentTracing.startRecording(options, callback)` @@ -43,12 +46,13 @@ contentTracing.startRecording(options, function() { 모든 프로세스에서 레코딩을 시작합니다. -레코딩은 지역적으로 즉시 실행됩니다. 그리고 비동기로 child 프로세스는 곧 EnableRecording 요청을 받게 됩니다. -모든 child 프로세스가 `startRecording` 요청을 승인하면 `callback`이 한 번 호출됩니다. +레코딩은 지역적으로 즉시 실행됩니다. 그리고 비동기로 child 프로세스는 곧 +EnableRecording 요청을 받게 됩니다. 모든 child 프로세스가 `startRecording` 요청을 +승인하면 `callback`이 한 번 호출됩니다. `categoryFilter`는 어떤 카테고리 그룹이 트레이싱 되어야 하는지 필터링할 수 있습니다. -필터는 `-` 접두사를 통해 특정 카테고리 그룹을 제외할 수 있습니다. -카테고리 패턴은 같은 리스트 내에서 포함과 제외를 함께 사용할 수 없습니다. +필터는 `-` 접두사를 통해 특정 카테고리 그룹을 제외할 수 있습니다. 카테고리 패턴은 같은 +리스트 내에서 포함과 제외를 함께 사용할 수 없습니다. 예제: @@ -56,7 +60,8 @@ contentTracing.startRecording(options, function() { * `test_MyTest*,test_OtherStuff`, * `"-excluded_category1,-excluded_category2` -`traceOptions`은 어떤 종류의 트레이싱을 사용할 수 있는지 지정하고 콤마로 리스트를 구분합니다. +`traceOptions`은 어떤 종류의 트레이싱을 사용할 수 있는지 지정하고 콤마로 리스트를 +구분합니다. 사용할 수 있는 옵션은 다음과 같습니다: @@ -67,12 +72,13 @@ contentTracing.startRecording(options, function() { * `enable-systrace` 첫번째부터 3번째까지의 옵션은 추적 레코딩 모드입니다. 이에 따라 상호 배타적입니다. -만약 레코딩 모드가 한 개 이상 지정되면 마지막 지정한 모드만 사용됩니다. -어떤 모드도 설정되지 않았다면 `record-until-full` 모드가 기본으로 사용됩니다. +만약 레코딩 모드가 한 개 이상 지정되면 마지막 지정한 모드만 사용됩니다. 어떤 모드도 +설정되지 않았다면 `record-until-full` 모드가 기본으로 사용됩니다. 추적 옵션은 `traceOptions`이 파싱되어 적용되기 전까지 다음과 같은 기본값이 사용됩니다. -`record-until-full`이 기본 모드, `enable-sampling`과 `enable-systrace`옵션은 포함되지 않음 +`record-until-full`이 기본 모드, `enable-sampling`과 `enable-systrace`옵션은 +포함되지 않음 ## `contentTracing.stopRecording(resultFilePath, callback)` @@ -81,15 +87,18 @@ contentTracing.startRecording(options, function() { 모든 프로세스에서 레코딩을 중지합니다. -Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시 그리고 추적 데이터를 메인 프로세스로 보내는 작업에 대해 캐싱 합니다. -이러한 일을 하는 이유는 IPC를 통해 추적 데이터를 보내는 작업은 매우 비싼 연산을 동반하기 때문입니다. -우리는 추적에 의한 런타임 오버헤드를 피하고자 합니다. -그래서 추적이 끝나면 모든 child 프로세스에 보류된 추적 데이터를 플러시 할 것인지 물어봅니다. +Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시 그리고 추적 데이터를 메인 +프로세스로 보내는 작업에 대해 캐싱 합니다. 이러한 일을 하는 이유는 IPC를 통해 추적 +데이터를 보내는 작업은 매우 비싼 연산을 동반하기 때문입니다. 우리는 추적에 의한 런타임 +오버헤드를 피하고자 합니다. 그래서 추적이 끝나면 모든 child 프로세스에 보류된 추적 +데이터를 플러시 할 것인지 물어봅니다. -모든 child 프로세스가 `stopRecording` 요청을 승인하면 `callback`에 추적 데이터 파일을 포함하여 한 번 호출됩니다. +모든 child 프로세스가 `stopRecording` 요청을 승인하면 `callback`에 추적 데이터 +파일을 포함하여 한 번 호출됩니다. -추적 데이터는 `resultFilePath` 해당 경로가 비어있는 경우에 한 해 해당 경로에 작성되거나 임시 파일에 작성됩니다. -실제 파일 경로는 null이 아닌 이상 `callback`을 통해 전달됩니다. +추적 데이터는 `resultFilePath` 해당 경로가 비어있는 경우에 한 해 해당 경로에 +작성되거나 임시 파일에 작성됩니다. 실제 파일 경로는 null이 아닌 이상 `callback`을 +통해 전달됩니다. ### `contentTracing.startMonitoring(options, callback)` @@ -100,7 +109,8 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시 모든 프로세스에서 모니터링을 시작합니다. -모니터링은 지역적으로 즉시 시작됩니다. 그리고 이내 자식 프로세스들이 `startMonitoring` 비동기 요청을 받습니다. +모니터링은 지역적으로 즉시 시작됩니다. 그리고 이내 자식 프로세스들이 +`startMonitoring` 비동기 요청을 받습니다. 모든 자식 프로세스가 `startMonitoring` 요청을 승인하면 `callback`이 한 번 호출됩니다. @@ -119,18 +129,21 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시 현재 모니터링 추적 데이터를 가져옵니다. -자식 프로세스들은 일반적으로 추적 데이터를 캐싱하며 드물게 플러시 하거나 메인 프로세스로 추적 데이터를 보냅니다. -왜냐하면 IPC를 통해 추적 데이터를 보내는데에는 많은 자원을 소비하기 때문입니다. -그리고 우리는 추적시 발생하는 불필요한 런타임 오버헤드를 피하고자 합니다. -그래서 추적이 끝나면 반드시 비동기로 자식 프로세스들의 보류된 추적 데이터를 플러시 할 것인지 물어봅니다. +자식 프로세스들은 일반적으로 추적 데이터를 캐싱하며 드물게 플러시 하거나 메인 +프로세스로 추적 데이터를 보냅니다. 왜냐하면 IPC를 통해 추적 데이터를 보내는데에는 +많은 자원을 소비하기 때문입니다. 그리고 우리는 추적시 발생하는 불필요한 런타임 +오버헤드를 피하고자 합니다. 그래서 추적이 끝나면 반드시 비동기로 자식 프로세스들의 +보류된 추적 데이터를 플러시 할 것인지 물어봅니다. -모든 자식 프로세스가 `captureMonitoringSnapshot` 요청을 승인하면 추적 데이터 파일을 포함하는 `callback`이 한 번 호출됩니다. +모든 자식 프로세스가 `captureMonitoringSnapshot` 요청을 승인하면 추적 데이터 파일을 +포함하는 `callback`이 한 번 호출됩니다. ### `contentTracing.getTraceBufferUsage(callback)` * `callback` Function -추적 버퍼 % 전체 상태의 프로세스간 최대치를 가져옵니다. TraceBufferUsage 값이 결정되면 `callback`이 한 번 호출됩니다. +추적 버퍼 % 전체 상태의 프로세스간 최대치를 가져옵니다. TraceBufferUsage 값이 +결정되면 `callback`이 한 번 호출됩니다. ### `contentTracing.setWatchEvent(categoryName, eventName, callback)` @@ -142,4 +155,5 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시 ### `contentTracing.cancelWatchEvent()` -Watch 이벤트를 중단합니다. 만약 추적이 활성화되어 있다면 이 메서드는 watch 이벤트 콜백과 race가 일어날 것입니다. +Watch 이벤트를 중단합니다. 만약 추적이 활성화되어 있다면 이 메서드는 watch 이벤트 +콜백과 race가 일어날 것입니다. diff --git a/docs-translations/ko-KR/api/crash-reporter.md b/docs-translations/ko-KR/api/crash-reporter.md index a5d29551571e..a4d42f013366 100644 --- a/docs-translations/ko-KR/api/crash-reporter.md +++ b/docs-translations/ko-KR/api/crash-reporter.md @@ -1,6 +1,7 @@ # crashReporter -`crash-reporter` 모듈은 어플리케이션의 크래시 정보를 자동으로 원격 서버에 업로드하는데 사용합니다. +`crash-reporter` 모듈은 어플리케이션의 크래시 정보를 자동으로 원격 서버에 +업로드하는데 사용합니다. 다음 예제는 윈격 서버에 어플리케이션 크래시 정보를 자동으로 보고하는 예제입니다: @@ -34,12 +35,13 @@ crashReporter.start({ * 크래시 리포트 시 같이 보낼 추가 정보를 지정하는 객체입니다. * 문자열로 된 속성만 정상적으로 보내집니다. * 중첩 객체는 지원되지 않습니다. (Nested objects are not supported) - + 다른 crashReporter API를 사용하기 전에 이 메서드를 먼저 호출해야 합니다. -**참고:** OS X에선 Windows와 Linux의 `breakpad`와 달리 새로운 `crashpad` 클라이언트를 사용합니다. -오류 수집 기능을 활성화 시키려면 오류를 수집하고 싶은 메인 프로세스나 랜더러 프로세스에서 -`crashReporter.start` 메서드를 호출하여 `crashpad`를 초기화 해야합니다. +**참고:** OS X에선 Windows와 Linux의 `breakpad`와 달리 새로운 `crashpad` +클라이언트를 사용합니다. 오류 수집 기능을 활성화 시키려면 오류를 수집하고 싶은 메인 +프로세스나 랜더러 프로세스에서 `crashReporter.start` 메서드를 호출하여 `crashpad`를 +초기화 해야합니다. ### `crashReporter.getLastCrashReport()` diff --git a/docs-translations/ko-KR/api/dialog.md b/docs-translations/ko-KR/api/dialog.md index e7e81240da0f..bb92c1f43e89 100644 --- a/docs-translations/ko-KR/api/dialog.md +++ b/docs-translations/ko-KR/api/dialog.md @@ -1,7 +1,8 @@ # dialog -`dialog` 모듈은 파일 열기, 알림과 같은 네이티브 시스템의 대화 상자를 조작할 때 사용할 수 있는 모듈입니다. -이 모듈을 사용하면 웹 어플리케이션에서 일반 네이티브 어플리케이션과 비슷한 사용자 경험을 제공할 수 있습니다. +`dialog` 모듈은 파일 열기, 알림과 같은 네이티브 시스템의 대화 상자를 조작할 때 사용할 +수 있는 모듈입니다. 이 모듈을 사용하면 웹 어플리케이션에서 일반 네이티브 어플리케이션과 +비슷한 사용자 경험을 제공할 수 있습니다. 다음 예제는 파일과 디렉터리를 다중으로 선택하는 대화 상자를 표시하는 예제입니다: @@ -11,7 +12,8 @@ const dialog = require('electron').dialog; console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]})); ``` -**OS X 알림**: 대화 상자를 시트처럼 보여지게 하려면 `browserWindow` 인자에 `BrowserWindow` 객체의 참조를 제공하면 됩니다. +**OS X 참고**: 대화 상자를 시트처럼 보여지게 하려면 `browserWindow` 인자에 +`BrowserWindow` 객체의 참조를 제공하면 됩니다. ## Methods @@ -25,15 +27,18 @@ console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', ' * `defaultPath` String * `filters` Array * `properties` Array - 대화 상자가 사용할 기능(모드)이 담긴 배열입니다. - 다음을 포함할 수 있습니다: `openFile`, `openDirectory`, `multiSelections`, `createDirectory` + 다음을 포함할 수 있습니다: `openFile`, `openDirectory`, `multiSelections`, + `createDirectory` * `callback` Function (optional) -사용할 대화 상자의 기능이 담긴 배열입니다. 다음을 포함할 수 있습니다: `openFile`, `openDirectory`, `multiSelections`, `createDirectory` +사용할 대화 상자의 기능이 담긴 배열입니다. 다음을 포함할 수 있습니다: `openFile`, +`openDirectory`, `multiSelections`, `createDirectory` -작업에 성공하면 콜백으로 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외엔 `undefined`를 반환합니다. +작업에 성공하면 콜백으로 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외의 +경우엔 `undefined`를 반환합니다. -`filters`를 지정하면 유저가 선택 가능한 파일 형식을 지정할 수 있습니다. -유저가 선택할 수 있는 타입에 제한을 두려면 다음과 같이 할 수 있습니다: +`filters`를 지정하면 유저가 선택 가능한 파일 형식을 지정할 수 있습니다. 유저가 선택할 +수 있는 타입에 제한을 두려면 다음과 같이 할 수 있습니다: ```javascript { @@ -46,14 +51,17 @@ console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', ' } ``` -`extensions` 배열은 반드시 와일드카드와 마침표를 제외한 파일 확장자를 포함시켜야 합니다. -(예를 들어 `'png'`는 가능하지만 `'.png'`와 `'*.png'`는 안됩니다) -모든 파일을 보여주려면 `'*'`와 같은 와일드카드를 사용하면 됩니다. (다른 와일드카드는 지원하지 않습니다) +`extensions` 배열은 반드시 와일드카드와 마침표를 제외한 파일 확장자를 포함시켜야 +합니다. (예를 들어 `'png'`는 가능하지만 `'.png'`와 `'*.png'`는 안됩니다) 모든 파일을 +보여주려면 `'*'`와 같은 와일드카드를 사용하면 됩니다. (다른 와일드카드는 지원하지 + 않습니다) -`callback`이 전달되면 메소드가 비동기로 작동되며 결과는 `callback(filenames)`을 통해 전달됩니다. +`callback`이 전달되면 메서드가 비동기로 작동되며 결과는 `callback(filenames)`을 +통해 전달됩니다. -**참고:** Windows와 Linux에선 파일 선택 모드, 디렉터리 선택 모드를 동시에 사용할 수 없습니다. -이러한 이유로 `properties`를 `['openFile', 'openDirectory']`로 설정하면 디렉터리 선택 대화 상자가 표시됩니다. +**참고:** Windows와 Linux에선 파일 선택 모드, 디렉터리 선택 모드를 동시에 사용할 수 +없습니다. 이러한 이유로 `properties`를 `['openFile', 'openDirectory']`로 설정하면 +디렉터리 선택 대화 상자가 표시됩니다. ### `dialog.showSaveDialog([browserWindow][, options][, callback])` @@ -64,43 +72,52 @@ console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', ' * `filters` Array * `callback` Function (optional) -작업에 성공하면 콜백으로 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외엔 `undefined`를 반환합니다. +작업에 성공하면 콜백으로 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외엔 +`undefined`를 반환합니다. -`filters`를 지정하면 유저가 저장 가능한 파일 형식을 지정할 수 있습니다. 사용 방법은 `dialog.showOpenDialog`의 `filters` 속성과 같습니다. +`filters`를 지정하면 유저가 저장 가능한 파일 형식을 지정할 수 있습니다. 사용 방법은 +`dialog.showOpenDialog`의 `filters` 속성과 같습니다. -`callback`이 전달되면 메소드가 비동기로 작동되며 결과는 `callback(filename)`을 통해 전달됩니다. +`callback`이 전달되면 메서드가 비동기로 작동되며 결과는 `callback(filename)`을 통해 전달됩니다. ### `dialog.showMessageBox([browserWindow][, options][, callback])` * `browserWindow` BrowserWindow * `options` Object - * `type` String - `"none"`, `"info"`, `"error"`, `"question"`, `"warning"` 중 하나를 사용할 수 있습니다. - Windows에선 따로 `icon`을 설정하지 않은 이상 "question"과 "info"는 같은 아이콘으로 표시됩니다. + * `type` String - `"none"`, `"info"`, `"error"`, `"question"`, `"warning"` 중 + 하나를 사용할 수 있습니다. Windows에선 따로 `icon`을 설정하지 않은 이상 + "question"과 "info"는 같은 아이콘으로 표시됩니다. * `buttons` Array - 버튼들의 라벨을 포함한 배열입니다. * `title` String - 대화 상자의 제목입니다. 몇몇 플랫폼에선 보이지 않을 수 있습니다. * `message` String - 대화 상자의 본문 내용입니다. * `detail` String - 메시지의 추가 정보입니다. * `icon` [NativeImage](native-image.md) - * `cancelId` Integer - 유저가 대화 상자의 버튼을 클릭하지 않고 대화 상자를 취소했을 때 반환되는 버튼의 인덱스입니다. - 기본적으로 버튼 리스트가 "cancel" 또는 "no" 라벨을 가지고 있을 때 해당 버튼의 인덱스를 반환합니다. 따로 두 라벨이 지정되지 않은 경우 0을 반환합니다. - OS X와 Windows에선 `cancelId` 지정 여부에 상관없이 "Cancel" 버튼이 언제나 `cancelId`로 지정됩니다. - * `noLink` Boolean - Windows Electron은 "Cancel"이나 "Yes"와 같은 흔히 사용되는 버튼을 찾으려고 시도하고 - 대화 상자 내에서 해당 버튼을 커맨드 링크처럼 만듭니다. 이 기능으로 앱을 좀 더 Modern Windows 앱처럼 만들 수 있습니다. - 이 기능을 원하지 않으면 `noLink`를 true로 지정하면 됩니다. + * `cancelId` Integer - 유저가 대화 상자의 버튼을 클릭하지 않고 대화 상자를 취소했을 + 때 반환되는 버튼의 인덱스입니다. 기본적으로 버튼 리스트가 "cancel" 또는 "no" + 라벨을 가지고 있을 때 해당 버튼의 인덱스를 반환합니다. 따로 두 라벨이 지정되지 + 않은 경우 0을 반환합니다. OS X와 Windows에선 `cancelId` 지정 여부에 상관없이 + "Cancel" 버튼이 언제나 `cancelId`로 지정됩니다. + * `noLink` Boolean - Windows Electron은 "Cancel"이나 "Yes"와 같은 흔히 사용되는 + 버튼을 찾으려고 시도하고 대화 상자 내에서 해당 버튼을 커맨드 링크처럼 만듭니다. + 이 기능으로 앱을 좀 더 Modern Windows 앱처럼 만들 수 있습니다. 이 기능을 원하지 + 않으면 `noLink`를 true로 지정하면 됩니다. * `callback` Function -대화 상자를 표시합니다. `browserWindow`를 지정하면 대화 상자가 완전히 닫힐 때까지 지정한 창을 사용할 수 없습니다. -완료 시 유저가 선택한 버튼의 인덱스를 반환합니다. +대화 상자를 표시합니다. `browserWindow`를 지정하면 대화 상자가 완전히 닫힐 때까지 +지정한 창을 사용할 수 없습니다. 완료 시 유저가 선택한 버튼의 인덱스를 반환합니다. -역주: 부정을 표현하는 "아니오", "취소"와 같은 한글 단어는 지원되지 않습니다. -만약 OS X 또는 Windows에서 "확인", "취소"와 같은 순서로 버튼을 지정하게 될 때 Alt + f4로 해당 대화 상자를 끄게 되면 "확인"을 누른 것으로 판단되어 버립니다. -이를 해결하려면 "Cancel"을 대신 사용하거나 BrowserWindow API를 사용하여 대화 상자를 직접 구현해야합니다. +역주: 부정을 표현하는 "아니오", "취소"와 같은 한글 단어는 지원되지 않습니다. 만약 +OS X 또는 Windows에서 "확인", "취소"와 같은 순서로 버튼을 지정하게 될 때 Alt + f4로 +해당 대화 상자를 끄게 되면 "확인"을 누른 것으로 판단되어 버립니다. 이를 해결하려면 +"Cancel"을 대신 사용하거나 BrowserWindow API를 사용하여 대화 상자를 직접 구현해야 +합니다. -`callback`이 전달되면 메소드가 비동기로 작동되며 결과는 `callback(response)`을 통해 전달됩니다. +`callback`이 전달되면 메서드가 비동기로 작동되며 결과는 `callback(response)`을 통해 +전달됩니다. ### `dialog.showErrorBox(title, content)` 에러 메시지를 보여주는 대화 상자를 표시합니다. -이 API는 `app` 모듈의 `ready` 이벤트가 발생하기 전에 사용할 수 있습니다. -이 메소드는 보통 어플리케이션이 시작되기 전에 특정한 에러를 표시하기 위해 사용됩니다. +이 API는 `app` 모듈의 `ready` 이벤트가 발생하기 전에 사용할 수 있습니다. 이 메서드는 +보통 어플리케이션이 시작되기 전에 특정한 에러를 표시하기 위해 사용됩니다. diff --git a/docs-translations/ko-KR/api/download-item.md b/docs-translations/ko-KR/api/download-item.md index 95a00c857533..a367d0e000bd 100644 --- a/docs-translations/ko-KR/api/download-item.md +++ b/docs-translations/ko-KR/api/download-item.md @@ -1,8 +1,8 @@ # DownloadItem `DownloadItem`은 EventEmitter를 상속받았으며 Electron의 다운로드 아이템을 표현합니다. -이 클래스 객체는 `Session` 모듈의 `will-download` 이벤트에 사용되며 -사용자가 다운로드 아이템을 다룰 수 있도록 도와줍니다. +이 클래스 객체는 `Session` 모듈의 `will-download` 이벤트에 사용되며 사용자가 다운로드 +아이템을 다룰 수 있도록 도와줍니다. ```javascript // 메인 프로세스 @@ -38,9 +38,9 @@ win.webContents.session.on('will-download', function(event, item, webContents) { * `cancelled` - 다운로드가 취소되었습니다. * `interrupted` - 다운로드 중 파일 서버로부터의 연결이 끊겼습니다. -다운로드가 종료될 때 발생하는 이벤트입니다. -이 이벤트는 다운로드 중 문제가 발생하여 중단되거나, 모두 성공적으로 완료된 경우, -`downloadItem.cancel()` 같은 메서드를 통해 취소하는 경우의 종료 작업이 모두 포함됩니다. +다운로드가 종료될 때 발생하는 이벤트입니다. 이 이벤트는 다운로드 중 문제가 발생하여 +중단되거나, 모두 성공적으로 완료된 경우, `downloadItem.cancel()` 같은 메서드를 통해 +취소하는 경우의 종료 작업이 모두 포함됩니다. ## Methods @@ -50,8 +50,9 @@ win.webContents.session.on('will-download', function(event, item, webContents) { * `path` String - 다운로드 아이템을 저장할 파일 경로를 지정합니다. -이 API는 세션의 `will-download` 콜백 함수에서만 사용할 수 있습니다. -사용자가 API를 통해 아무 경로도 설정하지 않을 경우 Electron은 기본 루틴 파일 저장을 실행합니다. (파일 대화 상자를 엽니다) +이 API는 세션의 `will-download` 콜백 함수에서만 사용할 수 있습니다. 사용자가 API를 +통해 아무 경로도 설정하지 않을 경우 Electron은 기본 루틴 파일 저장을 실행합니다. +(파일 대화 상자를 엽니다) ### `downloadItem.pause()` @@ -81,12 +82,14 @@ win.webContents.session.on('will-download', function(event, item, webContents) { 다운로드 아이템의 파일 이름을 표현하는 문자열을 반환합니다. -**참고:** 실제 파일 이름과 로컬 디스크에 저장되는 파일의 이름은 서로 다를 수 있습니다. 예를 들어 -만약 사용자가 파일을 저장할 때 파일 이름을 바꿨다면 실제 파일 이름과 저장 파일 이름은 서로 달라지게 됩니다. +**참고:** 실제 파일 이름과 로컬 디스크에 저장되는 파일의 이름은 서로 다를 수 있습니다. +예를 들어 만약 사용자가 파일을 저장할 때 파일 이름을 바꿨다면 실제 파일 이름과 저장 +파일 이름은 서로 달라지게 됩니다. ### `downloadItem.getTotalBytes()` -현재 아이템의 전체 다운로드 크기를 정수로 반환합니다. 크기가 unknown이면 0을 반환합니다. +현재 아이템의 전체 다운로드 크기를 정수로 반환합니다. 크기가 unknown이면 0을 +반환합니다. ### `downloadItem.getReceivedBytes()` diff --git a/docs-translations/ko-KR/api/file-object.md b/docs-translations/ko-KR/api/file-object.md index 6006220647dd..a2a19a530d4a 100644 --- a/docs-translations/ko-KR/api/file-object.md +++ b/docs-translations/ko-KR/api/file-object.md @@ -1,8 +1,8 @@ # `File` 객체 -DOM의 File 인터페이스는 네이티브 파일을 추상화 합니다. -유저가 직접 HTML5 File API를 이용하여 작업할 때 선택된 파일의 경로를 알 수 있도록 -Electron은 파일의 실제 경로를 담은 `path` 속성을 File 인터페이스에 추가하였습니다. +DOM의 File 인터페이스는 네이티브 파일을 추상화 합니다. 유저가 직접 HTML5 File API를 +이용하여 작업할 때 선택된 파일의 경로를 알 수 있도록 Electron은 파일의 실제 경로를 +담은 `path` 속성을 File 인터페이스에 추가하였습니다. 다음 예제는 앱으로 드래그 앤 드롭한 파일의 실제 경로를 가져옵니다: diff --git a/docs-translations/ko-KR/api/frameless-window.md b/docs-translations/ko-KR/api/frameless-window.md index a10cba190937..e13794e0fdfd 100644 --- a/docs-translations/ko-KR/api/frameless-window.md +++ b/docs-translations/ko-KR/api/frameless-window.md @@ -1,12 +1,14 @@ # Frameless Window -Frameless Window는 [창 테두리](https://developer.mozilla.org/en-US/docs/Glossary/Chrome)가 없는 윈도우를 말합니다. -이 기능은 윈도우 창의 일부분인 툴바와 같이 웹 페이지의 일부분이 아닌 부분을 보이지 않도록 합니다. -[`BrowserWindow`](browser-window.md) 클래스의 옵션에서 설정할 수 있습니다. +Frameless Window는 [창 테두리](https://developer.mozilla.org/en-US/docs/Glossary/Chrome)가 +없는 윈도우를 말합니다. 이 기능은 윈도우 창의 일부분인 툴바와 같이 웹 페이지의 일부분이 +아닌 부분을 보이지 않도록 합니다. [`BrowserWindow`](browser-window.md) 클래스의 +옵션에서 설정할 수 있습니다. ## Frameless Window 만들기 -Frameless Window를 만드려면 [BrowserWindow](browser-window.md) 객체의 `options`에서 `frame` 옵션을 `false`로 지정하면 됩니다: +Frameless Window를 만드려면 [BrowserWindow](browser-window.md) 객체의 +`options` 객체에서 `frame` 옵션을 `false`로 지정하면 됩니다: ```javascript const BrowserWindow = require('electron').BrowserWindow; @@ -15,9 +17,10 @@ var win = new BrowserWindow({ width: 800, height: 600, frame: false }); ### 최신 OS X에서 사용할 수 있는 대안 -OS X 10.10 Yosemite 이후의 최신 버전부터는 테두리가 없는 창을 만들 때 새로운 방법을 사용할 수 있습니다. -`frame` 옵션을 `false`로 지정하여 제목과 창 구성 요소를 모두 비활성화하는 대신 새로운 `title-bar-style` -옵션을 통해 제목만 숨기고 창 구성 요소("흔히 신호등으로 알고 있는")의 기능과 창 크기를 그대로 유지할 수 있습니다: +OS X 10.10 Yosemite 이후의 최신 버전부터는 테두리가 없는 창을 만들 때 새로운 방법을 +사용할 수 있습니다. `frame` 옵션을 `false`로 지정하여 제목과 창 구성 요소를 모두 +비활성화하는 대신 새로운 `title-bar-style` 옵션을 통해 제목만 숨기고 창 구성 요소 +("흔히 신호등으로 알고 있는")의 기능과 창 크기를 그대로 유지할 수 있습니다: ```javascript var win = new BrowserWindow({ 'title-bar-style': 'hidden' }); @@ -25,7 +28,8 @@ var win = new BrowserWindow({ 'title-bar-style': 'hidden' }); ## 투명한 창 만들기 -Frameless Window 창의 배경을 투명하게 만들고 싶다면 `transparent` 옵션을 `true`로 바꿔주기만 하면됩니다: +Frameless Window 창의 배경을 투명하게 만들고 싶다면 `transparent` 옵션을 `true`로 +바꿔주기만 하면됩니다: ```javascript var win = new BrowserWindow({ transparent: true, frame: false }); @@ -33,30 +37,38 @@ var win = new BrowserWindow({ transparent: true, frame: false }); ### API의 한계 -* 투명한 영역을 통과하여 클릭할 수 없습니다. 우리는 이 문제를 해결하기 위해 API를 제공할 예정이었지만 현재로써는 - [upstream 버그](https://code.google.com/p/chromium/issues/detail?id=387234)로 인해 중단된 상태입니다. -* 투명한 창은 크기를 조절할 수 없습니다. `resizable` 속성을 `true`로 할 경우 몇몇 플랫폼에선 크래시가 일어납니다. -* `blur` 필터는 웹 페이지에서만 적용됩니다. 윈도우 아래 컨텐츠에는 블러 효과를 적용할 방법이 없습니다. (예시: 유저의 시스템에 열린 다른 어플리케이션) -* Windows에선 DWM(데스크톱 창 관리자)가 비활성화되어 있을 경우 투명한 창이 작동하지 않습니다. +* 투명한 영역을 통과하여 클릭할 수 없습니다. 우리는 이 문제를 해결하기 위해 API를 + 제공할 예정이었지만 현재로써는 [upstream 버그](https://code.google.com/p/chromium/issues/detail?id=387234)로 + 인해 중단된 상태입니다. +* 투명한 창은 크기를 조절할 수 없습니다. `resizable` 속성을 `true`로 할 경우 몇몇 + 플랫폼에선 크래시가 일어납니다. +* `blur` 필터는 웹 페이지에서만 적용됩니다. 윈도우 아래 컨텐츠에는 블러 효과를 적용할 + 방법이 없습니다. (예시: 유저의 시스템에 열린 다른 어플리케이션) +* Windows에선 DWM(데스크톱 창 관리자)가 비활성화되어 있을 경우 투명한 창이 작동하지 + 않습니다. * Linux를 사용할 경우 [alpha channel doesn't work on some NVidia drivers](https://code.google.com/p/chromium/issues/detail?id=369209) - upstream 버그가 있는 관계로 투명한 창 기능을 사용하려면 CLI 옵션에 `--enable-transparent-visuals --disable-gpu`을 추가해야 합니다. - 이 옵션은 GPU의 사용을 중단하고 윈도우를 생성하는데 ARGB를 사용할 수 있도록 해줍니다. + upstream 버그가 있는 관계로 투명한 창 기능을 사용하려면 CLI 옵션에 + `--enable-transparent-visuals --disable-gpu`을 추가해야 합니다. 이 옵션은 GPU의 + 사용을 중단하고 윈도우를 생성하는데 ARGB를 사용할 수 있도록 해줍니다. * OS X(Mac)에선 네이티브 창에서 보여지는 그림자가 투명한 창에선 보이지 않습니다. ## 드래그 가능 위치 지정 -기본적으로 Frameless Window는 드래그 할 수 없습니다. -어플리케이션의 CSS에서 특정 범위를 `-webkit-app-region: drag`로 지정하면 OS의 기본 타이틀 바 처럼 드래그 되도록 할 수 있습니다. -그리고 `-webkit-app-region: no-drag`를 지정해서 드래그 불가능 영역을 만들 수도 있습니다. 현재 사각형 형태의 범위만 지원합니다. +기본적으로 Frameless Window는 드래그 할 수 없습니다. 어플리케이션의 CSS에서 특정 +범위를 `-webkit-app-region: drag`로 지정하면 OS의 기본 타이틀 바 처럼 드래그 되도록 +할 수 있습니다. 그리고 `-webkit-app-region: no-drag`를 지정해서 드래그 불가능 영역을 +만들 수도 있습니다. 현재 사각형 형태의 범위만 지원합니다. -창 전체를 드래그 가능하게 만드려면 `-webkit-app-region: drag`을 `body`의 스타일에 지정하면 됩니다: +창 전체를 드래그 가능하게 만드려면 `-webkit-app-region: drag`을 `body`의 스타일에 +지정하면 됩니다: ```html ``` -참고로 창 전체를 드래그 영역으로 지정할 경우 사용자가 버튼을 클릭할 수 없게 되므로 버튼은 드래그 불가능 영역으로 지정해야 합니다: +참고로 창 전체를 드래그 영역으로 지정할 경우 사용자가 버튼을 클릭할 수 없게 되므로 +버튼은 드래그 불가능 영역으로 지정해야 합니다: ```css button { @@ -64,13 +76,15 @@ button { } ``` -따로 커스텀 타이틀 바를 만들어 사용할 때는 타이틀 바 내부의 모든 버튼을 드래그 불가능 영역으로 지정해야 합니다. +따로 커스텀 타이틀 바를 만들어 사용할 때는 타이틀 바 내부의 모든 버튼을 드래그 불가 +영역으로 지정해야 합니다. ## 텍스트 선택 -Frameless Window에서 텍스트가 선택되는 드래그 동작은 혼란을 야기할 수 있습니다. -예를 들어 타이틀 바를 드래그 할 때 타이틀 바의 텍스트를 실수로 선택할 수 있습니다. -이를 방지하기 위해 다음과 같이 드래그 영역의 텍스트 선택 기능을 비활성화해야 할 필요가 있습니다: +Frameless Window에서 텍스트가 선택되는 드래그 동작은 혼란을 야기할 수 있습니다. 예를 +들어 타이틀 바를 드래그 할 때 타이틀 바의 텍스트를 실수로 선택할 수 있습니다. 이를 +방지하기 위해 다음과 같이 드래그 영역의 텍스트 선택 기능을 비활성화해야 할 필요가 +있습니다: ```css .titlebar { @@ -81,5 +95,7 @@ Frameless Window에서 텍스트가 선택되는 드래그 동작은 혼란을 ## 컨텍스트 메뉴 -몇몇 플랫폼에선 드래그 가능 영역이 non-client 프레임으로 처리됩니다. 이러한 플랫폼에선 드래그 가능 영역에서 오른쪽 클릭 할 경우 시스템 메뉴가 팝업 됩니다. -이러한 이유로 컨텍스트 메뉴 지정 시 모든 플랫폼에서 정상적으로 작동하게 하려면 커스텀 컨텍스트 메뉴를 드래그 영역 내에 만들어선 안됩니다. +몇몇 플랫폼에선 드래그 가능 영역이 non-client 프레임으로 처리됩니다. 이러한 플랫폼에선 +드래그 가능 영역에서 오른쪽 클릭 할 경우 시스템 메뉴가 팝업 됩니다. 이러한 이유로 +컨텍스트 메뉴 지정 시 모든 플랫폼에서 정상적으로 작동하게 하려면 커스텀 컨텍스트 메뉴를 +드래그 영역 내에 만들어선 안됩니다. diff --git a/docs-translations/ko-KR/api/global-shortcut.md b/docs-translations/ko-KR/api/global-shortcut.md index 2120f73cc5cb..1b8363bcbe70 100644 --- a/docs-translations/ko-KR/api/global-shortcut.md +++ b/docs-translations/ko-KR/api/global-shortcut.md @@ -1,10 +1,12 @@ # global-shortcut -`global-shortcut` 모듈은 운영체제의 전역 키보드 단축키를 등록/해제 하는 방법을 제공합니다. -이 모듈을 사용하여 사용자가 다양한 작업을 편하게 할 수 있도록 단축키를 정의 할 수 있습니다. +`global-shortcut` 모듈은 운영체제의 전역 키보드 단축키를 등록/해제 하는 방법을 +제공합니다. 이 모듈을 사용하여 사용자가 다양한 작업을 편하게 할 수 있도록 단축키를 +정의 할 수 있습니다. -**참고:** 등록된 단축키는 어플리케이션이 백그라운드로 작동(창이 포커스 되지 않음) 할 때도 계속해서 작동합니다. -이 모듈은 `app` 모듈의 `ready` 이벤트 이전에 사용할 수 없습니다. +**참고:** 등록된 단축키는 어플리케이션이 백그라운드로 작동(창이 포커스 되지 않음) 할 +때도 계속해서 작동합니다. 이 모듈은 `app` 모듈의 `ready` 이벤트 이전에 사용할 수 +없습니다. ```javascript const electron = require('electron'); @@ -43,13 +45,15 @@ app.on('will-quit', function() { * `accelerator` [Accelerator](accelerator.md) * `callback` Function -`accelerator`로 표현된 전역 단축키를 등록합니다. 유저로부터 등록된 단축키가 눌렸을 경우 `callback` 함수가 호출됩니다. +`accelerator`로 표현된 전역 단축키를 등록합니다. 유저로부터 등록된 단축키가 눌렸을 +경우 `callback` 함수가 호출됩니다. ### `globalShortcut.isRegistered(accelerator)` * `accelerator` [Accelerator](accelerator.md) -지정된 `accelerator` 단축키가 등록되었는지 여부를 확인합니다. 반환값은 boolean(true, false) 입니다. +지정된 `accelerator` 단축키가 등록되었는지 여부를 확인합니다. 반환값은 boolean값 +입니다. ### `globalShortcut.unregister(accelerator)` diff --git a/docs-translations/ko-KR/api/ipc-main.md b/docs-translations/ko-KR/api/ipc-main.md index fae8aa4d5cf6..2dffcaf79ab1 100644 --- a/docs-translations/ko-KR/api/ipc-main.md +++ b/docs-translations/ko-KR/api/ipc-main.md @@ -1,12 +1,14 @@ # ipcMain -`ipcMain` 모듈은 메인 프로세스에서 사용할 때 랜더러 프로세스(웹 페이지)에서 전달된 동기/비동기 메시지를 주고 받는 방법을 제공합니다. -랜더러 프로세스에서 메시지를 전달하면 이 모듈을 통해 메시지를 받을 수 있습니다. +`ipcMain` 모듈은 메인 프로세스에서 사용할 때 랜더러 프로세스(웹 페이지)에서 전달된 +동기/비동기 메시지를 주고 받는 방법을 제공합니다. 랜더러 프로세스에서 메시지를 전달하면 +이 모듈을 통해 메시지를 받을 수 있습니다. ## 메시지 전송 물론 메시지를 받는 것 말고도 메인 프로세스에서 랜더러 프로세스로 보내는 것도 가능합니다. -자세한 내용은 [webContents.send](web-contents.md#webcontentssendchannel-args)를 참고하세요. +자세한 내용은 [webContents.send](web-contents.md#webcontentssendchannel-args)를 +참고하세요. * 메시지를 전송할 때 이벤트 이름은 `channel`이 됩니다. * 메시지에 동기로 응답할 땐 반드시 `event.returnValue`를 설정해야 합니다. @@ -60,7 +62,8 @@ ipc.send('asynchronous-message', 'ping'); ### `Event.sender` -메시지를 보낸 `webContents` 객체를 반환합니다. `event.sender.send` 메서드를 통해 비동기로 메시지를 전달할 수 있습니다. -자세한 내용은 [webContents.send][webcontents-send]를 참고하세요. +메시지를 보낸 `webContents` 객체를 반환합니다. `event.sender.send` 메서드를 통해 +비동기로 메시지를 전달할 수 있습니다. 자세한 내용은 +[webContents.send][webcontents-send]를 참고하세요. [webcontents-send]: web-contents.md#webcontentssendchannel-args diff --git a/docs-translations/ko-KR/api/ipc-renderer.md b/docs-translations/ko-KR/api/ipc-renderer.md index 28442a29073a..e3b646b42a27 100644 --- a/docs-translations/ko-KR/api/ipc-renderer.md +++ b/docs-translations/ko-KR/api/ipc-renderer.md @@ -1,7 +1,7 @@ # ipcRenderer -`ipcRenderer` 모듈은 랜더러 프로세스에서 메인 프로세스로 동기/비동기 메시지를 주고 받는 방법을 제공합니다. -또한 메인 프로세스로부터 받은 메시지에 응답할 수도 있습니다. +`ipcRenderer` 모듈은 랜더러 프로세스에서 메인 프로세스로 동기/비동기 메시지를 주고 +받는 방법을 제공합니다. 또한 메인 프로세스로부터 받은 메시지에 응답할 수도 있습니다. [ipcMain](ipc-main.md)에서 코드 예제를 확인할 수 있습니다. @@ -25,24 +25,29 @@ * `channel` String - 이벤트 이름 * `arg` (optional) -`channel`을 통해 메인 프로세스에 비동기 메시지를 보냅니다. 그리고 필요에 따라 임의의 인자를 사용할 수도 있습니다. -메인 프로세스는 `ipcMain` 모듈의 `channel` 이벤트를 통해 이벤트를 리스닝 할 수 있습니다. +`channel`을 통해 메인 프로세스에 비동기 메시지를 보냅니다. 그리고 필요에 따라 임의의 +인자를 사용할 수도 있습니다. 메인 프로세스는 `ipcMain` 모듈의 `channel` 이벤트를 통해 +이벤트를 리스닝 할 수 있습니다. ### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])` * `channel` String - 이벤트 이름 * `arg` (optional) -`channel`을 통해 메인 프로세스에 동기 메시지를 보냅니다. 그리고 필요에 따라 임의의 인자를 사용할 수도 있습니다. -메인 프로세스는 `ipc`를 통해 `channel` 이벤트를 리스닝 할 수 있습니다. +`channel`을 통해 메인 프로세스에 동기 메시지를 보냅니다. 그리고 필요에 따라 임의의 +인자를 사용할 수도 있습니다. 메인 프로세스는 `ipc`를 통해 `channel` 이벤트를 리스닝 +할 수 있습니다. -메인 프로세스에선 `ipc` 모듈의 `channel` 이벤트를 통해 받은 `event.returnValue`로 회신 할 수 있습니다. +메인 프로세스에선 `ipc` 모듈의 `channel` 이벤트를 통해 받은 `event.returnValue`로 +회신 할 수 있습니다. -__참고:__ 동기 메서드는 모든 랜더러 프로세스의 작업을 일시 중단시킵니다. 사용 목적이 확실하지 않다면 사용하지 않는 것이 좋습니다. +__참고:__ 동기 메서드는 모든 랜더러 프로세스의 작업을 일시 중단시킵니다. 사용 목적이 +확실하지 않다면 사용하지 않는 것이 좋습니다. ### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])` * `channel` String - 이벤트 이름 * `arg` (optional) -`ipcRenderer.send`와 비슷하지만 이벤트를 메인 프로세스 대신 호스트 페이지내의 `` 요소로 보냅니다. +`ipcRenderer.send`와 비슷하지만 이벤트를 메인 프로세스 대신 호스트 페이지내의 +`` 요소로 보냅니다. diff --git a/docs-translations/ko-KR/api/menu-item.md b/docs-translations/ko-KR/api/menu-item.md index dfcc4fcb2413..388df1c7d571 100644 --- a/docs-translations/ko-KR/api/menu-item.md +++ b/docs-translations/ko-KR/api/menu-item.md @@ -1,6 +1,7 @@ # MenuItem -`menu-item` 모듈은 어플리케이션 또는 컨텍스트 [`menu`](menu.md)에 항목 아이템을 추가할 수 있도록 관련 클래스를 제공합니다. +`menu-item` 모듈은 어플리케이션 또는 컨텍스트 [`menu`](menu.md)에 항목 아이템을 +추가할 수 있도록 관련 클래스를 제공합니다. [`menu`](menu.md)에서 예제를 확인할 수 있습니다. @@ -11,9 +12,12 @@ ### new MenuItem(options) * `options` Object - * `click` Function - 메뉴 아이템이 클릭될 때 `click(menuItem, browserWindow)` 형태로 호출 되는 콜백 함수 - * `role` String - 메뉴 아이템의 액션을 정의합니다. 이 속성을 지정하면 `click` 속성이 무시됩니다. - * `type` String - `MenuItem`의 타입 `normal`, `separator`, `submenu`, `checkbox` 또는 `radio` 사용가능 + * `click` Function - 메뉴 아이템이 클릭될 때 `click(menuItem, browserWindow)` + 형태로 호출 되는 콜백 함수 + * `role` String - 메뉴 아이템의 액션을 정의합니다. 이 속성을 지정하면 `click` + 속성이 무시됩니다. + * `type` String - `MenuItem`의 타입 `normal`, `separator`, `submenu`, + `checkbox` 또는 `radio` 사용가능 * `label` String * `sublabel` String * `accelerator` [Accelerator](accelerator.md) @@ -21,11 +25,15 @@ * `enabled` Boolean * `visible` Boolean * `checked` Boolean - * `submenu` Menu - 보조메뉴를 설정합니다. `type`이 `submenu`일 경우 반드시 설정해야합니다. 일반 메뉴 아이템일 경우 생략할 수 있습니다. - * `id` String - 현재 메뉴 아이템에 대해 유일키를 지정합니다. 이 키는 이후 `position` 옵션에서 사용할 수 있습니다. - * `position` String - 미리 지정한 `id`를 이용하여 메뉴 아이템의 위치를 세밀하게 조정합니다. + * `submenu` Menu - 보조메뉴를 설정합니다. `type`이 `submenu`일 경우 반드시 + 설정해야 합니다. 일반 메뉴 아이템일 경우 생략할 수 있습니다. + * `id` String - 현재 메뉴 아이템에 대해 유일키를 지정합니다. 이 키는 이후 + `position` 옵션에서 사용할 수 있습니다. + * `position` String - 미리 지정한 `id`를 이용하여 메뉴 아이템의 위치를 세밀하게 + 조정합니다. -메뉴 아이템을 생성할 때, 다음 목록과 일치하는 표준 동작은 수동으로 직접 구현하는 대신 `role` 속성을 지정하여 고유 OS 경험을 최대한 살릴 수 있습니다. +메뉴 아이템을 생성할 때, 다음 목록과 일치하는 표준 동작은 수동으로 직접 구현하는 대신 +`role` 속성을 지정하여 고유 OS 경험을 최대한 살릴 수 있습니다. `role` 속성은 다음 값을 가질 수 있습니다: diff --git a/docs-translations/ko-KR/api/menu.md b/docs-translations/ko-KR/api/menu.md index d55fa807a362..3c5740de53a4 100644 --- a/docs-translations/ko-KR/api/menu.md +++ b/docs-translations/ko-KR/api/menu.md @@ -1,12 +1,14 @@ # Menu -`menu` 클래스는 어플리케이션 메뉴와 [컨텍스트 메뉴](https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/PopupGuide/ContextMenus)를 만들 때 사용됩니다. -이 모듈은 메인 프로세스용 모듈이지만 `remote` 모듈을 통해 랜더러 프로세스에서도 사용할 수 있습니다. +`menu` 클래스는 어플리케이션 메뉴와 [컨텍스트 메뉴](https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/PopupGuide/ContextMenus)를 +만들 때 사용됩니다. 이 모듈은 메인 프로세스용 모듈이지만 `remote` 모듈을 통해 랜더러 +프로세스에서도 사용할 수 있습니다. 각 메뉴는 여러 개의 [메뉴 아이템](menu-item.md)으로 구성되고 서브 메뉴를 가질 수도 있습니다. -다음 예제는 웹 페이지 내에서 [remote](remote.md) 모듈을 활용하여 동적으로 메뉴를 생성하는 예제입니다. -그리고 유저가 페이지에서 오른쪽 클릭을 할 때마다 마우스 위치에 팝업 형태로 메뉴를 표시합니다: +다음 예제는 웹 페이지 내에서 [remote](remote.md) 모듈을 활용하여 동적으로 메뉴를 +생성하는 예제입니다. 그리고 유저가 페이지에서 오른쪽 클릭을 할 때마다 마우스 위치에 +팝업 형태로 메뉴를 표시합니다: ```html @@ -27,7 +29,8 @@ window.addEventListener('contextmenu', function (e) { ``` -또 하나의 예를 들자면 다음 예제는 랜더러 프로세스에서 template API를 사용하여 어플리케이션 메뉴를 만듭니다: +또 하나의 예를 들자면 다음 예제는 랜더러 프로세스에서 template API를 사용하여 +어플리케이션 메뉴를 만듭니다: ```javascript var template = [ @@ -210,14 +213,15 @@ Menu.setApplicationMenu(menu); * `menu` Menu -지정한 `menu`를 어플리케이션 메뉴로 만듭니다. OS X에선 상단바에 표시되며 Windows와 Linux에선 각 창의 상단에 표시됩니다. +지정한 `menu`를 어플리케이션 메뉴로 만듭니다. OS X에선 상단바에 표시되며 Windows와 +Linux에선 각 창의 상단에 표시됩니다. ### `Menu.sendActionToFirstResponder(action)` _OS X_ * `action` String -`action`을 어플리케이션의 first responder에 전달합니다. -이 메서드는 Cocoa 메뉴 동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem`의 `selector` 속성에 사용됩니다. +`action`을 어플리케이션의 first responder에 전달합니다. 이 메서드는 Cocoa 메뉴 +동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem`의 `selector` 속성에 사용됩니다. **참고:** 이 메서드는 OS X에서만 사용할 수 있습니다. @@ -225,9 +229,11 @@ Menu.setApplicationMenu(menu); * `template` Array -기본적으로 `template`는 [MenuItem](menu-item.md)을 생성할 때 사용하는 `options`의 배열입니다. 사용법은 위에서 설명한 것과 같습니다. +기본적으로 `template`는 [MenuItem](menu-item.md)을 생성할 때 사용하는 `options`의 +배열입니다. 사용법은 위에서 설명한 것과 같습니다. -또한 `template`에는 다른 속성도 추가할 수 있으며 메뉴가 만들어질 때 해당 메뉴 아이템의 프로퍼티로 변환됩니다. +또한 `template`에는 다른 속성도 추가할 수 있으며 메뉴가 만들어질 때 해당 메뉴 아이템의 +프로퍼티로 변환됩니다. ### `Menu.popup([browserWindow, x, y])` @@ -235,9 +241,8 @@ Menu.setApplicationMenu(menu); * `x` Number (optional) * `y` Number (만약 `x`를 지정했을 경우 반드시 `y`도 지정해야 합니다) -메뉴를 `browserWindow` 내부 팝업으로 표시합니다. -옵션으로 메뉴를 표시할 `(x,y)` 좌표를 지정할 수 있습니다. -따로 좌표를 지정하지 않은 경우 마우스 커서 위치에 표시됩니다. +메뉴를 `browserWindow` 내부 팝업으로 표시합니다. 옵션으로 메뉴를 표시할 `(x,y)` +좌표를 지정할 수 있습니다. 따로 좌표를 지정하지 않은 경우 마우스 커서 위치에 표시됩니다. ### `Menu.append(menuItem)` @@ -259,13 +264,14 @@ Menu.setApplicationMenu(menu); ## OS X 어플리케이션 메뉴에 대해 알아 둬야 할 것들 OS X에선 Windows, Linux와 달리 완전히 다른 어플리케이션 메뉴 스타일을 가지고 있습니다. -그래서 어플리케이션을 네이티브처럼 작동할 수 있도록 하기 위해 다음 몇 가지 유의 사항을 숙지해야 합니다. +그래서 어플리케이션을 네이티브처럼 작동할 수 있도록 하기 위해 다음 몇 가지 유의 사항을 +숙지해야 합니다. ### 기본 메뉴 -OS X엔 `Services`나 `Windows`와 같은 많은 시스템 지정 기본 메뉴가 있습니다. -기본 메뉴를 만들려면 반드시 다음 리스트 중 한 가지를 선택하여 메뉴의 `role`로 지정해야 합니다. -그러면 Electron이 자동으로 인식하여 해당 메뉴를 기본 메뉴로 만듭니다: +OS X엔 `Services`나 `Windows`와 같은 많은 시스템 지정 기본 메뉴가 있습니다. 기본 +메뉴를 만들려면 반드시 다음 리스트 중 한 가지를 선택하여 메뉴의 `role`로 지정해야 +합니다. 그러면 Electron이 자동으로 인식하여 해당 메뉴를 기본 메뉴로 만듭니다: * `window` * `help` @@ -273,29 +279,38 @@ OS X엔 `Services`나 `Windows`와 같은 많은 시스템 지정 기본 메뉴 ### 메뉴 아이템 기본 동작 -OS X는 몇가지 메뉴 아이템에 대해 `About xxx`, `Hide xxx`, `Hide Others`와 같은 기본 동작을 제공하고 있습니다. -메뉴 아이템의 기본 동작을 지정하려면 반드시 메뉴 아이템의 `role` 속성을 지정해야 합니다. +OS X는 몇가지 메뉴 아이템에 대해 `About xxx`, `Hide xxx`, `Hide Others`와 같은 +기본 동작을 제공하고 있습니다. 메뉴 아이템의 기본 동작을 지정하려면 반드시 메뉴 +아이템의 `role` 속성을 지정해야 합니다. ### 메인 메뉴의 이름 -OS X에선 지정한 어플리케이션 메뉴에 상관없이 메뉴의 첫번째 라벨은 언제나 어플리케이션의 이름이 됩니다. -어플리케이션 이름을 변경하려면 앱 번들내의 `Info.plist` 파일을 수정해야합니다. -자세한 내용은 [About Information Property List Files][AboutInformationPropertyListFiles] 문서를 참고하세요. +OS X에선 지정한 어플리케이션 메뉴에 상관없이 메뉴의 첫번째 라벨은 언제나 어플리케이션의 +이름이 됩니다. 어플리케이션 이름을 변경하려면 앱 번들내의 `Info.plist` 파일을 수정해야 +합니다. 자세한 내용은 [About Information Property List Files][AboutInformationPropertyListFiles] 문서를 참고하세요. ## 메뉴 아이템 위치 -`Menu.buildFromTemplate`로 메뉴를 만들 때 `position`과 `id`를 사용해서 아이템의 위치를 지정할 수 있습니다. +`Menu.buildFromTemplate`로 메뉴를 만들 때 `position`과 `id`를 사용해서 아이템의 +위치를 지정할 수 있습니다. -`MenuItem`의 `position` 속성은 `[placement]=[id]`와 같은 형식을 가지며 `placement`는 -`before`, `after`, `endof` 속성 중 한가지를 사용할 수 있고 `id`는 메뉴 아이템이 가지는 유일 ID 입니다: +`MenuItem`의 `position` 속성은 `[placement]=[id]`와 같은 형식을 가지며 +`placement`는 `before`, `after`, `endof` 속성 중 한가지를 사용할 수 있고 `id`는 +메뉴 아이템이 가지는 유일 ID 입니다: -* `before` - 이 아이템을 지정한 id 이전의 위치에 삽입합니다. 만약 참조된 아이템이 없을 경우 메뉴의 맨 뒤에 삽입됩니다. -* `after` - 이 아이템을 지정한 id 다음의 위치에 삽입합니다. 만약 참조된 아이템이 없을 경우 메뉴의 맨 뒤에 삽입됩니다. -* `endof` - 이 아이템을 id의 논리 그룹에 맞춰서 각 그룹의 항목 뒤에 삽입합니다. (그룹은 분리자 아이템에 의해 만들어집니다) - 만약 참조된 아이템의 분리자 그룹이 존재하지 않을 경우 지정된 id로 새로운 분리자 그룹을 만든 후 해당 그룹의 뒤에 삽입됩니다. +* `before` - 이 아이템을 지정한 id 이전의 위치에 삽입합니다. 만약 참조된 아이템이 + 없을 경우 메뉴의 맨 뒤에 삽입됩니다. +* `after` - 이 아이템을 지정한 id 다음의 위치에 삽입합니다. 만약 참조된 아이템이 + 없을 경우 메뉴의 맨 뒤에 삽입됩니다. +* `endof` - 이 아이템을 id의 논리 그룹에 맞춰서 각 그룹의 항목 뒤에 삽입합니다. + (그룹은 분리자 아이템에 의해 만들어집니다) 만약 참조된 아이템의 분리자 그룹이 + 존재하지 않을 경우 지정된 id로 새로운 분리자 그룹을 만든 후 해당 그룹의 뒤에 + 삽입됩니다. -위치를 지정한 아이템의 뒤에 위치가 지정되지 않은 아이템이 있을 경우 각 아이템의 위치가 지정되기 전까지 모든 아이템이 위치가 지정된 아이템의 뒤에 삽입됩니다. -따라서 위치를 이동하고 싶은 특정 그룹의 아이템들이 있을 경우 해당 그룹의 맨 첫번째 메뉴 아이템의 위치만을 지정하면 됩니다. +위치를 지정한 아이템의 뒤에 위치가 지정되지 않은 아이템이 있을 경우 각 아이템의 위치가 +지정되기 전까지 모든 아이템이 위치가 지정된 아이템의 뒤에 삽입됩니다. 따라서 위치를 +이동하고 싶은 특정 그룹의 아이템들이 있을 경우 해당 그룹의 맨 첫번째 메뉴 아이템의 +위치만을 지정하면 됩니다. ### 예제 diff --git a/docs-translations/ko-KR/api/native-image.md b/docs-translations/ko-KR/api/native-image.md index 04d3fe57c453..917dbb3a71b8 100644 --- a/docs-translations/ko-KR/api/native-image.md +++ b/docs-translations/ko-KR/api/native-image.md @@ -1,9 +1,10 @@ # nativeImage -Electron은 파일 경로 또는 `nativeImage` 인스턴스를 통해 이미지를 사용할 수 있는 API를 가지고 있습니다. -`null`을 전달할 경우 빈 이미지가 생성됩니다. +Electron은 파일 경로 또는 `nativeImage` 인스턴스를 통해 이미지를 사용할 수 있는 API를 +가지고 있습니다. `null`을 전달할 경우 빈 이미지가 생성됩니다. -예를 들어 트레이 메뉴를 만들거나 윈도우의 아이콘을 설정할 때 다음과 같이 파일 경로를 전달하여 이미지를 사용할 수 있습니다: +예를 들어 트레이 메뉴를 만들거나 윈도우의 아이콘을 설정할 때 다음과 같이 파일 경로를 +전달하여 이미지를 사용할 수 있습니다: ```javascript var appIcon = new Tray('/Users/somebody/images/icon.png'); @@ -26,11 +27,15 @@ var appIcon = new Tray(image); ## 고해상도 이미지 -플랫폼이 high-DPI를 지원하는 경우 `@2x`와 같이 이미지의 파일명 뒤에 접미사를 추가하여 고해상도 이미지로 지정할 수 있습니다. +플랫폼이 high-DPI를 지원하는 경우 `@2x`와 같이 이미지의 파일명 뒤에 접미사를 추가하여 +고해상도 이미지로 지정할 수 있습니다. -예를 들어 `icon.png` 라는 기본 해상도의 이미지를 기준으로 크기를 두 배로 늘린 이미지를 `icon@2x.png` 처럼 지정하면 고해상도 이미지로 처리됩니다. +예를 들어 `icon.png` 라는 기본 해상도의 이미지를 기준으로 크기를 두 배로 늘린 이미지를 +`icon@2x.png` 처럼 지정하면 고해상도 이미지로 처리됩니다. -서로 다른 해상도(DPI)의 이미지를 같이 지원하고 싶다면 다중 해상도의 이미지를 접미사를 붙여 한 폴더에 같이 넣으면 됩니다. 이 이미지를 사용(로드)할 땐 따로 접미사를 붙이지 않습니다: +서로 다른 해상도(DPI)의 이미지를 같이 지원하고 싶다면 다중 해상도의 이미지를 접미사를 +붙여 한 폴더에 같이 넣으면 됩니다. 이 이미지를 사용(로드)할 땐 따로 접미사를 붙이지 +않습니다: ```text images/ @@ -60,14 +65,16 @@ var appIcon = new Tray('/Users/somebody/images/icon.png'); ## 템플릿 이미지 -템플릿 이미지는 검은색과 명확한 색상(알파 채널)으로 이루어져 있습니다. -템플릿 이미지는 단독 이미지로 사용되지 않고 다른 컨텐츠와 혼합되어 최종 외관 만드는데 사용됩니다. +템플릿 이미지는 검은색과 명확한 색상(알파 채널)으로 이루어져 있습니다. 템플릿 이미지는 +단독 이미지로 사용되지 않고 다른 컨텐츠와 혼합되어 최종 외관 만드는데 사용됩니다. -가장 일반적으로 템플릿 이미지는 밝고 어두운 테마 색상으로 변경할 수 있는 메뉴 바 아이콘 등에 사용되고 있습니다. +가장 일반적으로 템플릿 이미지는 밝고 어두운 테마 색상으로 변경할 수 있는 메뉴 바 아이콘 +등에 사용되고 있습니다. **참고:** 템플릿 이미지는 OS X 운영체제만 지원합니다. -템플릿 이미지를 지정하려면 다음 예제와 같이 파일명에 `Template` 문자열을 추가해야 합니다: +템플릿 이미지를 지정하려면 다음 예제와 같이 파일명에 `Template` 문자열을 추가해야 +합니다: * `xxxTemplate.png` * `xxxTemplate@2x.png` @@ -91,7 +98,8 @@ var appIcon = new Tray('/Users/somebody/images/icon.png'); * `buffer` [Buffer][buffer] * `scaleFactor` Double (optional) -`buffer`로부터 이미지를 로드하여 새로운 `nativeImage` 인스턴스를 만듭니다. `scaleFactor`의 기본값은 1.0 입니다. +`buffer`로부터 이미지를 로드하여 새로운 `nativeImage` 인스턴스를 만듭니다. +`scaleFactor`의 기본값은 1.0 입니다. ### `nativeImage.createFromDataURL(dataURL)` diff --git a/docs-translations/ko-KR/api/power-monitor.md b/docs-translations/ko-KR/api/power-monitor.md index e84bd9514330..29a3aabc84a1 100644 --- a/docs-translations/ko-KR/api/power-monitor.md +++ b/docs-translations/ko-KR/api/power-monitor.md @@ -1,8 +1,9 @@ # powerMonitor `power-monitor` 모듈은 PC의 파워 상태를 나타냅니다. (주로 노트북 등에서 사용됩니다) -이 모듈은 메인 프로세스에서만 사용할 수 있으며, (remote 모듈(RPC)을 사용해도 작동이 됩니다) -메인 프로세스의 `app` 모듈에서 `ready` 이벤트를 호출하기 전까지 사용할 수 없습니다. +이 모듈은 메인 프로세스에서만 사용할 수 있으며, (remote 모듈(RPC)을 사용해도 작동이 +됩니다) 메인 프로세스의 `app` 모듈에서 `ready` 이벤트를 호출하기 전까지 사용할 수 +없습니다. 예제: diff --git a/docs-translations/ko-KR/api/power-save-blocker.md b/docs-translations/ko-KR/api/power-save-blocker.md index 3a09591aaf97..560b3fc9cef5 100644 --- a/docs-translations/ko-KR/api/power-save-blocker.md +++ b/docs-translations/ko-KR/api/power-save-blocker.md @@ -1,6 +1,7 @@ # powerSaveBlocker -`powerSaveBlocker` 모듈은 시스템이 저전력(슬립) 모드로 진입하는 것을 막고 앱 시스템과 화면이 항상 활성화 상태를 유지할 수 있도록 하는 몇가지 유틸리티를 제공하는 모듈입니다. +`powerSaveBlocker` 모듈은 시스템이 저전력(슬립) 모드로 진입하는 것을 막고 앱 시스템과 +화면이 항상 활성화 상태를 유지할 수 있도록 하는 몇가지 유틸리티를 제공하는 모듈입니다. 예제: @@ -20,27 +21,36 @@ powerSaveBlocker.stop(id); ### `powerSaveBlocker.start(type)` * `type` String - Power save blocker 종류 - * `prevent-app-suspension` - 저전력 모드 등으로 인한 어플리케이션 작동 중단을 방지합니다. - 시스템을 항시 활성화 상태로 만듭니다. 하지만 화면은 자동으로 꺼질 수 있습니다. 사용 예시: 파일 다운로드, 음악 재생 등. - * `prevent-display-sleep`- 슬립 모드 등으로 인한 어플리케이션의 작동 중단을 방지합니다. - 시스템을 항시 활성화 상태로 만들고 슬립 모드(화면 꺼짐)를 방지합니다. 사용 예시: 비디오 재생 등. + * `prevent-app-suspension` - 저전력 모드 등으로 인한 어플리케이션 작동 중단을 + 방지합니다. 시스템을 항시 활성화 상태로 만듭니다. 하지만 화면은 자동으로 꺼질 수 + 있습니다. 사용 예시: 파일 다운로드, 음악 재생 등. + * `prevent-display-sleep`- 슬립 모드 등으로 인한 어플리케이션의 작동 중단을 + 방지합니다. 시스템을 항시 활성화 상태로 만들고 슬립 모드(화면 꺼짐)를 방지합니다. + 사용 예시: 비디오 재생 등. -시스템이 저전력 모드(슬립)로 진입하는 것을 막기 시작합니다. 정수로 된 식별 ID를 반환합니다. +시스템이 저전력 모드(슬립)로 진입하는 것을 막기 시작합니다. 정수로 된 식별 ID를 +반환합니다. -**참고:** `prevent-display-sleep` 모드는 `prevent-app-suspension` 보다 우선 순위가 높습니다. -두 모드 중 가장 높은 우선 순위의 모드만 작동합니다. 다시 말해 `prevent-display-sleep` 모드는 언제나 `prevent-app-suspension` 모드의 효과를 덮어씌웁니다. +**참고:** `prevent-display-sleep` 모드는 `prevent-app-suspension` 보다 우선 순위가 +높습니다. 두 모드 중 가장 높은 우선 순위의 모드만 작동합니다. 다시 말해 +`prevent-display-sleep` 모드는 언제나 `prevent-app-suspension` 모드의 효과를 +덮어씌웁니다. -예를 들어 A-요청이 `prevent-app-suspension` 모드를 사용하고 B-요청이 `prevent-display-sleep`를 사용하는 API 호출이 있었다 치면 -`prevent-display-sleep` 모드를 사용하는 B의 작동이 중단(stop)되기 전까지 작동하다 B가 중단되면 `prevent-app-suspension` 모드를 사용하는 A가 작동하기 시작합니다. +예를 들어 A-요청이 `prevent-app-suspension` 모드를 사용하고 B-요청이 +`prevent-display-sleep`를 사용하는 API 호출이 있었다 하면 `prevent-display-sleep` +모드를 사용하는 B의 작동이 중단(stop)되기 전까지 작동하다 B가 중단되면 +`prevent-app-suspension` 모드를 사용하는 A가 작동하기 시작합니다. ### `powerSaveBlocker.stop(id)` -* `id` Integer - `powerSaveBlocker.start`로 부터 반환되는 power save blocker 식별 ID. +* `id` Integer - `powerSaveBlocker.start`로부터 반환되는 power save blocker 식별 +ID. 설정한 power save blocker를 중지합니다. ### `powerSaveBlocker.isStarted(id)` -* `id` Integer - `powerSaveBlocker.start`로 부터 반환되는 power save blocker 식별 ID. +* `id` Integer - `powerSaveBlocker.start`로부터 반환되는 power save blocker 식별 +ID. 지정한 id의 `powerSaveBlocker`가 실행 중인지 확인합니다. diff --git a/docs-translations/ko-KR/api/process.md b/docs-translations/ko-KR/api/process.md index c66eb84cfeae..afbc6afd796d 100644 --- a/docs-translations/ko-KR/api/process.md +++ b/docs-translations/ko-KR/api/process.md @@ -2,19 +2,23 @@ Electron의 `process` 객체는 기존의 node와는 달리 약간의 차이점이 있습니다: -* `process.type` String - 프로세스의 타입, `browser` (메인 프로세스) 또는 `renderer`가 됩니다. +* `process.type` String - 프로세스의 타입, `browser` (메인 프로세스) 또는 + `renderer`가 됩니다. * `process.versions['electron']` String - Electron의 버전. * `process.versions['chrome']` String - Chromium의 버전. * `process.resourcesPath` String - JavaScript 소스 코드의 경로. -* `process.mas` Boolean - Mac 앱 스토어용 빌드일 때 `true`로 지정됩니다. 다른 빌드일 땐 `undefined`로 지정됩니다. +* `process.mas` Boolean - Mac 앱 스토어용 빌드일 때 `true`로 지정됩니다. 다른 + 빌드일 땐 `undefined`로 지정됩니다. ## Events ### Event: 'loaded' -Electron 내부 초기화 스크립트의 로드가 완료되고, 웹 페이지나 메인 스크립트를 로드하기 시작할 때 발생하는 이벤트입니다. +Electron 내부 초기화 스크립트의 로드가 완료되고, 웹 페이지나 메인 스크립트를 로드하기 +시작할 때 발생하는 이벤트입니다. -이 이벤트는 preload 스크립트를 통해 node 통합이 꺼져있는 전역 스코프에 node의 전역 심볼들을 다시 추가할 때 사용할 수 있습니다: +이 이벤트는 preload 스크립트를 통해 node 통합이 꺼져있는 전역 스코프에 node의 전역 +심볼들을 다시 추가할 때 사용할 수 있습니다: ```javascript // preload.js @@ -38,4 +42,5 @@ process.once('loaded', function() { * `maxDescriptors` Integer -현재 프로세스의 파일 기술자의 제한 값을 소프트 제한 `maxDescriptors`의 값이나 OS 하드 제한 중 낮은 값으로 설정합니다. +현재 프로세스 파일 디스크립터의 제한 값을 소프트 제한 `maxDescriptors`의 값이나 OS 하드 +제한 중 낮은 값으로 설정합니다. diff --git a/docs-translations/ko-KR/api/protocol.md b/docs-translations/ko-KR/api/protocol.md index f2e4ba3a5b1a..11198123e332 100644 --- a/docs-translations/ko-KR/api/protocol.md +++ b/docs-translations/ko-KR/api/protocol.md @@ -1,6 +1,7 @@ # protocol -`protocol` 모듈은 이미 있는 프로토콜의 동작을 가로채거나 새로운 프로토콜을 만들 수 있는 기능을 제공합니다. +`protocol` 모듈은 이미 있는 프로토콜의 동작을 가로채거나 새로운 프로토콜을 만들 수 +있는 기능을 제공합니다. 다음 예제는 `file://` 프로토콜과 비슷한 일을 하는 커스텀 프로토콜을 설정합니다: @@ -31,8 +32,8 @@ app.on('ready', function() { * `schemes` Array - 표준 스킴으로 등록할 커스텀 스킴 리스트 -표준 `scheme`의 형식은 RFC 3986 [일반 URI 구문](https://tools.ietf.org/html/rfc3986#section-3) 표준을 따릅니다. -이 형식은 `file:`과 `filesystem:`을 포함합니다. +표준 `scheme`의 형식은 RFC 3986 [일반 URI 구문](https://tools.ietf.org/html/rfc3986#section-3) +표준을 따릅니다. 이 형식은 `file:`과 `filesystem:`을 포함합니다. ### `protocol.registerFileProtocol(scheme, handler[, completion])` @@ -40,20 +41,23 @@ app.on('ready', function() { * `handler` Function * `completion` Function (optional) -`scheme`에 파일을 응답으로 보내는 프로토콜을 등록합니다. -`handler`는 `scheme`와 함께 `request`가 생성될 때 `handler(request, callback)` 형식으로 호출됩니다. -`completion` 콜백은 `scheme`가 성공적으로 등록되었을 때 `completion(null)` 형식으로 호출되고 -등록에 실패했을 땐 `completion(error)` 형식으로 에러 내용을 담아 호출됩니다. +`scheme`에 파일을 응답으로 보내는 프로토콜을 등록합니다. `handler`는 `scheme`와 함께 +`request`가 생성될 때 `handler(request, callback)` 형식으로 호출됩니다. +`completion` 콜백은 `scheme`가 성공적으로 등록되었을 때 `completion(null)` 형식으로 +호출되고, 등록에 실패했을 땐 `completion(error)` 형식으로 에러 내용을 담아 호출됩니다. -`request`를 처리할 때 반드시 파일 경로 또는 `path` 속성을 포함하는 객체를 인자에 포함하여 `callback`을 호출해야 합니다. -예: `callback(filePath)` 또는 `callback({path: filePath})`. +`request`를 처리할 때 반드시 파일 경로 또는 `path` 속성을 포함하는 객체를 인자에 +포함하여 `callback`을 호출해야 합니다. 예: `callback(filePath)` 또는 +`callback({path: filePath})`. -만약 `callback`이 아무 인자도 없이 호출되거나 숫자나 `error` 프로퍼티를 가진 객체가 인자로 전달될 경우 -`request`는 지정한 `error` 코드(숫자)를 출력합니다. -사용할 수 있는 에러 코드는 [네트워크 에러 목록](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h)에서 확인할 수 있습니다. +만약 `callback`이 아무 인자도 없이 호출되거나 숫자나 `error` 프로퍼티를 가진 객체가 +인자로 전달될 경우 `request`는 지정한 `error` 코드(숫자)를 출력합니다. 사용할 수 있는 +에러 코드는 [네트워크 에러 목록](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h)에서 +확인할 수 있습니다. -기본적으로 `scheme`은 `http:`와 같이 처리됩니다. `file:`과 같이 "일반적인 URI 문법"과는 다르게 인식되는 프로토콜은 -`protocol.registerStandardSchemes`을 사용하여 표준 스킴으로 처리되도록 할 수 있습니다. +기본적으로 `scheme`은 `http:`와 같이 처리됩니다. `file:`과 같이 "일반적인 URI 문법" +과는 다르게 인식되는 프로토콜은 `protocol.registerStandardSchemes`을 사용하여 표준 +스킴으로 처리되도록 할 수 있습니다. ### `protocol.registerBufferProtocol(scheme, handler[, completion])` @@ -61,8 +65,9 @@ app.on('ready', function() { * `handler` Function * `completion` Function (optional) -`scheme`에 `Buffer`를 응답으로 보내는 프로토콜을 등록합니다. -반드시 `Buffer` 또는 `data`, `mimeType`, `chart` 속성을 포함한 객체 중 하나를 인자에 포함하여 `callback`을 호출해야 합니다. +`scheme`에 `Buffer`를 응답으로 보내는 프로토콜을 등록합니다. 반드시 `Buffer` 또는 +`data`, `mimeType`, `chart` 속성을 포함한 객체 중 하나를 인자에 포함하여 +`callback`을 호출해야 합니다. 예제: @@ -81,8 +86,9 @@ protocol.registerBufferProtocol('atom', function(request, callback) { * `handler` Function * `completion` Function (optional) -`scheme`에 `문자열`을 응답으로 보내는 프로토콜을 등록합니다. -반드시 `문자열` 또는 `data`, `mimeType`, `chart` 속성을 포함한 객체 중 하나를 인자에 포함하여 `callback`을 호출해야 합니다. +`scheme`에 `문자열`을 응답으로 보내는 프로토콜을 등록합니다. 반드시 `문자열` 또는 +`data`, `mimeType`, `chart` 속성을 포함한 객체 중 하나를 인자에 포함하여 +`callback`을 호출해야 합니다. ### `protocol.registerHttpProtocol(scheme, handler[, completion])` @@ -90,10 +96,12 @@ protocol.registerBufferProtocol('atom', function(request, callback) { * `handler` Function * `completion` Function (optional) -`scheme`에 HTTP 요청을 응답으로 보내는 프로토콜을 등록합니다. -반드시 `url`, `method`, `referer`, `session` 속성을 포함하는 객체를 인자에 포함하여 `callback`을 호출해야 합니다. +`scheme`에 HTTP 요청을 응답으로 보내는 프로토콜을 등록합니다. 반드시 `url`, +`method`, `referer`, `session` 속성을 포함하는 객체를 인자에 포함하여 `callback`을 +호출해야 합니다. -기본적으로 HTTP 요청은 현재 세션을 재사용합니다. 만약 서로 다른 세션에 요청을 보내고 싶으면 `session`을 `null`로 지정해야 합니다. +기본적으로 HTTP 요청은 현재 세션을 재사용합니다. 만약 서로 다른 세션에 요청을 보내고 +싶으면 `session`을 `null`로 지정해야 합니다. ### `protocol.unregisterProtocol(scheme[, completion])` @@ -107,7 +115,8 @@ protocol.registerBufferProtocol('atom', function(request, callback) { * `scheme` String * `callback` Function -`scheme`에 동작(handler)이 등록되어 있는지 여부를 확인합니다. `callback`으로 결과(boolean)가 반환됩니다. +`scheme`에 동작(handler)이 등록되어 있는지 여부를 확인합니다. `callback`으로 +결과(boolean)가 반환됩니다. ### `protocol.interceptFileProtocol(scheme, handler[, completion])` @@ -131,7 +140,8 @@ protocol.registerBufferProtocol('atom', function(request, callback) { * `handler` Function * `completion` Function (optional) -`scheme` 프로토콜을 가로채고 `handler`를 `Buffer` 전송에 대한 새로운 동작으로 사용합니다. +`scheme` 프로토콜을 가로채고 `handler`를 `Buffer` 전송에 대한 새로운 동작으로 +사용합니다. ### `protocol.interceptHttpProtocol(scheme, handler[, completion])` @@ -139,7 +149,8 @@ protocol.registerBufferProtocol('atom', function(request, callback) { * `handler` Function * `completion` Function (optional) -`scheme` 프로토콜을 가로채고 `handler`를 HTTP 프로토콜의 요청에 대한 새로운 동작으로 사용합니다. +`scheme` 프로토콜을 가로채고 `handler`를 HTTP 프로토콜의 요청에 대한 새로운 동작으로 +사용합니다. ### `protocol.uninterceptProtocol(scheme[, completion])` diff --git a/docs-translations/ko-KR/api/remote.md b/docs-translations/ko-KR/api/remote.md index d8e84f0caed9..935b09865130 100644 --- a/docs-translations/ko-KR/api/remote.md +++ b/docs-translations/ko-KR/api/remote.md @@ -1,11 +1,13 @@ # remote -`remote` 모듈은 메인 프로세스와 랜더러 프로세스(웹 페이지) 사이의 inter-process (IPC) 통신을 간단하게 추상화 한 모듈입니다. +`remote` 모듈은 메인 프로세스와 랜더러 프로세스(웹 페이지) 사이의 inter-process +(IPC) 통신을 간단하게 추상화 한 모듈입니다. -Electron의 메인 프로세스에선 GUI와 관련 있는(`dialog`, `menu`등) 모듈만 사용할 수 있습니다. -랜더러 프로세스에서 이러한 모듈들을 사용하려면 `ipc` 모듈을 통해 메인 프로세스와 inter-process 통신을 해야합니다. -또한, `remote` 모듈을 사용하면 inter-process 통신을 하지 않고도 간단한 API를 통해 직접 메인 프로세스의 모듈과 메서드를 사용할 수 있습니다. -이 개념은 Java의 [RMI][rmi]와 비슷합니다. +Electron의 메인 프로세스에선 GUI와 관련 있는(`dialog`, `menu`등) 모듈만 사용할 수 +있습니다. 랜더러 프로세스에서 이러한 모듈들을 사용하려면 `ipc` 모듈을 통해 메인 +프로세스와 inter-process 통신을 해야합니다. 또한, `remote` 모듈을 사용하면 +inter-process 통신을 하지 않고도 간단한 API를 통해 직접 메인 프로세스의 모듈과 +메서드를 사용할 수 있습니다. 이 개념은 Java의 [RMI][rmi]와 비슷합니다. 다음 예제는 랜더러 프로세스에서 브라우저 창을 만드는 예제입니다: @@ -17,35 +19,44 @@ var win = new BrowserWindow({ width: 800, height: 600 }); win.loadURL('https://github.com'); ``` -**참고:** 반대로 메인 프로세스에서 랜더러 프로세스에 접근 하려면 [webContents.executeJavascript](web-contents.md#webcontentsexecutejavascriptcode-usergesture) 메서드를 사용하면 됩니다. +**참고:** 반대로 메인 프로세스에서 랜더러 프로세스에 접근 하려면 [webContents.executeJavascript](web-contents.md#webcontentsexecutejavascriptcode-usergesture) +메서드를 사용하면 됩니다. ## Remote 객체 -`remote` 모듈로부터 반환된 각 객체(메서드 포함)는 메인 프로세스의 객체를 추상화 한 객체입니다. (우리는 그것을 remote 객체 또는 remote 함수라고 부릅니다) -Remote 모듈의 메서드를 호출하거나, 객체에 접근하거나, 생성자로 객체를 생성하는 등의 작업은 실질적으로 동기형 inter-process 메시지를 보냅니다. +`remote` 모듈로부터 반환된 각 객체(메서드 포함)는 메인 프로세스의 객체를 추상화 한 +객체입니다. (우리는 그것을 remote 객체 또는 remote 함수라고 부릅니다) Remote 모듈의 +메서드를 호출하거나, 객체에 접근하거나, 생성자로 객체를 생성하는 등의 작업은 실질적으로 +동기형 inter-process 메시지를 보냅니다. -위의 예제에서 사용한 두 `BrowserWindow`와 `win`은 remote 객체입니다. 그리고 `new BrowserWindow`이 생성하는 `BrowserWindow` 객체는 랜더러 프로세스에서 생성되지 않습니다. -대신에 이 `BrowserWindow` 객체는 메인 프로세스에서 생성되며 랜더러 프로세스에 `win` 객체와 같이 이에 대응하는 remote 객체를 반환합니다. +위의 예제에서 사용한 두 `BrowserWindow`와 `win`은 remote 객체입니다. 그리고 +`new BrowserWindow`이 생성하는 `BrowserWindow` 객체는 랜더러 프로세스에서 생성되지 +않습니다. 대신에 이 `BrowserWindow` 객체는 메인 프로세스에서 생성되며 랜더러 +프로세스에 `win` 객체와 같이 이에 대응하는 remote 객체를 반환합니다. ## Remote 객체의 생명 주기 -Electron은 랜더러 프로세스의 remote 객체가 살아있는 한(다시 말해서 GC(garbage collection)가 일어나지 않습니다) 대응하는 메인 프로세스의 객체는 릴리즈되지 않습니다. +Electron은 랜더러 프로세스의 remote 객체가 살아있는 한(다시 말해서 GC(garbage +collection)가 일어나지 않습니다) 대응하는 메인 프로세스의 객체는 릴리즈되지 않습니다. Remote 객체가 GC 되려면 대응하는 메인 프로세스 내부 객체의 참조가 해제되어야만 합니다. -만약 remote 객체가 랜더러 프로세스에서 누수가 생겼다면 (예시: 맵에 저장하고 할당 해제하지 않음) 대응하는 메인 프로세스의 객체도 누수가 생깁니다. -그래서 remote 객체를 사용할 땐 메모리 누수가 생기지 않도록 매우 주의해서 사용해야 합니다. +만약 remote 객체가 랜더러 프로세스에서 누수가 생겼다면 (예시: 맵에 저장하고 할당 +해제하지 않음) 대응하는 메인 프로세스의 객체도 누수가 생깁니다. 그래서 remote 객체를 +사용할 땐 메모리 누수가 생기지 않도록 매우 주의해서 사용해야 합니다. 참고로 문자열, 숫자와 같은 원시 값 타입은 복사에 의한 참조로 전달됩니다. ## 메인 프로세스로 콜백 넘기기 -메인 프로세스의 코드는 `remote` 모듈을 통해 랜더러 프로세스가 전달하는 콜백 함수를 받을 수 있습니다. -하지만 이 작업은 반드시 주의를 기울여 사용해야 합니다. +메인 프로세스의 코드는 `remote` 모듈을 통해 랜더러 프로세스가 전달하는 콜백 함수를 +받을 수 있습니다. 하지만 이 작업은 반드시 주의를 기울여 사용해야 합니다. -첫째, 데드락을 피하기 위해 메인 프로세스로 전달된 콜백들은 비동기로 호출됩니다. -이러한 이유로 메인 프로세스로 전달된 콜백들의 반환 값을 내부 함수에서 언제나 정상적으로 받을 것이라고 예측해선 안됩니다. +첫째, 데드락을 피하기 위해 메인 프로세스로 전달된 콜백들은 비동기로 호출됩니다. 이러한 +이유로 메인 프로세스로 전달된 콜백들의 반환 값을 내부 함수에서 언제나 정상적으로 받을 +것이라고 예측해선 안됩니다. -예를 들어 메인 프로세스에서 `Array.map` 같은 메서드를 사용할 때 랜더러 프로세스에서 전달된 함수를 사용해선 안됩니다: +예를 들어 메인 프로세스에서 `Array.map` 같은 메서드를 사용할 때 랜더러 프로세스에서 +전달된 함수를 사용해선 안됩니다: ```javascript // mapNumbers.js 메인 프로세스 @@ -76,10 +87,12 @@ console.log(withRendererCb, withLocalCb) // [true, true, true], [2, 3, 4] 보다시피 랜더러 콜백의 동기 반환 값은 예상되지 않은 처리입니다. 그리고 메인 프로세스에서 처리한 함수의 반환 값과 일치하지 않습니다. -둘째, 콜백들은 메인 프로세스로 전달, 호출된 이후에도 자동으로 함수의 참조가 릴리즈 되지 않습니다. -함수 참조는 메인 프로세스에서 GC가 일어나기 전까지 계속 프로세스에 남아있게 됩니다. +둘째, 콜백들은 메인 프로세스로 전달, 호출된 이후에도 자동으로 함수의 참조가 릴리즈 되지 +않습니다. 함수 참조는 메인 프로세스에서 GC가 일어나기 전까지 계속 프로세스에 남아있게 +됩니다. -다음 코드를 보면 느낌이 올 것입니다. 이 예제는 remote 객체에 `close` 이벤트 콜백을 설치합니다: +다음 코드를 보면 느낌이 올 것입니다. 이 예제는 remote 객체에 `close` 이벤트 콜백을 +설치합니다: ```javascript var remote = require('remote'); @@ -89,19 +102,23 @@ remote.getCurrentWindow().on('close', function() { }); ``` -하지만 이 코드 처럼 이벤트를 명시적으로 제거하지 않는 이상 콜백 함수의 참조가 계속해서 메인 프로세스에 남아있게 됩니다. -만약 명시적으로 콜백을 제거하지 않으면 매 번 창을 새로고침 할 때마다 콜백을 새로 설치합니다. -게다가 이전 콜백이 제거되지 않고 계속해서 쌓이면서 메모리 누수가 발생합니다. +하지만 이 코드 처럼 이벤트를 명시적으로 제거하지 않는 이상 콜백 함수의 참조가 계속해서 +메인 프로세스에 남아있게 됩니다. 만약 명시적으로 콜백을 제거하지 않으면 매 번 창을 +새로고침 할 때마다 콜백을 새로 설치합니다. 게다가 이전 콜백이 제거되지 않고 계속해서 +쌓이면서 메모리 누수가 발생합니다. -설상가상으로 이전에 설치된 콜백의 콘텍스트가 릴리즈 되고 난 후(예: 페이지 새로고침) `close` 이벤트가 발생하면 예외가 발생하고 메인 프로세스가 작동 중지됩니다. +설상가상으로 이전에 설치된 콜백의 콘텍스트가 릴리즈 되고 난 후(예: 페이지 새로고침) +`close` 이벤트가 발생하면 예외가 발생하고 메인 프로세스가 작동 중지됩니다. -이러한 문제를 피하려면 랜더러 프로세스에서 메인 프로세스로 넘긴 함수의 참조를 사용 후 확실하게 제거해야 합니다. -작업 후 이벤트 콜백을 포함하여 책임 있게 함수의 참조를 제거하거나 메인 프로세스에서 랜더러 프로세스가 종료될 때 내부적으로 함수 참조를 제거하도록 설계해야 합니다. +이러한 문제를 피하려면 랜더러 프로세스에서 메인 프로세스로 넘긴 함수의 참조를 사용 후 +확실하게 제거해야 합니다. 작업 후 이벤트 콜백을 포함하여 책임 있게 함수의 참조를 +제거하거나 메인 프로세스에서 랜더러 프로세스가 종료될 때 내부적으로 함수 참조를 +제거하도록 설계해야 합니다. ## 메인 프로세스의 빌트인 모듈에 접근 -메인 프로세스의 빌트인 모듈은 `remote` 모듈에 getter로 등록되어 있습니다. -따라서 `remote` 모듈을 `electron` 모듈처럼 직접 사용할 수 있습니다. +메인 프로세스의 빌트인 모듈은 `remote` 모듈에 getter로 등록되어 있습니다. 따라서 +`remote` 모듈을 `electron` 모듈처럼 직접 사용할 수 있습니다. ```javascript const app = remote.app; @@ -133,6 +150,7 @@ const app = remote.app; ### `remote.process` -메인 프로세스의 `process` 객체를 반환합니다. `remote.getGlobal('process')`와 같습니다. 하지만 캐시 됩니다. +메인 프로세스의 `process` 객체를 반환합니다. `remote.getGlobal('process')`와 +같습니다. 하지만 캐시 됩니다. -[rmi]: http://en.wikipedia.org/wiki/Java_remote_method_invocation \ No newline at end of file +[rmi]: http://en.wikipedia.org/wiki/Java_remote_method_invocation diff --git a/docs-translations/ko-KR/api/screen.md b/docs-translations/ko-KR/api/screen.md index 62b717277300..dfd85fb446e1 100644 --- a/docs-translations/ko-KR/api/screen.md +++ b/docs-translations/ko-KR/api/screen.md @@ -3,10 +3,12 @@ `screen` 모듈은 화면 크기, 디스플레이, 커서 위치 등등의 다양한 정보를 가져옵니다. 이 모듈은 `app` 모듈의 `ready` 이벤트가 발생하기 전까지 사용할 수 없습니다. -`screen`은 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속 받았습니다. +`screen`은 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 +상속 받았습니다. -**참고:** 랜더러 / DevTools에선 이미 DOM 속성이 `window.screen`을 가지고 있으므로 `screen = require('screen')` 형식으로 모듈을 사용할 수 없습니다. -아래의 예제와 같이 `electronScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다. +**참고:** 랜더러 / DevTools에선 이미 DOM 속성이 `window.screen`을 가지고 있으므로 +`screen = require('screen')` 형식으로 모듈을 사용할 수 없습니다. 아래의 예제와 같이 +`electronScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다. 다음 예제는 화면 전체를 채우는 윈도우 창을 생성합니다: diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index 5df45f4ac216..aa5ab2ed3e50 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -1,7 +1,8 @@ # session -`session` 객체는 [`BrowserWindow`](browser-window.md)의 [`webContents`](web-contents.md)의 프로퍼티입니다. -다음과 같이 `BrowserWindow` 인스턴스에서 접근할 수 있습니다: +`session` 객체는 [`BrowserWindow`](browser-window.md)의 +[`webContents`](web-contents.md)의 프로퍼티입니다. 다음과 같이 `BrowserWindow` +인스턴스에서 접근할 수 있습니다: ```javascript var BrowserWindow = require('browser-window'); @@ -43,7 +44,8 @@ session.on('will-download', function(event, item, webContents) { * `callback` Function `hostname`에 대한 `certificate`의 유효성 검증이 실패했을 때 발생하는 이벤트 입니다. -인증서를 신뢰한다면 `event.preventDefault()` 와 `callback(true)`를 호출하여 기본 동작을 방지해야 합니다. +인증서를 신뢰한다면 `event.preventDefault()` 와 `callback(true)`를 호출하여 기본 +동작을 방지해야 합니다. ```javascript session.on('verify-certificate', function(event, hostname, certificate, callback) { @@ -63,7 +65,8 @@ session.on('verify-certificate', function(event, hostname, certificate, callback ### `session.cookies` -`cookies` 속성은 쿠키를 조작하는 방법을 제공합니다. 예를 들어 다음과 같이 할 수 있습니다: +`cookies` 속성은 쿠키를 조작하는 방법을 제공합니다. 예를 들어 다음과 같이 할 수 +있습니다: ```javascript var BrowserWindow = require('browser-window'); @@ -101,7 +104,8 @@ win.webContents.on('did-finish-load', function() { `details` Object, properties: -* `url` String - `url`에 관련된 쿠키를 가져옵니다. 이 속성을 비워두면 모든 url의 쿠키를 가져옵니다. +* `url` String - `url`에 관련된 쿠키를 가져옵니다. 이 속성을 비워두면 모든 url의 + 쿠키를 가져옵니다. * `name` String - 이름을 기준으로 쿠키를 필터링합니다. * `domain` String - `domain`과 일치하는 도메인과 서브 도메인에 대한 쿠키를 가져옵니다. * `path` String - `path`와 일치하는 경로에 대한 쿠키를 가져옵니다. @@ -116,23 +120,29 @@ win.webContents.on('did-finish-load', function() { * `domain` String - 쿠키의 도메인. * `host_only` String - 쿠키가 호스트 전용인가에 대한 여부. * `path` String - 쿠키의 경로. - * `secure` Boolean - 쿠키가 안전한 것으로 표시되는지에 대한 여부. (일반적으로 HTTPS) + * `secure` Boolean - 쿠키가 안전한 것으로 표시되는지에 대한 여부. (일반적으로 + HTTPS) * `http_only` Boolean - 쿠키가 HttpOnly로 표시되는지에 대한 여부. - * `session` Boolean - 쿠키가 세션 쿠키 또는 만료일이 있는 영구 쿠키인지에 대한 여부. - * `expirationDate` Double - (Option) UNIX 시간으로 표시되는 쿠키의 만료일에 대한 초 단위 시간. 세션 쿠키는 지원되지 않음. + * `session` Boolean - 쿠키가 세션 쿠키 또는 만료일이 있는 영구 쿠키인지에 대한 + 여부. + * `expirationDate` Double - (Option) UNIX 시간으로 표시되는 쿠키의 만료일에 + 대한 초 단위 시간. 세션 쿠키는 지원되지 않음. ### `session.cookies.set(details, callback)` `details` Object, properties: -* `url` String - `url`에 관련된 쿠키를 가져옵니다. +* `url` String - `url`에 관련된 쿠키를 가져옵니다. * `name` String - 쿠키의 이름입니다. 기본적으로 비워두면 생략됩니다. * `value` String - 쿠키의 값입니다. 기본적으로 비워두면 생략됩니다. * `domain` String - 쿠키의 도메인입니다. 기본적으로 비워두면 생략됩니다. * `path` String - 쿠키의 경로입니다. 기본적으로 비워두면 생략됩니다. -* `secure` Boolean - 쿠키가 안전한 것으로 표시되는지에 대한 여부입니다. 기본값은 false입니다. -* `session` Boolean - 쿠키가 HttpOnly로 표시되는지에 대한 여부입니다. 기본값은 false입니다. -* `expirationDate` Double - UNIX 시간으로 표시되는 쿠키의 만료일에 대한 초 단위 시간입니다. 생략하면 쿠키는 세션 쿠키가 됩니다. +* `secure` Boolean - 쿠키가 안전한 것으로 표시되는지에 대한 여부입니다. 기본값은 + false입니다. +* `session` Boolean - 쿠키가 HttpOnly로 표시되는지에 대한 여부입니다. 기본값은 + false입니다. +* `expirationDate` Double - UNIX 시간으로 표시되는 쿠키의 만료일에 대한 초 단위 + 시간입니다. 생략하면 쿠키는 세션 쿠키가 됩니다. * `callback` Function - function(error) * `error` Error @@ -154,7 +164,8 @@ win.webContents.on('did-finish-load', function() { ### `session.clearStorageData([options, ]callback)` * `options` Object (optional), proprties: - * `origin` String - `scheme://host:port`와 같은 `window.location.origin` 규칙을 따르는 origin 문자열. + * `origin` String - `scheme://host:port`와 같은 `window.location.origin` 규칙을 + 따르는 origin 문자열. * `storages` Array - 비우려는 스토리지의 종류, 다음과 같은 타입을 포함할 수 있습니다: `appcache`, `cookies`, `filesystem`, `indexdb`, `local storage`, `shadercache`, `websql`, `serviceworkers` @@ -171,7 +182,8 @@ win.webContents.on('did-finish-load', function() { 세션에 사용할 프록시 `config`를 분석하고 프록시를 적용합니다. -세션에 사용할 프록시는 `config`가 PAC 주소일 경우 그대로 적용하고, 다른 형식일 경우 다음 규칙에 따라 적용합니다. +세션에 사용할 프록시는 `config`가 PAC 주소일 경우 그대로 적용하고, 다른 형식일 경우 +다음 규칙에 따라 적용합니다. ``` config = scheme-proxies[";"] @@ -181,27 +193,35 @@ proxy-uri-list = [","] proxy-uri = ["://"][":"] 예시: - "http=foopy:80;ftp=foopy2" -- http:// URL에 "foopy:80" HTTP 프록시를 사용합니다. - "foopy2:80" 는 ftp:// URL에 사용됩니다. + "http=foopy:80;ftp=foopy2" -- http:// URL에 "foopy:80" HTTP 프록시를 + 사용합니다. "foopy2:80" 는 ftp:// URL에 + 사용됩니다. "foopy:80" -- 모든 URL에 "foopy:80" 프록시를 사용합니다. - "foopy:80,bar,direct://" -- 모든 URL에 "foopy:80" HTTP 프록시를 사용합니다. - 문제가 발생하여 "foopy:80"를 사용할 수 없는 경우 "bar"를 대신 사용하여 - 장애를 복구하며 그 다음 문제가 생긴 경우 프록시를 사용하지 않습니다. - "socks4://foopy" -- 모든 URL에 "foopy:1000" SOCKS v4 프록시를 사용합니다. - "http=foopy,socks5://bar.com -- http:// URL에 "foopy" HTTP 프록시를 사용합니다. - 문제가 발생하여 "foopy"를 사용할 수 없는 경우 SOCKS5 "bar.com" + "foopy:80,bar,direct://" -- 모든 URL에 "foopy:80" HTTP 프록시를 + 사용합니다. 문제가 발생하여 "foopy:80"를 + 사용할 수 없는 경우 "bar"를 대신 사용하여 + 장애를 복구하며 그 다음 문제가 생긴 경우 + 프록시를 사용하지 않습니다. + "socks4://foopy" -- 모든 URL에 "foopy:1000" SOCKS v4 프록시를 + 사용합니다. + "http=foopy,socks5://bar.com -- http:// URL에 "foopy" HTTP 프록시를 + 사용합니다. 문제가 발생하여 "foopy"를 + 사용할 수 없는 경우 SOCKS5 "bar.com" 프록시를 대신 사용합니다. - "http=foopy,direct:// -- http:// URL에 "foopy" HTTP 프록시를 사용합니다. - 그리고 문제가 발생하여 "foopy"를 사용할 수 없는 경우 프록시를 사용하지 않습니다. - "http=foopy;socks=foopy2 -- http:// URL에 "foopy" HTTP 프록시를 사용합니다. - 그리고 "socks4://foopy2" 프록시를 다른 모든 URL에 사용합니다. + "http=foopy,direct:// -- http:// URL에 "foopy" HTTP 프록시를 + 사용합니다. 그리고 문제가 발생하여 "foopy"를 + 사용할 수 없는 경우 프록시를 사용하지 않습니다. + "http=foopy;socks=foopy2 -- http:// URL에 "foopy" HTTP 프록시를 + 사용합니다. 그리고 "socks4://foopy2" + 프록시를 다른 모든 URL에 사용합니다. ``` ### `session.setDownloadPath(path)` * `path` String - 다운로드 위치 -다운로드 저장 위치를 지정합니다. 기본 다운로드 위치는 각 어플리케이션 데이터 디렉터리의 `Downloads` 폴더입니다. +다운로드 저장 위치를 지정합니다. 기본 다운로드 위치는 각 어플리케이션 데이터 디렉터리의 +`Downloads` 폴더입니다. ### `session.enableNetworkEmulation(options)` diff --git a/docs-translations/ko-KR/api/shell.md b/docs-translations/ko-KR/api/shell.md index dfcbdea20590..4183d3b2502d 100644 --- a/docs-translations/ko-KR/api/shell.md +++ b/docs-translations/ko-KR/api/shell.md @@ -29,9 +29,10 @@ shell.openExternal('https://github.com'); * `url` String -제공된 외부 프로토콜 URL을 기반으로 데스크톱의 기본 프로그램으로 엽니다. (예를 들어 mailto: URL은 유저의 기본 이메일 에이전트로 URL을 엽니다.) +제공된 외부 프로토콜 URL을 기반으로 데스크톱의 기본 프로그램으로 엽니다. (예를 들어 +mailto: URL은 유저의 기본 이메일 에이전트로 URL을 엽니다.) -역주: 폴더는 'file:\\\\C:\\'와 같이 지정하여 열 수 있습니다. (`\\`로 경로를 표현한 이유는 Escape 문자열을 참고하세요.) +역주: 폴더는 'file:\\\\C:\\'와 같이 지정하여 열 수 있습니다. (Windows의 경우) ### `shell.moveItemToTrash(fullPath)` diff --git a/docs-translations/ko-KR/api/synopsis.md b/docs-translations/ko-KR/api/synopsis.md index 77a8514fbb2e..fd0791cd4a8e 100644 --- a/docs-translations/ko-KR/api/synopsis.md +++ b/docs-translations/ko-KR/api/synopsis.md @@ -1,13 +1,17 @@ # 개요 -Electron은 모든 [Node.js의 built-in 모듈](http://nodejs.org/api/)과 third-party node 모듈을 완벽하게 지원합니다. ([네이티브 모듈](../tutorial/using-native-node-modules.md) 포함) +Electron은 모든 [Node.js의 built-in 모듈](http://nodejs.org/api/)과 third-party +node 모듈을 완벽하게 지원합니다. ([네이티브 모듈](../tutorial/using-native-node-modules.md) +포함) -또한 Electron은 네이티브 데스크톱 어플리케이션을 개발 할 수 있도록 추가적인 built-in 모듈을 제공합니다. -몇몇 모듈은 메인 프로세스에서만 사용할 수 있고 어떤 모듈은 랜더러 프로세스(웹 페이지)에서만 사용할 수 있습니다. -또한 두 프로세스 모두 사용할 수 있는 모듈도 있습니다. +또한 Electron은 네이티브 데스크톱 어플리케이션을 개발 할 수 있도록 추가적인 built-in +모듈을 제공합니다. 몇몇 모듈은 메인 프로세스에서만 사용할 수 있고 어떤 모듈은 랜더러 +프로세스(웹 페이지)에서만 사용할 수 있습니다. 또한 두 프로세스 모두 사용할 수 있는 +모듈도 있습니다. -기본적인 규칙으로 [GUI][gui]와 저 수준 시스템에 관련된 모듈들은 오직 메인 프로세스에서만 사용할 수 있습니다. -[메인 프로세스 vs. 랜더러 프로세스](../tutorial/quick-start.md#메인-프로세스) 컨셉에 익숙해야 모듈을 다루기 쉬우므로 관련 문서를 읽어 보는 것을 권장합니다. +기본적인 규칙으로 [GUI][gui]와 저 수준 시스템에 관련된 모듈들은 오직 메인 +프로세스에서만 사용할 수 있습니다. [메인 프로세스 vs. 랜더러 프로세스](../tutorial/quick-start.md#메인-프로세스) +컨셉에 익숙해야 모듈을 다루기 쉬우므로 관련 문서를 읽어 보는 것을 권장합니다. 메인 프로세스 스크립트는 일반 Node.js 스크립트와 비슷합니다: @@ -24,7 +28,8 @@ app.on('ready', function() { }); ``` -랜더러 프로세스도 예외적인 node module들을 사용할 수 있다는 점을 제외하면 일반 웹 페이지와 크게 다를게 없습니다: +랜더러 프로세스도 예외적인 node module들을 사용할 수 있다는 점을 제외하면 일반 웹 +페이지와 크게 다를게 없습니다: ```html @@ -38,7 +43,8 @@ app.on('ready', function() { ``` -어플리케이션을 실행하려면 [앱 실행하기](../tutorial/quick-start.md#앱 실행하기) 문서를 참고하기 바랍니다. +어플리케이션을 실행하려면 [앱 실행하기](../tutorial/quick-start.md#앱 실행하기) +문서를 참고하기 바랍니다. ## 분리 할당 @@ -49,15 +55,17 @@ app.on('ready', function() { const {app, BrowserWindow} = require('electron') ``` -아직 플레인 자바스크립트를 쓰고 있다면, Chrome이 ES6를 완전히 지원하기 전까지 기다려야 합니다. +아직 플레인 자바스크립트를 쓰고 있다면, Chrome이 ES6를 완전히 지원하기 전까지 기다려야 +합니다. ## 이전 스타일의 빌트인 모듈 비활성화 -v0.35.0 이전 버전에선 빌트인 모듈이 모두 `require('module-name')`같은 형식으로 사용되었습니다. -하지만 [많은 단점][issue-387]이 있기 때문에 현재 변경되었습니다. +v0.35.0 이전 버전에선 빌트인 모듈이 모두 `require('module-name')`같은 형식으로 +사용되었습니다. 하지만 [많은 단점][issue-387]이 있기 때문에 현재 API가 변경되었습니다. 하지만 오래된 앱의 호환성 유지를 위해 아직 구 버전 API를 지원하고 있습니다. -완벽하게 모든 구 버전 API를 비활성화하려면 `ELECTRON_HIDE_INTERNAL_MODULES` 환경 변수를 설정하면 됩니다: +완벽하게 모든 구 버전 API를 비활성화하려면 `ELECTRON_HIDE_INTERNAL_MODULES` 환경 +변수를 설정하면 됩니다: ```javascript process.env.ELECTRON_HIDE_INTERNAL_MODULES = 'true' @@ -72,4 +80,4 @@ require('electron').hideInternalModules() [gui]: https://en.wikipedia.org/wiki/Graphical_user_interface [main-process]: ../tutorial/quick-start.md#메인-프로세스 [desctructuring-assignment]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment -[issue-387]: https://github.com/atom/electron/issues/387 \ No newline at end of file +[issue-387]: https://github.com/atom/electron/issues/387 diff --git a/docs-translations/ko-KR/api/tray.md b/docs-translations/ko-KR/api/tray.md index 7a883b026797..97db97f42607 100644 --- a/docs-translations/ko-KR/api/tray.md +++ b/docs-translations/ko-KR/api/tray.md @@ -1,6 +1,7 @@ # Tray -`Tray`는 OS의 알림 영역에 아이콘을 표시합니다. 보통 컨텍스트 메뉴(context menu)를 같이 사용합니다. +`Tray`는 OS의 알림 영역에 아이콘을 표시합니다. 보통 컨텍스트 메뉴(context menu)를 +같이 사용합니다. ```javascript const electron = require('electron'); @@ -25,13 +26,15 @@ app.on('ready', function(){ __플랫폼별 한계:__ -* Linux에서는 앱 알림 표시기(app indicator)가 지원되면 해당 기능을 사용합니다. 만약 지원하지 않으면 `GtkStatusIcon`을 대신 사용합니다. -* Linux 배포판이 앱 알림 표시기만 지원하고 있다면 `libappindicator1`를 설치하여 트레이 아이콘이 작동하도록 만들 수 있습니다. +* Linux에서는 앱 알림 표시기(app indicator)가 지원되면 해당 기능을 사용합니다. 만약 + 지원하지 않으면 `GtkStatusIcon`을 대신 사용합니다. +* Linux 배포판이 앱 알림 표시기만 지원하고 있다면 `libappindicator1`를 설치하여 + 트레이 아이콘이 작동하도록 만들 수 있습니다. * 앱 알림 표시기는 컨텍스트 메뉴를 가지고 있을 때만 보입니다. -* Linux에서 앱 알림 표시기가 사용될 경우, `clicked` 이벤트는 무시됩니다. +* Linux에서 앱 표시기가 사용될 경우, `click` 이벤트는 무시됩니다. -이러한 이유로 Tray API가 모든 플랫폼에서 똑같이 작동하게 하고 싶다면 `click` 이벤트에 의존해선 안됩니다. -그리고 언제나 컨텍스트 메뉴를 포함해야 합니다. +이러한 이유로 Tray API가 모든 플랫폼에서 똑같이 작동하게 하고 싶다면 `click` 이벤트에 +의존해선 안되며 언제나 컨텍스트 메뉴를 포함해야 합니다. ## Class: Tray @@ -47,7 +50,7 @@ __플랫폼별 한계:__ `Tray` 모듈은 다음과 같은 이벤트를 가지고 있습니다: -**참고:** 몇가지 이벤트는 특정한 플랫폼에서만 작동합니다. +**참고:** 몇몇 이벤트는 특정한 플랫폼에서만 작동합니다. ### Event: 'click' diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index 1bad5b47e863..edec4d472b22 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -1,8 +1,9 @@ # webContents -`webContents`는 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속받았습니다. - -웹 페이지의 렌더링과 관리를 책임지며 [`BrowserWindow`](browser-window.md)의 속성입니다. 다음은 `webContents` 객체에 접근하는 예제입니다: +`webContents`는 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 +상속받았습니다. 웹 페이지의 렌더링과 관리를 책임지며 +[`BrowserWindow`](browser-window.md)의 속성입니다. 다음은 `webContents` 객체에 +접근하는 예제입니다: ```javascript const BrowserWindow = require('electron').BrowserWindow; @@ -19,7 +20,8 @@ var webContents = win.webContents; ### Event: 'did-finish-load' -탐색 작업이 끝났을 때 발생하는 이벤트입니다. 브라우저의 탭의 스피너가 멈추고 `onload` 이벤트가 발생했을 때를 말합니다. +탐색 작업이 끝났을 때 발생하는 이벤트입니다. 브라우저의 탭의 스피너가 멈추고 `onload` +이벤트가 발생했을 때를 말합니다. ### Event: 'did-fail-load' @@ -30,8 +32,10 @@ Returns: * `errorDescription` String * `validatedURL` String -이 이벤트는 `did-finish-load`와 비슷하나, 로드가 실패했거나 취소되었을 때 발생합니다. 예를 들면 `window.stop()`이 실행되었을 때 발생합니다. -발생할 수 있는 전체 에러 코드의 목록과 설명은 [여기](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h)서 확인할 수 있습니다. +이 이벤트는 `did-finish-load`와 비슷하나, 로드가 실패했거나 취소되었을 때 발생합니다. +예를 들면 `window.stop()`이 실행되었을 때 발생합니다. 발생할 수 있는 전체 에러 코드의 +목록과 설명은 [여기](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h)서 +확인할 수 있습니다. ### Event: 'did-frame-finish-load' @@ -126,8 +130,8 @@ Returns: 사용자 또는 페이지가 새로운 페이지로 이동할 때 발생하는 이벤트입니다. `window.location` 객체가 변경되거나 사용자가 페이지의 링크를 클릭했을 때 발생합니다. -이 이벤트는 `webContents.loadURL`과 `webContents.back` 같은 API를 이용하여 프로그램적으로 -시작된 탐색에 대해서는 발생하지 않습니다. +이 이벤트는 `webContents.loadURL`과 `webContents.back` 같은 API를 이용하여 +프로그램적으로 시작된 탐색에 대해서는 발생하지 않습니다. `event.preventDefault()`를 호출하면 탐색을 방지할 수 있습니다. @@ -200,8 +204,9 @@ webContents에서 사용되는 `session`객체를 반환합니다. * `userAgent` String - 요청을 시작한 유저 에이전트. * `extraHeaders` String - "\n"로 구분된 Extra 헤더들. -윈도우에 웹 페이지 `url`을 로드합니다. `url`은 `http://` or `file://`과 같은 프로토콜 접두사를 가지고 있어야 합니다. -만약 반드시 http 캐시를 사용하지 않고 로드해야 하는 경우 `pragma` 헤더를 사용할 수 있습니다. +윈도우에 웹 페이지 `url`을 로드합니다. `url`은 `http://` or `file://`과 같은 +프로토콜 접두사를 가지고 있어야 합니다. 만약 반드시 http 캐시를 사용하지 않고 로드해야 +하는 경우 `pragma` 헤더를 사용할 수 있습니다. ```javascript const options = {"extraHeaders" : "pragma: no-cache\n"} @@ -308,8 +313,9 @@ CSS 코드를 현재 웹 페이지에 삽입합니다. 페이지에서 자바스크립트 코드를 실행합니다. -기본적으로 `requestFullScreen`와 같은 몇몇 HTML API들은 사용자의 조작에 의해서만 호출될 수 있습니다. -`userGesture`를 `true`로 설정하면 이러한 제약을 무시할 수 있습니다. +기본적으로 `requestFullScreen`와 같은 몇몇 HTML API들은 사용자의 조작에 의해서만 +호출될 수 있습니다. `userGesture`를 `true`로 설정하면 이러한 제약을 무시할 수 +있습니다. ### `webContents.setAudioMuted(muted)` @@ -373,14 +379,15 @@ CSS 코드를 현재 웹 페이지에 삽입합니다. * `callback` Function -ServiceWorker가 등록되어있는지 확인하고 `callback`에 대한 응답으로 boolean 값을 반환합니다. +ServiceWorker가 등록되어있는지 확인하고 `callback`에 대한 응답으로 boolean 값을 +반환합니다. ### `webContents.unregisterServiceWorker(callback)` * `callback` Function -ServiceWorker가 존재하면 모두 등록을 해제하고 JS Promise가 만족될 때 `callback`에 대한 -응답으로 boolean을 반환하거나 JS Promise가 만족되지 않을 때 `false`를 반환합니다. +ServiceWorker가 존재하면 모두 등록을 해제하고 JS Promise가 만족될 때 `callback`에 +대한 응답으로 boolean을 반환하거나 JS Promise가 만족되지 않을 때 `false`를 반환합니다. ### `webContents.print([options])` @@ -390,14 +397,16 @@ ServiceWorker가 존재하면 모두 등록을 해제하고 JS Promise가 만족 * `printBackground` Boolean - 웹 페이지의 배경 색과 이미지를 출력합니다. 기본값은 `false`입니다. -윈도우의 웹 페이지를 프린트합니다. `silent`가 `false`로 지정되어있을 땐, Electron이 시스템의 -기본 프린터와 기본 프린터 설정을 가져옵니다. +윈도우의 웹 페이지를 프린트합니다. `silent`가 `false`로 지정되어있을 땐, Electron이 +시스템의 기본 프린터와 기본 프린터 설정을 가져옵니다. 웹 페이지에서 `window.print()`를 호출하는 것은 -`webContents.print({silent: false, printBackground: false})`를 호출하는 것과 같습니다. +`webContents.print({silent: false, printBackground: false})`를 호출하는 것과 +같습니다. -**Note:** Windows에서의 프린터 API는 `pdf.dll`에 의존합니다. -어플리케이션이 print 기능을 사용하지 않는 경우 전체 바이너리 크기를 줄이기 위해 `pdf.dll`을 삭제해도 됩니다. +**참고:** Windows에서의 프린터 API는 `pdf.dll`에 의존합니다. 따라서 어플리케이션이 +print기능을 사용하지 않는 경우 전체 바이너리 크기를 줄이기 위해 `pdf.dll`을 삭제해도 +됩니다. ### `webContents.printToPDF(options, callback)` @@ -423,7 +432,8 @@ ServiceWorker가 존재하면 모두 등록을 해제하고 JS Promise가 만족 * `error` Error * `data` Buffer - PDF 파일 내용. -Chromium의 미리보기 프린팅 커스텀 설정을 이용하여 윈도우의 웹 페이지를 PDF로 프린트합니다. +Chromium의 미리보기 프린팅 커스텀 설정을 이용하여 윈도우의 웹 페이지를 PDF로 +프린트합니다. 기본으로 비어있는 `options`은 다음과 같이 여겨지게 됩니다: @@ -507,8 +517,9 @@ win.webContents.on("did-finish-load", function() { * `channel` String * `arg` (optional) -`channel`을 통하여 렌더러 프로세스에 비동기 메시지를 보냅ㄹ니다. 임의의 아규먼트를 보낼수도 있습니다. -렌더러 프로세스는 `ipcRenderer` 모듈을 통하여 `channel`를 리슨하여 메시지를 처리할 수 있습니다. +`channel`을 통하여 렌더러 프로세스에 비동기 메시지를 보냅니다. 임의의 인수를 보낼수도 +있습니다. 렌더러 프로세스는 `ipcRenderer` 모듈을 통하여 `channel`를 리슨하여 메시지를 +처리할 수 있습니다. 메인 프로세스에서 렌더러 프로세스로 메시지를 보내는 예시 입니다: @@ -545,42 +556,43 @@ app.on('ready', function() { (기본값: `desktop`) * `desktop` * `mobile` -* `screenSize` Object - 에뮬레이트 화면의 크기를 지정합니다 (screenPosition == mobile) +* `screenSize` Object - 에뮬레이트 화면의 크기를 지정합니다 (screenPosition == + mobile) * `width` Integer - 에뮬레이트 화면의 너비를 지정합니다 * `height` Integer - 에뮬레이트 화면의 높이를 지정합니다 -* `viewPosition` Object - 화면에서 뷰의 위치 - (screenPosition == mobile) (기본값: `{x: 0, y: 0}`) +* `viewPosition` Object - 화면에서 뷰의 위치 (screenPosition == mobile) (기본값: + `{x: 0, y: 0}`) * `x` Integer - 좌상단 모서리로부터의 x 축의 오프셋 * `y` Integer - 좌상단 모서리로부터의 y 축의 오프셋 * `deviceScaleFactor` Integer - 디바이스의 스케일 팩터(scale factor)를 지정합니다. - (0일 경우 기본 디바이스 스케일 팩터를 기본으로 사용합니다) (기본값: `0`) -* `viewSize` Object - 에뮬레이트 된 뷰의 크기를 지정합니다 (빈 값은 오버라이드 하지 않는 다는 - 것을 의미합니다) + (0일 경우 기본 디바이스 스케일 팩터를 기본으로 사용합니다. 기본값: `0`) +* `viewSize` Object - 에뮬레이트 된 뷰의 크기를 지정합니다 (빈 값은 덮어쓰지 않는 + 다는 것을 의미합니다) * `width` Integer - 에뮬레이트 된 뷰의 너비를 지정합니다 * `height` Integer - 에뮬레이트 된 뷰의 높이를 지정합니다 -* `fitToView` Boolean - 에뮬레이트의 뷰가 사용 가능한 공간에 맞추어 스케일 다운 될지 여부를 +* `fitToView` Boolean - 에뮬레이트의 뷰가 사용 가능한 공간에 맞추어 스케일 다운될지를 지정합니다 (기본값: `false`) -* `offset` Object - 사용 가능한 공간에서 에뮬레이트 된 뷰의 오프셋을 지정합니다 - (fit to view 모드 외에서) (기본값: `{x: 0, y: 0}`) +* `offset` Object - 사용 가능한 공간에서 에뮬레이트 된 뷰의 오프셋을 지정합니다 (fit + to view 모드 외에서) (기본값: `{x: 0, y: 0}`) * `x` Float - 좌상단 모서리에서 x 축의 오프셋을 지정합니다 * `y` Float - 좌상단 모서리에서 y 축의 오프셋을 지정합니다 -* `scale` Float - 사용 가능한 공간에서 에뮬레이드 된 뷰의 스케일 (fit to view 모드 외에서) - (기본값: `1`) +* `scale` Float - 사용 가능한 공간에서 에뮬레이드 된 뷰의 스케일 (fit to view 모드 + 외에서, 기본값: `1`) -주어진 파라미터로 디바이스 에뮬레이션을 사용합니다. +`parameters`로 디바이스 에뮬레이션을 사용합니다. ### `webContents.disableDeviceEmulation()` -`webContents.enableDeviceEmulation`로 사용가능해진 디바이스 에뮬레이선을 비활성화 합니다. +`webContents.enableDeviceEmulation`로 활성화된 디바이스 에뮬레이선을 비활성화 합니다. ### `webContents.sendInputEvent(event)` * `event` Object - * `type` String (**required**) - 이벤트의 타입. 다음 값들을 사용할 수 있습니다: `mouseDown`, - `mouseUp`, `mouseEnter`, `mouseLeave`, `contextMenu`, `mouseWheel`, - `mouseMove`, `keyDown`, `keyUp`, `char`. - * `modifiers` Array - 이벤트의 수정자(modifier)들에 대한 배열. 다음 값들을 포함 할 수 - 있습니다: `shift`, `control`, `alt`, `meta`, `isKeypad`, `isAutoRepeat`, + * `type` String (**required**) - 이벤트의 타입. 다음 값들을 사용할 수 있습니다: + `mouseDown`, `mouseUp`, `mouseEnter`, `mouseLeave`, `contextMenu`, + `mouseWheel`, `mouseMove`, `keyDown`, `keyUp`, `char`. + * `modifiers` Array - 이벤트의 수정자(modifier)들에 대한 배열. 다음 값들을 포함 + 할 수 있습니다: `shift`, `control`, `alt`, `meta`, `isKeypad`, `isAutoRepeat`, `leftButtonDown`, `middleButtonDown`, `rightButtonDown`, `capsLock`, `numLock`, `left`, `right`. @@ -588,10 +600,11 @@ Input `event`를 웹 페이지로 전송합니다. 키보드 이벤트들에 대해서는 `event` 객체는 다음 속성들을 사용할 수 있습니다: -* `keyCode` Char or String (**required**) - 키보드 이벤트로 보내지는 문자. - 단일 UTF-8 문자를 사용할 수 있고 이벤트를 발생시키는 다음 키 중 하나를 포함할 수 있습니다: - `enter`, `backspace`, `delete`, `tab`, `escape`, `control`, `alt`, `shift`, `end`, - `home`, `insert`, `left`, `up`, `right`, `down`, `pageUp`, `pageDown`, `printScreen` +* `keyCode` Char or String (**required**) - 키보드 이벤트로 보내지는 문자. 단일 + UTF-8 문자를 사용할 수 있고 이벤트를 발생시키는 다음 키 중 하나를 포함할 수 있습니다: + `enter`, `backspace`, `delete`, `tab`, `escape`, `control`, `alt`, `shift`, + `end`, `home`, `insert`, `left`, `up`, `right`, `down`, `pageUp`, `pageDown`, + `printScreen` 마우스 이벤트들에 대해서는 `event` 객체는 다음 속성들을 사용할 수 있습니다: @@ -619,13 +632,14 @@ Input `event`를 웹 페이지로 전송합니다. * `callback` Function -프레젠테이션 이벤트들과 캡쳐된 프레임들에 대한 구독을 시작하면 `callback`이 프레젠테이션 이벤트가 -발생할 때 `callback(frameBuffer)`과 같은 형식으로 호출됩니다. +캡처된 프레임과 프레젠테이션 이벤트를 구독하기 시작합니다. `callback`은 +프레젠테이션 이벤트가 발생했을 때 `callback(frameBuffer)` 형태로 호출됩니다. -`frameBuffer`는 raw 픽셀 데이터를 포함한 `Buffer`입니다. 대부분의 기계에서 픽셀 데이터는 32bit -BGRA 포맷으로 효율적으로 저장됩니다. 하지만 실제 재프리젠테이션은 프로세서의 endianness에 의존성을 -가지고 있습니다(대부분의 현재 프로세스들은 little-endian입니다. big-endian 프로세서들를 가진 -기계들에서 data는 32bit ARGB format입니다). +`frameBuffer`는 raw 픽셀 데이터를 가지고 있는 `Buffer` 객체입니다. 많은 장치에서 +32비트 BGRA 포맷을 사용하여 효율적으로 픽셀 데이터를 저장합니다. 하지만 실질적인 +데이터 저장 방식은 프로세서의 엔디안 방식에 따라서 달라집니다. (따라서 현대의 많은 +프로세서에선 little-endian 방식을 사용하므로 위의 포맷을 그대로 표현합니다. 하지만 +몇몇 프로세서는 big-endian 방식을 사용하는데, 이 경우 32비트 ARGB 포맷을 사용합니다) ### `webContents.endFrameSubscription()` @@ -639,7 +653,8 @@ BGRA 포맷으로 효율적으로 저장됩니다. 하지만 실제 재프리젠 이 `WebContents`에 대한 개발자 도구의 `WebContents`를 가져옵니다. -**Note:** 사용자가 절대로 이 객체를 저장해서는 안 됩니다. 개발자 도구가 닫혔을 때, `null`이 반환될 수 있습니다. +**참고:** 사용자가 절대로 이 객체를 저장해서는 안 됩니다. 개발자 도구가 닫혔을 때, +`null`이 반환될 수 있습니다. ### `webContents.savePage(fullPath, saveType, callback)` diff --git a/docs-translations/ko-KR/api/web-frame.md b/docs-translations/ko-KR/api/web-frame.md index 5b94a9a6ad71..2e4a469b5485 100644 --- a/docs-translations/ko-KR/api/web-frame.md +++ b/docs-translations/ko-KR/api/web-frame.md @@ -1,6 +1,7 @@ # webFrame -`web-frame` 모듈은 현재 웹 페이지의 랜더링 상태를 설정 할 수 있도록 관련 유틸리티를 제공하는 모듈입니다. +`web-frame` 모듈은 현재 웹 페이지의 랜더링 상태를 설정 할 수 있도록 관련 유틸리티를 +제공하는 모듈입니다. 다음 예제는 현재 페이지를 200% 줌 합니다: @@ -18,7 +19,8 @@ webFrame.setZoomFactor(2); * `factor` Number - Zoom 값 -지정한 값으로 페이지를 줌 합니다. 줌 값은 퍼센트를 100으로 나눈 값입니다. (예시: 300% = 3.0) +지정한 값으로 페이지를 줌 합니다. 줌 값은 퍼센트를 100으로 나눈 값입니다. +(예시: 300% = 3.0) ### `webFrame.getZoomFactor()` @@ -28,8 +30,9 @@ webFrame.setZoomFactor(2); * `level` Number - Zoom level -지정한 레벨로 줌 레벨을 변경합니다. 0은 "기본 크기" 입니다. -그리고 각각 레벨 값을 올리거나 내릴 때마다 20%씩 커지거나 작아지고 기본 크기의 50%부터 300%까지 조절 제한이 있습니다. +지정한 레벨로 줌 레벨을 변경합니다. 0은 "기본 크기" 입니다. 그리고 각각 레벨 값을 +올리거나 내릴 때마다 20%씩 커지거나 작아지고 기본 크기의 50%부터 300%까지 조절 제한이 +있습니다. ### `webFrame.getZoomLevel()` @@ -50,7 +53,8 @@ webFrame.setZoomFactor(2); Input field나 text area에 철자 검사(spell checking) 제공자를 설정합니다. -`provider`는 반드시 전달된 단어의 철자가 맞았는지 검사하는 `spellCheck` 메소드를 가지고 있어야 합니다. +`provider`는 반드시 전달된 단어의 철자가 맞았는지 검사하는 `spellCheck` 메소드를 +가지고 있어야 합니다. [node-spellchecker][spellchecker]를 철자 검사 제공자로 사용하는 예제입니다: @@ -68,7 +72,8 @@ webFrame.setSpellCheckProvider("en-US", true, { 지정한 `scheme`을 보안 스킴으로 등록합니다. -보안 스킴은 혼합된 컨텐츠 경고를 발생시키지 않습니다. 예를 들어 `https` 와 `data`는 네트워크 공격자로부터 손상될 가능성이 없기 때문에 보안 스킴이라고 할 수 있습니다. +보안 스킴은 혼합된 컨텐츠 경고를 발생시키지 않습니다. 예를 들어 `https` 와 `data`는 +네트워크 공격자로부터 손상될 가능성이 없기 때문에 보안 스킴이라고 할 수 있습니다. ### `webFrame.registerURLSchemeAsBypassingCSP(scheme)` @@ -77,9 +82,9 @@ webFrame.setSpellCheckProvider("en-US", true, { 현재 페이지 컨텐츠의 보안 정책에 상관없이 `scheme`로부터 리소스가 로드됩니다. ### `webFrame.registerURLSchemeAsPrivileged(scheme)` - + * `scheme` String - + 보안 `scheme`를 지정합니다. 리소스와 ServiceWorker 설정에 대해 보안 정책을 우회합니다. [spellchecker]: https://github.com/atom/node-spellchecker diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index 7b3d259fdfc7..4ef7f47c853f 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -1,24 +1,29 @@ # `` 태그 -`guest` 컨텐츠(웹 페이지)를 Electron 앱 페이지에 삽입하기 위해 `webview` 태그를 사용할 수 있습니다. -게스트 컨텐츠는 `webview` 컨테이너에 담겨 대상 페이지에 삽입되고 해당 페이지에선 게스트 컨텐츠의 배치 및 렌더링 과정을 조작할 수 있습니다. +`guest` 컨텐츠(웹 페이지)를 Electron 앱 페이지에 삽입하기 위해 `webview` 태그를 +사용할 수 있습니다. 게스트 컨텐츠는 `webview` 컨테이너에 담겨 대상 페이지에 삽입되고 +해당 페이지에선 게스트 컨텐츠의 배치 및 렌더링 과정을 조작할 수 있습니다. `iframe`과는 달리 `webview`는 어플리케이션과 분리된 프로세스에서 작동합니다. -이는 웹 페이지와 같은 권한을 가지지 않고 앱과 임베디드(게스트) 컨텐츠간의 모든 상호작용이 비동기로 작동한다는 것을 의미합니다. -따라서 임베디드 컨텐츠로부터 어플리케이션을 안전하게 유지할 수 있습니다. +이는 웹 페이지와 같은 권한을 가지지 않고 앱과 임베디드(게스트) 컨텐츠간의 모든 +상호작용이 비동기로 작동한다는 것을 의미합니다. 따라서 임베디드 컨텐츠로부터 +어플리케이션을 안전하게 유지할 수 있습니다. ## 예제 -웹 페이지를 어플리케이션에 삽입하려면 `webview` 태그를 사용해 원하는 타겟 페이지에 추가하면 됩니다. (게스트 컨텐츠가 앱 페이지에 추가 됩니다) -간단한 예로 `webview` 태그의 `src` 속성에 페이지를 지정하고 css 스타일을 이용해서 컨테이너의 외관을 설정할 수 있습니다: +웹 페이지를 어플리케이션에 삽입하려면 `webview` 태그를 사용해 원하는 타겟 페이지에 +추가하면 됩니다. (게스트 컨텐츠가 앱 페이지에 추가 됩니다) 간단한 예로 `webview` +태그의 `src` 속성에 페이지를 지정하고 css 스타일을 이용해서 컨테이너의 외관을 설정할 +수 있습니다: ```html ``` -게스트 컨텐츠를 조작하기 위해 자바스크립트로 `webview` 태그의 이벤트를 리스닝 하여 응답을 받을 수 있습니다. -다음 예제를 참고하세요: 첫번째 리스너는 페이지 로딩 시작시의 이벤트를 확인하고 두번째 리스너는 페이지의 로딩이 끝난시점을 확인합니다. -그리고 페이지를 로드하는 동안 "loading..." 메시지를 표시합니다. +게스트 컨텐츠를 조작하기 위해 자바스크립트로 `webview` 태그의 이벤트를 리스닝 하여 +응답을 받을 수 있습니다. 다음 예제를 참고하세요: 첫번째 리스너는 페이지 로딩 시작시의 +이벤트를 확인하고 두번째 리스너는 페이지의 로딩이 끝난시점을 확인합니다. 그리고 +페이지를 로드하는 동안 "loading..." 메시지를 표시합니다. ```html -

Welcome to Electron

+

+ +

To run your app with Electron, execute the following command under your @@ -87,8 +91,18 @@

The path-to-your-app should be the path to your own Electron - app, you can read the quick start - guide in Electron's docs + app, you can read the + + guide in Electron's + on how to write one.

diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index 3916cfb2884e..49016c05ad2e 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -148,7 +148,11 @@ app.once('ready', function() { }, { label: 'Documentation', - click: function() { shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme') } + click: function() { + shell.openExternal( + `https://github.com/atom/electron/tree/v${process.versions.electron}/docs#readme` + ) + } }, { label: 'Community Discussions', @@ -249,7 +253,11 @@ if (option.file && !option.webdriver) { } catch(e) { if (e.code == 'MODULE_NOT_FOUND') { app.focus(); - dialog.showErrorBox('Error opening app', 'The app provided is not a valid electron app, please read the docs on how to write one:\nhttps://github.com/atom/electron/tree/master/docs\n\n' + e.toString()); + dialog.showErrorBox( + 'Error opening app', + 'The app provided is not a valid Electron app, please read the docs on how to write one:\n' + + `https://github.com/atom/electron/tree/v${process.versions.electron}/docs\n\n${e.toString()}` + ); process.exit(1); } else { console.error('App threw an error when running', e); From 4d4bb0a73e2fd01347dfe569d177e56572ed23da Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 21 Nov 2015 02:32:53 +0200 Subject: [PATCH 597/738] Added ctags cache files to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b8a221c9e52f..eb9aedb4e2f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +.tags* /.idea/ /build/ /dist/ From 5730d588d0debf86d25781d540c7e6c8aee5bb0d Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 21 Nov 2015 03:31:52 +0200 Subject: [PATCH 598/738] Add a note to readme about docs versioning Added a note to readme about using the correct docs version. Hopefully this will reduce users confusion. --- docs/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/README.md b/docs/README.md index 208ff8bf47b6..a1c8526e6ef5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,10 @@ +Please make sure that you use the documents that match your Electron version. +The version number should be a part of the URL. If it's not, you are probably +using the documentation of a development branch which may contain API changes +that are not compatible with your Electron version. +When in doubt, run Electron without supplying an app path, and click on the +`docs` link. + ## Guides * [Supported Platforms](tutorial/supported-platforms.md) From df8cc85d2c207e0e5f33de59e32079f4e9f5d7f1 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 21 Nov 2015 04:22:16 +0200 Subject: [PATCH 599/738] Rephrased the note --- docs/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/README.md b/docs/README.md index a1c8526e6ef5..9b6372524bd3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,9 +1,11 @@ Please make sure that you use the documents that match your Electron version. -The version number should be a part of the URL. If it's not, you are probably -using the documentation of a development branch which may contain API changes -that are not compatible with your Electron version. -When in doubt, run Electron without supplying an app path, and click on the -`docs` link. +The version number should be a part of the page URL. If it's not, you are +probably using the documentation of a development branch which may contain API +changes that are not compatible with your Electron version. If that's the case, +you can switch to a different version of the documentation at the +[available versions](http://electron.atom.io/docs/) list on atom.io, or if +you're using the GitHub interface, open the "Switch branches/tags" dropdown and +select the tag that matches your version. ## Guides From 1cf3216f50fde3a33e0fdb8aa8ab6e5a4db61cb3 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sat, 21 Nov 2015 13:15:37 +0900 Subject: [PATCH 600/738] Add missed translation --- docs-translations/ko-KR/api/app.md | 31 ++++++++++++++++++- docs-translations/ko-KR/api/web-contents.md | 33 +++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index 29f21547afc7..d41ce1ab37b9 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -139,6 +139,35 @@ Returns: 새로운 [browserWindow](browser-window.md)가 생성되었을 때 발생하는 이벤트 입니다. +### Event: 'certificate-error' + +Returns: + +* `event` Event +* `webContents` [WebContents](web-contents.md) +* `url` URL +* `error` String - 에러 코드 +* `certificate` Object + * `data` Buffer - PEM 인코딩된 데이터 + * `issuerName` String +* `callback` Function + +`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 { + callback(false); + } +}); +``` + ### Event: 'select-client-certificate' Returns: @@ -151,7 +180,7 @@ Returns: * `issuerName` String - 발급자의 공통 이름 * `callback` Function -사용자 인증이 요청되었을 때 발생하는 이벤트 입니다. +클라이언트 인증이 요청되었을 때 발생하는 이벤트 입니다. `url`은 클라이언트 인증서를 요청하는 탐색 항목에 해당합니다. 그리고 `callback`은 목록에서 필터링된 항목과 함께 호출될 필요가 있습니다. diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index d2255eb6d984..ac98afe7c84c 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -165,6 +165,39 @@ Returns: 개발자 도구에 포커스가 가거나 개발자 도구가 열렸을 때 발생되는 이벤트입니다. +### Event: 'certificate-error' + +Returns: + +* `event` Event +* `url` URL +* `error` String - 에러 코드 +* `certificate` Object + * `data` Buffer - PEM 인코딩된 데이터 + * `issuerName` String +* `callback` Function + +`url`에 대한 `certificate` 인증서의 유효성 검증에 실패했을 때 발생하는 이벤트입니다. + +사용법은 [`app`의 `certificate-error` 이벤트](app.md#event-certificate-error)와 +같습니다. + +### Event: 'select-client-certificate' + +Returns: + +* `event` Event +* `url` URL +* `certificateList` [Objects] + * `data` Buffer - PEM 인코딩된 데이터 + * `issuerName` String - 인증서 발급자 이름 +* `callback` Function + +클라이언트 인증이 요청되었을 때 발생하는 이벤트 입니다. + +사용법은 [`app`의 `select-client-certificate` 이벤트](app.md#event-select-client-certificate)와 +같습니다. + ### Event: 'login' Returns: From 18de28c3ff4340e88bf01265604d7e78c84cef27 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 21 Nov 2015 06:22:19 +0200 Subject: [PATCH 601/738] Make BrowserWindow options argument optional Resolves #3473 --- atom/browser/api/atom_api_window.cc | 14 ++++++++++++-- atom/browser/api/atom_api_window.h | 3 +-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 7f5b78a79780..a5aa4a126687 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -261,13 +261,23 @@ void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) { #endif // static -mate::Wrappable* Window::New(v8::Isolate* isolate, - const mate::Dictionary& options) { +mate::Wrappable* Window::New(v8::Isolate* isolate, mate::Arguments* args) { if (!Browser::Get()->is_ready()) { isolate->ThrowException(v8::Exception::Error(mate::StringToV8( isolate, "Cannot create BrowserWindow before app is ready"))); return nullptr; } + + if (args->Length() > 1) { + args->ThrowError(); + return nullptr; + } + + mate::Dictionary options; + if (!(args->Length() == 1 && args->GetNext(&options))) { + options = mate::Dictionary::CreateEmpty(isolate); + } + return new Window(isolate, options); } diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 4161584206a7..757abd205b31 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -38,8 +38,7 @@ class WebContents; class Window : public mate::TrackableObject, public NativeWindowObserver { public: - static mate::Wrappable* New(v8::Isolate* isolate, - const mate::Dictionary& options); + static mate::Wrappable* New(v8::Isolate* isolate, mate::Arguments* args); static void BuildPrototype(v8::Isolate* isolate, v8::Local prototype); From ab693ca571fce1682f43092f34e7bea157d79e92 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 21 Nov 2015 06:42:40 +0200 Subject: [PATCH 602/738] Update docs --- docs/api/browser-window.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 52b1bb8d5c5e..f86f6e685655 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -25,17 +25,17 @@ You can also create a window without chrome by using It creates a new `BrowserWindow` with native properties as set by the `options`. -### `new BrowserWindow(options)` +### `new BrowserWindow([options])` -`options` Object, properties: +`options` Object (optional), properties: -* `width` Integer - Window's width. -* `height` Integer - Window's height. +* `width` Integer - Window's width. Default is 800 pixels. +* `height` Integer - Window's height. Default is 600 pixels. * `x` Integer - Window's left offset from screen. * `y` Integer - Window's top offset from screen. * `useContentSize` Boolean - The `width` and `height` would be used as web page's size, which means the actual window's size will include window - frame's size and be slightly larger. + frame's size and be slightly larger. Default is `false`. * `center` Boolean - Show window in the center of the screen. * `minWidth` Integer - Window's minimum width. * `minHeight` Integer - Window's minimum height. @@ -51,7 +51,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `title` String - Default window title. * `icon` [NativeImage](native-image.md) - The window icon, when omitted on Windows the executable's icon would be used as window icon. -* `show` Boolean - Whether window should be shown when created. +* `show` Boolean - Whether window should be shown when created. Default is +`true`. * `frame` Boolean - Specify `false` to create a [Frameless Window](frameless-window.md). * `acceptFirstMouse` Boolean - Whether the web view accepts a single From 4027d04662542b94ed5196a6bb190539c516171f Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 21 Nov 2015 06:58:17 +0200 Subject: [PATCH 603/738] Add test --- spec/api-browser-window-spec.coffee | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 00437ae412ba..8df4c9a9479e 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -322,3 +322,11 @@ describe 'browser-window module', -> done() w.loadURL "file://#{fixtures}/pages/save_page/index.html" + + describe 'BrowserWindow options argument is optional', -> + it 'should create a window with default size (800x600)', -> + w.destroy() + w = new BrowserWindow() + size = w.getSize() + assert.equal size[0], 800 + assert.equal size[1], 600 From 651254424d1427d21a7446e827d366f2820d2e92 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sat, 21 Nov 2015 21:50:23 +0200 Subject: [PATCH 604/738] Expand the descriptions of options with defaults Resolves #3367 --- docs/api/browser-window.md | 93 ++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index f86f6e685655..15135d5eb464 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -29,46 +29,54 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. `options` Object (optional), properties: -* `width` Integer - Window's width. Default is 800 pixels. -* `height` Integer - Window's height. Default is 600 pixels. -* `x` Integer - Window's left offset from screen. -* `y` Integer - Window's top offset from screen. +* `width` Integer - Window's width in pixels. Default is `800`. +* `height` Integer - Window's height in pixels. Default is `600`. +* `x` Integer - Window's left offset from screen. Default is to center the +window. +* `y` Integer - Window's top offset from screen. Default is to center the +window. * `useContentSize` Boolean - The `width` and `height` would be used as web page's size, which means the actual window's size will include window frame's size and be slightly larger. Default is `false`. * `center` Boolean - Show window in the center of the screen. -* `minWidth` Integer - Window's minimum width. -* `minHeight` Integer - Window's minimum height. -* `maxWidth` Integer - Window's maximum width. -* `maxHeight` Integer - Window's maximum height. -* `resizable` Boolean - Whether window is resizable. +* `minWidth` Integer - Window's minimum width. Default is `0`. +* `minHeight` Integer - Window's minimum height. Default is `0`. +* `maxWidth` Integer - Window's maximum width. Default is no limit. +* `maxHeight` Integer - Window's maximum height. Default is no limit. +* `resizable` Boolean - Whether window is resizable. Default is `true`. * `alwaysOnTop` Boolean - Whether the window should always stay on top of - other windows. + other windows. Default is `false`. * `fullscreen` Boolean - Whether the window should show in fullscreen. When set to `false` the fullscreen button will be hidden or disabled on OS X. -* `skipTaskbar` Boolean - Whether to show the window in taskbar. -* `kiosk` Boolean - The kiosk mode. -* `title` String - Default window title. + Default is `false`. +* `skipTaskbar` Boolean - Whether to show the window in taskbar. Default is +`false`. +* `kiosk` Boolean - The kiosk mode. Default is `false`. +* `title` String - Default window title. Default is `"Electron"`. * `icon` [NativeImage](native-image.md) - The window icon, when omitted on Windows the executable's icon would be used as window icon. * `show` Boolean - Whether window should be shown when created. Default is `true`. * `frame` Boolean - Specify `false` to create a -[Frameless Window](frameless-window.md). +[Frameless Window](frameless-window.md). Default is `true`. * `acceptFirstMouse` Boolean - Whether the web view accepts a single - mouse-down event that simultaneously activates the window. -* `disableAutoHideCursor` Boolean - Whether to hide cursor when typing. + mouse-down event that simultaneously activates the window. Default is `false`. +* `disableAutoHideCursor` Boolean - Whether to hide cursor when typing. Default +is `false`. * `autoHideMenuBar` Boolean - Auto hide the menu bar unless the `Alt` - key is pressed. + key is pressed. Default is `false`. * `enableLargerThanScreen` Boolean - Enable the window to be resized larger - than screen. + than screen. Default is `false`. * `backgroundColor` String - Window's background color as Hexadecimal value, like `#66CD00` or `#FFF`. This is only implemented on Linux and Windows. + Default is `#000` (black). * `darkTheme` Boolean - Forces using dark theme for the window, only works on - some GTK+3 desktop environments. + some GTK+3 desktop environments. Default is `false`. * `transparent` Boolean - Makes the window [transparent](frameless-window.md). +Default is `false`. * `type` String - Specifies the type of the window, which applies - additional platform-specific properties. + additional platform-specific properties. By default it's undefined and you'll + get a regular app window. Supported values: * On Linux, possible types are `desktop`, `dock`, `toolbar`, `splash`, `notification`. * On OS X, possible types are `desktop`, `textured`. The `textured` type adds @@ -80,7 +88,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `titleBarStyle` String, OS X - specifies the style of window title bar. This option is supported on OS X 10.10 Yosemite and newer. There are three possible values: - * `default` or not specified results in the standard gray opaque Mac title + * `default` or not specified, results in the standard gray opaque Mac title bar. * `hidden` results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls ("traffic lights") in @@ -105,33 +113,38 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. `partition`, multiple pages can share the same session. If the `partition` is unset then default session of the app will be used. * `zoomFactor` Number - The default zoom factor of the page, `3.0` represents - `300%`. - * `javascript` Boolean + `300%`. Default is `1.0`. + * `javascript` Boolean - Enables JavaScript support. Default is `true`. * `webSecurity` Boolean - When setting `false`, it will disable the same-origin policy (Usually using testing websites by people), and set `allowDisplayingInsecureContent` and `allowRunningInsecureContent` to - `true` if these two options are not set by user. + `true` if these two options are not set by user. Default is `true`. * `allowDisplayingInsecureContent` Boolean - Allow an https page to display - content like images from http URLs. + content like images from http URLs. Default is `false`. * `allowRunningInsecureContent` Boolean - Allow a https page to run - JavaScript, CSS or plugins from http URLs. - * `images` Boolean - * `java` Boolean - * `textAreasAreResizable` Boolean - * `webgl` Boolean - * `webaudio` Boolean - * `plugins` Boolean - Whether plugins should be enabled. - * `experimentalFeatures` Boolean - * `experimentalCanvasFeatures` Boolean - * `overlayScrollbars` Boolean - * `overlayFullscreenVideo` Boolean - * `sharedWorker` Boolean - * `directWrite` Boolean - Whether the DirectWrite font rendering system on - Windows is enabled. + JavaScript, CSS or plugins from http URLs. Default is `false`. + * `images` Boolean - Enables image support. Default is `true`. + * `java` Boolean - Enables Java support. Default is `false`. + * `textAreasAreResizable` Boolean - Make TextArea elements resizable. Default + is `true`. + * `webgl` Boolean - Enables WebGL support. Default is `true`. + * `webaudio` Boolean - Enables WebAudio support. Default is `true`. + * `plugins` Boolean - Whether plugins should be enabled. Default is `false`. + * `experimentalFeatures` Boolean - Enables Chromium's experimental features. + Default is `false`. + * `experimentalCanvasFeatures` Boolean - Enables Chromium's experimental + canvas features. Default is `false`. + * `overlayScrollbars` Boolean - Enables overlay scrollbars. Default is + `false`. + * `overlayFullscreenVideo` Boolean - Enables overlay fullscreen video. Default + is `false` + * `sharedWorker` Boolean - Enables Shared Worker support. Default is `false`. + * `directWrite` Boolean - Enables DirectWrite font rendering system on + Windows. Default is `true`. * `pageVisibility` Boolean - Page would be forced to be always in visible or hidden state once set, instead of reflecting current window's visibility. Users can set it to `true` to prevent throttling of DOM - timers. + timers. Default is `false`. ## Events From 6db6842c14c3cd179c31581a42c51c7f71ae7f69 Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sun, 22 Nov 2015 01:13:57 +0200 Subject: [PATCH 605/738] Fix menu-item using deprecated API Some of the roles in menu-item use methods on BrowserWindow instead of WebContents which outputs a deprecation warning. I changed it to use the correct methods. --- atom/browser/api/lib/menu-item.coffee | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/lib/menu-item.coffee b/atom/browser/api/lib/menu-item.coffee index 92e2283b417d..57beb6ffdae3 100644 --- a/atom/browser/api/lib/menu-item.coffee +++ b/atom/browser/api/lib/menu-item.coffee @@ -13,6 +13,11 @@ rolesMap = minimize: 'minimize' close: 'close' +# Maps methods that should be called directly on the BrowserWindow instance +methodInBrowserWindow = + minimize: true + close: true + class MenuItem @types = ['normal', 'separator', 'submenu', 'checkbox', 'radio'] @@ -42,8 +47,12 @@ class MenuItem # Manually flip the checked flags when clicked. @checked = !@checked if @type in ['checkbox', 'radio'] - if @role and rolesMap[@role] and process.platform isnt 'darwin' - focusedWindow?[rolesMap[@role]]() + if @role and rolesMap[@role] and process.platform isnt 'darwin' and focusedWindow? + methodName = rolesMap[@role] + if methodInBrowserWindow[methodName] + focusedWindow[methodName]() + else + focusedWindow.webContents?[methodName]() else if typeof click is 'function' click this, focusedWindow else if typeof @selector is 'string' From b406774055577b5c18bb069fc05aa3dc72757eea Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Sun, 22 Nov 2015 19:50:52 +0900 Subject: [PATCH 606/738] Fix a typo in Korean quick-start tutotial --- docs-translations/ko-KR/tutorial/quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 8946f44716f2..b69a31b7926d 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -70,7 +70,7 @@ your-app/ __알림__: 만약 `main` 필드가 `package.json`에 설정되어 있지 않으면 Electron은 자동으로 같은 디렉터리의 `index.js`를 로드합니다. -반드시 `main.js`에서 창을 만들고 시스템 이밴트를 처리해야합니다. 대표적인 예제로 +반드시 `main.js`에서 창을 만들고 시스템 이벤트를 처리해야합니다. 대표적인 예제로 다음과 같이 작성할 수 있습니다: ```javascript From 10a7ecee464b0955af2c8abdedd72e3f86af6fd0 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Sun, 22 Nov 2015 19:55:36 +0900 Subject: [PATCH 607/738] Add space, too --- docs-translations/ko-KR/tutorial/quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index b69a31b7926d..cfdc19f00e9c 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -70,7 +70,7 @@ your-app/ __알림__: 만약 `main` 필드가 `package.json`에 설정되어 있지 않으면 Electron은 자동으로 같은 디렉터리의 `index.js`를 로드합니다. -반드시 `main.js`에서 창을 만들고 시스템 이벤트를 처리해야합니다. 대표적인 예제로 +반드시 `main.js`에서 창을 만들고 시스템 이벤트를 처리해야 합니다. 대표적인 예제로 다음과 같이 작성할 수 있습니다: ```javascript From df570269e36899d52617f3f0cd57796ca61247bd Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Sun, 22 Nov 2015 23:16:56 +0900 Subject: [PATCH 608/738] Fix typos in Korean api/ipc-main.md --- docs-translations/ko-KR/api/ipc-main.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs-translations/ko-KR/api/ipc-main.md b/docs-translations/ko-KR/api/ipc-main.md index 2dffcaf79ab1..6eb0d5527582 100644 --- a/docs-translations/ko-KR/api/ipc-main.md +++ b/docs-translations/ko-KR/api/ipc-main.md @@ -19,12 +19,12 @@ ```javascript // 메인 프로세스 const ipcMain = require('electron').ipcMain; -ipc.on('asynchronous-message', function(event, arg) { +ipcMain.on('asynchronous-message', function(event, arg) { console.log(arg); // "ping" 출력 event.sender.send('asynchronous-reply', 'pong'); }); -ipc.on('synchronous-message', function(event, arg) { +ipcMain.on('synchronous-message', function(event, arg) { console.log(arg); // "ping" 출력 event.returnValue = 'pong'; }); @@ -35,17 +35,17 @@ ipc.on('synchronous-message', function(event, arg) { const ipcRenderer = require('electron').ipcRenderer; console.log(ipc.sendSync('synchronous-message', 'ping')); // "pong" 출력 -ipc.on('asynchronous-reply', function(arg) { +ipcRenderer.on('asynchronous-reply', function(arg) { console.log(arg); // "pong" 출력 }); -ipc.send('asynchronous-message', 'ping'); +ipcRenderer.send('asynchronous-message', 'ping'); ``` ## 메시지 리스닝 `ipcMain`은 다음과 같은 이벤트 리스닝 메서드를 가지고 있습니다: -### `ipc.on(channel, callback)` +### `ipcMain.on(channel, callback)` * `channel` String - 이벤트 이름 * `callback` Function @@ -56,11 +56,11 @@ ipc.send('asynchronous-message', 'ping'); `callback`에서 전달된 `event` 객체는 다음과 같은 메서드와 속성을 가지고 있습니다: -### `Event.returnValue` +### `event.returnValue` 이 메시지를 지정하면 동기 메시지를 전달합니다. -### `Event.sender` +### `event.sender` 메시지를 보낸 `webContents` 객체를 반환합니다. `event.sender.send` 메서드를 통해 비동기로 메시지를 전달할 수 있습니다. 자세한 내용은 From fbdef9e1121b66463da8251168b7864ca51c9bf8 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Sun, 22 Nov 2015 09:08:35 -0800 Subject: [PATCH 609/738] Remove trailing colons from default menu roles `hideothers` and `unhide` had trailing colons which prevented them from being enabled / working in the default app. #3543 --- 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 3916cfb2884e..01a2a0d8764e 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -189,11 +189,11 @@ app.once('ready', function() { { label: 'Hide Others', accelerator: 'Command+Shift+H', - role: 'hideothers:' + role: 'hideothers' }, { label: 'Show All', - role: 'unhide:' + role: 'unhide' }, { type: 'separator' From 167f11e797227283effc765ef064ac5249367250 Mon Sep 17 00:00:00 2001 From: Robo Date: Sat, 21 Nov 2015 02:20:51 +0530 Subject: [PATCH 610/738] protocol: handle http responses with no content --- atom/browser/net/url_request_fetch_job.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/atom/browser/net/url_request_fetch_job.cc b/atom/browser/net/url_request_fetch_job.cc index a8a16e286b30..24a72226606e 100644 --- a/atom/browser/net/url_request_fetch_job.cc +++ b/atom/browser/net/url_request_fetch_job.cc @@ -181,6 +181,11 @@ void URLRequestFetchJob::Kill() { bool URLRequestFetchJob::ReadRawData(net::IOBuffer* dest, int dest_size, int* bytes_read) { + if (GetResponseCode() == 204) { + *bytes_read = 0; + request()->set_received_response_content_length(prefilter_bytes_read()); + return true; + } pending_buffer_ = dest; pending_buffer_size_ = dest_size; SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); @@ -207,6 +212,14 @@ int URLRequestFetchJob::GetResponseCode() const { } void URLRequestFetchJob::OnURLFetchComplete(const net::URLFetcher* source) { + if (!response_info_) { + // Since we notify header completion only after first write there will be + // no response object constructed for http respones with no content 204. + // We notify header completion here. + HeadersCompleted(); + return; + } + pending_buffer_ = nullptr; pending_buffer_size_ = 0; NotifyDone(fetcher_->GetStatus()); From baab0486f05d447bb93aaaef663ff4ba3e13d1be Mon Sep 17 00:00:00 2001 From: Eran Tiktin Date: Sun, 22 Nov 2015 23:44:20 +0200 Subject: [PATCH 611/738] Add documentation for --proxy-bypass-list Depends on atom/brightray#179 --- docs/api/chrome-command-line-switches.md | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index c1adf3c425f8..ad7fafbe14f5 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -1,9 +1,9 @@ # Supported Chrome command line switches -This page lists the command line switches used by the Chrome browser that are also supported by -Electron. You can use [app.commandLine.appendSwitch][append-switch] to append -them in your app's main script before the [ready][ready] event of [app][app] -module is emitted: +This page lists the command line switches used by the Chrome browser that are +also supported by Electron. You can use +[app.commandLine.appendSwitch][append-switch] to append them in your app's main +script before the [ready][ready] event of [app][app] module is emitted: ```javascript const app = require('electron').app; @@ -47,6 +47,20 @@ only affects requests with HTTP protocol, including HTTPS and WebSocket requests. It is also noteworthy that not all proxy servers support HTTPS and WebSocket requests. +## --proxy-bypass-list=`hosts` + +Instructs Electron to bypass the proxy server for the given semi-colon-separated +list of hosts. This flag has an effect only if used in tandem with +`--proxy-server`. + +For example: + +`app.commandLine.appendSwitch('proxy-bypass-list', ';*.google.com;*foo.com;1.2.3.4:5678')` + +Will use the proxy server for all hosts except for local addresses (localhost, +127.0.0.1 etc.), google.com subdomains, hosts that contain the suffix foo.com +and anything at 1.2.3.4:5678. + ## --proxy-pac-url=`url` Uses the PAC script at the specified `url`. From 6d46c3a75e984be04ee502f0c03018f9f8d6845c Mon Sep 17 00:00:00 2001 From: Sunny Date: Mon, 23 Nov 2015 13:40:23 +0800 Subject: [PATCH 612/738] docs: Fix deprecated usage tips --- docs/api/menu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/menu.md b/docs/api/menu.md index 1d819682160b..b5f2fbe9516e 100644 --- a/docs/api/menu.md +++ b/docs/api/menu.md @@ -225,7 +225,7 @@ will be set as each window's top menu. Sends the `action` to the first responder of application. This is used for emulating default Cocoa menu behaviors, usually you would just use the -`selector` property of `MenuItem`. +`role` property of `MenuItem`. ### `Menu.buildFromTemplate(template)` From ba8b448c366b796869437bd65491026117eb18cb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 23 Nov 2015 16:59:15 +0800 Subject: [PATCH 613/738] docs: Add indent for items in list Some markdown renderers require it to be able to render the list correctly. --- docs/api/browser-window.md | 25 ++++++++++++------------- docs/api/web-contents.md | 2 +- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 15135d5eb464..a987e2924615 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -32,9 +32,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `width` Integer - Window's width in pixels. Default is `800`. * `height` Integer - Window's height in pixels. Default is `600`. * `x` Integer - Window's left offset from screen. Default is to center the -window. + window. * `y` Integer - Window's top offset from screen. Default is to center the -window. + window. * `useContentSize` Boolean - The `width` and `height` would be used as web page's size, which means the actual window's size will include window frame's size and be slightly larger. Default is `false`. @@ -50,19 +50,19 @@ window. set to `false` the fullscreen button will be hidden or disabled on OS X. Default is `false`. * `skipTaskbar` Boolean - Whether to show the window in taskbar. Default is -`false`. + `false`. * `kiosk` Boolean - The kiosk mode. Default is `false`. * `title` String - Default window title. Default is `"Electron"`. * `icon` [NativeImage](native-image.md) - The window icon, when omitted on Windows the executable's icon would be used as window icon. * `show` Boolean - Whether window should be shown when created. Default is -`true`. + `true`. * `frame` Boolean - Specify `false` to create a -[Frameless Window](frameless-window.md). Default is `true`. + [Frameless Window](frameless-window.md). Default is `true`. * `acceptFirstMouse` Boolean - Whether the web view accepts a single mouse-down event that simultaneously activates the window. Default is `false`. * `disableAutoHideCursor` Boolean - Whether to hide cursor when typing. Default -is `false`. + is `false`. * `autoHideMenuBar` Boolean - Auto hide the menu bar unless the `Alt` key is pressed. Default is `false`. * `enableLargerThanScreen` Boolean - Enable the window to be resized larger @@ -73,7 +73,7 @@ is `false`. * `darkTheme` Boolean - Forces using dark theme for the window, only works on some GTK+3 desktop environments. Default is `false`. * `transparent` Boolean - Makes the window [transparent](frameless-window.md). -Default is `false`. + Default is `false`. * `type` String - Specifies the type of the window, which applies additional platform-specific properties. By default it's undefined and you'll get a regular app window. Supported values: @@ -102,7 +102,6 @@ Default is `false`. scripts run in the page. This script will always have access to node APIs no matter whether node integration is turned on or off. The value should be the absolute file path to the script. - When node integration is turned off, the preload script can reintroduce Node global symbols back to the global scope. See example [here](process.md#event-loaded). @@ -126,18 +125,18 @@ Default is `false`. * `images` Boolean - Enables image support. Default is `true`. * `java` Boolean - Enables Java support. Default is `false`. * `textAreasAreResizable` Boolean - Make TextArea elements resizable. Default - is `true`. + is `true`. * `webgl` Boolean - Enables WebGL support. Default is `true`. * `webaudio` Boolean - Enables WebAudio support. Default is `true`. * `plugins` Boolean - Whether plugins should be enabled. Default is `false`. * `experimentalFeatures` Boolean - Enables Chromium's experimental features. - Default is `false`. + Default is `false`. * `experimentalCanvasFeatures` Boolean - Enables Chromium's experimental - canvas features. Default is `false`. + canvas features. Default is `false`. * `overlayScrollbars` Boolean - Enables overlay scrollbars. Default is - `false`. + `false`. * `overlayFullscreenVideo` Boolean - Enables overlay fullscreen video. Default - is `false` + is `false` * `sharedWorker` Boolean - Enables Shared Worker support. Default is `false`. * `directWrite` Boolean - Enables DirectWrite font rendering system on Windows. Default is `true`. diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index a716bdc593a7..2612d6212279 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -349,7 +349,7 @@ this limitation. ### `webContents.setAudioMuted(muted)` -+ `muted` Boolean +* `muted` Boolean Mute the audio on the current web page. From 6636effb1defbb811e565eac6fe8b55c5ec898b2 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Tue, 24 Nov 2015 10:21:30 +0900 Subject: [PATCH 614/738] Update as upstream * Update as upstream * Add caution of translation version --- docs-translations/ko-KR/README.md | 15 ++- docs-translations/ko-KR/api/browser-window.md | 118 ++++++++++-------- docs-translations/ko-KR/api/menu.md | 2 +- docs-translations/ko-KR/api/web-contents.md | 2 +- 4 files changed, 81 insertions(+), 56 deletions(-) diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index d70894f8a96a..e6ea629c1e0a 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -1,4 +1,17 @@ -## 개발 가이드 +반드시 사용하는 Electron 버전과 문서 버전을 일치시켜야 합니다. 버전 숫자는 문서 페이지 +URL에 포함되어 있습니다. 만약 그렇지 않다면, 아마 현재 보고 있는 문서는 개발 중인 +브랜치의 문서를 보고 있을 가능성이 있으며 해당 문서는 추후 API의 변경 가능성이 있고 +현재 사용하고 있는 Electron의 버전과 호환되지 않을 수 있습니다. 이 경우 atom.io의 +[사용할 수 있는 버전](http://electron.atom.io/docs/) 목록에서 다른 버전으로 변경할 +수 있습니다. 또한 GitHub 인터페이스의 "Switch branches/tags" 드롭다운 메뉴에서도 +사용 중인 Electron 버전으로 변경할 수 있습니다. + +**역주:** 한국어 번역 문서는 atom.io에 반영이 되어있지 않습니다. 따라서 번역 문서는 +GitHub 프로젝트내에서만 볼 수 있고 `master` 브랜치의 문서는 현재 개발중인 프로젝트의 +문서입니다. 한국어 번역 문서는 현재 `upstream` 원본 문서의 변경에 따라 최대한 문서의 +버전을 맞추려고 노력하고 있지만 가끔 누락된 번역이 존재할 수 있습니다. + +## 개발 가이드 * [지원하는 플랫폼](tutorial/supported-platforms.md) * [어플리케이션 배포](tutorial/application-distribution.md) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 85357d8ba684..73b14e7db9ed 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -27,49 +27,55 @@ win.show(); `BrowserWindow`는 `options`를 통해 네이티브 속성을 포함한 새로운 윈도우 창을 생성합니다. -### `new BrowserWindow(options)` +### `new BrowserWindow([options])` -`options` 객체에서 사용할 수 있는 속성들: +`options` 객체 (optional), 사용할 수 있는 속성들: -* `width` Integer - 윈도우 창의 가로 너비. -* `height` Integer - 윈도우 창의 세로 높이. -* `x` Integer - 화면을 기준으로 창 좌측을 오프셋 한 위치. -* `y` Integer - 화면을 기준으로 창 상단을 오프셋 한 위치. +* `width` Integer - 윈도우 창의 가로 너비. 기본값은 `800`입니다. +* `height` Integer - 윈도우 창의 세로 높이. 기본값은 `600`입니다. +* `x` Integer - 화면을 기준으로 창 좌측을 오프셋 한 위치. 기본값은 화면 중앙입니다. +* `y` Integer - 화면을 기준으로 창 상단을 오프셋 한 위치. 기본값은 화면 중앙입니다. * `useContentSize` Boolean - `width`와 `height`를 웹 페이지의 크기로 사용합니다. 이 속성을 사용하면 웹 페이지의 크기에 윈도우 프레임 크기가 추가되므로 실제 창은 조금 - 더 커질 수 있습니다. + 더 커질 수 있습니다. 기본값은 `false`입니다. * `center` Boolean - 윈도우 창을 화면 정 중앙에 위치시킵니다. -* `minWidth` Integer - 윈도우 창의 최소 가로 너비. -* `minHeight` Integer - 윈도우 창의 최소 세로 높이. -* `maxWidth` Integer - 윈도우 창의 최대 가로 너비. -* `maxHeight` Integer - 윈도우 창의 최대 세로 높이. -* `resizable` Boolean - 윈도우 창의 크기를 재조정 할 수 있는지 여부. +* `minWidth` Integer - 윈도우 창의 최소 가로 너비. 기본값은 `0`입니다. +* `minHeight` Integer - 윈도우 창의 최소 세로 높이. 기본값은 `0`입니다. +* `maxWidth` Integer - 윈도우 창의 최대 가로 너비. 기본값은 `제한없음`입니다. +* `maxHeight` Integer - 윈도우 창의 최대 세로 높이. 기본값은 `제한없음`입니다. +* `resizable` Boolean - 윈도우 창의 크기를 재조정 할 수 있는지 여부. 기본값은 `true` + 입니다. * `alwaysOnTop` Boolean - 윈도우 창이 언제나 다른 창들 위에 유지되는지 여부. -* `fullscreen` Boolean - 윈도우 창의 전체화면 활성화 여부. + 기본값은 `false`입니다. +* `fullscreen` Boolean - 윈도우 창의 전체화면 활성화 여부. 기본값은 `false` 입니다. `false`로 지정했을 경우 OS X에선 전체화면 버튼이 숨겨지거나 비활성화됩니다. -* `skipTaskbar` Boolean - 작업표시줄 어플리케이션 아이콘 표시 여부. -* `kiosk` Boolean - Kiosk(키오스크) 모드. -* `title` String - 기본 윈도우 창 제목. +* `skipTaskbar` Boolean - 작업표시줄 어플리케이션 아이콘 표시 스킵 여부. 기본값은 + `false`입니다. +* `kiosk` Boolean - Kiosk(키오스크) 모드. 기본값은 `false`입니다. +* `title` String - 기본 윈도우 창 제목. 기본값은 `"Electron"`입니다. * `icon` [NativeImage](native-image.md) - 윈도우 아이콘, 생략하면 실행 파일의 아이콘이 대신 사용됩니다. -* `show` Boolean - 윈도우가 생성되면 보여줄지 여부. +* `show` Boolean - 윈도우가 생성되면 보여줄지 여부. 기본값은 `true`입니다. * `frame` Boolean - `false`로 지정하면 창을 [Frameless Window](frameless-window.md) - 형태로 생성합니다. + 형태로 생성합니다. 기본값은 `true`입니다. * `acceptFirstMouse` Boolean - 윈도우가 비활성화 상태일 때 내부 컨텐츠 클릭 시 - 활성화 되는 동시에 단일 mouse-down 이벤트를 발생시킬지 여부. -* `disableAutoHideCursor` Boolean - 파이핑중 자동으로 커서를 숨길지 여부. + 활성화 되는 동시에 단일 mouse-down 이벤트를 발생시킬지 여부. 기본값은 `false`입니다. +* `disableAutoHideCursor` Boolean - 파이핑중 자동으로 커서를 숨길지 여부. 기본값은 + `false`입니다. * `autoHideMenuBar` Boolean - `Alt`를 누르지 않는 한 어플리케이션 메뉴바를 숨길지 - 여부. + 여부. 기본값은 `false`입니다. * `enableLargerThanScreen` Boolean - 윈도우 창 크기가 화면 크기보다 크게 재조정 될 - 수 있는지 여부. + 수 있는지 여부. 기본값은 `false`입니다. * `backgroundColor` String - 16진수로 표현된 윈도우의 배경 색. `#66CD00` 또는 - `#FFF`가 사용될 수 있습니다. - 이 속성은 Linux와 Windows에만 구현되어 있습니다. + `#FFF`가 사용될 수 있습니다. 이 속성은 Linux와 Windows에만 구현되어 있습니다. + 기본값은 `#000`(검정)입니다. * `darkTheme` Boolean - 설정에 상관 없이 무조건 어두운 윈도우 테마를 사용합니다. - 몇몇 GTK+3 데스크톱 환경에서만 작동합니다. -* `transparent` Boolean - 윈도우 창을 [투명화](frameless-window.md)합니다. -* `type` String - 특정 플랫폼에만 적용되는 윈도우 창의 종류를 지정합니다. 사용할 수 - 있는 창의 종류는 다음과 같습니다: + 몇몇 GTK+3 데스크톱 환경에서만 작동합니다. 기본값은 `false`입니다. +* `transparent` Boolean - 윈도우 창을 [투명화](frameless-window.md)합니다. 기본값은 + `false`입니다. +* `type` String - 특정 플랫폼에만 적용되는 윈도우 창의 종류를 지정합니다. 기본적으로 + 이 속성이 `undefined`일 경우 표준 윈도우가 사용됩니다. 사용할 수 있는 창의 종류는 + 다음과 같습니다: * Linux의 경우: `desktop`, `dock`, `toolbar`, `splash`, `notification` 종류를 사용할 수 있습니다. * OS X의 경우: `desktop`, `textured` 종류를 사용할 수 있습니다. `textured` 종류는 @@ -93,11 +99,9 @@ win.show(); * `preload` String - 스크립트를 지정하면 페이지 내의 다른 스크립트가 작동하기 전에 로드됩니다. 여기서 지정한 스크립트는 node 통합 활성화 여부에 상관없이 언제나 모든 node API에 접근할 수 있습니다. 이 속성의 스크립트 경로는 절대 경로로 지정해야 - 합니다. - - note 통합이 비활성화되어있을 경우, preload 스크립트는 Node의 global 심볼들을 - 다시 global 스코프로 다시 포함 시킬 수 있습니다. [여기](process.md#event-loaded) - 의 예제를 참고하세요. + 합니다. node 통합이 비활성화되어있을 경우, preload 스크립트는 node의 global + 심볼들을 다시 global 스코프로 다시 포함 시킬 수 있습니다. + [여기](process.md#event-loaded)의 예제를 참고하세요. * `partition` String - 페이지에서 사용할 세션을 지정합니다. 만약 `partition`이 `persist:`로 시작하면 페이지는 지속성 세션을 사용하며 다른 모든 앱 내의 페이지에서 같은 `partition`을 사용할 수 있습니다. 만약 `persist:` 접두어로 @@ -105,32 +109,40 @@ win.show(); `partition`을 지정하면 같은 세션을 공유할 수 있습니다. `partition`을 지정하지 않으면 어플리케이션의 기본 세션이 사용됩니다. * `zoomFactor` Number - 페이지의 기본 줌 값을 지정합니다. 예를 들어 `300%`를 - 표현하려면 `3.0`으로 지정합니다. - * `javascript` Boolean + 표현하려면 `3.0`으로 지정합니다. 기본값은 `1.0`입니다. + * `javascript` Boolean - 자바스크립트를 활성화합니다. 기본값은 `false`입니다. * `webSecurity` Boolean - `false`로 지정하면 same-origin 정책을 비활성화합니다. - (이 속성은 보통 사람에 의해 웹 사이트를 테스트할 때 사용합니다) 그리고 - `allowDisplayingInsecureContent`와 `allowRunningInsecureContent`이 - 사용자로부터 `true`로 지정되지 않은 경우 `true`로 지정합니다. + (이 속성은 보통 사람들에 의해 웹 사이트를 테스트할 때 사용합니다) 그리고 + `allowDisplayingInsecureContent`와 `allowRunningInsecureContent` 두 속성을 + 사용자가 `true`로 지정되지 않은 경우 `true`로 지정합니다. 기본값은 + `true`입니다. * `allowDisplayingInsecureContent` Boolean - https 페이지에서 http URL에서 - 로드한 이미지 같은 리소스를 표시할 수 있도록 허용합니다. + 로드한 이미지 같은 리소스를 표시할 수 있도록 허용합니다. 기본값은 `false`입니다. * `allowRunningInsecureContent` Boolean - https 페이지에서 http URL에서 로드한 - JavaScript와 CSS 또는 플러그인을 실행시킬 수 있도록 허용합니다. - * `images` Boolean - * `java` Boolean - * `textAreasAreResizable` Boolean - * `webgl` Boolean - * `webaudio` Boolean - * `plugins` Boolean - 어떤 플러그인이 활성화되어야 하는지 지정합니다. - * `experimentalFeatures` Boolean - * `experimentalCanvasFeatures` Boolean - * `overlayScrollbars` Boolean - * `overlayFullscreenVideo` Boolean - * `sharedWorker` Boolean + JavaScript와 CSS 또는 플러그인을 실행시킬 수 있도록 허용합니다. 기본값은 + `false`입니다. + * `images` Boolean - 이미지 지원을 활성화합니다. 기본값은 `true`입니다. + * `java` Boolean - Java 지원을 활성화합니다. 기본값은 `false`입니다. + * `textAreasAreResizable` Boolean - HTML TextArea 요소의 크기를 재조정을 + 허용합니다. 기본값은 `true`입니다. + * `webgl` Boolean - WebGL 지원을 활성화합니다. 기본값은 `true`입니다. + * `webaudio` Boolean - WebAudio 지원을 활성화합니다. 기본값은 `true`입니다. + * `plugins` Boolean - 플러그인 활성화 여부를 지정합니다. 기본값은 `false`입니다. + * `experimentalFeatures` Boolean - Chrome의 실험적인 기능을 활성화합니다. + 기본값은 `false`입니다. + * `experimentalCanvasFeatures` Boolean - Chrome의 실험적인 캔버스(canvas) 기능을 + 활성화합니다. 기본값은 `false`입니다. + * `overlayScrollbars` Boolean - 오버레이 스크롤바를 활성화합니다. 기본값은 + `false`입니다. + * `overlayFullscreenVideo` Boolean - 오버레이 전체화면 비디오 기능을 활성화합니다. + 기본값은 `false`입니다. + * `sharedWorker` Boolean - SharedWorker 기능을 활성화합니다. 기본값은 + `false`입니다. * `directWrite` Boolean - Windows에서 폰트 랜더링을 위해 DirectWrite를 - 사용하는지를 지정합니다. + 사용하는지를 지정합니다. 기본값은 `true`입니다. * `pageVisibility` Boolean - 현재 윈도우의 가시성을 반영하는 대신 페이지가 visible 또는 hidden 중 지정된 상태를 계속 유지하도록 합니다. 이 속성을 `true`로 - 지정하면 DOM 타이머의 스로틀링을 방지할 수 있습니다. + 지정하면 DOM 타이머의 스로틀링을 방지할 수 있습니다. 기본값은 `false`입니다. ## Events diff --git a/docs-translations/ko-KR/api/menu.md b/docs-translations/ko-KR/api/menu.md index 3c5740de53a4..f01021ae1082 100644 --- a/docs-translations/ko-KR/api/menu.md +++ b/docs-translations/ko-KR/api/menu.md @@ -221,7 +221,7 @@ Linux에선 각 창의 상단에 표시됩니다. * `action` String `action`을 어플리케이션의 first responder에 전달합니다. 이 메서드는 Cocoa 메뉴 -동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem`의 `selector` 속성에 사용됩니다. +동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem`의 `role` 속성에 사용됩니다. **참고:** 이 메서드는 OS X에서만 사용할 수 있습니다. diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index ac98afe7c84c..c92149ce44a6 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -346,7 +346,7 @@ CSS 코드를 현재 웹 페이지에 삽입합니다. ### `webContents.setAudioMuted(muted)` -+ `muted` Boolean +* `muted` Boolean 현재 웹 페이지의 소리를 음소거합니다. From 6e6cee3ac671156307371dac43f2722f79a38746 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Tue, 24 Nov 2015 10:23:52 +0900 Subject: [PATCH 615/738] Small fixes --- docs-translations/ko-KR/api/browser-window.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 73b14e7db9ed..6ff934afa095 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -33,8 +33,8 @@ win.show(); * `width` Integer - 윈도우 창의 가로 너비. 기본값은 `800`입니다. * `height` Integer - 윈도우 창의 세로 높이. 기본값은 `600`입니다. -* `x` Integer - 화면을 기준으로 창 좌측을 오프셋 한 위치. 기본값은 화면 중앙입니다. -* `y` Integer - 화면을 기준으로 창 상단을 오프셋 한 위치. 기본값은 화면 중앙입니다. +* `x` Integer - 화면을 기준으로 창 좌측을 오프셋 한 위치. 기본값은 `화면중앙`입니다. +* `y` Integer - 화면을 기준으로 창 상단을 오프셋 한 위치. 기본값은 `화면중앙`입니다. * `useContentSize` Boolean - `width`와 `height`를 웹 페이지의 크기로 사용합니다. 이 속성을 사용하면 웹 페이지의 크기에 윈도우 프레임 크기가 추가되므로 실제 창은 조금 더 커질 수 있습니다. 기본값은 `false`입니다. From a4a14a5f0ef0ff3c1423720005f461a42bf4cd25 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 24 Nov 2015 15:14:48 +0800 Subject: [PATCH 616/738] Update brightray for #3458 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index d4fab33427eb..77eca8fcbc18 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit d4fab33427eb728a553896527f1931887ce6d9d9 +Subproject commit 77eca8fcbc18d2244b356045295f4472492cedb7 From 24e892dd17e51fbc984b828fcd9d2c91ee4cfeae Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 24 Nov 2015 18:39:16 +0800 Subject: [PATCH 617/738] Update brightray for #3550 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 77eca8fcbc18..8893a279435a 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 77eca8fcbc18d2244b356045295f4472492cedb7 +Subproject commit 8893a279435af82e3c2d4b4afe4d9d069f8a2820 From b9fd095b046856f07f58adbbf1dbee074b9bc0d7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 24 Nov 2015 18:40:50 +0800 Subject: [PATCH 618/738] docs: Mark code blocks --- docs/api/chrome-command-line-switches.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index ad7fafbe14f5..edeba0c9ad1b 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -55,11 +55,13 @@ list of hosts. This flag has an effect only if used in tandem with For example: -`app.commandLine.appendSwitch('proxy-bypass-list', ';*.google.com;*foo.com;1.2.3.4:5678')` +```javascript +app.commandLine.appendSwitch('proxy-bypass-list', ';*.google.com;*foo.com;1.2.3.4:5678')` +``` -Will use the proxy server for all hosts except for local addresses (localhost, -127.0.0.1 etc.), google.com subdomains, hosts that contain the suffix foo.com -and anything at 1.2.3.4:5678. +Will use the proxy server for all hosts except for local addresses (`localhost`, +`127.0.0.1` etc.), `google.com` subdomains, hosts that contain the suffix +`foo.com` and anything at `1.2.3.4:5678`. ## --proxy-pac-url=`url` From 4acbd3e03f95d1a908d6d2a191d150f01def37a4 Mon Sep 17 00:00:00 2001 From: laiso Date: Tue, 24 Nov 2015 21:02:14 +0900 Subject: [PATCH 619/738] s/loadUrl/loadURL/g in docs-translations/ --- docs-translations/es/api/synopsis.md | 2 +- docs-translations/es/tutorial/application-packaging.md | 2 +- docs-translations/es/tutorial/online-offline-events.md | 4 ++-- docs-translations/es/tutorial/using-pepper-flash-plugin.md | 2 +- docs-translations/pt-BR/tutorial/application-packaging.md | 4 ++-- docs-translations/pt-BR/tutorial/online-offline-events.md | 4 ++-- .../pt-BR/tutorial/using-pepper-flash-plugin.md | 2 +- docs-translations/zh-CN/tutorial/online-offline-events.md | 6 +++--- docs-translations/zh-TW/api/synopsis.md | 2 +- docs-translations/zh-TW/tutorial/online-offline-events.md | 4 ++-- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs-translations/es/api/synopsis.md b/docs-translations/es/api/synopsis.md index eb4fcb39f636..534fafcf2f7c 100644 --- a/docs-translations/es/api/synopsis.md +++ b/docs-translations/es/api/synopsis.md @@ -25,7 +25,7 @@ var window = null; app.on('ready', function() { window = new BrowserWindow({width: 800, height: 600}); - window.loadUrl('https://github.com'); + window.loadURL('https://github.com'); }); ``` diff --git a/docs-translations/es/tutorial/application-packaging.md b/docs-translations/es/tutorial/application-packaging.md index 56698c1aaecb..c0cca7ecd916 100644 --- a/docs-translations/es/tutorial/application-packaging.md +++ b/docs-translations/es/tutorial/application-packaging.md @@ -70,7 +70,7 @@ También puedes mostrar una página web contenida en un `asar` utilizando `Brows ```javascript var BrowserWindow = require('browser-window'); var win = new BrowserWindow({width: 800, height: 600}); -win.loadUrl('file:///path/to/example.asar/static/index.html'); +win.loadURL('file:///path/to/example.asar/static/index.html'); ``` ### API Web diff --git a/docs-translations/es/tutorial/online-offline-events.md b/docs-translations/es/tutorial/online-offline-events.md index 0e43f9b16109..450702e2f84c 100644 --- a/docs-translations/es/tutorial/online-offline-events.md +++ b/docs-translations/es/tutorial/online-offline-events.md @@ -12,7 +12,7 @@ var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ``` @@ -50,7 +50,7 @@ var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ipc.on('online-status-changed', function(event, status) { diff --git a/docs-translations/es/tutorial/using-pepper-flash-plugin.md b/docs-translations/es/tutorial/using-pepper-flash-plugin.md index 53d2d024c1d1..4e45524fb6af 100644 --- a/docs-translations/es/tutorial/using-pepper-flash-plugin.md +++ b/docs-translations/es/tutorial/using-pepper-flash-plugin.md @@ -46,7 +46,7 @@ app.on('ready', function() { 'plugins': true } }); - mainWindow.loadUrl('file://' + __dirname + '/index.html'); + mainWindow.loadURL('file://' + __dirname + '/index.html'); // Something else }); ``` diff --git a/docs-translations/pt-BR/tutorial/application-packaging.md b/docs-translations/pt-BR/tutorial/application-packaging.md index f55cbb2f7d64..209188b2f5f9 100644 --- a/docs-translations/pt-BR/tutorial/application-packaging.md +++ b/docs-translations/pt-BR/tutorial/application-packaging.md @@ -71,7 +71,7 @@ Você também pode renderizar uma página web apartir de um arquivo `asar` utili ```javascript var BrowserWindow = require('browser-window'); var win = new BrowserWindow({width: 800, height: 600}); -win.loadUrl('file:///path/to/example.asar/static/index.html'); +win.loadURL('file:///path/to/example.asar/static/index.html'); ``` ### API Web @@ -155,4 +155,4 @@ Depois de executar o comando, além do `app.asar`, há também `app.asar.unpacked` pasta gerada que contém os arquivos descompactados, você deve copiá-lo juntamente com `app.asar` quando enviá-lo para os usuários. -Mais informações no repositório [asar](https://github.com/atom/asar) \ No newline at end of file +Mais informações no repositório [asar](https://github.com/atom/asar) diff --git a/docs-translations/pt-BR/tutorial/online-offline-events.md b/docs-translations/pt-BR/tutorial/online-offline-events.md index 294a62e7a81c..8cdc1a6647e5 100644 --- a/docs-translations/pt-BR/tutorial/online-offline-events.md +++ b/docs-translations/pt-BR/tutorial/online-offline-events.md @@ -13,7 +13,7 @@ var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ``` @@ -53,7 +53,7 @@ var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ipc.on('online-status-changed', function(event, status) { diff --git a/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md b/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md index dfcca01a5c7e..e5222ba0772d 100644 --- a/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md +++ b/docs-translations/pt-BR/tutorial/using-pepper-flash-plugin.md @@ -54,7 +54,7 @@ app.on('ready', function() { 'plugins': true } }); - mainWindow.loadUrl('file://' + __dirname + '/index.html'); + mainWindow.loadURL('file://' + __dirname + '/index.html'); // Algo mais }); ``` diff --git a/docs-translations/zh-CN/tutorial/online-offline-events.md b/docs-translations/zh-CN/tutorial/online-offline-events.md index de292490f0be..764b81aa5d2f 100644 --- a/docs-translations/zh-CN/tutorial/online-offline-events.md +++ b/docs-translations/zh-CN/tutorial/online-offline-events.md @@ -9,7 +9,7 @@ var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ```` @@ -43,7 +43,7 @@ var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ipc.on('online-status-changed', function(event, status) { @@ -69,4 +69,4 @@ ipc.on('online-status-changed', function(event, status) { -```` \ No newline at end of file +```` diff --git a/docs-translations/zh-TW/api/synopsis.md b/docs-translations/zh-TW/api/synopsis.md index 484f5e353847..e28d1fd8cb0d 100644 --- a/docs-translations/zh-TW/api/synopsis.md +++ b/docs-translations/zh-TW/api/synopsis.md @@ -20,7 +20,7 @@ var window = null; app.on('ready', function() { window = new BrowserWindow({width: 800, height: 600}); - window.loadUrl('https://github.com'); + window.loadURL('https://github.com'); }); ``` diff --git a/docs-translations/zh-TW/tutorial/online-offline-events.md b/docs-translations/zh-TW/tutorial/online-offline-events.md index a4366f88a03a..234a02710eb7 100644 --- a/docs-translations/zh-TW/tutorial/online-offline-events.md +++ b/docs-translations/zh-TW/tutorial/online-offline-events.md @@ -12,7 +12,7 @@ var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ``` @@ -50,7 +50,7 @@ var onlineStatusWindow; app.on('ready', function() { onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }); - onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html'); + onlineStatusWindow.loadURL('file://' + __dirname + '/online-status.html'); }); ipc.on('online-status-changed', function(event, status) { From 0f5a3baff4f6d1bcfb1ff9efbb05eff9d5e14ebc Mon Sep 17 00:00:00 2001 From: Ryan Prichard Date: Tue, 24 Nov 2015 16:49:52 -0600 Subject: [PATCH 620/738] Fix https://github.com/atom/electron/issues/3565 by adding a typeof --- atom/browser/lib/rpc-server.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index ce63d9189664..d9b1047bc807 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -107,7 +107,7 @@ unwrapArgs = (sender, args) -> # style function and the caller didn't pass a callback. callFunction = (event, func, caller, args) -> funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous') - funcPassedCallback = args[args.length - 1] is 'function' + funcPassedCallback = typeof args[args.length - 1] is 'function' try if funcMarkedAsync and not funcPassedCallback From 34aecc9327755e4e904444128e7d26152371f434 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Wed, 25 Nov 2015 08:55:04 +0900 Subject: [PATCH 621/738] Update as upstream --- .../ko-KR/api/chrome-command-line-switches.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs-translations/ko-KR/api/chrome-command-line-switches.md b/docs-translations/ko-KR/api/chrome-command-line-switches.md index 3c825b1abb13..443a8f218743 100644 --- a/docs-translations/ko-KR/api/chrome-command-line-switches.md +++ b/docs-translations/ko-KR/api/chrome-command-line-switches.md @@ -49,6 +49,21 @@ $ electron --js-flags="--harmony_proxies --harmony_collections" your-app 그리고 WebSocket 요청에만 적용됩니다. 그리고 모든 프록시 서버가 HTTPS가 WebSocket 요청을 지원하지 않고 있을 수 있으므로 사용시 주의해야 합니다. +## --proxy-bypass-list=`hosts` + +Electron이 세미콜론으로 구분된 호스트 리스트에서 지정한 프록시 서버를 건너뛰도록 +지시합니다. + +예시: + +```javascript +app.commandLine.appendSwitch('proxy-bypass-list', ';*.google.com;*foo.com;1.2.3.4:5678')` +``` + +위 예시는 로컬 주소(`localhost`, `127.0.0.1`, 등)와 `google.com`의 서브도메인, +`foo.com`을 접미사로 가지는 호스트, `1.2.3.4:5678` 호스트를 제외한 모든 연결에서 +프록시 서버를 사용합니다. + ## --proxy-pac-url=`url` 지정한 `url`의 PAC 스크립트를 사용합니다. From 789380dfad09ca59950bb8228f3edb3ac5dc039d Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 25 Nov 2015 15:54:30 -0800 Subject: [PATCH 622/738] Ensure calling webview.send will not block the renderer When the browser process is busy, calling webview.send (a method that appears on its face to be non-blocking) will actually block, because most webview methods are remoted to a guest view instance in the browser. Instead, define a few methods which will instead send its call over an async IPC message. --- atom/browser/lib/rpc-server.coffee | 8 ++++++++ atom/renderer/lib/web-view/web-view.coffee | 24 +++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index ce63d9189664..8a67d2112ece 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -221,3 +221,11 @@ ipcMain.on 'ATOM_BROWSER_GUEST_WEB_CONTENTS', (event, guestInstanceId) -> ipcMain.on 'ATOM_BROWSER_LIST_MODULES', (event) -> event.returnValue = (name for name of electron) + +ipcMain.on 'ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', (event, guestInstanceId, method, args...) -> + try + guestViewManager = require './guest-view-manager' + guest = guestViewManager.getGuest(guestInstanceId) + guest[method].apply(guest, args) + catch e + event.returnValue = exceptionToMeta e diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 5e3f7d6bae56..720e6e84c5d4 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -1,4 +1,4 @@ -{deprecate, webFrame, remote} = require 'electron' +{deprecate, webFrame, remote, ipcRenderer} = require 'electron' v8Util = process.atomBinding 'v8_util' guestViewInternal = require './guest-view-internal' @@ -270,8 +270,6 @@ registerWebViewElement = -> 'isCrashed' 'setUserAgent' 'getUserAgent' - 'executeJavaScript' - 'insertCSS' 'openDevTools' 'closeDevTools' 'isDevToolsOpened' @@ -289,20 +287,32 @@ registerWebViewElement = -> 'unselect' 'replace' 'replaceMisspelling' - 'send' 'getId' 'inspectServiceWorker' 'print' 'printToPDF' - 'sendInputEvent' + ] + + nonblockMethods = [ + 'send', + 'sendInputEvent', + 'executeJavaScript', + 'insertCSS' ] # Forward proto.foo* method calls to WebViewImpl.foo*. - createHandler = (m) -> + createBlockHandler = (m) -> (args...) -> internal = v8Util.getHiddenValue this, 'internal' internal.webContents[m] args... - proto[m] = createHandler m for m in methods + proto[m] = createBlockHandler m for m in methods + + createNonBlockHandler = (m) -> + (args...) -> + internal = v8Util.getHiddenValue this, 'internal' + ipcRenderer.send('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', internal.guestInstanceId, m, args...) + + proto[m] = createNonBlockHandler m for m in nonblockMethods # Deprecated. deprecate.rename proto, 'getUrl', 'getURL' From 9c62be8fc998856fb6f5dbf032f85cacd3818659 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 26 Nov 2015 11:06:56 +0800 Subject: [PATCH 623/738] Improve the deprecation notice for ipc module Close #3577. --- atom/browser/api/lib/ipc.coffee | 2 +- atom/renderer/api/lib/ipc.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/lib/ipc.coffee b/atom/browser/api/lib/ipc.coffee index 8019a385dd90..018cb6bb0437 100644 --- a/atom/browser/api/lib/ipc.coffee +++ b/atom/browser/api/lib/ipc.coffee @@ -1,6 +1,6 @@ {deprecate, ipcMain} = require 'electron' # This module is deprecated, we mirror everything from ipcMain. -deprecate.warn 'ipc module', 'ipcMain module' +deprecate.warn 'ipc module', 'require("electron").ipcMain' module.exports = ipcMain diff --git a/atom/renderer/api/lib/ipc.coffee b/atom/renderer/api/lib/ipc.coffee index b0e951d70e48..edd7d29b6f06 100644 --- a/atom/renderer/api/lib/ipc.coffee +++ b/atom/renderer/api/lib/ipc.coffee @@ -2,7 +2,7 @@ {EventEmitter} = require 'events' # This module is deprecated, we mirror everything from ipcRenderer. -deprecate.warn 'ipc module', 'ipcRenderer module' +deprecate.warn 'ipc module', 'require("electron").ipcRenderer' # Routes events of ipcRenderer. ipc = new EventEmitter From 6c1878d15b8c34f1441565ebacaaf34247276b30 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 26 Nov 2015 13:55:59 +0800 Subject: [PATCH 624/738] mac: Clears the delegate when window is going to be closed Since EL Capitan it is possible that the methods of delegate would get called after the window has been closed. Refs atom/atom#9584. --- atom/browser/native_window_mac.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 7959eb04f55b..42894c107de4 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -192,6 +192,11 @@ bool ScopedDisableResize::disable_resize_ = false; - (void)windowWillClose:(NSNotification*)notification { shell_->NotifyWindowClosed(); + + // Clears the delegate when window is going to be closed, since EL Capitan it + // is possible that the methods of delegate would get called after the window + // has been closed. + [shell_->GetNativeWindow() setDelegate:nil]; } - (BOOL)windowShouldClose:(id)window { From b0d4aa211df8778d97047268c3e86e576adc7d39 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 26 Nov 2015 13:57:48 +0800 Subject: [PATCH 625/738] Fix compatibility with activate-with-no-open-windows event --- atom/browser/api/lib/app.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index a2fdb847e1c5..4d1803a0296f 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -54,7 +54,7 @@ deprecate.event app, 'finish-launching', 'ready', -> setImmediate => # give default app a chance to setup default menu. @emit 'finish-launching' deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) -> - @emit 'activate-with-no-open-windows' if not hasVisibleWindows + @emit 'activate-with-no-open-windows', event if not hasVisibleWindows deprecate.event app, 'select-certificate', 'select-client-certificate' # Wrappers for native classes. From fe4638ef332295e5a8b9e3b901060c37e2a96627 Mon Sep 17 00:00:00 2001 From: Vincent Quagliaro Date: Thu, 26 Nov 2015 09:05:02 +0100 Subject: [PATCH 626/738] :memo: open-file and open-url events are only available on OS X --- docs/api/app.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/api/app.md b/docs/api/app.md index 00aade7c54ab..cf4284586d1d 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -66,7 +66,7 @@ the `will-quit` and `window-all-closed` events. Emitted when the application is quitting. -### Event: 'open-file' +### Event: 'open-file' _OS X_ Returns: @@ -82,7 +82,9 @@ handle this case (even before the `ready` event is emitted). You should call `event.preventDefault()` if you want to handle this event. -### Event: 'open-url' +On Windows, you have to parse `process.argv` to get the filepath. + +### Event: 'open-url' _OS X_ Returns: From 5ee9e6144560294eaf6a2451e67f906ea4821e53 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 26 Nov 2015 19:10:43 +0800 Subject: [PATCH 627/738] Update brightray for #1369 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 8893a279435a..57842edb817c 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 8893a279435af82e3c2d4b4afe4d9d069f8a2820 +Subproject commit 57842edb817cc1ae38a02fd7f266dd6aa3afbb45 From b1e6d4f64c6aa841650340c87d743b794572bb24 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 26 Nov 2015 20:15:35 +0800 Subject: [PATCH 628/738] Check ELECTRON_RUN_AS_NODE env var --- atom/app/atom_main.cc | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/atom/app/atom_main.cc b/atom/app/atom_main.cc index 26dcb9421266..88bb137bae0f 100644 --- a/atom/app/atom_main.cc +++ b/atom/app/atom_main.cc @@ -36,10 +36,27 @@ #include "base/at_exit.h" #include "base/i18n/icu_util.h" -#if defined(OS_WIN) - namespace { +const char* kRunAsNode = "ELECTRON_RUN_AS_NODE"; +const char* kOldRunAsNode = "ATOM_SHELL_INTERNAL_RUN_AS_NODE"; + +bool IsEnvSet(const char* name) { +#if defined(OS_WIN) + size_t required_size; + getenv_s(&required_size, nullptr, 0, name); + return required_size != 0; +#else + char* indicator = getenv(name); + return indicator && indicator[0] != '\0'; +#endif +} + +bool IsRunAsNode() { + return IsEnvSet(kRunAsNode) || IsEnvSet(kOldRunAsNode); +} + +#if defined(OS_WIN) // Win8.1 supports monitor-specific DPI scaling. bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) { typedef HRESULT(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS); @@ -77,9 +94,11 @@ void EnableHighDPISupport() { SetProcessDPIAwareWrapper(); } } +#endif } // namespace +#if defined(OS_WIN) int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { int argc = 0; wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); @@ -131,16 +150,12 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { } } - std::string node_indicator, crash_service_indicator; - if (env->GetVar("ATOM_SHELL_INTERNAL_RUN_AS_NODE", &node_indicator) && - node_indicator == "1") { + if (IsRunAsNode()) { // Now that argv conversion is done, we can finally start. base::AtExitManager atexit_manager; base::i18n::InitializeICU(); return atom::NodeMain(argc, argv); - } else if (env->GetVar("ATOM_SHELL_INTERNAL_CRASH_SERVICE", - &crash_service_indicator) && - crash_service_indicator == "1") { + } else if (IsEnvSet("ATOM_SHELL_INTERNAL_CRASH_SERVICE")) { return crash_service::Main(cmd); } @@ -164,8 +179,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { #elif defined(OS_LINUX) // defined(OS_WIN) int main(int argc, const char* argv[]) { - char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE"); - if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) { + if (IsRunAsNode()) { base::i18n::InitializeICU(); base::AtExitManager atexit_manager; return atom::NodeMain(argc, const_cast(argv)); @@ -182,8 +196,7 @@ int main(int argc, const char* argv[]) { #else // defined(OS_LINUX) int main(int argc, const char* argv[]) { - char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE"); - if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) { + if (IsRunAsNode()) { return AtomInitializeICUandStartNode(argc, const_cast(argv)); } From 6534a0e616471c6bd577282f84e750c16ff699cf Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 26 Nov 2015 20:37:48 +0800 Subject: [PATCH 629/738] docs: Add Environment Variables --- docs/README.md | 1 + docs/api/environment-variables.md | 32 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 docs/api/environment-variables.md diff --git a/docs/README.md b/docs/README.md index 9b6372524bd3..917f4050b3d3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -30,6 +30,7 @@ select the tag that matches your version. * [Synopsis](api/synopsis.md) * [Process Object](api/process.md) * [Supported Chrome Command Line Switches](api/chrome-command-line-switches.md) +* [Environment Variables](api/environment-variables.md) ### Custom DOM Elements: diff --git a/docs/api/environment-variables.md b/docs/api/environment-variables.md new file mode 100644 index 000000000000..76cf4304e53b --- /dev/null +++ b/docs/api/environment-variables.md @@ -0,0 +1,32 @@ +# Environment variables + +Some behaviors of Electron are controlled by environment variables, because they +are initialized earlier than command line and the app's code. + +## `ELECTRON_RUN_AS_NODE` + +Starts the process as a normal Node.js process. + +## `ELECTRON_ENABLE_LOGGING` + +Prints Chrome's internal logging to console. + +## `ELECTRON_ENABLE_STACK_DUMPING` + +When Electron crashed, prints the stack trace to console. + +This environment variable will not work if `crashReporter` is started. + +## `ELECTRON_DEFAULT_ERROR_MODE` _Windows_ + +Shows Windows's crash dialog when Electron crashed. + +This environment variable will not work if `crashReporter` is started. + +## `ELECTRON_FORCE_WINDOW_MENU_BAR` _Linux_ + +Don't use global menu bar on Linux. + +## `ELECTRON_HIDE_INTERNAL_MODULES` + +Turns off compatibility mode for old built-in modules like `require('ipc')`. From 682b48095a3110a6ed891f076cb1983c809a3ddc Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 26 Nov 2015 20:44:07 +0800 Subject: [PATCH 630/738] docs: Add example --- docs/api/environment-variables.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/api/environment-variables.md b/docs/api/environment-variables.md index 76cf4304e53b..b5d3ff3f6f7b 100644 --- a/docs/api/environment-variables.md +++ b/docs/api/environment-variables.md @@ -3,6 +3,20 @@ Some behaviors of Electron are controlled by environment variables, because they are initialized earlier than command line and the app's code. +Examples on POSIX shells: + +```bash +$ export ELECTRON_ENABLE_LOGGING=true +$ electron +``` + +on Windows console: + +```powershell +> set ELECTRON_ENABLE_LOGGING=true +> electron +``` + ## `ELECTRON_RUN_AS_NODE` Starts the process as a normal Node.js process. From 59402eb23fb1cd87bd92e8bea618c2f2321fe105 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 26 Nov 2015 21:02:55 +0800 Subject: [PATCH 631/738] Add ELECTRON_NO_ATTACH_CONSOLE env var Close #1556. --- atom/app/atom_main.cc | 13 +++++++------ docs/api/environment-variables.md | 4 ++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/atom/app/atom_main.cc b/atom/app/atom_main.cc index 88bb137bae0f..5b5df448dfa8 100644 --- a/atom/app/atom_main.cc +++ b/atom/app/atom_main.cc @@ -5,7 +5,6 @@ #include "atom/app/atom_main.h" #include -#include #if defined(OS_WIN) #include @@ -57,6 +56,12 @@ bool IsRunAsNode() { } #if defined(OS_WIN) +bool IsCygwin() { + std::string os; + scoped_ptr env(base::Environment::Create()); + return env->GetVar("OS", &os) && os == "cygwin"; +} + // Win8.1 supports monitor-specific DPI scaling. bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) { typedef HRESULT(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS); @@ -103,17 +108,13 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { int argc = 0; wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - scoped_ptr env(base::Environment::Create()); - // Make output work in console if we are not in cygiwn. - std::string os; - if (env->GetVar("OS", &os) && os != "cygwin") { + if (!IsCygwin() && !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE")) { AttachConsole(ATTACH_PARENT_PROCESS); FILE* dontcare; freopen_s(&dontcare, "CON", "w", stdout); freopen_s(&dontcare, "CON", "w", stderr); - freopen_s(&dontcare, "CON", "r", stdin); } // Convert argv to to UTF8 diff --git a/docs/api/environment-variables.md b/docs/api/environment-variables.md index b5d3ff3f6f7b..6b000aaa1080 100644 --- a/docs/api/environment-variables.md +++ b/docs/api/environment-variables.md @@ -37,6 +37,10 @@ Shows Windows's crash dialog when Electron crashed. This environment variable will not work if `crashReporter` is started. +## `ELECTRON_NO_ATTACH_CONSOLE` _Windows_ + +Don't attach to current console session. + ## `ELECTRON_FORCE_WINDOW_MENU_BAR` _Linux_ Don't use global menu bar on Linux. From 932cd92bf6dded7756196254f5d7593fc5d2e14d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 27 Nov 2015 10:30:51 +0800 Subject: [PATCH 632/738] Fix wrong deprecation wrappers of BrowserWindow --- atom/browser/api/lib/browser-window.coffee | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 4cdffae87a60..d693a6d93403 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -90,16 +90,18 @@ deprecate.member BrowserWindow, 'copy', 'webContents' deprecate.member BrowserWindow, 'paste', 'webContents' deprecate.member BrowserWindow, 'selectAll', 'webContents' deprecate.member BrowserWindow, 'reloadIgnoringCache', 'webContents' -deprecate.member BrowserWindow, 'getPageTitle', 'webContents' deprecate.member BrowserWindow, 'isLoading', 'webContents' deprecate.member BrowserWindow, 'isWaitingForResponse', 'webContents' deprecate.member BrowserWindow, 'stop', 'webContents' deprecate.member BrowserWindow, 'isCrashed', 'webContents' -deprecate.member BrowserWindow, 'executeJavaScriptInDevTools', 'webContents' deprecate.member BrowserWindow, 'print', 'webContents' deprecate.member BrowserWindow, 'printToPDF', 'webContents' deprecate.rename BrowserWindow, 'restart', 'reload' deprecate.rename BrowserWindow, 'loadUrl', 'loadURL' deprecate.rename BrowserWindow, 'getUrl', 'getURL' +BrowserWindow::executeJavaScriptInDevTools = deprecate 'executeJavaScriptInDevTools', 'devToolsWebContents.executeJavaScript', (code) -> + @devToolsWebContents?.executeJavaScript code +BrowserWindow::getPageTitle = deprecate 'getPageTitle', 'webContents.getTitle', -> + @webContents?.getTitle() module.exports = BrowserWindow From 585ff9062cbf92ca65fcc50607e8f2b751f9d05e Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Thu, 26 Nov 2015 08:48:47 -0400 Subject: [PATCH 633/738] :bug: Fix missing execution permission bit in execFile override Consider an electron application that uses `execFile` to run a script that lives within the application code base: ```coffee child_process = require 'child_process' child_process.execFile __dirname + '/script.sh', (error) -> throw error if error? ``` An application like this will fail when being packaged in an `asar` with an following error: ``` Error: spawn EACCES ``` Electron overrides certain `fs` functions to make them work within an `asar` package. In the case of `execFile`, the file to be executed is extracted from the `asar` package into a temporary file and ran from there. The problem is that during the extraction, the original permissions of the file are lost. We workaround this by: 1. Extending `asar.stat` to return whether a file is executable or not, which is information that's already saved in the `asar` header. 2. Setting execution permissions on the extracted file if the above property holds true. Fixes: https://github.com/atom/electron/issues/3512 --- atom/common/api/atom_api_asar.cc | 1 + atom/common/asar/archive.cc | 3 +++ atom/common/asar/archive.h | 1 + atom/common/lib/asar.coffee | 11 +++++++++++ 4 files changed, 16 insertions(+) diff --git a/atom/common/api/atom_api_asar.cc b/atom/common/api/atom_api_asar.cc index 4ea7d8c5c362..489118bd70af 100644 --- a/atom/common/api/atom_api_asar.cc +++ b/atom/common/api/atom_api_asar.cc @@ -54,6 +54,7 @@ class Archive : public mate::Wrappable { mate::Dictionary dict(isolate, v8::Object::New(isolate)); dict.Set("size", stats.size); dict.Set("offset", stats.offset); + dict.Set("executable", stats.executable); dict.Set("isFile", stats.is_file); dict.Set("isDirectory", stats.is_directory); dict.Set("isLink", stats.is_link); diff --git a/atom/common/asar/archive.cc b/atom/common/asar/archive.cc index 969f958956ca..61b22e9013f6 100644 --- a/atom/common/asar/archive.cc +++ b/atom/common/asar/archive.cc @@ -107,6 +107,9 @@ bool FillFileInfoWithNode(Archive::FileInfo* info, return false; info->offset += header_size; + info->executable = false; + node->GetBoolean("executable", &info->executable); + return true; } diff --git a/atom/common/asar/archive.h b/atom/common/asar/archive.h index f2ff2f76d676..fb52c6265d31 100644 --- a/atom/common/asar/archive.h +++ b/atom/common/asar/archive.h @@ -27,6 +27,7 @@ class Archive { struct FileInfo { FileInfo() : size(0), offset(0) {} bool unpacked; + bool executable; uint32 size; uint64 offset; }; diff --git a/atom/common/lib/asar.coffee b/atom/common/lib/asar.coffee index f7eeceb3f314..fba3faed8ce2 100644 --- a/atom/common/lib/asar.coffee +++ b/atom/common/lib/asar.coffee @@ -1,5 +1,6 @@ asar = process.binding 'atom_common_asar' child_process = require 'child_process' +fs = require 'fs' path = require 'path' util = require 'util' @@ -83,6 +84,11 @@ overrideAPISync = (module, name, arg = 0) -> newPath = archive.copyFileOut filePath notFoundError asarPath, filePath unless newPath + stat = archive.stat filePath + + if stat.executable + fs.chmodSync(newPath, 0o755) + arguments[arg] = newPath old.apply this, arguments @@ -102,6 +108,11 @@ overrideAPI = (module, name, arg = 0) -> newPath = archive.copyFileOut filePath return notFoundError asarPath, filePath, callback unless newPath + stat = archive.stat filePath + + if stat.executable + fs.chmodSync(newPath, 0o755) + arguments[arg] = newPath old.apply this, arguments From 0b245b96e4c42ef90f98809ede7e4deaf942f3c2 Mon Sep 17 00:00:00 2001 From: Stephen Niedzielski Date: Thu, 26 Nov 2015 22:35:22 -0700 Subject: [PATCH 634/738] Update docs for globalShortcut.register Document return value for globalShortcut.register and common failure scenario. Fix: #3600 --- docs/api/global-shortcut.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/api/global-shortcut.md b/docs/api/global-shortcut.md index a0f069d7f1c5..ab6123bd877e 100644 --- a/docs/api/global-shortcut.md +++ b/docs/api/global-shortcut.md @@ -46,7 +46,10 @@ The `global-shortcut` module has the following methods: * `callback` Function Registers a global shortcut of `accelerator`. The `callback` is called when -the registered shortcut is pressed by the user. +the registered shortcut is pressed by the user. Returns `true` if the shortcut +`accelerator` was registered, `false` otherwise. For example, the specified +`accelerator` has already been registered by another caller or other native +applications. ### `globalShortcut.isRegistered(accelerator)` From 62c65280a177a50ba9d3aac8c2de4ee8a9908564 Mon Sep 17 00:00:00 2001 From: Stephen Niedzielski Date: Thu, 26 Nov 2015 23:16:00 -0700 Subject: [PATCH 635/738] Update docs for webContents.addWorkSpace Specify that webContents.addWorkSpace cannot be called before DevTools creation and include example. Fix: #3536 --- docs/api/web-contents.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 2612d6212279..e976b0ddb814 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -499,7 +499,14 @@ win.webContents.on("did-finish-load", function() { * `path` String -Adds the specified path to DevTools workspace. +Adds the specified path to DevTools workspace. Must be used after DevTools +creation: + +```javascript +mainWindow.webContents.on('devtools-opened', function() { + mainWindow.webContents.addWorkSpace(__dirname); +}); +``` ### `webContents.removeWorkSpace(path)` From a96c408df59d16c5ac5eb2b5ee134674f2cb8509 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 27 Nov 2015 17:28:09 +0900 Subject: [PATCH 636/738] Update as upstream --- docs-translations/ko-KR/README.md | 1 + docs-translations/ko-KR/api/app.md | 6 ++- .../ko-KR/api/environment-variables.md | 49 +++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 docs-translations/ko-KR/api/environment-variables.md diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index e6ea629c1e0a..e7aae9e6d6fa 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -34,6 +34,7 @@ GitHub 프로젝트내에서만 볼 수 있고 `master` 브랜치의 문서는 * [개요](api/synopsis.md) * [Process 객체](api/process.md) * [크롬 명령줄 스위치 지원](api/chrome-command-line-switches.md) +* [환경 변수](api/environment-variables.md) ### 커스텀 DOM elements: diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index d41ce1ab37b9..095e7b39c626 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -70,7 +70,7 @@ Returns: 어플리케이션이 종료될 때 발생하는 이벤트입니다. -### Event: 'open-file' +### Event: 'open-file' _OS X_ Returns: @@ -87,7 +87,9 @@ Returns: 이 이벤트를 처리할 땐 반드시 `event.preventDefault()`를 호출해야 합니다. -### Event: 'open-url' +Windows에선 `process.argv`를 통해 파일 경로를 얻을 수 있습니다. + +### Event: 'open-url' _OS X_ Returns: diff --git a/docs-translations/ko-KR/api/environment-variables.md b/docs-translations/ko-KR/api/environment-variables.md new file mode 100644 index 000000000000..11d350692161 --- /dev/null +++ b/docs-translations/ko-KR/api/environment-variables.md @@ -0,0 +1,49 @@ +# 환경 변수 + +Electron의 몇몇 동작은 명령 줄과 어플리케이션의 코드보다 먼저 초기화되어야 하므로 환경 변수에 의해 작동합니다. + +POSIX 쉘의 예시입니다: + +```bash +$ export ELECTRON_ENABLE_LOGGING=true +$ electron +``` + +Windows 콘솔의 예시입니다: + +```powershell +> set ELECTRON_ENABLE_LOGGING=true +> electron +``` + +## `ELECTRON_RUN_AS_NODE` + +프로세스를 일반 Node.js 프로세스처럼 시작합니다. (electron 모듈 제외) + +## `ELECTRON_ENABLE_LOGGING` + +Chrome의 내부 로그를 콘솔에 출력합니다. + +## `ELECTRON_ENABLE_STACK_DUMPING` + +Electron이 크래시되면, 콘솔에 stack trace를 출력합니다. + +이 환경 변수는 `crashReporter`가 시작되지 않았을 경우 작동하지 않습니다. + +## `ELECTRON_DEFAULT_ERROR_MODE` _Windows_ + +Electron이 크래시되면, 크래시 정보 창을 표시합니다. + +이 환경 변수는 `crashReporter`가 시작되지 않았을 경우 작동하지 않습니다. + +## `ELECTRON_NO_ATTACH_CONSOLE` _Windows_ + +현재 콘솔 세션에 소속시키지 않습니다. + +## `ELECTRON_FORCE_WINDOW_MENU_BAR` _Linux_ + +Linux의 글로벌 메뉴 막대를 사용하지 않습니다. + +## `ELECTRON_HIDE_INTERNAL_MODULES` + +`require('ipc')`같은 예전 방식의 빌트인 모듈을 비활성화합니다. From a1fdc701eeab630b9652e1c992eaf24164612e84 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 27 Nov 2015 21:29:31 +0800 Subject: [PATCH 637/738] docs: Add notes on spawn and exec --- docs/tutorial/application-packaging.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/tutorial/application-packaging.md b/docs/tutorial/application-packaging.md index 45973e49eaa9..c6e0ae3c4103 100644 --- a/docs/tutorial/application-packaging.md +++ b/docs/tutorial/application-packaging.md @@ -132,6 +132,7 @@ work. This adds a little overhead for those APIs. APIs that requires extra unpacking are: * `child_process.execFile` +* `child_process.execFileSync` * `fs.open` * `fs.openSync` * `process.dlopen` - Used by `require` on native modules @@ -143,6 +144,17 @@ archives is generated by guessing, because those files do not exist on the filesystem. So you should not trust the `Stats` object except for getting file size and checking file type. +### Executing Binaries Inside `asar` Archive + +There are Node APIs that can execute binaries like `child_process.exec`, +`child_process.spawn` and `child_process.execFile`, but only `execFile` is +supported to execute binaries inside `asar` archive. + +This is because `exec` and `spawn` accept `command` instead of `file` as input, +and `command`s are executed under shell. There is no reliable way to determine +whether a command uses a file in asar archive, and even if we do, we can not be +sure whether we can replace the path in command without side effects. + ## Adding Unpacked Files in `asar` Archive As stated above, some Node APIs will unpack the file to filesystem when From 6ef6a830425ecab31ca94a48d12aea30f14e274d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 27 Nov 2015 21:38:43 +0800 Subject: [PATCH 638/738] spec: Test execFile and execFileSync --- spec/asar-spec.coffee | 16 ++++++++++++++++ spec/fixtures/asar/echo.asar | Bin 0 -> 18112 bytes 2 files changed, 16 insertions(+) create mode 100644 spec/fixtures/asar/echo.asar diff --git a/spec/asar-spec.coffee b/spec/asar-spec.coffee index ad480a582525..af39fa3ec5ea 100644 --- a/spec/asar-spec.coffee +++ b/spec/asar-spec.coffee @@ -392,6 +392,22 @@ describe 'asar package', -> done() child.send file + describe 'child_process.execFile', -> + return unless process.platform is 'darwin' + + {execFile, execFileSync} = require 'child_process' + echo = path.join fixtures, 'asar', 'echo.asar', 'echo' + + it 'executes binaries', (done) -> + child = execFile echo, ['test'], (error, stdout) -> + assert.equal error, null + assert.equal stdout, 'test\n' + done() + + it 'execFileSync executes binaries', -> + output = execFileSync echo, ['test'] + assert.equal String(output), 'test\n' + describe 'internalModuleReadFile', -> internalModuleReadFile = process.binding('fs').internalModuleReadFile diff --git a/spec/fixtures/asar/echo.asar b/spec/fixtures/asar/echo.asar new file mode 100644 index 0000000000000000000000000000000000000000..4d72f7a92a7bbd6ccc205942348801eea307742e GIT binary patch literal 18112 zcmeHNcUV(N*S|LjO-ewdC<50A76fub6R;5_OQIl1u|o{W1tKKG6pEE1YD5++YeN*p zwV>-OqGA`6RV*u@=qkGS?%Lo*T|3y|n@M4T)!px}cfap>GEe57IWuR@ocT?;=gx$J zAP5`8KoA2!TtJHxCJ{24{{kApPe_JTCY(>u{29Kur-v&oIWA5{$Z7sGoaRa+(g?mn z&WlX~<#MTlShQ$S?T2R_1_*+Z5hQ~I^qGS=M-M@A5DcUcq(6wTJuWwl8N`~&3J-<3 zJpI^0{|3yr=N8hwzbXwqLITrOWGmkP!4n!?`t(x~eGT4~B5 z-#zrO6%=r}3UR7XEZ_>oamgya=Xexo^o41ZK)$z*?)tf0B7qwx<%tM&Zg2bkt|lC35Lk z^=Z{WJ>Bhs^TQBCZQyc~cz>nOTw`B=rUK-<>x1_7(JBMQUjKW)T|L2UMb%+FnCIwOB(D4Db>_3jhT_6+W>17+{P6Jva!gb3kD_ z3`7{9er<$!8o|u3galB(?-$Czv_>!x;c})cWKw#PFqSSzPZ9tg20IX;9eZky%l9>p z8gPL2mR8R?o8ScU%t1tq0a_rsXnB}-5i522Vv)u*-BO=J9mL$a9*Mzi}8@1 z(R^XjE!f%T&6%CGfQMcHNBIjgyOXp~FDOqi?lUuQ zwiC+ce`HrZp)}tG!2Q$ z+jeGm@N*S)XJLJ6V4G4=$EF6J1Hzo#sCJHW+6#^{s9mwXl?)oqUQ~xDtU#j;-5Skh zU1ch(Sve2ozRa`G=VoSpf+SG+fJqI#uTmVWe5Y(|rhztqEuC_V%|Fks`ZtAxUSJNt zr?|$bWM@~~&SK7HMl)lW-01TF!e>x8cTr_C^b!DnOUnZm(GE^T7)RO0R(@ZK)0Y|AmD+8fnBOW0%>-KQmPd6c{`m;LAujjoM%4|5N1TDGY`;$1fT8E!3sc1)<@Ak|AjU@o`eQOFpB^g|)8S{c>fz3JO~DxM3}4Ix$Gzz|gU-M) z+}GdJ&)>rX6N)4lD@}s+^4S804IUmA9vT$R4DpAWFbr@LSra1tW#AhyiOUxWWNr-K zk==cDWKMj5n-~%Cl9H17NUBsQClG&3?aqTfBLhK%p*w}627Od7Kw;#Wfd>dM4ZjOa zfS1}&<*6cQ5m3TI$!Ps_J+vPb0s);Lj-YAgsJV%OVF7I9E1?+Zg~g>BdRRlxXlRXw zUf0lj8v0m6zoJ%`twTVEfDQp20y+eA2N1=QPDKRZ@_LFCDL|y=76DvvDJzvGt5{pW5@|v?EW$uqbBF=BVSocy%Y2ap zmf>oytDdi#Pa?#yGyrhwa}U6(cN5lJ}XxBe8_{k!7oyE6x>)+S>TQL}*(8h>*gr^aFW-Ag&<7JUBwoT(e&0fh>glp~)D?m|Nf(`bI9x z*vr~XQ3FzO2A)AeQ3e$^)i;{6jExdx3JKLix(k6?#aU+NcoxMB&mz4mCX-MS2^|D$ zX!M|Zphhgi7&p= z@g-lj!Q@LenEZ_mo;X8ggNcjA)?@*JMF``?;GZbiR}9CqP+E6f0FvY^l!}1-KBO#g zKd@tu#k@|l_r{6s&ZZkPqZ4PGo@u8nfAZ-0HNTC6z5UqR2JIVq=lK@wg}~P^(PVe+ zy|AP9`qi^uMh_^AB$mnOv5$ODqvissXrVBOx5Zp<$b;6LbFNPJ=AIk3;?vdr!-KbT z(k(VCQXV-RtGjM=I5;Bh<9*wd?fE(UB0;klhIJo??`q}SUA9S`1S*8cvE+hr+biTwfbhjA;)ua*Qnw^?pGW&Nqz zhi*TdYnd@QdLZFBlw2BLves$&#pUUw zl5UuNdi(l~bbv?M<)LOxdv0vXpZj>zN8Y8-S2ks~@h|Yo3w@r~1ZM73o_v|kJpcSa zO=A4Qt4W+?!K52E=8A2%w9odf!Iy8w8{>x^`)zZ2vURkxMi?0;v~9|E(PX_rbk9yge9RxTg=; z5j?$d58O|~{#R`HyG8$S^#)ps3&!dms7#iTEFYxUVNEja3FZhvLd`${&XhAV^ux_>fPH}FhZ1e0#Y)@Tx$xXfJv(Wiq8%*i7?DhX@g@17Y|LqFTLgAao9;0NThM+|X zh=}G@#TV$Ic;+kIMZ3e0P-_Rc{$*d?0PxK7UBVUG}GMPd|$S@wCPe|nII&q*50izg$n+$mQfj_rmGEgeuNd=gk zkcvPBu>b@Aq7(?>i&2Ip$6*Q?;o74iNiwJl8v~ME?ZeloM9SmKg}^+Z6a3kW5X)um zy_TkG`nHjN1y`D$-rz_+dqWd(h2pLruI ze12U(y^ZKx7PX!$$cv8*P)kRiqf7vIbvh8=iXwP_hsjscc`}#8+JGiwrJbFKVOzP z=YriVBl?;{?SbqUb9}d2y&W?o9$V=-x6L%GwyCv*{yt*vEI}pTGqug%z;$YCBXy8j z;|W>+&?9$zmQ*c|y0d%JagXsIZ{M7^b@BG_3cJ&5$2;|Pxk$A?8nPvZUo$DgCaiSj z&BlkH>WmCV9#kj>;aPg4z!o-Gy?q(FG|oG*`?SrrUQqq>J_U4oJaI3Ehlhu!m!~&$ zdKleUeCq$g>9N7Bz?z^Ko0zGcnTX^#c`8pzF#6**uz+l0uFcZ=IAGcQwJ&oPKPKN8 zdO+WJ=Q=SXQe;#=y5yjr`QEz6rE_S}Hy$qC5x^`ET$nRvHLo#z4{PXFSHYEs4tt#X zg!`A@cxuf|tJ+$x|2WN=Z}|HDW#(i14)2yJvn{Q1Tk4DEEvUa#I%(^s#{A0R$LIyg zJ5Lh%8FPOglOTGScJBMW^mdPy#h0RIuNrHO+5H?-WVg)Cu^Ghx~8$0o%d-FKUo5fb;(RZGdwEWe((T&MM2Ws~) zOQ4<#qH&Ks>@)7&wJo96!@uam{IM+%JgsZpdpk4v|GAxcLv$P|?zk)NQar49$TBAl z0>D-4=Ed=W&n{ED>?$X&hs$Y@fm=g0&d|H;?RBa@ZTJFxYYGW`-1Pj`QEi{o8h#u! z&8}Z#Uk_IcJrfG`yV8c=KD??HB{YSHo6=-8IWqg-r%Zmal5;R&9WjM=|8qdT_u+(q z@RQEpUj1-wVc)5@E9;{4j!Y~&!u#~y!qqX-`eBFdM~E6H#c$L5^!Uk)i4$TR7c3ol zrsKrQ5uSSM!m^KbY`#lAnHT%2zbJL>14XUR3`UHhC>k9|M1-$RN!wy$Z0@k`luyCb zNrCPg@9bi1e=#s_-KI#H<&i1Ar<`^a;o4O%MN_PLXF zzPSJX(I*PYmy$zP5H?`canr3!vvy?lb|Nhvk@+0%!JS&ej zh>L6>HheyC>b2w8x6wl@XX^QU^ZGyQr`bkV$A>WPzpQX-bge?_tX>`dF@(<>_RY}u z7vKFzde*i|h#c9**pM4GP&6tx)i!nN&BAet-wiikvPopKSZ-6=B#ZNBHP8=kTRrkj z5>am_YZw|ie#zvw)9=tYG30R%``X%`6zqQ4m-KP=%7*XCa!&2COXFq>6XvDpmDXJM zinm|L*wLcAJ@e`Y+qLg@d9GR$aQyqD^~P7w%wnLJU|z82^5hK!<=10UZK51at`K5P%5$52E*41^@s6 literal 0 HcmV?d00001 From cfdcfcbd80c43fa124b6926ebd6a355f4c6cc5ce Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 27 Nov 2015 22:06:37 +0800 Subject: [PATCH 639/738] Add executable permission in CopyFileOut --- atom/common/api/atom_api_asar.cc | 1 - atom/common/asar/archive.cc | 10 ++++++++-- atom/common/asar/archive.h | 2 +- atom/common/lib/asar.coffee | 11 ----------- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/atom/common/api/atom_api_asar.cc b/atom/common/api/atom_api_asar.cc index 489118bd70af..4ea7d8c5c362 100644 --- a/atom/common/api/atom_api_asar.cc +++ b/atom/common/api/atom_api_asar.cc @@ -54,7 +54,6 @@ class Archive : public mate::Wrappable { mate::Dictionary dict(isolate, v8::Object::New(isolate)); dict.Set("size", stats.size); dict.Set("offset", stats.offset); - dict.Set("executable", stats.executable); dict.Set("isFile", stats.is_file); dict.Set("isDirectory", stats.is_directory); dict.Set("isLink", stats.is_link); diff --git a/atom/common/asar/archive.cc b/atom/common/asar/archive.cc index 61b22e9013f6..ab93e301b1ab 100644 --- a/atom/common/asar/archive.cc +++ b/atom/common/asar/archive.cc @@ -13,6 +13,7 @@ #include "atom/common/asar/scoped_temporary_file.h" #include "base/files/file.h" +#include "base/files/file_util.h" #include "base/logging.h" #include "base/pickle.h" #include "base/json/json_reader.h" @@ -96,7 +97,6 @@ bool FillFileInfoWithNode(Archive::FileInfo* info, return false; info->size = static_cast(size); - info->unpacked = false; if (node->GetBoolean("unpacked", &info->unpacked) && info->unpacked) return true; @@ -107,7 +107,6 @@ bool FillFileInfoWithNode(Archive::FileInfo* info, return false; info->offset += header_size; - info->executable = false; node->GetBoolean("executable", &info->executable); return true; @@ -276,6 +275,13 @@ bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) { if (!temp_file->InitFromFile(&file_, info.offset, info.size)) return false; +#if defined(OS_POSIX) + if (info.executable) { + // chmod a+x temp_file; + base::SetPosixFilePermissions(temp_file->path(), 0755); + } +#endif + *out = temp_file->path(); external_files_.set(path, temp_file.Pass()); return true; diff --git a/atom/common/asar/archive.h b/atom/common/asar/archive.h index fb52c6265d31..de5b9de605a3 100644 --- a/atom/common/asar/archive.h +++ b/atom/common/asar/archive.h @@ -25,7 +25,7 @@ class ScopedTemporaryFile; class Archive { public: struct FileInfo { - FileInfo() : size(0), offset(0) {} + FileInfo() : unpacked(false), executable(false), size(0), offset(0) {} bool unpacked; bool executable; uint32 size; diff --git a/atom/common/lib/asar.coffee b/atom/common/lib/asar.coffee index fba3faed8ce2..f7eeceb3f314 100644 --- a/atom/common/lib/asar.coffee +++ b/atom/common/lib/asar.coffee @@ -1,6 +1,5 @@ asar = process.binding 'atom_common_asar' child_process = require 'child_process' -fs = require 'fs' path = require 'path' util = require 'util' @@ -84,11 +83,6 @@ overrideAPISync = (module, name, arg = 0) -> newPath = archive.copyFileOut filePath notFoundError asarPath, filePath unless newPath - stat = archive.stat filePath - - if stat.executable - fs.chmodSync(newPath, 0o755) - arguments[arg] = newPath old.apply this, arguments @@ -108,11 +102,6 @@ overrideAPI = (module, name, arg = 0) -> newPath = archive.copyFileOut filePath return notFoundError asarPath, filePath, callback unless newPath - stat = archive.stat filePath - - if stat.executable - fs.chmodSync(newPath, 0o755) - arguments[arg] = newPath old.apply this, arguments From 62add3abccf7b192e222c54071202c0ddf934470 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 27 Nov 2015 22:23:19 +0800 Subject: [PATCH 640/738] Bump v0.35.2 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/atom.gyp b/atom.gyp index 9d667410523e..202a414003fc 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.35.1', + 'version%': '0.35.2', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 481945b8e893..fb4a2332334e 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.35.1 + 0.35.2 CFBundleShortVersionString - 0.35.1 + 0.35.2 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 875727cdaff8..773871fd5583 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,35,1,0 - PRODUCTVERSION 0,35,1,0 + FILEVERSION 0,35,2,0 + PRODUCTVERSION 0,35,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.35.1" + VALUE "FileVersion", "0.35.2" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.35.1" + VALUE "ProductVersion", "0.35.2" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 093da7b5c601..b5cc0982d0d7 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 35 -#define ATOM_PATCH_VERSION 1 +#define ATOM_PATCH_VERSION 2 #define ATOM_VERSION_IS_RELEASE 1 From eeb1143debf7f6eab6592e6ff9e8328d560efab9 Mon Sep 17 00:00:00 2001 From: Ivan Kulikov Date: Fri, 27 Nov 2015 22:32:45 +0300 Subject: [PATCH 641/738] init russian lang docs --- README.md | 1 + docs-translations/ru-RU/README.md | 82 +++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 docs-translations/ru-RU/README.md diff --git a/README.md b/README.md index beb96b4e5c2a..db82fac88ec6 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ contains documents describing how to build and contribute to Electron. - [Spanish](https://github.com/atom/electron/tree/master/docs-translations/es) - [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN) - [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW) +- [Russian](https://github.com/atom/electron/tree/master/docs-translations/ru-RU) ## Quick Start diff --git a/docs-translations/ru-RU/README.md b/docs-translations/ru-RU/README.md new file mode 100644 index 000000000000..07e50028df94 --- /dev/null +++ b/docs-translations/ru-RU/README.md @@ -0,0 +1,82 @@ +Пожалуйста, убедитесь, что вы используете документацию, которые соответствует вашей версии Electron. +Номер версии должен быть частью адреса страницы. Если это не так, вы +возможно,используете документицию ветки разработки, которая может содержать изменения api, +которые не совместимы с вашей версией Electron. Если это так, +Вы можете переключиться на другую версию документации в списке +[доступные версии](http://electron.atom.io/docs/) на atom.io, или +если вы используете интерфейс GitHub, откройте список "переключение ветки/тега" и +выберите тег, который соответствует вашей версии. + +## Руководства + +* [Поддерживаемые платформы](tutorial/supported-platforms.md) +* [Application Distribution](tutorial/application-distribution.md) +* [Mac App Store Submission Guide](tutorial/mac-app-store-submission-guide.md) +* [Application Packaging](tutorial/application-packaging.md) +* [Using Native Node Modules](tutorial/using-native-node-modules.md) +* [Отладка главного процесса](tutorial/debugging-main-process.md) +* [Использование Selenium и WebDriver](tutorial/using-selenium-and-webdriver.md) +* [DevTools Extension](tutorial/devtools-extension.md) +* [Использование Pepper Flash Plugin](tutorial/using-pepper-flash-plugin.md) + +## Учебники + +* [Быстрый старт](tutorial/quick-start.md) +* [Desktop Environment Integration](tutorial/desktop-environment-integration.md) +* [Online/Offline Event Detection](tutorial/online-offline-events.md) + +## API References + +* [Краткий обзор](api/synopsis.md) +* [Process Object](api/process.md) +* [Поддерживаемые параметры командной строки Chrome](api/chrome-command-line-switches.md) + +### Пользовательские элементы DOM: + +* [`File` Object](api/file-object.md) +* [`` Tag](api/web-view-tag.md) +* [`window.open` Function](api/window-open.md) + +### Modules for the Main Process: + +* [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) + +### Модули для Renderer Process (Web Page): + +* [ipcRenderer](api/ipc-renderer.md) +* [remote](api/remote.md) +* [webFrame](api/web-frame.md) + +### Modules for Both Processes: + +* [clipboard](api/clipboard.md) +* [crashReporter](api/crash-reporter.md) +* [nativeImage](api/native-image.md) +* [screen](api/screen.md) +* [shell](api/shell.md) + +## Разработка + +* [Стиль кодирования](development/coding-style.md) +* [Source Code Directory Structure](development/source-code-directory-structure.md) +* [Technical Differences to NW.js (formerly node-webkit)](development/atom-shell-vs-node-webkit.md) +* [Обзор системы сборки](development/build-system-overview.md) +* [Инструкции по сборке (OS X)](development/build-instructions-osx.md) +* [Инструкции по сборке (Windows)](development/build-instructions-windows.md) +* [Инструкции по сборке (Linux)](development/build-instructions-linux.md) +* [Настройка сервера символов для отладчика](development/setting-up-symbol-server.md) + From 5bbc46930fef4d9445ce148cebac4e94560572c3 Mon Sep 17 00:00:00 2001 From: "howard.zuo" Date: Sun, 29 Nov 2015 12:14:49 +0800 Subject: [PATCH 642/738] add packaging translation for ZH-CN --- .../zh-CN/tutorial/application-packaging.md | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 docs-translations/zh-CN/tutorial/application-packaging.md diff --git a/docs-translations/zh-CN/tutorial/application-packaging.md b/docs-translations/zh-CN/tutorial/application-packaging.md new file mode 100644 index 000000000000..ee4b7bf63b85 --- /dev/null +++ b/docs-translations/zh-CN/tutorial/application-packaging.md @@ -0,0 +1,141 @@ +# 应用打包 + +为舒缓Windows下路径名过长的问题[issues](https://github.com/joyent/node/issues/6960), 也略对`require`加速以及简单隐匿你的源代码, 你可以通过极小的源代码改动将你的应用打包成[asar][asar]. + +## 生成`asar`包 + +[asar][asar]是一种将多个文件合并成一个文件的类tar风格的归档格式。 Electron可以无需解压,即从其中读取任意文件内容。 + +参照如下步骤将你的应用打包成`asar`: + +### 1. 安装asar + +```bash +$ npm install -g asar +``` + +### 2. 用`asar pack`打包 + +```bash +$ asar pack your-app app.asar +``` + +## 使用`asar`包 + +在Electron中有两类APIs:Node.js提供的Node APIs和Chromium提供的Web APIs。这两种APIs都支持从`asar`包中读取文件。 + +### Node API + +由于Electron中打了特别补丁, Node APIs中如`fs.readFile`或者`require`之类的方法可以将`asar`视之为虚拟文件夹,读取`asar`里面的文件就和从真实的文件系统中读取一样。 + +例如,假设我们在`/path/to`文件夹下有个`example.asar`包: + +```bash +$ asar list /path/to/example.asar +/app.js +/file.txt +/dir/module.js +/static/index.html +/static/main.css +/static/jquery.min.js +``` + +从`asar`包读取一个文件: + +```javascript +const fs = require('fs'); +fs.readFileSync('/path/to/example.asar/file.txt'); +``` + +列出`asar`包中根目录下的所有文件: + +```javascript +const fs = require('fs'); +fs.readdirSync('/path/to/example.asar'); +``` + +使用`asar`包中的一个模块: + +```javascript +require('/path/to/example.asar/dir/module.js'); +``` + +你也可以使用`BrowserWindow`来显示一个`asar`包里的web页面: + +```javascript +const BrowserWindow = require('electron').BrowserWindow; +var win = new BrowserWindow({width: 800, height: 600}); +win.loadURL('file:///path/to/example.asar/static/index.html'); +``` + +### Web API + +在Web页面里,用`file:`协议可以获取`asar`包中文件。和Node API一样,视`asar`包如虚拟文件夹。 + +例如,用`$.get`获取文件: + +```html + +``` + +### 像“文件”那样处理`asar`包 + +有些场景,如:核查`asar`包的校验和,我们需要像读取“文件”那样读取`asar`包的内容(而不是当成虚拟文件夹)。你可以使用内置的`original-fs`(提供和`fs`一样的APIs)模块来读取`asar`包的真实信息。 + +```javascript +var originalFs = require('original-fs'); +originalFs.readFileSync('/path/to/example.asar'); +``` + +## Node API缺陷 + +尽管我们已经尽了最大努力使得`asar`包在Node API下的应用尽可能的趋向于真实的目录结构,但仍有一些底层Node API我们无法保证其正常工作。 + +### `asar`包是只读的 + +`asar`包中的内容不可更改,所以Node APIs里那些可以用来修改文件的方法在对待`asar`包时都无法正常工作。 + +### Working Directory在`asar`包中无效 + +尽管`asar`包是虚拟文件夹,但其实并没有真实的目录架构对应在文件系统里,所以你不可能将working Directory设置成`asar`包里的一个文件夹。将`asar`中的文件夹以`cwd`形式作为参数传入一些API中也会报错。 + +### API中的额外“开箱” + +大部分`fs`API可以无需解压即从`asar`包中读取文件或者文件的信息,但是在处理一些依赖真实文件路径的底层系统方法时,Electron会将所需文件解压到临时目录下,然后将临时目录下的真实文件路径传给底层系统方法使其正常工作。 对于这类API,耗费会略多一些。 + +以下是一些需要额外解压的APIs: + +* `child_process.execFile` +* `child_process.execFileSync` +* `fs.open` +* `fs.openSync` +* `process.dlopen` - `require`native模块时用到 + +### `fs.stat`获取的stat信息不可靠 + +对`asar`包中的文件取`fs.stat`,返回的`Stats`对象不是精确值,因为这些文件不是真实存在于文件系统里。所以除了文件大小和文件类型以外,你不应该依赖`Stats`对象的值。 + +### 执行`asar`包中的程序 + +Node中有一些可以执行程序的API,如`child_process.exec`,`child_process.spawn`和`child_process.execFile`等,但只有`execFile`可以执行`asar`包中的程序。 + +因为`exec`和`spawn`允许`command`替代`file`作为输入,而`command`是需要在shell下执行的,目前没有可靠的方法来判断`command`中是否在操作一个`asar`包中的文件,而且即便可以判断,我们依旧无法保证可以在无任何副作用的情况下替换`command`中的文件路径。 + +## 打包时排除文件 + +如上所述,一些Node API会在调用时将文件解压到文件系统中,除了效率问题外,也有可能引起杀毒软件的注意! + +为解决这个问题,你可以在生成`asar`包时使用`--unpack`选项来排除一些文件,使其不打包到`asar`包中,下面是如何排除一些用作共享用途的native模块的方法: + +```bash +$ asar pack app app.asar --unpack *.node +``` + +经过上述命令后,除了生成的`app.asar`包以外,还有一个包含了排除文件的`app.asar.unpacked`文件夹,你需要将这个文件夹一起拷贝,提供给用户。 + +[asar]: https://github.com/atom/asar From dab7058aa29c035aa844526e122cfd842e754e40 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sun, 29 Nov 2015 23:03:31 +0900 Subject: [PATCH 643/738] Update as upstream --- .../ko-KR/api/global-shortcut.md | 6 +++++- docs-translations/ko-KR/api/web-contents.md | 9 ++++++++- .../ko-KR/tutorial/application-packaging.md | 19 ++++++++++++++++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/docs-translations/ko-KR/api/global-shortcut.md b/docs-translations/ko-KR/api/global-shortcut.md index 1b8363bcbe70..9617d463e87e 100644 --- a/docs-translations/ko-KR/api/global-shortcut.md +++ b/docs-translations/ko-KR/api/global-shortcut.md @@ -46,7 +46,11 @@ app.on('will-quit', function() { * `callback` Function `accelerator`로 표현된 전역 단축키를 등록합니다. 유저로부터 등록된 단축키가 눌렸을 -경우 `callback` 함수가 호출됩니다. +경우 `callback` 함수가 호출됩니다. `accelerator` 단축키가 등록되었을 경우 +`true`를 반환합니다. 그 외엔 `false`를 반환합니다. 예를 들어 지정한 +`accelerator`가 이미 다른 호출자 또는 네이티브 어플리케이션에서 등록된 상태를 +생각할 수 있습니다. + ### `globalShortcut.isRegistered(accelerator)` diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index c92149ce44a6..82d426c1ce7e 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -497,7 +497,14 @@ win.webContents.on("did-finish-load", function() { * `path` String -특정 경로를 개발자 도구의 워크스페이스에 추가합니다. +특정 경로를 개발자 도구의 워크스페이스에 추가합니다. 반드시 개발자 도구의 생성이 완료된 +이후에 사용해야 합니다. + +```javascript +mainWindow.webContents.on('devtools-opened', function() { + mainWindow.webContents.addWorkSpace(__dirname); +}); +``` ### `webContents.removeWorkSpace(path)` diff --git a/docs-translations/ko-KR/tutorial/application-packaging.md b/docs-translations/ko-KR/tutorial/application-packaging.md index 7a9141976306..0e958fe862e7 100644 --- a/docs-translations/ko-KR/tutorial/application-packaging.md +++ b/docs-translations/ko-KR/tutorial/application-packaging.md @@ -129,16 +129,29 @@ API가 원할하게 작동할 수 있도록 임시 경로에 해당되는 파일 위 예외에 해당하는 API 메서드는 다음과 같습니다: * `child_process.execFile` +* `child_process.execFileSync` * `fs.open` * `fs.openSync` * `process.dlopen` - Used by `require` on native modules -### `fs.stat`의 잘못된 스테이터스 정보 +### `fs.stat`의 모조된(예측) 스테이터스 정보 `fs.stat` 로부터 반환되는 `Stats` 객체와 비슷한 API들은 `asar` 아카이브를 타겟으로 할 경우 예측된 디렉터리 파일 정보를 가집니다. 왜냐하면 아카이브의 디렉터리 경로는 실제 -파일 시스템에 존재하지 않기 때문입니다. 그러한 이유로 파일 크기와 -파일 타입 등을 확인할 때 `Stats` 객체를 신뢰해선 안됩니다. +파일 시스템에 존재하지 않기 때문입니다. 그러한 이유로 파일 크기와 파일 타입 등을 확인할 +때 `Stats` 객체를 신뢰해선 안됩니다. + +### `asar` 아카이브 내부의 바이너리 실행 + +Node API에는 `child_process.exec`, `child_process.spawn` 그리고 +`child_process.execFile`와 같은 바이너리를 실행시킬 수 있는 API가 있습니다. 하지만 +`asar` 아카이브 내에선 `execFile` API만 사용할 수 있습니다. + +이 한계가 존재하는 이유는 `exec`와 `spawn`은 `file` 대신 `command`를 인수로 허용하고 +있고 `command`는 shell에서 작동하기 때문입니다. Electron은 어떤 커맨드가 `asar` +아카이브 내의 파일을 사용하는지 결정하는데 적절한 방법을 가지고 있지 않으며, 심지어 +그게 가능하다고 해도 부작용 없이 명령 경로를 대체할 수 있는지에 대해 확실히 알 수 +있는 방법이 없습니다. ## `asar` 아카이브에 미리 압축 해제된 파일 추가하기 From 22dbf5e9fc7dabd9e271026669056b4c1b8de58d Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sun, 29 Nov 2015 23:06:01 +0900 Subject: [PATCH 644/738] Small fixes --- docs-translations/ko-KR/tutorial/application-packaging.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs-translations/ko-KR/tutorial/application-packaging.md b/docs-translations/ko-KR/tutorial/application-packaging.md index 0e958fe862e7..97054110ce80 100644 --- a/docs-translations/ko-KR/tutorial/application-packaging.md +++ b/docs-translations/ko-KR/tutorial/application-packaging.md @@ -150,8 +150,8 @@ Node API에는 `child_process.exec`, `child_process.spawn` 그리고 이 한계가 존재하는 이유는 `exec`와 `spawn`은 `file` 대신 `command`를 인수로 허용하고 있고 `command`는 shell에서 작동하기 때문입니다. Electron은 어떤 커맨드가 `asar` 아카이브 내의 파일을 사용하는지 결정하는데 적절한 방법을 가지고 있지 않으며, 심지어 -그게 가능하다고 해도 부작용 없이 명령 경로를 대체할 수 있는지에 대해 확실히 알 수 -있는 방법이 없습니다. +그게 가능하다고 해도 부작용 없이 명령 경로를 대체할 수 있는지에 대해 확실히 알 수 있는 +방법이 없습니다. ## `asar` 아카이브에 미리 압축 해제된 파일 추가하기 From df9ecefe015913fe0053e79cb7a3c448dc8deb7b Mon Sep 17 00:00:00 2001 From: Luke Westby Date: Sun, 29 Nov 2015 12:22:53 -0600 Subject: [PATCH 645/738] fix typo in "rotation" string --- atom/browser/api/atom_api_screen.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_screen.cc b/atom/browser/api/atom_api_screen.cc index b73bda9ced84..407a71f0cc41 100644 --- a/atom/browser/api/atom_api_screen.cc +++ b/atom/browser/api/atom_api_screen.cc @@ -41,7 +41,7 @@ std::vector MetricsToArray(uint32_t metrics) { if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR) array.push_back("scaleFactor"); if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_ROTATION) - array.push_back("rotaion"); + array.push_back("rotation"); return array; } From c7420e17ab0e74dfcfbcf5a53f0c13f35104d107 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Sun, 29 Nov 2015 14:04:57 -0500 Subject: [PATCH 646/738] Suggest [ci skip] in documentation-only commits --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6ca3ea5d2f32..31e31edf1f40 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -57,6 +57,7 @@ possible with your report. If you can, please include: * Use the imperative mood ("Move cursor to..." not "Moves cursor to...") * Limit the first line to 72 characters or less * Reference issues and pull requests liberally +* When only changing documentation, include [ci skip] in the commit description * Consider starting the commit message with an applicable emoji: * :art: `:art:` when improving the format/structure of the code * :racehorse: `:racehorse:` when improving performance From 9c0afcd9017966125eb8605f683e202d70a062de Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Sun, 29 Nov 2015 14:57:48 -0500 Subject: [PATCH 647/738] Wrap [ci skip] in backticks --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31e31edf1f40..630b8b0ba0e2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -57,7 +57,7 @@ possible with your report. If you can, please include: * Use the imperative mood ("Move cursor to..." not "Moves cursor to...") * Limit the first line to 72 characters or less * Reference issues and pull requests liberally -* When only changing documentation, include [ci skip] in the commit description +* When only changing documentation, include `[ci skip]` in the commit description * Consider starting the commit message with an applicable emoji: * :art: `:art:` when improving the format/structure of the code * :racehorse: `:racehorse:` when improving performance From 7d827c2f3e1734db241d37f04101c9cdde449b8e Mon Sep 17 00:00:00 2001 From: Artur de Oliveira Tsuda Date: Sun, 29 Nov 2015 22:56:34 -0200 Subject: [PATCH 648/738] Remove 'Google Translator'-like translation --- .../pt-BR/development/coding-style.md | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/docs-translations/pt-BR/development/coding-style.md b/docs-translations/pt-BR/development/coding-style.md index f3b4d6d58f37..b0068d568924 100644 --- a/docs-translations/pt-BR/development/coding-style.md +++ b/docs-translations/pt-BR/development/coding-style.md @@ -2,28 +2,25 @@ Estas são as diretrizes de estilo para codificar no Electron. -## C++ and Python +## C++ e Python -Para C ++ e Python, seguimos os padrões do projeto Chromium [Estilo de Codificação](http://www.chromium.org/developers/coding-style). Há também um +Para C++ e Python, seguimos o [Estilo de Codificação](http://www.chromium.org/developers/coding-style) do projeto Chromium. Há também um script `script/cpplint.py` para verificar se todos os arquivos estão em conformidade. A versão Python que estamos usando agora é a Python 2.7. -O código C ++ usa do Chromium's um monte de tipos e abstrações, por isso é recomendada para se familiarizar com eles. Um bom lugar para começar com a documentação do Chromium's [Important Abstractions and Data Structures](https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures). O documento menciona alguns tipos especiais, com escopo tipos (que automaticamente libera sua memória quando sai do escopo), registrando mecanismos etc. +O código C++ usa várias abstrações e tipos do Chromium, por isso é recomendado familiarizar-se com eles. Um bom lugar para começar é com a documentação do Chromium [Important Abstractions and Data Structures](https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures). O documento menciona alguns tipos especiais, *scoped types* (que automaticamente liberam sua memória ao sair do escopo), mecanismos de *log* etc. ## CoffeeScript -For CoffeeScript, we follow GitHub's [Style -Guide](https://github.com/styleguide/javascript) and the following rules: +Para CoffeeScript, seguimos o [Guia de Estilo] (https://github.com/styleguide/javascript) do GitHub com as seguintes regras: -Para CoffeeScript, seguimos o estilo do GitHub [Guia de Estilo] (https://github.com/styleguide/javascript) com as seguintes regras: +* Os arquivos **NÃO DEVEM** terminar com uma nova linha, porque queremos corresponder aos padrões de estilo Google. -* Os arquivos devem **NÃO DEVEM** com nova linha no final, porque queremos corresponder aos padrões de estilo Google. - -* Os nomes dos arquivos devem ser concatenados com o `-` em vez de`_`, por exemplo, `file-name.coffee` em vez de`file_name.coffee`, porque no [github/atom](https://github.com/github/atom) os nomes dos módulos são geralmente em o formulário `module-name`. Esta regra só se aplica aos arquivos com extensão `.coffee`. +* Os nomes dos arquivos devem ser concatenados com `-` em vez de `_`, por exemplo, `file-name.coffee` em vez de `file_name.coffee`, porque no [github/atom](https://github.com/github/atom) os nomes dos módulos são geralmente da forma `module-name`. Esta regra só se aplica aos arquivos com extensão `.coffee`. * -## API Names +## Nomes de APIs -Ao criar uma nova API, devemos preferencialmente utilizar métodos getters e setters em vez de -estilo de uma função do jQuery. Por exemplo, `.getText()` e `.setText(text)` utilize `.text([text])`. Existe uma +Ao criar uma nova API, devemos preferencialmente utilizar métodos getters e setters em vez do +estilo de uma função única do jQuery. Por exemplo, `.getText()` e `.setText(text)` são preferenciais a `.text([text])`. Existe uma [discussão](https://github.com/atom/electron/issues/46) sobre este assunto. From 45e9ed5f0c61fe8fbd4a3c2ff4c559c0ce0b08f2 Mon Sep 17 00:00:00 2001 From: Artur de Oliveira Tsuda Date: Sun, 29 Nov 2015 23:25:16 -0200 Subject: [PATCH 649/738] =?UTF-8?q?Update=20'Estilo=20de=20c=C3=B3digo'=20?= =?UTF-8?q?link.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'Estilo de código' in 'Desenvolvimento' section now points to the translated coding-style.md --- docs-translations/pt-BR/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/pt-BR/README.md b/docs-translations/pt-BR/README.md index db88edaf77eb..1641f2380704 100644 --- a/docs-translations/pt-BR/README.md +++ b/docs-translations/pt-BR/README.md @@ -61,7 +61,7 @@ Módulos de ambos os processos: ## Desenvolvimento -* [Estilo de código](../../docs/development/coding-style.md) +* [Estilo de código](development/coding-style.md) * [Estrutura de diretórios padrão](../../docs/development/source-code-directory-structure.md) * [Diferenças técnicas do NW.js (antigo node-webkit)](../../docs/development/atom-shell-vs-node-webkit.md) * [Visão geral do build](../../docs/development/build-system-overview.md) From bf4b94561ef38c29ebace0c557686795c03d29d3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 30 Nov 2015 15:21:39 +0800 Subject: [PATCH 650/738] docs: Mention submitting to MAC costs money Close #3617. --- docs/tutorial/mac-app-store-submission-guide.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md index 43b2d9a0a49b..036676fe853a 100644 --- a/docs/tutorial/mac-app-store-submission-guide.md +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -4,6 +4,9 @@ Since v0.34.0, Electron allows submitting packaged apps to the Mac App Store (MAS). This guide provides information on: how to submit your app and the limitations of the MAS build. +__Note:__ Submitting an app to Mac App Store requires enrolling [Apple Developer +Program][developer-program], which costs money. + ## How to Submit Your App The following steps introduce a simple way to submit your app to Mac App Store. @@ -108,6 +111,7 @@ Also, due to the usage of app sandboxing, the resources which can be accessed by the app are strictly limited; you can read [App Sandboxing][app-sandboxing] for more information. +[developer-program]: https://developer.apple.com/support/compare-memberships/ [submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html [nwjs-guide]: https://github.com/nwjs/nw.js/wiki/Mac-App-Store-%28MAS%29-Submission-Guideline#first-steps [enable-app-sandbox]: https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html From 9fa6527460149d4b1251f099d6582186a11ff0ca Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Mon, 30 Nov 2015 17:24:43 +0900 Subject: [PATCH 651/738] Update as upstream --- .../ko-KR/tutorial/mac-app-store-submission-guide.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md b/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md index 16a74d03edd1..d316d16da83f 100644 --- a/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md +++ b/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md @@ -4,6 +4,10 @@ Electron은 v0.34.0 버전부터 앱 패키지를 Mac App Store(MAS)에 제출 되었습니다. 이 가이드는 어플리케이션을 앱 스토어에 등록하는 방법과 빌드의 한계에 대한 설명을 제공합니다. +__참고:__ Mac App Store에 어플리케이션을 등록하려면 +[Apple Developer Program][developer-program]에 등록되어 있어야 하며 비용이 발생할 +수 있습니다. + ## 앱 스토어에 어플리케이션을 등록하는 방법 다음 몇 가지 간단한 절차에 따라 앱 스토어에 어플리케이션을 등록하는 방법을 알아봅니다. @@ -109,6 +113,7 @@ productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RES **역주:** [Mac 앱 배포 가이드 공식 문서](https://developer.apple.com/osx/distribution/kr/) +[developer-program]: https://developer.apple.com/support/compare-memberships/ [submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html [nwjs-guide]: https://github.com/nwjs/nw.js/wiki/Mac-App-Store-%28MAS%29-Submission-Guideline#first-steps [enable-app-sandbox]: https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html From 4d5028fb4c8e4643a16ea866ea318821f7c10994 Mon Sep 17 00:00:00 2001 From: Smite Chow Date: Mon, 30 Nov 2015 17:16:35 +0800 Subject: [PATCH 652/738] :art: add miss charactor --- .../zh-CN/development/atom-shell-vs-node-webkit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/zh-CN/development/atom-shell-vs-node-webkit.md b/docs-translations/zh-CN/development/atom-shell-vs-node-webkit.md index 9774580eeb7b..beea91e3ff16 100644 --- a/docs-translations/zh-CN/development/atom-shell-vs-node-webkit.md +++ b/docs-translations/zh-CN/development/atom-shell-vs-node-webkit.md @@ -12,7 +12,7 @@ __1. 应用的入口__ 在 Electron 中,入口是一个 JavaScript 脚本。不同于直接提供一个URL,你需要手动创建一个浏览器窗口,然后通过 API 加载 HTML 文件。你还可以监听窗口事件,决定何时让应用退出。 -Electron 的工作方式更像 Node.js 运行时。 Electron 的 APIs 更加底层,因此你可以它替代 [PhantomJS](http://phantomjs.org/) 做浏览器测试。 +Electron 的工作方式更像 Node.js 运行时。 Electron 的 APIs 更加底层,因此你可以用它替代 [PhantomJS](http://phantomjs.org/) 做浏览器测试。 __2. 构建系统__ From 44e24ebf7adc5a6242085b35ed4150950b4eb560 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 30 Nov 2015 22:29:01 +0800 Subject: [PATCH 653/738] Delete BridgeTaskRunner when main message loop is ready --- atom/browser/atom_browser_main_parts.cc | 3 ++- atom/browser/bridge_task_runner.cc | 5 ----- atom/browser/bridge_task_runner.h | 6 +++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 0a8c16ca223f..3bfe3748f136 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -114,7 +114,8 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() { 1000)); brightray::BrowserMainParts::PreMainMessageLoopRun(); - BridgeTaskRunner::MessageLoopIsReady(); + bridge_task_runner_->MessageLoopIsReady(); + bridge_task_runner_ = nullptr; #if defined(USE_X11) libgtk2ui::GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess()); diff --git a/atom/browser/bridge_task_runner.cc b/atom/browser/bridge_task_runner.cc index 882a3050de48..36c8d17359e8 100644 --- a/atom/browser/bridge_task_runner.cc +++ b/atom/browser/bridge_task_runner.cc @@ -8,11 +8,6 @@ namespace atom { -// static -std::vector BridgeTaskRunner::tasks_; -std::vector BridgeTaskRunner::non_nestable_tasks_; - -// static void BridgeTaskRunner::MessageLoopIsReady() { auto message_loop = base::MessageLoop::current(); CHECK(message_loop); diff --git a/atom/browser/bridge_task_runner.h b/atom/browser/bridge_task_runner.h index 12508f009d17..b69b33b29516 100644 --- a/atom/browser/bridge_task_runner.h +++ b/atom/browser/bridge_task_runner.h @@ -20,7 +20,7 @@ class BridgeTaskRunner : public base::SingleThreadTaskRunner { ~BridgeTaskRunner() override {} // Called when message loop is ready. - static void MessageLoopIsReady(); + void MessageLoopIsReady(); // base::SingleThreadTaskRunner: bool PostDelayedTask(const tracked_objects::Location& from_here, @@ -35,8 +35,8 @@ class BridgeTaskRunner : public base::SingleThreadTaskRunner { private: using TaskPair = base::Tuple< tracked_objects::Location, base::Closure, base::TimeDelta>; - static std::vector tasks_; - static std::vector non_nestable_tasks_; + std::vector tasks_; + std::vector non_nestable_tasks_; DISALLOW_COPY_AND_ASSIGN(BridgeTaskRunner); }; From 7622bb40a95801d5cca594925e83b2c540cb957a Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 23 Nov 2015 23:29:49 -0800 Subject: [PATCH 654/738] Enable all origins via CORS header for custom schemes This PR disables CORS for custom schemes, which allows you to serve Font resources from custom schemes after using registerCustomSchemeAsSecure --- atom/browser/net/url_request_buffer_job.cc | 3 +++ atom/browser/net/url_request_buffer_job.h | 2 ++ atom/browser/net/url_request_string_job.cc | 3 +++ 3 files changed, 8 insertions(+) diff --git a/atom/browser/net/url_request_buffer_job.cc b/atom/browser/net/url_request_buffer_job.cc index affc3dd37d25..c4936ba15696 100644 --- a/atom/browser/net/url_request_buffer_job.cc +++ b/atom/browser/net/url_request_buffer_job.cc @@ -50,6 +50,9 @@ void URLRequestBufferJob::GetResponseInfo(net::HttpResponseInfo* info) { status.append("\0\0", 2); net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); + std::string cors("Access-Control-Allow-Origin: *"); + headers->AddHeader(cors); + if (!mime_type_.empty()) { std::string content_type_header(net::HttpRequestHeaders::kContentType); content_type_header.append(": "); diff --git a/atom/browser/net/url_request_buffer_job.h b/atom/browser/net/url_request_buffer_job.h index ab8de7e8f030..8de5d82e0df2 100644 --- a/atom/browser/net/url_request_buffer_job.h +++ b/atom/browser/net/url_request_buffer_job.h @@ -12,6 +12,8 @@ #include "net/http/http_status_code.h" #include "net/url_request/url_request_simple_job.h" +const std::string kCorsHeader("Access-Control-Allow-Origin: *"); + namespace atom { class URLRequestBufferJob : public JsAsker { diff --git a/atom/browser/net/url_request_string_job.cc b/atom/browser/net/url_request_string_job.cc index 4a631b813eff..5d7a7dd017c9 100644 --- a/atom/browser/net/url_request_string_job.cc +++ b/atom/browser/net/url_request_string_job.cc @@ -32,6 +32,9 @@ void URLRequestStringJob::GetResponseInfo(net::HttpResponseInfo* info) { std::string status("HTTP/1.1 200 OK"); net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); + std::string cors("Access-Control-Allow-Origin: *"); + headers->AddHeader(cors); + if (!mime_type_.empty()) { std::string content_type_header(net::HttpRequestHeaders::kContentType); content_type_header.append(": "); From 65cb1488b0e32034d17ba3f8753b7dca015828aa Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 25 Nov 2015 15:00:34 -0800 Subject: [PATCH 655/738] Fix CORS header code to be cleaner --- atom/browser/net/js_asker.cc | 2 ++ atom/browser/net/js_asker.h | 1 + atom/browser/net/url_request_buffer_job.cc | 3 +-- atom/browser/net/url_request_string_job.cc | 3 +-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index 8f0d1d2b9577..0e232feffb9d 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -11,6 +11,8 @@ namespace atom { +const std::string kCorsHeader("Access-Control-Allow-Origin: *"); + namespace internal { namespace { diff --git a/atom/browser/net/js_asker.h b/atom/browser/net/js_asker.h index 8ec245ee8c4f..cdc0417f36d3 100644 --- a/atom/browser/net/js_asker.h +++ b/atom/browser/net/js_asker.h @@ -17,6 +17,7 @@ #include "v8/include/v8.h" namespace atom { +extern const std::string kCorsHeader; using JavaScriptHandler = base::Callback)>; diff --git a/atom/browser/net/url_request_buffer_job.cc b/atom/browser/net/url_request_buffer_job.cc index c4936ba15696..55603e77e027 100644 --- a/atom/browser/net/url_request_buffer_job.cc +++ b/atom/browser/net/url_request_buffer_job.cc @@ -50,8 +50,7 @@ void URLRequestBufferJob::GetResponseInfo(net::HttpResponseInfo* info) { status.append("\0\0", 2); net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); - std::string cors("Access-Control-Allow-Origin: *"); - headers->AddHeader(cors); + headers->AddHeader(kCorsHeader); if (!mime_type_.empty()) { std::string content_type_header(net::HttpRequestHeaders::kContentType); diff --git a/atom/browser/net/url_request_string_job.cc b/atom/browser/net/url_request_string_job.cc index 5d7a7dd017c9..6a12026b2d74 100644 --- a/atom/browser/net/url_request_string_job.cc +++ b/atom/browser/net/url_request_string_job.cc @@ -32,8 +32,7 @@ void URLRequestStringJob::GetResponseInfo(net::HttpResponseInfo* info) { std::string status("HTTP/1.1 200 OK"); net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); - std::string cors("Access-Control-Allow-Origin: *"); - headers->AddHeader(cors); + headers->AddHeader(kCorsHeader); if (!mime_type_.empty()) { std::string content_type_header(net::HttpRequestHeaders::kContentType); From 7cce3987eb0a91ae481c53568c378ea3a115a720 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 25 Nov 2015 15:00:47 -0800 Subject: [PATCH 656/738] Add CORS header to file jobs --- atom/browser/net/url_request_async_asar_job.cc | 9 +++++++++ atom/browser/net/url_request_async_asar_job.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/atom/browser/net/url_request_async_asar_job.cc b/atom/browser/net/url_request_async_asar_job.cc index 303bfc0170d9..86d92071e320 100644 --- a/atom/browser/net/url_request_async_asar_job.cc +++ b/atom/browser/net/url_request_async_asar_job.cc @@ -34,4 +34,13 @@ void URLRequestAsyncAsarJob::StartAsync(scoped_ptr options) { } } + +void URLRequestAsyncAsarJob::GetResponseInfo(net::HttpResponseInfo* info) { + std::string status("HTTP/1.1 200 OK"); + net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); + + headers->AddHeader(kCorsHeader); + info->headers = headers; +} + } // namespace atom diff --git a/atom/browser/net/url_request_async_asar_job.h b/atom/browser/net/url_request_async_asar_job.h index df1aed350b8b..d65142f0bdbb 100644 --- a/atom/browser/net/url_request_async_asar_job.h +++ b/atom/browser/net/url_request_async_asar_job.h @@ -18,6 +18,9 @@ class URLRequestAsyncAsarJob : public JsAsker { // JsAsker: void StartAsync(scoped_ptr options) override; + // URLRequestJob: + void GetResponseInfo(net::HttpResponseInfo* info) override; + private: DISALLOW_COPY_AND_ASSIGN(URLRequestAsyncAsarJob); }; From 15b8d7680ecbfb86168acdbdfe218d9ab962273d Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 25 Nov 2015 15:20:50 -0800 Subject: [PATCH 657/738] Add tests to verify behavior --- spec/api-protocol-spec.coffee | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/spec/api-protocol-spec.coffee b/spec/api-protocol-spec.coffee index d160512cd736..5332b2b17ce6 100644 --- a/spec/api-protocol-spec.coffee +++ b/spec/api-protocol-spec.coffee @@ -81,6 +81,21 @@ describe 'protocol module', -> error: (xhr, errorType, error) -> done(error) + it 'sets Access-Control-Allow-Origin', (done) -> + handler = (request, callback) -> callback(text) + protocol.registerStringProtocol protocolName, handler, (error) -> + return done(error) if error + $.ajax + url: "#{protocolName}://fake-host" + success: (data, status, request) -> + assert.equal data, text + assert.equal( + request.getResponseHeader('Access-Control-Allow-Origin'), + '*') + done() + error: (xhr, errorType, error) -> + done(error) + it 'sends object as response', (done) -> handler = (request, callback) -> callback(data: text, mimeType: 'text/html') protocol.registerStringProtocol protocolName, handler, (error) -> @@ -120,6 +135,21 @@ describe 'protocol module', -> error: (xhr, errorType, error) -> done(error) + it 'sets Access-Control-Allow-Origin', (done) -> + handler = (request, callback) -> callback(buffer) + protocol.registerBufferProtocol protocolName, handler, (error) -> + return done(error) if error + $.ajax + url: "#{protocolName}://fake-host" + success: (data, status, request) -> + assert.equal data, text + assert.equal( + request.getResponseHeader('Access-Control-Allow-Origin'), + '*') + done() + error: (xhr, errorType, error) -> + done(error) + it 'sends object as response', (done) -> handler = (request, callback) -> callback(data: buffer, mimeType: 'text/html') protocol.registerBufferProtocol protocolName, handler, (error) -> @@ -163,6 +193,21 @@ describe 'protocol module', -> error: (xhr, errorType, error) -> done(error) + it 'sets Access-Control-Allow-Origin', (done) -> + handler = (request, callback) -> callback(filePath) + protocol.registerFileProtocol protocolName, handler, (error) -> + return done(error) if error + $.ajax + url: "#{protocolName}://fake-host" + success: (data, status, request) -> + assert.equal data, String(fileContent) + assert.equal( + request.getResponseHeader('Access-Control-Allow-Origin'), + '*') + done() + error: (xhr, errorType, error) -> + done(error) + it 'sends object as response', (done) -> handler = (request, callback) -> callback(path: filePath) protocol.registerFileProtocol protocolName, handler, (error) -> From 549da7fd91325b2370716fadfa2bc1a177593fe6 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 30 Nov 2015 11:08:22 -0800 Subject: [PATCH 658/738] Linting --- atom/browser/net/js_asker.h | 2 ++ atom/browser/net/url_request_buffer_job.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/net/js_asker.h b/atom/browser/net/js_asker.h index cdc0417f36d3..b353b98fa7c4 100644 --- a/atom/browser/net/js_asker.h +++ b/atom/browser/net/js_asker.h @@ -5,6 +5,8 @@ #ifndef ATOM_BROWSER_NET_JS_ASKER_H_ #define ATOM_BROWSER_NET_JS_ASKER_H_ +#include + #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" diff --git a/atom/browser/net/url_request_buffer_job.h b/atom/browser/net/url_request_buffer_job.h index 8de5d82e0df2..ab8de7e8f030 100644 --- a/atom/browser/net/url_request_buffer_job.h +++ b/atom/browser/net/url_request_buffer_job.h @@ -12,8 +12,6 @@ #include "net/http/http_status_code.h" #include "net/url_request/url_request_simple_job.h" -const std::string kCorsHeader("Access-Control-Allow-Origin: *"); - namespace atom { class URLRequestBufferJob : public JsAsker { From c83976dfdc1444d1aa2a1d90bab873186d6c533a Mon Sep 17 00:00:00 2001 From: Artur de Oliveira Tsuda Date: Mon, 30 Nov 2015 19:14:33 -0200 Subject: [PATCH 659/738] :memo: [ci skip] Fix typos --- .../pt-BR/tutorial/quick-start.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs-translations/pt-BR/tutorial/quick-start.md b/docs-translations/pt-BR/tutorial/quick-start.md index f9883144c825..eecf67878fc4 100644 --- a/docs-translations/pt-BR/tutorial/quick-start.md +++ b/docs-translations/pt-BR/tutorial/quick-start.md @@ -4,7 +4,7 @@ Electron permite criar aplicações desktop com puro JavaScript através de um runtime com APIs ricas e nativas. Você pode ver isso como uma variação do runtime do io.js que é focado em aplicações desktop em vez de web servers. -Isso não significa que o Electron é uma ligação em JavaScript para blibliotécas +Isso não significa que o Electron é uma ligação em JavaScript para bibliotecas de interface gráfica (GUI). Em vez disso, Electron usa páginas web como interface gráfica, então você pode ver isso também como um navegador Chromium mínimo, controlado por JavaScript. @@ -17,13 +17,13 @@ mostrar uma GUI criando páginas web. ### Processo Renderizador -Desde que o Electron usa o Chromium para mostrar as páginas web, a arquitetura +Já que o Electron usa o Chromium para mostrar as páginas web, a arquitetura multi-processo do Chromium também é usada. Cada página web no Electron roda em seu próprio processo, o que é chamado de __processo renderizador__. Em navegadores comuns, as páginas web normalmente rodam em um ambiente em sandbox -e não tem permissão de acesso para recursos nativos. Usuários Electron, entretanto, -tem o poder de usar as APIs do io.js nas páginas web, permitindo interações de baixo +e não têm permissão de acesso para recursos nativos. Usuários Electron, entretanto, +têm o poder de usar as APIs do io.js nas páginas web, permitindo interações de baixo nível no sistema operacional. ### Diferenças Entre o Processo Principal e o Processo Renderizador @@ -33,12 +33,12 @@ Cada instância de `BrowserWindow` roda a página web em seu próprio processo r Quando uma instância de `BrowserWindow` é destruída, o processo renderizador correspondente também é finalizado. -O processo principal gerência todas as páginas web de seus processos renderizadores +O processo principal gerencia todas as páginas web de seus processos renderizadores correspondentes. Cada processo renderizador é isolado e toma conta de sua respectiva página web. Nas páginas web, chamar APIs nativas relacionadas à GUI não é permitido porque -gerênciar recursos de GUI em páginas web é muito perigoso e torna fácil o vazamento de +gerenciar recursos de GUI em páginas web é muito perigoso e torna fácil o vazamento de recursos. Se você quer realizar operações com GUI em páginas web, o processo renderizador da página web deve se comunicar com o processo principal para requisitar que o processo principal realize estas operações. @@ -52,26 +52,26 @@ módulo [remoto](../../../docs/api/remote.md) para comunicação RPC. Geralmente, um app Electron é estruturado assim: ```text -your-app/ +seu-app/ ├── package.json ├── main.js └── index.html ``` -O formato de `package.json` é exatamente o mesmo que os dos módulos do Node, e +O formato de `package.json` é exatamente o mesmo que o dos módulos do Node, e o script especificado pelo campo `main` é o script de inicialização do seu app, que irá executar o processo principal. Um exemplo do seu `package.json` deve parecer com isso: ```json { - "name" : "your-app", + "name" : "seu-app", "version" : "0.1.0", "main" : "main.js" } ``` -__Nota__: Se o campo `main` não estiver presente no `package.jso`, o Electron irá +__Nota__: Se o campo `main` não estiver presente no `package.json`, o Electron irá tentar carregar um `index.js` O `main.js` deve criar as janelas e os manipuladores de eventos do sistema, um típico @@ -140,8 +140,8 @@ Finalmente o `index.html` é a página web que você quer mostrar: ## Execute seu App -Uma vez que você criou seus arquivos `main.js`, `index.html, e `package.json` iniciais, -você provavelmente vai querer tentar executar seu app localmente para testa-lo a ter +Uma vez que você criou seus arquivos `main.js`, `index.html`, e `package.json` iniciais, +você provavelmente vai querer tentar executar seu app localmente para testa-lo e ter certeza que funciona como você espera. ### electron-prebuilt @@ -167,19 +167,19 @@ executar seu app diretamente. #### Windows ```bash -$ .\electron\electron.exe your-app\ +$ .\electron\electron.exe seu-app\ ``` #### Linux ```bash -$ ./electron/electron your-app/ +$ ./electron/electron seu-app/ ``` #### OS X ```bash -$ ./Electron.app/Contents/MacOS/Electron your-app/ +$ ./Electron.app/Contents/MacOS/Electron seu-app/ ``` `Electron.app` aqui é uma parte do pacote de lançamento do Electron, você pode baixa-lo @@ -188,5 +188,5 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/ ### Executar como uma distribuição Depois de terminar seu app, você pode criar uma distribuição seguindo o guia -[Application Distribution](./application-distribution.md) e então executar o app +[Distribuição de aplicações](./application-distribution.md) e então executar o app empacotado. From 97f535251b215a515db7af2a1c79453926a025d9 Mon Sep 17 00:00:00 2001 From: Artur de Oliveira Tsuda Date: Mon, 30 Nov 2015 19:43:19 -0200 Subject: [PATCH 660/738] :memo: [ci skip] Update to match english docs. --- docs-translations/pt-BR/README.md | 77 ++++++++++++++++++------------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/docs-translations/pt-BR/README.md b/docs-translations/pt-BR/README.md index 1641f2380704..61202f8ca471 100644 --- a/docs-translations/pt-BR/README.md +++ b/docs-translations/pt-BR/README.md @@ -1,71 +1,82 @@ +Por favor, certifique-se de que está utilizando a documentação que corresponde à sua versão do Electron. +O número da versão deve ser uma parte da URL da página. Se não for, você provavelmente está utilizando +a documentação de um branch de desenvolvimento que pode conter mudanças na API que não são compatíveis +com a sua versão do Electron. Se este for o caso, você pode mudar para uma versão diferente da +documentação na lista de [versões disponíveis](http://electron.atom.io/docs/) em atom.io, +ou se você estiver usando a interface do GitHub, abra o *dropdown* "Switch branches/tags" e +selecione a *tag* que corresponde à sua versão. + ## Guias +* [Platformas Suportadas](../../tutorial/supported-platforms.md) * [Distribuição de Aplicações](tutorial/application-distribution.md) -* [Empacotamento da aplicação](tutorial/application-packaging.md) -* [Usando módulos nativos](tutorial/using-native-node-modules.md) -* [Depuração do processo principal](tutorial/debugging-main-process.md) +* [Guia de Submissão da Mac App Store](../../tutorial/mac-app-store-submission-guide.md) +* [Empacotamento da Aplicação](tutorial/application-packaging.md) +* [Usando Módulos Nativos do Node](tutorial/using-native-node-modules.md) +* [Depuração do Processo Principal](tutorial/debugging-main-process.md) * [Usando Selenium e WebDriver](../../docs/tutorial/using-selenium-and-webdriver.md) * [Extensão DevTools](../../docs/tutorial/devtools-extension.md) -* [Usando o plugin papper flash](tutorial/using-pepper-flash-plugin.md) +* [Usando o Plugin Pepper Flash](tutorial/using-pepper-flash-plugin.md) ## Tutoriais * [Introdução](tutorial/quick-start.md) -* [A integração com o ambiente de desenvolvimento](tutorial/desktop-environment-integration.md) -* [Evento de detecção on-line/off-line](tutorial/online-offline-events.md) +* [Integração com o Ambiente de Desenvolvimento](tutorial/desktop-environment-integration.md) +* [Evento de Detecção Online/Offline](tutorial/online-offline-events.md) -## API - Referencias +## API - Referências * [Sinopse](../../docs/api/synopsis.md) * [Processos](api/process.md) * [Aceleradores (Teclas de Atalho)](api/accelerator.md) * [Parâmetros CLI suportados (Chrome)](../../docs/api/chrome-command-line-switches.md) +* [Variáveis de Ambiente](../../docs/api/environment-variables.md) -DOM elementos personalizados: +### Elementos DOM Personalizados: * [Objeto `File`](../../docs/api/file-object.md) * [Tag ``](../../docs/api/web-view-tag.md) * [Função `window.open`](../../docs/api/window-open.md) -Os principais módulos: +### Módulos para o Processo Principal: * [app](../../docs/api/app.md) -* [auto-updater](../../docs/api/auto-updater.md) -* [browser-window](../../docs/api/browser-window.md) -* [content-tracing](../../docs/api/content-tracing.md) +* [autoUpdater](../../docs/api/auto-updater.md) +* [BrowserWindow](../../docs/api/browser-window.md) +* [contentTracing](../../docs/api/content-tracing.md) * [dialog](../../docs/api/dialog.md) -* [global-shortcut](../../docs/api/global-shortcut.md) -* [ipc (main process)](../../docs/api/ipc-main-process.md) -* [menu](../../docs/api/menu.md) -* [menu-item](../../docs/api/menu-item.md) -* [power-monitor](../../docs/api/power-monitor.md) -* [power-save-blocker](../../docs/api/power-save-blocker.md) +* [globalShortcut](../../docs/api/global-shortcut.md) +* [ipcMain](../../docs/api/ipc-main-process.md) +* [Menu](../../docs/api/menu.md) +* [MenuItem](../../docs/api/menu-item.md) +* [powerMonitor](../../docs/api/power-monitor.md) +* [powerSaveBlocker](../../docs/api/power-save-blocker.md) * [protocol](../../docs/api/protocol.md) * [session](../../docs/api/session.md) * [webContents](../../docs/api/web-contents.md) -* [tray](../../docs/api/tray.md) +* [Tray](../../docs/api/tray.md) -Módulos do renderizador (web page): +### Módulos para o Processo Renderizador: -* [ipc (renderer)](../../docs/api/ipc-renderer.md) +* [ipcRenderer](../../docs/api/ipc-renderer.md) * [remote](../../docs/api/remote.md) -* [web-frame](../../docs/api/web-frame.md) +* [webFrame](../../docs/api/web-frame.md) -Módulos de ambos os processos: +### Módulos para ambos os processos: * [clipboard](../../docs/api/clipboard.md) -* [crash-reporter](../../docs/api/crash-reporter.md) -* [native-image](../../docs/api/native-image.md) +* [crashReporter](../../docs/api/crash-reporter.md) +* [nativeImage](../../docs/api/native-image.md) * [screen](../../docs/api/screen.md) * [shell](api/shell.md) ## Desenvolvimento -* [Estilo de código](development/coding-style.md) -* [Estrutura de diretórios padrão](../../docs/development/source-code-directory-structure.md) -* [Diferenças técnicas do NW.js (antigo node-webkit)](../../docs/development/atom-shell-vs-node-webkit.md) -* [Visão geral do build](../../docs/development/build-system-overview.md) -* [Instrução de build (Mac)](../../docs/development/build-instructions-osx.md) -* [Instrução de build (Windows)](../../docs/development/build-instructions-windows.md) -* [Instrução de build (Linux)](../../docs/development/build-instructions-linux.md) -* [Configurando um symbol server no debugger](../../docs/development/setting-up-symbol-server.md) +* [Estilo de Código](development/coding-style.md) +* [Estrutura de Diretórios de Código Fonte](../../docs/development/source-code-directory-structure.md) +* [Diferenças Técnicas do NW.js (antigo node-webkit)](../../docs/development/atom-shell-vs-node-webkit.md) +* [Visão Geral do Build](../../docs/development/build-system-overview.md) +* [Instrução de Build (Mac)](../../docs/development/build-instructions-osx.md) +* [Instrução de Build (Windows)](../../docs/development/build-instructions-windows.md) +* [Instrução de Build (Linux)](../../docs/development/build-instructions-linux.md) +* [Configurando um Symbol Server no Debugger](../../docs/development/setting-up-symbol-server.md) From 7da78a9fa8ffdd0d9300bb12892683de6a154a5d Mon Sep 17 00:00:00 2001 From: Artur de Oliveira Tsuda Date: Mon, 30 Nov 2015 21:56:19 -0200 Subject: [PATCH 661/738] :memo: [ci skip] Add translation to app.md --- docs-translations/pt-BR/api/app.md | 452 +++++++++++++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 docs-translations/pt-BR/api/app.md diff --git a/docs-translations/pt-BR/api/app.md b/docs-translations/pt-BR/api/app.md new file mode 100644 index 000000000000..85cfaade5852 --- /dev/null +++ b/docs-translations/pt-BR/api/app.md @@ -0,0 +1,452 @@ +# app + +O módulo `app` é responsável por controlar o ciclo de vida do aplicativo. + +O exemplo a seguir mostra como fechar o aplicativo quando a última janela é fechada: + +```javascript +const app = require('electron').app; +app.on('window-all-closed', function() { + app.quit(); +}); +``` + +## Eventos + +O objeto `app` emite os seguintes eventos: + +### Evento: 'will-finish-launching' + +Emitido quando o aplicativo finaliza a inicialização básica. No Windows e no Linux, +o evento `will-finish-launching` é o mesmo que o evento `ready`; No OS X, +esse evento representa a notificação `applicationWillFinishLaunching` do `NSApplication`. +Normalmente aqui seriam criados *listeners* para os eventos `open-file` e `open-url`, e inicializar o *crash reporter* e atualizador automático. + +Na maioria dos casos, você deve fazer tudo no manipulador de eventos do `ready`. + +### Evento: 'ready' + +Emitido quando o Electron finaliza a inicialização. + +### Evento: 'window-all-closed' + +Emitido quando todas as janelas forem fechadas. + +Este evento só é emitido quando o aplicativo não for fechar. Se o +usuário pressionou`Cmd + Q`, ou o desenvolvedor chamou `app.quit()`, +o Electron tentará primeiro fechar todas as janelas e então emitir o +evento `will-quit`, e neste caso o evento `window-all-closed` não +seria emitido. + +### Evento: 'before-quit' + +Retorna: + +* `event` Event + +Emitido antes que o aplicativo comece a fechar suas janelas. +Chamar `event.preventDefault()` irá impedir o comportamento padrão, +que é terminar o aplicativo. + +### Evento: 'will-quit' + +Retorna: + +* `event` Event + +Emitido quando todas as janelas foram fechadas e o aplicativo irá finalizar. +Chamar `event.preventDefault()` irá impedir o comportamento padrão, +que é terminar o aplicativo. + +Veja a descrição do evento `window-all-closed` para as diferenças entre o +evento `will-quit` e `window-all-closed`. + +### Evento: 'quit' + +Emitido quando o aplicativo está finalizando. + +### Evento: 'open-file' _OS X_ + +Retorna: + +* `event` Event +* `path` String + +Emitido quando o usuário deseja abrir um arquivo com o aplicativo. O evento +`open-file` normalmente é emitido quando o aplicativo já está aberto e o S.O. +quer reutilizar o aplicativo para abrir o arquivo. `open-file` também é emitido +quando um arquivo é jogado no *dock* e o aplicativo ainda não está rodando. +Certifique-se de utilizar um *listener* para o evento `open-file` cedo na +inicialização do seu aplicativo para cuidar deste caso (antes mesmo do evento +`ready` ser emitido). + +Você deve chamar `event.preventDefault()` se quiser cuidar deste caso. + +No Windows, você deve fazer o *parse* do `process.argv` para pegar o +endereço do arquivo. + +### Evento: 'open-url' _OS X_ + +Retorna: + +* `event` Event +* `url` String + +Emitido quando o usuário deseja abrir uma URL com o aplicativo. O esquema deve +ser registrado para ser aberto pelo seu aplicativo. + +Você deve chamar `event.preventDefault()` se quiser cuidar deste caso. + +### Evento: 'activate' _OS X_ + +Retorna: + +* `event` Event +* `hasVisibleWindows` Boolean + +Emitido quando o aplicativo é ativado, que normalmente acontece quando o ícone +do aplicativo no *dock* é clicado. + +### Evento: 'browser-window-blur' + +Retorna: + +* `event` Event +* `window` BrowserWindow + +Emitido quando uma [browserWindow](../../../docs/api/browser-window.md) fica embaçada. + +### Evento: 'browser-window-focus' + +Retorna: + +* `event` Event +* `window` BrowserWindow + +Emitido quando uma [browserWindow](../../../docs/api/browser-window.md) é focada. + +### Evento: 'browser-window-created' + +Retorna: + +* `event` Event +* `window` BrowserWindow + +Emitido quando uma nova [browserWindow](../../../docs/api/browser-window.md) é criada. + +### Evento: 'certificate-error' + +Returns: + +* `event` Event +* `webContents` [WebContents](../../../docs/api/web-contents.md) +* `url` URL +* `error` String - O código de erro +* `certificate` Object + * `data` Buffer - dados codificados PEM + * `issuerName` String +* `callback` Function + +Emitido quando há uma falha na verificação do `certificate` para a `url`, +para confiar no certificado, você deve impedir o comportamento padrão com +`event.preventDefault()` e chamar `callback(true)`. + +```javascript +session.on('certificate-error', function(event, webContents, url, error, certificate, callback) { + if (url == "https://github.com") { + // Lógica de verificação. + event.preventDefault(); + callback(true); + } else { + callback(false); + } +}); +``` + +### Evento: 'select-client-certificate' + +Retorna: + +* `event` Event +* `webContents` [WebContents](../../../docs/api/web-contents.md) +* `url` URL +* `certificateList` [Objects] + * `data` Buffer - dados codificados PEM + * `issuerName` String - Nome Comum do Emissor +* `callback` Function + +Emitido quando um certificado de cliente é requisitado. + +A `url` corresponde à entrada de navegação requisitando o certificado do +cliente e `callback` precisa ser chamada com uma entrada filtrada da lista. +Usar `event.preventDefault()` impede o aplicativo de usar o primeiro certificado +da memória. + +```javascript +app.on('select-client-certificate', function(event, webContents, url, list, callback) { + event.preventDefault(); + callback(list[0]); +}) +``` + +### Evento: 'login' + +Retorna: + +* `event` Event +* `webContents` [WebContents](../../../docs/api/web-contents.md) +* `request` Object + * `method` String + * `url` URL + * `referrer` URL +* `authInfo` Object + * `isProxy` Boolean + * `scheme` String + * `host` String + * `port` Integer + * `realm` String +* `callback` Function + +Emitido quando `webContents` deseja fazer autenticação básica. + +O comportamento padrão é cancelar todas as autenticações, para sobrescrever +isto, você deve impedir esse comportamento com `event.preventDefault()` e +chamar `callback(username, password)` com as credenciais. + +```javascript +app.on('login', function(event, webContents, request, authInfo, callback) { + event.preventDefault(); + callback('username', 'secret'); +}) +``` + +### Evento: 'gpu-process-crashed' + +Emitido quando o processo da gpu falha. + +## Métodos + +O objeto `app` possui os seguintes métodos: + +**Nota:** Alguns métodos só estão disponíveis em sistemas operacionais específicos e estão rotulados como tal. + +### `app.quit()` + +Tente fechar todas as janelas. O evento `before-quit` será emitido primeiro. Se todas +as janelas fecharem com sucesso, o evento `will-quit` será emitido e por padrão o +aplicativo irá terminar. + +Este método garante que todos os manipuladores de evento `beforeunload` e `unload` +sejam corretamente executados. É possível que uma janela cancele o processo de +encerramento ao retornar `false` no manipulador de evento `beforeunload`. + +### `app.exit(exitCode)` + +* `exitCode` Integer + +Finaliza imediatamente com `exitCode`. + +Todas as janelas serão fechadas imediatamente sem perguntar ao usuário, e os eventos +`before-quit` e `will-quit` não serão emitidos. + +### `app.getAppPath()` + +Retorna o atual diretório do aplicativo. + +### `app.getPath(name)` + +* `name` String + +Retorna um endereço para um diretório especial ou arquivo associado com `nome`. +Numa falha um `Error` é lançado. + +Você pode requisitar os seguintes endereços pelo nome: + +* `home` Diretório *home* do usuário. +* `appData` Diretório de dados do aplicativo por usuário, que por padrão aponta para: + * `%APPDATA%` no Windows + * `$XDG_CONFIG_HOME` ou `~/.config` no Linux + * `~/Library/Application Support` no OS X +* `userData` O diretório para guardar os arquivos de configuração do seu aplicativo, que por padrão é o diretório `appData` concatenado com o nome do seu aplicativo. +* `temp` Diretório temporário. +* `exe` O arquivo executável atual. +* `module` A biblioteca `libchromiumcontent`. +* `desktop` O diretório *Desktop* do usuário atual. +* `documents` Diretório "Meus Documentos" do usuário. +* `downloads` Diretório dos downloads do usuário. +* `music` Diretório de músicas do usuário. +* `pictures` Diretório de imagens do usuário. +* `videos` Diretório de vídeos do usuário. + +### `app.setPath(name, path)` + +* `name` String +* `path` String + +Sobrescreve o `path` para um diretório especial ou arquivo associado com `name`. +Se o endereço especifica um diretório não existente, o diretório será criado por +este método. Numa falha um `Error` é lançado. + +Você pode sobrescrever apenas endereços com um `name` definido em `app.getPath`. + +Por padrão, *cookies* e *caches* de páginas web serão guardadas no diretório `userData`. Se você quiser mudar esta localização, você deve sobrescrever o +endereço `userData` antes que o evento `ready` do módulo `app` seja emitido. + +### `app.getVersion()` + +Retorna a versão do aplicativo carregado. Se nenhuma versão for encontrada no +arquivo `package.json` do aplicativo, a versão do pacote ou executável atual é +retornada. + +### `app.getName()` + +Retorna o nome do aplicativo atual, que é o nome no arquivo `package.json` do +aplicativo. + +Normalmente o campo `name` do `package.json` é um nome curto em letras minúsculas, +de acordo com as especificações de módulos npm. Normalmente você deve também +especificar um campo `productName`, que é o nome completo em letras maiúsculas do +seu aplicativo, e que será preferido ao `name` pelo Electron. + +### `app.getLocale()` + +Retorna a localidade atual do aplicativo. + +### `app.addRecentDocument(path)` _OS X_ _Windows_ + +* `path` String + +Adiciona `path` à lista de documentos recentes. + +Esta lista é gerenciada pelo S.O.. No Windows você pode visitar a lista pela +barra de tarefas, e no OS X você pode visita-la pelo *dock*. + +### `app.clearRecentDocuments()` _OS X_ _Windows_ + +Limpa a lista de documentos recentes. + +### `app.setUserTasks(tasks)` _Windows_ + +* `tasks` Array - Vetor de objetos `Task` + +Adiciona `tasks` à categoria [Tasks][tasks] do JumpList no Windows. + +`tasks` é um vetor de objetos `Task` no seguinte formato: + +`Task` Object +* `program` String - Endereço do programa a ser executado, normalmente você deve especificar `process.execPath` que abre o programa atual. +* `arguments` String - Os argumentos de linha de comando quando `program` é executado. +* `title` String - A string a ser exibida em uma JumpList. +* `description` String - Descrição desta *task*. +* `iconPath` String - O endereço absoluto para um ícone a ser exibido em uma JumpList, que pode ser um arquivo arbitrário que contém um ícone. Normalmente você pode especificar `process.execPath` para mostrar o ícone do programa. +* `iconIndex` Integer - O índice do ícone do arquivo do icone. Se um arquivo de ícone consiste de dois ou mais ícones, defina este valor para identificar o ícone. Se o arquivo de ícone consiste de um ícone apenas, este valor é 0. + +### `app.allowNTLMCredentialsForAllDomains(allow)` + +* `allow` Boolean + +Define dinamicamente se sempre envia credenciais para HTTP NTLM ou autenticação *Negotiate* - normalmente, o Electron irá mandar apenas credenciais NTLM/Kerberos para URLs que se enquadram em sites "Intranet Local" (estão no mesmo domínio que você). +Entretanto, esta detecção frequentemente falha quando redes corporativas são mal configuradas, então isso permite optar por esse comportamento e habilitá-lo para todas as URLs. + +### `app.makeSingleInstance(callback)` + +* `callback` Function + +Este método faz da sua aplicação uma Aplicação de Instância Única - invés de permitir múltiplas instâncias do seu aplicativo rodarem, isto irá assegurar que apenas uma única instância do seu aplicativo rodará, e outras instâncias sinalizam esta instância e finalizam. + +`callback` será chamado com `callback(argv, workingDirectory)` quando uma segunda instância tenha sido executada. `argv` é um vetor de argumentos de linha de comando da segunda instância, e `workingDirectory` é o atual endereço de seu diretório. +Normalmente aplicativos respondem à isso não minimizando sua janela primária e dando foco à ela. + +É garantida a execução do `callback` após o evento `ready` do `app` ser emitido. + +Este método retorna `false` caso seu processo seja a instância primária do aplicativo e seu aplicativo deve continuar carregando. E retorna `true` caso seu processo tenha enviado seus parâmetros para outra instância, e você deve imediatamente finalizar. + +No OS X o sistema enforça instância única automaticamente quando usuários tentam abrir uma segunda instância do seu aplicativo no *Finder*, e os eventos `open-file` e `open-url` serão emitidos para isso. Entretanto, quando usuários inicializam seu aplicativo na linha de comando, o mecanismo de instância única do sistema será ignorado e você terá de utilizar esse método para assegurar-se de ter uma instância única. + +Um exemplo de ativação da janela de primeira instância quando uma segunda instância inicializa: + +```js +var myWindow = null; + +var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) { + // Alguém tentou rodar uma segunda instância, devemos focar nossa janela + if (myWindow) { + if (myWindow.isMinimized()) myWindow.restore(); + myWindow.focus(); + } + return true; +}); + +if (shouldQuit) { + app.quit(); + return; +} + +// Cria myWindow, carrega o resto do aplicativo, etc... +app.on('ready', function() { +}); +``` + +### `app.setAppUserModelId(id)` _Windows_ + +* `id` String + +Muda o [Application User Model ID][app-user-model-id] para `id`. + +### `app.commandLine.appendSwitch(switch[, value])` + +Adiciona uma opção (com `value` opcional) à linha de comando do Chromium. + +**Nota:** Isto não irá afetar `process.argv`, e é utilizado principalmente por desenvolvedores para controlar alguns comportamentos de baixo nível do Chromium. + +### `app.commandLine.appendArgument(value)` + +Adiciona um argumento à linha de comando do Chromium. O argumento será passado com aspas corretamente. + +**Nota:** Isto não irá afetar `process.argv`. + +### `app.dock.bounce([type])` _OS X_ + +* `type` String (opcional) - Pode ser `critical` ou `informational`. O padrão é + `informational` + +Quando `critical` é passado, o ícone do *dock* irá pular até que o aplicativo se torne ativo ou a requisição seja cancelada. + +Quando `informational` é passado, o ícone do *dock* irá pular por um segundo. +Entretanto, a requisição se mantém ativa até que o aplicativo se torne ativo ou a requisição seja cancelada. + +Retorna um ID representando a requisição. + +### `app.dock.cancelBounce(id)` _OS X_ + +* `id` Integer + +Cancela o salto do `id`. + +### `app.dock.setBadge(text)` _OS X_ + +* `text` String + +Define a string a ser exibida na área de *badging* do *dock*. + +### `app.dock.getBadge()` _OS X_ + +Retorna a string da *badge* do *dock*. + +### `app.dock.hide()` _OS X_ + +Esconde o ícone do *dock*. + +### `app.dock.show()` _OS X_ + +Exibe o ícone do *dock*. + +### `app.dock.setMenu(menu)` _OS X_ + +* `menu` Menu + +Define o [menu do dock][dock-menu] do aplicativo. + +[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 7fd1db192b1d0f9da0150e01f34c64bf596eb875 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 30 Nov 2015 18:12:00 -0800 Subject: [PATCH 662/738] Lint harder --- atom/browser/net/url_request_async_asar_job.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/atom/browser/net/url_request_async_asar_job.cc b/atom/browser/net/url_request_async_asar_job.cc index 86d92071e320..46065259fca6 100644 --- a/atom/browser/net/url_request_async_asar_job.cc +++ b/atom/browser/net/url_request_async_asar_job.cc @@ -4,6 +4,8 @@ #include "atom/browser/net/url_request_async_asar_job.h" +#include + namespace atom { URLRequestAsyncAsarJob::URLRequestAsyncAsarJob( From e3ec1fe8abbad5c78dcf785fa64dfc2e10c751dd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 1 Dec 2015 13:09:37 +0800 Subject: [PATCH 663/738] Add process.noAsar to turn off asar support --- atom/common/lib/asar.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/atom/common/lib/asar.coffee b/atom/common/lib/asar.coffee index f7eeceb3f314..2373385f75d4 100644 --- a/atom/common/lib/asar.coffee +++ b/atom/common/lib/asar.coffee @@ -18,6 +18,7 @@ process.on 'exit', -> # Separate asar package's path from full path. splitPath = (p) -> + return [false] if process.noAsar # shortcut to disable asar. return [false] if typeof p isnt 'string' return [true, p, ''] if p.substr(-5) is '.asar' p = path.normalize p From 900dc78a47598cec6bbfc0d6220ce69016919e82 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 1 Dec 2015 13:09:50 +0800 Subject: [PATCH 664/738] spec: process.noAsar --- spec/asar-spec.coffee | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/spec/asar-spec.coffee b/spec/asar-spec.coffee index af39fa3ec5ea..b7a62f8eeaa2 100644 --- a/spec/asar-spec.coffee +++ b/spec/asar-spec.coffee @@ -423,6 +423,41 @@ describe 'asar package', -> p = path.join fixtures, 'asar', 'unpack.asar', 'a.txt' assert.equal internalModuleReadFile(p).toString().trim(), 'a' + describe 'process.noAsar', -> + beforeEach -> + process.noAsar = true + afterEach -> + process.noAsar = false + + it 'disables asar support in sync API', -> + file = path.join fixtures, 'asar', 'a.asar', 'file1' + dir = path.join fixtures, 'asar', 'a.asar', 'dir1' + assert.throws (-> fs.readFileSync file), /ENOTDIR/ + assert.throws (-> fs.lstatSync file), /ENOTDIR/ + assert.throws (-> fs.realpathSync file), /ENOTDIR/ + assert.throws (-> fs.readdirSync dir), /ENOTDIR/ + + it 'disables asar support in async API', (done) -> + file = path.join fixtures, 'asar', 'a.asar', 'file1' + dir = path.join fixtures, 'asar', 'a.asar', 'dir1' + fs.readFile file, (error) -> + assert.equal error.code, 'ENOTDIR' + fs.lstat file, (error) -> + assert.equal error.code, 'ENOTDIR' + fs.realpath file, (error) -> + assert.equal error.code, 'ENOTDIR' + fs.readdir dir, (error) -> + assert.equal error.code, 'ENOTDIR' + done() + + it 'treats *.asar as normal file', -> + originalFs = require 'original-fs' + asar = path.join fixtures, 'asar', 'a.asar' + content1 = fs.readFileSync asar + content2 = originalFs.readFileSync asar + assert.equal content1.compare(content2), 0 + assert.throws (-> fs.readdirSync asar), /ENOTDIR/ + describe 'asar protocol', -> url = require 'url' From 165b464a1503e8a03e761e8a0549848724b2b699 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 1 Dec 2015 13:43:52 +0800 Subject: [PATCH 665/738] docs: process.noAsar --- docs/api/process.md | 9 ++++++++- docs/tutorial/application-packaging.md | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/api/process.md b/docs/api/process.md index 22fe452b0cad..620ad6dc931a 100644 --- a/docs/api/process.md +++ b/docs/api/process.md @@ -31,11 +31,18 @@ process.once('loaded', function() { }); ``` +## Properties + +### `process.noAsar` + +Setting this to `true` can disable the support for `asar` archives in Node's +built-in modules. + ## Methods The `process` object has the following method: -### `process.hang` +### `process.hang()` Causes the main thread of the current process hang. diff --git a/docs/tutorial/application-packaging.md b/docs/tutorial/application-packaging.md index c6e0ae3c4103..b42a2f9298ba 100644 --- a/docs/tutorial/application-packaging.md +++ b/docs/tutorial/application-packaging.md @@ -103,6 +103,14 @@ var originalFs = require('original-fs'); originalFs.readFileSync('/path/to/example.asar'); ``` +You can also set `process.noAsar` to `true` to disable the support for `asar` in +the `fs` module: + +```javascript +process.noAsar = true; +fs.readFileSync('/path/to/example.asar'); +``` + ## Limitations on Node API Even though we tried hard to make `asar` archives in the Node API work like From 0f17a0163d16f8cdc2a032ebd96a3034525c0271 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 1 Dec 2015 16:21:15 +0800 Subject: [PATCH 666/738] Put common constants in atom_constants --- atom/browser/net/js_asker.cc | 2 -- atom/browser/net/js_asker.h | 3 --- atom/browser/net/url_request_async_asar_job.cc | 5 +++-- atom/browser/net/url_request_buffer_job.cc | 3 ++- atom/browser/net/url_request_string_job.cc | 3 ++- atom/common/atom_constants.cc | 11 +++++++++++ atom/common/atom_constants.h | 15 +++++++++++++++ filenames.gypi | 2 ++ 8 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 atom/common/atom_constants.cc create mode 100644 atom/common/atom_constants.h diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index 0e232feffb9d..8f0d1d2b9577 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -11,8 +11,6 @@ namespace atom { -const std::string kCorsHeader("Access-Control-Allow-Origin: *"); - namespace internal { namespace { diff --git a/atom/browser/net/js_asker.h b/atom/browser/net/js_asker.h index b353b98fa7c4..8ec245ee8c4f 100644 --- a/atom/browser/net/js_asker.h +++ b/atom/browser/net/js_asker.h @@ -5,8 +5,6 @@ #ifndef ATOM_BROWSER_NET_JS_ASKER_H_ #define ATOM_BROWSER_NET_JS_ASKER_H_ -#include - #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" @@ -19,7 +17,6 @@ #include "v8/include/v8.h" namespace atom { -extern const std::string kCorsHeader; using JavaScriptHandler = base::Callback)>; diff --git a/atom/browser/net/url_request_async_asar_job.cc b/atom/browser/net/url_request_async_asar_job.cc index 46065259fca6..3578f3b7971c 100644 --- a/atom/browser/net/url_request_async_asar_job.cc +++ b/atom/browser/net/url_request_async_asar_job.cc @@ -6,6 +6,8 @@ #include +#include "atom/common/atom_constants.h" + namespace atom { URLRequestAsyncAsarJob::URLRequestAsyncAsarJob( @@ -36,12 +38,11 @@ void URLRequestAsyncAsarJob::StartAsync(scoped_ptr options) { } } - void URLRequestAsyncAsarJob::GetResponseInfo(net::HttpResponseInfo* info) { std::string status("HTTP/1.1 200 OK"); net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); - headers->AddHeader(kCorsHeader); + headers->AddHeader(kCORSHeader); info->headers = headers; } diff --git a/atom/browser/net/url_request_buffer_job.cc b/atom/browser/net/url_request_buffer_job.cc index 55603e77e027..aa273bf81693 100644 --- a/atom/browser/net/url_request_buffer_job.cc +++ b/atom/browser/net/url_request_buffer_job.cc @@ -6,6 +6,7 @@ #include +#include "atom/common/atom_constants.h" #include "base/strings/string_number_conversions.h" #include "net/base/net_errors.h" @@ -50,7 +51,7 @@ void URLRequestBufferJob::GetResponseInfo(net::HttpResponseInfo* info) { status.append("\0\0", 2); net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); - headers->AddHeader(kCorsHeader); + headers->AddHeader(kCORSHeader); if (!mime_type_.empty()) { std::string content_type_header(net::HttpRequestHeaders::kContentType); diff --git a/atom/browser/net/url_request_string_job.cc b/atom/browser/net/url_request_string_job.cc index 6a12026b2d74..606781142da0 100644 --- a/atom/browser/net/url_request_string_job.cc +++ b/atom/browser/net/url_request_string_job.cc @@ -6,6 +6,7 @@ #include +#include "atom/common/atom_constants.h" #include "net/base/net_errors.h" namespace atom { @@ -32,7 +33,7 @@ void URLRequestStringJob::GetResponseInfo(net::HttpResponseInfo* info) { std::string status("HTTP/1.1 200 OK"); net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); - headers->AddHeader(kCorsHeader); + headers->AddHeader(kCORSHeader); if (!mime_type_.empty()) { std::string content_type_header(net::HttpRequestHeaders::kContentType); diff --git a/atom/common/atom_constants.cc b/atom/common/atom_constants.cc new file mode 100644 index 000000000000..dacda3c816c8 --- /dev/null +++ b/atom/common/atom_constants.cc @@ -0,0 +1,11 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/atom_constants.h" + +namespace atom { + +const char* kCORSHeader = "Access-Control-Allow-Origin: *"; + +} // namespace atom diff --git a/atom/common/atom_constants.h b/atom/common/atom_constants.h new file mode 100644 index 000000000000..e0d42e83eef9 --- /dev/null +++ b/atom/common/atom_constants.h @@ -0,0 +1,15 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_ATOM_CONSTANTS_H_ +#define ATOM_COMMON_ATOM_CONSTANTS_H_ + +namespace atom { + +// Header to ignore CORS. +extern const char* kCORSHeader; + +} // namespace atom + +#endif // ATOM_COMMON_ATOM_CONSTANTS_H_ diff --git a/filenames.gypi b/filenames.gypi index 7157079178ee..151a69ff1c9e 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -286,6 +286,8 @@ 'atom/common/asar/scoped_temporary_file.h', 'atom/common/atom_command_line.cc', 'atom/common/atom_command_line.h', + 'atom/common/atom_constants.cc', + 'atom/common/atom_constants.h', 'atom/common/common_message_generator.cc', 'atom/common/common_message_generator.h', 'atom/common/crash_reporter/crash_reporter.cc', From 1b3eb1cc5df74ed2dac3f8e7e0fea17497ddda28 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 1 Dec 2015 16:55:52 +0800 Subject: [PATCH 667/738] Delay the did-fail-provisional-load event to next tick Chrome is doing some stuff after the DidFailProvisionalLoad event, if we call LoadURL at this time crash would happen. --- atom/browser/api/atom_api_web_contents.cc | 5 ++--- atom/browser/api/lib/web-contents.coffee | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 066ca9cc7b65..339be85fe9bd 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -460,14 +460,13 @@ void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host, Emit("did-finish-load"); } -// this error occurs when host could not be found void WebContents::DidFailProvisionalLoad( content::RenderFrameHost* render_frame_host, - const GURL& validated_url, + const GURL& url, int error_code, const base::string16& error_description, bool was_ignored_by_handler) { - Emit("did-fail-load", error_code, error_description, validated_url); + Emit("did-fail-provisional-load", error_code, error_description, url); } void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host, diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index 335928dcea81..45545fe24874 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -70,6 +70,12 @@ wrapWebContents = (webContents) -> menu = Menu.buildFromTemplate params.menu menu.popup params.x, params.y + # This error occurs when host could not be found. + webContents.on 'did-fail-provisional-load', (args...) -> + # Calling loadURL during this event might cause crash, so delay the event + # until next tick. + setImmediate => @emit 'did-fail-load', args... + # Deprecated. deprecate.rename webContents, 'loadUrl', 'loadURL' deprecate.rename webContents, 'getUrl', 'getURL' From 8d20dda6d77370b962eddae38e4fa0c42bad08ba Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 1 Dec 2015 17:51:09 +0800 Subject: [PATCH 668/738] No need to override TitleWasSet in NativeWindow --- atom/browser/api/atom_api_window.cc | 5 ----- atom/browser/api/atom_api_window.h | 2 -- atom/browser/api/lib/browser-window.coffee | 5 +++++ atom/browser/native_window.cc | 11 ----------- atom/browser/native_window.h | 1 - atom/browser/native_window_observer.h | 4 ---- 6 files changed, 5 insertions(+), 23 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index a5aa4a126687..569640554468 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -161,11 +161,6 @@ Window::~Window() { Destroy(); } -void Window::OnPageTitleUpdated(bool* prevent_default, - const std::string& title) { - *prevent_default = Emit("page-title-updated", title); -} - void Window::WillCloseWindow(bool* prevent_default) { *prevent_default = Emit("close"); } diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 757abd205b31..a04e00cfb48e 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -54,8 +54,6 @@ class Window : public mate::TrackableObject, virtual ~Window(); // NativeWindowObserver: - void OnPageTitleUpdated(bool* prevent_default, - const std::string& title) override; void WillCloseWindow(bool* prevent_default) override; void OnWindowClosed() override; void OnWindowBlur() override; diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index d693a6d93403..84c7690867d1 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -31,6 +31,11 @@ BrowserWindow::_init = -> @webContents.on 'crashed', => @emit 'crashed' + # Change window title to page title. + @webContents.on 'page-title-set', (event, title, explicitSet) => + @emit 'page-title-updated', event, title + @setTitle title unless event.defaultPrevented + # Sometimes the webContents doesn't get focus when window is shown, so we have # to force focusing on webContents in this case. The safest way is to focus it # when we first start to load URL, if we do it earlier it won't have effect, diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index ad7a6c4b0654..a3df240e4d57 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -505,17 +505,6 @@ void NativeWindow::BeforeUnloadDialogCancelled() { window_unresposive_closure_.Cancel(); } -void NativeWindow::TitleWasSet(content::NavigationEntry* entry, - bool explicit_set) { - bool prevent_default = false; - std::string text = entry ? base::UTF16ToUTF8(entry->GetTitle()) : ""; - FOR_EACH_OBSERVER(NativeWindowObserver, - observers_, - OnPageTitleUpdated(&prevent_default, text)); - if (!prevent_default && !is_closed_) - SetTitle(text); -} - bool NativeWindow::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(NativeWindow, message) diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index e32b94811823..0c918d92df99 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -262,7 +262,6 @@ class NativeWindow : public base::SupportsUserData, // content::WebContentsObserver: void RenderViewCreated(content::RenderViewHost* render_view_host) override; void BeforeUnloadDialogCancelled() override; - void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override; bool OnMessageReceived(const IPC::Message& message) override; private: diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 54004a300d94..ce2d41c6fad6 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -21,10 +21,6 @@ class NativeWindowObserver { public: virtual ~NativeWindowObserver() {} - // Called when the web page of the window has updated it's document title. - virtual void OnPageTitleUpdated(bool* prevent_default, - const std::string& title) {} - // Called when the web page in window wants to create a popup window. virtual void WillCreatePopupWindow(const base::string16& frame_name, const GURL& target_url, From 83ee78451ad9d861deb0f14634f6c3fc2300e5d1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 1 Dec 2015 17:52:13 +0800 Subject: [PATCH 669/738] Emit event when title becomes empty --- atom/browser/api/atom_api_web_contents.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 339be85fe9bd..0c8a5ff3df25 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -519,9 +519,10 @@ void WebContents::DidNavigateMainFrame( void WebContents::TitleWasSet(content::NavigationEntry* entry, bool explicit_set) { - // Back/Forward navigation may have pruned entries. if (entry) Emit("page-title-set", entry->GetTitle(), explicit_set); + else + Emit("page-title-set", "", explicit_set); } void WebContents::DidUpdateFaviconURL( From c95117fb227f438b8dc622f124fb9096f6a915ed Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 1 Dec 2015 18:34:58 +0800 Subject: [PATCH 670/738] Delay the page-title-set event to next tick --- atom/browser/api/atom_api_web_contents.cc | 4 ++-- atom/browser/api/lib/web-contents.coffee | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 0c8a5ff3df25..b12b3fea2b85 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -520,9 +520,9 @@ void WebContents::DidNavigateMainFrame( void WebContents::TitleWasSet(content::NavigationEntry* entry, bool explicit_set) { if (entry) - Emit("page-title-set", entry->GetTitle(), explicit_set); + Emit("-page-title-set", entry->GetTitle(), explicit_set); else - Emit("page-title-set", "", explicit_set); + Emit("-page-title-set", "", explicit_set); } void WebContents::DidUpdateFaviconURL( diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index 45545fe24874..dbc9a15fc20c 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -76,6 +76,10 @@ wrapWebContents = (webContents) -> # until next tick. setImmediate => @emit 'did-fail-load', args... + # Delays the page-title-set event to next tick. + webContents.on '-page-title-set', (args...) -> + setImmediate => @emit 'page-title-set', args... + # Deprecated. deprecate.rename webContents, 'loadUrl', 'loadURL' deprecate.rename webContents, 'getUrl', 'getURL' From e5974e44ed5584db59eac5318b5d0b2dbd1dba7e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 1 Dec 2015 18:50:56 +0800 Subject: [PATCH 671/738] Deprecate the page-title-set event We have two names for the same event, page-title-updated wins. --- atom/browser/api/atom_api_web_contents.cc | 4 ++-- atom/browser/api/lib/browser-window.coffee | 2 +- atom/browser/api/lib/web-contents.coffee | 8 +++++--- atom/browser/lib/guest-view-manager.coffee | 2 +- .../lib/web-view/guest-view-internal.coffee | 20 +++++++++++-------- docs/api/web-view-tag.md | 6 +++--- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index b12b3fea2b85..f377e8fda9e8 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -520,9 +520,9 @@ void WebContents::DidNavigateMainFrame( void WebContents::TitleWasSet(content::NavigationEntry* entry, bool explicit_set) { if (entry) - Emit("-page-title-set", entry->GetTitle(), explicit_set); + Emit("-page-title-updated", entry->GetTitle(), explicit_set); else - Emit("-page-title-set", "", explicit_set); + Emit("-page-title-updated", "", explicit_set); } void WebContents::DidUpdateFaviconURL( diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 84c7690867d1..07b4191d7c7b 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -32,7 +32,7 @@ BrowserWindow::_init = -> @emit 'crashed' # Change window title to page title. - @webContents.on 'page-title-set', (event, title, explicitSet) => + @webContents.on 'page-title-updated', (event, title, explicitSet) => @emit 'page-title-updated', event, title @setTitle title unless event.defaultPrevented diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index dbc9a15fc20c..dacbc919d665 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -76,13 +76,15 @@ wrapWebContents = (webContents) -> # until next tick. setImmediate => @emit 'did-fail-load', args... - # Delays the page-title-set event to next tick. - webContents.on '-page-title-set', (args...) -> - setImmediate => @emit 'page-title-set', args... + # Delays the page-title-updated event to next tick. + webContents.on '-page-title-updated', (args...) -> + setImmediate => @emit 'page-title-updated', args... # Deprecated. deprecate.rename webContents, 'loadUrl', 'loadURL' deprecate.rename webContents, 'getUrl', 'getURL' + deprecate.event webContents, 'page-title-set', 'page-title-updated', (args...) -> + @emit 'page-title-set', args... webContents.printToPDF = (options, callback) -> printingSetting = diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index e6be05a907bf..d4bf55158fed 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -19,7 +19,7 @@ supportedWebViewEvents = [ 'gpu-crashed' 'plugin-crashed' 'destroyed' - 'page-title-set' + 'page-title-updated' 'page-favicon-updated' 'enter-html-full-screen' 'leave-html-full-screen' diff --git a/atom/renderer/lib/web-view/guest-view-internal.coffee b/atom/renderer/lib/web-view/guest-view-internal.coffee index 61a93d8cb6e3..b28fec23ed83 100644 --- a/atom/renderer/lib/web-view/guest-view-internal.coffee +++ b/atom/renderer/lib/web-view/guest-view-internal.coffee @@ -21,23 +21,27 @@ WEB_VIEW_EVENTS = 'gpu-crashed': [] 'plugin-crashed': ['name', 'version'] 'destroyed': [] - 'page-title-set': ['title', 'explicitSet'] + 'page-title-updated': ['title', 'explicitSet'] 'page-favicon-updated': ['favicons'] 'enter-html-full-screen': [] 'leave-html-full-screen': [] -dispatchEvent = (webView, event, args...) -> - throw new Error("Unknown event #{event}") unless WEB_VIEW_EVENTS[event]? - domEvent = new Event(event) - for f, i in WEB_VIEW_EVENTS[event] +DEPRECATED_EVENTS = + 'page-title-updated': 'page-title-set' + +dispatchEvent = (webView, eventName, eventKey, args...) -> + if DEPRECATED_EVENTS[eventName]? + dispatchEvent webView, DEPRECATED_EVENTS[eventName], eventKey, args... + domEvent = new Event(eventName) + for f, i in WEB_VIEW_EVENTS[eventKey] domEvent[f] = args[i] webView.dispatchEvent domEvent - webView.onLoadCommit domEvent if event == 'load-commit' + webView.onLoadCommit domEvent if eventName is 'load-commit' module.exports = registerEvents: (webView, viewInstanceId) -> - ipcRenderer.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}", (event, domEvent, args...) -> - dispatchEvent webView, domEvent, args... + ipcRenderer.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}", (event, eventName, args...) -> + dispatchEvent webView, eventName, eventName, args... ipcRenderer.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}", (event, channel, args...) -> domEvent = new Event('ipc-message') diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 47a3050a0429..56909a52e30f 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -452,15 +452,15 @@ Fired when a redirect was received while requesting a resource. Fired when document in the given frame is loaded. -### Event: 'page-title-set' +### Event: 'page-title-updated' Returns: * `title` String * `explicitSet` Boolean -Fired when page title is set during navigation. `explicitSet` is false when title is synthesised from file -url. +Fired when page title is set during navigation. `explicitSet` is false when +title is synthesised from file url. ### Event: 'page-favicon-updated' From a99c193cf2d783308a0777e6c6ee606590bfa263 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Tue, 1 Dec 2015 11:57:32 -0400 Subject: [PATCH 672/738] :checkered_flag: Preserve file extension when extracting from asar Currently, when calling `copyFileOut`, the original extension from the file is lost, and a generic `*.tmp` is added instead. This becomes problematic in the scenario where we use `child_process.execFile` on a Windows Batch script that lives inside the `asar` package. Windows relies on the extension being present in order to interpret the script accordingly, which results in the following bug because the operating system doesn't know what do to with this `*.tmp` file: ``` Error: spawn UNKNOWN ``` Steps to reproduce: 1. Create a dummy batch script (test.bat): ``` @echo off echo "Hello world" ``` 2. Create an electron app that attemps to call this script with `child_process.execFile`: ```js var child_process = require('child_process'); var path = require('path'); child_process.execFile(path.join(__dirname, 'test.bat'), function(error, stdout) { if (error) throw error; console.log(stdout); }); ``` 3. Package this small application as an asar archive: ```sh > asar pack mytestapp app.asar ``` 4. Execute the application: ```sh > electron.exe app.asar ``` --- atom/common/asar/archive.cc | 3 ++- atom/common/asar/scoped_temporary_file.cc | 14 +++++++++++--- atom/common/asar/scoped_temporary_file.h | 8 +++++--- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/atom/common/asar/archive.cc b/atom/common/asar/archive.cc index ab93e301b1ab..ebb80cc2c485 100644 --- a/atom/common/asar/archive.cc +++ b/atom/common/asar/archive.cc @@ -272,7 +272,8 @@ bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) { } scoped_ptr temp_file(new ScopedTemporaryFile); - if (!temp_file->InitFromFile(&file_, info.offset, info.size)) + base::FilePath::StringType ext = path.Extension(); + if (!temp_file->InitFromFile(&file_, ext, info.offset, info.size)) return false; #if defined(OS_POSIX) diff --git a/atom/common/asar/scoped_temporary_file.cc b/atom/common/asar/scoped_temporary_file.cc index 6fccc9434fdb..2cc51991e185 100644 --- a/atom/common/asar/scoped_temporary_file.cc +++ b/atom/common/asar/scoped_temporary_file.cc @@ -28,20 +28,28 @@ ScopedTemporaryFile::~ScopedTemporaryFile() { } } -bool ScopedTemporaryFile::Init() { +bool ScopedTemporaryFile::Init(const base::FilePath::StringType ext) { if (!path_.empty()) return true; base::ThreadRestrictions::ScopedAllowIO allow_io; - return base::CreateTemporaryFile(&path_); + + base::FilePath temporaryPath_; + if (!base::CreateTemporaryFile(&temporaryPath_)) { + return false; + } + + path_ = temporaryPath_.AddExtension(ext); + return base::Move(temporaryPath_, path_); } bool ScopedTemporaryFile::InitFromFile(base::File* src, + const base::FilePath::StringType ext, uint64 offset, uint64 size) { if (!src->IsValid()) return false; - if (!Init()) + if (!Init(ext)) return false; std::vector buf(size); diff --git a/atom/common/asar/scoped_temporary_file.h b/atom/common/asar/scoped_temporary_file.h index ffaee22e514e..c0804a4e6e5f 100644 --- a/atom/common/asar/scoped_temporary_file.h +++ b/atom/common/asar/scoped_temporary_file.h @@ -22,11 +22,13 @@ class ScopedTemporaryFile { ScopedTemporaryFile(); virtual ~ScopedTemporaryFile(); - // Init an empty temporary file. - bool Init(); + // Init an empty temporary file with a certain extension. + bool Init(const base::FilePath::StringType ext); // Init an temporary file and fill it with content of |path|. - bool InitFromFile(base::File* src, uint64 offset, uint64 size); + bool InitFromFile(base::File* src, + const base::FilePath::StringType ext, + uint64 offset, uint64 size); base::FilePath path() const { return path_; } From 1b1c4bec4e4634087bb17fb96a8e60098329dabc Mon Sep 17 00:00:00 2001 From: Artur de Oliveira Tsuda Date: Tue, 1 Dec 2015 21:09:20 -0200 Subject: [PATCH 673/738] :memo: [ci skip] Add translation to auto-updater, change links --- docs-translations/pt-BR/README.md | 4 +- docs-translations/pt-BR/api/auto-updater.md | 85 +++++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 docs-translations/pt-BR/api/auto-updater.md diff --git a/docs-translations/pt-BR/README.md b/docs-translations/pt-BR/README.md index 61202f8ca471..f458e51da8f3 100644 --- a/docs-translations/pt-BR/README.md +++ b/docs-translations/pt-BR/README.md @@ -40,8 +40,8 @@ selecione a *tag* que corresponde à sua versão. ### Módulos para o Processo Principal: -* [app](../../docs/api/app.md) -* [autoUpdater](../../docs/api/auto-updater.md) +* [app](api/app.md) +* [autoUpdater](api/auto-updater.md) * [BrowserWindow](../../docs/api/browser-window.md) * [contentTracing](../../docs/api/content-tracing.md) * [dialog](../../docs/api/dialog.md) diff --git a/docs-translations/pt-BR/api/auto-updater.md b/docs-translations/pt-BR/api/auto-updater.md new file mode 100644 index 000000000000..1c27a4b77991 --- /dev/null +++ b/docs-translations/pt-BR/api/auto-updater.md @@ -0,0 +1,85 @@ +# autoUpdater + +Este módulo oferece uma interface para o framework de atualização automática `Squirrel`. + +## Notificações de Plataforma + +Embora o `autoUpdater` ofereça uma API uniforme para diferentes plataformas, existem diferenças sutis em cada plataforma. + +### OS X + +No OS X, o módulo `autoUpdater` é construído sobre o [Squirrel.Mac][squirrel-mac], o que significa que você não precisa de nenhuma configuração especial para fazê-lo funcionar. Para requerimentos de servidor, você pode ler [Server Support][server-support]. + +### Windows + +No Windows, você deve instalar seu aplicativo na máquina de um usuário antes que possa usar o auto-updater, então é recomendado utilizar o módulo [grunt-electron-installer][installer] para gerar um instalador do Windows. + +O instalador gerado com Squirrel irá criar um ícone de atalho com um [Application User Model ID][app-user-model-id] no formato `com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`, por exemplo: `com.squirrel.slack.Slack` e `com.squirrel.code.Code`. Você precisa usar o mesmo ID para seu aplicativo a API `app.setAppUserModelId`, senão o Windows não conseguirá fixar seu aplicativo corretamente na barra de tarefas. + +A configuração do servidor também é diferente do OS X. Você pode ler a documentação do [Squirrel.Windows][squirrel-windows] para mais detalhes. + +### Linux + +Não há suporte nativo do auto-updater para Linux, então é recomendado utilizar o gerenciador de pacotes da distribuição para atualizar seu aplicativo. + +## Eventos + +O objeto `autoUpdater` emite os seguintes eventos: + +### Evento: 'error' + +Retorna: + +* `error` Error + +Emitido quando há um erro durante a atualização. + +### Evento: 'checking-for-update' + +Emitido quando está verificando se uma atualização foi inicializada. + +### Evento: 'update-available' + +Emitido quando há uma atualização disponível. A autalização é baixada automaticamente. + +### Evento: 'update-not-available' + +Emitido quando não há uma atualização disponível. + +### Evento: 'update-downloaded' + +Retorna: + +* `event` Event +* `releaseNotes` String +* `releaseName` String +* `releaseDate` Date +* `updateURL` String + +Emitido quando uma atualização foi baixada. + +No Windows apenas `releaseName` está disponível. + +## Métodos + +O objeto `autoUpdater` possui os seguintes métodos: + +### `autoUpdater.setFeedURL(url)` + +* `url` String + +Define a `url` e inicializa o auto-updater. A `url` não pode ser alterada uma vez que foi definida. + +### `autoUpdater.checkForUpdates()` + +Pergunta ao servidor se há uma atualização. Você deve chamar `setFeedURL` antes de usar esta API. + +### `autoUpdater.quitAndInstall()` + +Reinicia o aplicativo e instala a atualização após esta ter sido baixada. Só deve ser chamado após o `update-downloaded` ter sido emitido. + +[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 229dc02a41b06f47285746f6de3350795d36e8f3 Mon Sep 17 00:00:00 2001 From: Artur de Oliveira Tsuda Date: Tue, 1 Dec 2015 21:34:35 -0200 Subject: [PATCH 674/738] :memo: [ci skip] Update to match english docs, fix typos --- docs-translations/pt-BR/api/process.md | 40 +++++++++++++++++++++----- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/docs-translations/pt-BR/api/process.md b/docs-translations/pt-BR/api/process.md index 3da0dc58391b..1c20e2df1187 100644 --- a/docs-translations/pt-BR/api/process.md +++ b/docs-translations/pt-BR/api/process.md @@ -1,22 +1,48 @@ # process -O objeto `process` no Electron tem as seguintes diferenças de um upstream node: +O objeto `process` no Electron tem as seguintes diferenças do objeto no upstream node: -* `process.type` String - Tipo de processo, pode ser `browser` (i.e. main process) +* `process.type` String - Tipo de processo, pode ser `browser` (processo principal) ou `renderer`. * `process.versions['electron']` String - Versão do Electron. * `process.versions['chrome']` String - Versão do Chromium. -* `process.resourcesPath` String - Caminho para os códigos fontes JavaScript. +* `process.resourcesPath` String - Caminho para o código fonte JavaScript. +* `process.mas` Boolean - Para build da Mac App Store, este valor é `true`, para outros builds é `undefined`. + +## Eventos + +### Evento: 'loaded' + +Emitido quando o Electron carregou seu script de inicialização interno e está começando a carregar a página web ou o script principal. + +Pode ser utilizado pelo script pré-carregamento (preload.js abaixo) para adicionar símbolos globais do Node removidos para o escopo global quando a integração do node é desligada: + +```js +// preload.js +var _setImmediate = setImmediate; +var _clearImmediate = clearImmediate; +process.once('loaded', function() { + global.setImmediate = _setImmediate; + global.clearImmediate = _clearImmediate; +}); +``` + +## Propriedades + +### `process.noAsar` + +Definir isto para `true` pode desabilitar o suporte para arquivos `asar` nos módulos nativos do Node. # Métodos -O objeto `process` tem os seguintes método: + +O objeto `process` tem os seguintes métodos: ### `process.hang` -Afeta a thread principal do processo atual. +Faz com que o *thread* principal do processo congele. -## process.setFdLimit(MaxDescritores) _OS X_ _Linux_ +### `process.setFdLimit(maxDescriptors)` _OS X_ _Linux_ * `maxDescriptors` Integer Define o limite do arquivo descritor para `maxDescriptors` ou para o limite do OS, -o que for menor para o processo atual. \ No newline at end of file +o que for menor para o processo atual. From d76e21853b6a35552dec7d933dbf8e9aa4cfebeb Mon Sep 17 00:00:00 2001 From: Artur de Oliveira Tsuda Date: Tue, 1 Dec 2015 21:38:25 -0200 Subject: [PATCH 675/738] Change header --- docs-translations/pt-BR/api/auto-updater.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/pt-BR/api/auto-updater.md b/docs-translations/pt-BR/api/auto-updater.md index 1c27a4b77991..27c3ef3c0740 100644 --- a/docs-translations/pt-BR/api/auto-updater.md +++ b/docs-translations/pt-BR/api/auto-updater.md @@ -2,7 +2,7 @@ Este módulo oferece uma interface para o framework de atualização automática `Squirrel`. -## Notificações de Plataforma +## Avisos sobre Plataformas Embora o `autoUpdater` ofereça uma API uniforme para diferentes plataformas, existem diferenças sutis em cada plataforma. From 9a93ecc3cfe74f6d953751dfc75059fcb81b9feb Mon Sep 17 00:00:00 2001 From: Artur de Oliveira Tsuda Date: Tue, 1 Dec 2015 21:46:13 -0200 Subject: [PATCH 676/738] :memo: [ci skip] fix typos --- docs-translations/pt-BR/api/accelerator.md | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs-translations/pt-BR/api/accelerator.md b/docs-translations/pt-BR/api/accelerator.md index 87987258b11c..92d70c844e83 100644 --- a/docs-translations/pt-BR/api/accelerator.md +++ b/docs-translations/pt-BR/api/accelerator.md @@ -1,7 +1,7 @@ # Acelerador (teclas de atalhos) -Um acelerador é uma string que representa um atalho de tecla. Isso pode conter -multiplos modificadores e códigos chaves, combinado pelo caracter `+`. +Um acelerador é uma string que representa um atalho de tecla. Ele pode conter +múltiplos modificadores e códigos chaves, combinados pelo caractere `+`. Exemplos: @@ -11,13 +11,13 @@ Exemplos: ## Aviso sobre plataformas No Linux e no Windows a tecla `Command` não tem nenhum efeito, -então use `CommandOrControl` que representa a tecla `Command` existente no OSX e +então use `CommandOrControl` que representa a tecla `Command` existente no OS X e `Control` no Linux e no Windows para definir aceleradores (atalhos). A chave `Super` está mapeada para a tecla `Windows` para Windows e Linux, -e para a tecla `Cmd` para OSX. +e para a tecla `Cmd` para OS X. -## Modificadores disponiveis +## Modificadores disponíveis * `Command` (ou `Cmd` abreviado) * `Control` (ou `Ctrl` abreviado) @@ -26,21 +26,21 @@ e para a tecla `Cmd` para OSX. * `Shift` * `Super` -## Códigos chaves disponiveis +## Códigos chaves disponíveis -* `0` to `9` -* `A` to `Z` -* `F1` to `F24` -* Punctuations like `~`, `!`, `@`, `#`, `$`, etc. +* `0` até `9` +* `A` até `Z` +* `F1` até `F24` +* Pontuações como `~`, `!`, `@`, `#`, `$`, etc. * `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` \ No newline at end of file +* `Return` (ou `Enter` como pseudônimo) +* `Up`, `Down`, `Left` e `Right` +* `Home` e `End` +* `PageUp` e `PageDown` +* `Escape` (ou `Esc` abreviado) +* `VolumeUp`, `VolumeDown` e `VolumeMute` +* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` e `MediaPlayPause` From 5cae8397ccaf6116be4606dc81da498fa529bc9d Mon Sep 17 00:00:00 2001 From: Artur de Oliveira Tsuda Date: Tue, 1 Dec 2015 21:57:07 -0200 Subject: [PATCH 677/738] :memo: [ci skip] fix more typos --- docs-translations/pt-BR/api/shell.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs-translations/pt-BR/api/shell.md b/docs-translations/pt-BR/api/shell.md index 7c3f24ade509..65e0a2d42636 100644 --- a/docs-translations/pt-BR/api/shell.md +++ b/docs-translations/pt-BR/api/shell.md @@ -1,11 +1,11 @@ # shell -O módulo `shell` fornece funções relacionadas intereções com o OS do usuário. +O módulo `shell` fornece funções relacionadas à integração com o desktop. Um exemplo para abrir uma URL no browser padrão do usuário: ```javascript -var shell = require('shell'); +const shell = require('shell'); shell.openExternal('https://github.com'); ``` @@ -17,26 +17,26 @@ O módulo `shell` tem os seguintes métodos: * `fullPath` String -Exibe o arquivo no gerenciador de arquivos padrão do sistema. Se possivel, seleciona o arquivo automaticamente. +Exibe o arquivo num gerenciador de arquivos. Se possivel, seleciona o arquivo. ### `shell.openItem(fullPath)` * `fullPath` String -Abre o arquivo em seu programa padrão. +Abre o arquivo de maneira padrão do desktop. ### `shell.openExternal(url)` * `url` String -Abre o arquivo seguido de um protocol em seu programa padrão. (Por -exemplo, mailto:foo@bar.com.) +Abre a URL de protocolo externo de maneira padrão do desktop. (Por +exemplo, mailto: URLs no programa de email padrão do usuário) ### `shell.moveItemToTrash(fullPath)` * `fullPath` String -Move o arquivo para a lixeira e retorna um boolean com o resultado da operação. +Move o arquivo para a lixeira e retorna um status boolean com o resultado da operação. ### `shell.beep()` From c691094aa103ee7d036ba524623edd280371dc72 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 2 Dec 2015 11:00:28 +0800 Subject: [PATCH 678/738] spec: Fix failing tests on win32 --- spec/asar-spec.coffee | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/spec/asar-spec.coffee b/spec/asar-spec.coffee index b7a62f8eeaa2..495d89734e5f 100644 --- a/spec/asar-spec.coffee +++ b/spec/asar-spec.coffee @@ -424,6 +424,8 @@ describe 'asar package', -> assert.equal internalModuleReadFile(p).toString().trim(), 'a' describe 'process.noAsar', -> + errorName = if process.platform is 'win32' then 'ENOENT' else 'ENOTDIR' + beforeEach -> process.noAsar = true afterEach -> @@ -432,22 +434,22 @@ describe 'asar package', -> it 'disables asar support in sync API', -> file = path.join fixtures, 'asar', 'a.asar', 'file1' dir = path.join fixtures, 'asar', 'a.asar', 'dir1' - assert.throws (-> fs.readFileSync file), /ENOTDIR/ - assert.throws (-> fs.lstatSync file), /ENOTDIR/ - assert.throws (-> fs.realpathSync file), /ENOTDIR/ - assert.throws (-> fs.readdirSync dir), /ENOTDIR/ + assert.throws (-> fs.readFileSync file), new RegExp(errorName) + assert.throws (-> fs.lstatSync file), new RegExp(errorName) + assert.throws (-> fs.realpathSync file), new RegExp(errorName) + assert.throws (-> fs.readdirSync dir), new RegExp(errorName) it 'disables asar support in async API', (done) -> file = path.join fixtures, 'asar', 'a.asar', 'file1' dir = path.join fixtures, 'asar', 'a.asar', 'dir1' fs.readFile file, (error) -> - assert.equal error.code, 'ENOTDIR' + assert.equal error.code, errorName fs.lstat file, (error) -> - assert.equal error.code, 'ENOTDIR' + assert.equal error.code, errorName fs.realpath file, (error) -> - assert.equal error.code, 'ENOTDIR' + assert.equal error.code, errorName fs.readdir dir, (error) -> - assert.equal error.code, 'ENOTDIR' + assert.equal error.code, errorName done() it 'treats *.asar as normal file', -> From c3645e3f9532f71fea15dd5c6dad603954978afe Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 2 Dec 2015 11:04:47 +0800 Subject: [PATCH 679/738] Don't call Move if there is no need to move --- atom/common/asar/scoped_temporary_file.cc | 17 ++++++++++------- atom/common/asar/scoped_temporary_file.h | 4 ++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/atom/common/asar/scoped_temporary_file.cc b/atom/common/asar/scoped_temporary_file.cc index 2cc51991e185..14f2ba8ef9dd 100644 --- a/atom/common/asar/scoped_temporary_file.cc +++ b/atom/common/asar/scoped_temporary_file.cc @@ -28,23 +28,26 @@ ScopedTemporaryFile::~ScopedTemporaryFile() { } } -bool ScopedTemporaryFile::Init(const base::FilePath::StringType ext) { +bool ScopedTemporaryFile::Init(const base::FilePath::StringType& ext) { if (!path_.empty()) return true; base::ThreadRestrictions::ScopedAllowIO allow_io; - base::FilePath temporaryPath_; - if (!base::CreateTemporaryFile(&temporaryPath_)) { + base::FilePath temp_path; + if (!base::CreateTemporaryFile(&temp_path)) return false; - } - path_ = temporaryPath_.AddExtension(ext); - return base::Move(temporaryPath_, path_); + if (ext.empty()) + return true; + + // Keep the original extension. + path_ = temp_path.AddExtension(ext); + return base::Move(temp_path, path_); } bool ScopedTemporaryFile::InitFromFile(base::File* src, - const base::FilePath::StringType ext, + const base::FilePath::StringType& ext, uint64 offset, uint64 size) { if (!src->IsValid()) return false; diff --git a/atom/common/asar/scoped_temporary_file.h b/atom/common/asar/scoped_temporary_file.h index c0804a4e6e5f..23660a239011 100644 --- a/atom/common/asar/scoped_temporary_file.h +++ b/atom/common/asar/scoped_temporary_file.h @@ -23,11 +23,11 @@ class ScopedTemporaryFile { virtual ~ScopedTemporaryFile(); // Init an empty temporary file with a certain extension. - bool Init(const base::FilePath::StringType ext); + bool Init(const base::FilePath::StringType& ext); // Init an temporary file and fill it with content of |path|. bool InitFromFile(base::File* src, - const base::FilePath::StringType ext, + const base::FilePath::StringType& ext, uint64 offset, uint64 size); base::FilePath path() const { return path_; } From c493bec0898b2cdc3ae20b2d41b19cdf3041f599 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 2 Dec 2015 11:36:29 +0800 Subject: [PATCH 680/738] Make sure temp file will be cleaned up when base::Move fails --- atom/common/asar/scoped_temporary_file.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/atom/common/asar/scoped_temporary_file.cc b/atom/common/asar/scoped_temporary_file.cc index 14f2ba8ef9dd..6dd12782d8ee 100644 --- a/atom/common/asar/scoped_temporary_file.cc +++ b/atom/common/asar/scoped_temporary_file.cc @@ -33,17 +33,20 @@ bool ScopedTemporaryFile::Init(const base::FilePath::StringType& ext) { return true; base::ThreadRestrictions::ScopedAllowIO allow_io; - - base::FilePath temp_path; - if (!base::CreateTemporaryFile(&temp_path)) + if (!base::CreateTemporaryFile(&path_)) return false; - if (ext.empty()) - return true; - +#if defined(OS_WIN) // Keep the original extension. - path_ = temp_path.AddExtension(ext); - return base::Move(temp_path, path_); + if (!ext.empty()) { + base::FilePath new_path = path_.AddExtension(ext); + if (!base::Move(path_, new_path)) + return false; + path_ = new_path; + } +#endif + + return true; } bool ScopedTemporaryFile::InitFromFile(base::File* src, From 202475f5a98cf4530845b80c87cd6c218059dc82 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 2 Dec 2015 17:29:58 +0800 Subject: [PATCH 681/738] Deprecating a property with method of same name causes trouble Close #3511. --- atom/browser/api/lib/app.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 4d1803a0296f..d0ec41c4d23c 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -65,7 +65,6 @@ wrapDownloadItem = (downloadItem) -> deprecate.property downloadItem, 'url', 'getURL' deprecate.property downloadItem, 'filename', 'getFilename' deprecate.property downloadItem, 'mimeType', 'getMimeType' - deprecate.property downloadItem, 'hasUserGesture', 'hasUserGesture' deprecate.rename downloadItem, 'getUrl', 'getURL' downloadItemBindings._setWrapDownloadItem wrapDownloadItem From 95675996989e9675acd06d3fcc4fa30b615eadfc Mon Sep 17 00:00:00 2001 From: Luke Page Date: Wed, 2 Dec 2015 10:23:21 +0000 Subject: [PATCH 682/738] Update debugging-main-process.md --- docs/tutorial/debugging-main-process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/debugging-main-process.md b/docs/tutorial/debugging-main-process.md index 38c6e61ffcde..aa95ae312b9a 100644 --- a/docs/tutorial/debugging-main-process.md +++ b/docs/tutorial/debugging-main-process.md @@ -19,7 +19,7 @@ Like `--debug` but pauses the script on the first line. ## Use node-inspector for Debugging -__Note:__ Electron uses node v0.11.13, which currently doesn't work very well +__Note:__ Electron doesn't currently work very well with node-inspector, and the main process will crash if you inspect the `process` object under node-inspector's console. From 2fba05b5e70e5d71f89c350dd42d096bb0f71016 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 2 Dec 2015 18:43:11 +0800 Subject: [PATCH 683/738] Add `menu` parameter for Tray.popUpContextMenu --- atom/browser/api/atom_api_tray.cc | 4 +++- atom/browser/ui/tray_icon.cc | 3 ++- atom/browser/ui/tray_icon.h | 4 +++- atom/browser/ui/tray_icon_cocoa.h | 3 ++- atom/browser/ui/tray_icon_cocoa.mm | 3 ++- atom/browser/ui/win/notify_icon.cc | 5 +++-- atom/browser/ui/win/notify_icon.h | 3 ++- docs/api/tray.md | 8 ++++++-- 8 files changed, 23 insertions(+), 10 deletions(-) diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index 5e32657f008a..1e1c7c304d82 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -137,9 +137,11 @@ void Tray::DisplayBalloon(mate::Arguments* args, } void Tray::PopUpContextMenu(mate::Arguments* args) { + Menu* menu = nullptr; + args->GetNext(&menu); gfx::Point pos; args->GetNext(&pos); - tray_icon_->PopUpContextMenu(pos); + tray_icon_->PopUpContextMenu(pos, menu ? menu->model() : nullptr); } void Tray::SetContextMenu(mate::Arguments* args, Menu* menu) { diff --git a/atom/browser/ui/tray_icon.cc b/atom/browser/ui/tray_icon.cc index 1696aab276b1..60923c2ad0a6 100644 --- a/atom/browser/ui/tray_icon.cc +++ b/atom/browser/ui/tray_icon.cc @@ -26,7 +26,8 @@ void TrayIcon::DisplayBalloon(const gfx::Image& icon, const base::string16& contents) { } -void TrayIcon::PopUpContextMenu(const gfx::Point& pos) { +void TrayIcon::PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model) { } void TrayIcon::NotifyClicked(const gfx::Rect& bounds, int modifiers) { diff --git a/atom/browser/ui/tray_icon.h b/atom/browser/ui/tray_icon.h index bc29acd8a255..c80ff08d6a52 100644 --- a/atom/browser/ui/tray_icon.h +++ b/atom/browser/ui/tray_icon.h @@ -47,7 +47,9 @@ class TrayIcon { const base::string16& title, const base::string16& contents); - virtual void PopUpContextMenu(const gfx::Point& pos); + // Popups the menu. + virtual void PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model); // Set the context menu for this icon. virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) = 0; diff --git a/atom/browser/ui/tray_icon_cocoa.h b/atom/browser/ui/tray_icon_cocoa.h index 7781c93a1c03..59e2241aa480 100644 --- a/atom/browser/ui/tray_icon_cocoa.h +++ b/atom/browser/ui/tray_icon_cocoa.h @@ -29,7 +29,8 @@ class TrayIconCocoa : public TrayIcon, void SetToolTip(const std::string& tool_tip) override; void SetTitle(const std::string& title) override; void SetHighlightMode(bool highlight) override; - void PopUpContextMenu(const gfx::Point& pos) override; + void PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model) override; void SetContextMenu(ui::SimpleMenuModel* menu_model) override; protected: diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index e25f8ab5c201..5005234ab131 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -338,7 +338,8 @@ void TrayIconCocoa::SetHighlightMode(bool highlight) { [status_item_view_ setHighlight:highlight]; } -void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos) { +void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model) { [status_item_view_ popUpContextMenu]; } diff --git a/atom/browser/ui/win/notify_icon.cc b/atom/browser/ui/win/notify_icon.cc index b2ca4bceedd1..133ab068da7b 100644 --- a/atom/browser/ui/win/notify_icon.cc +++ b/atom/browser/ui/win/notify_icon.cc @@ -66,7 +66,7 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos, return; } else if (!double_button_click) { // single right click if (menu_model_) - PopUpContextMenu(cursor_pos); + PopUpContextMenu(cursor_pos, menu_model_); else NotifyRightClicked(gfx::Rect(rect), modifiers); } @@ -142,7 +142,8 @@ void NotifyIcon::DisplayBalloon(const gfx::Image& icon, LOG(WARNING) << "Unable to create status tray balloon."; } -void NotifyIcon::PopUpContextMenu(const gfx::Point& pos) { +void NotifyIcon::PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model) { // Returns if context menu isn't set. if (!menu_model_) return; diff --git a/atom/browser/ui/win/notify_icon.h b/atom/browser/ui/win/notify_icon.h index d368dec71327..8ee600033e94 100644 --- a/atom/browser/ui/win/notify_icon.h +++ b/atom/browser/ui/win/notify_icon.h @@ -52,7 +52,8 @@ class NotifyIcon : public TrayIcon { void DisplayBalloon(const gfx::Image& icon, const base::string16& title, const base::string16& contents) override; - void PopUpContextMenu(const gfx::Point& pos) override; + void PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model) override; void SetContextMenu(ui::SimpleMenuModel* menu_model) override; private: diff --git a/docs/api/tray.md b/docs/api/tray.md index f230c324ec08..08a43638be14 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -187,12 +187,16 @@ when the tray icon is clicked. Defaults to true. Displays a tray balloon. -### `Tray.popUpContextMenu([position])` _OS X_ _Windows_ +### `Tray.popUpContextMenu([menu, position])` _OS X_ _Windows_ -* `position` Object (optional)- The pop up position. +* `menu` Menu (optional) +* `position` Object (optional) - The pop up position. * `x` Integer * `y` Integer +Popups the context menu of tray icon. When `menu` is passed, the `menu` will +showed instead of the tray's context menu. + The `position` is only available on Windows, and it is (0, 0) by default. ### `Tray.setContextMenu(menu)` From 3cdd0f35c7d501572164a13051c2bb7ea6ac808f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 2 Dec 2015 19:05:22 +0800 Subject: [PATCH 684/738] mac: Implement menu parameter --- atom/browser/api/atom_api_tray.cc | 4 ++-- atom/browser/ui/tray_icon_cocoa.mm | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index 1e1c7c304d82..3b1a3a6321bb 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -137,11 +137,11 @@ void Tray::DisplayBalloon(mate::Arguments* args, } void Tray::PopUpContextMenu(mate::Arguments* args) { - Menu* menu = nullptr; + mate::Handle menu; args->GetNext(&menu); gfx::Point pos; args->GetNext(&pos); - tray_icon_->PopUpContextMenu(pos, menu ? menu->model() : nullptr); + tray_icon_->PopUpContextMenu(pos, menu.IsEmpty() ? nullptr : menu->model()); } void Tray::SetContextMenu(mate::Arguments* args, Menu* menu) { diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index 5005234ab131..997ac6fd3134 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -23,6 +23,7 @@ const CGFloat kVerticalTitleMargin = 2; atom::TrayIconCocoa* trayIcon_; // weak AtomMenuController* menuController_; // weak BOOL isHighlightEnable_; + BOOL forceHighlight_; BOOL inMouseEventSequence_; base::scoped_nsobject image_; base::scoped_nsobject alternateImage_; @@ -39,6 +40,8 @@ const CGFloat kVerticalTitleMargin = 2; image_.reset([image copy]); trayIcon_ = icon; isHighlightEnable_ = YES; + forceHighlight_ = NO; + inMouseEventSequence_ = NO; if ((self = [super initWithFrame: CGRectZero])) { // Setup the image view. @@ -238,7 +241,19 @@ const CGFloat kVerticalTitleMargin = 2; [self setNeedsDisplay:YES]; } -- (void)popUpContextMenu { +- (void)popUpContextMenu:(ui::SimpleMenuModel*)menu_model { + // Show a custom menu. + if (menu_model) { + base::scoped_nsobject menuController( + [[AtomMenuController alloc] initWithModel:menu_model]); + forceHighlight_ = YES; // Should highlight when showing menu. + [self setNeedsDisplay:YES]; + [statusItem_ popUpStatusItemMenu:[menuController menu]]; + forceHighlight_ = NO; + [self setNeedsDisplay:YES]; + return; + } + if (menuController_ && ![menuController_ isMenuOpen]) { // Redraw the dray icon to show highlight if it is enabled. [self setNeedsDisplay:YES]; @@ -288,6 +303,8 @@ const CGFloat kVerticalTitleMargin = 2; } - (BOOL)shouldHighlight { + if (isHighlightEnable_ && forceHighlight_) + return true; BOOL isMenuOpen = menuController_ && [menuController_ isMenuOpen]; return isHighlightEnable_ && (inMouseEventSequence_ || isMenuOpen); } @@ -340,7 +357,7 @@ void TrayIconCocoa::SetHighlightMode(bool highlight) { void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos, ui::SimpleMenuModel* menu_model) { - [status_item_view_ popUpContextMenu]; + [status_item_view_ popUpContextMenu:menu_model]; } void TrayIconCocoa::SetContextMenu(ui::SimpleMenuModel* menu_model) { From 615ce45849db3d0c2db785d3dce8e2450d9e197c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 2 Dec 2015 19:58:10 +0800 Subject: [PATCH 685/738] win: Implement menu parameter --- atom/browser/ui/win/notify_icon.cc | 21 +++++++++++---------- atom/browser/ui/win/notify_icon.h | 3 +-- atom/browser/ui/win/notify_icon_host.cc | 4 ---- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/atom/browser/ui/win/notify_icon.cc b/atom/browser/ui/win/notify_icon.cc index 133ab068da7b..1ac29f1360cb 100644 --- a/atom/browser/ui/win/notify_icon.cc +++ b/atom/browser/ui/win/notify_icon.cc @@ -13,6 +13,7 @@ #include "ui/gfx/image/image.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/screen.h" #include "ui/views/controls/menu/menu_runner.h" namespace atom { @@ -45,8 +46,7 @@ NotifyIcon::~NotifyIcon() { Shell_NotifyIcon(NIM_DELETE, &icon_data); } -void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos, - int modifiers, +void NotifyIcon::HandleClickEvent(int modifiers, bool left_mouse_click, bool double_button_click) { NOTIFYICONIDENTIFIER icon_id; @@ -66,7 +66,7 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos, return; } else if (!double_button_click) { // single right click if (menu_model_) - PopUpContextMenu(cursor_pos, menu_model_); + PopUpContextMenu(gfx::Point(), menu_model_); else NotifyRightClicked(gfx::Rect(rect), modifiers); } @@ -145,22 +145,23 @@ void NotifyIcon::DisplayBalloon(const gfx::Image& icon, void NotifyIcon::PopUpContextMenu(const gfx::Point& pos, ui::SimpleMenuModel* menu_model) { // Returns if context menu isn't set. - if (!menu_model_) + if (!menu_model) return; // Set our window as the foreground window, so the context menu closes when // we click away from it. if (!SetForegroundWindow(window_)) return; + // Show menu at mouse's position by default. + gfx::Rect rect(pos, gfx::Size()); + if (pos.IsOrigin()) + rect.set_origin(gfx::Screen::GetNativeScreen()->GetCursorScreenPoint()); + views::MenuRunner menu_runner( - menu_model_, + menu_model, views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS); ignore_result(menu_runner.RunMenuAt( - NULL, - NULL, - gfx::Rect(pos, gfx::Size()), - views::MENU_ANCHOR_TOPLEFT, - ui::MENU_SOURCE_MOUSE)); + NULL, NULL, rect, views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_MOUSE)); } void NotifyIcon::SetContextMenu(ui::SimpleMenuModel* menu_model) { diff --git a/atom/browser/ui/win/notify_icon.h b/atom/browser/ui/win/notify_icon.h index 8ee600033e94..23608c7c7ab6 100644 --- a/atom/browser/ui/win/notify_icon.h +++ b/atom/browser/ui/win/notify_icon.h @@ -33,8 +33,7 @@ class NotifyIcon : public TrayIcon { // Handles a click event from the user - if |left_button_click| is true and // there is a registered observer, passes the click event to the observer, // otherwise displays the context menu if there is one. - void HandleClickEvent(const gfx::Point& cursor_pos, - int modifiers, + void HandleClickEvent(int modifiers, bool left_button_click, bool double_button_click); diff --git a/atom/browser/ui/win/notify_icon_host.cc b/atom/browser/ui/win/notify_icon_host.cc index 2c84837e714d..a0d4287ff614 100644 --- a/atom/browser/ui/win/notify_icon_host.cc +++ b/atom/browser/ui/win/notify_icon_host.cc @@ -15,7 +15,6 @@ #include "base/win/win_util.h" #include "base/win/wrapped_window_proc.h" #include "ui/events/event_constants.h" -#include "ui/gfx/screen.h" #include "ui/gfx/win/hwnd_util.h" namespace atom { @@ -172,10 +171,7 @@ LRESULT CALLBACK NotifyIconHost::WndProc(HWND hwnd, case WM_CONTEXTMENU: // Walk our icons, find which one was clicked on, and invoke its // HandleClickEvent() method. - gfx::Point cursor_pos( - gfx::Screen::GetNativeScreen()->GetCursorScreenPoint()); win_icon->HandleClickEvent( - cursor_pos, GetKeyboardModifers(), (lparam == WM_LBUTTONDOWN || lparam == WM_LBUTTONDBLCLK), (lparam == WM_LBUTTONDBLCLK || lparam == WM_RBUTTONDBLCLK)); From 75c28ff993c24f5a463a918259259fb007311eed Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 3 Dec 2015 00:21:34 +0900 Subject: [PATCH 686/738] Update as upstream --- docs-translations/ko-KR/api/process.md | 7 +++++++ docs-translations/ko-KR/api/tray.md | 8 ++++++-- docs-translations/ko-KR/api/web-view-tag.md | 4 ++-- docs-translations/ko-KR/tutorial/application-packaging.md | 8 ++++++++ .../ko-KR/tutorial/debugging-main-process.md | 6 +++--- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/docs-translations/ko-KR/api/process.md b/docs-translations/ko-KR/api/process.md index afbc6afd796d..de24b5ac174e 100644 --- a/docs-translations/ko-KR/api/process.md +++ b/docs-translations/ko-KR/api/process.md @@ -30,6 +30,13 @@ process.once('loaded', function() { }); ``` +## Properties + +### `process.noAsar` + +이 속성을 `true`로 지정하면 Node 빌트인 모듈의 `asar` 아카이브 지원을 비활성화 시킬 +수 있습니다. + ## Methods `process` 객체는 다음과 같은 메서드를 가지고 있습니다: diff --git a/docs-translations/ko-KR/api/tray.md b/docs-translations/ko-KR/api/tray.md index 97db97f42607..e182f6471e7a 100644 --- a/docs-translations/ko-KR/api/tray.md +++ b/docs-translations/ko-KR/api/tray.md @@ -184,12 +184,16 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다. 트레이에 풍선 팝업을 생성합니다. -### `Tray.popContextMenu([position])` _OS X_ _Windows_ +### `Tray.popUpContextMenu([menu, position])` _OS X_ _Windows_ -* `position` Object (optional) - 팝업 메뉴 위치 +* `menu` Menu (optional) +* `position` Object (optional) - 팝업 메뉴의 위치 * `x` Integer * `y` Integer +트레이 아이콘의 컨텍스트 메뉴를 팝업시킵니다. `menu`가 전달되면, `menu`가 트레이 +메뉴의 컨텍스트 메뉴 대신 표시됩니다. + `position`은 Windows에서만 사용할 수 있으며 기본값은 (0, 0)입니다. ### `Tray.setContextMenu(menu)` diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index 4ef7f47c853f..531b19adcedd 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -441,7 +441,7 @@ Returns: 프레임 문서의 로드가 끝나면 발생하는 이벤트입니다. -### Event: 'page-title-set' +### Event: 'page-title-updated' Returns: @@ -449,7 +449,7 @@ Returns: * `explicitSet` Boolean 탐색하는 동안에 페이지의 제목이 설정되면 발생하는 이벤트입니다. `explicitSet`는 파일 -URL에서 종합(synthesised)된 제목인 경우 false로 표시됩니다. +URL에서 합성(synthesised)된 제목인 경우 false로 표시됩니다. ### Event: 'page-favicon-updated' diff --git a/docs-translations/ko-KR/tutorial/application-packaging.md b/docs-translations/ko-KR/tutorial/application-packaging.md index 97054110ce80..9183f0eafe96 100644 --- a/docs-translations/ko-KR/tutorial/application-packaging.md +++ b/docs-translations/ko-KR/tutorial/application-packaging.md @@ -103,6 +103,14 @@ var originalFs = require('original-fs'); originalFs.readFileSync('/path/to/example.asar'); ``` +또한 `process.noAsar`를 `true`로 지정하면 `fs` 모듈의 `asar` 지원을 비활성화 시킬 수 +있습니다. + +```javascript +process.noAsar = true; +fs.readFileSync('/path/to/example.asar'); +``` + ## Node API의 한계 `asar` 아카이브를 Node API가 최대한 디렉터리 구조로 작동하도록 노력해왔지만 여전히 diff --git a/docs-translations/ko-KR/tutorial/debugging-main-process.md b/docs-translations/ko-KR/tutorial/debugging-main-process.md index 32a6bd00f7ae..ee7e8432d420 100644 --- a/docs-translations/ko-KR/tutorial/debugging-main-process.md +++ b/docs-translations/ko-KR/tutorial/debugging-main-process.md @@ -19,9 +19,9 @@ ## node-inspector로 디버깅 하기 -__참고:__ Electron은 node v0.11.13 버전을 사용합니다. 그리고 현재 node-inspector -유틸리티와 호환성 문제가 있습니다. 추가로 node-inspector 콘솔 내에서 메인 프로세스의 -`process` 객체를 탐색할 경우 크래시가 발생할 수 있습니다. +__참고:__ Electron은 현재 node-inspector 유틸리티와 호환성 문제가 있습니다. 따라서 +node-inspector 콘솔 내에서 메인 프로세스의 `process` 객체를 탐색할 경우 크래시가 +발생할 수 있습니다. ### 1. [node-inspector][node-inspector] 서버 시작 From 0553b9c672f3fdb51b54fb181813e460e15b15ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9verton=20Heming?= Date: Wed, 2 Dec 2015 15:27:23 +0000 Subject: [PATCH 687/738] Add electron-br --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index beb96b4e5c2a..63c8aae69f3d 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ locations: forums - `#atom-shell` channel on Freenode - [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack +- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)* Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron) for a community maintained list of useful example apps, tools and resources. From 32e949efed094d8212d8aafd2e6d0e7f7ffb46c0 Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Wed, 2 Dec 2015 11:50:44 -0800 Subject: [PATCH 688/738] Read window size properly in `window.open` test `BrowserWindow#getSize` returns `[width, height]`, not `{width, height}`. --- spec/chromium-spec.coffee | 4 ++-- spec/fixtures/pages/window-open-size.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/chromium-spec.coffee b/spec/chromium-spec.coffee index 435f7bbbe3e5..7aecde218dab 100644 --- a/spec/chromium-spec.coffee +++ b/spec/chromium-spec.coffee @@ -75,8 +75,8 @@ describe 'chromium feature', -> it 'inherit options of parent window', (done) -> listener = (event) -> - size = remote.getCurrentWindow().getSize() - assert.equal event.data, "size: #{size.width} #{size.height}" + [width, height] = remote.getCurrentWindow().getSize() + assert.equal event.data, "size: #{width} #{height}" b.close() done() window.addEventListener 'message', listener diff --git a/spec/fixtures/pages/window-open-size.html b/spec/fixtures/pages/window-open-size.html index b32e39889a4c..93b5039f7966 100644 --- a/spec/fixtures/pages/window-open-size.html +++ b/spec/fixtures/pages/window-open-size.html @@ -2,7 +2,7 @@ From 225fe72d0337410117ad8f29647fc5ccd72e78c1 Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Wed, 2 Dec 2015 11:54:52 -0800 Subject: [PATCH 689/738] Ensure that `window.open` does not override the child options Fixes https://github.com/atom/electron/issues/3652. --- atom/browser/lib/guest-window-manager.coffee | 2 +- spec/chromium-spec.coffee | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index c311e01cf487..9b4490c4e08d 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -5,7 +5,7 @@ frameToGuest = {} # Copy attribute of |parent| to |child| if it is not defined in |child|. mergeOptions = (child, parent) -> - for own key, value of parent when key not in child + for own key, value of parent when key not in Object.keys child if typeof value is 'object' child[key] = mergeOptions {}, value else diff --git a/spec/chromium-spec.coffee b/spec/chromium-spec.coffee index 7aecde218dab..211de346846b 100644 --- a/spec/chromium-spec.coffee +++ b/spec/chromium-spec.coffee @@ -82,6 +82,15 @@ describe 'chromium feature', -> window.addEventListener 'message', listener b = window.open "file://#{fixtures}/pages/window-open-size.html", '', 'show=no' + it 'does not override child options', (done) -> + size = {width: 350, height: 450} + listener = (event) -> + assert.equal event.data, "size: #{size.width} #{size.height}" + b.close() + done() + window.addEventListener 'message', listener + b = window.open "file://#{fixtures}/pages/window-open-size.html", '', "show=no,width=#{size.width},height=#{size.height}" + describe 'window.opener', -> @timeout 10000 From c311c6cf1bb139a9b980297a3ae78015367dfc76 Mon Sep 17 00:00:00 2001 From: Charlie Hess Date: Wed, 2 Dec 2015 13:49:30 -0800 Subject: [PATCH 690/738] Add a DownloadURL method on WebContents. --- atom/browser/api/atom_api_web_contents.cc | 10 ++++++++++ atom/browser/api/atom_api_web_contents.h | 1 + 2 files changed, 11 insertions(+) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index f377e8fda9e8..116bf03b1d4c 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -634,6 +634,15 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) { web_contents()->GetController().LoadURLWithParams(params); } +void WebContents::DownloadURL(const GURL& url) { + auto browser_context = web_contents()->GetBrowserContext(); + auto download_manager = + content::BrowserContext::GetDownloadManager(browser_context); + + download_manager->DownloadUrl( + content::DownloadUrlParameters::FromWebContents(web_contents(), url)); +} + GURL WebContents::GetURL() const { return web_contents()->GetURL(); } @@ -996,6 +1005,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("getId", &WebContents::GetID) .SetMethod("equal", &WebContents::Equal) .SetMethod("_loadURL", &WebContents::LoadURL) + .SetMethod("downloadURL", &WebContents::DownloadURL) .SetMethod("_getURL", &WebContents::GetURL) .SetMethod("getTitle", &WebContents::GetTitle) .SetMethod("isLoading", &WebContents::IsLoading) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 568a563e2c84..07cb79dfab9c 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -60,6 +60,7 @@ class WebContents : public mate::TrackableObject, int GetID() const; bool Equal(const WebContents* web_contents) const; void LoadURL(const GURL& url, const mate::Dictionary& options); + void DownloadURL(const GURL& url); GURL GetURL() const; base::string16 GetTitle() const; bool IsLoading() const; From 5839df66e4fc22d9b8d55455837211387f0a6bec Mon Sep 17 00:00:00 2001 From: Charlie Hess Date: Wed, 2 Dec 2015 13:49:42 -0800 Subject: [PATCH 691/738] Document the new method. --- docs/api/web-contents.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index e976b0ddb814..c35bbc9ae33c 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -242,6 +242,13 @@ const options = {"extraHeaders" : "pragma: no-cache\n"} webContents.loadURL(url, options) ``` +### `webContents.downloadURL(url)` + +* `url` URL + +Initiates a download of the resource at `url` without navigating. The +`will-download` event of `session` will be triggered. + ### `webContents.getURL()` Returns URL of the current web page. From 0d30a8d70cf82610a300552ea19d405913971433 Mon Sep 17 00:00:00 2001 From: Charlie Hess Date: Wed, 2 Dec 2015 18:40:02 -0800 Subject: [PATCH 692/738] Make downloadURL available on the webview tag. --- atom/renderer/lib/web-view/web-view.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 720e6e84c5d4..da36886f6ffa 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -288,6 +288,7 @@ registerWebViewElement = -> 'replace' 'replaceMisspelling' 'getId' + 'downloadURL' 'inspectServiceWorker' 'print' 'printToPDF' From b369d4991e56c8c1290c742b098797a9b2742fcc Mon Sep 17 00:00:00 2001 From: Charlie Hess Date: Wed, 2 Dec 2015 18:40:39 -0800 Subject: [PATCH 693/738] Write a spec for downloading from the webview tag. --- spec/api-session-spec.coffee | 40 +++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/spec/api-session-spec.coffee b/spec/api-session-spec.coffee index 6d0a8ac167c0..98e47e357a58 100644 --- a/spec/api-session-spec.coffee +++ b/spec/api-session-spec.coffee @@ -87,23 +87,43 @@ describe 'session module', -> res.end mockPDF downloadServer.close() - it 'can download successfully', (done) -> + assertDownload = (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}/" + assert.equal mimeType, 'application/pdf' + assert.equal receivedBytes, mockPDF.length + assert.equal totalBytes, mockPDF.length + assert.equal disposition, contentDisposition + assert fs.existsSync downloadFilePath + fs.unlinkSync downloadFilePath + + it 'can download using BrowserWindow.loadURL', (done) -> downloadServer.listen 0, '127.0.0.1', -> {port} = downloadServer.address() ipcRenderer.sendSync 'set-download-option', false w.loadURL "#{url}:#{port}" ipcRenderer.once 'download-done', (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) -> - assert.equal state, 'completed' - assert.equal filename, 'mock.pdf' - assert.equal url, "http://127.0.0.1:#{port}/" - assert.equal mimeType, 'application/pdf' - assert.equal receivedBytes, mockPDF.length - assert.equal totalBytes, mockPDF.length - assert.equal disposition, contentDisposition - assert fs.existsSync downloadFilePath - fs.unlinkSync downloadFilePath + assertDownload event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port done() + it 'can download using WebView.downloadURL', (done) -> + downloadServer.listen 0, '127.0.0.1', -> + {port} = downloadServer.address() + ipcRenderer.sendSync 'set-download-option', false + + webview = new WebView + webview.src = "file://#{fixtures}/api/blank.html" + webview.addEventListener 'did-finish-load', -> + webview.downloadURL "#{url}:#{port}/" + + ipcRenderer.once 'download-done', (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) -> + assertDownload event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port + document.body.removeChild(webview) + done() + + document.body.appendChild webview + it 'can cancel download', (done) -> downloadServer.listen 0, '127.0.0.1', -> {port} = downloadServer.address() From b1391270ed1b71b156cb4f5b8d84d2a6859b2a90 Mon Sep 17 00:00:00 2001 From: Charlie Hess Date: Wed, 2 Dec 2015 18:40:57 -0800 Subject: [PATCH 694/738] This spec is a little unreliable; up the timeout. --- spec/api-browser-window-spec.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 8df4c9a9479e..86beb1fdc600 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -262,6 +262,7 @@ describe 'browser-window module', -> w.loadURL "file://#{fixtures}/pages/window-open.html" it 'emits when link with target is called', (done) -> + @timeout 10000 w.webContents.once 'new-window', (e, url, frameName) -> e.preventDefault() assert.equal url, 'http://host/' From e5358d405ab2ba464005fa7189ff912e0d44b90a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 3 Dec 2015 11:24:33 +0800 Subject: [PATCH 695/738] Make sure V8 Function passed to native code are destroyed on UI thread --- .../common/native_mate_converters/callback.cc | 74 +++++++++++++++---- atom/common/native_mate_converters/callback.h | 30 ++++---- 2 files changed, 73 insertions(+), 31 deletions(-) diff --git a/atom/common/native_mate_converters/callback.cc b/atom/common/native_mate_converters/callback.cc index 87faa3df3cd5..cd9838c1edb3 100644 --- a/atom/common/native_mate_converters/callback.cc +++ b/atom/common/native_mate_converters/callback.cc @@ -5,6 +5,9 @@ #include "atom/common/native_mate_converters/callback.h" #include "atom/browser/atom_browser_main_parts.h" +#include "content/public/browser/browser_thread.h" + +using content::BrowserThread; namespace mate { @@ -56,31 +59,72 @@ v8::Local BindFunctionWith(v8::Isolate* isolate, } // namespace +// Destroy the class on UI thread when possible. +struct DeleteOnUIThread { + template + static void Destruct(const T* x) { + if (Locker::IsBrowserProcess() && + !BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, x); + } else { + delete x; + } + } +}; + +// Like v8::Global, but ref-counted. +template +class RefCountedGlobal : public base::RefCountedThreadSafe, + DeleteOnUIThread> { + public: + RefCountedGlobal(v8::Isolate* isolate, v8::Local value) + : handle_(isolate, v8::Local::Cast(value)), + weak_factory_(this) { + // In browser process, we need to ensure the V8 handle is destroyed before + // the JavaScript env gets destroyed. + if (Locker::IsBrowserProcess() && atom::AtomBrowserMainParts::Get()) { + atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback( + base::Bind(&RefCountedGlobal::FreeHandle, + weak_factory_.GetWeakPtr())); + } + } + + bool IsAlive() const { + return !handle_.IsEmpty(); + } + + v8::Local NewHandle(v8::Isolate* isolate) const { + return v8::Local::New(isolate, handle_); + } + + private: + void FreeHandle() { + handle_.Reset(); + } + + v8::Global handle_; + base::WeakPtrFactory> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(RefCountedGlobal); +}; + SafeV8Function::SafeV8Function(v8::Isolate* isolate, v8::Local value) - : v8_function_(new RefCountedPersistent(isolate, value)), - weak_factory_(this) { - Init(); + : v8_function_(new RefCountedGlobal(isolate, value)) { } SafeV8Function::SafeV8Function(const SafeV8Function& other) - : v8_function_(other.v8_function_), - weak_factory_(this) { - Init(); + : v8_function_(other.v8_function_) { } -v8::Local SafeV8Function::NewHandle() const { - return v8_function_->NewHandle(); +SafeV8Function::~SafeV8Function() { } -void SafeV8Function::Init() { - if (Locker::IsBrowserProcess() && atom::AtomBrowserMainParts::Get()) - atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback( - base::Bind(&SafeV8Function::FreeHandle, weak_factory_.GetWeakPtr())); +bool SafeV8Function::IsAlive() const { + return v8_function_.get() && v8_function_->IsAlive(); } -void SafeV8Function::FreeHandle() { - Locker locker(v8_function_->isolate()); - v8_function_ = nullptr; +v8::Local SafeV8Function::NewHandle(v8::Isolate* isolate) const { + return v8_function_->NewHandle(isolate); } v8::Local CreateFunctionFromTranslater( diff --git a/atom/common/native_mate_converters/callback.h b/atom/common/native_mate_converters/callback.h index 5dd9d3cec9b1..3cba2b32a820 100644 --- a/atom/common/native_mate_converters/callback.h +++ b/atom/common/native_mate_converters/callback.h @@ -19,23 +19,21 @@ namespace mate { namespace internal { -// Manages the V8 function with RAII, and automatically cleans the handle when -// JavaScript context is destroyed, even when the class is not destroyed. +template +class RefCountedGlobal; + +// Manages the V8 function with RAII. class SafeV8Function { public: SafeV8Function(v8::Isolate* isolate, v8::Local value); SafeV8Function(const SafeV8Function& other); + ~SafeV8Function(); - bool is_alive() const { return v8_function_.get(); } - - v8::Local NewHandle() const; + bool IsAlive() const; + v8::Local NewHandle(v8::Isolate* isolate) const; private: - void Init(); - void FreeHandle(); - - scoped_refptr> v8_function_; - base::WeakPtrFactory weak_factory_; + scoped_refptr> v8_function_; }; // Helper to invoke a V8 function with C++ parameters. @@ -49,12 +47,12 @@ struct V8FunctionInvoker(ArgTypes...)> { ArgTypes... raw) { Locker locker(isolate); v8::EscapableHandleScope handle_scope(isolate); - if (!function.is_alive()) + if (!function.IsAlive()) return v8::Null(isolate); scoped_ptr script_scope( Locker::IsBrowserProcess() ? nullptr : new blink::WebScopedRunV8Script(isolate)); - v8::Local holder = function.NewHandle(); + v8::Local holder = function.NewHandle(isolate); v8::Local context = holder->CreationContext(); v8::Context::Scope context_scope(context); std::vector> args = { ConvertToV8(isolate, raw)... }; @@ -70,12 +68,12 @@ struct V8FunctionInvoker { ArgTypes... raw) { Locker locker(isolate); v8::HandleScope handle_scope(isolate); - if (!function.is_alive()) + if (!function.IsAlive()) return; scoped_ptr script_scope( Locker::IsBrowserProcess() ? nullptr : new blink::WebScopedRunV8Script(isolate)); - v8::Local holder = function.NewHandle(); + v8::Local holder = function.NewHandle(isolate); v8::Local context = holder->CreationContext(); v8::Context::Scope context_scope(context); std::vector> args = { ConvertToV8(isolate, raw)... }; @@ -91,12 +89,12 @@ struct V8FunctionInvoker { Locker locker(isolate); v8::HandleScope handle_scope(isolate); ReturnType ret = ReturnType(); - if (!function.is_alive()) + if (!function.IsAlive()) return ret; scoped_ptr script_scope( Locker::IsBrowserProcess() ? nullptr : new blink::WebScopedRunV8Script(isolate)); - v8::Local holder = function.NewHandle(); + v8::Local holder = function.NewHandle(isolate); v8::Local context = holder->CreationContext(); v8::Context::Scope context_scope(context); std::vector> args = { ConvertToV8(isolate, raw)... }; From 6795bd1d9695634786badc3b2082019ec905c297 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 3 Dec 2015 15:38:43 +0800 Subject: [PATCH 696/738] Do not manually manage native resources We should rely on the destructor to cleanup everything, instead of putting them in the Destroy method. --- atom/browser/api/atom_api_download_item.cc | 26 +++++-------- atom/browser/api/atom_api_download_item.h | 3 -- atom/browser/api/atom_api_global_shortcut.cc | 3 -- atom/browser/api/atom_api_global_shortcut.h | 3 -- atom/browser/api/atom_api_menu.cc | 9 +---- atom/browser/api/atom_api_menu.h | 4 -- atom/browser/api/atom_api_menu_mac.h | 1 - atom/browser/api/atom_api_menu_mac.mm | 5 --- atom/browser/api/atom_api_power_monitor.cc | 3 -- atom/browser/api/atom_api_power_monitor.h | 3 -- .../api/atom_api_power_save_blocker.cc | 5 --- .../browser/api/atom_api_power_save_blocker.h | 3 -- atom/browser/api/atom_api_session.cc | 10 +---- atom/browser/api/atom_api_session.h | 4 -- atom/browser/api/atom_api_tray.cc | 11 +----- atom/browser/api/atom_api_tray.h | 6 --- atom/browser/api/atom_api_web_contents.cc | 37 +++++++------------ atom/browser/api/atom_api_web_contents.h | 4 -- atom/browser/api/atom_api_window.cc | 34 ++++++----------- atom/browser/api/atom_api_window.h | 6 --- atom/browser/api/trackable_object.cc | 15 +++++++- atom/browser/api/trackable_object.h | 11 ++++-- vendor/native_mate | 2 +- 23 files changed, 59 insertions(+), 149 deletions(-) diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index 7dd271304a43..fe63d7004355 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -70,29 +70,20 @@ DownloadItem::DownloadItem(content::DownloadItem* download_item) : } DownloadItem::~DownloadItem() { - Destroy(); -} - -void DownloadItem::Destroy() { - if (download_item_) { - download_item_->RemoveObserver(this); - auto iter = g_download_item_objects.find(download_item_->GetId()); - if (iter != g_download_item_objects.end()) - g_download_item_objects.erase(iter); - download_item_ = nullptr; - } -} - -bool DownloadItem::IsDestroyed() const { - return download_item_ == nullptr; + if (download_item_) + OnDownloadDestroyed(download_item_); } void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) { download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated"); } -void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) { - Destroy(); +void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) { + download_item_->RemoveObserver(this); + auto iter = g_download_item_objects.find(download_item_->GetId()); + if (iter != g_download_item_objects.end()) + g_download_item_objects.erase(iter); + download_item_ = nullptr; } int64 DownloadItem::GetReceivedBytes() { @@ -147,6 +138,7 @@ void DownloadItem::Cancel() { mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) + .MakeDestroyable() .SetMethod("pause", &DownloadItem::Pause) .SetMethod("resume", &DownloadItem::Resume) .SetMethod("cancel", &DownloadItem::Cancel) diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h index 955801cd9940..412b6ce9bf83 100644 --- a/atom/browser/api/atom_api_download_item.h +++ b/atom/browser/api/atom_api_download_item.h @@ -56,9 +56,6 @@ class DownloadItem : public mate::EventEmitter, // mate::Wrappable: mate::ObjectTemplateBuilder GetObjectTemplateBuilder( v8::Isolate* isolate) override; - bool IsDestroyed() const override; - - void Destroy(); content::DownloadItem* download_item_; diff --git a/atom/browser/api/atom_api_global_shortcut.cc b/atom/browser/api/atom_api_global_shortcut.cc index 6ab4fa4b6186..f5a03e4abf90 100644 --- a/atom/browser/api/atom_api_global_shortcut.cc +++ b/atom/browser/api/atom_api_global_shortcut.cc @@ -23,9 +23,6 @@ GlobalShortcut::GlobalShortcut() { } GlobalShortcut::~GlobalShortcut() { -} - -void GlobalShortcut::Destroy() { UnregisterAll(); } diff --git a/atom/browser/api/atom_api_global_shortcut.h b/atom/browser/api/atom_api_global_shortcut.h index 93eb7853ae0d..d7057b000320 100644 --- a/atom/browser/api/atom_api_global_shortcut.h +++ b/atom/browser/api/atom_api_global_shortcut.h @@ -27,9 +27,6 @@ class GlobalShortcut : public extensions::GlobalShortcutListener::Observer, GlobalShortcut(); ~GlobalShortcut() override; - // mate::TrackableObject: - void Destroy() override; - // mate::Wrappable implementations: mate::ObjectTemplateBuilder GetObjectTemplateBuilder( v8::Isolate* isolate) override; diff --git a/atom/browser/api/atom_api_menu.cc b/atom/browser/api/atom_api_menu.cc index 1f16a428da01..96cba3fe9914 100644 --- a/atom/browser/api/atom_api_menu.cc +++ b/atom/browser/api/atom_api_menu.cc @@ -27,14 +27,6 @@ Menu::Menu() Menu::~Menu() { } -void Menu::Destroy() { - model_.reset(); -} - -bool Menu::IsDestroyed() const { - return !model_; -} - void Menu::AfterInit(v8::Isolate* isolate) { mate::Dictionary wrappable(isolate, GetWrapper(isolate)); mate::Dictionary delegate; @@ -159,6 +151,7 @@ bool Menu::IsVisibleAt(int index) const { void Menu::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { mate::ObjectTemplateBuilder(isolate, prototype) + .MakeDestroyable() .SetMethod("insertItem", &Menu::InsertItemAt) .SetMethod("insertCheckItem", &Menu::InsertCheckItemAt) .SetMethod("insertRadioItem", &Menu::InsertRadioItemAt) diff --git a/atom/browser/api/atom_api_menu.h b/atom/browser/api/atom_api_menu.h index 545dd18e386c..17bb9073a719 100644 --- a/atom/browser/api/atom_api_menu.h +++ b/atom/browser/api/atom_api_menu.h @@ -39,11 +39,7 @@ class Menu : public mate::TrackableObject, Menu(); ~Menu() override; - // mate::TrackableObject: - void Destroy() override; - // mate::Wrappable: - bool IsDestroyed() const override; void AfterInit(v8::Isolate* isolate) override; // ui::SimpleMenuModel::Delegate: diff --git a/atom/browser/api/atom_api_menu_mac.h b/atom/browser/api/atom_api_menu_mac.h index baa2aff349e1..5a086776a639 100644 --- a/atom/browser/api/atom_api_menu_mac.h +++ b/atom/browser/api/atom_api_menu_mac.h @@ -19,7 +19,6 @@ class MenuMac : public Menu { protected: MenuMac(); - void Destroy() override; void Popup(Window* window) override; void PopupAt(Window* window, int x, int y) override; diff --git a/atom/browser/api/atom_api_menu_mac.mm b/atom/browser/api/atom_api_menu_mac.mm index 5936e0439f4f..071753218d6a 100644 --- a/atom/browser/api/atom_api_menu_mac.mm +++ b/atom/browser/api/atom_api_menu_mac.mm @@ -18,11 +18,6 @@ namespace api { MenuMac::MenuMac() { } -void MenuMac::Destroy() { - menu_controller_.reset(); - Menu::Destroy(); -} - void MenuMac::Popup(Window* window) { NativeWindow* native_window = window->window(); if (!native_window) diff --git a/atom/browser/api/atom_api_power_monitor.cc b/atom/browser/api/atom_api_power_monitor.cc index eeb9475c2847..31b35e10cea8 100644 --- a/atom/browser/api/atom_api_power_monitor.cc +++ b/atom/browser/api/atom_api_power_monitor.cc @@ -19,9 +19,6 @@ PowerMonitor::PowerMonitor() { } PowerMonitor::~PowerMonitor() { -} - -void PowerMonitor::Destroy() { base::PowerMonitor::Get()->RemoveObserver(this); } diff --git a/atom/browser/api/atom_api_power_monitor.h b/atom/browser/api/atom_api_power_monitor.h index 9303b3ab288f..8fb52eeec95e 100644 --- a/atom/browser/api/atom_api_power_monitor.h +++ b/atom/browser/api/atom_api_power_monitor.h @@ -23,9 +23,6 @@ class PowerMonitor : public mate::TrackableObject, PowerMonitor(); ~PowerMonitor() override; - // mate::TrackableObject: - void Destroy() override; - // base::PowerObserver implementations: void OnPowerStateChange(bool on_battery_power) override; void OnSuspend() override; diff --git a/atom/browser/api/atom_api_power_save_blocker.cc b/atom/browser/api/atom_api_power_save_blocker.cc index f77979ae417f..58983e6c846a 100644 --- a/atom/browser/api/atom_api_power_save_blocker.cc +++ b/atom/browser/api/atom_api_power_save_blocker.cc @@ -45,11 +45,6 @@ PowerSaveBlocker::PowerSaveBlocker() PowerSaveBlocker::~PowerSaveBlocker() { } -void PowerSaveBlocker::Destroy() { - power_save_blocker_types_.clear(); - power_save_blocker_.reset(); -} - void PowerSaveBlocker::UpdatePowerSaveBlocker() { if (power_save_blocker_types_.empty()) { power_save_blocker_.reset(); diff --git a/atom/browser/api/atom_api_power_save_blocker.h b/atom/browser/api/atom_api_power_save_blocker.h index e7ce97878ffb..a698d746ceb0 100644 --- a/atom/browser/api/atom_api_power_save_blocker.h +++ b/atom/browser/api/atom_api_power_save_blocker.h @@ -28,9 +28,6 @@ class PowerSaveBlocker : public mate::TrackableObject { PowerSaveBlocker(); ~PowerSaveBlocker() override; - // mate::TrackableObject: - void Destroy() override; - // mate::Wrappable implementations: mate::ObjectTemplateBuilder GetObjectTemplateBuilder( v8::Isolate* isolate) override; diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 27e1521f3d3f..495a4c46dd26 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -253,7 +253,6 @@ Session::Session(AtomBrowserContext* browser_context) Session::~Session() { content::BrowserContext::GetDownloadManager(browser_context())-> RemoveObserver(this); - Destroy(); } void Session::OnDownloadCreated(content::DownloadManager* manager, @@ -271,14 +270,6 @@ void Session::OnDownloadCreated(content::DownloadManager* manager, } } -bool Session::IsDestroyed() const { - return !browser_context_; -} - -void Session::Destroy() { - browser_context_ = nullptr; -} - void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) { new ResolveProxyHelper(browser_context(), url, callback); } @@ -379,6 +370,7 @@ v8::Local Session::Cookies(v8::Isolate* isolate) { mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) + .MakeDestroyable() .SetMethod("resolveProxy", &Session::ResolveProxy) .SetMethod("clearCache", &Session::ClearCache) .SetMethod("clearStorageData", &Session::ClearStorageData) diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 01dc0a408a8c..104a8e40cc63 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -59,12 +59,8 @@ class Session: public mate::TrackableObject, // mate::Wrappable: mate::ObjectTemplateBuilder GetObjectTemplateBuilder( v8::Isolate* isolate) override; - bool IsDestroyed() const override; private: - // mate::TrackableObject: - void Destroy() override; - void ResolveProxy(const GURL& url, ResolveProxyCallback callback); void ClearCache(const net::CompletionCallback& callback); void ClearStorageData(mate::Arguments* args); diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index 3b1a3a6321bb..5f351f485049 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -94,14 +94,6 @@ void Tray::OnDragEnded() { Emit("drag-end"); } -bool Tray::IsDestroyed() const { - return !tray_icon_; -} - -void Tray::Destroy() { - tray_icon_.reset(); -} - void Tray::SetImage(mate::Arguments* args, const gfx::Image& image) { tray_icon_->SetImage(image); } @@ -162,8 +154,7 @@ v8::Local Tray::ModifiersToObject(v8::Isolate* isolate, void Tray::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { mate::ObjectTemplateBuilder(isolate, prototype) - .SetMethod("destroy", &Tray::Destroy, true) - .SetMethod("isDestroyed", &Tray::IsDestroyed, true) + .MakeDestroyable() .SetMethod("setImage", &Tray::SetImage) .SetMethod("setPressedImage", &Tray::SetPressedImage) .SetMethod("setToolTip", &Tray::SetToolTip) diff --git a/atom/browser/api/atom_api_tray.h b/atom/browser/api/atom_api_tray.h index d8d6dcead16c..0e0d153ad0d3 100644 --- a/atom/browser/api/atom_api_tray.h +++ b/atom/browser/api/atom_api_tray.h @@ -54,12 +54,6 @@ class Tray : public mate::TrackableObject, void OnDragExited() override; void OnDragEnded() override; - // mate::Wrappable: - bool IsDestroyed() const override; - - // mate::TrackableObject: - void Destroy() override; - void SetImage(mate::Arguments* args, const gfx::Image& image); void SetPressedImage(mate::Arguments* args, const gfx::Image& image); void SetToolTip(mate::Arguments* args, const std::string& tool_tip); diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index f377e8fda9e8..2f8353e27338 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -290,7 +290,15 @@ WebContents::WebContents(v8::Isolate* isolate, } WebContents::~WebContents() { - Destroy(); + if (type_ == WEB_VIEW && managed_web_contents()) { + // When force destroying the "destroyed" event is not emitted. + WebContentsDestroyed(); + + guest_delegate_->Destroy(); + + Observe(nullptr); + DestroyWebContents(); + } } bool WebContents::AddMessageToConsole(content::WebContents* source, @@ -591,19 +599,6 @@ void WebContents::NavigationEntryCommitted( details.is_in_page, details.did_replace_entry); } -void WebContents::Destroy() { - session_.Reset(); - if (type_ == WEB_VIEW && managed_web_contents()) { - // When force destroying the "destroyed" event is not emitted. - WebContentsDestroyed(); - - guest_delegate_->Destroy(); - - Observe(nullptr); - DestroyWebContents(); - } -} - int WebContents::GetID() const { return web_contents()->GetRenderProcessHost()->GetID(); } @@ -991,8 +986,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( v8::Isolate* isolate) { if (template_.IsEmpty()) template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) - .SetMethod("destroy", &WebContents::Destroy, true) - .SetMethod("isDestroyed", &WebContents::IsDestroyed, true) + .MakeDestroyable() .SetMethod("getId", &WebContents::GetID) .SetMethod("equal", &WebContents::Equal) .SetMethod("_loadURL", &WebContents::LoadURL) @@ -1034,7 +1028,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling) .SetMethod("focus", &WebContents::Focus) .SetMethod("tabTraverse", &WebContents::TabTraverse) - .SetMethod("_send", &WebContents::SendIPCMessage, true) + .SetMethod("_send", &WebContents::SendIPCMessage) .SetMethod("sendInputEvent", &WebContents::SendInputEvent) .SetMethod("beginFrameSubscription", &WebContents::BeginFrameSubscription) @@ -1052,19 +1046,14 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("_printToPDF", &WebContents::PrintToPDF) .SetMethod("addWorkSpace", &WebContents::AddWorkSpace) .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace) - .SetProperty("session", &WebContents::Session, true) - .SetProperty("devToolsWebContents", - &WebContents::DevToolsWebContents, true) + .SetProperty("session", &WebContents::Session) + .SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents) .Build()); return mate::ObjectTemplateBuilder( isolate, v8::Local::New(isolate, template_)); } -bool WebContents::IsDestroyed() const { - return !web_contents(); -} - AtomBrowserContext* WebContents::GetBrowserContext() const { return static_cast(web_contents()->GetBrowserContext()); } diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 568a563e2c84..9462e926ee86 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -54,9 +54,6 @@ class WebContents : public mate::TrackableObject, static mate::Handle Create( v8::Isolate* isolate, const mate::Dictionary& options); - // mate::TrackableObject: - void Destroy() override; - int GetID() const; bool Equal(const WebContents* web_contents) const; void LoadURL(const GURL& url, const mate::Dictionary& options); @@ -152,7 +149,6 @@ class WebContents : public mate::TrackableObject, // mate::Wrappable: mate::ObjectTemplateBuilder GetObjectTemplateBuilder( v8::Isolate* isolate) override; - bool IsDestroyed() const override; // content::WebContentsDelegate: bool AddMessageToConsole(content::WebContents* source, diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 569640554468..79c91db3fa5d 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -157,8 +157,8 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) { } Window::~Window() { - if (window_) - Destroy(); + if (!window_->IsClosed()) + window_->CloseContents(nullptr); } void Window::WillCloseWindow(bool* prevent_default) { @@ -166,19 +166,19 @@ void Window::WillCloseWindow(bool* prevent_default) { } void Window::OnWindowClosed() { - if (api_web_contents_) { - api_web_contents_->DestroyWebContents(); - api_web_contents_ = nullptr; - web_contents_.Reset(); - } + api_web_contents_->DestroyWebContents(); RemoveFromWeakMap(); window_->RemoveObserver(this); + // We can not call Destroy here because we need to call Emit first, but we + // also do not want any method to be used, so just mark as destroyed here. + MarkDestroyed(); + Emit("closed"); - // Clean up the resources after window has been closed. - base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release()); + // Destroy the native class when window is closed. + base::MessageLoop::current()->PostTask(FROM_HERE, GetDestroyClosure()); } void Window::OnWindowBlur() { @@ -276,15 +276,6 @@ mate::Wrappable* Window::New(v8::Isolate* isolate, mate::Arguments* args) { return new Window(isolate, options); } -bool Window::IsDestroyed() const { - return !window_ || window_->IsClosed(); -} - -void Window::Destroy() { - if (window_) - window_->CloseContents(nullptr); -} - void Window::Close() { window_->Close(); } @@ -622,8 +613,7 @@ v8::Local Window::WebContents(v8::Isolate* isolate) { void Window::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { mate::ObjectTemplateBuilder(isolate, prototype) - .SetMethod("destroy", &Window::Destroy, true) - .SetMethod("isDestroyed", &Window::IsDestroyed, true) + .MakeDestroyable() .SetMethod("close", &Window::Close) .SetMethod("focus", &Window::Focus) .SetMethod("isFocused", &Window::IsFocused) @@ -695,8 +685,8 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("showDefinitionForSelection", &Window::ShowDefinitionForSelection) #endif - .SetProperty("id", &Window::ID, true) - .SetProperty("webContents", &Window::WebContents, true); + .SetProperty("id", &Window::ID) + .SetProperty("webContents", &Window::WebContents); } // static diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index a04e00cfb48e..6d5ce22f4316 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -77,13 +77,7 @@ class Window : public mate::TrackableObject, void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override; #endif - // mate::Wrappable: - bool IsDestroyed() const override; - private: - // mate::TrackableObject: - void Destroy() override; - // APIs for NativeWindow. void Close(); void Focus(); diff --git a/atom/browser/api/trackable_object.cc b/atom/browser/api/trackable_object.cc index 50bfa59e6a7a..5b1c6b82407d 100644 --- a/atom/browser/api/trackable_object.cc +++ b/atom/browser/api/trackable_object.cc @@ -30,8 +30,7 @@ class IDUserData : public base::SupportsUserData::Data { TrackableObjectBase::TrackableObjectBase() : weak_map_id_(0), wrapped_(nullptr), weak_factory_(this) { - RegisterDestructionCallback( - base::Bind(&TrackableObjectBase::Destroy, weak_factory_.GetWeakPtr())); + RegisterDestructionCallback(GetDestroyClosure()); } TrackableObjectBase::~TrackableObjectBase() { @@ -42,6 +41,18 @@ void TrackableObjectBase::AfterInit(v8::Isolate* isolate) { AttachAsUserData(wrapped_); } +void TrackableObjectBase::MarkDestroyed() { + GetWrapper(isolate())->SetAlignedPointerInInternalField(0, nullptr); +} + +base::Closure TrackableObjectBase::GetDestroyClosure() { + return base::Bind(&TrackableObjectBase::Destroy, weak_factory_.GetWeakPtr()); +} + +void TrackableObjectBase::Destroy() { + delete this; +} + void TrackableObjectBase::AttachAsUserData(base::SupportsUserData* wrapped) { if (weak_map_id_ != 0) { wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_)); diff --git a/atom/browser/api/trackable_object.h b/atom/browser/api/trackable_object.h index 8ff7d1c04041..975bb130b671 100644 --- a/atom/browser/api/trackable_object.h +++ b/atom/browser/api/trackable_object.h @@ -30,15 +30,18 @@ class TrackableObjectBase : public mate::EventEmitter { // Wrap TrackableObject into a class that SupportsUserData. void AttachAsUserData(base::SupportsUserData* wrapped); - // Subclasses should implement this to destroy their native types. - virtual void Destroy() = 0; - protected: ~TrackableObjectBase() override; // mate::Wrappable: void AfterInit(v8::Isolate* isolate) override; + // Mark the JS object as destroyed. + void MarkDestroyed(); + + // Returns a closure that can destroy the native class. + base::Closure GetDestroyClosure(); + // Get the weak_map_id from SupportsUserData. static int32_t GetIDFromWrappedClass(base::SupportsUserData* wrapped); @@ -50,6 +53,8 @@ class TrackableObjectBase : public mate::EventEmitter { base::SupportsUserData* wrapped_; private: + void Destroy(); + base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(TrackableObjectBase); diff --git a/vendor/native_mate b/vendor/native_mate index 93984941005b..e859228db163 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit 93984941005bab194a2d47aff655d525c064efcb +Subproject commit e859228db163c27410fb200c2df0715478fdf0d7 From a15f9fab5b76b3619d7411826beb6456850cbdd6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 3 Dec 2015 16:04:46 +0800 Subject: [PATCH 697/738] Use BuildPrototype to build prototype This saves the step of manually keeping the global template object, which is easy to forget then leak. --- atom/browser/api/atom_api_cookies.cc | 17 +-- atom/browser/api/atom_api_cookies.h | 12 +- atom/browser/api/atom_api_download_item.cc | 7 +- atom/browser/api/atom_api_download_item.h | 10 +- atom/browser/api/atom_api_session.cc | 31 ++--- atom/browser/api/atom_api_session.h | 8 +- atom/browser/api/atom_api_web_contents.cc | 138 ++++++++++----------- atom/browser/api/atom_api_web_contents.h | 8 +- atom/browser/api/trackable_object.h | 18 +++ atom/common/api/atom_api_asar.cc | 25 ++-- 10 files changed, 148 insertions(+), 126 deletions(-) diff --git a/atom/browser/api/atom_api_cookies.cc b/atom/browser/api/atom_api_cookies.cc index a3b2c37c9acd..3b1bd499be4c 100644 --- a/atom/browser/api/atom_api_cookies.cc +++ b/atom/browser/api/atom_api_cookies.cc @@ -322,14 +322,6 @@ void Cookies::OnSetCookies(const CookiesCallback& callback, callback)); } -mate::ObjectTemplateBuilder Cookies::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return mate::ObjectTemplateBuilder(isolate) - .SetMethod("get", &Cookies::Get) - .SetMethod("remove", &Cookies::Remove) - .SetMethod("set", &Cookies::Set); -} - net::CookieStore* Cookies::GetCookieStore() { return request_context_getter_->GetURLRequestContext()->cookie_store(); } @@ -341,6 +333,15 @@ mate::Handle Cookies::Create( return mate::CreateHandle(isolate, new Cookies(browser_context)); } +// static +void Cookies::BuildPrototype(v8::Isolate* isolate, + v8::Local prototype) { + mate::ObjectTemplateBuilder(isolate, prototype) + .SetMethod("get", &Cookies::Get) + .SetMethod("remove", &Cookies::Remove) + .SetMethod("set", &Cookies::Set); +} + } // namespace api } // namespace atom diff --git a/atom/browser/api/atom_api_cookies.h b/atom/browser/api/atom_api_cookies.h index 0c309b3f18ee..5afa1bd23ca6 100644 --- a/atom/browser/api/atom_api_cookies.h +++ b/atom/browser/api/atom_api_cookies.h @@ -7,8 +7,8 @@ #include +#include "atom/browser/api/trackable_object.h" #include "base/callback.h" -#include "native_mate/wrappable.h" #include "native_mate/handle.h" #include "net/cookies/canonical_cookie.h" @@ -33,7 +33,7 @@ namespace atom { namespace api { -class Cookies : public mate::Wrappable { +class Cookies : public mate::TrackableObject { public: // node.js style callback function(error, result) typedef base::Callback, v8::Local)> @@ -42,6 +42,10 @@ class Cookies : public mate::Wrappable { static mate::Handle Create(v8::Isolate* isolate, content::BrowserContext* browser_context); + // mate::TrackableObject: + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); + protected: explicit Cookies(content::BrowserContext* browser_context); ~Cookies(); @@ -70,10 +74,6 @@ class Cookies : public mate::Wrappable { void OnSetCookies(const CookiesCallback& callback, bool set_success); - // mate::Wrappable: - mate::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate) override; - private: // Must be called on IO thread. net::CookieStore* GetCookieStore(); diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index fe63d7004355..f186821e7d31 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -135,9 +135,10 @@ void DownloadItem::Cancel() { download_item_->Cancel(true); } -mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return mate::ObjectTemplateBuilder(isolate) +// static +void DownloadItem::BuildPrototype(v8::Isolate* isolate, + v8::Local prototype) { + mate::ObjectTemplateBuilder(isolate, prototype) .MakeDestroyable() .SetMethod("pause", &DownloadItem::Pause) .SetMethod("resume", &DownloadItem::Resume) diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h index 412b6ce9bf83..471913c2266a 100644 --- a/atom/browser/api/atom_api_download_item.h +++ b/atom/browser/api/atom_api_download_item.h @@ -17,7 +17,7 @@ namespace atom { namespace api { -class DownloadItem : public mate::EventEmitter, +class DownloadItem : public mate::TrackableObject, public content::DownloadItem::Observer { public: class SavePathData : public base::SupportsUserData::Data { @@ -32,6 +32,10 @@ class DownloadItem : public mate::EventEmitter, content::DownloadItem* item); static void* UserDataKey(); + // mate::TrackableObject: + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); + protected: explicit DownloadItem(content::DownloadItem* download_item); ~DownloadItem(); @@ -53,10 +57,6 @@ class DownloadItem : public mate::EventEmitter, void SetSavePath(const base::FilePath& path); private: - // mate::Wrappable: - mate::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate) override; - content::DownloadItem* download_item_; DISALLOW_COPY_AND_ASSIGN(DownloadItem); diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 495a4c46dd26..f39073825c00 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -367,21 +367,6 @@ v8::Local Session::Cookies(v8::Isolate* isolate) { return v8::Local::New(isolate, cookies_); } -mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return mate::ObjectTemplateBuilder(isolate) - .MakeDestroyable() - .SetMethod("resolveProxy", &Session::ResolveProxy) - .SetMethod("clearCache", &Session::ClearCache) - .SetMethod("clearStorageData", &Session::ClearStorageData) - .SetMethod("setProxy", &Session::SetProxy) - .SetMethod("setDownloadPath", &Session::SetDownloadPath) - .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation) - .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation) - .SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc) - .SetProperty("cookies", &Session::Cookies); -} - // static mate::Handle Session::CreateFrom( v8::Isolate* isolate, AtomBrowserContext* browser_context) { @@ -402,6 +387,22 @@ mate::Handle Session::FromPartition( static_cast(browser_context.get())); } +// static +void Session::BuildPrototype(v8::Isolate* isolate, + v8::Local prototype) { + mate::ObjectTemplateBuilder(isolate, prototype) + .MakeDestroyable() + .SetMethod("resolveProxy", &Session::ResolveProxy) + .SetMethod("clearCache", &Session::ClearCache) + .SetMethod("clearStorageData", &Session::ClearStorageData) + .SetMethod("setProxy", &Session::SetProxy) + .SetMethod("setDownloadPath", &Session::SetDownloadPath) + .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation) + .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation) + .SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc) + .SetProperty("cookies", &Session::Cookies); +} + void ClearWrapSession() { g_wrap_session.Reset(); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 104a8e40cc63..e800a992d4b7 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -48,6 +48,10 @@ class Session: public mate::TrackableObject, AtomBrowserContext* browser_context() const { return browser_context_.get(); } + // mate::TrackableObject: + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); + protected: explicit Session(AtomBrowserContext* browser_context); ~Session(); @@ -56,10 +60,6 @@ class Session: public mate::TrackableObject, void OnDownloadCreated(content::DownloadManager* manager, content::DownloadItem* item) override; - // mate::Wrappable: - mate::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate) override; - private: void ResolveProxy(const GURL& url, ResolveProxyCallback callback); void ClearCache(const net::CompletionCallback& callback); diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 2f8353e27338..da28dcf60c61 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -194,8 +194,6 @@ namespace api { namespace { -v8::Persistent template_; - // The wrapWebContents function which is implemented in JavaScript using WrapWebContentsCallback = base::Callback)>; WrapWebContentsCallback g_wrap_web_contents; @@ -982,76 +980,72 @@ v8::Local WebContents::DevToolsWebContents(v8::Isolate* isolate) { return v8::Local::New(isolate, devtools_web_contents_); } -mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - if (template_.IsEmpty()) - template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) - .MakeDestroyable() - .SetMethod("getId", &WebContents::GetID) - .SetMethod("equal", &WebContents::Equal) - .SetMethod("_loadURL", &WebContents::LoadURL) - .SetMethod("_getURL", &WebContents::GetURL) - .SetMethod("getTitle", &WebContents::GetTitle) - .SetMethod("isLoading", &WebContents::IsLoading) - .SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse) - .SetMethod("_stop", &WebContents::Stop) - .SetMethod("_goBack", &WebContents::GoBack) - .SetMethod("_goForward", &WebContents::GoForward) - .SetMethod("_goToOffset", &WebContents::GoToOffset) - .SetMethod("isCrashed", &WebContents::IsCrashed) - .SetMethod("setUserAgent", &WebContents::SetUserAgent) - .SetMethod("getUserAgent", &WebContents::GetUserAgent) - .SetMethod("insertCSS", &WebContents::InsertCSS) - .SetMethod("savePage", &WebContents::SavePage) - .SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript) - .SetMethod("openDevTools", &WebContents::OpenDevTools) - .SetMethod("closeDevTools", &WebContents::CloseDevTools) - .SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened) - .SetMethod("enableDeviceEmulation", - &WebContents::EnableDeviceEmulation) - .SetMethod("disableDeviceEmulation", - &WebContents::DisableDeviceEmulation) - .SetMethod("toggleDevTools", &WebContents::ToggleDevTools) - .SetMethod("inspectElement", &WebContents::InspectElement) - .SetMethod("setAudioMuted", &WebContents::SetAudioMuted) - .SetMethod("isAudioMuted", &WebContents::IsAudioMuted) - .SetMethod("undo", &WebContents::Undo) - .SetMethod("redo", &WebContents::Redo) - .SetMethod("cut", &WebContents::Cut) - .SetMethod("copy", &WebContents::Copy) - .SetMethod("paste", &WebContents::Paste) - .SetMethod("pasteAndMatchStyle", &WebContents::PasteAndMatchStyle) - .SetMethod("delete", &WebContents::Delete) - .SetMethod("selectAll", &WebContents::SelectAll) - .SetMethod("unselect", &WebContents::Unselect) - .SetMethod("replace", &WebContents::Replace) - .SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling) - .SetMethod("focus", &WebContents::Focus) - .SetMethod("tabTraverse", &WebContents::TabTraverse) - .SetMethod("_send", &WebContents::SendIPCMessage) - .SetMethod("sendInputEvent", &WebContents::SendInputEvent) - .SetMethod("beginFrameSubscription", - &WebContents::BeginFrameSubscription) - .SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription) - .SetMethod("setSize", &WebContents::SetSize) - .SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency) - .SetMethod("isGuest", &WebContents::IsGuest) - .SetMethod("getWebPreferences", &WebContents::GetWebPreferences) - .SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow) - .SetMethod("hasServiceWorker", &WebContents::HasServiceWorker) - .SetMethod("unregisterServiceWorker", - &WebContents::UnregisterServiceWorker) - .SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker) - .SetMethod("print", &WebContents::Print) - .SetMethod("_printToPDF", &WebContents::PrintToPDF) - .SetMethod("addWorkSpace", &WebContents::AddWorkSpace) - .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace) - .SetProperty("session", &WebContents::Session) - .SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents) - .Build()); - - return mate::ObjectTemplateBuilder( - isolate, v8::Local::New(isolate, template_)); +// static +void WebContents::BuildPrototype(v8::Isolate* isolate, + v8::Local prototype) { + mate::ObjectTemplateBuilder(isolate, prototype) + .MakeDestroyable() + .SetMethod("getId", &WebContents::GetID) + .SetMethod("equal", &WebContents::Equal) + .SetMethod("_loadURL", &WebContents::LoadURL) + .SetMethod("_getURL", &WebContents::GetURL) + .SetMethod("getTitle", &WebContents::GetTitle) + .SetMethod("isLoading", &WebContents::IsLoading) + .SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse) + .SetMethod("_stop", &WebContents::Stop) + .SetMethod("_goBack", &WebContents::GoBack) + .SetMethod("_goForward", &WebContents::GoForward) + .SetMethod("_goToOffset", &WebContents::GoToOffset) + .SetMethod("isCrashed", &WebContents::IsCrashed) + .SetMethod("setUserAgent", &WebContents::SetUserAgent) + .SetMethod("getUserAgent", &WebContents::GetUserAgent) + .SetMethod("insertCSS", &WebContents::InsertCSS) + .SetMethod("savePage", &WebContents::SavePage) + .SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript) + .SetMethod("openDevTools", &WebContents::OpenDevTools) + .SetMethod("closeDevTools", &WebContents::CloseDevTools) + .SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened) + .SetMethod("enableDeviceEmulation", + &WebContents::EnableDeviceEmulation) + .SetMethod("disableDeviceEmulation", + &WebContents::DisableDeviceEmulation) + .SetMethod("toggleDevTools", &WebContents::ToggleDevTools) + .SetMethod("inspectElement", &WebContents::InspectElement) + .SetMethod("setAudioMuted", &WebContents::SetAudioMuted) + .SetMethod("isAudioMuted", &WebContents::IsAudioMuted) + .SetMethod("undo", &WebContents::Undo) + .SetMethod("redo", &WebContents::Redo) + .SetMethod("cut", &WebContents::Cut) + .SetMethod("copy", &WebContents::Copy) + .SetMethod("paste", &WebContents::Paste) + .SetMethod("pasteAndMatchStyle", &WebContents::PasteAndMatchStyle) + .SetMethod("delete", &WebContents::Delete) + .SetMethod("selectAll", &WebContents::SelectAll) + .SetMethod("unselect", &WebContents::Unselect) + .SetMethod("replace", &WebContents::Replace) + .SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling) + .SetMethod("focus", &WebContents::Focus) + .SetMethod("tabTraverse", &WebContents::TabTraverse) + .SetMethod("_send", &WebContents::SendIPCMessage) + .SetMethod("sendInputEvent", &WebContents::SendInputEvent) + .SetMethod("beginFrameSubscription", + &WebContents::BeginFrameSubscription) + .SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription) + .SetMethod("setSize", &WebContents::SetSize) + .SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency) + .SetMethod("isGuest", &WebContents::IsGuest) + .SetMethod("getWebPreferences", &WebContents::GetWebPreferences) + .SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow) + .SetMethod("hasServiceWorker", &WebContents::HasServiceWorker) + .SetMethod("unregisterServiceWorker", + &WebContents::UnregisterServiceWorker) + .SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker) + .SetMethod("print", &WebContents::Print) + .SetMethod("_printToPDF", &WebContents::PrintToPDF) + .SetMethod("addWorkSpace", &WebContents::AddWorkSpace) + .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace) + .SetProperty("session", &WebContents::Session) + .SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents); } AtomBrowserContext* WebContents::GetBrowserContext() const { diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 9462e926ee86..637785aacea8 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -141,15 +141,15 @@ class WebContents : public mate::TrackableObject, v8::Local Session(v8::Isolate* isolate); v8::Local DevToolsWebContents(v8::Isolate* isolate); + // mate::TrackableObject: + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); + protected: explicit WebContents(content::WebContents* web_contents); WebContents(v8::Isolate* isolate, const mate::Dictionary& options); ~WebContents(); - // mate::Wrappable: - mate::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate) override; - // content::WebContentsDelegate: bool AddMessageToConsole(content::WebContents* source, int32 level, diff --git a/atom/browser/api/trackable_object.h b/atom/browser/api/trackable_object.h index 975bb130b671..562ab5ba4f9b 100644 --- a/atom/browser/api/trackable_object.h +++ b/atom/browser/api/trackable_object.h @@ -12,6 +12,7 @@ #include "base/bind.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "native_mate/object_template_builder.h" namespace base { class SupportsUserData; @@ -120,16 +121,33 @@ class TrackableObject : public TrackableObjectBase { } private: + // mate::Wrappable: + mate::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override { + if (template_.IsEmpty()) { + auto templ = v8::ObjectTemplate::New(isolate); + T::BuildPrototype(isolate, templ); + template_.Reset(isolate, templ); + } + + return ObjectTemplateBuilder( + isolate, v8::Local::New(isolate, template_)); + } + // Releases all weak references in weak map, called when app is terminating. static void ReleaseAllWeakReferences() { weak_map_.reset(); } + static v8::Persistent template_; static scoped_ptr weak_map_; DISALLOW_COPY_AND_ASSIGN(TrackableObject); }; +template +v8::Persistent TrackableObject::template_; + template scoped_ptr TrackableObject::weak_map_; diff --git a/atom/common/api/atom_api_asar.cc b/atom/common/api/atom_api_asar.cc index 4ea7d8c5c362..7aee71fc3294 100644 --- a/atom/common/api/atom_api_asar.cc +++ b/atom/common/api/atom_api_asar.cc @@ -18,6 +18,8 @@ namespace { +v8::Persistent template_; + class Archive : public mate::Wrappable { public: static v8::Local Create(v8::Isolate* isolate, @@ -101,15 +103,20 @@ class Archive : public mate::Wrappable { // mate::Wrappable: mate::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) { - return mate::ObjectTemplateBuilder(isolate) - .SetValue("path", archive_->path()) - .SetMethod("getFileInfo", &Archive::GetFileInfo) - .SetMethod("stat", &Archive::Stat) - .SetMethod("readdir", &Archive::Readdir) - .SetMethod("realpath", &Archive::Realpath) - .SetMethod("copyFileOut", &Archive::CopyFileOut) - .SetMethod("getFd", &Archive::GetFD) - .SetMethod("destroy", &Archive::Destroy); + if (template_.IsEmpty()) + template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) + .SetValue("path", archive_->path()) + .SetMethod("getFileInfo", &Archive::GetFileInfo) + .SetMethod("stat", &Archive::Stat) + .SetMethod("readdir", &Archive::Readdir) + .SetMethod("realpath", &Archive::Realpath) + .SetMethod("copyFileOut", &Archive::CopyFileOut) + .SetMethod("getFd", &Archive::GetFD) + .SetMethod("destroy", &Archive::Destroy) + .Build()); + + return mate::ObjectTemplateBuilder( + isolate, v8::Local::New(isolate, template_)); } private: From 117b7462dea71db40ee4f43039d9893ac2cad719 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 3 Dec 2015 16:17:10 +0800 Subject: [PATCH 698/738] window.id is no longer available when window is closed --- atom/browser/lib/guest-window-manager.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index c311e01cf487..2394b582ec4c 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -39,11 +39,12 @@ createGuest = (embedder, url, frameName, options) -> # When |embedder| is destroyed we should also destroy attached guest, and if # guest is closed by user then we should prevent |embedder| from double # closing guest. + guestId = guest.id closedByEmbedder = -> guest.removeListener 'closed', closedByUser guest.destroy() closedByUser = -> - embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', guest.id + embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', guestId embedder.removeListener 'render-view-deleted', closedByEmbedder embedder.once 'render-view-deleted', closedByEmbedder guest.once 'closed', closedByUser From 1e7c8c9fda4072d9a0672d0f9125c4edec60f272 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 3 Dec 2015 16:33:57 +0800 Subject: [PATCH 699/738] It is fine to leak a V8 handle on exit --- atom/common/native_mate_converters/callback.cc | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/atom/common/native_mate_converters/callback.cc b/atom/common/native_mate_converters/callback.cc index cd9838c1edb3..8bf5c459b0a2 100644 --- a/atom/common/native_mate_converters/callback.cc +++ b/atom/common/native_mate_converters/callback.cc @@ -4,7 +4,6 @@ #include "atom/common/native_mate_converters/callback.h" -#include "atom/browser/atom_browser_main_parts.h" #include "content/public/browser/browser_thread.h" using content::BrowserThread; @@ -78,15 +77,7 @@ class RefCountedGlobal : public base::RefCountedThreadSafe, DeleteOnUIThread> { public: RefCountedGlobal(v8::Isolate* isolate, v8::Local value) - : handle_(isolate, v8::Local::Cast(value)), - weak_factory_(this) { - // In browser process, we need to ensure the V8 handle is destroyed before - // the JavaScript env gets destroyed. - if (Locker::IsBrowserProcess() && atom::AtomBrowserMainParts::Get()) { - atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback( - base::Bind(&RefCountedGlobal::FreeHandle, - weak_factory_.GetWeakPtr())); - } + : handle_(isolate, v8::Local::Cast(value)) { } bool IsAlive() const { @@ -98,12 +89,7 @@ class RefCountedGlobal : public base::RefCountedThreadSafe, } private: - void FreeHandle() { - handle_.Reset(); - } - v8::Global handle_; - base::WeakPtrFactory> weak_factory_; DISALLOW_COPY_AND_ASSIGN(RefCountedGlobal); }; From eb8426269f7ed36c043dc41cde35a7f3717602e6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 3 Dec 2015 17:04:40 +0800 Subject: [PATCH 700/738] Remove itself from the cleanup list when it is destroyed --- atom/browser/api/trackable_object.cc | 9 +++++---- atom/browser/api/trackable_object.h | 3 ++- atom/browser/atom_browser_main_parts.cc | 17 ++++++++++++++--- atom/browser/atom_browser_main_parts.h | 5 +++-- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/atom/browser/api/trackable_object.cc b/atom/browser/api/trackable_object.cc index 5b1c6b82407d..77a936cde02c 100644 --- a/atom/browser/api/trackable_object.cc +++ b/atom/browser/api/trackable_object.cc @@ -30,10 +30,11 @@ class IDUserData : public base::SupportsUserData::Data { TrackableObjectBase::TrackableObjectBase() : weak_map_id_(0), wrapped_(nullptr), weak_factory_(this) { - RegisterDestructionCallback(GetDestroyClosure()); + cleanup_ = RegisterDestructionCallback(GetDestroyClosure()); } TrackableObjectBase::~TrackableObjectBase() { + cleanup_.Run(); } void TrackableObjectBase::AfterInit(v8::Isolate* isolate) { @@ -74,9 +75,9 @@ int32_t TrackableObjectBase::GetIDFromWrappedClass(base::SupportsUserData* w) { } // static -void TrackableObjectBase::RegisterDestructionCallback( - const base::Closure& closure) { - atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(closure); +base::Closure TrackableObjectBase::RegisterDestructionCallback( + const base::Closure& c) { + return atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(c); } } // namespace mate diff --git a/atom/browser/api/trackable_object.h b/atom/browser/api/trackable_object.h index 562ab5ba4f9b..8aad497034a8 100644 --- a/atom/browser/api/trackable_object.h +++ b/atom/browser/api/trackable_object.h @@ -48,7 +48,7 @@ class TrackableObjectBase : public mate::EventEmitter { // Register a callback that should be destroyed before JavaScript environment // gets destroyed. - static void RegisterDestructionCallback(const base::Closure& closure); + static base::Closure RegisterDestructionCallback(const base::Closure& c); int32_t weak_map_id_; base::SupportsUserData* wrapped_; @@ -56,6 +56,7 @@ class TrackableObjectBase : public mate::EventEmitter { private: void Destroy(); + base::Closure cleanup_; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(TrackableObjectBase); diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 3bfe3748f136..fd72f5e4ae9a 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -25,6 +25,11 @@ namespace atom { +template +void Erase(T* container, typename T::iterator iter) { + container->erase(iter); +} + // static AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL; @@ -56,9 +61,10 @@ bool AtomBrowserMainParts::SetExitCode(int code) { return true; } -void AtomBrowserMainParts::RegisterDestructionCallback( +base::Closure AtomBrowserMainParts::RegisterDestructionCallback( const base::Closure& callback) { - destruction_callbacks_.push_back(callback); + auto iter = destructors_.insert(destructors_.end(), callback); + return base::Bind(&Erase>, &destructors_, iter); } void AtomBrowserMainParts::PreEarlyInitialization() { @@ -150,8 +156,13 @@ void AtomBrowserMainParts::PostMainMessageLoopRun() { // Make sure destruction callbacks are called before message loop is // destroyed, otherwise some objects that need to be deleted on IO thread // won't be freed. - for (const auto& callback : destruction_callbacks_) + // We don't use ranged for loop because iterators are getting invalided when + // the callback runs. + for (auto iter = destructors_.begin(); iter != destructors_.end();) { + base::Closure& callback = *iter; + ++iter; callback.Run(); + } // Destroy JavaScript environment immediately after running destruction // callbacks. diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index bb4b204669fd..fbc59f7f811d 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -36,7 +36,8 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { // Register a callback that should be destroyed before JavaScript environment // gets destroyed. - void RegisterDestructionCallback(const base::Closure& callback); + // Returns a closure that can be used to remove |callback| from the list. + base::Closure RegisterDestructionCallback(const base::Closure& callback); Browser* browser() { return browser_.get(); } @@ -82,7 +83,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { base::Timer gc_timer_; // List of callbacks should be executed before destroying JS env. - std::list destruction_callbacks_; + std::list destructors_; static AtomBrowserMainParts* self_; From 48a11bd237df77953d6136958a28a9e824c30551 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 3 Dec 2015 17:10:14 +0800 Subject: [PATCH 701/738] Weak map only needs to be deleted for once --- atom/browser/api/trackable_object.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/atom/browser/api/trackable_object.h b/atom/browser/api/trackable_object.h index 8aad497034a8..7c4ed03fe052 100644 --- a/atom/browser/api/trackable_object.h +++ b/atom/browser/api/trackable_object.h @@ -98,11 +98,6 @@ class TrackableObject : public TrackableObjectBase { return std::vector>(); } - TrackableObject() { - RegisterDestructionCallback( - base::Bind(&TrackableObject::ReleaseAllWeakReferences)); - } - // Removes this instance from the weak map. void RemoveFromWeakMap() { if (weak_map_ && weak_map_->Has(weak_map_id())) @@ -110,13 +105,17 @@ class TrackableObject : public TrackableObjectBase { } protected: + TrackableObject() {} ~TrackableObject() override { RemoveFromWeakMap(); } void AfterInit(v8::Isolate* isolate) override { - if (!weak_map_) + if (!weak_map_) { weak_map_.reset(new atom::IDWeakMap); + RegisterDestructionCallback( + base::Bind(&TrackableObject::ReleaseAllWeakReferences)); + } weak_map_id_ = weak_map_->Add(isolate, GetWrapper(isolate)); TrackableObjectBase::AfterInit(isolate); } From dec714bda49f9af82dc923ae73be7c40360ac0ea Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 3 Dec 2015 08:40:47 -0800 Subject: [PATCH 702/738] Add newline before example code block --- docs/api/web-view-tag.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 56909a52e30f..e317ef8eab1e 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -164,6 +164,7 @@ The `webview` tag has the following methods: **Note:** The webview element must be loaded before using the methods. **Example** + ```javascript webview.addEventListener("dom-ready", function() { webview.openDevTools(); From c412b9b892fae6d6606b23018fd89f4e9888f76d Mon Sep 17 00:00:00 2001 From: Charlie Hess Date: Thu, 3 Dec 2015 12:14:08 -0800 Subject: [PATCH 703/738] Revert accidental change to this submodule. --- vendor/native_mate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/native_mate b/vendor/native_mate index 93984941005b..e859228db163 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit 93984941005bab194a2d47aff655d525c064efcb +Subproject commit e859228db163c27410fb200c2df0715478fdf0d7 From d583cf7d8cbe8886e689c3018744cdcbf5f16ebb Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 4 Dec 2015 07:54:09 +0900 Subject: [PATCH 704/738] Update as upstream [ci skip] --- docs-translations/ko-KR/api/web-view-tag.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index 531b19adcedd..935976b6bde9 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -158,6 +158,7 @@ API를 사용할 수 있습니다. 이를 지정하면 내부에서 로우레벨 **참고:** 태그 객체의 메서드는 페이지 로드가 끝난 뒤에만 사용할 수 있습니다. **예제** + ```javascript webview.addEventListener("dom-ready", function() { webview.openDevTools(); From 149859c97b5eec2dafdf715d1218ee8c50fef302 Mon Sep 17 00:00:00 2001 From: Zeke Sikelianos Date: Thu, 3 Dec 2015 18:06:18 -0600 Subject: [PATCH 705/738] add CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000000..444ce0b4c821 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,24 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery +- Personal attacks +- Trolling or insulting/derogatory comments +- Public or private harassment +- Publishing other's private information, such as physical or electronic addresses, without explicit permission +- Other unethical or unprofessional conduct + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at [atom@github.com](mailto:atom@github.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. + +This Code of Conduct is adapted from the Contributor Covenant, version 1.3.0, available from http://contributor-covenant.org/version/1/3/0/ From 7951226f5c3d88e047594fbe1cee4d5a7b129d52 Mon Sep 17 00:00:00 2001 From: Zeke Sikelianos Date: Thu, 3 Dec 2015 18:06:58 -0600 Subject: [PATCH 706/738] link to CoC from README and CONTRIBUTING --- CONTRIBUTING.md | 5 +++-- README.md | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 630b8b0ba0e2..67c1323205e5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,8 +2,9 @@ :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: -This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0). -By participating, you are expected to uphold this code. Please report unacceptable behavior to atom@github.com. +This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). +By participating, you are expected to uphold this code. Please report unacceptable +behavior to atom@github.com. The following is a set of guidelines for contributing to Electron. These are just guidelines, not rules, use your best judgment and feel free to diff --git a/README.md b/README.md index db82fac88ec6..8052e705bc8f 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ editor](https://github.com/atom/atom). Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important announcements. -This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0/). -By participating, you are expected to uphold this code. Please report -unacceptable behavior to atom@github.com. +This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). +By participating, you are expected to uphold this code. Please report unacceptable +behavior to atom@github.com. ## Downloads From 53350d26ae1b9f109636bde17f59f8c6c2f33891 Mon Sep 17 00:00:00 2001 From: Zeke Sikelianos Date: Thu, 3 Dec 2015 18:08:10 -0600 Subject: [PATCH 707/738] add placeholder CoC content to Korean README --- README-ko.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README-ko.md b/README-ko.md index 606d4e973e3e..7546f8c9f9a0 100644 --- a/README-ko.md +++ b/README-ko.md @@ -16,9 +16,7 @@ Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주 Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서 [@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요. -이 프로젝트는 [기여자 규약 1.2](http://contributor-covenant.org/version/1/2/0/)을 -준수합니다. 따라서 이 프로젝트의 개발에 참여하려면 이 계약을 지켜야 합니다. 받아들일 수 -없는 행위를 발견했을 경우 atom@github.com로 보고 하십시오. +[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) ## 다운로드 From 06a9ad3984cc388005b7f7ab3d062da8e89e202c Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 4 Dec 2015 10:06:25 +0900 Subject: [PATCH 708/738] Add contributing guide [ci skip] --- CONTRIBUTING-ko.md | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 CONTRIBUTING-ko.md diff --git a/CONTRIBUTING-ko.md b/CONTRIBUTING-ko.md new file mode 100644 index 000000000000..6747ad469003 --- /dev/null +++ b/CONTRIBUTING-ko.md @@ -0,0 +1,80 @@ +# Electron에 기여하기 + +:+1::tada: 먼저, 이 프로젝트에 기여해주셔서 감사합니다! :tada::+1: + +이 프로젝트는 기여자 규약 [행동 강령](CODE_OF_CONDUCT.md)을 +준수합니다. 따라서 이 프로젝트의 개발에 참여하려면 이 규약을 지켜야 합니다. 받아들일 수 +없는 행위를 발견했을 경우 atom@github.com로 보고 하십시오. + +다음 항목들은 Electron에 기여하는 가이드라인을 제시합니다. +참고로 이 항목들은 그저 가이드라인에 불과하며 규칙이 아닙니다. 따라서 스스로의 적절한 +판단에 따라 이 문서의 변경을 제안할 수 있으며 변경시 pull request를 넣으면 됩니다. + +## 이슈 제출 + +* [여기](https://github.com/atom/electron/issues/new)에서 새로운 이슈를 만들 수 +있습니다. 하지만 이슈를 작성하기 전에 아래의 항목들을 숙지하고 가능한한 이슈 보고에 +대해 최대한 많은 정보와 자세한 설명을 포함해야 합니다. 가능하다면 다음 항목을 포함해야 +합니다: + * 사용하고 있는 Electron의 버전 + * 현재 사용중인 운영체제 + * 가능하다면 무엇을 하려고 했고, 어떤 결과를 예측했으며, 어떤 것이 예측된대로 + 작동하지 않았는지에 대해 서술해야 합니다. +* 추가로 다음 사항을 준수하면 이슈를 해결하는데 큰 도움이 됩니다: + * 스크린샷 또는 GIF 애니메이션 이미지들 + * 터미널에 출력된 에러의 내용 또는 개발자 도구, 알림창에 뜬 내용 + * [Cursory search](https://github.com/atom/electron/issues?utf8=✓&q=is%3Aissue+)를 + 통해 이미 비슷한 내용의 이슈가 등록되어있는지 확인 + +## Pull Request 하기 + +* 가능한한 스크린샷과 GIF 애니메이션 이미지를 pull request에 추가 +* CoffeeScript, JavaScript, C++과 Python등 +[참조문서에 정의된 코딩스타일](/docs-translations/ko-KR/development/coding-style.md)을 +준수 +* [문서 스타일 가이드](/docs-translations/ko-KR/styleguide.md)에 따라 문서를 +[Markdown](https://daringfireball.net/projects/markdown) 형식으로 작성. +* 짧은, 현재 시제 커밋 메시지 사용. [커밋 메시지 스타일 가이드](#Git-커밋-메시지)를 +참고하세요 + +## 스타일 가이드 + +### 공통 코드 + +* 파일 마지막에 공백 라인(newline) 추가 +* 다음 순서에 맞춰서 require 코드 작성: + * Node 빌트인 모듈 (`path` 같은) + * Electron 모듈 (`ipc`, `app` 같은) + * 로컬 모듈 (상대 경로상에 있는) +* 다음 순서에 맞춰서 클래스 속성 지정: + * 클래스 메서드와 속성 (메서드는 `@`로 시작) + * 인스턴스 메서드와 속성 +* 플랫폼 종속적인 코드 자제: + * 파일 이름 결합시 `path.join()`을 사용. + * 임시 디렉터리가 필요할 땐 `/tmp` 대신 `os.tmpdir()`을 통해 접근. +* 명시적인 함수 종료가 필요할 땐 `return` 만 사용. + * `return null`, `return undefined`, `null`, 또는 `undefined` 사용 X + +### Git 커밋 메시지 + +* 현재 시제 사용 ("Added feature" 대신 "Add feature" 사용) +* 필수적 분위기(imperative mood) 사용 ("Moves cursor to..." 대신 "Move cursor to..." 사용) +* 첫 줄은 72자에 맞추거나 그 보다 적게 제한 +* 자유롭게 필요에 따라 이슈나 PR링크를 참조 +* 단순한 문서 변경일 경우 `[ci skip]`을 커밋 메시지에 추가 +* 커밋 메시지의 도입부에 의미있는 이모티콘 사용: + * :art: `:art:` 코드의 포맷이나 구조를 개선(추가)했을 때 + * :racehorse: `:racehorse:` 성능을 개선했을 때 + * :non-potable_water: `:non-potable_water:` 메모리 누수를 연결했을 때 + * :memo: `:memo:` 문서를 작성했을 때 + * :penguin: `:penguin:` Linux에 대한 패치를 했을 때 + * :apple: `:apple:` Mac OS에 대한 패치를 했을 때 + * :checkered_flag: `:checkered_flag:` Windows에 대한 패치를 했을 때 + * :bug: `:bug:` 버그를 고쳤을 때 + * :fire: `:fire:` 코드 또는 파일을 삭제했을 때 + * :green_heart: `:green_heart:` CI 빌드를 고쳤을 때 + * :white_check_mark: `:white_check_mark:` 테스트를 추가했을 때 + * :lock: `:lock:` 보안 문제를 해결했을 때 + * :arrow_up: `:arrow_up:` 종속성 라이브러리를 업데이트 했을 때 + * :arrow_down: `:arrow_down:` 종속성 라이브러리를 다운그레이드 했을 때 + * :shirt: `:shirt:` linter(코드 검사기)의 경고를 제거했을 때 From 2c6d23225460be0102ab7aeb0da0c6c14b09f838 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 4 Dec 2015 11:02:55 +0800 Subject: [PATCH 709/738] Don't add too much listeners in BrowserWindowProxy --- atom/browser/lib/guest-window-manager.coffee | 2 +- atom/renderer/lib/override.coffee | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index 35ef7b89bb44..eea26462b68d 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -44,7 +44,7 @@ createGuest = (embedder, url, frameName, options) -> guest.removeListener 'closed', closedByUser guest.destroy() closedByUser = -> - embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', guestId + embedder.send "ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_#{guestId}" embedder.removeListener 'render-view-deleted', closedByEmbedder embedder.once 'render-view-deleted', closedByEmbedder guest.once 'closed', closedByUser diff --git a/atom/renderer/lib/override.coffee b/atom/renderer/lib/override.coffee index 0b60ce0d6686..cb4fb8fbac2d 100644 --- a/atom/renderer/lib/override.coffee +++ b/atom/renderer/lib/override.coffee @@ -10,9 +10,8 @@ resolveURL = (url) -> class BrowserWindowProxy constructor: (@guestId) -> @closed = false - ipcRenderer.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', (event, guestId) => - if guestId is @guestId - @closed = true + ipcRenderer.once "ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_#{@guestId}", => + @closed = true close: -> ipcRenderer.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', @guestId From 973ae06f214122686c501ec28ff5f55e60fd4f0e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 4 Dec 2015 11:35:04 +0800 Subject: [PATCH 710/738] Destroy the native window in next tick It fixes a possible crash when native code is iterating all windows while the JavaScript code decides to destroy a window. --- atom/browser/api/atom_api_window.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 79c91db3fa5d..84e5c53ebe65 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -159,6 +159,10 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) { Window::~Window() { if (!window_->IsClosed()) window_->CloseContents(nullptr); + + // Destroy the native window in next tick because the native code might be + // iterating all windows. + base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release()); } void Window::WillCloseWindow(bool* prevent_default) { From 5e5ae81c536948d4bd39fe78de26880dea3e46cb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 4 Dec 2015 11:40:35 +0800 Subject: [PATCH 711/738] 'key of' is better than Object.keys --- atom/browser/lib/guest-window-manager.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index eea26462b68d..53bbb735b044 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -5,7 +5,7 @@ frameToGuest = {} # Copy attribute of |parent| to |child| if it is not defined in |child|. mergeOptions = (child, parent) -> - for own key, value of parent when key not in Object.keys child + for own key, value of parent when key not of child if typeof value is 'object' child[key] = mergeOptions {}, value else From 13c737823bee91f7f486f7d341b3d5712f6d5733 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 4 Dec 2015 11:52:34 +0800 Subject: [PATCH 712/738] spec: Suppress execFileSync test It somehow makes the test flaky after refresh. --- spec/asar-spec.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/asar-spec.coffee b/spec/asar-spec.coffee index 495d89734e5f..479443292b44 100644 --- a/spec/asar-spec.coffee +++ b/spec/asar-spec.coffee @@ -404,7 +404,8 @@ describe 'asar package', -> assert.equal stdout, 'test\n' done() - it 'execFileSync executes binaries', -> + # execFileSync makes the test flaky after a refresh. + xit 'execFileSync executes binaries', -> output = execFileSync echo, ['test'] assert.equal String(output), 'test\n' From 01f9107f0057df8fb66be6f0d9a9bf4f16665ea4 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 4 Dec 2015 13:48:38 +0900 Subject: [PATCH 713/738] Update as upstream [ci skip] --- CONTRIBUTING-ko.md | 6 +++--- README-ko.md | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING-ko.md b/CONTRIBUTING-ko.md index 6747ad469003..52887c8d38a7 100644 --- a/CONTRIBUTING-ko.md +++ b/CONTRIBUTING-ko.md @@ -2,9 +2,9 @@ :+1::tada: 먼저, 이 프로젝트에 기여해주셔서 감사합니다! :tada::+1: -이 프로젝트는 기여자 규약 [행동 강령](CODE_OF_CONDUCT.md)을 -준수합니다. 따라서 이 프로젝트의 개발에 참여하려면 이 규약을 지켜야 합니다. 받아들일 수 -없는 행위를 발견했을 경우 atom@github.com로 보고 하십시오. +이 프로젝트는 기여자 규약 [행동강령](CODE_OF_CONDUCT.md)을 준수합니다. 따라서 이 +프로젝트의 개발에 참여하려면 이 규약을 지켜야 합니다. 받아들일 수 없는 행위를 발견했을 +경우 atom@github.com로 보고 하십시오. 다음 항목들은 Electron에 기여하는 가이드라인을 제시합니다. 참고로 이 항목들은 그저 가이드라인에 불과하며 규칙이 아닙니다. 따라서 스스로의 적절한 diff --git a/README-ko.md b/README-ko.md index 7546f8c9f9a0..2bd24dfe5800 100644 --- a/README-ko.md +++ b/README-ko.md @@ -16,7 +16,9 @@ Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주 Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서 [@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요. -[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) +이 프로젝트는 기여자 규약 [행동강령](CODE_OF_CONDUCT.md)을 준수합니다. 따라서 이 +프로젝트의 개발에 참여하려면 이 규약을 지켜야 합니다. 받아들일 수 없는 행위를 발견했을 +경우 atom@github.com로 보고 하십시오. ## 다운로드 From 0bcc23d8fe17d5da943c92e036d2439411d51033 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Fri, 4 Dec 2015 13:52:03 +0900 Subject: [PATCH 714/738] Update as upstream [ci skip] --- docs-translations/ko-KR/api/web-contents.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index 82d426c1ce7e..4667ba733967 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -240,6 +240,13 @@ const options = {"extraHeaders" : "pragma: no-cache\n"} webContents.loadURL(url, options) ``` +### `webContents.downloadURL(url)` + +* `url` URL + +`url`의 리소스를 탐색 없이 다운로드를 시작합니다. `session`의 `will-download` +이벤트가 발생합니다. + ### `webContents.getURL()` 현재 웹 페이지의 URL을 반환합니다. From 7c1ea0b0f46334c31c59928731efb776bdbc7cc2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 4 Dec 2015 12:25:46 +0800 Subject: [PATCH 715/738] spec: Suppress flaky tests on Travis --- spec/api-protocol-spec.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/api-protocol-spec.coffee b/spec/api-protocol-spec.coffee index 5332b2b17ce6..034b9765927c 100644 --- a/spec/api-protocol-spec.coffee +++ b/spec/api-protocol-spec.coffee @@ -365,6 +365,9 @@ describe 'protocol module', -> done(error) it 'sends error when callback is called with nothing', (done) -> + # Flaky on Travis. + return done() if process.env.TRAVIS is 'true' + protocol.interceptBufferProtocol 'http', emptyHandler, (error) -> return done(error) if error $.ajax From c4f2d946e135b3a66572e685cd1856c9ed30b4d5 Mon Sep 17 00:00:00 2001 From: "Howard.Zuo" Date: Fri, 4 Dec 2015 15:18:55 +0800 Subject: [PATCH 716/738] add translation of using-native-node-modules for ZH-CN --- .../tutorial/using-native-node-modules.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 docs-translations/zh-CN/tutorial/using-native-node-modules.md diff --git a/docs-translations/zh-CN/tutorial/using-native-node-modules.md b/docs-translations/zh-CN/tutorial/using-native-node-modules.md new file mode 100644 index 000000000000..e03e7b8948a1 --- /dev/null +++ b/docs-translations/zh-CN/tutorial/using-native-node-modules.md @@ -0,0 +1,53 @@ +# 使用原生模块 + +Electron同样也支持原生模块,但由于和官方的Node相比使用了不同的V8引擎,如果你想编译原生模块,则需要手动设置Electron的headers的位置。 + +## 原生Node模块的兼容性 + +当Node开始换新的V8引擎版本时,原生模块可能“坏”掉。为确保一切工作正常,你需要检查你想要使用的原生模块是否被Electron内置的Node支持。你可以在[这里](https://github.com/atom/electron/releases)查看Electron内置的Node版本,或者使用`process.version`(参考:[快速入门](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md))查看。 + +考虑到[NAN](https://github.com/nodejs/nan/)可以使你的开发更容易对多版本Node的支持,建议使用它来开发你自己的模块。你也可以使用[NAN](https://github.com/nodejs/nan/)来移植旧的模块到新的Node版本,以使它们可以在新的Electron下良好工作。 + +## 如何安装原生模块 + +如下三种方法教你安装原生模块: + +### 最简单方式 + +最简单的方式就是通过[`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild)包重新编译原生模块,它帮你自动完成了下载headers、编译原生模块等步骤: + +```sh +npm install --save-dev electron-rebuild + +# 每次运行"npm install"时,也运行这条命令 +./node_modules/.bin/electron-rebuild + +# 在windows下如果上述命令遇到了问题,尝试这个: +.\node_modules\.bin\electron-rebuild.cmd +``` + +### 通过npm安装 + +你当然也可以通过`npm`安装原生模块。大部分步骤和安装普通模块时一样,除了以下一些系统环境变量你需要自己操作: + +```bash +export npm_config_disturl=https://atom.io/download/atom-shell +export npm_config_target=0.33.1 +export npm_config_arch=x64 +export npm_config_runtime=electron +HOME=~/.electron-gyp npm install module-name +``` + +### 通过node-gyp安装 + +你需要告诉`node-gyp`去哪下载Electron的headers,以及下载什么版本: + +```bash +$ cd /path-to-module/ +$ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=https://atom.io/download/atom-shell +``` + +`HOME=~/.electron-gyp`设置了去哪找开发时的headers。 +`--target=0.29.1`设置了Electron的版本 +`--dist-url=...`设置了Electron的headers的下载地址 +`--arch=x64`设置了该模块为适配64bit操作系统而编译 From c8e2be7b281d55bab8036058df9db52d90d14faa Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 4 Dec 2015 16:43:23 +0800 Subject: [PATCH 717/738] Bump v0.35.3 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/atom.gyp b/atom.gyp index 202a414003fc..2f97e206742a 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.35.2', + 'version%': '0.35.3', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index fb4a2332334e..dbb1f5082690 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.35.2 + 0.35.3 CFBundleShortVersionString - 0.35.2 + 0.35.3 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 773871fd5583..aaceb3420c97 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,35,2,0 - PRODUCTVERSION 0,35,2,0 + FILEVERSION 0,35,3,0 + PRODUCTVERSION 0,35,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.35.2" + VALUE "FileVersion", "0.35.3" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.35.2" + VALUE "ProductVersion", "0.35.3" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index b5cc0982d0d7..c1593120fd16 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 35 -#define ATOM_PATCH_VERSION 2 +#define ATOM_PATCH_VERSION 3 #define ATOM_VERSION_IS_RELEASE 1 From d14f15c33ae831704abc72f8f4d973ef46908b8d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 4 Dec 2015 19:23:30 +0800 Subject: [PATCH 718/738] Update native_mate: isDestroy => isDestroyed --- vendor/native_mate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/native_mate b/vendor/native_mate index e859228db163..5e70868fd0c0 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit e859228db163c27410fb200c2df0715478fdf0d7 +Subproject commit 5e70868fd0c005dc2c43bea15ca6e93da0b68741 From e1d7ef7e24affd8f4ede3689c5354ef11036bf62 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 4 Dec 2015 19:23:48 +0800 Subject: [PATCH 719/738] Bump v0.35.4 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/atom.gyp b/atom.gyp index 2f97e206742a..9f1ffe582505 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.35.3', + 'version%': '0.35.4', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index dbb1f5082690..179f26db03f3 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.35.3 + 0.35.4 CFBundleShortVersionString - 0.35.3 + 0.35.4 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index aaceb3420c97..05fb3f336ff6 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,35,3,0 - PRODUCTVERSION 0,35,3,0 + FILEVERSION 0,35,4,0 + PRODUCTVERSION 0,35,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.35.3" + VALUE "FileVersion", "0.35.4" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.35.3" + VALUE "ProductVersion", "0.35.4" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index c1593120fd16..a4930d0edb2e 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 35 -#define ATOM_PATCH_VERSION 3 +#define ATOM_PATCH_VERSION 4 #define ATOM_VERSION_IS_RELEASE 1 From 766bbfcb056d53d809a97b67d0ed81d6c3533834 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 7 Dec 2015 15:14:31 +0800 Subject: [PATCH 720/738] Chrome 47.0.2526.73 --- 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 2fb841acf35c..4978302abb0f 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '17a4337f7948a45b5ea4b8f391df152ba8db5979' +LIBCHROMIUMCONTENT_COMMIT = 'd534691711ecdef1739878674a9ffd5f2d5ac4a2' PLATFORM = { 'cygwin': 'win32', From 73e7773d841cdb82a3460ab6b3ade1892861b396 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 7 Dec 2015 19:56:23 +0800 Subject: [PATCH 721/738] Update to API changes of Chrome 47 --- atom/app/atom_content_client.cc | 19 ++-- atom/app/atom_content_client.h | 2 +- atom/browser/api/atom_api_session.cc | 7 +- atom/browser/api/atom_api_web_contents.cc | 4 +- atom/browser/api/frame_subscriber.cc | 9 +- atom/browser/atom_browser_client.cc | 3 +- atom/browser/atom_browser_context.cc | 12 +- atom/browser/atom_browser_context.h | 4 +- atom/browser/common_web_contents_delegate.cc | 2 +- atom/browser/native_window.cc | 4 +- atom/browser/native_window_mac.mm | 43 ++++--- atom/browser/native_window_views.cc | 2 +- atom/browser/net/url_request_fetch_job.cc | 8 +- atom/browser/net/url_request_fetch_job.h | 1 + atom/browser/ui/accelerator_util.cc | 6 +- .../ui/cocoa/event_processing_window.h | 30 ----- .../ui/cocoa/event_processing_window.mm | 106 ------------------ atom/browser/ui/message_box_gtk.cc | 2 +- atom/browser/ui/message_box_win.cc | 2 +- atom/browser/ui/x/x_window_utils.cc | 2 +- atom/browser/web_contents_preferences.cc | 4 - atom/common/api/atom_api_native_image.cc | 3 +- atom/common/api/event_emitter_caller.cc | 2 +- atom/common/crash_reporter/crash_reporter.cc | 8 +- .../crash_reporter/crash_reporter_linux.cc | 2 +- .../crash_reporter/crash_reporter_linux.h | 4 +- .../crash_reporter/crash_reporter_mac.h | 4 +- .../crash_reporter/crash_reporter_mac.mm | 2 +- .../crash_reporter/crash_reporter_win.cc | 2 +- .../crash_reporter/crash_reporter_win.h | 4 +- .../native_mate_converters/blink_converter.cc | 10 +- atom/common/native_mate_converters/callback.h | 6 +- atom/common/node_bindings.cc | 2 +- atom/common/options_switches.cc | 2 - atom/common/options_switches.h | 2 - atom/renderer/atom_renderer_client.cc | 2 - .../printing/print_view_manager_base.cc | 2 +- .../chrome/browser/process_singleton_posix.cc | 2 +- .../browser/speech/tts_controller_impl.cc | 2 +- .../browser/speech/tts_controller_impl.h | 4 +- chromium_src/chrome/browser/speech/tts_mac.mm | 4 +- .../pepper/pepper_flash_renderer_host.cc | 3 +- .../printing/print_web_view_helper.cc | 1 - docs/api/browser-window.md | 3 - filenames.gypi | 2 - vendor/brightray | 2 +- 46 files changed, 113 insertions(+), 239 deletions(-) delete mode 100644 atom/browser/ui/cocoa/event_processing_window.h delete mode 100644 atom/browser/ui/cocoa/event_processing_window.mm diff --git a/atom/app/atom_content_client.cc b/atom/app/atom_content_client.cc index 0931a1b55a41..9f161ac569a6 100644 --- a/atom/app/atom_content_client.cc +++ b/atom/app/atom_content_client.cc @@ -31,8 +31,8 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path, plugin.path = path; plugin.permissions = ppapi::PERMISSION_ALL_BITS; - std::vector flash_version_numbers; - base::SplitString(version, '.', &flash_version_numbers); + std::vector flash_version_numbers = base::SplitString( + version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); if (flash_version_numbers.size() < 1) flash_version_numbers.push_back("11"); // |SplitString()| puts in an empty string given an empty string. :( @@ -47,7 +47,7 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path, // E.g., "Shockwave Flash 10.2 r154": plugin.description = plugin.name + " " + flash_version_numbers[0] + "." + flash_version_numbers[1] + " r" + flash_version_numbers[2]; - plugin.version = JoinString(flash_version_numbers, '.'); + plugin.version = base::JoinString(flash_version_numbers, "."); content::WebPluginMimeType swf_mime_type( content::kFlashPluginSwfMimeType, content::kFlashPluginSwfExtension, @@ -81,19 +81,18 @@ std::string AtomContentClient::GetUserAgent() const { } void AtomContentClient::AddAdditionalSchemes( - std::vector* standard_schemes, + std::vector* standard_schemes, std::vector* savable_schemes) { auto command_line = base::CommandLine::ForCurrentProcess(); auto custom_schemes = command_line->GetSwitchValueASCII( switches::kRegisterStandardSchemes); if (!custom_schemes.empty()) { - std::vector schemes; - base::SplitString(custom_schemes, ',', &schemes); - standard_schemes->insert(standard_schemes->end(), - schemes.begin(), - schemes.end()); + std::vector schemes = base::SplitString( + custom_schemes, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + for (const std::string& scheme : schemes) + standard_schemes->push_back({scheme.c_str(), url::SCHEME_WITHOUT_PORT}); } - standard_schemes->push_back("chrome-extension"); + standard_schemes->push_back({"chrome-extension", url::SCHEME_WITHOUT_PORT}); } void AtomContentClient::AddPepperPlugins( diff --git a/atom/app/atom_content_client.h b/atom/app/atom_content_client.h index a6b2f73e7faa..2716b1eea400 100644 --- a/atom/app/atom_content_client.h +++ b/atom/app/atom_content_client.h @@ -22,7 +22,7 @@ class AtomContentClient : public brightray::ContentClient { std::string GetProduct() const override; std::string GetUserAgent() const override; void AddAdditionalSchemes( - std::vector* standard_schemes, + std::vector* standard_schemes, std::vector* savable_schemes) override; void AddPepperPlugins( std::vector* plugins) override; diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index f39073825c00..9cec7378b8e0 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -51,7 +51,7 @@ struct ClearStorageDataOptions { uint32 GetStorageMask(const std::vector& storage_types) { uint32 storage_mask = 0; for (const auto& it : storage_types) { - auto type = base::StringToLowerASCII(it); + auto type = base::ToLowerASCII(it); if (type == "appcache") storage_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE; else if (type == "cookies") @@ -75,7 +75,7 @@ uint32 GetStorageMask(const std::vector& storage_types) { uint32 GetQuotaMask(const std::vector& quota_types) { uint32 quota_mask = 0; for (const auto& it : quota_types) { - auto type = base::StringToLowerASCII(it); + auto type = base::ToLowerASCII(it); if (type == "temporary") quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY; else if (type == "persistent") @@ -233,7 +233,8 @@ void SetProxyInIO(net::URLRequestContextGetter* getter, const net::ProxyConfig& config, const base::Closure& callback) { auto proxy_service = getter->GetURLRequestContext()->proxy_service(); - proxy_service->ResetConfigService(new net::ProxyConfigServiceFixed(config)); + proxy_service->ResetConfigService(make_scoped_ptr( + new net::ProxyConfigServiceFixed(config))); // Refetches and applies the new pac script if provided. proxy_service->ForceReloadProxyConfig(); RunCallbackInUI(callback); diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index b16ab8c89960..a70b6cf4e0b2 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -148,7 +148,7 @@ struct Converter { std::string key; std::string value; while (headers->EnumerateHeaderLines(&iter, &key, &value)) { - key = base::StringToLowerASCII(key); + key = base::ToLowerASCII(key); if (response_headers.HasKey(key)) { base::ListValue* values = nullptr; if (response_headers.GetList(key, &values)) @@ -171,7 +171,7 @@ struct Converter { std::string save_type; if (!ConvertFromV8(isolate, val, &save_type)) return false; - save_type = base::StringToLowerASCII(save_type); + save_type = base::ToLowerASCII(save_type); if (save_type == "htmlonly") { *out = content::SAVE_PAGE_TYPE_AS_ONLY_HTML; } else if (save_type == "htmlcomplete") { diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index cf0eae14a9a8..5b7241486b72 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -24,12 +24,11 @@ bool FrameSubscriber::ShouldCaptureFrame( base::TimeTicks present_time, scoped_refptr* storage, DeliverFrameCallback* callback) { - *storage = media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_, - gfx::Rect(size_), size_, - base::TimeDelta()); + *storage = media::VideoFrame::CreateFrame( + media::PIXEL_FORMAT_YV12, + size_, gfx::Rect(size_), size_, base::TimeDelta()); *callback = base::Bind(&FrameSubscriber::OnFrameDelivered, - base::Unretained(this), - *storage); + base::Unretained(this), *storage); return true; } diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 38fdc0e19f9e..b9b186d187d0 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -84,7 +84,7 @@ void AtomBrowserClient::SuppressRendererProcessRestartForOnce() { void AtomBrowserClient::SetCustomSchemes( const std::vector& schemes) { - g_custom_schemes = JoinString(schemes, ','); + g_custom_schemes = base::JoinString(schemes, ","); } AtomBrowserClient::AtomBrowserClient() : delegate_(nullptr) { @@ -116,7 +116,6 @@ void AtomBrowserClient::OverrideWebkitPrefs( prefs->javascript_can_open_windows_automatically = true; prefs->plugins_enabled = true; prefs->dom_paste_enabled = true; - prefs->java_enabled = false; prefs->allow_scripts_to_close_windows = true; prefs->javascript_can_access_clipboard = true; prefs->local_storage_enabled = true; diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index 08c799962728..b9589d569b68 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -61,7 +61,7 @@ std::string RemoveWhitespace(const std::string& str) { AtomBrowserContext::AtomBrowserContext(const std::string& partition, bool in_memory) : brightray::BrowserContext(partition, in_memory), - cert_verifier_(new AtomCertVerifier), + cert_verifier_(nullptr), job_factory_(new AtomURLRequestJobFactory), allow_ntlm_everywhere_(false) { } @@ -86,7 +86,7 @@ std::string AtomBrowserContext::GetUserAgent() { return content::BuildUserAgentFromProduct(user_agent); } -net::URLRequestJobFactory* AtomBrowserContext::CreateURLRequestJobFactory( +scoped_ptr AtomBrowserContext::CreateURLRequestJobFactory( content::ProtocolHandlerMap* handlers, content::URLRequestInterceptorScopedVector* interceptors) { scoped_ptr job_factory(job_factory_); @@ -131,7 +131,7 @@ net::URLRequestJobFactory* AtomBrowserContext::CreateURLRequestJobFactory( top_job_factory.Pass(), make_scoped_ptr(*it))); interceptors->weak_clear(); - return top_job_factory.release(); + return top_job_factory.Pass(); } net::HttpCache::BackendFactory* @@ -160,8 +160,10 @@ content::BrowserPluginGuestManager* AtomBrowserContext::GetGuestManager() { return guest_manager_.get(); } -net::CertVerifier* AtomBrowserContext::CreateCertVerifier() { - return cert_verifier_; +scoped_ptr AtomBrowserContext::CreateCertVerifier() { + DCHECK(!cert_verifier_); + cert_verifier_ = new AtomCertVerifier; + return make_scoped_ptr(cert_verifier_); } net::SSLConfigService* AtomBrowserContext::CreateSSLConfigService() { diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index d3d7735c810d..564c9955d917 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -23,12 +23,12 @@ class AtomBrowserContext : public brightray::BrowserContext { // brightray::URLRequestContextGetter::Delegate: std::string GetUserAgent() override; - net::URLRequestJobFactory* CreateURLRequestJobFactory( + scoped_ptr CreateURLRequestJobFactory( content::ProtocolHandlerMap* handlers, content::URLRequestInterceptorScopedVector* interceptors) override; net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory( const base::FilePath& base_path) override; - net::CertVerifier* CreateCertVerifier() override; + scoped_ptr CreateCertVerifier() override; net::SSLConfigService* CreateSSLConfigService() override; bool AllowNTLMCredentialsForDomain(const GURL& auth_origin) override; diff --git a/atom/browser/common_web_contents_delegate.cc b/atom/browser/common_web_contents_delegate.cc index 8b7a159dd7d6..72a664f8cd00 100644 --- a/atom/browser/common_web_contents_delegate.cc +++ b/atom/browser/common_web_contents_delegate.cc @@ -380,7 +380,7 @@ gfx::ImageSkia CommonWebContentsDelegate::GetDevToolsWindowIcon() { void CommonWebContentsDelegate::GetDevToolsWindowWMClass( std::string* name, std::string* class_name) { *class_name = Browser::Get()->GetName(); - *name = base::StringToLowerASCII(*class_name); + *name = base::ToLowerASCII(*class_name); } #endif diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index a3df240e4d57..666da2d6b71d 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -291,10 +291,10 @@ void NativeWindow::CapturePage(const gfx::Rect& rect, const float scale = screen->GetDisplayNearestWindow(native_view).device_scale_factor(); if (scale > 1.0f) - bitmap_size = gfx::ToCeiledSize(gfx::ScaleSize(view_size, scale)); + bitmap_size = gfx::ScaleToCeiledSize(view_size, scale); host->CopyFromBackingStore( - rect.IsEmpty() ? gfx::Rect(view_size) : rect, + gfx::Rect(view_size), bitmap_size, base::Bind(&NativeWindow::OnCapturePageDone, weak_factory_.GetWeakPtr(), diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 42894c107de4..d7ed15cf0708 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -6,7 +6,6 @@ #include -#import "atom/browser/ui/cocoa/event_processing_window.h" #include "atom/common/draggable_region.h" #include "atom/common/options_switches.h" #include "base/mac/mac_util.h" @@ -19,6 +18,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "native_mate/dictionary.h" +#import "ui/base/cocoa/command_dispatcher.h" #include "ui/gfx/skia_util.h" namespace { @@ -209,10 +209,11 @@ bool ScopedDisableResize::disable_resize_ = false; @end -@interface AtomNSWindow : EventProcessingWindow { +@interface AtomNSWindow : NSWindow { @private atom::NativeWindowMac* shell_; bool enable_larger_than_screen_; + base::scoped_nsobject commandDispatcher_; } @property BOOL acceptsFirstMouse; @property BOOL disableAutoHideCursor; @@ -226,12 +227,15 @@ bool ScopedDisableResize::disable_resize_ = false; - (void)setShell:(atom::NativeWindowMac*)shell { shell_ = shell; + commandDispatcher_.reset([[CommandDispatcher alloc] initWithOwner:self]); } - (void)setEnableLargerThanScreen:(bool)enable { enable_larger_than_screen_ = enable; } +// NSWindow overrides. + - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen { // Resizing is disabled. if (ScopedDisableResize::IsResizeDisabled()) @@ -272,6 +276,25 @@ bool ScopedDisableResize::disable_resize_ = false; return !self.disableKeyOrMainWindow; } +// CommandDispatchingWindow implementation. + +- (void)setCommandHandler:(id)commandHandler { +} + +- (BOOL)redispatchKeyEvent:(NSEvent*)event { + return [commandDispatcher_ redispatchKeyEvent:event]; +} + +- (BOOL)defaultPerformKeyEquivalent:(NSEvent*)event { + return [super performKeyEquivalent:event]; +} + +- (void)commandDispatch:(id)sender { +} + +- (void)commandDispatchUsingKeyModifiers:(id)sender { +} + @end @interface ControlRegionView : NSView @@ -766,20 +789,14 @@ void NativeWindowMac::HandleKeyboardEvent( event.type == content::NativeWebKeyboardEvent::Char) return; - if (event.os_event.window == window_.get()) { - EventProcessingWindow* event_window = - static_cast(window_); - DCHECK([event_window isKindOfClass:[EventProcessingWindow class]]); - [event_window redispatchKeyEvent:event.os_event]; - } else { + 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 - // handled by the devtools itself, we now send it to application menu to - // make menu acclerators work. - BOOL handled = [[NSApp mainMenu] performKeyEquivalent:event.os_event]; - // Handle the cmd+~ shortcut. if (!handled && (event.os_event.modifierFlags & NSCommandKeyMask) && - (event.os_event.keyCode == 50 /* ~ key */)) + (event.os_event.keyCode == 50 /* ~ key */)) { + // Handle the cmd+~ shortcut. Focus(true); + } } } diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index c12ae1986c64..16faee58c5a4 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -180,7 +180,7 @@ NativeWindowViews::NativeWindowViews( // Set WM_WINDOW_ROLE. params.wm_role_name = "browser-window"; // Set WM_CLASS. - params.wm_class_name = base::StringToLowerASCII(name); + params.wm_class_name = base::ToLowerASCII(name); params.wm_class_class = name; #endif diff --git a/atom/browser/net/url_request_fetch_job.cc b/atom/browser/net/url_request_fetch_job.cc index 24a72226606e..f04ecd4060f0 100644 --- a/atom/browser/net/url_request_fetch_job.cc +++ b/atom/browser/net/url_request_fetch_job.cc @@ -14,6 +14,7 @@ #include "net/http/http_response_headers.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher_response_writer.h" +#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_builder.h" #include "net/url_request/url_request_status.h" @@ -23,7 +24,7 @@ namespace { // Convert string to RequestType. net::URLFetcher::RequestType GetRequestType(const std::string& raw) { - std::string method = base::StringToUpperASCII(raw); + std::string method = base::ToUpperASCII(raw); if (method.empty() || method == "GET") return net::URLFetcher::GET; else if (method == "POST") @@ -138,8 +139,9 @@ net::URLRequestContextGetter* URLRequestFetchJob::CreateRequestContext() { auto task_runner = base::ThreadTaskRunnerHandle::Get(); net::URLRequestContextBuilder builder; builder.set_proxy_service(net::ProxyService::CreateDirect()); - url_request_context_getter_ = - new net::TrivialURLRequestContextGetter(builder.Build(), task_runner); + request_context_ = builder.Build(); + url_request_context_getter_ = new net::TrivialURLRequestContextGetter( + request_context_.get(), task_runner); } return url_request_context_getter_.get(); } diff --git a/atom/browser/net/url_request_fetch_job.h b/atom/browser/net/url_request_fetch_job.h index 189cebf01b18..399f78ae3963 100644 --- a/atom/browser/net/url_request_fetch_job.h +++ b/atom/browser/net/url_request_fetch_job.h @@ -45,6 +45,7 @@ class URLRequestFetchJob : public JsAsker, // Create a independent request context. net::URLRequestContextGetter* CreateRequestContext(); + scoped_ptr request_context_; scoped_refptr url_request_context_getter_; scoped_ptr fetcher_; scoped_refptr pending_buffer_; diff --git a/atom/browser/ui/accelerator_util.cc b/atom/browser/ui/accelerator_util.cc index e25e14b7968c..a0b90e0c7e58 100644 --- a/atom/browser/ui/accelerator_util.cc +++ b/atom/browser/ui/accelerator_util.cc @@ -24,10 +24,10 @@ bool StringToAccelerator(const std::string& description, LOG(ERROR) << "The accelerator string can only contain ASCII characters"; return false; } - std::string shortcut(base::StringToLowerASCII(description)); + std::string shortcut(base::ToLowerASCII(description)); - std::vector tokens; - base::SplitString(shortcut, '+', &tokens); + std::vector tokens = base::SplitString( + shortcut, "+", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); // Now, parse it into an accelerator. int modifiers = ui::EF_NONE; diff --git a/atom/browser/ui/cocoa/event_processing_window.h b/atom/browser/ui/cocoa/event_processing_window.h deleted file mode 100644 index 88242711f8b7..000000000000 --- a/atom/browser/ui/cocoa/event_processing_window.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_UI_COCOA_EVENT_PROCESSING_WINDOW_H_ -#define ATOM_BROWSER_UI_COCOA_EVENT_PROCESSING_WINDOW_H_ - -#import - -// Override NSWindow to access unhandled keyboard events (for command -// processing); subclassing NSWindow is the only method to do -// this. -@interface EventProcessingWindow : NSWindow { - @private - BOOL redispatchingEvent_; - BOOL eventHandled_; -} - -// Sends a key event to |NSApp sendEvent:|, but also makes sure that it's not -// short-circuited to the RWHV. This is used to send keyboard events to the menu -// and the cmd-` handler if a keyboard event comes back unhandled from the -// renderer. The event must be of type |NSKeyDown|, |NSKeyUp|, or -// |NSFlagsChanged|. -// Returns |YES| if |event| has been handled. -- (BOOL)redispatchKeyEvent:(NSEvent*)event; - -- (BOOL)performKeyEquivalent:(NSEvent*)theEvent; -@end - -#endif // ATOM_BROWSER_UI_COCOA_EVENT_PROCESSING_WINDOW_H_ diff --git a/atom/browser/ui/cocoa/event_processing_window.mm b/atom/browser/ui/cocoa/event_processing_window.mm deleted file mode 100644 index d47cdf37b508..000000000000 --- a/atom/browser/ui/cocoa/event_processing_window.mm +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#import "atom/browser/ui/cocoa/event_processing_window.h" - -#include "base/logging.h" -#import "content/public/browser/render_widget_host_view_mac_base.h" - -@interface EventProcessingWindow () -// Duplicate the given key event, but changing the associated window. -- (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event; -@end - -@implementation EventProcessingWindow - -- (BOOL)redispatchKeyEvent:(NSEvent*)event { - DCHECK(event); - NSEventType eventType = [event type]; - if (eventType != NSKeyDown && - eventType != NSKeyUp && - eventType != NSFlagsChanged) { - NOTREACHED(); - return YES; // Pretend it's been handled in an effort to limit damage. - } - - // Ordinarily, the event's window should be this window. However, when - // switching between normal and fullscreen mode, we switch out the window, and - // the event's window might be the previous window (or even an earlier one if - // the renderer is running slowly and several mode switches occur). In this - // rare case, we synthesize a new key event so that its associate window - // (number) is our own. - if ([event window] != self) - event = [self keyEventForWindow:self fromKeyEvent:event]; - - // Redispatch the event. - eventHandled_ = YES; - redispatchingEvent_ = YES; - [NSApp sendEvent:event]; - redispatchingEvent_ = NO; - - // If the event was not handled by [NSApp sendEvent:], the sendEvent: - // method below will be called, and because |redispatchingEvent_| is YES, - // |eventHandled_| will be set to NO. - return eventHandled_; -} - -- (void)sendEvent:(NSEvent*)event { - if (!redispatchingEvent_) - [super sendEvent:event]; - else - eventHandled_ = NO; -} - -- (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event { - NSEventType eventType = [event type]; - - // Convert the event's location from the original window's coordinates into - // our own. - NSPoint eventLoc = [event locationInWindow]; - eventLoc = [self convertRectFromScreen: - [[event window] convertRectToScreen:NSMakeRect(eventLoc.x, eventLoc.y, 0, 0)]].origin; - - // Various things *only* apply to key down/up. - BOOL eventIsARepeat = NO; - NSString* eventCharacters = nil; - NSString* eventUnmodCharacters = nil; - if (eventType == NSKeyDown || eventType == NSKeyUp) { - eventIsARepeat = [event isARepeat]; - eventCharacters = [event characters]; - eventUnmodCharacters = [event charactersIgnoringModifiers]; - } - - // This synthesis may be slightly imperfect: we provide nil for the context, - // since I (viettrungluu) am sceptical that putting in the original context - // (if one is given) is valid. - return [NSEvent keyEventWithType:eventType - location:eventLoc - modifierFlags:[event modifierFlags] - timestamp:[event timestamp] - windowNumber:[window windowNumber] - context:nil - characters:eventCharacters - charactersIgnoringModifiers:eventUnmodCharacters - isARepeat:eventIsARepeat - keyCode:[event keyCode]]; -} - - -- (BOOL)performKeyEquivalent:(NSEvent*)event { - if (redispatchingEvent_) - return NO; - - // Give the web site a chance to handle the event. If it doesn't want to - // handle it, it will call us back with one of the |handle*| methods above. - NSResponder* r = [self firstResponder]; - if ([r conformsToProtocol:@protocol(RenderWidgetHostViewMacBase)]) - return [r performKeyEquivalent:event]; - - if ([super performKeyEquivalent:event]) - return YES; - - return NO; -} - -@end // EventProcessingWindow diff --git a/atom/browser/ui/message_box_gtk.cc b/atom/browser/ui/message_box_gtk.cc index 41682190e60e..de8d994e5bca 100644 --- a/atom/browser/ui/message_box_gtk.cc +++ b/atom/browser/ui/message_box_gtk.cc @@ -92,7 +92,7 @@ class GtkMessageBox { } const char* TranslateToStock(int id, const std::string& text) { - std::string lower = base::StringToLowerASCII(text); + std::string lower = base::ToLowerASCII(text); if (lower == "cancel") return GTK_STOCK_CANCEL; else if (lower == "no") diff --git a/atom/browser/ui/message_box_win.cc b/atom/browser/ui/message_box_win.cc index 697a7ad410a2..656be9f10bb2 100644 --- a/atom/browser/ui/message_box_win.cc +++ b/atom/browser/ui/message_box_win.cc @@ -34,7 +34,7 @@ struct CommonButtonID { int id; }; CommonButtonID GetCommonID(const base::string16& button) { - base::string16 lower = base::StringToLowerASCII(button); + base::string16 lower = base::ToLowerASCII(button); if (lower == L"ok") return { TDCBF_OK_BUTTON, IDOK }; else if (lower == L"yes") diff --git a/atom/browser/ui/x/x_window_utils.cc b/atom/browser/ui/x/x_window_utils.cc index f5c3f54ec123..db83753bb376 100644 --- a/atom/browser/ui/x/x_window_utils.cc +++ b/atom/browser/ui/x/x_window_utils.cc @@ -42,7 +42,7 @@ void SetWindowType(::Window xwindow, const std::string& type) { XDisplay* xdisplay = gfx::GetXDisplay(); std::string type_prefix = "_NET_WM_WINDOW_TYPE_"; ::Atom window_type = XInternAtom( - xdisplay, (type_prefix + base::StringToUpperASCII(type)).c_str(), False); + xdisplay, (type_prefix + base::ToUpperASCII(type)).c_str(), False); XChangeProperty(xdisplay, xwindow, XInternAtom(xdisplay, "_NET_WM_WINDOW_TYPE", False), XA_ATOM, diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 83145368c5fe..3d86df96dd76 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -36,8 +36,6 @@ FeaturePair kWebRuntimeFeatures[] = { switches::kExperimentalCanvasFeatures }, { options::kOverlayScrollbars, switches::kOverlayScrollbars }, - { options::kOverlayFullscreenVideo, - switches::kOverlayFullscreenVideo }, { options::kSharedWorker, switches::kSharedWorker }, { options::kPageVisibility, @@ -148,8 +146,6 @@ void WebContentsPreferences::OverrideWebkitPrefs( prefs->javascript_enabled = b; if (self->web_preferences_.GetBoolean("images", &b)) prefs->images_enabled = b; - if (self->web_preferences_.GetBoolean("java", &b)) - prefs->java_enabled = b; if (self->web_preferences_.GetBoolean("textAreasAreResizable", &b)) prefs->text_areas_are_resizable = b; if (self->web_preferences_.GetBoolean("webgl", &b)) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index e0f0940a7420..a810069e71b9 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -63,7 +63,8 @@ float GetScaleFactorFromPath(const base::FilePath& path) { // We don't try to convert string to float here because it is very very // expensive. for (unsigned i = 0; i < arraysize(kScaleFactorPairs); ++i) { - if (base::EndsWith(filename, kScaleFactorPairs[i].name, true)) + if (base::EndsWith(filename, kScaleFactorPairs[i].name, + base::CompareCase::INSENSITIVE_ASCII)) return kScaleFactorPairs[i].scale; } diff --git a/atom/common/api/event_emitter_caller.cc b/atom/common/api/event_emitter_caller.cc index 94eb9ce9e79a..4b44553d3740 100644 --- a/atom/common/api/event_emitter_caller.cc +++ b/atom/common/api/event_emitter_caller.cc @@ -19,7 +19,7 @@ v8::Local CallEmitWithArgs(v8::Isolate* isolate, // Perform microtask checkpoint after running JavaScript. scoped_ptr script_scope( Locker::IsBrowserProcess() ? - nullptr : new blink::WebScopedRunV8Script(isolate)); + nullptr : new blink::WebScopedRunV8Script); // Use node::MakeCallback to call the callback, and it will also run pending // tasks in Node.js. return node::MakeCallback( diff --git a/atom/common/crash_reporter/crash_reporter.cc b/atom/common/crash_reporter/crash_reporter.cc index b87ce54acd51..f4f0ff9b7b16 100644 --- a/atom/common/crash_reporter/crash_reporter.cc +++ b/atom/common/crash_reporter/crash_reporter.cc @@ -48,11 +48,11 @@ CrashReporter::GetUploadedReports(const std::string& path) { std::vector result; if (base::ReadFileToString(base::FilePath::FromUTF8Unsafe(path), &file_content)) { - std::vector reports; - base::SplitString(file_content, '\n', &reports); + std::vector reports = base::SplitString( + file_content, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); for (const std::string& report : reports) { - std::vector report_item; - base::SplitString(report, ',', &report_item); + std::vector report_item = base::SplitString( + report, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); int report_time = 0; if (report_item.size() >= 2 && base::StringToInt(report_item[0], &report_time)) { diff --git a/atom/common/crash_reporter/crash_reporter_linux.cc b/atom/common/crash_reporter/crash_reporter_linux.cc index 8a5608dad0cb..6fe69f486956 100644 --- a/atom/common/crash_reporter/crash_reporter_linux.cc +++ b/atom/common/crash_reporter/crash_reporter_linux.cc @@ -130,7 +130,7 @@ bool CrashReporterLinux::CrashDone(const MinidumpDescriptor& minidump, // static CrashReporterLinux* CrashReporterLinux::GetInstance() { - return Singleton::get(); + return base::Singleton::get(); } // static diff --git a/atom/common/crash_reporter/crash_reporter_linux.h b/atom/common/crash_reporter/crash_reporter_linux.h index 2f7d639e9075..165c288ab2b1 100644 --- a/atom/common/crash_reporter/crash_reporter_linux.h +++ b/atom/common/crash_reporter/crash_reporter_linux.h @@ -12,7 +12,9 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" +namespace base { template struct DefaultSingletonTraits; +} namespace google_breakpad { class ExceptionHandler; @@ -34,7 +36,7 @@ class CrashReporterLinux : public CrashReporter { void SetUploadParameters() override; private: - friend struct DefaultSingletonTraits; + friend struct base::DefaultSingletonTraits; CrashReporterLinux(); virtual ~CrashReporterLinux(); diff --git a/atom/common/crash_reporter/crash_reporter_mac.h b/atom/common/crash_reporter/crash_reporter_mac.h index cbdb3c65feb1..f03154359155 100644 --- a/atom/common/crash_reporter/crash_reporter_mac.h +++ b/atom/common/crash_reporter/crash_reporter_mac.h @@ -14,7 +14,9 @@ #include "base/strings/string_piece.h" #include "vendor/crashpad/client/simple_string_dictionary.h" +namespace base { template struct DefaultSingletonTraits; +} namespace crash_reporter { @@ -31,7 +33,7 @@ class CrashReporterMac : public CrashReporter { void SetUploadParameters() override; private: - friend struct DefaultSingletonTraits; + friend struct base::DefaultSingletonTraits; CrashReporterMac(); virtual ~CrashReporterMac(); diff --git a/atom/common/crash_reporter/crash_reporter_mac.mm b/atom/common/crash_reporter/crash_reporter_mac.mm index 00f37cc3febb..74ac70125b7d 100644 --- a/atom/common/crash_reporter/crash_reporter_mac.mm +++ b/atom/common/crash_reporter/crash_reporter_mac.mm @@ -126,7 +126,7 @@ CrashReporterMac::GetUploadedReports(const std::string& path) { // static CrashReporterMac* CrashReporterMac::GetInstance() { - return Singleton::get(); + return base::Singleton::get(); } // static diff --git a/atom/common/crash_reporter/crash_reporter_win.cc b/atom/common/crash_reporter/crash_reporter_win.cc index 240c229ca4b6..49a5ad8021ea 100644 --- a/atom/common/crash_reporter/crash_reporter_win.cc +++ b/atom/common/crash_reporter/crash_reporter_win.cc @@ -259,7 +259,7 @@ google_breakpad::CustomClientInfo* CrashReporterWin::GetCustomInfo( // static CrashReporterWin* CrashReporterWin::GetInstance() { - return Singleton::get(); + return base::Singleton::get(); } // static diff --git a/atom/common/crash_reporter/crash_reporter_win.h b/atom/common/crash_reporter/crash_reporter_win.h index 09c7ff4eaad6..181c9eabd23c 100644 --- a/atom/common/crash_reporter/crash_reporter_win.h +++ b/atom/common/crash_reporter/crash_reporter_win.h @@ -13,7 +13,9 @@ #include "base/memory/scoped_ptr.h" #include "vendor/breakpad/src/client/windows/handler/exception_handler.h" +namespace base { template struct DefaultSingletonTraits; +} namespace crash_reporter { @@ -33,7 +35,7 @@ class CrashReporterWin : public CrashReporter { int CrashForException(EXCEPTION_POINTERS* info); private: - friend struct DefaultSingletonTraits; + friend struct base::DefaultSingletonTraits; CrashReporterWin(); virtual ~CrashReporterWin(); diff --git a/atom/common/native_mate_converters/blink_converter.cc b/atom/common/native_mate_converters/blink_converter.cc index 2c871276ba26..d192018da012 100644 --- a/atom/common/native_mate_converters/blink_converter.cc +++ b/atom/common/native_mate_converters/blink_converter.cc @@ -45,7 +45,7 @@ template<> struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Handle val, blink::WebInputEvent::Type* out) { - std::string type = base::StringToLowerASCII(V8ToString(val)); + std::string type = base::ToLowerASCII(V8ToString(val)); if (type == "mousedown") *out = blink::WebInputEvent::MouseDown; else if (type == "mouseup") @@ -82,7 +82,7 @@ template<> struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Handle val, blink::WebMouseEvent::Button* out) { - std::string button = base::StringToLowerASCII(V8ToString(val)); + std::string button = base::ToLowerASCII(V8ToString(val)); if (button == "left") *out = blink::WebMouseEvent::Button::ButtonLeft; else if (button == "middle") @@ -97,7 +97,7 @@ template<> struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Handle val, blink::WebInputEvent::Modifiers* out) { - std::string modifier = base::StringToLowerASCII(V8ToString(val)); + std::string modifier = base::ToLowerASCII(V8ToString(val)); if (modifier == "shift") *out = blink::WebInputEvent::ShiftKey; else if (modifier == "control" || modifier == "ctrl") @@ -166,7 +166,7 @@ bool Converter::FromV8( out->windowsKeyCode = atom::KeyboardCodeFromCharCode(code, &shifted); else if (dict.Get("keyCode", &identifier)) out->windowsKeyCode = atom::KeyboardCodeFromKeyIdentifier( - base::StringToLowerASCII(identifier)); + base::ToLowerASCII(identifier)); else return false; @@ -263,7 +263,7 @@ bool Converter::FromV8( std::string screen_position; if (dict.Get("screenPosition", &screen_position)) { - screen_position = base::StringToLowerASCII(screen_position); + screen_position = base::ToLowerASCII(screen_position); if (screen_position == "mobile") out->screenPosition = blink::WebDeviceEmulationParams::Mobile; else if (screen_position == "desktop") diff --git a/atom/common/native_mate_converters/callback.h b/atom/common/native_mate_converters/callback.h index 3cba2b32a820..6ef8e74c735a 100644 --- a/atom/common/native_mate_converters/callback.h +++ b/atom/common/native_mate_converters/callback.h @@ -51,7 +51,7 @@ struct V8FunctionInvoker(ArgTypes...)> { return v8::Null(isolate); scoped_ptr script_scope( Locker::IsBrowserProcess() ? - nullptr : new blink::WebScopedRunV8Script(isolate)); + nullptr : new blink::WebScopedRunV8Script); v8::Local holder = function.NewHandle(isolate); v8::Local context = holder->CreationContext(); v8::Context::Scope context_scope(context); @@ -72,7 +72,7 @@ struct V8FunctionInvoker { return; scoped_ptr script_scope( Locker::IsBrowserProcess() ? - nullptr : new blink::WebScopedRunV8Script(isolate)); + nullptr : new blink::WebScopedRunV8Script); v8::Local holder = function.NewHandle(isolate); v8::Local context = holder->CreationContext(); v8::Context::Scope context_scope(context); @@ -93,7 +93,7 @@ struct V8FunctionInvoker { return ret; scoped_ptr script_scope( Locker::IsBrowserProcess() ? - nullptr : new blink::WebScopedRunV8Script(isolate)); + nullptr : new blink::WebScopedRunV8Script); v8::Local holder = function.NewHandle(isolate); v8::Local context = holder->CreationContext(); v8::Context::Scope context_scope(context); diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index dbd0bd8d96ee..04a0c9139e28 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -227,7 +227,7 @@ void NodeBindings::UvRunOnce() { // Perform microtask checkpoint after running JavaScript. scoped_ptr script_scope( - is_browser_ ? nullptr : new blink::WebScopedRunV8Script(env->isolate())); + is_browser_ ? nullptr : new blink::WebScopedRunV8Script); // Deal with uv events. int r = uv_run(uv_loop_, UV_RUN_NOWAIT); diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 1124cfba4bac..a0cb8384a340 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -95,7 +95,6 @@ const char kDirectWrite[] = "directWrite"; const char kExperimentalFeatures[] = "experimentalFeatures"; const char kExperimentalCanvasFeatures[] = "experimentalCanvasFeatures"; const char kOverlayScrollbars[] = "overlayScrollbars"; -const char kOverlayFullscreenVideo[] = "overlayFullscreenVideo"; const char kSharedWorker[] = "sharedWorker"; } // namespace options @@ -139,7 +138,6 @@ const char kGuestInstanceID[] = "guest-instance-id"; const char kExperimentalFeatures[] = "experimental-features"; const char kExperimentalCanvasFeatures[] = "experimental-canvas-features"; const char kOverlayScrollbars[] = "overlay-scrollbars"; -const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video"; const char kSharedWorker[] = "shared-worker"; const char kPageVisibility[] = "page-visiblity"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index cd52c97597c9..6960db83bc10 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -50,7 +50,6 @@ extern const char kGuestInstanceID[]; extern const char kExperimentalFeatures[]; extern const char kExperimentalCanvasFeatures[]; extern const char kOverlayScrollbars[]; -extern const char kOverlayFullscreenVideo[]; extern const char kSharedWorker[]; extern const char kPageVisibility[]; @@ -79,7 +78,6 @@ extern const char kGuestInstanceID[]; extern const char kExperimentalFeatures[]; extern const char kExperimentalCanvasFeatures[]; extern const char kOverlayScrollbars[]; -extern const char kOverlayFullscreenVideo[]; extern const char kSharedWorker[]; extern const char kPageVisibility[]; diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 362b0b8026a7..7c04c04249a7 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -226,8 +226,6 @@ void AtomRendererClient::EnableWebRuntimeFeatures() { blink::WebRuntimeFeatures::enableExperimentalCanvasFeatures(true); if (IsSwitchEnabled(command_line, switches::kOverlayScrollbars)) blink::WebRuntimeFeatures::enableOverlayScrollbars(true); - if (IsSwitchEnabled(command_line, switches::kOverlayFullscreenVideo)) - blink::WebRuntimeFeatures::enableOverlayFullscreenVideo(true); if (IsSwitchEnabled(command_line, switches::kSharedWorker)) blink::WebRuntimeFeatures::enableSharedWorker(true); } diff --git a/chromium_src/chrome/browser/printing/print_view_manager_base.cc b/chromium_src/chrome/browser/printing/print_view_manager_base.cc index 35c62fbc5327..ede1d3b8ba8c 100644 --- a/chromium_src/chrome/browser/printing/print_view_manager_base.cc +++ b/chromium_src/chrome/browser/printing/print_view_manager_base.cc @@ -410,7 +410,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() { // be CPU bound, the page overly complex/large or the system just // memory-bound. static const int kPrinterSettingsTimeout = 60000; - base::OneShotTimer quit_timer; + base::OneShotTimer quit_timer; quit_timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(kPrinterSettingsTimeout), base::MessageLoop::current(), &base::MessageLoop::Quit); diff --git a/chromium_src/chrome/browser/process_singleton_posix.cc b/chromium_src/chrome/browser/process_singleton_posix.cc index b03ce431e47e..98fb948730e0 100644 --- a/chromium_src/chrome/browser/process_singleton_posix.cc +++ b/chromium_src/chrome/browser/process_singleton_posix.cc @@ -503,7 +503,7 @@ class ProcessSingleton::LinuxWatcher // reads. size_t bytes_read_; - base::OneShotTimer timer_; + base::OneShotTimer timer_; DISALLOW_COPY_AND_ASSIGN(SocketReader); }; diff --git a/chromium_src/chrome/browser/speech/tts_controller_impl.cc b/chromium_src/chrome/browser/speech/tts_controller_impl.cc index 6b66b6a61960..610ce1656759 100644 --- a/chromium_src/chrome/browser/speech/tts_controller_impl.cc +++ b/chromium_src/chrome/browser/speech/tts_controller_impl.cc @@ -111,7 +111,7 @@ TtsController* TtsController::GetInstance() { // static TtsControllerImpl* TtsControllerImpl::GetInstance() { - return Singleton::get(); + return base::Singleton::get(); } TtsControllerImpl::TtsControllerImpl() diff --git a/chromium_src/chrome/browser/speech/tts_controller_impl.h b/chromium_src/chrome/browser/speech/tts_controller_impl.h index 651f836cdf6c..6c8aa5747d20 100644 --- a/chromium_src/chrome/browser/speech/tts_controller_impl.h +++ b/chromium_src/chrome/browser/speech/tts_controller_impl.h @@ -77,7 +77,7 @@ class TtsControllerImpl : public TtsController { int GetMatchingVoice(const Utterance* utterance, std::vector& voices); - friend struct DefaultSingletonTraits; + friend struct base::DefaultSingletonTraits; // The current utterance being spoken. Utterance* current_utterance_; @@ -101,4 +101,4 @@ class TtsControllerImpl : public TtsController { DISALLOW_COPY_AND_ASSIGN(TtsControllerImpl); }; -#endif // CHROME_BROWSER_SPEECH_TTS_CONTROLLER_IMPL_H_ \ No newline at end of file +#endif // CHROME_BROWSER_SPEECH_TTS_CONTROLLER_IMPL_H_ diff --git a/chromium_src/chrome/browser/speech/tts_mac.mm b/chromium_src/chrome/browser/speech/tts_mac.mm index acfa5b58bf3b..aafbd4692515 100644 --- a/chromium_src/chrome/browser/speech/tts_mac.mm +++ b/chromium_src/chrome/browser/speech/tts_mac.mm @@ -91,7 +91,7 @@ class TtsPlatformImplMac : public TtsPlatformImpl { int last_char_index_; bool paused_; - friend struct DefaultSingletonTraits; + friend struct base::DefaultSingletonTraits; DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplMac); }; @@ -291,7 +291,7 @@ TtsPlatformImplMac::~TtsPlatformImplMac() { // static TtsPlatformImplMac* TtsPlatformImplMac::GetInstance() { - return Singleton::get(); + return base::Singleton::get(); } @implementation ChromeTtsDelegate diff --git a/chromium_src/chrome/renderer/pepper/pepper_flash_renderer_host.cc b/chromium_src/chrome/renderer/pepper/pepper_flash_renderer_host.cc index fe5e28ebbeb8..66edd3f938ad 100644 --- a/chromium_src/chrome/renderer/pepper/pepper_flash_renderer_host.cc +++ b/chromium_src/chrome/renderer/pepper/pepper_flash_renderer_host.cc @@ -29,7 +29,6 @@ #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPoint.h" -#include "third_party/skia/include/core/SkTemplates.h" #include "third_party/skia/include/core/SkTypeface.h" #include "ui/gfx/geometry/rect.h" #include "url/gurl.h" @@ -315,7 +314,7 @@ int32_t PepperFlashRendererHost::OnNavigate( bool rejected = false; while (header_iter.GetNext()) { std::string lower_case_header_name = - base::StringToLowerASCII(header_iter.name()); + base::ToLowerASCII(header_iter.name()); if (!IsSimpleHeader(lower_case_header_name, header_iter.values())) { rejected = true; diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper.cc b/chromium_src/chrome/renderer/printing/print_web_view_helper.cc index 20ac1fdc9b4f..3bfe719a0c92 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper.cc +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper.cc @@ -544,7 +544,6 @@ void PrepareFrameAndViewForPrint::CopySelection( // on the page). WebPreferences prefs = preferences; prefs.javascript_enabled = false; - prefs.java_enabled = false; blink::WebView* web_view = blink::WebView::create(this); owns_web_view_ = true; diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index a987e2924615..db02b6aa14b3 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -123,7 +123,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `allowRunningInsecureContent` Boolean - Allow a https page to run JavaScript, CSS or plugins from http URLs. Default is `false`. * `images` Boolean - Enables image support. Default is `true`. - * `java` Boolean - Enables Java support. Default is `false`. * `textAreasAreResizable` Boolean - Make TextArea elements resizable. Default is `true`. * `webgl` Boolean - Enables WebGL support. Default is `true`. @@ -135,8 +134,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. canvas features. Default is `false`. * `overlayScrollbars` Boolean - Enables overlay scrollbars. Default is `false`. - * `overlayFullscreenVideo` Boolean - Enables overlay fullscreen video. Default - is `false` * `sharedWorker` Boolean - Enables Shared Worker support. Default is `false`. * `directWrite` Boolean - Enables DirectWrite font rendering system on Windows. Default is `true`. diff --git a/filenames.gypi b/filenames.gypi index 151a69ff1c9e..5e44ad7d713c 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -200,8 +200,6 @@ 'atom/browser/ui/atom_menu_model.h', 'atom/browser/ui/cocoa/atom_menu_controller.h', 'atom/browser/ui/cocoa/atom_menu_controller.mm', - 'atom/browser/ui/cocoa/event_processing_window.h', - 'atom/browser/ui/cocoa/event_processing_window.mm', 'atom/browser/ui/file_dialog.h', 'atom/browser/ui/file_dialog_gtk.cc', 'atom/browser/ui/file_dialog_mac.mm', diff --git a/vendor/brightray b/vendor/brightray index 57842edb817c..fff0f0e2d398 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 57842edb817cc1ae38a02fd7f266dd6aa3afbb45 +Subproject commit fff0f0e2d39886a49fce4f78aa3b625b880b3607 From 95e7c796ec28e805a979004ba6912d1d87d8acab Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 7 Dec 2015 20:48:39 +0800 Subject: [PATCH 722/738] V8 now checks strictly when callin Neuter() --- script/lib/config.py | 2 +- vendor/node | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/lib/config.py b/script/lib/config.py index 4978302abb0f..159839c7f559 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = 'd534691711ecdef1739878674a9ffd5f2d5ac4a2' +LIBCHROMIUMCONTENT_COMMIT = '451ea93cc3090f7000f8f0daa4cb84e90ad6c842' PLATFORM = { 'cygwin': 'win32', diff --git a/vendor/node b/vendor/node index 1445826ca73c..97d9298d8a43 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 1445826ca73cc79bc57d503dd11d4ffaf695625c +Subproject commit 97d9298d8a431f27e2aded918ae9f2a673c9cf6f From 647f151906dc46bc3be4b188294ccc389617b7e2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 7 Dec 2015 21:25:19 +0800 Subject: [PATCH 723/738] Fix the failing sendSync --- atom/renderer/api/lib/remote.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index 48cdd937fb07..357b88406930 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -119,7 +119,11 @@ metaToPlainObject = (meta) -> # Browser calls a callback in renderer. ipcRenderer.on 'ATOM_RENDERER_CALLBACK', (event, id, args) -> - callbacksRegistry.apply id, metaToValue(args) + # Delay the callback to next tick in case the browser is still in the middle + # of sending this message while the callback sends a sync message to browser, + # which can fail sometimes. + setImmediate -> + callbacksRegistry.apply id, metaToValue(args) # A callback in browser is released. ipcRenderer.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) -> From 27dd233820ccc7b8e1cd4a56982c9d31f3f4cd13 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 7 Dec 2015 21:28:58 +0800 Subject: [PATCH 724/738] spec: Make the "remote listeners" test more reliable --- spec/api-ipc-spec.coffee | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/spec/api-ipc-spec.coffee b/spec/api-ipc-spec.coffee index a8d2a65cdef7..1aa715c9f759 100644 --- a/spec/api-ipc-spec.coffee +++ b/spec/api-ipc-spec.coffee @@ -89,14 +89,14 @@ describe 'ipc module', -> w.loadURL 'file://' + path.join(fixtures, 'api', 'send-sync-message.html') describe 'remote listeners', -> - it 'can be added and removed correctly', -> - count = 0 - w = new BrowserWindow(show: false) - listener = () -> - count += 1 - w.removeListener 'blur', listener - w.on 'blur', listener - w.emit 'blur' - w.emit 'blur' - assert.equal count, 1 + w = null + afterEach -> w.destroy() + + it 'can be added and removed correctly', -> + w = new BrowserWindow(show: false) + listener = -> + w.on 'test', listener + assert.equal w.listenerCount('test'), 1 + w.removeListener 'test', listener + assert.equal w.listenerCount('test'), 0 From d0be6c74116e92b667213c1740ff57014aceee66 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 7 Dec 2015 22:44:35 +0800 Subject: [PATCH 725/738] Fix cppling warning --- atom/browser/atom_browser_context.cc | 3 ++- vendor/brightray | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index b9589d569b68..ec123825822e 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -86,7 +86,8 @@ std::string AtomBrowserContext::GetUserAgent() { return content::BuildUserAgentFromProduct(user_agent); } -scoped_ptr AtomBrowserContext::CreateURLRequestJobFactory( +scoped_ptr +AtomBrowserContext::CreateURLRequestJobFactory( content::ProtocolHandlerMap* handlers, content::URLRequestInterceptorScopedVector* interceptors) { scoped_ptr job_factory(job_factory_); diff --git a/vendor/brightray b/vendor/brightray index fff0f0e2d398..878e63860b59 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit fff0f0e2d39886a49fce4f78aa3b625b880b3607 +Subproject commit 878e63860b59d3443cd9f739d7533f2be1109773 From 3931ebb7ef4b38867440315b07b2796a05da411f Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 7 Dec 2015 10:02:06 -0800 Subject: [PATCH 726/738] Fix up Windows build errors --- atom/browser/browser_win.cc | 2 +- atom/browser/ui/file_dialog_win.cc | 6 ++++-- atom/common/crash_reporter/crash_reporter_win.cc | 4 ++-- atom/common/crash_reporter/win/crash_service.cc | 5 ++--- atom/common/crash_reporter/win/crash_service_main.cc | 2 +- chromium_src/chrome/browser/speech/tts_win.cc | 8 ++++---- .../renderer/printing/print_web_view_helper_pdf_win.cc | 1 - .../net/test/embedded_test_server/stream_listen_socket.cc | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/atom/browser/browser_win.cc b/atom/browser/browser_win.cc index ce36d56b620c..fdf4bd8c3bbe 100644 --- a/atom/browser/browser_win.cc +++ b/atom/browser/browser_win.cc @@ -127,7 +127,7 @@ void Browser::SetUserTasks(const std::vector& tasks) { PCWSTR Browser::GetAppUserModelID() { if (app_user_model_id_.empty()) { - SetAppUserModelID(ReplaceStringPlaceholders( + SetAppUserModelID(base::ReplaceStringPlaceholders( kAppUserModelIDFormat, base::UTF8ToUTF16(GetName()), nullptr)); } diff --git a/atom/browser/ui/file_dialog_win.cc b/atom/browser/ui/file_dialog_win.cc index d218beaa27f1..f39094f9dfc5 100644 --- a/atom/browser/ui/file_dialog_win.cc +++ b/atom/browser/ui/file_dialog_win.cc @@ -51,7 +51,7 @@ void ConvertFilters(const Filters& filters, std::vector extensions(filter.second); for (size_t j = 0; j < extensions.size(); ++j) extensions[j].insert(0, "*."); - buffer->push_back(base::UTF8ToWide(JoinString(extensions, ";"))); + buffer->push_back(base::UTF8ToWide(base::JoinString(extensions, ";"))); spec.pszSpec = buffer->back().c_str(); filterspec->push_back(spec); @@ -273,7 +273,9 @@ bool ShowSaveDialog(atom::NativeWindow* parent_window, bool matched = false; for (size_t i = 0; i < filter.second.size(); ++i) { if (filter.second[i] == "*" || - base::EndsWith(file_name, filter.second[i], false)) { + base::EndsWith( + file_name, filter.second[i], + base::CompareCase::INSENSITIVE_ASCII)) { matched = true; break;; } diff --git a/atom/common/crash_reporter/crash_reporter_win.cc b/atom/common/crash_reporter/crash_reporter_win.cc index 49a5ad8021ea..939a02f090c5 100644 --- a/atom/common/crash_reporter/crash_reporter_win.cc +++ b/atom/common/crash_reporter/crash_reporter_win.cc @@ -153,9 +153,9 @@ void CrashReporterWin::InitBreakpad(const std::string& product_name, return; } - base::string16 pipe_name = ReplaceStringPlaceholders( + base::string16 pipe_name = base::ReplaceStringPlaceholders( kPipeNameFormat, base::UTF8ToUTF16(product_name), NULL); - base::string16 wait_name = ReplaceStringPlaceholders( + base::string16 wait_name = base::ReplaceStringPlaceholders( kWaitEventFormat, base::UTF8ToUTF16(product_name), NULL); // Wait until the crash service is started. diff --git a/atom/common/crash_reporter/win/crash_service.cc b/atom/common/crash_reporter/win/crash_service.cc index 9b6ba7e03a65..67e22381aef8 100644 --- a/atom/common/crash_reporter/win/crash_service.cc +++ b/atom/common/crash_reporter/win/crash_service.cc @@ -118,7 +118,7 @@ HWND g_top_window = NULL; bool CreateTopWindow(HINSTANCE instance, const base::string16& application_name, bool visible) { - base::string16 class_name = ReplaceStringPlaceholders( + base::string16 class_name = base::ReplaceStringPlaceholders( kClassNameFormat, application_name, NULL); WNDCLASSEXW wcx = {0}; @@ -309,7 +309,7 @@ bool CrashService::Initialize(const base::string16& application_name, // Create or open an event to signal the browser process that the crash // service is initialized. - base::string16 wait_name = ReplaceStringPlaceholders( + base::string16 wait_name = base::ReplaceStringPlaceholders( kWaitEventFormat, application_name, NULL); HANDLE wait_event = ::CreateEventW(NULL, TRUE, TRUE, wait_name.c_str()); ::SetEvent(wait_event); @@ -524,4 +524,3 @@ PSECURITY_DESCRIPTOR CrashService::GetSecurityDescriptorForLowIntegrity() { } } // namespace breakpad - diff --git a/atom/common/crash_reporter/win/crash_service_main.cc b/atom/common/crash_reporter/win/crash_service_main.cc index 7a5eeb10133a..56d46970b67f 100644 --- a/atom/common/crash_reporter/win/crash_service_main.cc +++ b/atom/common/crash_reporter/win/crash_service_main.cc @@ -68,7 +68,7 @@ int Main(const wchar_t* cmd) { VLOG(1) << "Session start. cmdline is [" << cmd << "]"; // Setting the crash reporter. - base::string16 pipe_name = ReplaceStringPlaceholders(kPipeNameFormat, + base::string16 pipe_name = base::ReplaceStringPlaceholders(kPipeNameFormat, application_name, NULL); cmd_line.AppendSwitch("no-window"); diff --git a/chromium_src/chrome/browser/speech/tts_win.cc b/chromium_src/chrome/browser/speech/tts_win.cc index c7b0a0ca724c..89a8f413e5dd 100644 --- a/chromium_src/chrome/browser/speech/tts_win.cc +++ b/chromium_src/chrome/browser/speech/tts_win.cc @@ -57,7 +57,7 @@ class TtsPlatformImplWin : public TtsPlatformImpl { int char_position_; bool paused_; - friend struct DefaultSingletonTraits; + friend struct base::DefaultSingletonTraits; DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplWin); }; @@ -246,12 +246,12 @@ TtsPlatformImplWin::TtsPlatformImplWin() // static TtsPlatformImplWin* TtsPlatformImplWin::GetInstance() { - return Singleton >::get(); + return base::Singleton< TtsPlatformImplWin, + base::LeakySingletonTraits >::get(); } // static void TtsPlatformImplWin::SpeechEventCallback( WPARAM w_param, LPARAM l_param) { GetInstance()->OnSpeechEvent(); -} \ No newline at end of file +} diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc b/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc index dcd388fd1111..5b34ff309043 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc @@ -135,7 +135,6 @@ bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, printed_page_params.page_size = page_size_in_dpi[i]; printed_page_params.content_area = content_area_in_dpi[i]; Send(new PrintHostMsg_DidPrintPage(routing_id(), printed_page_params)); - printed_page_params.metafile_data_handle = INVALID_HANDLE_VALUE; } return true; } diff --git a/chromium_src/net/test/embedded_test_server/stream_listen_socket.cc b/chromium_src/net/test/embedded_test_server/stream_listen_socket.cc index 1056983a8e2f..897b23bbd56e 100644 --- a/chromium_src/net/test/embedded_test_server/stream_listen_socket.cc +++ b/chromium_src/net/test/embedded_test_server/stream_listen_socket.cc @@ -228,7 +228,7 @@ void StreamListenSocket::CloseSocket() { void StreamListenSocket::WatchSocket(WaitState state) { #if defined(OS_WIN) WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ); - watcher_.StartWatching(socket_event_, this); + watcher_.StartWatchingOnce(socket_event_, this); #elif defined(OS_POSIX) // Implicitly calls StartWatchingFileDescriptor(). base::MessageLoopForIO::current()->WatchFileDescriptor( @@ -264,7 +264,7 @@ void StreamListenSocket::OnObjectSignaled(HANDLE object) { return; } // The object was reset by WSAEnumNetworkEvents. Watch for the next signal. - watcher_.StartWatching(object, this); + watcher_.StartWatchingOnce(object, this); if (ev.lNetworkEvents == 0) { // Occasionally the event is set even though there is no new data. From af289001898f80feddc5d8af62b6f3c0442dcaba Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 7 Dec 2015 13:27:05 -0800 Subject: [PATCH 727/738] Fix up Chrome47 changes --- atom/browser/ui/file_dialog_gtk.cc | 4 +++- atom/browser/ui/views/menu_bar.cc | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/atom/browser/ui/file_dialog_gtk.cc b/atom/browser/ui/file_dialog_gtk.cc index 5885ffe3611c..ed79449655f0 100644 --- a/atom/browser/ui/file_dialog_gtk.cc +++ b/atom/browser/ui/file_dialog_gtk.cc @@ -22,7 +22,9 @@ gboolean FileFilterCaseInsensitive(const GtkFileFilterInfo* file_info, // Makes .* file extension matches all file types. if (*file_extension == ".*") return true; - return base::EndsWith(file_info->filename, *file_extension, false); + return base::EndsWith( + file_info->filename, + *file_extension, base::CompareCase::INSENSITIVE_ASCII); } // Deletes |data| when gtk_file_filter_add_custom() is done with it. diff --git a/atom/browser/ui/views/menu_bar.cc b/atom/browser/ui/views/menu_bar.cc index d3059a50a41b..b7712929d024 100644 --- a/atom/browser/ui/views/menu_bar.cc +++ b/atom/browser/ui/views/menu_bar.cc @@ -17,7 +17,6 @@ #if defined(OS_WIN) #include "ui/gfx/color_utils.h" #elif defined(USE_X11) -#include "chrome/browser/ui/libgtk2ui/owned_widget_gtk2.h" #include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h" #endif @@ -33,15 +32,16 @@ const SkColor kDefaultColor = SkColorSetARGB(255, 233, 233, 233); #if defined(USE_X11) void GetMenuBarColor(SkColor* enabled, SkColor* disabled, SkColor* highlight, SkColor* hover, SkColor* background) { - libgtk2ui::OwnedWidgetGtk fake_menu_bar; - fake_menu_bar.Own(gtk_menu_bar_new()); + GtkWidget* menu_bar = gtk_menu_bar_new(); - GtkStyle* style = gtk_rc_get_style(fake_menu_bar.get()); + GtkStyle* style = gtk_rc_get_style(menu_bar); *enabled = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_NORMAL]); *disabled = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_INSENSITIVE]); *highlight = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_SELECTED]); *hover = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_PRELIGHT]); *background = libgtk2ui::GdkColorToSkColor(style->bg[GTK_STATE_NORMAL]); + + gtk_widget_destroy(menu_bar); } #endif From 8d5c153e9bbd5e324f2cb14fc87158044890d5d6 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 7 Dec 2015 14:23:01 -0800 Subject: [PATCH 728/738] Update to Chrome 47 version of tts_win --- chromium_src/chrome/browser/speech/tts_win.cc | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/chromium_src/chrome/browser/speech/tts_win.cc b/chromium_src/chrome/browser/speech/tts_win.cc index 89a8f413e5dd..ac2582058894 100644 --- a/chromium_src/chrome/browser/speech/tts_win.cc +++ b/chromium_src/chrome/browser/speech/tts_win.cc @@ -15,26 +15,26 @@ class TtsPlatformImplWin : public TtsPlatformImpl { public: - virtual bool PlatformImplAvailable() { + bool PlatformImplAvailable() override { return true; } - virtual bool Speak( + bool Speak( int utterance_id, const std::string& utterance, const std::string& lang, const VoiceData& voice, - const UtteranceContinuousParameters& params); + const UtteranceContinuousParameters& params) override; - virtual bool StopSpeaking(); + bool StopSpeaking() override; - virtual void Pause(); + void Pause() override; - virtual void Resume(); + void Resume() override; - virtual bool IsSpeaking(); + bool IsSpeaking() override; - virtual void GetVoices(std::vector* out_voices) override; + void GetVoices(std::vector* out_voices) override; // Get the single instance of this class. static TtsPlatformImplWin* GetInstance(); @@ -43,7 +43,7 @@ class TtsPlatformImplWin : public TtsPlatformImpl { private: TtsPlatformImplWin(); - virtual ~TtsPlatformImplWin() {} + ~TtsPlatformImplWin() override {} void OnSpeechEvent(); @@ -220,6 +220,8 @@ void TtsPlatformImplWin::OnSpeechEvent() { utterance_id_, TTS_EVENT_SENTENCE, char_position_, std::string()); break; + default: + break; } } } @@ -246,8 +248,8 @@ TtsPlatformImplWin::TtsPlatformImplWin() // static TtsPlatformImplWin* TtsPlatformImplWin::GetInstance() { - return base::Singleton< TtsPlatformImplWin, - base::LeakySingletonTraits >::get(); + return base::Singleton>::get(); } // static From 4a8d58f9141610fa6986618f9d374f30bfc16d7b Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 7 Dec 2015 14:25:52 -0800 Subject: [PATCH 729/738] Update to Chrome47 version of GlobalMenuBarRegistrarX11 --- .../frame/global_menu_bar_registrar_x11.cc | 28 +++++++++---------- .../frame/global_menu_bar_registrar_x11.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc b/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc index 0d2a6dd73824..3913325f21ca 100644 --- a/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc +++ b/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc @@ -21,7 +21,7 @@ const char kAppMenuRegistrarPath[] = "/com/canonical/AppMenu/Registrar"; // static GlobalMenuBarRegistrarX11* GlobalMenuBarRegistrarX11::GetInstance() { - return Singleton::get(); + return base::Singleton::get(); } void GlobalMenuBarRegistrarX11::OnWindowMapped(unsigned long xid) { @@ -39,7 +39,7 @@ void GlobalMenuBarRegistrarX11::OnWindowUnmapped(unsigned long xid) { } GlobalMenuBarRegistrarX11::GlobalMenuBarRegistrarX11() - : registrar_proxy_(NULL) { + : registrar_proxy_(nullptr) { // libdbusmenu uses the gio version of dbus; I tried using the code in dbus/, // but it looks like that's isn't sharing the bus name with the gio version, // even when |connection_type| is set to SHARED. @@ -49,11 +49,11 @@ GlobalMenuBarRegistrarX11::GlobalMenuBarRegistrarX11() G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START), - NULL, + nullptr, kAppMenuRegistrarName, kAppMenuRegistrarPath, kAppMenuRegistrarName, - NULL, // TODO: Probalby want a real cancelable. + nullptr, // TODO: Probalby want a real cancelable. static_cast(OnProxyCreatedThunk), this); } @@ -70,7 +70,7 @@ GlobalMenuBarRegistrarX11::~GlobalMenuBarRegistrarX11() { void GlobalMenuBarRegistrarX11::RegisterXID(unsigned long xid) { DCHECK(registrar_proxy_); - std::string path = atom::GlobalMenuBarX11::GetPathForWindow(xid); + std::string path = GlobalMenuBarX11::GetPathForWindow(xid); ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/314087 // TODO(erg): The mozilla implementation goes to a lot of callback trouble @@ -84,14 +84,14 @@ void GlobalMenuBarRegistrarX11::RegisterXID(unsigned long xid) { "RegisterWindow", g_variant_new("(uo)", xid, path.c_str()), G_DBUS_CALL_FLAGS_NONE, -1, - NULL, - NULL, - NULL); + nullptr, + nullptr, + nullptr); } void GlobalMenuBarRegistrarX11::UnregisterXID(unsigned long xid) { DCHECK(registrar_proxy_); - std::string path = atom::GlobalMenuBarX11::GetPathForWindow(xid); + std::string path = GlobalMenuBarX11::GetPathForWindow(xid); ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/314087 // TODO(erg): The mozilla implementation goes to a lot of callback trouble @@ -105,14 +105,14 @@ void GlobalMenuBarRegistrarX11::UnregisterXID(unsigned long xid) { "UnregisterWindow", g_variant_new("(u)", xid), G_DBUS_CALL_FLAGS_NONE, -1, - NULL, - NULL, - NULL); + nullptr, + nullptr, + nullptr); } void GlobalMenuBarRegistrarX11::OnProxyCreated(GObject* source, GAsyncResult* result) { - GError* error = NULL; + GError* error = nullptr; GDBusProxy* proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (error) { g_error_free(error); @@ -128,7 +128,7 @@ void GlobalMenuBarRegistrarX11::OnProxyCreated(GObject* source, g_signal_connect(registrar_proxy_, "notify::g-name-owner", G_CALLBACK(OnNameOwnerChangedThunk), this); - OnNameOwnerChanged(NULL, NULL); + OnNameOwnerChanged(nullptr, nullptr); } void GlobalMenuBarRegistrarX11::OnNameOwnerChanged(GObject* /* ignored */, diff --git a/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h b/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h index e35e87c0d20c..694f776b24ef 100644 --- a/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h +++ b/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h @@ -28,7 +28,7 @@ class GlobalMenuBarRegistrarX11 { void OnWindowUnmapped(unsigned long xid); private: - friend struct DefaultSingletonTraits; + friend struct base::DefaultSingletonTraits; GlobalMenuBarRegistrarX11(); ~GlobalMenuBarRegistrarX11(); From fe86239a9c2f120a9ef1eafee89890b6a98d0d80 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 7 Dec 2015 14:28:42 -0800 Subject: [PATCH 730/738] Update to Chrome47 version of tts_linux --- .../chrome/browser/speech/tts_linux.cc | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/chromium_src/chrome/browser/speech/tts_linux.cc b/chromium_src/chrome/browser/speech/tts_linux.cc index 43b28a5eade7..ba15516ce036 100644 --- a/chromium_src/chrome/browser/speech/tts_linux.cc +++ b/chromium_src/chrome/browser/speech/tts_linux.cc @@ -13,6 +13,7 @@ #include "base/synchronization/lock.h" #include "chrome/browser/speech/tts_platform.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/content_switches.h" #include "library_loaders/libspeechd.h" @@ -32,18 +33,17 @@ struct SPDChromeVoice { class TtsPlatformImplLinux : public TtsPlatformImpl { public: - virtual bool PlatformImplAvailable() override; - virtual bool Speak( - int utterance_id, - const std::string& utterance, - const std::string& lang, - const VoiceData& voice, - const UtteranceContinuousParameters& params) override; - virtual bool StopSpeaking() override; - virtual void Pause() override; - virtual void Resume() override; - virtual bool IsSpeaking() override; - virtual void GetVoices(std::vector* out_voices) override; + bool PlatformImplAvailable() override; + bool Speak(int utterance_id, + const std::string& utterance, + const std::string& lang, + const VoiceData& voice, + const UtteranceContinuousParameters& params) override; + bool StopSpeaking() override; + void Pause() override; + void Resume() override; + bool IsSpeaking() override; + void GetVoices(std::vector* out_voices) override; void OnSpeechEvent(SPDNotificationType type); @@ -52,7 +52,7 @@ class TtsPlatformImplLinux : public TtsPlatformImpl { private: TtsPlatformImplLinux(); - virtual ~TtsPlatformImplLinux(); + ~TtsPlatformImplLinux() override; // Initiate the connection with the speech dispatcher. void Initialize(); @@ -83,7 +83,7 @@ class TtsPlatformImplLinux : public TtsPlatformImpl { // uniquely identify a voice across all available modules. scoped_ptr > all_native_voices_; - friend struct DefaultSingletonTraits; + friend struct base::DefaultSingletonTraits; DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplLinux); }; @@ -94,6 +94,11 @@ SPDNotificationType TtsPlatformImplLinux::current_notification_ = TtsPlatformImplLinux::TtsPlatformImplLinux() : utterance_id_(0) { + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + if (!command_line.HasSwitch(switches::kEnableSpeechDispatcher)) + return; + BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(&TtsPlatformImplLinux::Initialize, @@ -111,7 +116,7 @@ void TtsPlatformImplLinux::Initialize() { // http://crbug.com/317360 ANNOTATE_SCOPED_MEMORY_LEAK; conn_ = libspeechd_loader_.spd_open( - "chrome", "extension_api", NULL, SPD_MODE_SINGLE); + "chrome", "extension_api", NULL, SPD_MODE_THREADED); } if (!conn_) return; @@ -146,7 +151,7 @@ void TtsPlatformImplLinux::Reset() { if (conn_) libspeechd_loader_.spd_close(conn_); conn_ = libspeechd_loader_.spd_open( - "chrome", "extension_api", NULL, SPD_MODE_SINGLE); + "chrome", "extension_api", NULL, SPD_MODE_THREADED); } bool TtsPlatformImplLinux::PlatformImplAvailable() { @@ -187,6 +192,10 @@ bool TtsPlatformImplLinux::Speak( libspeechd_loader_.spd_set_voice_rate(conn_, 100 * log10(rate) / log10(3)); libspeechd_loader_.spd_set_voice_pitch(conn_, 100 * log10(pitch) / log10(3)); + // Support languages other than the default + if (!lang.empty()) + libspeechd_loader_.spd_set_language(conn_, lang.c_str()); + utterance_ = utterance; utterance_id_ = utterance_id; @@ -337,8 +346,9 @@ void TtsPlatformImplLinux::IndexMarkCallback(size_t msg_id, // static TtsPlatformImplLinux* TtsPlatformImplLinux::GetInstance() { - return Singleton >::get(); + return base::Singleton< + TtsPlatformImplLinux, + base::LeakySingletonTraits>::get(); } // static From 9a0cecf943a0b2985ea6508539245eb911f0f1ab Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Mon, 7 Dec 2015 14:29:11 -0800 Subject: [PATCH 731/738] Rig GlobalMenuBarRegistrarX11 for Atom --- .../browser/ui/views/frame/global_menu_bar_registrar_x11.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc b/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc index 3913325f21ca..cead675a74d3 100644 --- a/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc +++ b/chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc @@ -70,7 +70,7 @@ GlobalMenuBarRegistrarX11::~GlobalMenuBarRegistrarX11() { void GlobalMenuBarRegistrarX11::RegisterXID(unsigned long xid) { DCHECK(registrar_proxy_); - std::string path = GlobalMenuBarX11::GetPathForWindow(xid); + std::string path = atom::GlobalMenuBarX11::GetPathForWindow(xid); ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/314087 // TODO(erg): The mozilla implementation goes to a lot of callback trouble @@ -91,7 +91,7 @@ void GlobalMenuBarRegistrarX11::RegisterXID(unsigned long xid) { void GlobalMenuBarRegistrarX11::UnregisterXID(unsigned long xid) { DCHECK(registrar_proxy_); - std::string path = GlobalMenuBarX11::GetPathForWindow(xid); + std::string path = atom::GlobalMenuBarX11::GetPathForWindow(xid); ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/314087 // TODO(erg): The mozilla implementation goes to a lot of callback trouble From e78a02806e2a591c48e7f4ffaf678190a249012f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 8 Dec 2015 10:07:47 +0800 Subject: [PATCH 732/738] Make it safe to use sendSync --- atom/renderer/api/lib/ipc-renderer.coffee | 8 ++++++++ atom/renderer/api/lib/remote.coffee | 6 +----- .../renderer/printing/print_web_view_helper_pdf_win.cc | 2 ++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/atom/renderer/api/lib/ipc-renderer.coffee b/atom/renderer/api/lib/ipc-renderer.coffee index 29004d212b56..92be75aa20ba 100644 --- a/atom/renderer/api/lib/ipc-renderer.coffee +++ b/atom/renderer/api/lib/ipc-renderer.coffee @@ -1,9 +1,17 @@ +{EventEmitter} = require 'events' + binding = process.atomBinding 'ipc' v8Util = process.atomBinding 'v8_util' # Created by init.coffee. ipcRenderer = v8Util.getHiddenValue global, 'ipc' +# Delay the callback to next tick in case the browser is still in the middle +# of sending a message while the callback sends a sync message to browser, +# which can fail sometimes. +ipcRenderer.emit = (args...) -> + setTimeout (-> EventEmitter::emit.call ipcRenderer, args...), 0 + ipcRenderer.send = (args...) -> binding.send 'ipc-message', [args...] diff --git a/atom/renderer/api/lib/remote.coffee b/atom/renderer/api/lib/remote.coffee index 357b88406930..48cdd937fb07 100644 --- a/atom/renderer/api/lib/remote.coffee +++ b/atom/renderer/api/lib/remote.coffee @@ -119,11 +119,7 @@ metaToPlainObject = (meta) -> # Browser calls a callback in renderer. ipcRenderer.on 'ATOM_RENDERER_CALLBACK', (event, id, args) -> - # Delay the callback to next tick in case the browser is still in the middle - # of sending this message while the callback sends a sync message to browser, - # which can fail sometimes. - setImmediate -> - callbacksRegistry.apply id, metaToValue(args) + callbacksRegistry.apply id, metaToValue(args) # A callback in browser is released. ipcRenderer.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) -> diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc b/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc index 5b34ff309043..0b21de46995b 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc @@ -135,6 +135,8 @@ bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, printed_page_params.page_size = page_size_in_dpi[i]; printed_page_params.content_area = content_area_in_dpi[i]; Send(new PrintHostMsg_DidPrintPage(routing_id(), printed_page_params)); + // Send the rest of the pages with an invalid metafile handle. + printed_page_params.metafile_data_handle = base::SharedMemoryHandle(); } return true; } From c3f7f2447cbaaf60290ed21cb37c2a39dbf4618c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 8 Dec 2015 10:26:32 +0800 Subject: [PATCH 733/738] Update the libspeechd_loader --- chromium_src/library_loaders/libspeechd.h | 1 + chromium_src/library_loaders/libspeechd_loader.cc | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/chromium_src/library_loaders/libspeechd.h b/chromium_src/library_loaders/libspeechd.h index 0d62f2c5da6e..f7b276287a41 100644 --- a/chromium_src/library_loaders/libspeechd.h +++ b/chromium_src/library_loaders/libspeechd.h @@ -33,6 +33,7 @@ class LibSpeechdLoader { decltype(&::spd_set_synthesis_voice) spd_set_synthesis_voice; decltype(&::spd_list_modules) spd_list_modules; decltype(&::spd_set_output_module) spd_set_output_module; + decltype(&::spd_set_language) spd_set_language; private: diff --git a/chromium_src/library_loaders/libspeechd_loader.cc b/chromium_src/library_loaders/libspeechd_loader.cc index 606661000528..f09ea3ae861b 100644 --- a/chromium_src/library_loaders/libspeechd_loader.cc +++ b/chromium_src/library_loaders/libspeechd_loader.cc @@ -201,6 +201,19 @@ bool LibSpeechdLoader::Load(const std::string& library_name) { return false; } +#if defined(LIBRARY_LOADER_OUT_RELEASE_GEN_LIBRARY_LOADERS_LIBSPEECHD_H_DLOPEN) + spd_set_language = + reinterpret_castspd_set_language)>( + dlsym(library_, "spd_set_language")); +#endif +#if defined(LIBRARY_LOADER_OUT_RELEASE_GEN_LIBRARY_LOADERS_LIBSPEECHD_H_DT_NEEDED) + spd_set_language = &::spd_set_language; +#endif + if (!spd_set_language) { + CleanUp(true); + return false; + } + loaded_ = true; return true; @@ -227,5 +240,6 @@ void LibSpeechdLoader::CleanUp(bool unload) { spd_set_synthesis_voice = NULL; spd_list_modules = NULL; spd_set_output_module = NULL; + spd_set_language = NULL; } From c63a8c944bef19a67a153b80ce98356645921f5f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 8 Dec 2015 10:42:51 +0800 Subject: [PATCH 734/738] Fix release title --- script/upload.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/script/upload.py b/script/upload.py index c021d743a82e..3245d9caaa76 100755 --- a/script/upload.py +++ b/script/upload.py @@ -174,11 +174,10 @@ def create_or_get_release_draft(github, releases, tag, tag_exists): def create_release_draft(github, tag): + name = '{0} {1}'.format(PROJECT_NAME, tag) if os.environ.has_key('CI'): - name = '{0} pending draft'.format(PROJECT_NAME) body = '(placeholder)' else: - name = '{0} {1}'.format(PROJECT_NAME, tag) body = get_text_with_editor(name) if body == '': sys.stderr.write('Quit due to empty release note.\n') From 4af219089066ca515a18aedfb5603bf9248e73cd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 8 Dec 2015 11:14:30 +0800 Subject: [PATCH 735/738] Upgrade to Node v5.1.1 --- script/bootstrap.py | 2 +- vendor/node | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/bootstrap.py b/script/bootstrap.py index ef48c1f8023f..6eaf635bfd86 100755 --- a/script/bootstrap.py +++ b/script/bootstrap.py @@ -196,7 +196,7 @@ def create_chrome_version_h(): def touch_config_gypi(): config_gypi = os.path.join(SOURCE_ROOT, 'vendor', 'node', 'config.gypi') with open(config_gypi, 'w+') as f: - content = '\n{}' + content = "\n{'variables':{}}" if f.read() != content: f.write(content) diff --git a/vendor/node b/vendor/node index 97d9298d8a43..38d791843463 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 97d9298d8a431f27e2aded918ae9f2a673c9cf6f +Subproject commit 38d791843463b19c623c97c1c550a4e3c5a406d4 From 0f2f9b55430675e7fb9ff9dd915554075b728515 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 8 Dec 2015 11:20:07 +0800 Subject: [PATCH 736/738] No need to use CommandDispatcher --- atom/browser/native_window_mac.mm | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index d7ed15cf0708..ef33a119e107 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -18,7 +18,6 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "native_mate/dictionary.h" -#import "ui/base/cocoa/command_dispatcher.h" #include "ui/gfx/skia_util.h" namespace { @@ -209,11 +208,10 @@ bool ScopedDisableResize::disable_resize_ = false; @end -@interface AtomNSWindow : NSWindow { +@interface AtomNSWindow : NSWindow { @private atom::NativeWindowMac* shell_; bool enable_larger_than_screen_; - base::scoped_nsobject commandDispatcher_; } @property BOOL acceptsFirstMouse; @property BOOL disableAutoHideCursor; @@ -227,7 +225,6 @@ bool ScopedDisableResize::disable_resize_ = false; - (void)setShell:(atom::NativeWindowMac*)shell { shell_ = shell; - commandDispatcher_.reset([[CommandDispatcher alloc] initWithOwner:self]); } - (void)setEnableLargerThanScreen:(bool)enable { @@ -276,25 +273,6 @@ bool ScopedDisableResize::disable_resize_ = false; return !self.disableKeyOrMainWindow; } -// CommandDispatchingWindow implementation. - -- (void)setCommandHandler:(id)commandHandler { -} - -- (BOOL)redispatchKeyEvent:(NSEvent*)event { - return [commandDispatcher_ redispatchKeyEvent:event]; -} - -- (BOOL)defaultPerformKeyEquivalent:(NSEvent*)event { - return [super performKeyEquivalent:event]; -} - -- (void)commandDispatch:(id)sender { -} - -- (void)commandDispatchUsingKeyModifiers:(id)sender { -} - @end @interface ControlRegionView : NSView From da208b5155037578a230affdb81733c72de845ae Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 8 Dec 2015 11:41:47 +0800 Subject: [PATCH 737/738] We are now on 0.36.0 --- atom.gyp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom.gyp b/atom.gyp index 9f1ffe582505..01a2c99e08d8 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.35.4', + 'version%': '0.36.0', }, 'includes': [ 'filenames.gypi', From 407e88cbad1470ca312b7f7b992d3268e8eb7e41 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 8 Dec 2015 12:06:32 +0800 Subject: [PATCH 738/738] Update brightray --- atom/common/chrome_version.h | 2 +- vendor/brightray | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/common/chrome_version.h b/atom/common/chrome_version.h index 250051683786..c92fee1649bd 100644 --- a/atom/common/chrome_version.h +++ b/atom/common/chrome_version.h @@ -8,7 +8,7 @@ #ifndef ATOM_COMMON_CHROME_VERSION_H_ #define ATOM_COMMON_CHROME_VERSION_H_ -#define CHROME_VERSION_STRING "45.0.2454.85" +#define CHROME_VERSION_STRING "47.0.2526.73" #define CHROME_VERSION "v" CHROME_VERSION_STRING #endif // ATOM_COMMON_CHROME_VERSION_H_ diff --git a/vendor/brightray b/vendor/brightray index 878e63860b59..9b4d052d2af7 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 878e63860b59d3443cd9f739d7533f2be1109773 +Subproject commit 9b4d052d2af716c340034ed7815d9d758cd7804d