Compare commits

..

344 Commits

Author SHA1 Message Date
Cheng Zhao
30ec7fdeed Bump v0.34.1 2015-10-23 20:32:02 +08:00
Cheng Zhao
0e3e1be85c Merge pull request #3186 from atom/auto-updater-fix
Clean up the code of auto-updater
2015-10-23 20:31:20 +08:00
Cheng Zhao
df9ea104c2 Merge pull request #3188 from alexandrubau/master
Updated docs
2015-10-23 20:13:00 +08:00
Cheng Zhao
88b05cff3e docs: auto-updater on Windows 2015-10-23 20:11:59 +08:00
Cheng Zhao
fae2c7bc7a win: Make auto-updater really work
Apparently that PR was never tested.
2015-10-23 19:41:54 +08:00
Alexandru Bau
96130dd4c2 Updated docs
Updated docs to better understand how to use electron-rebuild on all
platforms
2015-10-23 14:15:39 +03:00
Alexandru Bau
79e593aca6 Updated docs
Updated docs to better understand how to use electron-rebuild on Windows
2015-10-23 11:37:51 +03:00
Cheng Zhao
aeafc46ded Keep compatibility with old API style 2015-10-23 15:50:55 +08:00
Cheng Zhao
f89d28a63e 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.
2015-10-23 15:40:56 +08:00
Cheng Zhao
d74ef5c078 Move implementation of auto-updater on OS X to another file 2015-10-23 15:13:24 +08:00
Cheng Zhao
85c84a0eb0 Emit Date object in C++ directly 2015-10-23 14:58:19 +08:00
Cheng Zhao
a3f62da615 Fix passing Date object in remote
Close #2017.
2015-10-23 14:51:41 +08:00
Cheng Zhao
95fe4beda8 Pass real Error object in error event 2015-10-23 14:37:35 +08:00
Cheng Zhao
d5c964c68c Fix passing Error object in remote
Closes #3089
2015-10-23 14:37:28 +08:00
Cheng Zhao
07adbc8e8a Merge pull request #1984 from patrickdet/windows-auto-updater
Windows Auto Updater
2015-10-23 13:54:29 +08:00
Cheng Zhao
90e3f726e4 Merge pull request #3184 from atom/windows-background-color
Make background-color work on Windows
2015-10-23 13:53:12 +08:00
Cheng Zhao
83ef23ff8d docs: background-color on Windows 2015-10-23 13:32:04 +08:00
Cheng Zhao
e36d455d51 Add setBackgroundColor method 2015-10-23 11:35:33 +08:00
Cheng Zhao
4a6134f3f7 win: Set native window's background color 2015-10-23 11:17:14 +08:00
Cheng Zhao
6182e4ce81 Merge pull request #3179 from deepak1556/session_api_patch
session: allow setproxy to use external pac script
2015-10-23 10:36:37 +08:00
Cheng Zhao
79d4d52172 Merge pull request #3178 from deepak1556/node_debugger_patch
debugger: expose v8debug
2015-10-23 10:36:06 +08:00
Cheng Zhao
e3ce1b50ec Merge pull request #3175 from atom/improve-make-single-instance
Fix some problems of makeSingleInstance
2015-10-23 09:13:57 +08:00
Robo
e9a5d05b27 session: allow setproxy to use external pac script 2015-10-22 23:03:47 +05:30
Cheng Zhao
61f07307cb docs: New behaviors of makeSingleInstance 2015-10-22 19:26:05 +08:00
Cheng Zhao
6bfe06ec4e Pass original argv in callback 2015-10-22 19:02:21 +08:00
Robo
7b5a1b06ba debugger: expose v8debug 2015-10-22 16:20:48 +05:30
Cheng Zhao
d52ef50b01 win: Pass original command line 2015-10-22 17:52:06 +08:00
Cheng Zhao
93a3a946f3 posix: Pass original command line 2015-10-22 17:43:55 +08:00
Cheng Zhao
afc1fff792 Remove the need for ProcessSingletonStartupLock 2015-10-22 17:12:09 +08:00
Cheng Zhao
70e74d05e0 Revert "app.makeSingleInstance is not available on OS X"
This reverts commit bcb78ebc00.
2015-10-22 17:03:18 +08:00
Cheng Zhao
f9d797d1ea win: Fix compiler warning 2015-10-22 16:55:54 +08:00
Cheng Zhao
e14fd62f46 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.
2015-10-22 16:24:35 +08:00
Cheng Zhao
ca876e424b Fix crash when calling app.quit() before app is ready 2015-10-22 16:06:37 +08:00
Cheng Zhao
230f2760e7 linux: Delay creating watcher until message loop is ready 2015-10-22 15:57:37 +08:00
Cheng Zhao
f01e84a418 linux: Delay listening to socket until message loop is ready 2015-10-22 15:54:58 +08:00
Cheng Zhao
05c6300329 Don't discard tasks in BridgeTaskRunner 2015-10-22 15:54:27 +08:00
Cheng Zhao
bcb78ebc00 app.makeSingleInstance is not available on OS X 2015-10-22 15:02:32 +08:00
Cheng Zhao
310954713f Simplify the usage of singleton 2015-10-22 14:59:12 +08:00
Cheng Zhao
acb2c099f6 Make sure current task runner is available
When calling makeSingleInstance we have to ensure current task runnder
is available, otherwise crash may happen.
2015-10-22 14:56:57 +08:00
Cheng Zhao
63cc2ec369 docs: Make code more JS-style 2015-10-22 14:24:09 +08:00
Cheng Zhao
04d3eed60e Merge pull request #3145 from atom/single-instance
Implement Single-Instance for Windows / Linux
2015-10-22 14:18:31 +08:00
Cheng Zhao
f7840e7379 docs: background-color is Linux-only for now 2015-10-22 14:16:17 +08:00
Cheng Zhao
15e0248d82 Merge pull request #3168 from deepak1556/window_background_color_patch
browser: option to set window background color
2015-10-22 14:13:37 +08:00
Robo
9411508d3e browser: option to set window background color 2015-10-22 09:54:29 +05:30
Cheng Zhao
f5659cd9a9 Merge pull request #3173 from tommoor/patch-5
Update crash-reporter.md
2015-10-22 11:10:30 +08:00
Cheng Zhao
803b3c8d5b Merge pull request #3172 from thomasjfox1/master
quick fix removing excess character
2015-10-22 11:08:30 +08:00
Tom Moor
bac3d2e372 Update crash-reporter.md 2015-10-21 17:07:36 -07:00
Paul Betts
759b6a1534 📝 for makeSingleInstance 2015-10-21 13:52:17 -07:00
Paul Betts
de66888051 Remove atom_process_singleton, just use the Chrome classes directly 2015-10-21 13:38:39 -07:00
Paul Betts
d020a7dc86 cpplinting 2015-10-21 13:17:56 -07:00
Paul Betts
938d68eb36 Move all the browser.cc code over to atom_api_app.cc 2015-10-21 13:04:50 -07:00
Thomas J Fox
b61c2e6ff7 quick fix removing excess character 2015-10-21 15:03:12 -05:00
Paul Betts
658a9872fb Only cleanup if we are the main process 2015-10-21 12:29:21 -07:00
Paul Betts
a160891a27 If a user calls makeSingleInstance more than once, just ignore it 2015-10-21 12:29:00 -07:00
Paul Betts
38d6ff79c8 Need to free this early or get a SIGSEGV on Linux 2015-10-21 11:06:42 -07:00
Cheng Zhao
73f4aa1113 Merge pull request #3169 from atom/fix-node-buffer
Fix memory corruption when cleaning timer
2015-10-21 21:23:25 +08:00
Cheng Zhao
444f461269 Fix memory corruption when cleaning timer 2015-10-21 20:46:16 +08:00
Cheng Zhao
2d410ede48 Initialize things in the same sequence with main process 2015-10-21 16:24:54 +08:00
Cheng Zhao
ed9579a2f7 Merge pull request #3165 from roadev/master
Grammatical corrections for spanish translations at api, styleguide a…
2015-10-21 13:28:48 +08:00
Cheng Zhao
567d8e7434 Merge pull request #3163 from atom/fix-osx-app-region
osx: Implement draggable region with mouseDownCanMoveWindow
2015-10-21 09:53:02 +08:00
Cheng Zhao
d092c6acc9 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.
2015-10-21 08:54:46 +08:00
Paul Betts
99c496471b Allow WM_COPYDATA from all processes 2015-10-20 17:36:05 -07:00
Paul Betts
e5094fff3e Since setting up process_singleton is now conditional, its cleanup / unlock must be too 2015-10-20 17:27:28 -07:00
Juan Roa
fe25f3e747 grammatical corrections for spanish translations at api, styleguide and README 2015-10-20 18:10:08 -05:00
Cheng Zhao
b6859cab91 Merge pull request #3158 from ngoldman/patch-1
use webContents.openDevTools for quick start guide
2015-10-21 06:58:16 +08:00
Cheng Zhao
26d922d18d Merge pull request #3156 from preco21/master
Update as upstream
2015-10-21 06:52:10 +08:00
Paul Betts
15f00db1bf I don't think we need this 2015-10-20 15:03:59 -07:00
Paul Betts
4a7a09aae1 Infinite Linting 2015-10-20 15:00:10 -07:00
Paul Betts
f759471e01 Update to use Chromium sources 2015-10-20 14:36:01 -07:00
Paul Betts
4bc54ac5e3 Fix up filenames to include Chrome source 2015-10-20 14:33:34 -07:00
Paul Betts
5886398f22 Port our changes over 2015-10-20 14:24:45 -07:00
Paul Betts
7491d5cfb5 Copy back the original versions of Chromium files in 2015-10-20 14:05:07 -07:00
Paul Betts
b6f1729acd Move initialization of Single Instance into MakeSingleInstance call 2015-10-20 13:38:57 -07:00
Paul Betts
5d4c29a1e3 Ditch double-callback, just use mate directly 2015-10-20 13:27:34 -07:00
Paul Betts
a2eedcc027 Wire up the final callback to JS 2015-10-20 13:17:26 -07:00
Paul Betts
63417bc975 I am not good at C++ at all 2015-10-20 13:17:25 -07:00
Paul Betts
4a4b829cfc Fix callback handle usage 2015-10-20 13:17:25 -07:00
Paul Betts
50fab0733b At Browser ctor time, DIR_USER_DATA is unset, wait 2015-10-20 13:16:49 -07:00
Paul Betts
b02f89e63b Typo 2015-10-20 13:16:49 -07:00
Paul Betts
cdd51fa96d Wire everything up 2015-10-20 13:16:48 -07:00
Paul Betts
c38f2fcf75 Add a native mate converter for command lines 2015-10-20 13:15:12 -07:00
Paul Betts
7491ae4000 Set up Browser to create the process singleton 2015-10-20 13:15:12 -07:00
Paul Betts
4d5495a0a0 Bring in chrome_process_singleton but nuke the active dialog bits 2015-10-20 13:15:11 -07:00
Paul Betts
717aba9631 Create a dummy method in app that we'll twerk 2015-10-20 13:15:11 -07:00
Paul Betts
8288a22458 Fix build against old OneShotTimer 2015-10-20 13:14:08 -07:00
Paul Betts
88dd1480cc Get POSIX mostly compiling 2015-10-20 13:14:08 -07:00
Paul Betts
c46579b1ac Remove a bunch of stuff we don't need in process_singleton_win 2015-10-20 13:14:07 -07:00
Paul Betts
1b3363c811 Get process finder working 2015-10-20 13:14:07 -07:00
Paul Betts
daa65a138b Come Correct with headers 2015-10-20 13:14:06 -07:00
Paul Betts
d3b23a2032 Renames to avoid confusion, add file 2015-10-20 13:14:06 -07:00
Paul Betts
05b22b9372 Import process_finder verbatim 2015-10-20 13:14:05 -07:00
Paul Betts
ff2d9759d5 Start to remove / rearrange some header files 2015-10-20 13:14:05 -07:00
Paul Betts
90b997ef08 Add the files to filenames.gypi 2015-10-20 13:14:05 -07:00
Paul Betts
27fa5d880a Copy some relevant files over from Chromium 2015-10-20 13:14:04 -07:00
Paul Betts
285a4789b3 Update app.md 2015-10-20 12:35:56 -07:00
Nate Goldman
da7161d5a7 use webContents.openDevTools
https://github.com/atom/electron/issues/3125#issuecomment-148975593
2015-10-20 10:44:02 -07:00
Patrick Detlefsen
db3bc28937 PR feedback adressed 2015-10-20 19:25:03 +02:00
Jessica Lord
a0e2af6fac Merge pull request #3157 from IonicaBizauKitchen/doc-improvements
Doc improvements
2015-10-20 10:20:11 -07:00
Ionică Bizău
1ad979f9bd Add some missing words ("be" and "the") 2015-10-20 19:44:01 +03:00
Plusb Preco
f7a9b02c63 Merge remote-tracking branch 'refs/remotes/atom/master' 2015-10-21 00:26:30 +09:00
Plusb Preco
7a0db35d91 Update as upstream 2015-10-21 00:25:24 +09:00
Cheng Zhao
c928894627 docs: app.allowNTLMCredentialsForAllDomains 2015-10-20 13:56:31 +08:00
Cheng Zhao
a7a399dcd8 Code cleanup 2015-10-20 13:52:39 +08:00
Cheng Zhao
14e2bbe4c7 Update brightray for #3120 2015-10-20 13:50:19 +08:00
Cheng Zhao
370cb5b5e1 Merge pull request #3120 from atom/ntlm-part-two
Optionally allow NTLM authentication for all domains
2015-10-20 13:48:12 +08:00
Cheng Zhao
78261973fb Merge pull request #3153 from atom/development-env
Add a few environment variables helpful for debugging
2015-10-20 13:47:17 +08:00
Cheng Zhao
be36a17dbf docs: Mention the ELECTRON_ENABLE_LOGGING env 2015-10-20 13:06:41 +08:00
Cheng Zhao
fb8ca33d5d Add ELECTRON_ENABLE_STACK_DUMPING env
It enables in-process stack dumping, which is convenient for debugging.
2015-10-20 13:02:48 +08:00
Cheng Zhao
2c4a24d26b Add ELECTRON_ENABLE_LOGGING env
It is the same with --enable-logging.
2015-10-20 13:00:28 +08:00
Cheng Zhao
4005e65e28 Merge pull request #3150 from atom/jl-upadate-qs
Update Quick Start HTML
2015-10-20 11:17:30 +08:00
Cheng Zhao
86327fb4bb Merge pull request #3149 from atom/jl-add-quick-start-repo
Add links to electron-quick-start Repository
2015-10-20 11:17:23 +08:00
Cheng Zhao
5a46147e9b Update brightray for atom/brightray#158 2015-10-20 10:34:33 +08:00
Cheng Zhao
bb8bb3dbea Merge pull request #3147 from deepak1556/cipher_suite_disable_patch
browser: flag to disable specified cipher suites
2015-10-20 10:29:49 +08:00
Jessica Lord
d09b09b744 Match the electron-quick-start repo 2015-10-19 16:37:18 -07:00
Jessica Lord
bc7c7da799 Add links to electron-quick-start 2015-10-19 15:52:02 -07:00
Robo
9f8479e9d8 browser: flag to diable specified cipher suites 2015-10-20 02:51:56 +05:30
Paul Betts
e3535d664b Fixed linter issues but now the code looks awful 2015-10-19 13:12:17 -07:00
Paul Betts
b3c7e2bf33 Plumb the method back 2015-10-19 13:07:14 -07:00
Paul Betts
489090fcf8 Set up our browser context to use new delegate-based API 2015-10-19 13:03:20 -07:00
Cheng Zhao
0afefe13f6 Merge pull request #3141 from jhen0409/patch-2
Sync recently updated docs to zh-TW docs-translations
2015-10-19 22:09:06 +08:00
Jhen
7f15d63552 Update README.md for zh-TW docs-translations 2015-10-19 21:54:29 +08:00
Jhen
09ee24514e Replace Mac with OS X for zh-TW docs translation 2015-10-19 21:49:57 +08:00
Jhen
d9c7401d0b Replace io.js with node.js for zh-TW docs translation 2015-10-19 21:29:10 +08:00
Cheng Zhao
de3e16ce60 Merge pull request #3129 from brandoncash/fix-tray-notify-typo
Fix: tray NotfiyDropFiles typo
2015-10-19 19:11:26 +08:00
Cheng Zhao
72e0da069c Merge pull request #3132 from princejwesley/issue-readFileSync
Fix: honor fs.readFileSync contract for empty packed asar file
2015-10-19 16:59:47 +08:00
Cheng Zhao
0d9e0a38c0 Merge pull request #3128 from atom/fix-save-page-position
Fix: 'savePage API' saves external resources in a wrong directory.
2015-10-19 16:40:45 +08:00
Prince J Wesley
810af2f95d 🐛 Honor fs.readFileSync contract for empty packed asar file 2015-10-19 08:43:50 +05:30
Plusb Preco
0aefa98e5a Small fix in README 2015-10-19 11:34:13 +09:00
Cheng Zhao
0e50b00fdf Merge pull request #3111 from preco21/master
Add app.md translation into ko-KR, some fixes
2015-10-18 21:45:25 +08:00
Brandon Cash
60b14d03e9 Fix: tray NotfiyDropFiles typo 2015-10-18 00:32:13 -05:00
Haojian Wu
49d25d0069 Fix: savePage API saves external resources in a wrong directory. 2015-10-18 11:28:05 +08:00
Plusb Preco
82e6058607 Update as upstream 2015-10-18 03:30:37 +09:00
Plusb Preco
c46ed897dd Update translation progress in README.md 2015-10-18 03:22:35 +09:00
Ivan Žužak
c7d9352972 Merge pull request #3118 from learningjs/thcm
[Tiny correction of misspelling]
2015-10-17 10:10:06 +02:00
Jessica Lord
cd2f924db8 Merge pull request #3117 from ggamel/patch-1
Update MAS tutorial to improve readability
2015-10-16 17:56:32 -07:00
Paul Betts
b958982d99 Rollback submodule change 2015-10-16 17:00:31 -07:00
Paul Betts
a3fc25110e Linter fixes 2015-10-16 16:55:28 -07:00
Paul Betts
5ae6bd2ef4 Wire it up 2015-10-16 16:46:05 -07:00
Paul Betts
7ac643d5f8 Create a new method on App to override URL Security Manager's decisions wrt NTLM 2015-10-16 16:45:54 -07:00
Greg Gamel
5e7a30deea Additional updates to adhere to styleguide
Per @jlord's recommendations.
2015-10-16 18:25:30 -05:00
max_devjs
72078f7b02 [truly humble correction of a misspelling]
Substituting webp with web in frameless-window.md .
2015-10-16 19:56:45 -03:00
Greg Gamel
b5478eaef7 Update MAS tutorial to improve readability
Adjusted tutorial body copy and headings to improve readability, clarify sentences, and fix some (minor) grammatical missteps.
2015-10-16 17:50:41 -05:00
Jessica Lord
1ae4be7571 Merge pull request #3115 from romankl/doc-osx
replace Mac with OS X
2015-10-16 14:21:54 -07:00
Roman Klauke
32523ae352 replace Mac with OS X
Commit 691d8dd replaced "Mac" with "OS X". This commit replaces some
other occurrences.
2015-10-16 22:03:47 +02:00
Plusb Preco
c0ee8f4e60 Merge remote-tracking branch 'refs/remotes/atom/master' 2015-10-16 22:36:01 +09:00
Plusb Preco
edd6032ed0 Improve grammar for more readability 2015-10-16 22:26:27 +09:00
Plusb Preco
f05fc3c0ea Improve grammar, some fixes
* Improve grammar
* Fix typos
* Fix some mistranslations
* Fix quotes (' to `)
2015-10-16 22:23:31 +09:00
Cheng Zhao
f0825bf7ef Merge pull request #3109 from fplucas/master
Translation of debugging-main-process to pt-br.
2015-10-16 20:28:34 +08:00
Cheng Zhao
d9fdfb711f Clean up CallbackRegistry
There were some ancient code there.
2015-10-16 20:25:30 +08:00
Cheng Zhao
94f64c755d spec: Load url after event listener is set up 2015-10-16 20:22:04 +08:00
Cheng Zhao
4871ea715c Merge pull request #3103 from bengotow/bengotow/debug-release
Allow "released callback" errors to be traced to remote calls
2015-10-16 20:21:46 +08:00
Cheng Zhao
115bb31ab4 docs: Small fix on mas guide 2015-10-16 20:21:06 +08:00
Lucas
2725068a0c Updating README.md 2015-10-16 09:11:30 -03:00
Lucas Pugliesi
5e5caf2e86 Translation of debugging-main-process to pt-br. 2015-10-16 09:09:24 -03:00
Cheng Zhao
22e9c2f4eb Bump v0.34.0 2015-10-16 18:53:25 +08:00
Cheng Zhao
c371c713a9 Merge pull request #3108 from atom/mas-build
Prepare for MAS build and add a guide
2015-10-16 18:51:45 +08:00
Cheng Zhao
776077c8de Bump v0.33.9 2015-10-16 17:42:55 +08:00
Cheng Zhao
16b9f8995d Revert "Go back to using node's console.* and std*.write"
This reverts commit 4e8db2c3be.

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.
2015-10-16 17:38:11 +08:00
Cheng Zhao
18fd126c64 docs: Mac App Store Submission Guide 2015-10-16 17:16:12 +08:00
Cheng Zhao
7bdbe45c91 subpixel-font-scaling option is removed 2015-10-16 15:01:28 +08:00
Cheng Zhao
fb99e72484 Update libchromiumcontent to have mas build 2015-10-16 15:01:28 +08:00
Cheng Zhao
0e94ccb72b Merge pull request #3080 from atom/save-page-api
Implement webContents.savePage API.
2015-10-16 09:52:43 +08:00
Ben Gotow
aeb24b784d Allow "released callback" errors to be traced to remote calls 2015-10-15 18:46:59 -07:00
Cheng Zhao
125444df15 Merge pull request #3101 from fplucas/master
Translation of using-pepper-flash-plugin to pt-br.
2015-10-16 09:25:34 +08:00
Haojian Wu
facd0fbc08 Implement webContents.savePage API. 2015-10-16 09:23:08 +08:00
Lucas Pugliesi
3dba56c335 Translation of using-pepper-flash-plugin to pt-br. 2015-10-15 17:16:48 -03:00
Cheng Zhao
89527ec232 Merge pull request #3097 from fplucas/master
Translation of using-native-node-modules to pt-br.
2015-10-15 23:14:30 +08:00
Lucas Pugliesi
904f3c2564 Translation of using-native-node-modules to pt-br. 2015-10-15 10:52:30 -03:00
Cheng Zhao
d2b3d6d129 Merge pull request #3092 from atom/crash-reporter
Fix problems of crash-reporter on Windows
2015-10-15 19:29:29 +08:00
Cheng Zhao
909779babf spec: Bring back crash-reporter spec on x64 Windows 2015-10-15 18:25:34 +08:00
Cheng Zhao
f5c25d6277 win: Only install breakpad hook when crash-reporter is used 2015-10-15 18:25:07 +08:00
Cheng Zhao
d90b598125 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.
2015-10-15 16:36:30 +08:00
Cheng Zhao
55d5660ddb win: Make the event in crash service signaled by default
Otherwise it seems to block the crash client on some machines.

Fix #2769.
2015-10-15 16:36:29 +08:00
Cheng Zhao
11a49bba35 win: Fix "enable-larger-than-screen" option spec 2015-10-15 16:36:29 +08:00
Cheng Zhao
6aec8b092c views: Fix crash when setSizeConstrains is called early 2015-10-15 16:36:28 +08:00
Cheng Zhao
f52c4af605 win: Don't output newline except for main process 2015-10-15 12:44:55 +08:00
Plusb Preco
b61baacfe1 Merge pull request #1 from ibocon/translateIntoKR
Add `app.md` translation
2015-10-15 07:59:25 +09:00
Yegun Kim
79311af8eb translate "/docs-translations/ko-KR/api/app.md" 2015-10-15 16:26:24 -05:00
Jessica Lord
7a6ef0ec6e Merge pull request #3084 from kokdemo/master
translate the debugging-main-process.md
2015-10-14 13:58:27 -07:00
kokdemo
4270eba438 translate the debugging-main-process.md 2015-10-15 00:00:52 +08:00
Thomas Johansen
d14b59c754 Merge pull request #3082 from nikarc/patch-1
Update application-distribution.md
2015-10-14 12:42:18 +02:00
Nicholas Arcuri
95c4847d60 Update application-distribution.md
Fix typo on line 38
2015-10-14 06:28:27 -04:00
Cheng Zhao
74d389b2b0 Bump v0.33.8 2015-10-14 12:36:03 +08:00
Cheng Zhao
eb344f3f04 Merge pull request #2920 from atom/mas
Add MAS build
2015-10-14 12:34:46 +08:00
Cheng Zhao
b47076231c mas: Do not link with QTKit for mas build 2015-10-14 11:57:01 +08:00
Cheng Zhao
51335934c1 mac: Set CFBundleExecutable for Electron Framework 2015-10-14 11:54:59 +08:00
Cheng Zhao
d6842751bb mac: Don't specify CFBundleExecutable in framework 2015-10-14 11:54:59 +08:00
Cheng Zhao
96c15f19e3 mac: Set LSApplicationCategoryType in Info.plist 2015-10-14 11:54:58 +08:00
Cheng Zhao
9e51ff2b4b mac: Set CFBundleShortVersionString in Info.plist 2015-10-14 11:54:26 +08:00
Cheng Zhao
48faf74f7f mas: Use mas as platform name in dist 2015-10-14 11:53:53 +08:00
Cheng Zhao
df7a9b80b1 Fix linking error 2015-10-14 11:53:53 +08:00
Cheng Zhao
3afc9c4ebe spec: Disable crash reporter test for MAS build 2015-10-14 11:53:53 +08:00
Cheng Zhao
7b57a945f8 mac: Set process.mas to true for MAS build 2015-10-14 11:53:52 +08:00
Cheng Zhao
b62e3554dc mac: Disable auto updater in MAS build 2015-10-14 11:53:52 +08:00
Cheng Zhao
a9f5667899 mac: Disable crash reporter for MAS build 2015-10-14 11:53:52 +08:00
Cheng Zhao
644af0800c Update brightray for atom/brightray#156 2015-10-14 09:47:46 +08:00
Cheng Zhao
699dafc5db Merge pull request #3076 from kokdemo/master
translate the supported-platforms.md and update the README.md
2015-10-14 09:15:41 +08:00
kokdemo
d152b25fb6 translate the supported-platforms.md and update the README.md 2015-10-14 00:27:17 +08:00
Plusb Preco
af8049941e Update as upstream 2015-10-13 20:53:04 +09:00
Cheng Zhao
d9a4a41293 Merge pull request #3073 from wangdashuaihenshuai/master
doc-translations-zh-CN
2015-10-13 16:13:36 +08:00
Cheng Zhao
ddea2fced4 Merge pull request #3071 from alex-sherwin/patch-1
Fixing "tile" -> "title" typo
2015-10-13 09:32:22 +08:00
Cheng Zhao
34d49441b1 Merge pull request #3070 from deepak1556/v8_value_converter_patch
nativemate: handle binary types in v8 value conversion
2015-10-13 09:05:14 +08:00
Cheng Zhao
b9b25180f8 Update brightray for #2903 2015-10-13 09:04:10 +08:00
Alex Sherwin
b9d838975d Fixing "tile" -> "title" typo 2015-10-12 20:17:06 -04:00
Robo
5ff97c686a nativemate: handle binary types in v8 value conversion 2015-10-13 01:13:59 +05:30
Cheng Zhao
460adfa1bc Merge branch 'master' of https://github.com/preco21/electron into preco21-master 2015-10-12 09:42:10 +08:00
Cheng Zhao
ff9846da48 Merge pull request #3062 from kokdemo/master
translate the application-distrubution.md
2015-10-12 09:39:16 +08:00
Plusb Preco
9de9d2ecc1 Add missing paragraphs 2015-10-12 08:23:30 +09:00
Plusb Preco
799748cc5d Update as upstream, improve grammar 2015-10-12 08:19:44 +09:00
kokdemo
ab1f39589a Merge remote-tracking branch 'atom/master' 2015-10-11 22:28:44 +08:00
kokdemo
9419a2ec2c translate the application-distrubution.md 2015-10-11 22:26:14 +08:00
Cheng Zhao
c58ca76cac Merge pull request #3061 from flying-sheep/patch-1
fixed devtools instructions
2015-10-11 21:45:36 +08:00
Philipp A.
36bbf5d51f fixed devtools instructions 2015-10-11 15:18:27 +02:00
Cheng Zhao
8012792457 Merge pull request #3060 from etiktin/output_fixes
Output to console fixes
2015-10-11 15:19:07 +08:00
Cheng Zhao
2820fa8fd4 Merge pull request #3059 from osanyin/docs-translation
Some docs translated to pt-BR
2015-10-11 15:18:35 +08:00
jinhai.wang
bd95be23f3 fix docs-translations/zh-CN/api ipc-main-process.md '' -> bug 2015-10-11 14:56:23 +08:00
jinhai.wang
6ec184a2ce add new file: ipc-main-process.md 2015-10-11 13:52:06 +08:00
Eran Tiktin
cb903a09c0 Block all internal logs when running without --enable-logging 2015-10-10 20:44:22 +03:00
Eran Tiktin
4e8db2c3be 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).
2015-10-10 20:17:08 +03:00
Rafael Guimarães
692816f9d2 online-offline-events.md translated to pt-BR 2015-10-10 14:01:55 -03:00
Rafael Guimarães
0cd1195eea online-offline-events.md translated to pt-BR 2015-10-10 13:41:32 -03:00
Eran Tiktin
71fdb91f5c Merge remote-tracking branch 'refs/remotes/atom/master' 2015-10-10 18:16:55 +03:00
Cheng Zhao
6d20d37101 Bump v0.33.7 2015-10-10 17:43:56 +08:00
Cheng Zhao
df12f181a4 Can not print string16 in wcout on POSIX 2015-10-10 17:43:56 +08:00
Cheng Zhao
be5f1b09f4 Merge pull request #3056 from etiktin/fix_console_windows
Fix console.* calls on Windows
2015-10-10 17:32:15 +08:00
Plusb Preco
b5b6e30c8b Update as upstream 2015-10-10 15:10:34 +09:00
Plusb Preco
ccd17f060d Merge remote-tracking branch 'atom/master' 2015-10-10 15:10:24 +09:00
Eran Tiktin
c71efc8ca5 Fix process.std*.write
- Support printing Buffer
- Don't add '\n' at the end the chunk
2015-10-10 08:13:27 +03:00
Cheng Zhao
8278ee533d Merge pull request #3055 from kokdemo/master
add translate of app.md in zh-CN
2015-10-10 12:25:48 +08:00
Rafael Guimarães
b6cfa6f967 Copying online-offline-events.md file 2015-10-10 01:20:42 -03:00
Eran Tiktin
1896deb10e Fix console.* calls on Windows
- Calls for console.* on browser process are printed with no need for
--enable-logging
- The output is without the logging prefix
- The cursor in the terminal is always after the last output
- The first output starts on a new line and not at the prompt
- console.* from renderer are not printed to cmd
- Added a missing '\n' in the default_app help output
2015-10-10 06:39:02 +03:00
kokdemo
095b2e6047 add translate of app.md in zh-CN 2015-10-10 11:33:14 +08:00
Eran Tiktin
e682dc7544 Merge remote-tracking branch 'refs/remotes/atom/master' 2015-10-10 06:01:01 +03:00
Rafael Guimarães
4392f1d77c Some fixes 2015-10-09 22:47:07 -03:00
Rafael Guimarães
288572f08e README.md updated 2015-10-09 22:17:21 -03:00
Rafael Guimarães
6cbbce544f Translation to pt-BR of the desktop-environment-integration.md file 2015-10-09 22:15:14 -03:00
Cheng Zhao
8127bbc992 Merge pull request #3046 from mariozaizar/better-translations
Missing translations for ES lang.
2015-10-10 09:13:53 +08:00
Mario Zaizar
9fd46ac4db Revert vendor/ changes added by mistake. 2015-10-09 09:17:54 -07:00
Mario Zaizar
1e13159157 Merge branch 'master' of https://github.com/atom/electron into better-translations 2015-10-09 08:58:07 -07:00
Cheng Zhao
215ca78c7f Update brightray for #3048 2015-10-09 21:08:00 +08:00
Cheng Zhao
0404cc850b Merge pull request #3048 from deepak1556/accept_language_patch
browser: get accept-language header from system locale
2015-10-09 21:05:57 +08:00
Robo
fb5260eb30 browser: get accept-language header from system locale 2015-10-09 13:18:37 +05:30
Mario Zaizar
28b3678159 Removing "Rebranding", "Empaquetamiento" and other minor changes to es/tutorial/application-distribution.md 2015-10-08 23:55:32 -07:00
Mario Zaizar
965471d9f8 Merge branch 'master' of https://github.com/atom/electron into better-translations 2015-10-08 23:24:23 -07:00
Mario Zaizar
d7c67d795b Merge remote-tracking branch 'atom/master' into better-translations 2015-10-08 23:19:32 -07:00
Mario Zaizar
841407a619 Breakdown a super long line inside styleguide.md 2015-10-08 23:19:16 -07:00
Mario Zaizar
1759a71814 Adding /docs-translations/es/styleguide.md 2015-10-08 23:16:15 -07:00
Mario Zaizar
d61bec0fb8 Adding missing links to /docs-translations/es/README.md and improving some texts. 2015-10-08 22:56:11 -07:00
Cheng Zhao
442db4c5ba Merge branch 'xcode-7' of https://github.com/joshaber/electron into joshaber-xcode-7 2015-10-09 12:29:45 +08:00
Cheng Zhao
922fce1892 Merge pull request #3040 from theojulienne/accessibility-fixes
Fix Text to Speech on OS X 10.11
2015-10-09 12:25:11 +08:00
Cheng Zhao
38b27bbd66 Merge pull request #3036 from renatoalencar/master
Add pt-BR translation for quick-start guide
2015-10-09 10:17:02 +08:00
Theo Julienne
6bc59cf2d7 Enable accessibility tree only when VoiceOver enabled, fixes atom/atom#3288. 2015-10-08 15:56:26 -07:00
Theo Julienne
957de56343 NSWorkspace selectFile:inFileViewerRootedAtPath: requires a non-null second argument. 2015-10-08 11:25:05 -07:00
Renato Alencar
1a2b5834ed Merge branch 'master' of https://www.github.com/atom/electron 2015-10-08 12:41:56 -03:00
Cheng Zhao
59b43a6571 Merge pull request #3025 from janwiemers/master
add a --app parameter to the default_app
2015-10-08 16:26:05 +08:00
Jan Wiemers
1a55cd3efe remove the --app option from the default_app documentation 2015-10-08 10:22:37 +02:00
Cheng Zhao
c8122392de Merge pull request #3033 from deepak1556/response_headers_patch
webcontents: dont modify response header value
2015-10-08 16:16:23 +08:00
Cheng Zhao
8b7d2b5ce3 Update brightray and crashpad for XCode 7 fixes 2015-10-08 16:09:22 +08:00
Robo
d9c6cf7b75 webcontents: dont modify response header value 2015-10-08 11:31:41 +05:30
Cheng Zhao
e1318ffb34 Merge pull request #3010 from deepak1556/guest_zoom_level_patch
webcontents: notify guests of embedders' zoom level change
2015-10-08 13:52:22 +08:00
Robo
7756bb6762 webcontents: notify guests of embedders' zoom level change 2015-10-08 10:38:22 +05:30
Cheng Zhao
d9cf9a7cbc docs: Fix wrong level for API titles 2015-10-08 11:14:04 +08:00
Cheng Zhao
87faae1b13 Merge pull request #3027 from stevekinney/minor-style-update-global-shortcut
Minor style update to the global-shortcut documentation
2015-10-08 10:47:39 +08:00
Cheng Zhao
051548aa69 Merge pull request #3024 from preco21/master
Improve grammar, fix small typos
2015-10-08 10:47:00 +08:00
Cheng Zhao
9dd714f056 Fix postMessage not working for windows opened by window.open 2015-10-08 10:44:30 +08:00
Cheng Zhao
fe4d86925b Merge pull request #3020 from atom/fix-switch-path
Fix a wrong usage of switch commandline.
2015-10-08 10:37:09 +08:00
Cheng Zhao
617892400f Merge pull request #3030 from atom/fix-xcode-6
Fix building with Xcode 6
2015-10-08 10:31:41 +08:00
Cheng Zhao
73ab6d409b Fix building with Xcode 6 2015-10-08 10:19:24 +08:00
Cheng Zhao
55715bec23 Merge pull request #3017 from Meyito/API-es
Translations of some of the Electron docs API in Spanish
2015-10-08 09:37:21 +08:00
Cheng Zhao
115526424a Move native modules to optionalDependencies
Fixes #3016.
2015-10-08 09:25:31 +08:00
Renato Alencar
aebc1d0650 grammar and corrections 2015-10-07 18:57:43 -03:00
Jan Wiemers
c7dc901607 add --app parameter and update the example usage in the default_app #1877 2015-10-07 23:22:00 +02:00
Renato Alencar
b1ae60a639 grammar corrections 2015-10-07 14:24:09 -03:00
Renato Alencar
7e7b6df72b Merge branch 'master' of https://github.com/renatoalencar/electron 2015-10-07 14:13:27 -03:00
Renato Alencar
05f0b5a8a4 add quick-start guide pt-BR translation 2015-10-07 14:11:58 -03:00
Steve Kinney
2978beaeb7 💄 Add preposition to globalShortcut.unregisterAll() 2015-10-07 09:03:46 -07:00
Steve Kinney
6f61832a34 💄 Add semicolon to global-shortcut code example
This keeps this line consistent with the rest of the documentation.
2015-10-07 09:03:11 -07:00
Plusb Preco
63c1fdd22a Improve grammar
* Improve the `auto-updater.md` content grammar.
2015-10-07 20:46:57 +09:00
Plusb Preco
3966441d21 Fix small typos 2015-10-07 20:20:34 +09:00
Plusb Preco
579f253340 Fix small typo 2015-10-07 20:19:37 +09:00
Haojian Wu
821005e6b4 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.
2015-10-07 12:17:49 +08:00
Meyito
871571c65e Translations of some of the Electron docs API in Spanish 2015-10-06 22:09:57 -05:00
joshaber
326af3cbe3 Use Xcode 7. 2015-10-06 16:34:20 -04:00
joshaber
4c3fd38774 This now has to be non-nil. 2015-10-06 16:15:03 -04:00
joshaber
74be1d5b25 ++brightray 2015-10-06 16:14:49 -04:00
joshaber
cab466f999 ++crashpad 2015-10-06 16:14:44 -04:00
joshaber
4cb3e2ecb5 Merge remote-tracking branch 'atom/master' 2015-10-06 14:24:05 -04:00
Eran Tiktin
cb22b88e6a Merge pull request #9 from atom/master
Update from original
2015-10-06 19:26:36 +03:00
Cheng Zhao
5bdc077b48 Update brightray for #2855 2015-10-06 22:45:00 +08:00
Cheng Zhao
927c3f34c3 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.
2015-10-06 22:25:55 +08:00
Cheng Zhao
c916baa939 Update brightray, fix #2315 2015-10-06 21:40:08 +08:00
Cheng Zhao
3a97439fe9 Merge pull request #3005 from preco21/master
Update as upstream
2015-10-06 21:27:50 +08:00
Plusb Preco
c6d5a92d34 Update as upstream 2015-10-06 19:53:35 +09:00
Cheng Zhao
2d802d6f1e Merge branch 'master' into no-vistas-no-problem 2015-10-06 17:02:08 +08:00
Cheng Zhao
fa59ea3bc5 Merge pull request #2998 from brenca/master
Minor fixes to sendInputEvent API.
2015-10-06 16:56:26 +08:00
Cheng Zhao
804cf5e8ba Merge pull request #2994 from etiktin/update_native_modules_doc
Update native modules doc
2015-10-06 16:55:25 +08:00
Cheng Zhao
fc0153f0bc Merge pull request #2993 from etiktin/update_screen_doc
Update screen.md
2015-10-06 16:55:16 +08:00
Cheng Zhao
c823e31904 Merge pull request #2992 from etiktin/update_process_doc
Update process.md
2015-10-06 16:55:10 +08:00
Cheng Zhao
2ef66cb660 Merge pull request #2997 from atom/size-constraints
Improve how we handle min/max sizes
2015-10-06 16:54:45 +08:00
Cheng Zhao
f607e81fac views: Make size constraints work immediately after set 2015-10-06 16:16:02 +08:00
Cheng Zhao
e06778178a linux: Restore size constraints when became sizable 2015-10-06 16:09:03 +08:00
Cheng Zhao
f6327de7f7 spec: Increase timeout for window.open specs 2015-10-06 16:08:32 +08:00
Cheng Zhao
8e40947938 spec: Make window.open specs more reliable 2015-10-06 15:43:36 +08:00
Cheng Zhao
898db4d6bd osx: Set resizable flag when creating window
Setting resizable for frameless window before it is shown will change
its size.
2015-10-06 15:23:23 +08:00
Cheng Zhao
6fea6cf58a osx: Fix setting size constraints for frameless window 2015-10-06 15:15:23 +08:00
Cheng Zhao
428c5b6d01 Setting "x" and "y" should not change window size 2015-10-06 14:50:18 +08:00
Plusb Preco
3f37439da3 Merge remote-tracking branch 'atom/master' 2015-10-06 13:55:06 +09:00
Plusb Preco
db46c1b925 Update as upstream 2015-10-06 13:48:39 +09:00
Eran Tiktin
c3cd438d34 Replace io.js references with node.js references 2015-10-05 21:12:29 +03:00
Heilig Benedek
ccf4ed907a Fix some minor bugs related to KeyboardEvent sending 2015-10-05 19:11:20 +02:00
Cheng Zhao
b70e7c6a4c Remove default definition of ContentSizeToWindowSize 2015-10-06 00:39:16 +08:00
Heilig Benedek
4d302956d3 Merge pull request #1 from atom/master
update
2015-10-05 18:32:04 +02:00
Cheng Zhao
c8723238f8 win: Fix building on Windows 2015-10-06 00:21:37 +08:00
Cheng Zhao
60fb406c61 views: Fix content size constraints in window with menubar 2015-10-06 00:15:47 +08:00
Cheng Zhao
bb49515145 Separate Windows specific code of NativeWindow to another file 2015-10-06 00:13:57 +08:00
Eran Tiktin
87e0c812e9 Update native modules doc 2015-10-05 17:48:48 +03:00
Eran Tiktin
ea3e84e7ff Update screen.md
Removed a trailing comma.
2015-10-05 16:56:36 +03:00
Eran Tiktin
239b97cde1 Update process.md
Fixed the `loaded` example according to
[this](https://github.com/atom/electron/issues/2984#issuecomment-145465907)
comment.
2015-10-05 16:51:49 +03:00
Eran Tiktin
c22ffd863b Merge pull request #8 from atom/master
Update from original
2015-10-05 16:41:30 +03:00
Cheng Zhao
857acd2574 win: Fix GetContentSize for minimized window 2015-10-05 21:06:57 +08:00
Cheng Zhao
3b1ee994e2 views: Remove hack on setting min/max size for frameless window 2015-10-05 20:37:08 +08:00
Cheng Zhao
e675407552 Make min/max size respect use-content-size 2015-10-05 20:36:28 +08:00
Cheng Zhao
d19ead1907 osx: Call setContentMinSize in SetContentSizeConstraints 2015-10-05 20:09:29 +08:00
Cheng Zhao
a9b0111c3e 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.
2015-10-05 20:07:20 +08:00
Cheng Zhao
279407f7a3 osx: Fix converting size for frameless window 2015-10-05 20:07:20 +08:00
Cheng Zhao
a76ea00249 views: Implement NativeWindow::SetSizeConstraints 2015-10-05 20:07:20 +08:00
Cheng Zhao
8577f2b52f osx: Add NativeWindow::SetSizeConstraints 2015-10-05 20:07:20 +08:00
Cheng Zhao
526cee7ec3 Merge tag 'v0.33.6' 2015-10-05 19:58:47 +08:00
Cheng Zhao
2b9b4c6789 Merge pull request #2979 from etiktin/fix_calculating_min_max_4_frameless
Fix calculating min/max size in frameless view
2015-10-05 15:10:27 +08:00
Cheng Zhao
de24ed7cea Merge pull request #2985 from etiktin/fix_restore_size_windows
[Windows] Fix restore/unmaximize wrong window size
2015-10-05 15:09:24 +08:00
Eran Tiktin
c34c123b33 Make it work only on Windows
Limiting the solution to Windows only.
2015-10-05 04:01:25 +03:00
Eran Tiktin
4d02fc58fa Fix restore/unmaximize wrong window size
This resolves #2498.
2015-10-05 03:29:02 +03:00
Eran Tiktin
aea1f8aebb 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).
2015-10-03 22:09:57 +03:00
Paul Betts
bb938b02d8 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
2015-10-03 09:02:50 -07:00
Eran Tiktin
8c31c7fb59 Merge pull request #7 from atom/master
Update from original
2015-10-03 01:25:23 +03:00
joshaber
2365ffe143 Merge remote-tracking branch 'atom/master' 2015-09-20 22:46:36 +01:00
Patrick Detlefsen
6c4016af46 make sure the query params are stripped from the updateUrl 2015-06-22 15:51:47 +02:00
Patrick Detlefsen
154ca8575c limit the auto-updater-win api to very few methods 2015-06-22 15:33:08 +02:00
Patrick Detlefsen
ae5411c37b move squirrel bahaviour into proper place 2015-06-22 15:17:07 +02:00
Patrick Detlefsen
62882fe49e auto updater win is an EventEmitter already 2015-06-16 16:13:23 +02:00
Patrick Detlefsen
a8469fc79d auto-updater extends event-emitter 2015-06-16 12:31:55 +02:00
Patrick Detlefsen
7aa60baafb switch statement coffee else instead of default 2015-06-16 11:48:39 +02:00
Patrick Detlefsen
99f352228c addresses suggestions from pull-request 2015-06-16 11:04:37 +02:00
Patrick Detlefsen
621178f558 initial idea 2015-06-15 20:28:47 +02:00
173 changed files with 6185 additions and 991 deletions

View File

@@ -10,6 +10,7 @@ os:
- osx
env:
- TARGET_ARCH=x64
osx_image: xcode7
matrix:
include:

View File

@@ -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)를 팔로우 하세요.
@@ -47,9 +47,13 @@ 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을 간단히 접해볼 수 있습니다.
## 커뮤니티
다음 링크를 통해 커뮤니티에 질문을 올리거나 토론을 나누실 수 있습니다:
다음 링크를 통해 커뮤니티에 질문을 올리거나 토론을 나 수 있습니다:
- Atom 포럼의 [`electron`](http://discuss.atom.io/category/electron) 카테고리
- Freenode 채팅의 `#atom-shell` 채널

View File

@@ -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).
@@ -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

View File

@@ -4,7 +4,7 @@
'product_name%': 'Electron',
'company_name%': 'GitHub, Inc',
'company_abbr%': 'github',
'version%': '0.33.6',
'version%': '0.34.1',
},
'includes': [
'filenames.gypi',
@@ -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',
@@ -285,12 +296,28 @@
'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"
'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': [
'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',
],
}], # OS=="mac" and mas_build==1
['OS=="linux"', {
'link_settings': {
'ldflags': [
@@ -393,9 +420,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,
@@ -439,12 +463,6 @@
'<@(copied_libraries)',
],
},
{
'destination': '<(PRODUCT_DIR)/<(product_name) Framework.framework/Versions/A/Resources',
'files': [
'<(PRODUCT_DIR)/crashpad_handler',
],
},
],
'postbuilds': [
{
@@ -476,6 +494,25 @@
],
},
],
'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',
'files': [
'<(PRODUCT_DIR)/crashpad_handler',
],
},
],
}],
],
}, # target framework
{
'target_name': '<(project_name)_helper',

View File

@@ -99,7 +99,7 @@ void AtomContentClient::AddAdditionalSchemes(
void AtomContentClient::AddPepperPlugins(
std::vector<content::PepperPluginInfo>* 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

View File

@@ -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")

View File

@@ -5,6 +5,7 @@
#include "atom/app/atom_main_delegate.h"
#include <string>
#include <iostream>
#include "atom/app/atom_content_client.h"
#include "atom/browser/atom_browser_client.h"
@@ -20,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() {
}
@@ -27,8 +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.
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;
@@ -43,19 +59,25 @@ 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))
scoped_ptr<base::Environment> 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);
}
logging::InitLogging(settings);
// 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);
}
@@ -77,7 +99,7 @@ void AtomMainDelegate::PreSandboxStartup() {
}
// Only append arguments for browser process.
if (!process_type.empty())
if (!IsBrowserProcess(command_line))
return;
#if defined(OS_WIN)

View File

@@ -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<const char**>(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<UvTaskRunner> 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<const char**>(argv), &exec_argc, &exec_argv);
node::Environment* env = node::CreateEnvironment(
gin_env.isolate(), loop, gin_env.context(), argc, argv,
exec_argc, exec_argv);

View File

@@ -48,8 +48,13 @@ void UvTaskRunner::OnTimeout(uv_timer_t* timer) {
self->tasks_[timer].Run();
self->tasks_.erase(timer);
uv_unref(reinterpret_cast<uv_handle_t*>(timer));
delete timer;
uv_timer_stop(timer);
uv_close(reinterpret_cast<uv_handle_t*>(timer), UvTaskRunner::OnClose);
}
// static
void UvTaskRunner::OnClose(uv_handle_t* handle) {
delete reinterpret_cast<uv_timer_t*>(handle);
}
} // namespace atom

View File

@@ -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_;

View File

@@ -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"
@@ -109,6 +111,23 @@ int GetPathConstant(const std::string& name) {
return -1;
}
bool NotificationCallbackWrapper(
const ProcessSingleton::NotificationCallback& callback,
const base::CommandLine::StringVector& 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<base::SingleThreadTaskRunner> 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();
}
void OnClientCertificateSelected(
v8::Isolate* isolate,
std::shared_ptr<content::ClientCertificateDelegate> delegate,
@@ -158,6 +177,11 @@ void App::OnWindowAllClosed() {
void App::OnQuit() {
Emit("quit");
if (process_singleton_.get()) {
process_singleton_->Cleanup();
process_singleton_.reset();
}
}
void App::OnOpenFile(bool* prevent_default, const std::string& file_path) {
@@ -249,6 +273,12 @@ void App::SetAppUserModelId(const std::string& app_id) {
#endif
}
void App::AllowNTLMCredentialsForAllDomains(bool should_allow) {
auto browser_context = static_cast<AtomBrowserContext*>(
AtomBrowserMainParts::Get()->browser_context());
browser_context->AllowNTLMCredentialsForAllDomains(should_allow);
}
std::string App::GetLocale() {
return l10n_util::GetApplicationLocale("");
}
@@ -260,6 +290,28 @@ v8::Local<v8::Value> App::DefaultSession(v8::Isolate* isolate) {
return v8::Local<v8::Value>::New(isolate, default_session_);
}
bool App::MakeSingleInstance(
const ProcessSingleton::NotificationCallback& callback) {
if (process_singleton_.get())
return false;
base::FilePath user_dir;
PathService::Get(brightray::DIR_USER_DATA, &user_dir);
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();
return true;
case ProcessSingleton::NotifyResult::PROCESS_NONE:
default: // Shouldn't be needed, but VS warns if it is not there.
return false;
}
}
mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
auto browser = base::Unretained(Browser::Get());
@@ -283,7 +335,10 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
.SetMethod("getPath", &App::GetPath)
.SetMethod("setDesktopName", &App::SetDesktopName)
.SetMethod("setAppUserModelId", &App::SetAppUserModelId)
.SetMethod("allowNTLMCredentialsForAllDomains",
&App::AllowNTLMCredentialsForAllDomains)
.SetMethod("getLocale", &App::GetLocale)
.SetMethod("makeSingleInstance", &App::MakeSingleInstance)
.SetProperty("defaultSession", &App::DefaultSession);
}
@@ -301,6 +356,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);

View File

@@ -9,6 +9,8 @@
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/browser_observer.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"
@@ -65,11 +67,16 @@ 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 ProcessSingleton::NotificationCallback& callback);
std::string GetLocale();
v8::Local<v8::Value> DefaultSession(v8::Isolate* isolate);
v8::Global<v8::Value> default_session_;
scoped_ptr<ProcessSingleton> process_singleton_;
DISALLOW_COPY_AND_ASSIGN(App);
};

View File

@@ -5,12 +5,31 @@
#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/native_mate_converters/callback.h"
#include "atom/common/node_includes.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
namespace mate {
template<>
struct Converter<base::Time> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::Time& val) {
v8::MaybeLocal<v8::Value> 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 {
@@ -20,11 +39,18 @@ AutoUpdater::AutoUpdater() {
}
AutoUpdater::~AutoUpdater() {
auto_updater::AutoUpdater::SetDelegate(NULL);
auto_updater::AutoUpdater::SetDelegate(nullptr);
}
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() {
@@ -42,11 +68,14 @@ 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 base::Closure& quit_and_install) {
quit_and_install_ = quit_and_install;
Emit("update-downloaded-raw", release_notes, release_name,
release_date.ToJsTime(), update_url);
const std::string& 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() {
QuitAndInstall();
}
mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder(
@@ -54,14 +83,21 @@ mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder(
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

View File

@@ -7,9 +7,9 @@
#include <string>
#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<AutoUpdater> 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);
};

View File

@@ -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"
@@ -104,6 +105,24 @@ struct Converter<ClearStorageDataOptions> {
}
};
template<>
struct Converter<net::ProxyConfig> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> 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 {
@@ -208,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);
}
@@ -237,6 +256,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),
@@ -284,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) {

View File

@@ -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<Session>,
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();

View File

@@ -31,6 +31,7 @@
#include "chrome/browser/printing/print_view_manager_basic.h"
#include "chrome/browser/printing/print_preview_message_handler.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/navigation_details.h"
@@ -51,6 +52,7 @@
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/base/l10n/l10n_util.h"
#include "atom/common/node_includes.h"
@@ -62,9 +64,21 @@ struct PrintSettings {
};
void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
std::string accept_lang,
std::string user_agent) {
getter->GetURLRequestContext()->set_http_user_agent_settings(
new net::StaticHttpUserAgentSettings("en-us,en", user_agent));
new net::StaticHttpUserAgentSettings(
net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang),
user_agent));
}
bool NotifyZoomLevelChanged(
double level, content::WebContents* guest_web_contents) {
guest_web_contents->SendToAllFrames(
new AtomViewMsg_SetZoomLevel(MSG_ROUTING_NONE, level));
// Return false to iterate over all guests.
return false;
}
} // namespace
@@ -133,7 +147,6 @@ struct Converter<net::HttpResponseHeaders*> {
std::string value;
while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
key = base::StringToLowerASCII(key);
value = base::StringToLowerASCII(value);
if (response_headers.HasKey(key)) {
base::ListValue* values = nullptr;
if (response_headers.GetList(key, &values))
@@ -149,6 +162,26 @@ struct Converter<net::HttpResponseHeaders*> {
}
};
template<>
struct Converter<content::SavePageType> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> 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
@@ -528,6 +561,7 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage)
IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync,
OnRendererMessageSync)
IPC_MESSAGE_HANDLER(AtomViewHostMsg_ZoomLevelChanged, OnZoomLevelChanged)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -637,8 +671,10 @@ void WebContents::SetUserAgent(const std::string& user_agent) {
web_contents()->SetUserAgentOverride(user_agent);
scoped_refptr<net::URLRequestContextGetter> getter =
web_contents()->GetBrowserContext()->GetRequestContext();
auto accept_lang = l10n_util::GetApplicationLocale("");
getter->GetNetworkTaskRunner()->PostTask(FROM_HERE,
base::Bind(&SetUserAgentInIO, getter, user_agent));
base::Bind(&SetUserAgentInIO, getter, accept_lang, user_agent));
}
std::string WebContents::GetUserAgent() {
@@ -649,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));
@@ -960,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)
@@ -1033,6 +1077,15 @@ void WebContents::OnRendererMessageSync(const base::string16& channel,
EmitWithSender(base::UTF16ToUTF8(channel), web_contents(), message, args);
}
void WebContents::OnZoomLevelChanged(double level) {
auto manager = web_contents()->GetBrowserContext()->GetGuestManager();
if (!manager)
return;
manager->ForEachGuest(web_contents(),
base::Bind(&NotifyZoomLevelChanged,
level));
}
// static
mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents) {

View File

@@ -9,6 +9,7 @@
#include <vector>
#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<WebContents>,
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);
@@ -247,6 +251,10 @@ class WebContents : public mate::TrackableObject<WebContents>,
const base::ListValue& args,
IPC::Message* message);
// Called when guests need to be notified of
// embedders' zoom level change.
void OnZoomLevelChanged(double level);
v8::Global<v8::Value> session_;
v8::Global<v8::Value> devtools_web_contents_;

View File

@@ -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)

View File

@@ -122,6 +122,7 @@ class Window : public mate::TrackableObject<Window>,
void SetSkipTaskbar(bool skip);
void SetKiosk(bool kiosk);
bool IsKiosk();
void SetBackgroundColor(const std::string& color_name);
void FocusOnWebView();
void BlurWebView();
bool IsWebViewFocused();

View File

@@ -1,24 +1,7 @@
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
@emit 'update-downloaded', args..., => @quitAndInstall()
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')

View File

@@ -0,0 +1,6 @@
{EventEmitter} = require 'events'
{autoUpdater} = process.atomBinding 'auto_updater'
autoUpdater.__proto__ = EventEmitter.prototype
module.exports = autoUpdater

View File

@@ -0,0 +1,42 @@
app = require 'app'
url = require 'url'
{EventEmitter} = require 'events'
squirrelUpdate = require './squirrel-update-win'
class AutoUpdater extends EventEmitter
quitAndInstall: ->
squirrelUpdate.processStart()
app.quit()
setFeedUrl: (updateUrl) ->
@updateUrl = updateUrl
checkForUpdates: ->
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) =>
return @emitError error if error?
return @emit 'update-not-available' unless update?
@emit 'update-available'
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
@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

View File

@@ -0,0 +1,67 @@
fs = require 'fs'
path = require 'path'
{spawn} = require 'child_process'
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, detached, callback) ->
try
spawnedProcess = spawn updateExe, args, {detached}
catch error
# 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
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
# Process terminated with error.
if code isnt 0
return callback "Command failed: #{signal ? code}\n#{stderr}"
# 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()
update = JSON.parse(json)?.releasesToApply?.pop?()
catch
return callback "Invalid result:\n#{stdout}"
callback null, update
# 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 = ->
try
fs.accessSync updateExe, fs.R_OK
return true
catch
return false

View File

@@ -0,0 +1,83 @@
// 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 <string>
#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);
// 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,
saved_main_directory_path,
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<v8::String> 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

View File

@@ -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 <string>
#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<void(v8::Local<v8::Value>)>;
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_

View File

@@ -60,7 +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 +169,16 @@ void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
base::FilePath());
}
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;
}
} // namespace atom
namespace brightray {

View File

@@ -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;
@@ -36,6 +37,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_; }
private:
@@ -45,6 +48,8 @@ class AtomBrowserContext : public brightray::BrowserContext {
// Managed by brightray::BrowserContext.
AtomURLRequestJobFactory* job_factory_;
bool allow_ntlm_everywhere_;
DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext);
};

View File

@@ -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();
@@ -107,6 +105,7 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() {
1000));
brightray::BrowserMainParts::PreMainMessageLoopRun();
BridgeTaskRunner::MessageLoopIsReady();
#if defined(USE_X11)
libgtk2ui::GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess());

View File

@@ -5,11 +5,14 @@
#include "atom/browser/atom_ssl_config_service.h"
#include <string>
#include <vector>
#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<uint16> ParseCipherSuites(
const std::vector<std::string>& cipher_strings) {
std::vector<uint16> 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() {

View File

@@ -6,14 +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)
void AutoUpdater::SetFeedURL(const std::string& url) {
}
void AutoUpdater::CheckForUpdates() {
}
void AutoUpdater::QuitAndInstall() {
}
#endif
} // namespace auto_updater

View File

@@ -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);
};

View File

@@ -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 <string>
#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_

View File

@@ -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

View File

@@ -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 <iostream>
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

View File

@@ -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

View File

@@ -8,13 +8,33 @@
namespace atom {
// static
std::vector<BridgeTaskRunner::TaskPair> BridgeTaskRunner::tasks_;
std::vector<BridgeTaskRunner::TaskPair> 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);

View File

@@ -5,17 +5,23 @@
#ifndef ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_
#define ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_
#include <vector>
#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<TaskPair> tasks_;
static std::vector<TaskPair> non_nestable_tasks_;
DISALLOW_COPY_AND_ASSIGN(BridgeTaskRunner);
};

View File

@@ -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 {

View File

@@ -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_; }

View File

@@ -18,6 +18,9 @@ for (var i = 0; i < argv.length; i++) {
if (argv[i] == '--version' || argv[i] == '-v') {
option.version = true;
break;
} else if (argv[i].match(/^--app=/)) {
option.file = argv[i].split('=')[1];
break;
} else if (argv[i] == '--help' || argv[i] == '-h') {
option.help = true;
break;
@@ -260,7 +263,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 += " -r, --require Module to preload (option can be repeated)\n";
helpMessage += " -h, --help Print this usage message.\n";
helpMessage += " -v, --version Print the version.";
console.log(helpMessage);

View File

@@ -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,7 +21,12 @@ JavascriptEnvironment::JavascriptEnvironment()
}
bool JavascriptEnvironment::Initialize() {
gin::V8Initializer::LoadV8Snapshot();
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;

View File

@@ -67,7 +67,7 @@ ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestId, method,
ipc.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 '*'
guestContents.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', message, targetOrigin
guestContents.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, targetOrigin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, guestId, message, targetOrigin, sourceOrigin) ->
embedder = v8Util.getHiddenValue event.sender, 'embedder'

View File

@@ -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...) ->
process.log util.format(args...)
console.log = console.error = console.warn = print
process.stdout.write = process.stderr.write = print
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

View File

@@ -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'

View File

@@ -10,6 +10,8 @@ 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 = 'date' if value instanceof Date
meta.type = 'promise' if value? and value.constructor.name is 'Promise'
# Treat simple objects as value.
@@ -36,6 +38,10 @@ 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 if meta.type is 'date'
meta.value = value.getTime()
else
meta.type = 'value'
meta.value = value
@@ -43,8 +49,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) ->
@@ -69,7 +75,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
@@ -98,19 +106,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
@@ -124,7 +132,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
@@ -132,7 +140,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
@@ -142,7 +150,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
@@ -150,7 +158,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
@@ -158,14 +166,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
@@ -175,4 +183,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

View File

@@ -43,11 +43,20 @@
atom::Browser::Get()->OpenURL(base::SysNSStringToUTF8(url));
}
- (bool)voiceOverEnabled {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults addSuiteNamed:@"com.apple.universalaccess"];
[defaults synchronize];
return [defaults boolForKey:@"voiceOverOnOffKey"];
}
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
// Undocumented attribute that VoiceOver happens to set while running.
// Chromium uses this too, even though it's not exactly right.
if ([attribute isEqualToString:@"AXEnhancedUserInterface"]) {
[self updateAccessibilityEnabled:[value boolValue]];
bool enableAccessibility = ([self voiceOverEnabled] && [value boolValue]);
[self updateAccessibilityEnabled:enableAccessibility];
}
return [super accessibilitySetValue:value forAttribute:attribute];
}

View File

@@ -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<SkRegion> DraggableRegionsToSkRegion(
const std::vector<DraggableRegion>& regions) {
scoped_ptr<SkRegion> 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)
@@ -112,27 +92,35 @@ 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, &center) && 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)) {
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);
}
#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);
@@ -151,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);
@@ -178,6 +170,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) {
}
@@ -411,6 +464,20 @@ void NativeWindow::NotifyWindowExecuteWindowsCommand(
OnExecuteWindowsCommand(command));
}
scoped_ptr<SkRegion> NativeWindow::DraggableRegionsToSkRegion(
const std::vector<DraggableRegion>& regions) {
scoped_ptr<SkRegion> 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_)

View File

@@ -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;
@@ -127,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);
@@ -234,6 +242,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<SkRegion> DraggableRegionsToSkRegion(
const std::vector<DraggableRegion>& 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<DraggableRegion>& regions);
// content::WebContentsObserver:
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void BeforeUnloadDialogCancelled() override;
@@ -241,10 +262,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<DraggableRegion>& regions);
// Schedule a notification unresponsive event.
void ScheduleUnresponsiveEvent(int ms);
@@ -269,6 +286,9 @@ class NativeWindow : public base::SupportsUserData,
// has to been explicitly provided.
scoped_ptr<SkRegion> 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_;

View File

@@ -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;
@@ -61,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;
@@ -75,12 +72,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:
@@ -88,13 +83,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<gfx::Rect> CalculateNonDraggableRegions(
const std::vector<DraggableRegion>& 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<DraggableRegion>& 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<DraggableRegion>& regions);
base::scoped_nsobject<AtomNSWindow> window_;
base::scoped_nsobject<AtomNSWindowDelegate> window_delegate_;
@@ -102,6 +108,8 @@ class NativeWindowMac : public NativeWindow {
// The view that will fill the whole frameless window.
base::scoped_nsobject<FullSizeContentView> content_view_;
std::vector<DraggableRegion> draggable_regions_;
bool is_kiosk_;
NSInteger attention_request_id_; // identifier from requestUserAttention
@@ -109,10 +117,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);
};

View File

@@ -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
@@ -350,6 +332,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 +341,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;
@@ -434,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() {
@@ -549,56 +531,30 @@ 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) {
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 = convertSize(size_constraints.GetMinimumSize());
[window_ setContentMinSize:[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 = convertSize(size_constraints.GetMaximumSize());
[window_ setContentMaxSize:[content convertSize:max_size toView:nil]];
}
NativeWindow::SetContentSizeConstraints(size_constraints);
}
void NativeWindowMac::SetResizable(bool resizable) {
@@ -679,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)];
}
@@ -767,36 +726,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) {
@@ -821,6 +750,48 @@ void NativeWindowMac::HandleKeyboardEvent(
}
}
std::vector<gfx::Rect> NativeWindowMac::CalculateNonDraggableRegions(
const std::vector<DraggableRegion>& regions, int width, int height) {
std::vector<gfx::Rect> result;
if (regions.empty()) {
result.push_back(gfx::Rect(0, 0, width, height));
} else {
scoped_ptr<SkRegion> draggable(DraggableRegionsToSkRegion(regions));
scoped_ptr<SkRegion> 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;
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);
}
void NativeWindowMac::UpdateDraggableRegions(
const std::vector<DraggableRegion>& 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];
@@ -843,8 +814,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];
@@ -861,14 +830,55 @@ void NativeWindowMac::UninstallView() {
[view removeFromSuperview];
}
void NativeWindowMac::InstallDraggableRegionView() {
void NativeWindowMac::UpdateDraggableRegionViews(
const std::vector<DraggableRegion>& 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<NSView> 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<NSArray> 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<gfx::Rect> 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<gfx::Rect>::const_iterator iter =
system_drag_exclude_areas.begin();
iter != system_drag_exclude_areas.end();
++iter) {
base::scoped_nsobject<NSView> 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

View File

@@ -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"
@@ -77,69 +78,28 @@ 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";
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;
}
#endif
class NativeWindowClientView : public views::ClientView {
public:
@@ -186,7 +146,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);
@@ -268,13 +229,8 @@ NativeWindowViews::NativeWindowViews(
// Add web view.
SetLayoutManager(new MenuLayout(this, kMenuBarHeight));
set_background(views::Background::CreateStandardPanelBackground());
AddChildView(web_view_);
if (has_frame() &&
options.Get(switches::kUseContentSize, &use_content_size_) &&
use_content_size_)
bounds = ContentBoundsToWindowBounds(bounds);
AddChildView(web_view_);
#if defined(OS_WIN)
// Save initial window state.
@@ -283,6 +239,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.
@@ -314,8 +272,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();
}
@@ -438,42 +402,26 @@ gfx::Rect NativeWindowViews::GetBounds() {
return window_->GetWindowBoundsInScreen();
}
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();
#if defined(OS_WIN)
if (IsMinimized())
return NativeWindow::GetContentSize();
#endif
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;
return web_view_->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::SetContentSizeConstraints(
const extensions::SizeConstraints& size_constraints) {
NativeWindow::SetContentSizeConstraints(size_constraints);
// 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;
#endif
}
void NativeWindowViews::SetResizable(bool resizable) {
@@ -492,11 +440,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
@@ -570,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
@@ -608,8 +573,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);
}
}
}
@@ -812,68 +793,47 @@ void NativeWindowViews::OnWidgetMove() {
NotifyWindowMove();
}
gfx::Size NativeWindowViews::ContentSizeToWindowSize(const gfx::Size& size) {
if (!has_frame())
return size;
gfx::Size window_size(size);
#if defined(OS_WIN)
bool NativeWindowViews::ExecuteWindowsCommand(int command_id) {
std::string command = AppCommandToString(command_id);
NotifyWindowExecuteWindowsCommand(command);
return false;
}
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)
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)
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;
}
}
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) {
@@ -915,6 +875,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);
@@ -937,26 +905,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;

View File

@@ -63,12 +63,9 @@ class NativeWindowViews : 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;
@@ -80,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,
@@ -140,20 +138,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();
@@ -170,12 +168,23 @@ class NativeWindowViews : public NativeWindow,
// Handles window state events.
scoped_ptr<WindowStateWatcher> 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_;
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
@@ -189,8 +198,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);

View File

@@ -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.
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;
}
}
} // namespace atom

View File

@@ -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.

View File

@@ -17,7 +17,11 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.33.6</string>
<string>0.34.1</string>
<key>CFBundleShortVersionString</key>
<string>0.34.1</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
<string>10.8.0</string>
<key>NSMainNibFile</key>

View File

@@ -56,8 +56,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,33,6,0
PRODUCTVERSION 0,33,6,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.33.6"
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.33.6"
VALUE "ProductVersion", "0.34.1"
VALUE "SquirrelAwareVersion", "1"
END
END

View File

@@ -55,7 +55,7 @@ void TrayIcon::NotifyRightClicked(const gfx::Rect& bounds, int modifiers) {
OnRightClicked(bounds, modifiers));
}
void TrayIcon::NotfiyDropFiles(const std::vector<std::string>& files) {
void TrayIcon::NotifyDropFiles(const std::vector<std::string>& files) {
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDropFiles(files));
}

View File

@@ -61,7 +61,7 @@ class TrayIcon {
void NotifyBalloonClosed();
void NotifyRightClicked(const gfx::Rect& bounds = gfx::Rect(),
int modifiers = 0);
void NotfiyDropFiles(const std::vector<std::string>& files);
void NotifyDropFiles(const std::vector<std::string>& files);
protected:
TrayIcon();

View File

@@ -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;

View File

@@ -104,11 +104,11 @@ gfx::Size FramelessView::GetPreferredSize() const {
}
gfx::Size FramelessView::GetMinimumSize() const {
return window_->GetMinimumSize();
return window_->GetContentSizeConstraints().GetMinimumSize();
}
gfx::Size FramelessView::GetMaximumSize() const {
return window_->GetMaximumSize();
return window_->GetContentSizeConstraints().GetMaximumSize();
}
const char* FramelessView::GetClassName() const {

View File

@@ -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) {
}

View File

@@ -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);
};

View File

@@ -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,16 +38,6 @@ int WinFrameView::NonClientHitTest(const gfx::Point& point) {
return FramelessView::NonClientHitTest(point);
}
gfx::Size WinFrameView::GetMinimumSize() const {
gfx::Size size = FramelessView::GetMinimumSize();
return gfx::win::DIPToScreenSize(size);
}
gfx::Size WinFrameView::GetMaximumSize() const {
gfx::Size size = FramelessView::GetMaximumSize();
return gfx::win::DIPToScreenSize(size);
}
const char* WinFrameView::GetClassName() const {
return kViewClassName;
}

View File

@@ -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:

View File

@@ -26,7 +26,6 @@ namespace {
const char* kWebRuntimeFeatures[] = {
switches::kExperimentalFeatures,
switches::kExperimentalCanvasFeatures,
switches::kSubpixelFontScaling,
switches::kOverlayScrollbars,
switches::kOverlayFullscreenVideo,
switches::kSharedWorker,

View File

@@ -30,6 +30,12 @@ IPC_SYNC_MESSAGE_ROUTED2_1(AtomViewHostMsg_Message_Sync,
base::ListValue /* arguments */,
base::string16 /* result (in JSON) */)
IPC_MESSAGE_ROUTED1(AtomViewHostMsg_ZoomLevelChanged,
double /* level */)
IPC_MESSAGE_ROUTED1(AtomViewMsg_SetZoomLevel,
double /* level */)
IPC_MESSAGE_ROUTED2(AtomViewMsg_Message,
base::string16 /* channel */,
base::ListValue /* arguments */)

View File

@@ -6,6 +6,7 @@
#include <algorithm>
#include <string>
#include <iostream>
#include "atom/common/atom_version.h"
#include "atom/common/chrome_version.h"
@@ -40,7 +41,7 @@ void FatalErrorCallback(const char* location, const char* message) {
}
void Log(const base::string16& message) {
logging::LogMessage("CONSOLE", 0, 0).stream() << message;
std::cout << message << std::flush;
}
} // namespace
@@ -71,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);

View File

@@ -1,16 +1,25 @@
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.
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
@@ -18,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]

View File

@@ -6,8 +6,8 @@
#define ATOM_VERSION_H
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 33
#define ATOM_PATCH_VERSION 6
#define ATOM_MINOR_VERSION 34
#define ATOM_PATCH_VERSION 1
#define ATOM_VERSION_IS_RELEASE 1

View File

@@ -64,4 +64,23 @@ CrashReporter::GetUploadedReports(const std::string& path) {
return result;
}
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() {
}
#if defined(OS_MACOSX) && defined(MAS_BUILD)
// static
CrashReporter* CrashReporter::GetInstance() {
static CrashReporter crash_reporter;
return &crash_reporter;
}
#endif
} // namespace crash_reporter

View File

@@ -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_;

View File

@@ -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,6 +43,94 @@ const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
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<NtTerminateProcessPtr>(
static_cast<char*>(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<CrashReporterWin*>(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<ExceptionHandlerRecord*>(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<DWORD>(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<DWORD64>(start)));
}
void UnregisterNonABICompliantCodeRange(void* start) {
ExceptionHandlerRecord* record =
reinterpret_cast<ExceptionHandlerRecord*>(start);
CHECK(RtlDeleteFunctionTable(&record->runtime_function));
}
#endif // _WIN64
} // namespace
CrashReporterWin::CrashReporterWin() {
@@ -63,26 +170,46 @@ 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)));
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() {
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,

View File

@@ -29,6 +29,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<CrashReporterWin>;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -61,7 +61,7 @@ struct Converter<blink::WebInputEvent::Type> {
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")

View File

@@ -152,6 +152,10 @@ v8::Local<v8::Value> V8ValueConverter::ToV8ValueImpl(
return ToV8Object(isolate,
static_cast<const base::DictionaryValue*>(value));
case base::Value::TYPE_BINARY:
return ToArrayBuffer(isolate,
static_cast<const base::BinaryValue*>(value));
default:
LOG(ERROR) << "Unexpected value type: " << value->GetType();
return v8::Null(isolate);
@@ -200,6 +204,13 @@ v8::Local<v8::Value> V8ValueConverter::ToV8Object(
return result.GetHandle();
}
v8::Local<v8::Value> 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<v8::Value> val,

View File

@@ -41,6 +41,9 @@ class V8ValueConverter {
v8::Local<v8::Value> ToV8Object(
v8::Isolate* isolate,
const base::DictionaryValue* dictionary) const;
v8::Local<v8::Value> ToArrayBuffer(
v8::Isolate* isolate,
const base::BinaryValue* value) const;
base::Value* FromV8ValueImpl(FromV8ValueState* state,
v8::Local<v8::Value> value,

View File

@@ -93,13 +93,15 @@ 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";
// 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";
@@ -117,6 +119,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";

View File

@@ -47,11 +47,11 @@ 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[];
extern const char kExperimentalCanvasFeatures[];
extern const char kSubpixelFontScaling[];
extern const char kOverlayScrollbars[];
extern const char kOverlayFullscreenVideo[];
extern const char kSharedWorker[];
@@ -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[];

View File

@@ -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();
}

View File

@@ -2,12 +2,12 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>${PRODUCT_NAME} Framework</string>
<key>CFBundleIdentifier</key>
<string>${ATOM_BUNDLE_ID}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME} Framework</string>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>

View File

@@ -4,11 +4,13 @@
#include "atom/renderer/api/atom_api_web_frame.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/renderer/api/atom_api_spell_check_client.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "third_party/WebKit/public/web/WebDocument.h"
@@ -34,6 +36,10 @@ void WebFrame::SetName(const std::string& name) {
}
double WebFrame::SetZoomLevel(double level) {
auto render_view = content::RenderView::FromWebView(web_frame_->view());
// Notify guests if any for zoom level change.
render_view->Send(
new AtomViewHostMsg_ZoomLevelChanged(MSG_ROUTING_NONE, level));
return web_frame_->view()->setZoomLevel(level);
}

View File

@@ -46,7 +46,9 @@ 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 'date' then new Date(meta.value)
when 'exception'
throw new Error("#{meta.message}\n#{meta.stack}")
else
if meta.type is 'function'

View File

@@ -6,6 +6,7 @@
#include <string>
#include "atom/common/api/api_messages.h"
#include "atom/common/api/atom_bindings.h"
#include "atom/common/node_bindings.h"
#include "atom/common/node_includes.h"
@@ -21,11 +22,13 @@
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_thread.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/web/WebCustomElement.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebPluginParams.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebView.h"
#if defined(OS_WIN)
#include <shlobj.h>
@@ -64,6 +67,22 @@ class AtomRenderFrameObserver : public content::RenderFrameObserver {
render_frame()->GetWebFrame(), context);
}
bool OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AtomRenderFrameObserver, message)
IPC_MESSAGE_HANDLER(AtomViewMsg_SetZoomLevel, OnSetZoomLevel)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void OnSetZoomLevel(double level) {
auto view = render_frame()->GetWebFrame()->view();
if (view)
view->setZoomLevel(level);
}
private:
AtomRendererClient* renderer_client_;
@@ -215,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))

View File

@@ -0,0 +1,86 @@
// 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 <shellapi.h>
#include <string>
#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 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;
// Send the command line to the remote chrome window.
// Format is "START\0<<<current directory>>>\0<<<commandline>>>".
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(::GetCommandLineW());
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<DWORD>((to_send.length() + 1) * sizeof(wchar_t));
cds.lpData = const_cast<wchar_t*>(to_send.c_str());
DWORD_PTR result = 0;
if (::SendMessageTimeout(remote_window, WM_COPYDATA, NULL,
reinterpret_cast<LPARAM>(&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

View File

@@ -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 <windows.h>
#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_

View File

@@ -0,0 +1,182 @@
// 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 <windows.h>
#endif // defined(OS_WIN)
#include <set>
#include <vector>
#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<bool(const base::CommandLine::StringVector& command_line,
const base::FilePath& current_directory)>;
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<bool()>;
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<void(int)>& callback);
#endif
private:
NotificationCallback notification_callback_; // Handler for notifications.
#if defined(OS_WIN)
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)
// 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.
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<void(int)> 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<LinuxWatcher> watcher_;
#endif
DISALLOW_COPY_AND_ASSIGN(ProcessSingleton);
};
#endif // CHROME_BROWSER_PROCESS_SINGLETON_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,328 @@
// 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 <shellapi.h>
#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/chrome_process_finder_win.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";
// 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<bool*>(param);
*result = ::IsWindowVisible(window) != 0;
// Stops enumeration if a visible window has been found.
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::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
// 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<wchar_t*>(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 = CommandLineStringToArgv(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<COPYDATASTRUCT*>(lparam);
base::CommandLine::StringVector parsed_command_line;
base::FilePath current_directory;
if (!ParseCommandLine(cds, &parsed_command_line, &current_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 (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<LPARAM>(&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;
}
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_ = chrome::FindRunningChromeWindow(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_ = 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());
// 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());
}
}
}
return window_.hwnd() != NULL;
}
void ProcessSingleton::Cleanup() {
}
void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting(
const ShouldKillRemoteProcessCallback& display_dialog_callback) {
should_kill_remote_process_callback_ = display_dialog_callback;
}

View File

@@ -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 <algorithm>
#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

View File

@@ -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_

View File

@@ -1,32 +1,33 @@
## Guías
* [Distribución de aplicaciones](tutorial/application-distribution.md)
* [Empaquetamiento de aplicaciones](tutorial/application-packaging.md)
* [Utilizando módulos nativos](tutorial/using-native-node-modules.md)
* [Depurando el proceso principal](tutorial/debugging-main-process.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)
* [Extensión DevTools](tutorial/devtools-extension.md)
* [Utilizando el plugin pepper flash](tutorial/using-pepper-flash-plugin.md)
* [Utilizando el plugin Pepper Flash](tutorial/using-pepper-flash-plugin.md)
## 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
## Referencias a la 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:
### Elementos DOM personalizados:
* [Objeto `File`](../../docs/api/file-object.md)
* [Etiqueta `<webview>`](../../docs/api/web-view-tag.md)
* [Función `window.open`](../../docs/api/window-open.md)
Módulos del proceso principal:
### Módulos del Proceso Principal:
* [app](../../docs/api/app.md)
* [auto-updater](../../docs/api/auto-updater.md)
@@ -34,21 +35,23 @@ Módulos del proceso principal:
* [content-tracing](../../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)
* [ipc (proceso principal)](../../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)
* [protocol](../../docs/api/protocol.md)
* [session](../../docs/api/session.md)
* [web-contents](../../docs/api/web-contents.md)
* [tray](../../docs/api/tray.md)
Módulos del renderer (página web):
### Módulos del proceso de renderizado (Página Web):
* [ipc (renderer)](../../docs/api/ipc-renderer.md)
* [ipc (renderizador)](../../docs/api/ipc-renderer.md)
* [remote](../../docs/api/remote.md)
* [web-frame](../../docs/api/web-frame.md)
Módulos de ambos procesos:
### Módulos de Ambos Procesos:
* [clipboard](../../docs/api/clipboard.md)
* [crash-reporter](../../docs/api/crash-reporter.md)
@@ -58,11 +61,11 @@ Módulos de ambos procesos:
## Desarrollo
* [Guía de estilo](../../docs/development/coding-style.md)
* [Estructura de directorio](../../docs/development/source-code-directory-structure.md)
* [Diferencias técnicas con NW.js (anteriormente conocido como node-webkit)](../../docs/development/atom-shell-vs-node-webkit.md)
* [Sistema de compilación](../../docs/development/build-system-overview.md)
* [Instrucciones de compilación (Mac)](../../docs/development/build-instructions-osx.md)
* [Instrucciones de compilación (Windows)](../../docs/development/build-instructions-windows.md)
* [Instrucciones de compilación (Linux)](../../docs/development/build-instructions-linux.md)
* [Configurando un servidor de símbolos en el depurador](../../docs/development/setting-up-symbol-server.md)
* [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)
* [Instrucciones de Compilación (Windows)](../../development/build-instructions-windows.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)

View File

@@ -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
módulo [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 caché 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 esté cargada.
## --v=`log_level`
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` cambiaría el nivel de registro para todo el código,
los archivos de origen `my_module.*` y `foo*.*`.
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`.
Este modificador sólo funciona cuando también se pasa `--enable-logging`.

View File

@@ -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.

View File

@@ -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 (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
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
<!DOCTYPE html>
<html>
<body>
<script>
var remote = require('remote');
console.log(remote.require('app').getVersion());
</script>
</body>
</html>
```
Para ejecutar tu aplicación, lee [Ejecutar la aplicación](../tutorial/quick-start.md#run-your-app).

View File

@@ -0,0 +1,100 @@
# Gúia de estilo de Electron
Encuentra el apartado correcto para cada tarea: [leer la documentación de Electron](#reading-electron-documentation)
o [escribir documentación para Electron](#writing-electron-documentation).
## Escribir Documentación para Electron
Estas son las maneras en las que construimos la documentación de Electron.
- Máximo un título `h1` por página.
- Utilizar `bash` en lugar de `cmd` en los bloques de código (por el resaltado
de sintaxis).
- Los títulos `h1` en el documento deben corresponder al nombre del objeto
(ej. `browser-window``BrowserWindow`).
- 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: `código`.
- Cabeceras de Eventos son delimitados con 'comillas' simples.
- No generar listas de mas de dos niveles (debido al renderizador de Markdown
desafortunadamente).
- Agregar títulos de sección: Eventos, Métodos de Clases y Métodos de Instancia.
- Utilizar 'deberá' en lugar de 'debería' al describir resultados.
- Eventos y Métodos son cabeceras `h3`.
- 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 itálicas seguidas por la cabecera del método.
- ```### `method(foo, bar)` _OS X_```
- Preferir 'en el ___ proceso' en lugar de 'sobre el'
### Traducciones de la Documentación
Traducciones de documentos de Electron se encuentran dentro del folder
`docs-translations`.
Para agregar otro set (o un set parcial):
- Crear un subdirectorio nombrado igual a la abreviación del lenguaje.
- Dentro de ese subdirectorio, duplicar el directorio de `docs`, manteniendo los
mismos nombres de directorios y archivos.
- Traducir los archivos.
- Actualizar el `README.md` dentro del subdirectorio del lenguaje apuntando a
los archivos que has traducido.
- Agregar un enlace al folder de tu traducción en la sección principal Electron
[README](https://github.com/atom/electron#documentation-translations).
## Leyendo la Documentación de Electron
Estos son algunos consejos para entender la sintaxis de la documentación de
Electron.
### Métodos
Un ejemplo de la documentación del [método](https://developer.mozilla.org/en-US/docs/Glossary/Method):
---
`methodName(required[, optional]))`
* `require` String, **required**
* `optional` Integer
---
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 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),
[`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)
o un tipo personalizado como el [`webContent`](api/web-content.md) de Electron.
### Eventos
Un ejemplo de documentación del [evento](https://developer.mozilla.org/en-US/docs/Web/API/Event):
---
Event: 'wake-up'
Returns:
* `time` String
---
El evento es una cadena que es utilizada luego de un método observador `.on`. Si
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
Alarm.on('wake-up', function(time) {
console.log(time)
})
```

View File

@@ -1,10 +1,11 @@
# Distribución de aplicaciones
# Distribución de la Aplicación
Para distribuir tu aplicación con Electron, debes nombrar al directorio de tu aplicación
como `app`, y ponerlo bajo el directorio de recursos de Electron (en OSX es `Electron.app/Contents/Resources/`,
en Linux y Windows es `resources/`):
Para distribuir tu aplicación con Electron, el directorio que contiene la
aplicación deberá llamarse `app`, y ser colocado debajo del directorio de
recursos de Electron (en OSX es `Electron.app/Contents/Resources/`, en Linux y
Windows es `resources/`), de esta forma:
En OSX:
En OS X:
```text
electron/Electron.app/Contents/Resources/app/
@@ -22,18 +23,19 @@ electron/resources/app
└── index.html
```
Posteriormente ejecutas `Electron.app` (o `electron` en Linux, `electron.exe` en Windows),
y Electron iniciará la aplicación. El directorio `electron` será la distribución que recibirán los usuarios finales.
Luego ejecutar `Electron.app` (o `electron` en Linux, `electron.exe` en Windows),
y Electron será iniciado como tu aplicación. El directorio `electron` será
entonces tu distribución que recibirán los usuarios finales.
## Empaquetando tu aplicación como un archivo
## Empaquetando tu aplicación en un archivo
Además de copiar todos tus archivos fuente para la distribución, también puedes
empaquetar tu aplicación como un archivo [asar](https://github.com/atom/asar)
y de esta forma evitar la exposición del código fuente de tu aplicación a los usuarios.
Además de distribuir tu aplicación al copiar todos los archivos de código fuente,
también puedes empaquetar tu aplicación como un archivo [asar](https://github.com/atom/asar)
y de esta forma evitar exponer del código fuente de tu aplicación a los usuarios.
Para usar un archivo `asar` en reemplazo de la carpeta `app`, debes renombrar
el archivo a `app.asar`, y ponerlo bajo el directorio de recursos de Electron (como arriba),
Electron intentará leer el archivo y ejecutar la aplicación desde él.
Para utilizar un archivo `asar` en reemplazo del directorio `app`, debes de
renombrar el archivo a `app.asar`, y colocarlo por debajo el directorio de recursos
de Electron (ver en seguida), Electron intentará leer el archivo y arrancar desde el.
En OS X:
@@ -49,30 +51,33 @@ electron/resources/
└── app.asar
```
Más detalles en [Empaquetamiento de aplicaciones](application-packaging-es.md).
Más detalles en [Empaquetado de Aplicaciones](application-packaging.md).
## Rebranding con binarios descargados
## Redefinición con Binarios Descargados
Luego de empaquetar tu aplicación con Electron, podría ser útil agregar tu marca
antes de realizar la distribución.
Luego de empaquetar tu aplicación en Electron, querrás redefinir Electron antes
de distribuirlo a los usuarios.
### Windows
Puedes renombrar `electron.exe` a cualquier nombre que desees, y editar su ícono y otras informaciones
con herramientas como [rcedit](https://github.com/atom/rcedit) o [ResEdit](http://www.resedit.net).
Puedes renombrar `electron.exe` a cualquier nombre que desees, y editar su ícono
y otra información con herramientas como [rcedit](https://github.com/atom/rcedit)
o [ResEdit](http://www.resedit.net).
### OS X
### OSX
Puedes renombrar `Electron.app` a cualquier nombre que desees. También debes modificar los campos
`CFBundleDisplayName`, `CFBundleIdentifier` y `CFBundleName` en los siguientes archivos:
Puedes renombrar `Electron.app` a cualquier nombre que desees, y tendrás que
renombrar los campos `CFBundleDisplayName`, `CFBundleIdentifier` y `CFBundleName`
en los siguientes archivos:
* `Electron.app/Contents/Info.plist`
* `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist`
También puedes renombrar el helper de la aplicación para evitar que aparezca como `Electron Helper`
en el Monitor de Actividades.
También puedes renombrar el helper de la aplicación para evitar que aparezca
como `Electron Helper` en el Monitor de Actividades. Pero asegurate de renombrar
el nombre de archivo del ejecutable.
La estructura de una aplicación renombrada sería así:
La estructura de una aplicación renombrada será:
```
MyApp.app/Contents
@@ -98,17 +103,19 @@ MyApp.app/Contents
Puedes renombrar el ejectuable `electron` a cualquier nombre que desees.
## Rebranding desde el código fuente de Electron
## Redefinición mediante la recompilación de Electron desde el código fuente
También es posible agregar tu marca a Electron mediante un build personalizado.
Para realizar esto debes modificar el archivo `atom.gyp`.
También es posible redefinir Electron cambiando el nombre del producto y
compilandolo desde sus fuentes. Para realizar esto necesitas modificar el
archivo `atom.gyp` y realizar una compilación desde cero.
### grunt-build-atom-shell
La modificación del código de Electron para agregar tu marca puede resultar complicada, una tarea Grunt
se ha creado para manejar esto de forma automatizada:
La modificación a mano del código de Electron y su compilación puede resultar
complicada, por lo cual se ha generado una tarea Grunt para manejar esto de
forma automaticamente:
[grunt-build-atom-shell](https://github.com/paulcbetts/grunt-build-atom-shell).
Esta tarea se encargará de modificar el archivo `.gyp`, compilar el código
y reconstruir los módulos nativos de la aplicación para que coincidan con el nuevo nombre.
Esta tarea se encargará de modificar el archivo `.gyp`, compilar el código desde
las fuentes, y luego reconstruir los módulos nativos de la aplicación para que
coincidan con el nuevo nombre del ejecutable.

Some files were not shown because too many files have changed in this diff Show More