Compare commits

..

177 Commits

Author SHA1 Message Date
Cheng Zhao
18fcd6990b win: Fix running spec 2015-06-11 14:14:22 +08:00
Cheng Zhao
5fe130a684 Bump v0.28.0 2015-06-11 12:13:18 +08:00
Cheng Zhao
71598e15bf Update node to fix crash caused by malloc 2015-06-10 21:08:54 +08:00
Cheng Zhao
cd3c061448 win: Fix compilation error 2015-06-10 19:34:30 +08:00
Cheng Zhao
163790d107 docs: Update formats 2015-06-10 19:18:33 +08:00
Cheng Zhao
2fdc5780ff Merge pull request #1859 from deepak1556/client_certificate_patch
browser: support client certificate
2015-06-10 19:17:41 +08:00
Cheng Zhao
b76642bd10 Update brightray 2015-06-10 19:16:45 +08:00
Cheng Zhao
209e24bf0f Merge pull request #1925 from atom/update-iojs
Update to io.js v2.2.1
2015-06-10 19:11:57 +08:00
Cheng Zhao
731773765e Update iojs to fix linking on Linux 2015-06-10 16:40:35 +08:00
Cheng Zhao
333fe87490 Define V8_BASE 2015-06-10 16:30:47 +08:00
Cheng Zhao
36f0ef703a Update io.js to v2.2.1 2015-06-10 16:19:19 +08:00
Cheng Zhao
605722c397 Make asar work with internalModuleReadFile and internalModuleStat 2015-06-10 16:18:55 +08:00
Cheng Zhao
132c13a11b Fix calls to deprecated node::ThrowError API 2015-06-10 14:21:09 +08:00
Cheng Zhao
04d24f61fe Update to node.gyp's changes 2015-06-10 14:11:34 +08:00
Cheng Zhao
8eb5e651a2 Suppress some tests on CI
The Mac runner of Travis CI is too flacky.
2015-06-10 12:52:52 +08:00
Cheng Zhao
5cd0fc4d52 Merge pull request #1921 from samueleaton/patch-1
adds display:inline-block to style tag
2015-06-10 12:48:57 +08:00
Cheng Zhao
d12697c657 Merge pull request #1918 from kirkouimet/master
Fixing an issue compiling on Windows and improving webview interopability with other JavaScript libraries
2015-06-10 12:48:45 +08:00
Cheng Zhao
0819176cb1 Merge branch 'master' of https://github.com/alexwarren/electron into alexwarren-master 2015-06-10 12:39:59 +08:00
Cheng Zhao
7d1f6dae6f Merge pull request #1911 from thomastuts/doc-fixes
Documentation fixes: grammar, spelling and code
2015-06-10 12:35:55 +08:00
Cheng Zhao
5c2bb42d49 Merge pull request #1922 from atom/remote-clipboard
Don't use clipboard module in renderer process on Linux
2015-06-10 12:34:32 +08:00
Cheng Zhao
db9615f5cd Don't rely on JS for setting optional argument
It makes the code much shorter and cleaner.
2015-06-10 12:12:37 +08:00
Kirk Ouimet
09c5da7147 Fixing cpplint line width 2015-06-09 21:06:40 -07:00
Cheng Zhao
4b12a95d37 Transfer Buffer through "remote" 2015-06-10 11:58:15 +08:00
Cheng Zhao
200a19dad9 linux: Don't use clipboard module in renderer process 2015-06-10 11:57:28 +08:00
Sam Eaton
2ee6e43fb3 adds display:inline-block to style tag
The example attempts to change the height of an inline element (webview), which has no effect. 
The height will now take effect.
2015-06-09 21:51:10 -06:00
Kirk Ouimet
0fef09281b Guarding webview attributes against polluted Object.prototypes
Ran into an error with the buildParams function breaking when using a JavaScript library that modified the Object.prototype, this small fix resolves the issue.
2015-06-09 16:17:00 -07:00
kirkouimet
f91a81fe77 Convert std::string path to a FilePath to get compiling working on Windows 2015-06-09 15:56:54 -07:00
Alex Warren
78eff673ec Make consistent with other example 2015-06-09 22:09:23 +01:00
Alex Warren
51dc8ad70a Corrections to menu.md 2015-06-09 22:08:34 +01:00
Thomas Tuts
d8cd9b71b0 Clean up Selenium webdriver code example 2015-06-09 18:18:47 +02:00
Thomas Tuts
c78a3ff714 Replace shorthand if-statement notation in Pepper Flash docs 2015-06-09 18:17:38 +02:00
Thomas Tuts
4642630674 Replace shorthand if-statement notation in quick start docs 2015-06-09 18:17:12 +02:00
Thomas Tuts
a6a5d50c3f Add missing semicolons in devtools extension docs 2015-06-09 18:15:54 +02:00
Thomas Tuts
b4790a7531 Remove trailing commas in desktop environment docs 2015-06-09 18:15:30 +02:00
Thomas Tuts
9199d0df0a Add missing semicolon in webview tag documentation 2015-06-09 18:14:06 +02:00
Thomas Tuts
a84e6227ef Remove obsolete space in console log when using multiple arguments 2015-06-09 18:12:34 +02:00
Thomas Tuts
35dcdfc492 Remove trailing comma in tray code example 2015-06-09 18:11:40 +02:00
Thomas Tuts
2f4333b852 Declare one variable per statement in protocol code example 2015-06-09 18:10:02 +02:00
Thomas Tuts
bd1fd9680f Add missing commas in menu docs 2015-06-09 18:08:27 +02:00
Thomas Tuts
cf79f439ce Remove trailing commas in menu docs 2015-06-09 18:08:02 +02:00
Thomas Tuts
e829a28947 Clean up code in global shortcut code example 2015-06-09 18:01:09 +02:00
Thomas Tuts
6d756d9d13 Remove trailing commas from dialog filters code example 2015-06-09 17:59:53 +02:00
Thomas Tuts
29abfa68e9 Fix grammar and JS example for Chrome command line switches docs 2015-06-09 16:59:14 +02:00
Thomas Tuts
ab98dcd7cf Try to clarify docs for window.onbeforeunload() 2015-06-09 16:56:45 +02:00
Thomas Tuts
6494ed6b13 Make platform compatibility notes consistent 2015-06-09 16:51:54 +02:00
Thomas Tuts
8893c9502a Use consistent naming convention for 'task bar' concept 2015-06-09 16:49:44 +02:00
Thomas Tuts
13b6ed6dc5 Fix several typos and grammar errors 2015-06-09 16:49:21 +02:00
Cheng Zhao
8aa815e6d1 Merge pull request #1907 from timruffles/patch-1
doc on how to test with your application
2015-06-09 18:48:52 +08:00
Tim Ruffles
719f68a44b doc on how to test with your application 2015-06-09 10:29:47 +01:00
Cheng Zhao
4c48f0cd36 Merge pull request #1882 from atom/get_uploaded_report_api
Implement crash-reporter.getUploadedReports API
2015-06-09 16:35:08 +08:00
Cheng Zhao
8ef3351846 Merge pull request #1906 from atom/guest-owner-window
Fix getting owner window in guest WebContents
2015-06-09 16:23:28 +08:00
Cheng Zhao
9f0ac13edc Pass embedder when creating WebContents 2015-06-09 15:50:20 +08:00
Cheng Zhao
5459137d3d Remove unused options for WebContents.create 2015-06-09 15:40:04 +08:00
deepak1556
52b2c0d27f default to first certificate from cert store 2015-06-09 13:00:20 +05:30
Cheng Zhao
89087d402d Merge pull request #1873 from atom/multiline-headers
Support multiple-line headers in `did-get-response-details'
2015-06-09 12:03:45 +08:00
Haojian Wu
64e84b8f6a Support multiple-line headers in web-contents `did-get-response-details' event. 2015-06-09 11:18:46 +08:00
Cheng Zhao
24586c1330 Merge pull request #1883 from atom/http-referer-doc
📝 Add missing `httpreferer` option doc.
2015-06-09 11:15:44 +08:00
Cheng Zhao
f8c6056eec Upgrade brightray, fix #1901 2015-06-09 11:10:15 +08:00
Cheng Zhao
03ab9b2686 Merge pull request #1848 from Bitbored/master
Added `bounds` payload to tray `clicked` event on Windows
2015-06-09 10:49:01 +08:00
Haojian Wu
f1a8c5a1ca Use httpReferrer and userAgent new names in webview. 2015-06-09 10:44:54 +08:00
Haojian Wu
488801e244 Rename httpreferrer to httpReferrer, useragent to userAgent. 2015-06-09 10:10:29 +08:00
Haojian Wu
bf1765f941 📝 Add missing useragent doc. 2015-06-09 10:10:28 +08:00
Haojian Wu
994be9cdab 📝 Add missing httpreferer option doc. 2015-06-09 10:10:28 +08:00
Cheng Zhao
d4e4c6ca15 docs: Update formats of command line switches 2015-06-09 09:56:19 +08:00
Cheng Zhao
47cb06e201 Update brightray for --log-net-log 2015-06-09 09:52:11 +08:00
Seppe Stas
cac97cca0d Initialized rect with zeros
As per @zcbenz 's remark: The rect should be initialized with zeros to prevent random values being passed to the click event handler when `Shell_NotifyIconGetRect` fails.
2015-06-08 19:07:46 +02:00
Seppe Stas
16c08e7e37 Switched to gfx::Rect constructor that takes a RECT
As per @zcbenz's suggestion the rect passed to the click event handler now passes a rect constructed using `gfx::Rect(const RECT& r)`.
2015-06-08 19:04:56 +02:00
deepak1556
2de5f9de6c browser: support client certificate 2015-06-08 21:00:32 +05:30
Cheng Zhao
06a3875726 Merge pull request #1880 from deepak1556/net_log_patch
doc: adding info about log-net-log flag
2015-06-08 23:13:27 +08:00
Cheng Zhao
1ae8bed96a Merge pull request #1899 from kirkouimet/guard-for-in-loop
Guarding against polluted Object.prototypes
2015-06-08 22:45:43 +08:00
Cheng Zhao
2ec74b5958 Merge pull request #1886 from BobCochran/linux-build-instructions-issue-1809
Linux build instructions issue 1809
2015-06-08 22:42:04 +08:00
Cheng Zhao
72ebb2c9fe Merge pull request #1885 from lucidogen/patch-1
Added note and link for poorly documented operation.
2015-06-08 22:33:08 +08:00
Cheng Zhao
52166d2999 Merge pull request #1884 from lucidogen/master
Fixed example with correct capturePage api.
2015-06-08 22:32:06 +08:00
Cheng Zhao
676cfa03a1 Merge pull request #1894 from samccone/patch-5
📝 Fix english errors and language
2015-06-08 22:31:17 +08:00
Cheng Zhao
64a89fe755 Merge pull request #1889 from samccone/patch-2
📝 Fix english errors
2015-06-08 22:30:35 +08:00
Cheng Zhao
2bd03f6eda Merge pull request #1890 from samccone/patch-3
📝 Fix english errors and clarify docs
2015-06-08 22:30:25 +08:00
Cheng Zhao
eeaee1a0b7 Merge pull request #1891 from samccone/patch-4
📝 Improve devtools documentation
2015-06-08 22:29:06 +08:00
Cheng Zhao
fed9ef0687 Merge pull request #1860 from atom/dialog-show-file-name
Fix dialog.showSaveDialog doesn't show the non-exist file name on Linux.
2015-06-08 19:41:33 +08:00
Kirk Ouimet
75448ad7ed Guarding against polluted Object.prototypes 2015-06-07 23:59:49 -07:00
Cheng Zhao
25db6e0bd8 Merge pull request #1897 from atom/dumpsyms
mac: Build dump_syms
2015-06-08 13:54:24 +08:00
Cheng Zhao
cefe540ec0 mac: Build dump_syms
Crashpad doesn't ship dump_syms, we have to build to from breakpad.

Related: #1822
2015-06-08 13:47:08 +08:00
Cheng Zhao
8363a39a56 Bump v0.27.3 2015-06-08 13:24:47 +08:00
Cheng Zhao
57ef6adbbd win: Fix runing clipboard spec 2015-06-08 13:24:14 +08:00
Cheng Zhao
5ae9c633ca Fix building on Windows, close #1896 2015-06-08 13:19:56 +08:00
Sam Saccone
b6a5e927e0 📝 Fix english errors and language 2015-06-07 15:32:54 -04:00
BobCochran
625c17fa24 Merge branch 'linux-build-instructions-issue-vm' into linux-build-instructions-issue-1809
Edit the virtual machine section of the instructions.
2015-06-07 08:22:53 -04:00
BobCochran
f776932718 Edited virtual machines sections. 2015-06-07 08:11:44 -04:00
Sam Saccone
55c07cec68 📝 Improve devtools documentation 2015-06-06 21:56:13 -04:00
Sam Saccone
161dc45ec8 📝 Fix english errors and clarify docs 2015-06-06 21:46:51 -04:00
Sam Saccone
29827fa66b 📝 Fix english errors 2015-06-06 21:42:21 -04:00
BobCochran
40b6a1a37c Add instructions to clean build products 2015-06-06 18:04:11 -04:00
Lucidogen Media
e4ae579b16 Added note and link for poorly documented operation.
Accessing renderer process from main process is not documented and as "remote" does the opposite, it seems fair to add a pointer here.
2015-06-06 13:38:00 +02:00
Lucidogen Media
582a42f97c Added ending semicolon for consistency. 2015-06-06 13:31:22 +02:00
Lucidogen Media
9a0a10e766 Fixed example with correct capturePage api. 2015-06-06 13:20:47 +02:00
Haojian Wu
cd1c331112 Fix coffeelint error. 2015-06-06 17:59:20 +08:00
BobCochran
8a2b665097 Edit linux build instructions based on feedback 2015-06-05 19:38:30 -04:00
deepak1556
690513db7f doc: adding info about log-net-log flag 2015-06-06 00:59:28 +05:30
Cheng Zhao
13c1b078f9 Fix refreshing test window 2015-06-05 19:48:58 +08:00
Haojian Wu
4da7578dab 📝 Add getUploadedReports API doc. 2015-06-05 19:05:55 +08:00
Haojian Wu
c821a06e2f Implement crash-reporter.getUploadedReports API.
Also redefine the getLastCrashReport API implementation using
getUploadedReports API.
2015-06-05 18:59:03 +08:00
Cheng Zhao
cd7b3dd291 Merge pull request #1874 from atom/fewer-code
Remove duplicate code between api::WebContents and NativeWindow
2015-06-05 18:40:38 +08:00
Cheng Zhao
bb42c2c7b6 Avoid destorying api::WebContents for twice 2015-06-05 18:13:30 +08:00
Cheng Zhao
af62b7b5c9 Put common code of OpenURLFromTab to CommonWebContentsDelegate 2015-06-05 17:45:17 +08:00
Cheng Zhao
8f9a109fa6 Implement HTML5 fullscreen in CommonWebContentsDelegate 2015-06-05 17:27:24 +08:00
Cheng Zhao
05468cc3fa Remove devtools APIs from NativeWindow 2015-06-05 17:01:17 +08:00
Cheng Zhao
94d69777fa Enable calling WebContents::openDevTools for BrowserWindow's WebContents 2015-06-05 15:41:03 +08:00
Cheng Zhao
67144aaf2a Remove duplicate def of is_guest 2015-06-05 15:18:15 +08:00
Cheng Zhao
d9efc3b4bf Move more methods to CommonWebContentsDelegate 2015-06-05 15:12:38 +08:00
Cheng Zhao
c32aac0a56 Manage webview with CommonWebContentsDelegate 2015-06-05 15:01:51 +08:00
Cheng Zhao
92b15c81e9 Manage InspectableWebContents in CommonWebContentsDelegate 2015-06-05 14:55:07 +08:00
Cheng Zhao
19d742de37 Add CommonWebContentsDelegate 2015-06-05 13:49:24 +08:00
Cheng Zhao
e8f33f51fb Use DefaultWebContentsDelegate in api::WebContents 2015-06-05 13:41:45 +08:00
Cheng Zhao
7f7cdbf775 Remove NativeWindow::CallDevToolsFunction 2015-06-05 13:32:01 +08:00
Cheng Zhao
7f42c0fa21 Update brightray 2015-06-05 13:27:13 +08:00
Cheng Zhao
8306dc427a Merge pull request #1867 from deepak1556/devtools_workspace_patch
devtools: supporting workspace usage
2015-06-05 13:26:37 +08:00
Cheng Zhao
66b3972fbc Fix typo 2015-06-05 10:03:01 +08:00
BobCochran
ed244648d0 Update build instructions for Linux 2015-06-04 21:03:45 -04:00
deepak1556
790fba598e devtools: supporting workspace usage 2015-06-05 01:06:53 +05:30
Cheng Zhao
129159c895 docs: Say more about page-visibility option 2015-06-04 22:42:36 +08:00
Cheng Zhao
f4c696b922 Merge pull request #1863 from atom/default-menu
Create a default menu for apps ran by default_app
2015-06-04 22:36:33 +08:00
Cheng Zhao
f54506acc0 Merge pull request #1822 from hokein/crashpad-mac
Crashpad!
2015-06-04 22:11:14 +08:00
Cheng Zhao
4466082592 Revert "Update libchromiumcontent, fix #1786"
This reverts commit 1314b7c7e5.
2015-06-04 21:15:29 +08:00
Cheng Zhao
a8256a62e0 Merge pull request #1837 from deepak1556/render_client_patch
renderer: option to override page visiblity state
2015-06-04 21:13:55 +08:00
deepak1556
683917ae67 renderer: option to override page visiblity state 2015-06-04 14:40:13 +05:30
Cheng Zhao
a22b9be681 mac: Do nothing if calling Menu.setApplicationMenu(null) 2015-06-04 16:14:19 +08:00
Cheng Zhao
3b20f2aced docs: Mention how to remove menu bar 2015-06-04 16:12:29 +08:00
Cheng Zhao
5d23b7468e Allow removing menu bar 2015-06-04 16:10:19 +08:00
Haojian Wu
d5b47d1059 Simplify and polish the code. 2015-06-04 15:53:37 +08:00
Cheng Zhao
47e9deeb9a Remove Menu::AttachToWindow
It makes the logic more complex without any benefit
2015-06-04 15:32:33 +08:00
Cheng Zhao
6d6e75795f Allow settting menu to null 2015-06-04 15:14:43 +08:00
Cheng Zhao
cc3066e746 Create a default menu for apps ran by default_app 2015-06-04 14:54:53 +08:00
Cheng Zhao
0fcc0f3e0a Update brightray for #1809 2015-06-04 14:41:44 +08:00
Haojian Wu
da83ba6c06 Fix dialog.showSaveDialog doesn't show the non-exist file name on Linux. 2015-06-04 14:16:53 +08:00
Cheng Zhao
3c186946eb docs: python 2.7 is required, close #1830 2015-06-03 19:27:04 +08:00
Cheng Zhao
31beee9599 Check for nullness when comparing webContents, close #1838 2015-06-03 18:48:10 +08:00
Cheng Zhao
912ed2ca10 Merge pull request #1839 from deepak1556/devtools_api_patch
devtools: initialise devtoolsWebContents when opened with inspect* apis
2015-06-03 18:31:25 +08:00
Cheng Zhao
c2352d3499 Merge pull request #1850 from atom/webview-update-process-id
Don't search NativeWindow or guest view by child process ID
2015-06-03 15:02:39 +08:00
Cheng Zhao
3a3b05b2f0 Clean up code 2015-06-03 14:53:19 +08:00
Cheng Zhao
95a8f3fc70 Fix changing src would calling loadUrl for twice 2015-06-03 14:33:22 +08:00
Cheng Zhao
34cd1435b4 Clean up code 2015-06-03 14:17:28 +08:00
Cheng Zhao
d4be2da70e Don't rely on process_id to search for NativeWindow 2015-06-03 14:08:56 +08:00
Seppe Stas
e5c4e34ac4 Ow 💩, where did that extra space come from? 2015-06-03 07:54:38 +02:00
Cheng Zhao
6dfa7b5383 Don't rely on guest_process_id for searching guest 2015-06-03 13:45:06 +08:00
Haojian Wu
94382cbaa2 Fix cpplint error. 2015-06-03 11:31:34 +08:00
Haojian Wu
981908c336 Add missing crashpad submodule. 2015-06-03 11:13:20 +08:00
Cheng Zhao
3ee054e316 Merge pull request #1849 from atom/remove-devtools-hack
Remove AtomResourceDispatcherHostDelegate
2015-06-03 10:48:31 +08:00
Cheng Zhao
f22d4bf0c0 Merge pull request #1814 from fraserxu/master
convert message to string for window.alert method
2015-06-03 10:20:59 +08:00
Cheng Zhao
d46e986e80 Remove AtomResourceDispatcherHostDelegate 2015-06-03 10:08:05 +08:00
Cheng Zhao
bd6d41bd87 Update brightray for updates on devtools_ui 2015-06-03 10:00:29 +08:00
Haojian Wu
4457edb1d3 Implement crash-reporter.getLastLastCrashReport API on OS X. 2015-06-03 09:47:42 +08:00
Seppe Stas
e920ce3e24 Updated tray api docs to reflect changes in ce8aa07 2015-06-02 23:19:49 +02:00
Seppe Stas
ce8aa073ee Added bounds payload to tray clicked event
Used [Shell_NotifyIconGetRect function](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378426) to get the bounds of the application's tray icon.
Note: only works with Windows 7 and later.

Related to #1159, #1500.
2015-06-02 21:43:37 +02:00
Haojian Wu
2396b51cb6 Switch to use crashpad repo under atom org. 2015-06-02 11:46:20 +08:00
Haojian Wu
317406f26d Update crashpad implementation after code review. 2015-06-02 11:41:47 +08:00
deepak1556
67a9931b55 devtools: initialise devtoolsWebContents when opened with inspect* apis 2015-06-01 17:23:44 +05:30
Cheng Zhao
ad851547e0 Merge pull request #1834 from hokein/master
Ship pdf.dll in release, fix #1826
2015-06-01 13:25:31 +08:00
Haojian Wu
c4cbb5ecdb Ship pdf.dll in release. 2015-06-01 13:03:56 +08:00
Cheng Zhao
b97c22d4d7 win: Load pdf.dll with abosolute path, fix #1826 2015-06-01 12:53:43 +08:00
Cheng Zhao
fe631e6eeb Bump v0.27.2 2015-06-01 12:22:36 +08:00
Cheng Zhao
1314b7c7e5 Update libchromiumcontent, fix #1786 2015-06-01 12:19:56 +08:00
Yeechan Lu
c026863d48 Print real error messages even if it looks like an invalid app 2015-06-01 10:13:33 +08:00
Haojian Wu
51d5ef9d86 📝 crash-reporter note on OS X. 2015-05-30 10:06:29 +08:00
Haojian Wu
16fb847009 Add script to setup crashpad repository.
Crashpad use `gclient` to maintain its third_party libraries.
This patch switches `gclient` instead of `git submodule` to align crashpad way.
2015-05-30 09:42:40 +08:00
Haojian Wu
cd8ceec62e Send all crash reports to collection server.
Crashpad client only send reports once per hour. It's different with breakpad.
With this behavior, the other reports generated within an hour will be totally
skipped, which causes the crash api test only run once with an hour.

This patch unrestricts this time limit.
2015-05-30 08:47:52 +08:00
Haojian Wu
98a9d8a9e3 Enable crashpad test on OS X. 2015-05-30 07:34:56 +08:00
Haojian Wu
4e2f242ad0 Use Crashpad instead of Breakpad on OS X. 2015-05-29 23:25:11 +08:00
Cheng Zhao
02bdace366 Delete Node's symbols after Environment has been loaded
Fix #1803.
2015-05-29 22:20:20 +08:00
Cheng Zhao
6ed538b952 docs: Remove obsolete build instructions, close #1809 2015-05-29 18:21:25 +08:00
Cheng Zhao
dfbe158ca9 mac: Remove dead "Frameworks" link, close #1801 2015-05-29 18:14:59 +08:00
Cheng Zhao
fb37b5720d Update brightray to use correct Chrome version string
Close #1808
2015-05-29 17:52:46 +08:00
fraserxu
57ab704300 convert message to string for window.alert method 2015-05-29 15:55:11 +08:00
Cheng Zhao
4a310ad630 Merge pull request #1811 from atom/new-webview
Change how webview is resized
2015-05-29 14:14:23 +08:00
Cheng Zhao
a9ad783bca The ElementSizeChanged has been removed 2015-05-29 13:52:14 +08:00
Cheng Zhao
b5c9fe78f1 Listen to ElementSizeChanged event 2015-05-29 13:47:09 +08:00
Cheng Zhao
e4bb456964 Pass element size when attaching 2015-05-29 11:47:54 +08:00
Cheng Zhao
b45ed8d9a2 pendingGuestCreation is removed 2015-05-29 11:20:28 +08:00
Cheng Zhao
bdf73fcd4c Update to the new algorithm of setting webview size 2015-05-29 11:12:55 +08:00
101 changed files with 2012 additions and 1477 deletions

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@
/vendor/brightray/vendor/download/
/vendor/python_26/
/vendor/npm/
/vendor/.gclient
node_modules/
*.xcodeproj
*.swp

3
.gitmodules vendored
View File

@@ -13,3 +13,6 @@
[submodule "vendor/native_mate"]
path = vendor/native_mate
url = https://github.com/zcbenz/native-mate.git
[submodule "vendor/crashpad"]
path = vendor/crashpad
url = https://github.com/atom/crashpad.git

View File

@@ -4,7 +4,7 @@
'product_name%': 'Electron',
'company_name%': 'GitHub, Inc',
'company_abbr%': 'github',
'version%': '0.27.1',
'version%': '0.28.0',
'atom_source_root': '<!(["python", "tools/atom_source_root.py"])',
},
@@ -45,6 +45,7 @@
'dependencies': [
'<(project_name)_framework',
'<(project_name)_helper',
'vendor/breakpad/breakpad.gyp:dump_syms',
],
'xcode_settings': {
'ATOM_BUNDLE_ID': 'com.<(company_abbr).<(project_name)',
@@ -275,7 +276,8 @@
}], # OS=="win"
['OS=="mac"', {
'dependencies': [
'vendor/breakpad/breakpad.gyp:breakpad',
'vendor/crashpad/client/client.gyp:crashpad_client',
'vendor/crashpad/handler/handler.gyp:crashpad_handler',
],
}], # OS=="mac"
['OS=="linux"', {
@@ -430,8 +432,7 @@
{
'destination': '<(PRODUCT_DIR)/<(product_name) Framework.framework/Versions/A/Resources',
'files': [
'<(PRODUCT_DIR)/Inspector',
'<(PRODUCT_DIR)/crash_report_sender.app',
'<(PRODUCT_DIR)/crashpad_handler',
],
},
],
@@ -452,7 +453,6 @@
'tools/mac/create-framework-subdir-symlinks.sh',
'<(product_name) Framework',
'Libraries',
'Frameworks',
],
},
],

View File

@@ -70,10 +70,6 @@ void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
menu_will_show_.Run();
}
void Menu::AttachToWindow(Window* window) {
window->window()->SetMenu(model_.get());
}
void Menu::InsertItemAt(
int index, int command_id, const base::string16& label) {
model_->InsertItemAt(index, command_id, label);
@@ -168,7 +164,6 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
.SetMethod("attachToWindow", &Menu::AttachToWindow)
.SetMethod("_popup", &Menu::Popup)
.SetMethod("_popupAt", &Menu::PopupAt);
}

View File

@@ -51,7 +51,6 @@ class Menu : public mate::Wrappable,
void ExecuteCommand(int command_id, int event_flags) override;
void MenuWillShow(ui::SimpleMenuModel* source) override;
virtual void AttachToWindow(Window* window);
virtual void Popup(Window* window) = 0;
virtual void PopupAt(Window* window, int x, int y) = 0;
@@ -99,4 +98,27 @@ class Menu : public mate::Wrappable,
} // namespace atom
namespace mate {
template<>
struct Converter<ui::SimpleMenuModel*> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
ui::SimpleMenuModel** out) {
// null would be tranfered to NULL.
if (val->IsNull()) {
*out = nullptr;
return true;
}
atom::api::Menu* menu;
if (!Converter<atom::api::Menu*>::FromV8(isolate, val, &menu))
return false;
*out = menu->model();
return true;
}
};
} // namespace mate
#endif // ATOM_BROWSER_API_ATOM_API_MENU_H_

View File

@@ -41,8 +41,9 @@ void PowerMonitor::OnResume() {
// static
v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
if (!Browser::Get()->is_ready()) {
node::ThrowError("Cannot initialize \"power-monitor\" module"
"before app is ready");
node::ThrowError(
isolate,
"Cannot initialize \"power-monitor\" module before app is ready");
return v8::Null(isolate);
}

View File

@@ -192,28 +192,19 @@ Protocol::JsProtocolHandler Protocol::GetProtocolHandler(
mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate)
.SetMethod("registerProtocol",
base::Bind(&Protocol::RegisterProtocol,
base::Unretained(this)))
.SetMethod("unregisterProtocol",
base::Bind(&Protocol::UnregisterProtocol,
base::Unretained(this)))
.SetMethod("isHandledProtocol",
base::Bind(&Protocol::IsHandledProtocol,
base::Unretained(this)))
.SetMethod("interceptProtocol",
base::Bind(&Protocol::InterceptProtocol,
base::Unretained(this)))
.SetMethod("uninterceptProtocol",
base::Bind(&Protocol::UninterceptProtocol,
base::Unretained(this)));
.SetMethod("registerProtocol", &Protocol::RegisterProtocol)
.SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
.SetMethod("isHandledProtocol", &Protocol::IsHandledProtocol)
.SetMethod("interceptProtocol", &Protocol::InterceptProtocol)
.SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol);
}
void Protocol::RegisterProtocol(const std::string& scheme,
void Protocol::RegisterProtocol(v8::Isolate* isolate,
const std::string& scheme,
const JsProtocolHandler& callback) {
if (ContainsKey(protocol_handlers_, scheme) ||
job_factory_->IsHandledProtocol(scheme))
return node::ThrowError("The scheme is already registered");
return node::ThrowError(isolate, "The scheme is already registered");
protocol_handlers_[scheme] = callback;
BrowserThread::PostTask(BrowserThread::IO,
@@ -222,10 +213,11 @@ void Protocol::RegisterProtocol(const std::string& scheme,
base::Unretained(this), scheme));
}
void Protocol::UnregisterProtocol(const std::string& scheme) {
void Protocol::UnregisterProtocol(v8::Isolate* isolate,
const std::string& scheme) {
ProtocolHandlersMap::iterator it(protocol_handlers_.find(scheme));
if (it == protocol_handlers_.end())
return node::ThrowError("The scheme has not been registered");
return node::ThrowError(isolate, "The scheme has not been registered");
protocol_handlers_.erase(it);
BrowserThread::PostTask(BrowserThread::IO,
@@ -238,13 +230,14 @@ bool Protocol::IsHandledProtocol(const std::string& scheme) {
return job_factory_->IsHandledProtocol(scheme);
}
void Protocol::InterceptProtocol(const std::string& scheme,
void Protocol::InterceptProtocol(v8::Isolate* isolate,
const std::string& scheme,
const JsProtocolHandler& callback) {
if (!job_factory_->HasProtocolHandler(scheme))
return node::ThrowError("Scheme does not exist.");
return node::ThrowError(isolate, "Scheme does not exist.");
if (ContainsKey(protocol_handlers_, scheme))
return node::ThrowError("Cannot intercept custom procotols");
return node::ThrowError(isolate, "Cannot intercept custom procotols");
protocol_handlers_[scheme] = callback;
BrowserThread::PostTask(BrowserThread::IO,
@@ -253,10 +246,11 @@ void Protocol::InterceptProtocol(const std::string& scheme,
base::Unretained(this), scheme));
}
void Protocol::UninterceptProtocol(const std::string& scheme) {
void Protocol::UninterceptProtocol(v8::Isolate* isolate,
const std::string& scheme) {
ProtocolHandlersMap::iterator it(protocol_handlers_.find(scheme));
if (it == protocol_handlers_.end())
return node::ThrowError("The scheme has not been registered");
return node::ThrowError(isolate, "The scheme has not been registered");
protocol_handlers_.erase(it);
BrowserThread::PostTask(BrowserThread::IO,

View File

@@ -43,9 +43,10 @@ class Protocol : public mate::EventEmitter {
// Register/unregister an networking |scheme| which would be handled by
// |callback|.
void RegisterProtocol(const std::string& scheme,
void RegisterProtocol(v8::Isolate* isolate,
const std::string& scheme,
const JsProtocolHandler& callback);
void UnregisterProtocol(const std::string& scheme);
void UnregisterProtocol(v8::Isolate* isolate, const std::string& scheme);
// Returns whether a scheme has been registered.
// FIXME Should accept a callback and be asynchronous so we do not have to use
@@ -53,9 +54,10 @@ class Protocol : public mate::EventEmitter {
bool IsHandledProtocol(const std::string& scheme);
// Intercept/unintercept an existing protocol handler.
void InterceptProtocol(const std::string& scheme,
void InterceptProtocol(v8::Isolate* isolate,
const std::string& scheme,
const JsProtocolHandler& callback);
void UninterceptProtocol(const std::string& scheme);
void UninterceptProtocol(v8::Isolate* isolate, const std::string& scheme);
// The networking related operations have to be done in IO thread.
void RegisterProtocolInIO(const std::string& scheme);

View File

@@ -113,13 +113,14 @@ mate::ObjectTemplateBuilder Screen::GetObjectTemplateBuilder(
// static
v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
if (!Browser::Get()->is_ready()) {
node::ThrowError("Cannot initialize \"screen\" module before app is ready");
node::ThrowError(isolate,
"Cannot initialize \"screen\" module before app is ready");
return v8::Null(isolate);
}
gfx::Screen* screen = gfx::Screen::GetNativeScreen();
if (!screen) {
node::ThrowError("Failed to get screen information");
node::ThrowError(isolate, "Failed to get screen information");
return v8::Null(isolate);
}

View File

@@ -32,9 +32,9 @@ Tray::~Tray() {
}
// static
mate::Wrappable* Tray::New(const gfx::Image& image) {
mate::Wrappable* Tray::New(v8::Isolate* isolate, const gfx::Image& image) {
if (!Browser::Get()->is_ready()) {
node::ThrowError("Cannot create Tray before app is ready");
node::ThrowError(isolate, "Cannot create Tray before app is ready");
return nullptr;
}
return new Tray(image);

View File

@@ -31,7 +31,7 @@ class Menu;
class Tray : public mate::EventEmitter,
public TrayIconObserver {
public:
static mate::Wrappable* New(const gfx::Image& image);
static mate::Wrappable* New(v8::Isolate* isolate, const gfx::Image& image);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);

View File

@@ -8,10 +8,7 @@
#include "atom/browser/atom_browser_client.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_javascript_dialog_manager.h"
#include "atom/browser/native_window.h"
#include "atom/browser/web_dialog_helper.h"
#include "atom/browser/web_view_manager.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
@@ -21,7 +18,6 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/media/media_stream_devices_controller.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/guest_host.h"
#include "content/public/browser/navigation_details.h"
@@ -44,22 +40,47 @@
#include "atom/common/node_includes.h"
namespace mate {
template<>
struct Converter<atom::api::SetSizeParams> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
atom::api::SetSizeParams* out) {
mate::Dictionary params;
if (!ConvertFromV8(isolate, val, &params))
return false;
bool autosize;
if (params.Get("enableAutoSize", &autosize))
out->enable_auto_size.reset(new bool(true));
gfx::Size size;
if (params.Get("min", &size))
out->min_size.reset(new gfx::Size(size));
if (params.Get("max", &size))
out->max_size.reset(new gfx::Size(size));
if (params.Get("normal", &size))
out->normal_size.reset(new gfx::Size(size));
return true;
}
};
} // namespace mate
namespace atom {
namespace api {
namespace {
const int kDefaultWidth = 300;
const int kDefaultHeight = 300;
v8::Persistent<v8::ObjectTemplate> template_;
// Get the window that has the |guest| embedded.
NativeWindow* GetWindowFromGuest(const content::WebContents* guest) {
WebViewManager::WebViewInfo info;
if (WebViewManager::GetInfoForProcess(guest->GetRenderProcessHost(), &info))
return NativeWindow::FromWebContents(info.embedder);
else
return nullptr;
}
// The wrapWebContents funtion which is implemented in JavaScript
using WrapWebContentsCallback = base::Callback<void(v8::Local<v8::Value>)>;
WrapWebContentsCallback g_wrap_web_contents;
content::ServiceWorkerContext* GetServiceWorkerContext(
const content::WebContents* web_contents) {
@@ -68,46 +89,54 @@ content::ServiceWorkerContext* GetServiceWorkerContext(
if (!context || !site_instance)
return nullptr;
content::StoragePartition* storage_partition =
content::BrowserContext::GetStoragePartition(
context, site_instance);
DCHECK(storage_partition);
auto storage_partition =
content::BrowserContext::GetStoragePartition(context, site_instance);
if (!storage_partition)
return nullptr;
return storage_partition->GetServiceWorkerContext();
}
} // namespace
WebContents::WebContents(brightray::InspectableWebContents* web_contents)
: WebContents(web_contents->GetWebContents()) {
inspectable_web_contents_ = web_contents;
}
WebContents::WebContents(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
guest_instance_id_(-1),
element_instance_id_(-1),
: CommonWebContentsDelegate(false),
content::WebContentsObserver(web_contents),
guest_opaque_(true),
guest_host_(nullptr),
auto_size_enabled_(false) {
auto_size_enabled_(false),
is_full_page_plugin_(false),
inspectable_web_contents_(nullptr) {
}
WebContents::WebContents(const mate::Dictionary& options)
: guest_instance_id_(-1),
element_instance_id_(-1),
: CommonWebContentsDelegate(true),
guest_opaque_(true),
guest_host_(nullptr),
auto_size_enabled_(false) {
options.Get("guestInstanceId", &guest_instance_id_);
auto_size_enabled_(false),
is_full_page_plugin_(false) {
auto browser_context = AtomBrowserContext::Get();
content::SiteInstance* site_instance = content::SiteInstance::CreateForURL(
browser_context, GURL("chrome-guest://fake-host"));
content::WebContents::CreateParams params(browser_context, site_instance);
bool is_guest;
if (options.Get("isGuest", &is_guest) && is_guest)
params.guest_delegate = this;
params.guest_delegate = this;
auto web_contents = content::WebContents::Create(params);
storage_.reset(brightray::InspectableWebContents::Create(params));
Observe(storage_->GetWebContents());
web_contents()->SetDelegate(this);
NativeWindow* owner_window = nullptr;
WebContents* embedder = nullptr;
if (options.Get("embedder", &embedder) && embedder)
owner_window = NativeWindow::FromWebContents(embedder->web_contents());
InitWithWebContents(web_contents, owner_window);
inspectable_web_contents_ = managed_web_contents();
Observe(GetWebContents());
}
WebContents::~WebContents() {
@@ -155,56 +184,7 @@ content::WebContents* WebContents::OpenURLFromTab(
if (Emit("will-navigate", params.url))
return nullptr;
content::NavigationController::LoadURLParams load_url_params(params.url);
load_url_params.referrer = params.referrer;
load_url_params.transition_type = params.transition;
load_url_params.extra_headers = params.extra_headers;
load_url_params.should_replace_current_entry =
params.should_replace_current_entry;
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.transferred_global_request_id =
params.transferred_global_request_id;
load_url_params.should_clear_history_list = true;
web_contents()->GetController().LoadURLWithParams(load_url_params);
return web_contents();
}
content::JavaScriptDialogManager* WebContents::GetJavaScriptDialogManager(
content::WebContents* source) {
if (!dialog_manager_)
dialog_manager_.reset(new AtomJavaScriptDialogManager);
return dialog_manager_.get();
}
void WebContents::RunFileChooser(content::WebContents* guest,
const content::FileChooserParams& params) {
if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(GetWindowFromGuest(guest)));
web_dialog_helper_->RunFileChooser(guest, params);
}
void WebContents::EnumerateDirectory(content::WebContents* guest,
int request_id,
const base::FilePath& path) {
if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(GetWindowFromGuest(guest)));
web_dialog_helper_->EnumerateDirectory(guest, request_id, path);
}
bool WebContents::CheckMediaAccessPermission(content::WebContents* web_contents,
const GURL& security_origin,
content::MediaStreamType type) {
return true;
}
void WebContents::RequestMediaAccessPermission(
content::WebContents*,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) {
brightray::MediaStreamDevicesController controller(request, callback);
controller.TakeAction();
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
}
void WebContents::HandleKeyboardEvent(
@@ -220,32 +200,13 @@ void WebContents::HandleKeyboardEvent(
void WebContents::EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) {
auto window = GetWindowFromGuest(source);
if (window) {
window->SetHtmlApiFullscreen(true);
window->NotifyWindowEnterHtmlFullScreen();
source->GetRenderViewHost()->WasResized();
Emit("enter-html-full-screen");
}
CommonWebContentsDelegate::EnterFullscreenModeForTab(source, origin);
Emit("enter-html-full-screen");
}
void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
auto window = GetWindowFromGuest(source);
if (window) {
window->SetHtmlApiFullscreen(false);
window->NotifyWindowLeaveHtmlFullScreen();
source->GetRenderViewHost()->WasResized();
Emit("leave-html-full-screen");
}
}
bool WebContents::IsFullscreenForTabOrPending(
const content::WebContents* source) const {
auto window = GetWindowFromGuest(source);
if (window)
return window->is_html_api_fullscreen();
else
return false;
CommonWebContentsDelegate::ExitFullscreenModeForTab(source);
Emit("leave-html-full-screen");
}
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
@@ -315,15 +276,27 @@ void WebContents::DidGetResourceResponseStart(
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
mate::Dictionary response_headers(isolate, v8::Object::New(isolate));
base::DictionaryValue response_headers;
net::HttpResponseHeaders* headers = details.headers.get();
if (!headers)
return;
void* iter = nullptr;
std::string key;
std::string value;
while (headers && headers->EnumerateHeaderLines(&iter, &key, &value))
response_headers.Set(base::StringToLowerASCII(key),
base::StringToLowerASCII(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))
values->AppendString(value);
} else {
scoped_ptr<base::ListValue> values(new base::ListValue());
values->AppendString(value);
response_headers.Set(key, values.Pass());
}
}
Emit("did-get-response-details",
details.socket_address.IsEmpty(),
@@ -391,15 +364,11 @@ void WebContents::RenderViewReady() {
// WebContents::GetRenderWidgetHostView will return the RWHV of an
// interstitial page if one is showing at this time. We only want opacity
// to apply to web pages.
if (guest_opaque_) {
web_contents()
->GetRenderViewHost()
->GetView()
->SetBackgroundColorToDefault();
} else {
web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor(
SK_ColorTRANSPARENT);
}
auto render_view_host_view = web_contents()->GetRenderViewHost()->GetView();
if (guest_opaque_)
render_view_host_view->SetBackgroundColorToDefault();
else
render_view_host_view->SetBackgroundColor(SK_ColorTRANSPARENT);
}
void WebContents::WebContentsDestroyed() {
@@ -418,14 +387,6 @@ void WebContents::DidAttach(int guest_proxy_routing_id) {
Emit("did-attach");
}
void WebContents::ElementSizeChanged(const gfx::Size& size) {
element_size_ = size;
// Only resize if needed.
if (!size.IsEmpty())
guest_host_->SizeContents(size);
}
content::WebContents* WebContents::GetOwnerWebContents() const {
return embedder_web_contents_;
}
@@ -445,11 +406,11 @@ void WebContents::WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id,
bool is_full_page_plugin) {
embedder_web_contents_ = embedder_web_contents;
element_instance_id_ = element_instance_id;
is_full_page_plugin_ = is_full_page_plugin;
}
void WebContents::Destroy() {
if (storage_) {
if (is_guest() && managed_web_contents()) {
// When force destroying the "destroyed" event is not emitted.
WebContentsDestroyed();
@@ -458,7 +419,7 @@ void WebContents::Destroy() {
guest_host_ = nullptr;
Observe(nullptr);
storage_.reset();
DestroyWebContents();
}
}
@@ -470,12 +431,12 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
content::NavigationController::LoadURLParams params(url);
GURL http_referrer;
if (options.Get("httpreferrer", &http_referrer))
if (options.Get("httpReferrer", &http_referrer))
params.referrer = content::Referrer(http_referrer.GetAsReferrer(),
blink::WebReferrerPolicyDefault);
std::string user_agent;
if (options.Get("useragent", &user_agent))
if (options.Get("userAgent", &user_agent))
SetUserAgent(user_agent);
params.transition_type = ui::PAGE_TRANSITION_TYPED;
@@ -543,26 +504,82 @@ void WebContents::ExecuteJavaScript(const base::string16& code) {
web_contents()->GetMainFrame()->ExecuteJavaScript(code);
}
void WebContents::OpenDevTools() {
storage_->SetCanDock(false);
storage_->ShowDevTools();
void WebContents::OpenDevTools(mate::Arguments* args) {
if (!inspectable_web_contents())
return;
bool detach = false;
if (is_guest()) {
detach = true;
} else if (args && args->Length() == 1) {
mate::Dictionary options;
args->GetNext(&options) && options.Get("detach", &detach);
}
inspectable_web_contents()->SetCanDock(!detach);
inspectable_web_contents()->ShowDevTools();
}
void WebContents::CloseDevTools() {
storage_->CloseDevTools();
if (!inspectable_web_contents())
return;
inspectable_web_contents()->CloseDevTools();
}
bool WebContents::IsDevToolsOpened() {
return storage_->IsDevToolsViewShowing();
if (!inspectable_web_contents())
return false;
return inspectable_web_contents()->IsDevToolsViewShowing();
}
void WebContents::ToggleDevTools() {
if (IsDevToolsOpened())
CloseDevTools();
else
OpenDevTools(nullptr);
}
void WebContents::InspectElement(int x, int y) {
OpenDevTools();
if (!inspectable_web_contents())
return;
OpenDevTools(nullptr);
scoped_refptr<content::DevToolsAgentHost> agent(
content::DevToolsAgentHost::GetOrCreateFor(storage_->GetWebContents()));
content::DevToolsAgentHost::GetOrCreateFor(web_contents()));
agent->InspectElement(x, y);
}
void WebContents::InspectServiceWorker() {
if (!inspectable_web_contents())
return;
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
if (agent_host->GetType() ==
content::DevToolsAgentHost::TYPE_SERVICE_WORKER) {
OpenDevTools(nullptr);
inspectable_web_contents()->AttachTo(agent_host);
break;
}
}
}
void WebContents::HasServiceWorker(
const base::Callback<void(bool)>& callback) {
auto context = GetServiceWorkerContext(web_contents());
if (!context)
return;
context->CheckHasServiceWorker(web_contents()->GetLastCommittedURL(),
GURL::EmptyGURL(),
callback);
}
void WebContents::UnregisterServiceWorker(
const base::Callback<void(bool)>& callback) {
auto context = GetServiceWorkerContext(web_contents());
if (!context)
return;
context->UnregisterServiceWorker(web_contents()->GetLastCommittedURL(),
callback);
}
void WebContents::Undo() {
web_contents()->Undo();
}
@@ -612,31 +629,57 @@ bool WebContents::SendIPCMessage(const base::string16& channel,
return Send(new AtomViewMsg_Message(routing_id(), channel, args));
}
void WebContents::SetAutoSize(bool enabled,
const gfx::Size& min_size,
const gfx::Size& max_size) {
void WebContents::SetSize(const SetSizeParams& params) {
bool enable_auto_size =
params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_;
gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_;
gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_;
if (params.normal_size)
normal_size_ = *params.normal_size;
min_auto_size_ = min_size;
min_auto_size_.SetToMin(max_size);
max_auto_size_ = max_size;
max_auto_size_.SetToMax(min_size);
enabled &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty();
if (!enabled && !auto_size_enabled_)
return;
auto_size_enabled_ = enabled;
if (!attached())
return;
enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty();
content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
if (auto_size_enabled_) {
if (enable_auto_size) {
// Autosize is being enabled.
rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
normal_size_.SetSize(0, 0);
} else {
rvh->DisableAutoResize(element_size_);
guest_size_ = element_size_;
GuestSizeChangedDueToAutoSize(guest_size_, element_size_);
// Autosize is being disabled.
// Use default width/height if missing from partially defined normal size.
if (normal_size_.width() && !normal_size_.height())
normal_size_.set_height(GetDefaultSize().height());
if (!normal_size_.width() && normal_size_.height())
normal_size_.set_width(GetDefaultSize().width());
gfx::Size new_size;
if (!normal_size_.IsEmpty()) {
new_size = normal_size_;
} else if (!guest_size_.IsEmpty()) {
new_size = guest_size_;
} else {
new_size = GetDefaultSize();
}
if (auto_size_enabled_) {
// Autosize was previously enabled.
rvh->DisableAutoResize(new_size);
GuestSizeChangedDueToAutoSize(guest_size_, new_size);
} else {
// Autosize was already disabled.
guest_host_->SizeContents(new_size);
}
guest_size_ = new_size;
}
auto_size_enabled_ = enable_auto_size;
}
void WebContents::SetAllowTransparency(bool allow) {
@@ -658,36 +701,8 @@ void WebContents::SetAllowTransparency(bool allow) {
}
}
void WebContents::HasServiceWorker(
const base::Callback<void(bool)>& callback) {
auto context = GetServiceWorkerContext(web_contents());
if (!context)
return;
context->CheckHasServiceWorker(web_contents()->GetLastCommittedURL(),
GURL::EmptyGURL(),
callback);
}
void WebContents::UnregisterServiceWorker(
const base::Callback<void(bool)>& callback) {
auto context = GetServiceWorkerContext(web_contents());
if (!context)
return;
context->UnregisterServiceWorker(web_contents()->GetLastCommittedURL(),
callback);
}
void WebContents::InspectServiceWorker() {
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
if (agent_host->GetType() ==
content::DevToolsAgentHost::TYPE_SERVICE_WORKER) {
OpenDevTools();
storage_->AttachTo(agent_host);
break;
}
}
bool WebContents::IsGuest() const {
return is_guest();
}
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
@@ -714,6 +729,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("openDevTools", &WebContents::OpenDevTools)
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
.SetMethod("inspectElement", &WebContents::InspectElement)
.SetMethod("undo", &WebContents::Undo)
.SetMethod("redo", &WebContents::Redo)
@@ -727,9 +743,9 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("replace", &WebContents::Replace)
.SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
.SetMethod("_send", &WebContents::SendIPCMessage)
.SetMethod("setAutoSize", &WebContents::SetAutoSize)
.SetMethod("setSize", &WebContents::SetSize)
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
.SetMethod("isGuest", &WebContents::is_guest)
.SetMethod("isGuest", &WebContents::IsGuest)
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
.SetMethod("unregisterServiceWorker",
&WebContents::UnregisterServiceWorker)
@@ -760,16 +776,46 @@ void WebContents::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
new_size.width(), new_size.height());
}
gfx::Size WebContents::GetDefaultSize() const {
if (is_full_page_plugin_) {
// Full page plugins default to the size of the owner's viewport.
return embedder_web_contents_->GetRenderWidgetHostView()
->GetVisibleViewportSize();
} else {
return gfx::Size(kDefaultWidth, kDefaultHeight);
}
}
// static
mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, brightray::InspectableWebContents* web_contents) {
auto handle = mate::CreateHandle(isolate, new WebContents(web_contents));
g_wrap_web_contents.Run(handle.ToV8());
return handle;
}
// static
mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents) {
return mate::CreateHandle(isolate, new WebContents(web_contents));
auto handle = mate::CreateHandle(isolate, new WebContents(web_contents));
g_wrap_web_contents.Run(handle.ToV8());
return handle;
}
// static
mate::Handle<WebContents> WebContents::Create(
v8::Isolate* isolate, const mate::Dictionary& options) {
return mate::CreateHandle(isolate, new WebContents(options));
auto handle = mate::CreateHandle(isolate, new WebContents(options));
g_wrap_web_contents.Run(handle.ToV8());
return handle;
}
void SetWrapWebContents(const WrapWebContentsCallback& callback) {
g_wrap_web_contents = callback;
}
void ClearWrapWebContents() {
g_wrap_web_contents.Reset();
}
} // namespace api
@@ -784,6 +830,8 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.SetMethod("create", &atom::api::WebContents::Create);
dict.SetMethod("_setWrapWebContents", &atom::api::SetWrapWebContents);
dict.SetMethod("_clearWrapWebContents", &atom::api::ClearWrapWebContents);
}
} // namespace

View File

@@ -9,10 +9,9 @@
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "brightray/browser/default_web_contents_delegate.h"
#include "atom/browser/common_web_contents_delegate.h"
#include "content/public/browser/browser_plugin_guest_delegate.h"
#include "content/public/common/favicon_url.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "native_mate/handle.h"
@@ -23,23 +22,39 @@ class InspectableWebContents;
}
namespace mate {
class Arguments;
class Dictionary;
}
namespace atom {
class AtomJavaScriptDialogManager;
class WebDialogHelper;
namespace api {
// A struct of parameters for SetSize(). The parameters are all declared as
// scoped pointers since they are all optional. Null pointers indicate that the
// parameter has not been provided, and the last used value should be used. Note
// that when |enable_auto_size| is true, providing |normal_size| is not
// meaningful. This is because the normal size of the guestview is overridden
// whenever autosizing occurs.
struct SetSizeParams {
SetSizeParams() {}
~SetSizeParams() {}
scoped_ptr<bool> enable_auto_size;
scoped_ptr<gfx::Size> min_size;
scoped_ptr<gfx::Size> max_size;
scoped_ptr<gfx::Size> normal_size;
};
class WebContents : public mate::EventEmitter,
public content::BrowserPluginGuestDelegate,
public content::WebContentsDelegate,
public CommonWebContentsDelegate,
public content::WebContentsObserver,
public content::GpuDataManagerObserver {
public:
// Create from an existing WebContents.
static mate::Handle<WebContents> CreateFrom(
v8::Isolate* isolate, brightray::InspectableWebContents* web_contents);
static mate::Handle<WebContents> CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents);
@@ -64,13 +79,14 @@ class WebContents : public mate::EventEmitter,
void SetUserAgent(const std::string& user_agent);
void InsertCSS(const std::string& css);
void ExecuteJavaScript(const base::string16& code);
void OpenDevTools();
void OpenDevTools(mate::Arguments* args);
void CloseDevTools();
bool IsDevToolsOpened();
void ToggleDevTools();
void InspectElement(int x, int y);
void InspectServiceWorker();
void HasServiceWorker(const base::Callback<void(bool)>&);
void UnregisterServiceWorker(const base::Callback<void(bool)>&);
void InspectServiceWorker();
// Editing commands.
void Undo();
@@ -89,25 +105,26 @@ class WebContents : public mate::EventEmitter,
bool SendIPCMessage(const base::string16& channel,
const base::ListValue& args);
// Toggles autosize mode for corresponding <webview>.
void SetAutoSize(bool enabled,
const gfx::Size& min_size,
const gfx::Size& max_size);
// Used to toggle autosize mode for this GuestView, and set both the automatic
// and normal sizes.
void SetSize(const SetSizeParams& params);
// Sets the transparency of the guest.
void SetAllowTransparency(bool allow);
// Returns whether this is a guest view.
bool is_guest() const { return guest_instance_id_ != -1; }
bool IsGuest() const;
// Returns whether this guest has an associated embedder.
bool attached() const { return !!embedder_web_contents_; }
content::WebContents* web_contents() const {
return content::WebContentsObserver::web_contents();
// Returns the current InspectableWebContents object, nullptr will be returned
// if current WebContents can not beinspected, e.g. it is the devtools.
brightray::InspectableWebContents* inspectable_web_contents() const {
return inspectable_web_contents_;
}
protected:
explicit WebContents(brightray::InspectableWebContents* web_contents);
explicit WebContents(content::WebContents* web_contents);
explicit WebContents(const mate::Dictionary& options);
~WebContents();
@@ -135,28 +152,12 @@ class WebContents : public mate::EventEmitter,
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
content::WebContents* source) override;
void RunFileChooser(content::WebContents* web_contents,
const content::FileChooserParams& params) override;
void EnumerateDirectory(content::WebContents* web_contents,
int request_id,
const base::FilePath& path) override;
bool CheckMediaAccessPermission(content::WebContents* web_contents,
const GURL& security_origin,
content::MediaStreamType type) override;
void RequestMediaAccessPermission(
content::WebContents*,
const content::MediaStreamRequest&,
const content::MediaResponseCallback&) override;
void HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) override;
void EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) override;
void ExitFullscreenModeForTab(content::WebContents* source) override;
bool IsFullscreenForTabOrPending(
const content::WebContents* source) const override;
// content::WebContentsObserver:
void RenderViewDeleted(content::RenderViewHost*) override;
@@ -196,7 +197,6 @@ class WebContents : public mate::EventEmitter,
// content::BrowserPluginGuestDelegate:
void DidAttach(int guest_proxy_routing_id) final;
void ElementSizeChanged(const gfx::Size& size) final;
content::WebContents* GetOwnerWebContents() const final;
void GuestSizeChanged(const gfx::Size& new_size) final;
void SetGuestHost(content::GuestHost* guest_host) final;
@@ -217,25 +217,20 @@ class WebContents : public mate::EventEmitter,
const base::ListValue& args,
IPC::Message* message);
// This method is invoked when the contents auto-resized to give the container
// an opportunity to match it if it wishes.
//
// This gives the derived class an opportunity to inform its container element
// or perform other actions.
void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size);
scoped_ptr<WebDialogHelper> web_dialog_helper_;
scoped_ptr<AtomJavaScriptDialogManager> dialog_manager_;
// Unique ID for a guest WebContents.
int guest_instance_id_;
// |element_instance_id_| is an identifer that's unique to a particular
// element.
int element_instance_id_;
// Returns the default size of the guestview.
gfx::Size GetDefaultSize() const;
// Stores whether the contents of the guest can be transparent.
bool guest_opaque_;
// Stores the WebContents that managed by this class.
scoped_ptr<brightray::InspectableWebContents> storage_;
// The WebContents that attaches this guest view.
content::WebContents* embedder_web_contents_;
@@ -258,6 +253,16 @@ class WebContents : public mate::EventEmitter,
// The minimum size constraints of the container element in autosize mode.
gfx::Size min_auto_size_;
// The size that will be used when autosize mode is disabled.
gfx::Size normal_size_;
// Whether the guest view is inside a plugin document.
bool is_full_page_plugin_;
// Current InspectableWebContents object, can be nullptr for WebContents of
// devtools. It is a weak reference.
brightray::InspectableWebContents* inspectable_web_contents_;
DISALLOW_COPY_AND_ASSIGN(WebContents);
};

View File

@@ -4,6 +4,7 @@
#include "atom/browser/api/atom_api_window.h"
#include "atom/browser/api/atom_api_menu.h"
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/browser.h"
#include "atom/browser/native_window.h"
@@ -164,11 +165,32 @@ void Window::OnDevToolsFocus() {
Emit("devtools-focused");
}
void Window::OnDevToolsOpened() {
Emit("devtools-opened");
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
auto handle =
WebContents::CreateFrom(isolate, window_->GetDevToolsWebContents());
devtools_web_contents_.Reset(isolate, handle.ToV8());
}
void Window::OnDevToolsClosed() {
Emit("devtools-closed");
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
devtools_web_contents_.Reset();
}
// static
mate::Wrappable* Window::New(v8::Isolate* isolate,
const mate::Dictionary& options) {
if (!Browser::Get()->is_ready()) {
node::ThrowError("Cannot create BrowserWindow before app is ready");
node::ThrowError(isolate,
"Cannot create BrowserWindow before app is ready");
return nullptr;
}
return new Window(options);
@@ -355,26 +377,6 @@ bool Window::IsKiosk() {
return window_->IsKiosk();
}
void Window::OpenDevTools(bool can_dock) {
window_->OpenDevTools(can_dock);
}
void Window::CloseDevTools() {
window_->CloseDevTools();
}
bool Window::IsDevToolsOpened() {
return window_->IsDevToolsOpened();
}
void Window::InspectElement(int x, int y) {
window_->InspectElement(x, y);
}
void Window::InspectServiceWorker() {
window_->InspectServiceWorker();
}
void Window::FocusOnWebView() {
window_->FocusOnWebView();
}
@@ -437,6 +439,10 @@ void Window::SetOverlayIcon(const gfx::Image& overlay,
window_->SetOverlayIcon(overlay, description);
}
void Window::SetMenu(ui::SimpleMenuModel* menu) {
window_->SetMenu(menu);
}
void Window::SetAutoHideMenuBar(bool auto_hide) {
window_->SetAutoHideMenuBar(auto_hide);
}
@@ -467,13 +473,20 @@ bool Window::IsVisibleOnAllWorkspaces() {
return window_->IsVisibleOnAllWorkspaces();
}
mate::Handle<WebContents> Window::GetWebContents(v8::Isolate* isolate) const {
return WebContents::CreateFrom(isolate, window_->GetWebContents());
v8::Local<v8::Value> Window::WebContents(v8::Isolate* isolate) {
if (web_contents_.IsEmpty()) {
auto handle =
WebContents::CreateFrom(isolate, window_->managed_web_contents());
web_contents_.Reset(isolate, handle.ToV8());
}
return v8::Local<v8::Value>::New(isolate, web_contents_);
}
mate::Handle<WebContents> Window::GetDevToolsWebContents(
v8::Isolate* isolate) const {
return WebContents::CreateFrom(isolate, window_->GetDevToolsWebContents());
v8::Local<v8::Value> Window::DevToolsWebContents(v8::Isolate* isolate) {
if (devtools_web_contents_.IsEmpty())
return v8::Null(isolate);
else
return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
}
// static
@@ -524,10 +537,6 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename)
.SetMethod("setDocumentEdited", &Window::SetDocumentEdited)
.SetMethod("isDocumentEdited", &Window::IsDocumentEdited)
.SetMethod("_openDevTools", &Window::OpenDevTools)
.SetMethod("closeDevTools", &Window::CloseDevTools)
.SetMethod("isDevToolsOpened", &Window::IsDevToolsOpened)
.SetMethod("inspectElement", &Window::InspectElement)
.SetMethod("focusOnWebView", &Window::FocusOnWebView)
.SetMethod("blurWebView", &Window::BlurWebView)
.SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
@@ -535,6 +544,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("print", &Window::Print)
.SetMethod("setProgressBar", &Window::SetProgressBar)
.SetMethod("setOverlayIcon", &Window::SetOverlayIcon)
.SetMethod("_setMenu", &Window::SetMenu)
.SetMethod("setAutoHideMenuBar", &Window::SetAutoHideMenuBar)
.SetMethod("isMenuBarAutoHide", &Window::IsMenuBarAutoHide)
.SetMethod("setMenuBarVisibility", &Window::SetMenuBarVisibility)
@@ -547,9 +557,8 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("showDefinitionForSelection",
&Window::ShowDefinitionForSelection)
#endif
.SetMethod("_getWebContents", &Window::GetWebContents)
.SetMethod("_getDevToolsWebContents", &Window::GetDevToolsWebContents)
.SetMethod("inspectServiceWorker", &Window::InspectServiceWorker);
.SetProperty("webContents", &Window::WebContents)
.SetProperty("devToolsWebContents", &Window::DevToolsWebContents);
}
} // namespace api

View File

@@ -25,6 +25,10 @@ class Arguments;
class Dictionary;
}
namespace ui {
class SimpleMenuModel;
}
namespace atom {
class NativeWindow;
@@ -74,6 +78,8 @@ class Window : public mate::EventEmitter,
void OnRendererUnresponsive() override;
void OnRendererResponsive() override;
void OnDevToolsFocus() override;
void OnDevToolsOpened() override;
void OnDevToolsClosed() override;
private:
// APIs for NativeWindow.
@@ -117,11 +123,6 @@ class Window : public mate::EventEmitter,
void SetSkipTaskbar(bool skip);
void SetKiosk(bool kiosk);
bool IsKiosk();
void OpenDevTools(bool can_dock);
void CloseDevTools();
bool IsDevToolsOpened();
void InspectElement(int x, int y);
void InspectServiceWorker();
void FocusOnWebView();
void BlurWebView();
bool IsWebViewFocused();
@@ -134,6 +135,7 @@ class Window : public mate::EventEmitter,
void SetProgressBar(double progress);
void SetOverlayIcon(const gfx::Image& overlay,
const std::string& description);
void SetMenu(ui::SimpleMenuModel* menu);
void SetAutoHideMenuBar(bool auto_hide);
bool IsMenuBarAutoHide();
void SetMenuBarVisibility(bool visible);
@@ -146,9 +148,11 @@ class Window : public mate::EventEmitter,
void SetVisibleOnAllWorkspaces(bool visible);
bool IsVisibleOnAllWorkspaces();
// APIs for WebContents.
mate::Handle<WebContents> GetWebContents(v8::Isolate* isolate) const;
mate::Handle<WebContents> GetDevToolsWebContents(v8::Isolate* isolate) const;
v8::Local<v8::Value> WebContents(v8::Isolate* isolate);
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
v8::Global<v8::Value> web_contents_;
v8::Global<v8::Value> devtools_web_contents_;
scoped_ptr<NativeWindow> window_;

View File

@@ -2,7 +2,6 @@ EventEmitter = require('events').EventEmitter
IDWeakMap = require 'id-weak-map'
app = require 'app'
ipc = require 'ipc'
wrapWebContents = require('web-contents').wrap
BrowserWindow = process.atomBinding('window').BrowserWindow
BrowserWindow::__proto__ = EventEmitter.prototype
@@ -16,10 +15,6 @@ BrowserWindow::_init = ->
menu = app.getApplicationMenu()
@setMenu menu if menu?
@webContents = @getWebContents()
@devToolsWebContents = null
@webContents.once 'destroyed', => @webContents = null
# Remember the window ID.
Object.defineProperty this, 'id',
value: BrowserWindow.windows.add(this)
@@ -40,35 +35,11 @@ BrowserWindow::_init = ->
@once 'closed', =>
BrowserWindow.windows.remove @id if BrowserWindow.windows.has @id
BrowserWindow::openDevTools = (options={}) ->
options.detach ?= false
@_openDevTools !options.detach
# Force devToolsWebContents to be created.
@devToolsWebContents = @getDevToolsWebContents()
@devToolsWebContents.once 'destroyed', => @devToolsWebContents = null
# Emit devtools events.
@devToolsWebContents.once 'did-finish-load', => @emit 'devtools-opened'
@devToolsWebContents.once 'destroyed', => @emit 'devtools-closed'
BrowserWindow::toggleDevTools = ->
if @isDevToolsOpened() then @closeDevTools() else @openDevTools()
BrowserWindow::getWebContents = ->
wrapWebContents @_getWebContents()
BrowserWindow::getDevToolsWebContents = ->
wrapWebContents @_getDevToolsWebContents()
BrowserWindow::setMenu = (menu) ->
if process.platform is 'darwin'
throw new Error('BrowserWindow.setMenu is not available on OS X')
throw new TypeError('Invalid menu') unless menu?.constructor?.name is 'Menu'
throw new TypeError('Invalid menu') unless menu is null or menu?.constructor?.name is 'Menu'
@menu = menu # Keep a reference of menu in case of GC.
@menu.attachToWindow this
@_setMenu menu
BrowserWindow.getAllWindows = ->
windows = BrowserWindow.windows
@@ -80,11 +51,11 @@ BrowserWindow.getFocusedWindow = ->
BrowserWindow.fromWebContents = (webContents) ->
windows = BrowserWindow.getAllWindows()
return window for window in windows when webContents.equal window.webContents
return window for window in windows when window.webContents?.equal webContents
BrowserWindow.fromDevToolsWebContents = (webContents) ->
windows = BrowserWindow.getAllWindows()
return window for window in windows when webContents.equal window.devToolsWebContents
return window for window in windows when window.devToolsWebContents?.equal webContents
BrowserWindow.fromId = (id) ->
BrowserWindow.windows.get id
@@ -105,7 +76,12 @@ BrowserWindow::stop = -> @webContents.stop()
BrowserWindow::getRoutingId = -> @webContents.getRoutingId()
BrowserWindow::getProcessId = -> @webContents.getProcessId()
BrowserWindow::isCrashed = -> @webContents.isCrashed()
BrowserWindow::executeJavaScriptInDevTools = (code) ->
@devToolsWebContents.executeJavaScript code
BrowserWindow::executeJavaScriptInDevTools = (code) -> @devToolsWebContents?.executeJavaScript code
BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments
BrowserWindow::closeDevTools = -> @webContents.closeDevTools()
BrowserWindow::isDevToolsOpened = -> @webContents.isDevToolsOpened()
BrowserWindow::toggleDevTools = -> @webContents.toggleDevTools()
BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContents, arguments
BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker()
module.exports = BrowserWindow

View File

@@ -130,10 +130,11 @@ Menu::_callMenuWillShow = ->
applicationMenu = null
Menu.setApplicationMenu = (menu) ->
throw new TypeError('Invalid menu') unless menu?.constructor is Menu
throw new TypeError('Invalid menu') unless menu is null or menu.constructor is Menu
applicationMenu = menu # Keep a reference.
if process.platform is 'darwin'
return if menu is null
menu._callMenuWillShow()
bindings.setApplicationMenu menu
else

View File

@@ -3,9 +3,7 @@ NavigationController = require './navigation-controller'
binding = process.atomBinding 'web_contents'
ipc = require 'ipc'
module.exports.wrap = (webContents) ->
return null unless webContents.isAlive()
wrapWebContents = (webContents) ->
# webContents is an EventEmitter.
webContents.__proto__ = EventEmitter.prototype
@@ -62,5 +60,8 @@ module.exports.wrap = (webContents) ->
webContents
binding._setWrapWebContents wrapWebContents
process.once 'exit', binding._clearWrapWebContents
module.exports.create = (options={}) ->
@wrap binding.create(options)
binding.create(options)

View File

@@ -8,24 +8,26 @@
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/atom_quota_permission_context.h"
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
#include "atom/browser/atom_speech_recognition_manager_delegate.h"
#include "atom/browser/native_window.h"
#include "atom/browser/web_view_manager.h"
#include "atom/browser/window_list.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/printing/printing_message_filter.h"
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
#include "chrome/browser/speech/tts_message_filter.h"
#include "content/public/browser/browser_ppapi_host.h"
#include "content/public/browser/client_certificate_delegate.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/web_preferences.h"
#include "net/cert/x509_certificate.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "ppapi/host/ppapi_host.h"
#include "ui/base/l10n/l10n_util.h"
@@ -33,25 +35,58 @@ namespace atom {
namespace {
// The default routing id of WebContents.
// In Electron each RenderProcessHost only has one WebContents, so this ID is
// same for every WebContents.
int kDefaultRoutingID = 2;
// Next navigation should not restart renderer process.
bool g_suppress_renderer_process_restart = false;
struct FindByProcessId {
explicit FindByProcessId(int child_process_id)
: child_process_id_(child_process_id) {
}
bool operator() (NativeWindow* const window) {
content::WebContents* web_contents = window->GetWebContents();
if (!web_contents)
return false;
int id = window->GetWebContents()->GetRenderProcessHost()->GetID();
return id == child_process_id_;
}
int child_process_id_;
// Find out the owner of the child process according to |process_id|.
enum ProcessOwner {
OWNER_NATIVE_WINDOW,
OWNER_GUEST_WEB_CONTENTS,
OWNER_NONE, // it might be devtools though.
};
ProcessOwner GetProcessOwner(int process_id,
NativeWindow** window,
WebViewManager::WebViewInfo* info) {
auto web_contents = content::WebContents::FromRenderViewHost(
content::RenderViewHost::FromID(process_id, kDefaultRoutingID));
if (!web_contents)
return OWNER_NONE;
// First search for NativeWindow.
for (auto native_window : *WindowList::GetInstance())
if (web_contents == native_window->GetWebContents()) {
*window = native_window;
return OWNER_NATIVE_WINDOW;
}
// Then search for guest WebContents.
if (WebViewManager::GetInfoForWebContents(web_contents, info))
return OWNER_GUEST_WEB_CONTENTS;
return OWNER_NONE;
}
scoped_refptr<net::X509Certificate> ImportCertFromFile(
const base::FilePath& path) {
std::string cert_data;
if (!base::ReadFileToString(path, &cert_data))
return nullptr;
net::CertificateList certs =
net::X509Certificate::CreateCertificateListFromBytes(
cert_data.data(), cert_data.size(),
net::X509Certificate::FORMAT_AUTO);
if (certs.empty())
return nullptr;
return certs[0];
}
} // namespace
@@ -60,8 +95,7 @@ void AtomBrowserClient::SuppressRendererProcessRestartForOnce() {
g_suppress_renderer_process_restart = true;
}
AtomBrowserClient::AtomBrowserClient()
: dying_render_process_(nullptr) {
AtomBrowserClient::AtomBrowserClient() {
}
AtomBrowserClient::~AtomBrowserClient() {
@@ -83,15 +117,8 @@ content::AccessTokenStore* AtomBrowserClient::CreateAccessTokenStore() {
return new AtomAccessTokenStore;
}
void AtomBrowserClient::ResourceDispatcherHostCreated() {
resource_dispatcher_delegate_.reset(new AtomResourceDispatcherHostDelegate);
content::ResourceDispatcherHost::Get()->SetDelegate(
resource_dispatcher_delegate_.get());
}
void AtomBrowserClient::OverrideWebkitPrefs(
content::RenderViewHost* render_view_host,
content::WebPreferences* prefs) {
content::RenderViewHost* host, content::WebPreferences* prefs) {
prefs->javascript_enabled = true;
prefs->web_security_enabled = true;
prefs->javascript_can_open_windows_automatically = true;
@@ -109,18 +136,10 @@ void AtomBrowserClient::OverrideWebkitPrefs(
prefs->allow_displaying_insecure_content = false;
prefs->allow_running_insecure_content = false;
// Turn off web security for devtools.
auto web_contents = content::WebContents::FromRenderViewHost(
render_view_host);
if (web_contents && web_contents->GetURL().SchemeIs("chrome-devtools")) {
prefs->web_security_enabled = false;
return;
}
// Custom preferences of guest page.
auto process = render_view_host->GetProcess();
auto web_contents = content::WebContents::FromRenderViewHost(host);
WebViewManager::WebViewInfo info;
if (WebViewManager::GetInfoForProcess(process, &info)) {
if (WebViewManager::GetInfoForWebContents(web_contents, &info)) {
prefs->web_security_enabled = !info.disable_web_security;
return;
}
@@ -144,76 +163,37 @@ void AtomBrowserClient::OverrideSiteInstanceForNavigation(
return;
}
if (current_instance->HasProcess())
dying_render_process_ = current_instance->GetProcess();
// Restart renderer process for all navigations except "javacript:" scheme.
if (url.SchemeIs(url::kJavaScriptScheme))
return;
if (!url.SchemeIs(url::kJavaScriptScheme)) {
// Restart renderer process for all navigations except javacript: scheme.
*new_instance = content::SiteInstance::CreateForURL(browser_context, url);
}
*new_instance = content::SiteInstance::CreateForURL(browser_context, url);
}
void AtomBrowserClient::AppendExtraCommandLineSwitches(
base::CommandLine* command_line,
int child_process_id) {
int process_id) {
std::string process_type = command_line->GetSwitchValueASCII("type");
if (process_type != "renderer")
return;
WindowList* list = WindowList::GetInstance();
NativeWindow* window = nullptr;
NativeWindow* window;
WebViewManager::WebViewInfo info;
ProcessOwner owner = GetProcessOwner(process_id, &window, &info);
// Find the owner of this child process.
WindowList::const_iterator iter = std::find_if(
list->begin(), list->end(), FindByProcessId(child_process_id));
if (iter != list->end())
window = *iter;
// If the render process is a newly started one, which means the window still
// uses the old going-to-be-swapped render process, then we try to find the
// window from the swapped render process.
if (!window && dying_render_process_) {
int dying_process_id = dying_render_process_->GetID();
WindowList::const_iterator iter = std::find_if(
list->begin(), list->end(), FindByProcessId(dying_process_id));
if (iter != list->end()) {
window = *iter;
child_process_id = dying_process_id;
} else {
// It appears that the dying process doesn't belong to a BrowserWindow,
// then it might be a guest process, if it is we should update its
// process ID in the WebViewManager.
auto child_process = content::RenderProcessHost::FromID(child_process_id);
// Update the process ID in webview guests.
WebViewManager::UpdateGuestProcessID(dying_render_process_,
child_process);
}
if (owner == OWNER_NATIVE_WINDOW) {
window->AppendExtraCommandLineSwitches(command_line);
} else if (owner == OWNER_GUEST_WEB_CONTENTS) {
command_line->AppendSwitchASCII(
switches::kGuestInstanceID, base::IntToString(info.guest_instance_id));
command_line->AppendSwitchASCII(
switches::kNodeIntegration, info.node_integration ? "true" : "false");
if (info.plugins)
command_line->AppendSwitch(switches::kEnablePlugins);
if (!info.preload_script.empty())
command_line->AppendSwitchPath(
switches::kPreloadScript, info.preload_script);
}
if (window) {
window->AppendExtraCommandLineSwitches(command_line, child_process_id);
} else {
// Append commnad line arguments for guest web view.
auto child_process = content::RenderProcessHost::FromID(child_process_id);
WebViewManager::WebViewInfo info;
if (WebViewManager::GetInfoForProcess(child_process, &info)) {
command_line->AppendSwitchASCII(
switches::kGuestInstanceID,
base::IntToString(info.guest_instance_id));
command_line->AppendSwitchASCII(
switches::kNodeIntegration,
info.node_integration ? "true" : "false");
if (info.plugins)
command_line->AppendSwitch(switches::kEnablePlugins);
if (!info.preload_script.empty())
command_line->AppendSwitchPath(
switches::kPreloadScript,
info.preload_script);
}
}
dying_render_process_ = nullptr;
}
void AtomBrowserClient::DidCreatePpapiPlugin(
@@ -230,6 +210,29 @@ content::QuotaPermissionContext*
return new AtomQuotaPermissionContext;
}
void AtomBrowserClient::SelectClientCertificate(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
scoped_ptr<content::ClientCertificateDelegate> delegate) {
auto command_line = base::CommandLine::ForCurrentProcess();
auto cert_path = command_line->GetSwitchValueNative(
switches::kClientCertificate);
// TODO(zcbenz): allow users to select certificate from
// client_cert list. Right now defaults to first certificate
// in the list.
scoped_refptr<net::X509Certificate> certificate;
if (cert_path.empty()) {
if (!cert_request_info->client_certs.empty())
certificate = cert_request_info->client_certs[0];
} else {
certificate = ImportCertFromFile(base::FilePath(cert_path));
}
if (certificate.get())
delegate->ContinueWithCertificate(certificate.get());
}
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
const content::MainFunctionParams&) {
v8::V8::Initialize(); // Init V8 before creating main parts.

View File

@@ -11,12 +11,15 @@
namespace content {
class QuotaPermissionContext;
class ClientCertificateDelegate;
}
namespace net {
class SSLCertRequestInfo;
}
namespace atom {
class AtomResourceDispatcherHostDelegate;
class AtomBrowserClient : public brightray::BrowserClient {
public:
AtomBrowserClient();
@@ -31,7 +34,6 @@ class AtomBrowserClient : public brightray::BrowserClient {
content::SpeechRecognitionManagerDelegate*
CreateSpeechRecognitionManagerDelegate() override;
content::AccessTokenStore* CreateAccessTokenStore() override;
void ResourceDispatcherHostCreated() override;
void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
content::WebPreferences* prefs) override;
std::string GetApplicationLocale() override;
@@ -44,16 +46,15 @@ class AtomBrowserClient : public brightray::BrowserClient {
int child_process_id) override;
void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;
content::QuotaPermissionContext* CreateQuotaPermissionContext() override;
void SelectClientCertificate(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
private:
brightray::BrowserMainParts* OverrideCreateBrowserMainParts(
const content::MainFunctionParams&) override;
scoped_ptr<AtomResourceDispatcherHostDelegate> resource_dispatcher_delegate_;
// The render process which would be swapped out soon.
content::RenderProcessHost* dying_render_process_;
DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient);
};

View File

@@ -1,33 +0,0 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
#include <string>
#include "base/logging.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/resource_request_info.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
namespace atom {
AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() {
}
void AtomResourceDispatcherHostDelegate::OnResponseStarted(
net::URLRequest* request,
content::ResourceContext* resource_context,
content::ResourceResponse* response,
IPC::Sender* sender) {
// Remove the "X-Frame-Options" from response headers for devtools.
if (request->url().SchemeIs("chrome-devtools")) {
net::HttpResponseHeaders* response_headers = request->response_headers();
if (response_headers && response_headers->HasHeader("x-frame-options"))
response_headers->RemoveHeader("x-frame-options");
}
}
} // namespace atom

View File

@@ -1,30 +0,0 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
#define ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
#include "base/compiler_specific.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
namespace atom {
class AtomResourceDispatcherHostDelegate
: public content::ResourceDispatcherHostDelegate {
public:
AtomResourceDispatcherHostDelegate();
// content::ResourceDispatcherHostDelegate:
void OnResponseStarted(net::URLRequest* request,
content::ResourceContext* resource_context,
content::ResourceResponse* response,
IPC::Sender* sender) override;
private:
DISALLOW_COPY_AND_ASSIGN(AtomResourceDispatcherHostDelegate);
};
} // namespace atom
#endif // ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_

View File

@@ -0,0 +1,342 @@
// 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/common_web_contents_delegate.h"
#include <string>
#include <vector>
#include "atom/browser/atom_javascript_dialog_manager.h"
#include "atom/browser/native_window.h"
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/web_dialog_helper.h"
#include "base/files/file_util.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/renderer_preferences.h"
#include "storage/browser/fileapi/isolated_context.h"
namespace atom {
namespace {
struct FileSystem {
FileSystem() {
}
FileSystem(const std::string& file_system_name,
const std::string& root_url,
const std::string& file_system_path)
: file_system_name(file_system_name),
root_url(root_url),
file_system_path(file_system_path) {
}
std::string file_system_name;
std::string root_url;
std::string file_system_path;
};
std::string RegisterFileSystem(content::WebContents* web_contents,
const base::FilePath& path,
std::string* registered_name) {
auto isolated_context = storage::IsolatedContext::GetInstance();
std::string file_system_id = isolated_context->RegisterFileSystemForPath(
storage::kFileSystemTypeNativeLocal,
std::string(),
path,
registered_name);
content::ChildProcessSecurityPolicy* policy =
content::ChildProcessSecurityPolicy::GetInstance();
content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
int renderer_id = render_view_host->GetProcess()->GetID();
policy->GrantReadFileSystem(renderer_id, file_system_id);
policy->GrantWriteFileSystem(renderer_id, file_system_id);
policy->GrantCreateFileForFileSystem(renderer_id, file_system_id);
policy->GrantDeleteFromFileSystem(renderer_id, file_system_id);
if (!policy->CanReadFile(renderer_id, path))
policy->GrantReadFile(renderer_id, path);
return file_system_id;
}
FileSystem CreateFileSystemStruct(
content::WebContents* web_contents,
const std::string& file_system_id,
const std::string& registered_name,
const std::string& file_system_path) {
const GURL origin = web_contents->GetURL().GetOrigin();
std::string file_system_name =
storage::GetIsolatedFileSystemName(origin, file_system_id);
std::string root_url = storage::GetIsolatedFileSystemRootURIString(
origin, file_system_id, registered_name);
return FileSystem(file_system_name, root_url, file_system_path);
}
base::DictionaryValue* CreateFileSystemValue(const FileSystem& file_system) {
base::DictionaryValue* file_system_value = new base::DictionaryValue();
file_system_value->SetString("fileSystemName", file_system.file_system_name);
file_system_value->SetString("rootURL", file_system.root_url);
file_system_value->SetString("fileSystemPath", file_system.file_system_path);
return file_system_value;
}
} // namespace
CommonWebContentsDelegate::CommonWebContentsDelegate(bool is_guest)
: is_guest_(is_guest),
owner_window_(nullptr),
html_fullscreen_(false),
native_fullscreen_(false) {
}
CommonWebContentsDelegate::~CommonWebContentsDelegate() {
}
void CommonWebContentsDelegate::InitWithWebContents(
content::WebContents* web_contents,
NativeWindow* owner_window) {
owner_window_ = owner_window;
web_contents->SetDelegate(this);
// Tell renderer to handle all navigations in browser.
auto preferences = web_contents->GetMutableRendererPrefs();
preferences->browser_handles_non_local_top_level_requests = true;
preferences->browser_handles_all_top_level_requests = true;
web_contents->GetRenderViewHost()->SyncRendererPrefs();
// Create InspectableWebContents.
web_contents_.reset(brightray::InspectableWebContents::Create(web_contents));
web_contents_->SetDelegate(this);
}
void CommonWebContentsDelegate::DestroyWebContents() {
web_contents_.reset();
}
content::WebContents* CommonWebContentsDelegate::GetWebContents() const {
if (!web_contents_)
return nullptr;
return web_contents_->GetWebContents();
}
content::WebContents*
CommonWebContentsDelegate::GetDevToolsWebContents() const {
if (!web_contents_)
return nullptr;
return web_contents_->GetDevToolsWebContents();
}
content::WebContents* CommonWebContentsDelegate::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
content::NavigationController::LoadURLParams load_url_params(params.url);
load_url_params.referrer = params.referrer;
load_url_params.transition_type = params.transition;
load_url_params.extra_headers = params.extra_headers;
load_url_params.should_replace_current_entry =
params.should_replace_current_entry;
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.transferred_global_request_id =
params.transferred_global_request_id;
load_url_params.should_clear_history_list = true;
source->GetController().LoadURLWithParams(load_url_params);
return source;
}
void CommonWebContentsDelegate::RequestToLockMouse(
content::WebContents* web_contents,
bool user_gesture,
bool last_unlocked_by_target) {
GetWebContents()->GotResponseToLockMouseRequest(true);
}
bool CommonWebContentsDelegate::CanOverscrollContent() const {
return false;
}
bool CommonWebContentsDelegate::IsPopupOrPanel(
const content::WebContents* source) const {
return !is_guest_;
}
content::JavaScriptDialogManager*
CommonWebContentsDelegate::GetJavaScriptDialogManager(
content::WebContents* source) {
if (!dialog_manager_)
dialog_manager_.reset(new AtomJavaScriptDialogManager);
return dialog_manager_.get();
}
content::ColorChooser* CommonWebContentsDelegate::OpenColorChooser(
content::WebContents* web_contents,
SkColor color,
const std::vector<content::ColorSuggestion>& suggestions) {
return chrome::ShowColorChooser(web_contents, color);
}
void CommonWebContentsDelegate::RunFileChooser(
content::WebContents* guest,
const content::FileChooserParams& params) {
if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(owner_window_));
web_dialog_helper_->RunFileChooser(guest, params);
}
void CommonWebContentsDelegate::EnumerateDirectory(content::WebContents* guest,
int request_id,
const base::FilePath& path) {
if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(owner_window_));
web_dialog_helper_->EnumerateDirectory(guest, request_id, path);
}
void CommonWebContentsDelegate::EnterFullscreenModeForTab(
content::WebContents* source, const GURL& origin) {
if (!owner_window_)
return;
SetHtmlApiFullscreen(true);
owner_window_->NotifyWindowEnterHtmlFullScreen();
source->GetRenderViewHost()->WasResized();
}
void CommonWebContentsDelegate::ExitFullscreenModeForTab(
content::WebContents* source) {
if (!owner_window_)
return;
SetHtmlApiFullscreen(false);
owner_window_->NotifyWindowLeaveHtmlFullScreen();
source->GetRenderViewHost()->WasResized();
}
bool CommonWebContentsDelegate::IsFullscreenForTabOrPending(
const content::WebContents* source) const {
return html_fullscreen_;
}
void CommonWebContentsDelegate::DevToolsSaveToFile(
const std::string& url, const std::string& content, bool save_as) {
base::FilePath path;
PathsMap::iterator it = saved_files_.find(url);
if (it != saved_files_.end() && !save_as) {
path = it->second;
} else {
file_dialog::Filters filters;
base::FilePath default_path(base::FilePath::FromUTF8Unsafe(url));
if (!file_dialog::ShowSaveDialog(owner_window_, url, default_path,
filters, &path)) {
base::StringValue url_value(url);
web_contents_->CallClientFunction(
"DevToolsAPI.canceledSaveURL", &url_value, nullptr, nullptr);
return;
}
}
saved_files_[url] = path;
base::WriteFile(path, content.data(), content.size());
// Notify devtools.
base::StringValue url_value(url);
web_contents_->CallClientFunction(
"DevToolsAPI.savedURL", &url_value, nullptr, nullptr);
}
void CommonWebContentsDelegate::DevToolsAppendToFile(
const std::string& url, const std::string& content) {
PathsMap::iterator it = saved_files_.find(url);
if (it == saved_files_.end())
return;
base::AppendToFile(it->second, content.data(), content.size());
// Notify devtools.
base::StringValue url_value(url);
web_contents_->CallClientFunction(
"DevToolsAPI.appendedToURL", &url_value, nullptr, nullptr);
}
void CommonWebContentsDelegate::DevToolsAddFileSystem() {
file_dialog::Filters filters;
base::FilePath default_path;
std::vector<base::FilePath> paths;
int flag = file_dialog::FILE_DIALOG_OPEN_DIRECTORY;
if (!file_dialog::ShowOpenDialog(owner_window_, "", default_path,
filters, flag, &paths))
return;
base::FilePath path = paths[0];
std::string registered_name;
std::string file_system_id = RegisterFileSystem(GetDevToolsWebContents(),
path,
&registered_name);
WorkspaceMap::iterator it = saved_paths_.find(file_system_id);
if (it != saved_paths_.end())
return;
saved_paths_[file_system_id] = path;
FileSystem file_system = CreateFileSystemStruct(GetDevToolsWebContents(),
file_system_id,
registered_name,
path.AsUTF8Unsafe());
scoped_ptr<base::StringValue> error_string_value(
new base::StringValue(std::string()));
scoped_ptr<base::DictionaryValue> file_system_value;
if (!file_system.file_system_path.empty())
file_system_value.reset(CreateFileSystemValue(file_system));
web_contents_->CallClientFunction(
"DevToolsAPI.fileSystemAdded",
error_string_value.get(),
file_system_value.get(),
nullptr);
}
void CommonWebContentsDelegate::DevToolsRemoveFileSystem(
const std::string& file_system_path) {
if (!web_contents_)
return;
base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path);
storage::IsolatedContext::GetInstance()->RevokeFileSystemByPath(path);
for (auto it = saved_paths_.begin(); it != saved_paths_.end(); ++it)
if (it->second == path) {
saved_paths_.erase(it);
break;
}
base::StringValue file_system_path_value(file_system_path);
web_contents_->CallClientFunction(
"DevToolsAPI.fileSystemRemoved",
&file_system_path_value,
nullptr,
nullptr);
}
void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) {
// Window is already in fullscreen mode, save the state.
if (enter_fullscreen && owner_window_->IsFullscreen()) {
native_fullscreen_ = true;
html_fullscreen_ = true;
return;
}
// Exit html fullscreen state but not window's fullscreen mode.
if (!enter_fullscreen && native_fullscreen_) {
html_fullscreen_ = false;
return;
}
owner_window_->SetFullScreen(enter_fullscreen);
html_fullscreen_ = enter_fullscreen;
native_fullscreen_ = false;
}
} // namespace atom

View File

@@ -0,0 +1,124 @@
// 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_COMMON_WEB_CONTENTS_DELEGATE_H_
#define ATOM_BROWSER_COMMON_WEB_CONTENTS_DELEGATE_H_
#include <map>
#include <string>
#include <vector>
#include "brightray/browser/default_web_contents_delegate.h"
#include "brightray/browser/inspectable_web_contents_impl.h"
#include "brightray/browser/inspectable_web_contents_delegate.h"
namespace atom {
class AtomJavaScriptDialogManager;
class NativeWindow;
class WebDialogHelper;
class CommonWebContentsDelegate
: public brightray::DefaultWebContentsDelegate,
public brightray::InspectableWebContentsDelegate {
public:
explicit CommonWebContentsDelegate(bool is_guest);
virtual ~CommonWebContentsDelegate();
// Create a InspectableWebContents object and takes onwership of
// |web_contents|.
void InitWithWebContents(content::WebContents* web_contents,
NativeWindow* owner_window);
// Destroy the managed InspectableWebContents object.
void DestroyWebContents();
// Returns the WebContents managed by this delegate.
content::WebContents* GetWebContents() const;
// Returns the WebContents of devtools.
content::WebContents* GetDevToolsWebContents() const;
brightray::InspectableWebContents* managed_web_contents() const {
return web_contents_.get();
}
bool is_guest() const { return is_guest_; }
protected:
// content::WebContentsDelegate:
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
void RequestToLockMouse(content::WebContents* web_contents,
bool user_gesture,
bool last_unlocked_by_target) override;
bool CanOverscrollContent() const override;
bool IsPopupOrPanel(const content::WebContents* source) const override;
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
content::WebContents* source) override;
content::ColorChooser* OpenColorChooser(
content::WebContents* web_contents,
SkColor color,
const std::vector<content::ColorSuggestion>& suggestions) override;
void RunFileChooser(content::WebContents* web_contents,
const content::FileChooserParams& params) override;
void EnumerateDirectory(content::WebContents* web_contents,
int request_id,
const base::FilePath& path) override;
void EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) override;
void ExitFullscreenModeForTab(content::WebContents* source) override;
bool IsFullscreenForTabOrPending(
const content::WebContents* source) const override;
// brightray::InspectableWebContentsDelegate:
void DevToolsSaveToFile(const std::string& url,
const std::string& content,
bool save_as) override;
void DevToolsAppendToFile(const std::string& url,
const std::string& content) override;
void DevToolsAddFileSystem() override;
void DevToolsRemoveFileSystem(const std::string& file_system_path) override;
private:
// Set fullscreen mode triggered by html api.
void SetHtmlApiFullscreen(bool enter_fullscreen);
// Whether this is guest WebContents or NativeWindow.
const bool is_guest_;
// The window that this WebContents belongs to.
NativeWindow* owner_window_;
// Whether window is fullscreened by HTML5 api.
bool html_fullscreen_;
// Whether window is fullscreened by window api.
bool native_fullscreen_;
scoped_ptr<WebDialogHelper> web_dialog_helper_;
scoped_ptr<AtomJavaScriptDialogManager> dialog_manager_;
// The stored InspectableWebContents object.
// Notice that web_contents_ must be placed after dialog_manager_, so we can
// make sure web_contents_ is destroyed before dialog_manager_, otherwise a
// crash would happen.
scoped_ptr<brightray::InspectableWebContents> web_contents_;
// Maps url to file path, used by the file requests sent from devtools.
typedef std::map<std::string, base::FilePath> PathsMap;
PathsMap saved_files_;
// Maps file system id to file path, used by the file system requests
// sent from devtools.
typedef std::map<std::string, base::FilePath> WorkspaceMap;
WorkspaceMap saved_paths_;
DISALLOW_COPY_AND_ASSIGN(CommonWebContentsDelegate);
};
} // namespace atom
#endif // ATOM_BROWSER_COMMON_WEB_CONTENTS_DELEGATE_H_

View File

@@ -1,10 +1,7 @@
var app = require('app');
var Menu = require('menu');
var MenuItem = require('menu-item');
var BrowserWindow = require('browser-window');
var mainWindow = null;
var menu = null;
// Quit when all windows are closed.
app.on('window-all-closed', function() {
@@ -15,221 +12,9 @@ app.on('ready', function() {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
resizable: false,
'auto-hide-menu-bar': true,
'use-content-size': true,
});
mainWindow.loadUrl('file://' + __dirname + '/index.html');
mainWindow.focus();
if (process.platform == 'darwin') {
var template = [
{
label: 'Electron',
submenu: [
{
label: 'About Electron',
selector: 'orderFrontStandardAboutPanel:'
},
{
type: 'separator'
},
{
label: 'Services',
submenu: []
},
{
type: 'separator'
},
{
label: 'Hide Electron',
accelerator: 'Command+H',
selector: 'hide:'
},
{
label: 'Hide Others',
accelerator: 'Command+Shift+H',
selector: 'hideOtherApplications:'
},
{
label: 'Show All',
selector: 'unhideAllApplications:'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: function() { app.quit(); }
},
]
},
{
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'Command+Z',
selector: 'undo:'
},
{
label: 'Redo',
accelerator: 'Shift+Command+Z',
selector: 'redo:'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'Command+X',
selector: 'cut:'
},
{
label: 'Copy',
accelerator: 'Command+C',
selector: 'copy:'
},
{
label: 'Paste',
accelerator: 'Command+V',
selector: 'paste:'
},
{
label: 'Select All',
accelerator: 'Command+A',
selector: 'selectAll:'
},
]
},
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'Command+R',
click: function() { mainWindow.restart(); }
},
{
label: 'Toggle Full Screen',
accelerator: 'Ctrl+Command+F',
click: function() { mainWindow.setFullScreen(!mainWindow.isFullScreen()); }
},
{
label: 'Toggle Developer Tools',
accelerator: 'Alt+Command+I',
click: function() { mainWindow.toggleDevTools(); }
},
]
},
{
label: 'Window',
submenu: [
{
label: 'Minimize',
accelerator: 'Command+M',
selector: 'performMiniaturize:'
},
{
label: 'Close',
accelerator: 'Command+W',
selector: 'performClose:'
},
{
type: 'separator'
},
{
label: 'Bring All to Front',
selector: 'arrangeInFront:'
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
} else {
var template = [
{
label: '&File',
submenu: [
{
label: '&Open',
accelerator: 'Ctrl+O',
},
{
label: '&Close',
accelerator: 'Ctrl+W',
click: function() { mainWindow.close(); }
},
]
},
{
label: '&View',
submenu: [
{
label: '&Reload',
accelerator: 'Ctrl+R',
click: function() { mainWindow.restart(); }
},
{
label: 'Toggle &Full Screen',
accelerator: 'F11',
click: function() { mainWindow.setFullScreen(!mainWindow.isFullScreen()); }
},
{
label: 'Toggle &Developer Tools',
accelerator: 'Alt+Ctrl+I',
click: function() { mainWindow.toggleDevTools(); }
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
menu = Menu.buildFromTemplate(template);
mainWindow.setMenu(menu);
}
});

View File

@@ -2,6 +2,8 @@ var app = require('app');
var dialog = require('dialog');
var fs = require('fs');
var path = require('path');
var Menu = require('menu');
var BrowserWindow = require('browser-window');
// Quit when all windows are closed and no other one is listening to this.
app.on('window-all-closed', function() {
@@ -29,6 +31,246 @@ for (var i in argv) {
}
}
// Create default menu.
app.once('ready', function() {
var template;
if (process.platform == 'darwin') {
template = [
{
label: 'Electron',
submenu: [
{
label: 'About Electron',
selector: 'orderFrontStandardAboutPanel:'
},
{
type: 'separator'
},
{
label: 'Services',
submenu: []
},
{
type: 'separator'
},
{
label: 'Hide Electron',
accelerator: 'Command+H',
selector: 'hide:'
},
{
label: 'Hide Others',
accelerator: 'Command+Shift+H',
selector: 'hideOtherApplications:'
},
{
label: 'Show All',
selector: 'unhideAllApplications:'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: function() { app.quit(); }
},
]
},
{
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'Command+Z',
selector: 'undo:'
},
{
label: 'Redo',
accelerator: 'Shift+Command+Z',
selector: 'redo:'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'Command+X',
selector: 'cut:'
},
{
label: 'Copy',
accelerator: 'Command+C',
selector: 'copy:'
},
{
label: 'Paste',
accelerator: 'Command+V',
selector: 'paste:'
},
{
label: 'Select All',
accelerator: 'Command+A',
selector: 'selectAll:'
},
]
},
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'Command+R',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.reload();
}
},
{
label: 'Toggle Full Screen',
accelerator: 'Ctrl+Command+F',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
},
{
label: 'Toggle Developer Tools',
accelerator: 'Alt+Command+I',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.toggleDevTools();
}
},
]
},
{
label: 'Window',
submenu: [
{
label: 'Minimize',
accelerator: 'Command+M',
selector: 'performMiniaturize:'
},
{
label: 'Close',
accelerator: 'Command+W',
selector: 'performClose:'
},
{
type: 'separator'
},
{
label: 'Bring All to Front',
selector: 'arrangeInFront:'
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
} else {
template = [
{
label: '&File',
submenu: [
{
label: '&Open',
accelerator: 'Ctrl+O',
},
{
label: '&Close',
accelerator: 'Ctrl+W',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.close();
}
},
]
},
{
label: '&View',
submenu: [
{
label: '&Reload',
accelerator: 'Ctrl+R',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.reload();
}
},
{
label: 'Toggle &Full Screen',
accelerator: 'F11',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
},
{
label: 'Toggle &Developer Tools',
accelerator: 'Alt+Ctrl+I',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.toggleDevTools();
}
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
}
var menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
});
// Start the specified app if there is one specified in command line, otherwise
// start the default app.
if (option.file && !option.webdriver) {
@@ -53,7 +295,7 @@ if (option.file && !option.webdriver) {
} catch(e) {
if (e.code == 'MODULE_NOT_FOUND') {
app.focus();
dialog.showErrorBox('Error opening app', 'The app provided is not a valid electron app, please read the docs on how to write one:\nhttps://github.com/atom/electron/tree/master/docs');
dialog.showErrorBox('Error opening app', 'The app provided is not a valid electron app, please read the docs on how to write one:\nhttps://github.com/atom/electron/tree/master/docs\n\n' + e.toString());
process.exit(1);
} else {
console.error('App threw an error when running', e);

View File

@@ -38,10 +38,7 @@ createGuest = (embedder, params) ->
webViewManager ?= process.atomBinding 'web_view_manager'
id = getNextInstanceId embedder
guest = webContents.create
isGuest: true
guestInstanceId: id
storagePartitionId: params.storagePartitionId
guest = webContents.create {embedder}
guestInstances[id] = {guest, embedder}
# Destroy guest when the embedder is gone or navigated.
@@ -58,14 +55,19 @@ createGuest = (embedder, params) ->
delete @attachParams
@viewInstanceId = params.instanceId
min = width: params.minwidth, height: params.minheight
max = width: params.maxwidth, height: params.maxheight
@setAutoSize params.autosize, min, max
@setSize
normal:
width: params.elementWidth, height: params.elementHeight
enableAutoSize: params.autosize
min:
width: params.minwidth, height: params.minheight
max:
width: params.maxwidth, height: params.maxheight
if params.src
opts = {}
opts.httpreferrer = params.httpreferrer if params.httpreferrer
opts.useragent = params.useragent if params.useragent
opts.httpReferrer = params.httpreferrer if params.httpreferrer
opts.userAgent = params.useragent if params.useragent
@loadUrl params.src, opts
if params.allowtransparency?
@@ -123,7 +125,7 @@ destroyGuest = (embedder, id) ->
delete reverseEmbedderElementsMap[id]
delete embedderElementsMap[key]
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, type, params, requestId) ->
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, params, requestId) ->
event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}", createGuest(event.sender, params)
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, guestInstanceId, params) ->
@@ -132,8 +134,8 @@ ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId,
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) ->
destroyGuest event.sender, id
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', (event, id, params) ->
guestInstances[id]?.guest.setAutoSize params.enableAutoSize, params.min, params.max
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', (event, id, params) ->
guestInstances[id]?.guest.setSize params
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', (event, id, allowtransparency) ->
guestInstances[id]?.guest.setAllowTransparency allowtransparency

View File

@@ -7,6 +7,7 @@ v8Util = process.atomBinding 'v8_util'
valueToMeta = (sender, value) ->
meta = type: typeof value
meta.type = 'buffer' if Buffer.isBuffer value
meta.type = 'value' if value is null
meta.type = 'array' if Array.isArray value
@@ -26,6 +27,8 @@ valueToMeta = (sender, value) ->
meta.members = []
meta.members.push {name: prop, type: typeof field} for prop, field of value
else if meta.type is 'buffer'
meta.value = Array::slice.call value, 0
else
meta.type = 'value'
meta.value = value
@@ -43,6 +46,7 @@ unwrapArgs = (sender, args) ->
when 'value' then meta.value
when 'remote-object' then objectsRegistry.get meta.id
when 'array' then unwrapArgs sender, meta.value
when 'buffer' then new Buffer(meta.value)
when 'object'
ret = v8Util.createObjectWithName meta.name
for member in meta.members

View File

@@ -9,10 +9,7 @@
#include <vector>
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_javascript_dialog_manager.h"
#include "atom/browser/browser.h"
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/web_dialog_helper.h"
#include "atom/browser/window_list.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/atom_version.h"
@@ -31,16 +28,12 @@
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "chrome/browser/printing/print_view_manager_basic.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
@@ -78,6 +71,7 @@ const char* kWebRuntimeFeatures[] = {
switches::kOverlayScrollbars,
switches::kOverlayFullscreenVideo,
switches::kSharedWorker,
switches::kPageVisibility,
};
std::string RemoveWhitespace(const std::string& str) {
@@ -92,21 +86,20 @@ std::string RemoveWhitespace(const std::string& str) {
NativeWindow::NativeWindow(content::WebContents* web_contents,
const mate::Dictionary& options)
: content::WebContentsObserver(web_contents),
: CommonWebContentsDelegate(false),
content::WebContentsObserver(web_contents),
has_frame_(true),
transparent_(false),
enable_larger_than_screen_(false),
is_closed_(false),
node_integration_(true),
has_dialog_attached_(false),
html_fullscreen_(false),
native_fullscreen_(false),
zoom_factor_(1.0),
weak_factory_(this),
inspectable_web_contents_(
brightray::InspectableWebContents::Create(web_contents)) {
weak_factory_(this) {
printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
InitWithWebContents(web_contents, this);
options.Get(switches::kFrame, &has_frame_);
options.Get(switches::kTransparent, &transparent_);
options.Get(switches::kEnableLargerThanScreen, &enable_larger_than_screen_);
@@ -138,9 +131,6 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
// Read the zoom factor before any navigation.
options.Get(switches::kZoomFactor, &zoom_factor_);
web_contents->SetDelegate(this);
inspectable_web_contents()->SetDelegate(this);
WindowList::AddWindow(this);
// Override the user agent to contain application and atom-shell's version.
@@ -294,37 +284,6 @@ bool NativeWindow::HasModalDialog() {
return has_dialog_attached_;
}
void NativeWindow::OpenDevTools(bool can_dock) {
inspectable_web_contents()->SetCanDock(can_dock);
inspectable_web_contents()->ShowDevTools();
}
void NativeWindow::CloseDevTools() {
inspectable_web_contents()->CloseDevTools();
}
bool NativeWindow::IsDevToolsOpened() {
return inspectable_web_contents()->IsDevToolsViewShowing();
}
void NativeWindow::InspectElement(int x, int y) {
OpenDevTools(true);
scoped_refptr<content::DevToolsAgentHost> agent(
content::DevToolsAgentHost::GetOrCreateFor(GetWebContents()));
agent->InspectElement(x, y);
}
void NativeWindow::InspectServiceWorker() {
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
if (agent_host->GetType() ==
content::DevToolsAgentHost::TYPE_SERVICE_WORKER) {
OpenDevTools(true);
inspectable_web_contents()->AttachTo(agent_host);
break;
}
}
}
void NativeWindow::FocusOnWebView() {
GetWebContents()->GetRenderViewHost()->Focus();
}
@@ -373,13 +332,6 @@ void NativeWindow::CapturePage(const gfx::Rect& rect,
kBGRA_8888_SkColorType);
}
void NativeWindow::DestroyWebContents() {
if (!inspectable_web_contents_)
return;
inspectable_web_contents_.reset();
}
void NativeWindow::CloseWebContents() {
bool prevent_default = false;
FOR_EACH_OBSERVER(NativeWindowObserver,
@@ -409,20 +361,8 @@ void NativeWindow::CloseWebContents() {
web_contents->Close();
}
content::WebContents* NativeWindow::GetWebContents() const {
if (!inspectable_web_contents_)
return nullptr;
return inspectable_web_contents()->GetWebContents();
}
content::WebContents* NativeWindow::GetDevToolsWebContents() const {
if (!inspectable_web_contents_)
return nullptr;
return inspectable_web_contents()->devtools_web_contents();
}
void NativeWindow::AppendExtraCommandLineSwitches(
base::CommandLine* command_line, int child_process_id) {
base::CommandLine* command_line) {
// Append --node-integration to renderer process.
command_line->AppendSwitchASCII(switches::kNodeIntegration,
node_integration_ ? "true" : "false");
@@ -489,25 +429,6 @@ void NativeWindow::OverrideWebkitPrefs(content::WebPreferences* prefs) {
}
}
void NativeWindow::SetHtmlApiFullscreen(bool enter_fullscreen) {
// Window is already in fullscreen mode, save the state.
if (enter_fullscreen && IsFullscreen()) {
native_fullscreen_ = true;
html_fullscreen_ = true;
return;
}
// Exit html fullscreen state but not window's fullscreen mode.
if (!enter_fullscreen && native_fullscreen_) {
html_fullscreen_ = false;
return;
}
SetFullScreen(enter_fullscreen);
html_fullscreen_ = enter_fullscreen;
native_fullscreen_ = false;
}
void NativeWindow::NotifyWindowClosed() {
if (is_closed_)
return;
@@ -621,27 +542,7 @@ content::WebContents* NativeWindow::OpenURLFromTab(
if (prevent_default)
return nullptr;
content::NavigationController::LoadURLParams load_url_params(params.url);
load_url_params.referrer = params.referrer;
load_url_params.transition_type = params.transition;
load_url_params.extra_headers = params.extra_headers;
load_url_params.should_replace_current_entry =
params.should_replace_current_entry;
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.transferred_global_request_id =
params.transferred_global_request_id;
load_url_params.should_clear_history_list = true;
source->GetController().LoadURLWithParams(load_url_params);
return source;
}
content::JavaScriptDialogManager* NativeWindow::GetJavaScriptDialogManager(
content::WebContents* source) {
if (!dialog_manager_)
dialog_manager_.reset(new AtomJavaScriptDialogManager);
return dialog_manager_.get();
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
}
void NativeWindow::RenderViewCreated(
@@ -669,38 +570,6 @@ void NativeWindow::BeforeUnloadFired(content::WebContents* tab,
}
}
content::ColorChooser* NativeWindow::OpenColorChooser(
content::WebContents* web_contents,
SkColor color,
const std::vector<content::ColorSuggestion>& suggestions) {
return chrome::ShowColorChooser(web_contents, color);
}
void NativeWindow::RunFileChooser(content::WebContents* web_contents,
const content::FileChooserParams& params) {
if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(this));
web_dialog_helper_->RunFileChooser(web_contents, params);
}
void NativeWindow::EnumerateDirectory(content::WebContents* web_contents,
int request_id,
const base::FilePath& path) {
if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(this));
web_dialog_helper_->EnumerateDirectory(web_contents, request_id, path);
}
void NativeWindow::RequestToLockMouse(content::WebContents* web_contents,
bool user_gesture,
bool last_unlocked_by_target) {
GetWebContents()->GotResponseToLockMouseRequest(true);
}
bool NativeWindow::CanOverscrollContent() const {
return false;
}
void NativeWindow::ActivateContents(content::WebContents* contents) {
FocusOnWebView();
}
@@ -729,11 +598,6 @@ void NativeWindow::CloseContents(content::WebContents* source) {
window_unresposive_closure_.Cancel();
}
bool NativeWindow::IsPopupOrPanel(const content::WebContents* source) const {
// Only popup window can use things like window.moveTo.
return true;
}
void NativeWindow::RendererUnresponsive(content::WebContents* source) {
// Schedule the unresponsive shortly later, since we may receive the
// responsive event soon. This could happen after the whole application had
@@ -750,20 +614,6 @@ void NativeWindow::RendererResponsive(content::WebContents* source) {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive());
}
void NativeWindow::EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) {
SetHtmlApiFullscreen(true);
}
void NativeWindow::ExitFullscreenModeForTab(content::WebContents* source) {
SetHtmlApiFullscreen(false);
}
bool NativeWindow::IsFullscreenForTabOrPending(
const content::WebContents* source) const {
return is_html_api_fullscreen();
}
void NativeWindow::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
// Do nothing, we override this method just to avoid compilation error since
// there are two virtual functions named BeforeUnloadFired.
@@ -800,47 +650,18 @@ void NativeWindow::Observe(int type,
}
}
void NativeWindow::DevToolsSaveToFile(const std::string& url,
const std::string& content,
bool save_as) {
base::FilePath path;
PathsMap::iterator it = saved_files_.find(url);
if (it != saved_files_.end() && !save_as) {
path = it->second;
} else {
file_dialog::Filters filters;
base::FilePath default_path(base::FilePath::FromUTF8Unsafe(url));
if (!file_dialog::ShowSaveDialog(this, url, default_path, filters, &path)) {
base::StringValue url_value(url);
CallDevToolsFunction("DevToolsAPI.canceledSaveURL", &url_value);
return;
}
}
saved_files_[url] = path;
base::WriteFile(path, content.data(), content.size());
// Notify devtools.
base::StringValue url_value(url);
CallDevToolsFunction("DevToolsAPI.savedURL", &url_value);
}
void NativeWindow::DevToolsAppendToFile(const std::string& url,
const std::string& content) {
PathsMap::iterator it = saved_files_.find(url);
if (it == saved_files_.end())
return;
base::AppendToFile(it->second, content.data(), content.size());
// Notify devtools.
base::StringValue url_value(url);
CallDevToolsFunction("DevToolsAPI.appendedToURL", &url_value);
}
void NativeWindow::DevToolsFocused() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus());
}
void NativeWindow::DevToolsOpened() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened());
}
void NativeWindow::DevToolsClosed() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed());
}
void NativeWindow::ScheduleUnresponsiveEvent(int ms) {
if (!window_unresposive_closure_.IsCancelled())
return;
@@ -869,27 +690,4 @@ void NativeWindow::OnCapturePageDone(const CapturePageCallback& callback,
callback.Run(bitmap);
}
void NativeWindow::CallDevToolsFunction(const std::string& function_name,
const base::Value* arg1,
const base::Value* arg2,
const base::Value* arg3) {
std::string params;
if (arg1) {
std::string json;
base::JSONWriter::Write(arg1, &json);
params.append(json);
if (arg2) {
base::JSONWriter::Write(arg2, &json);
params.append(", " + json);
if (arg3) {
base::JSONWriter::Write(arg3, &json);
params.append(", " + json);
}
}
}
base::string16 javascript =
base::UTF8ToUTF16(function_name + "(" + params + ");");
GetDevToolsWebContents()->GetMainFrame()->ExecuteJavaScript(javascript);
}
} // namespace atom

View File

@@ -9,15 +9,13 @@
#include <string>
#include <vector>
#include "atom/browser/common_web_contents_delegate.h"
#include "atom/browser/native_window_observer.h"
#include "atom/browser/ui/accelerator_util.h"
#include "base/cancelable_callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "brightray/browser/default_web_contents_delegate.h"
#include "brightray/browser/inspectable_web_contents_delegate.h"
#include "brightray/browser/inspectable_web_contents_impl.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/readback_types.h"
@@ -50,12 +48,9 @@ class MenuModel;
namespace atom {
class AtomJavaScriptDialogManager;
struct DraggableRegion;
class WebDialogHelper;
class NativeWindow : public brightray::DefaultWebContentsDelegate,
public brightray::InspectableWebContentsDelegate,
class NativeWindow : public CommonWebContentsDelegate,
public content::WebContentsObserver,
public content::NotificationObserver {
public:
@@ -149,11 +144,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
virtual bool IsVisibleOnAllWorkspaces() = 0;
virtual bool IsClosed() const { return is_closed_; }
virtual void OpenDevTools(bool can_dock);
virtual void CloseDevTools();
virtual bool IsDevToolsOpened();
virtual void InspectElement(int x, int y);
virtual void InspectServiceWorker();
virtual void FocusOnWebView();
virtual void BlurWebView();
@@ -181,24 +171,14 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
// Should be called by platform code when user want to close the window.
virtual void CloseWebContents();
// Destroy the WebContents immediately.
virtual void DestroyWebContents();
base::WeakPtr<NativeWindow> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
content::WebContents* GetWebContents() const;
content::WebContents* GetDevToolsWebContents() const;
// Called when renderer process is going to be started.
void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
int child_process_id);
void AppendExtraCommandLineSwitches(base::CommandLine* command_line);
void OverrideWebkitPrefs(content::WebPreferences* prefs);
// Set fullscreen mode triggered by html api.
void SetHtmlApiFullscreen(bool enter_fullscreen);
// Public API used by platform-dependent delegates and observers to send UI
// related notifications.
void NotifyWindowClosed();
@@ -224,9 +204,11 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
observers_.RemoveObserver(obs);
}
bool has_frame() const { return has_frame_; }
brightray::InspectableWebContents* inspectable_web_contents() const {
return managed_web_contents();
}
bool is_html_api_fullscreen() const { return html_fullscreen_; }
bool has_frame() const { return has_frame_; }
void set_has_dialog_attached(bool has_dialog_attached) {
has_dialog_attached_ = has_dialog_attached;
@@ -236,11 +218,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
explicit NativeWindow(content::WebContents* web_contents,
const mate::Dictionary& options);
brightray::InspectableWebContentsImpl* inspectable_web_contents() const {
return static_cast<brightray::InspectableWebContentsImpl*>(
inspectable_web_contents_.get());
}
// Called when the window needs to update its draggable region.
virtual void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) = 0;
@@ -258,38 +235,16 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
content::WebContents* source) override;
void BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) override;
content::ColorChooser* OpenColorChooser(
content::WebContents* web_contents,
SkColor color,
const std::vector<content::ColorSuggestion>& suggestions) override;
void RunFileChooser(content::WebContents* web_contents,
const content::FileChooserParams& params) override;
void EnumerateDirectory(content::WebContents* web_contents,
int request_id,
const base::FilePath& path) override;
void RequestToLockMouse(content::WebContents* web_contents,
bool user_gesture,
bool last_unlocked_by_target) override;
bool CanOverscrollContent() const override;
void ActivateContents(content::WebContents* contents) override;
void DeactivateContents(content::WebContents* contents) override;
void MoveContents(content::WebContents* source,
const gfx::Rect& pos) override;
void CloseContents(content::WebContents* source) override;
bool IsPopupOrPanel(
const content::WebContents* source) const override;
void RendererUnresponsive(content::WebContents* source) override;
void RendererResponsive(content::WebContents* source) override;
void EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) override;
void ExitFullscreenModeForTab(content::WebContents* source) override;
bool IsFullscreenForTabOrPending(
const content::WebContents* source) const override;
// Implementations of content::WebContentsObserver.
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
@@ -302,12 +257,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
const content::NotificationDetails& details) override;
// Implementations of brightray::InspectableWebContentsDelegate.
void DevToolsSaveToFile(const std::string& url,
const std::string& content,
bool save_as) override;
void DevToolsAppendToFile(const std::string& url,
const std::string& content) override;
void DevToolsFocused() override;
void DevToolsOpened() override;
void DevToolsClosed() override;
// Whether window has standard frame.
bool has_frame_;
@@ -328,12 +280,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
// Dispatch unresponsive event to observers.
void NotifyWindowUnresponsive();
// Call a function in devtools.
void CallDevToolsFunction(const std::string& function_name,
const base::Value* arg1 = NULL,
const base::Value* arg2 = NULL,
const base::Value* arg3 = NULL);
// Called when CapturePage has done.
void OnCapturePageDone(const CapturePageCallback& callback,
const SkBitmap& bitmap,
@@ -354,12 +300,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
// There is a dialog that has been attached to window.
bool has_dialog_attached_;
// Whether window is fullscreened by HTML5 api.
bool html_fullscreen_;
// Whether window is fullscreened by window api.
bool native_fullscreen_;
// Closure that would be called when window is unresponsive when closing,
// it should be cancelled when we can prove that the window is responsive.
base::CancelableClosure window_unresposive_closure_;
@@ -375,18 +315,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
base::WeakPtrFactory<NativeWindow> weak_factory_;
scoped_ptr<WebDialogHelper> web_dialog_helper_;
scoped_ptr<AtomJavaScriptDialogManager> dialog_manager_;
// Notice that inspectable_web_contents_ must be placed after dialog_manager_,
// so we can make sure inspectable_web_contents_ is destroyed before
// dialog_manager_, otherwise a crash would happen.
scoped_ptr<brightray::InspectableWebContents> inspectable_web_contents_;
// Maps url to file path, used by the file requests sent from devtools.
typedef std::map<std::string, base::FilePath> PathsMap;
PathsMap saved_files_;
DISALLOW_COPY_AND_ASSIGN(NativeWindow);
};

View File

@@ -55,8 +55,10 @@ class NativeWindowObserver {
virtual void OnWindowEnterHtmlFullScreen() {}
virtual void OnWindowLeaveHtmlFullScreen() {}
// Called when devtools window gets focused.
// Redirect devtools events.
virtual void OnDevToolsFocus() {}
virtual void OnDevToolsOpened() {}
virtual void OnDevToolsClosed() {}
// Called when renderer is hung.
virtual void OnRendererUnresponsive() {}

View File

@@ -541,6 +541,19 @@ bool NativeWindowViews::IsKiosk() {
}
void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) {
if (menu_model == nullptr) {
// Remove accelerators
accelerator_table_.clear();
GetFocusManager()->UnregisterAccelerators(this);
// and menu bar.
#if defined(USE_X11)
global_menu_bar_.reset();
#endif
SetMenuBarVisibility(false);
menu_bar_.reset();
return;
}
RegisterAccelerators(menu_model);
#if defined(USE_X11)
@@ -713,7 +726,8 @@ void NativeWindowViews::OnWidgetActivationChanged(
else
NotifyWindowBlur();
if (active && GetWebContents() && !IsDevToolsOpened())
if (active && GetWebContents() &&
!inspectable_web_contents()->IsDevToolsViewShowing())
GetWebContents()->Focus();
// Hide menu bar when window is blured.

View File

@@ -17,7 +17,7 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.27.1</string>
<string>0.28.0</string>
<key>LSMinimumSystemVersion</key>
<string>10.8.0</string>
<key>NSMainNibFile</key>

View File

@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,27,1,0
PRODUCTVERSION 0,27,1,0
FILEVERSION 0,28,0,0
PRODUCTVERSION 0,28,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
VALUE "FileVersion", "0.27.1"
VALUE "FileVersion", "0.28.0"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
VALUE "ProductVersion", "0.27.1"
VALUE "ProductVersion", "0.28.0"
VALUE "SquirrelAwareVersion", "1"
END
END

View File

@@ -93,12 +93,15 @@ class FileChooserDialog {
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
if (!default_path.empty()) {
if (base::DirectoryExists(default_path))
if (base::DirectoryExists(default_path)) {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog_),
default_path.value().c_str());
else
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog_),
default_path.value().c_str());
} else {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog_),
default_path.DirName().value().c_str());
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog_),
default_path.BaseName().value().c_str());
}
}
if (!filters.empty())

View File

@@ -49,7 +49,16 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos,
bool left_mouse_click) {
// Pass to the observer if appropriate.
if (left_mouse_click) {
NotifyClicked();
NOTIFYICONIDENTIFIER icon_id;
memset(&icon_id, 0, sizeof(NOTIFYICONIDENTIFIER));
icon_id.uID = icon_id_;
icon_id.hWnd = window_;
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
RECT rect = { 0 };
Shell_NotifyIconGetRect(&icon_id, &rect);
NotifyClicked(gfx::Rect(rect));
return;
}

View File

@@ -12,10 +12,9 @@ namespace atom {
namespace {
WebViewManager* GetManagerFromProcess(content::RenderProcessHost* process) {
if (!process)
return nullptr;
auto context = process->GetBrowserContext();
WebViewManager* GetManagerFromWebContents(
const content::WebContents* web_contents) {
auto context = web_contents->GetBrowserContext();
if (!context)
return nullptr;
return static_cast<WebViewManager*>(context->GetGuestManager());
@@ -24,28 +23,17 @@ WebViewManager* GetManagerFromProcess(content::RenderProcessHost* process) {
} // namespace
// static
bool WebViewManager::GetInfoForProcess(content::RenderProcessHost* process,
WebViewInfo* info) {
auto manager = GetManagerFromProcess(process);
bool WebViewManager::GetInfoForWebContents(
const content::WebContents* web_contents, WebViewInfo* info) {
auto manager = GetManagerFromWebContents(web_contents);
if (!manager)
return false;
return manager->GetInfo(process->GetID(), info);
}
// static
void WebViewManager::UpdateGuestProcessID(
content::RenderProcessHost* old_process,
content::RenderProcessHost* new_process) {
auto manager = GetManagerFromProcess(old_process);
if (manager) {
base::AutoLock auto_lock(manager->lock_);
int old_id = old_process->GetID();
int new_id = new_process->GetID();
if (!ContainsKey(manager->webview_info_map_, old_id))
return;
manager->webview_info_map_[new_id] = manager->webview_info_map_[old_id];
manager->webview_info_map_.erase(old_id);
}
base::AutoLock auto_lock(manager->lock_);
auto iter = manager->webview_info_map_.find(web_contents);
if (iter == manager->webview_info_map_.end())
return false;
*info = iter->second;
return true;
}
WebViewManager::WebViewManager(content::BrowserContext* context) {
@@ -61,9 +49,7 @@ void WebViewManager::AddGuest(int guest_instance_id,
const WebViewInfo& info) {
base::AutoLock auto_lock(lock_);
web_contents_embdder_map_[guest_instance_id] = { web_contents, embedder };
int guest_process_id = web_contents->GetRenderProcessHost()->GetID();
webview_info_map_[guest_process_id] = info;
webview_info_map_[web_contents] = info;
// Map the element in embedder to guest.
int owner_process_id = embedder->GetRenderProcessHost()->GetID();
@@ -78,9 +64,7 @@ void WebViewManager::RemoveGuest(int guest_instance_id) {
auto web_contents = web_contents_embdder_map_[guest_instance_id].web_contents;
web_contents_embdder_map_.erase(guest_instance_id);
int guest_process_id = web_contents->GetRenderProcessHost()->GetID();
webview_info_map_.erase(guest_process_id);
webview_info_map_.erase(web_contents);
// Remove the record of element in embedder too.
for (const auto& element : element_instance_id_to_guest_map_)
@@ -90,16 +74,6 @@ void WebViewManager::RemoveGuest(int guest_instance_id) {
}
}
bool WebViewManager::GetInfo(int guest_process_id, WebViewInfo* webview_info) {
base::AutoLock auto_lock(lock_);
WebViewInfoMap::iterator iter = webview_info_map_.find(guest_process_id);
if (iter != webview_info_map_.end()) {
*webview_info = iter->second;
return true;
}
return false;
}
content::WebContents* WebViewManager::GetGuestByInstanceID(
int owner_process_id,
int element_instance_id) {

View File

@@ -29,14 +29,10 @@ class WebViewManager : public content::BrowserPluginGuestManager {
base::FilePath preload_script;
};
// Finds the WebViewManager attached with |process| and returns the
// Finds the WebViewManager attached with |web_contents| and returns the
// WebViewInfo of it.
static bool GetInfoForProcess(content::RenderProcessHost* process,
WebViewInfo* info);
// Updates the guest process ID.
static void UpdateGuestProcessID(content::RenderProcessHost* old_process,
content::RenderProcessHost* new_process);
static bool GetInfoForWebContents(const content::WebContents* web_contents,
WebViewInfo* info);
explicit WebViewManager(content::BrowserContext* context);
virtual ~WebViewManager();
@@ -48,10 +44,6 @@ class WebViewManager : public content::BrowserPluginGuestManager {
const WebViewInfo& info);
void RemoveGuest(int guest_instance_id);
// Looks up the information for the embedder <webview> for a given render
// view, if one exists. Called on the IO thread.
bool GetInfo(int guest_process_id, WebViewInfo* webview_info);
protected:
// content::BrowserPluginGuestManager:
content::WebContents* GetGuestByInstanceID(int owner_process_id,
@@ -89,8 +81,8 @@ class WebViewManager : public content::BrowserPluginGuestManager {
// (embedder_process_id, element_instance_id) => guest_instance_id
std::map<ElementInstanceKey, int> element_instance_id_to_guest_map_;
typedef std::map<int, WebViewInfo> WebViewInfoMap;
// guest_process_id => (guest_instance_id, embedder, ...)
typedef std::map<const content::WebContents*, WebViewInfo> WebViewInfoMap;
// web_contents => (guest_instance_id, embedder, ...)
WebViewInfoMap webview_info_map_;
base::Lock lock_;

View File

@@ -7,6 +7,7 @@
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "native_mate/arguments.h"
#include "native_mate/dictionary.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard.h"
@@ -15,44 +16,32 @@
#include "atom/common/node_includes.h"
namespace mate {
template<>
struct Converter<ui::ClipboardType> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
ui::ClipboardType* out) {
std::string type;
if (!Converter<std::string>::FromV8(isolate, val, &type))
return false;
if (type == "selection")
*out = ui::CLIPBOARD_TYPE_SELECTION;
else
*out = ui::CLIPBOARD_TYPE_COPY_PASTE;
return true;
}
};
} // namespace mate
namespace {
std::vector<base::string16> AvailableFormats(ui::ClipboardType type) {
ui::ClipboardType GetClipboardType(mate::Arguments* args) {
std::string type;
if (args->GetNext(&type) && type == "selection")
return ui::CLIPBOARD_TYPE_SELECTION;
else
return ui::CLIPBOARD_TYPE_COPY_PASTE;
}
std::vector<base::string16> AvailableFormats(mate::Arguments* args) {
std::vector<base::string16> format_types;
bool ignore;
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
clipboard->ReadAvailableTypes(type, &format_types, &ignore);
clipboard->ReadAvailableTypes(GetClipboardType(args), &format_types, &ignore);
return format_types;
}
bool Has(const std::string& format_string, ui::ClipboardType type) {
bool Has(const std::string& format_string, mate::Arguments* args) {
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
ui::Clipboard::FormatType format(ui::Clipboard::GetFormatType(format_string));
return clipboard->IsFormatAvailable(format, type);
return clipboard->IsFormatAvailable(format, GetClipboardType(args));
}
std::string Read(const std::string& format_string,
ui::ClipboardType type) {
mate::Arguments* args) {
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
ui::Clipboard::FormatType format(ui::Clipboard::GetFormatType(format_string));
@@ -61,62 +50,62 @@ std::string Read(const std::string& format_string,
return data;
}
base::string16 ReadText(ui::ClipboardType type) {
base::string16 ReadText(mate::Arguments* args) {
base::string16 data;
ui::Clipboard::GetForCurrentThread()->ReadText(type, &data);
ui::Clipboard::GetForCurrentThread()->ReadText(GetClipboardType(args), &data);
return data;
}
void WriteText(const base::string16& text, ui::ClipboardType type) {
ui::ScopedClipboardWriter writer(type);
void WriteText(const base::string16& text, mate::Arguments* args) {
ui::ScopedClipboardWriter writer(GetClipboardType(args));
writer.WriteText(text);
}
base::string16 ReadHtml(ui::ClipboardType type) {
base::string16 ReadHtml(mate::Arguments* args) {
base::string16 data;
base::string16 html;
std::string url;
uint32 start;
uint32 end;
ui::Clipboard::GetForCurrentThread()->ReadHTML(type, &html, &url,
&start, &end);
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
clipboard->ReadHTML(GetClipboardType(args), &html, &url, &start, &end);
data = html.substr(start, end - start);
return data;
}
void WriteHtml(const base::string16& html,
ui::ClipboardType type) {
ui::ScopedClipboardWriter writer(type);
void WriteHtml(const base::string16& html, mate::Arguments* args) {
ui::ScopedClipboardWriter writer(GetClipboardType(args));
writer.WriteHTML(html, std::string());
}
gfx::Image ReadImage(ui::ClipboardType type) {
SkBitmap bitmap = ui::Clipboard::GetForCurrentThread()->ReadImage(type);
gfx::Image ReadImage(mate::Arguments* args) {
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
SkBitmap bitmap = clipboard->ReadImage(GetClipboardType(args));
return gfx::Image::CreateFrom1xBitmap(bitmap);
}
void WriteImage(const gfx::Image& image, ui::ClipboardType type) {
ui::ScopedClipboardWriter writer(type);
void WriteImage(const gfx::Image& image, mate::Arguments* args) {
ui::ScopedClipboardWriter writer(GetClipboardType(args));
writer.WriteImage(image.AsBitmap());
}
void Clear(ui::ClipboardType type) {
ui::Clipboard::GetForCurrentThread()->Clear(type);
void Clear(mate::Arguments* args) {
ui::Clipboard::GetForCurrentThread()->Clear(GetClipboardType(args));
}
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("_availableFormats", &AvailableFormats);
dict.SetMethod("_has", &Has);
dict.SetMethod("_read", &Read);
dict.SetMethod("_readText", &ReadText);
dict.SetMethod("_writeText", &WriteText);
dict.SetMethod("_readHtml", &ReadHtml);
dict.SetMethod("_writeHtml", &WriteHtml);
dict.SetMethod("_readImage", &ReadImage);
dict.SetMethod("_writeImage", &WriteImage);
dict.SetMethod("_clear", &Clear);
dict.SetMethod("availableFormats", &AvailableFormats);
dict.SetMethod("has", &Has);
dict.SetMethod("read", &Read);
dict.SetMethod("readText", &ReadText);
dict.SetMethod("writeText", &WriteText);
dict.SetMethod("readHtml", &ReadHtml);
dict.SetMethod("writeHtml", &WriteHtml);
dict.SetMethod("readImage", &ReadImage);
dict.SetMethod("writeImage", &WriteImage);
dict.SetMethod("clear", &Clear);
}
} // namespace

View File

@@ -11,6 +11,8 @@
#include "atom/common/node_includes.h"
using crash_reporter::CrashReporter;
namespace mate {
template<>
@@ -31,17 +33,30 @@ struct Converter<std::map<std::string, std::string> > {
}
};
template<>
struct Converter<CrashReporter::UploadReportResult> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const CrashReporter::UploadReportResult& reports) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("date", v8::Date::New(isolate, reports.first*1000.0));
dict.Set("id", reports.second);
return dict.GetHandle();
}
};
} // namespace mate
namespace {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
using crash_reporter::CrashReporter;
mate::Dictionary dict(context->GetIsolate(), exports);
auto report = base::Unretained(CrashReporter::GetInstance());
dict.SetMethod("start",
base::Bind(&CrashReporter::Start,
base::Unretained(CrashReporter::GetInstance())));
base::Bind(&CrashReporter::Start, report));
dict.SetMethod("_getUploadedReports",
base::Bind(&CrashReporter::GetUploadedReports, report));
}
} // namespace

View File

@@ -35,7 +35,7 @@ int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Local<v8::Object> object) {
v8::Local<v8::Value> IDWeakMap::Get(v8::Isolate* isolate, int32_t key) {
if (!Has(key)) {
node::ThrowError("Invalid key");
node::ThrowError(isolate, "Invalid key");
return v8::Undefined(isolate);
}

View File

@@ -1,12 +1,5 @@
binding = process.atomBinding 'clipboard'
module.exports =
availableFormats: (type='standard') -> binding._availableFormats type
has: (format, type='standard') -> binding._has format, type
read: (format, type='standard') -> binding._read format, type
readText: (type='standard') -> binding._readText type
writeText: (text, type='standard') -> binding._writeText text, type
readHtml: (type='standard') -> binding._readHtml type
writeHtml: (markup, type='standard') -> binding._writeHtml markup, type
readImage: (type='standard') -> binding._readImage type
writeImage: (image, type='standard') -> binding._writeImage image, type
clear: (type='standard') -> binding._clear type
if process.platform is 'linux' and process.type is 'renderer'
# On Linux we could not access clipboard in renderer process.
module.exports = require('remote').require 'clipboard'
else
module.exports = process.atomBinding 'clipboard'

View File

@@ -41,19 +41,22 @@ class CrashReporter
start()
getLastCrashReport: ->
reports = this.getUploadedReports()
if reports.length > 0 then reports[0] else null
getUploadedReports: ->
tmpdir =
if process.platform is 'win32'
os.tmpdir()
else
'/tmp'
log = path.join tmpdir, "#{@productName} Crashes", 'uploads.log'
try
reports = String(fs.readFileSync(log)).split('\n')
return null unless reports.length > 1
[time, id] = reports[reports.length - 2].split ','
return {date: new Date(parseInt(time) * 1000), id}
catch e
return null
log =
if process.platform is 'darwin'
path.join tmpdir, "#{@productName} Crashes"
else
path.join tmpdir, "#{@productName} Crashes", 'uploads.log'
binding._getUploadedReports log
crashRepoter = new CrashReporter
module.exports = crashRepoter

View File

@@ -6,8 +6,8 @@
#define ATOM_VERSION_H
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 27
#define ATOM_PATCH_VERSION 1
#define ATOM_MINOR_VERSION 28
#define ATOM_PATCH_VERSION 0
#define ATOM_VERSION_IS_RELEASE 1

View File

@@ -8,7 +8,7 @@
#ifndef ATOM_COMMON_CHROME_VERSION_H_
#define ATOM_COMMON_CHROME_VERSION_H_
#define CHROME_VERSION_STRING "42.0.2311.107"
#define CHROME_VERSION_STRING "43.0.2357.65"
#define CHROME_VERSION "v" CHROME_VERSION_STRING
#endif // ATOM_COMMON_CHROME_VERSION_H_

View File

@@ -7,6 +7,9 @@
#include "atom/browser/browser.h"
#include "atom/common/atom_version.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/common/content_switches.h"
namespace crash_reporter {
@@ -39,4 +42,26 @@ void CrashReporter::SetUploadParameters(const StringMap& parameters) {
SetUploadParameters();
}
std::vector<CrashReporter::UploadReportResult>
CrashReporter::GetUploadedReports(const std::string& path) {
std::string file_content;
std::vector<CrashReporter::UploadReportResult> result;
if (base::ReadFileToString(base::FilePath::FromUTF8Unsafe(path),
&file_content)) {
std::vector<std::string> reports;
base::SplitString(file_content, '\n', &reports);
for (const std::string& report : reports) {
std::vector<std::string> report_item;
base::SplitString(report, ',', &report_item);
int report_time = 0;
if (report_item.size() >= 2 && base::StringToInt(report_item[0],
&report_time)) {
result.push_back(CrashReporter::UploadReportResult(report_time,
report_item[1]));
}
}
}
return result;
}
} // namespace crash_reporter

View File

@@ -7,6 +7,8 @@
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "base/basictypes.h"
@@ -15,6 +17,7 @@ namespace crash_reporter {
class CrashReporter {
public:
typedef std::map<std::string, std::string> StringMap;
typedef std::pair<int, std::string> UploadReportResult; // upload-date, id
static CrashReporter* GetInstance();
@@ -25,6 +28,9 @@ class CrashReporter {
bool skip_system_crash_handler,
const StringMap& extra_parameters);
virtual std::vector<CrashReporter::UploadReportResult> GetUploadedReports(
const std::string& path);
protected:
CrashReporter();
virtual ~CrashReporter();

View File

@@ -6,10 +6,13 @@
#define ATOM_COMMON_CRASH_REPORTER_CRASH_REPORTER_MAC_H_
#include <string>
#include <vector>
#include "atom/common/crash_reporter/crash_reporter.h"
#include "base/compiler_specific.h"
#import "vendor/breakpad/src/client/mac/Framework/Breakpad.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
#include "vendor/crashpad/client/simple_string_dictionary.h"
template <typename T> struct DefaultSingletonTraits;
@@ -33,7 +36,14 @@ class CrashReporterMac : public CrashReporter {
CrashReporterMac();
virtual ~CrashReporterMac();
BreakpadRef breakpad_;
void SetUploadsEnabled(bool enable_uploads);
void SetCrashKeyValue(const base::StringPiece& key,
const base::StringPiece& value);
std::vector<UploadReportResult> GetUploadedReports(
const std::string& path) override;
scoped_ptr<crashpad::SimpleStringDictionary> simple_string_dictionary_;
DISALLOW_COPY_AND_ASSIGN(CrashReporterMac);
};

View File

@@ -4,20 +4,25 @@
#include "atom/common/crash_reporter/crash_reporter_mac.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/mac_util.h"
#include "base/memory/singleton.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#import "vendor/breakpad/src/client/apple/Framework/BreakpadDefines.h"
#include "vendor/crashpad/client/crash_report_database.h"
#include "vendor/crashpad/client/crashpad_client.h"
#include "vendor/crashpad/client/crashpad_info.h"
#include "vendor/crashpad/client/settings.h"
namespace crash_reporter {
CrashReporterMac::CrashReporterMac()
: breakpad_(NULL) {
CrashReporterMac::CrashReporterMac() {
}
CrashReporterMac::~CrashReporterMac() {
if (breakpad_ != NULL)
BreakpadRelease(breakpad_);
}
void CrashReporterMac::InitBreakpad(const std::string& product_name,
@@ -26,54 +31,52 @@ void CrashReporterMac::InitBreakpad(const std::string& product_name,
const std::string& submit_url,
bool auto_submit,
bool skip_system_crash_handler) {
if (breakpad_ != NULL)
BreakpadRelease(breakpad_);
NSMutableDictionary* parameters =
[NSMutableDictionary dictionaryWithCapacity:4];
[parameters setValue:@ATOM_PRODUCT_NAME
forKey:@BREAKPAD_PRODUCT];
[parameters setValue:base::SysUTF8ToNSString(product_name)
forKey:@BREAKPAD_PRODUCT_DISPLAY];
[parameters setValue:base::SysUTF8ToNSString(version)
forKey:@BREAKPAD_VERSION];
[parameters setValue:base::SysUTF8ToNSString(company_name)
forKey:@BREAKPAD_VENDOR];
[parameters setValue:base::SysUTF8ToNSString(submit_url)
forKey:@BREAKPAD_URL];
[parameters setValue:(auto_submit ? @"YES" : @"NO")
forKey:@BREAKPAD_SKIP_CONFIRM];
[parameters setValue:(skip_system_crash_handler ? @"YES" : @"NO")
forKey:@BREAKPAD_SEND_AND_EXIT];
// Report all crashes (important for testing the crash reporter).
[parameters setValue:@"0" forKey:@BREAKPAD_REPORT_INTERVAL];
// Put dump files under "/tmp/ProductName Crashes".
std::string dump_dir = "/tmp/" + product_name + " Crashes";
[parameters setValue:base::SysUTF8ToNSString(dump_dir)
forKey:@BREAKPAD_DUMP_DIRECTORY];
// Temporarily run Breakpad in-process on 10.10 and later because APIs that
// it depends on got broken (http://crbug.com/386208).
// This can catch crashes in the browser process only.
if (base::mac::IsOSYosemiteOrLater()) {
[parameters setObject:[NSNumber numberWithBool:YES]
forKey:@BREAKPAD_IN_PROCESS];
}
breakpad_ = BreakpadCreate(parameters);
if (!breakpad_) {
LOG(ERROR) << "Failed to initialize breakpad";
// check whether crashpad has been initilized.
// Only need to initilize once.
if (simple_string_dictionary_)
return;
std::string dump_dir = "/tmp/" + product_name + " Crashes";
base::FilePath database_path(dump_dir);
if (is_browser_) {
@autoreleasepool {
base::FilePath framework_bundle_path = base::mac::FrameworkBundlePath();
base::FilePath handler_path =
framework_bundle_path.Append("Resources").Append("crashpad_handler");
crashpad::CrashpadClient crashpad_client;
if (crashpad_client.StartHandler(handler_path, database_path,
submit_url,
StringMap(),
std::vector<std::string>())) {
crashpad_client.UseHandler();
}
} // @autoreleasepool
}
for (StringMap::const_iterator iter = upload_parameters_.begin();
iter != upload_parameters_.end(); ++iter) {
BreakpadAddUploadParameter(breakpad_,
base::SysUTF8ToNSString(iter->first),
base::SysUTF8ToNSString(iter->second));
crashpad::CrashpadInfo* crashpad_info =
crashpad::CrashpadInfo::GetCrashpadInfo();
if (skip_system_crash_handler) {
crashpad_info->set_system_crash_reporter_forwarding(
crashpad::TriState::kDisabled);
}
simple_string_dictionary_.reset(new crashpad::SimpleStringDictionary());
crashpad_info->set_simple_annotations(simple_string_dictionary_.get());
SetCrashKeyValue("prod", ATOM_PRODUCT_NAME);
SetCrashKeyValue("process_type", is_browser_ ? "browser" : "renderer");
SetCrashKeyValue("ver", version);
for (const auto& upload_parameter: upload_parameters_) {
SetCrashKeyValue(upload_parameter.first, upload_parameter.second);
}
if (is_browser_) {
scoped_ptr<crashpad::CrashReportDatabase> database =
crashpad::CrashReportDatabase::Initialize(database_path);
if (database) {
database->GetSettings()->SetUploadsEnabled(auto_submit);
}
}
}
@@ -81,6 +84,46 @@ void CrashReporterMac::SetUploadParameters() {
upload_parameters_["platform"] = "darwin";
}
void CrashReporterMac::SetCrashKeyValue(const base::StringPiece& key,
const base::StringPiece& value) {
simple_string_dictionary_->SetKeyValue(key.data(), value.data());
}
std::vector<CrashReporter::UploadReportResult>
CrashReporterMac::GetUploadedReports(const std::string& path) {
std::vector<CrashReporter::UploadReportResult> uploaded_reports;
base::FilePath file_path(path);
if (!base::PathExists(file_path)) {
return uploaded_reports;
}
// Load crashpad database.
scoped_ptr<crashpad::CrashReportDatabase> database =
crashpad::CrashReportDatabase::Initialize(file_path);
DCHECK(database);
std::vector<crashpad::CrashReportDatabase::Report> completed_reports;
crashpad::CrashReportDatabase::OperationStatus status =
database->GetCompletedReports(&completed_reports);
if (status != crashpad::CrashReportDatabase::kNoError) {
return uploaded_reports;
}
for (const crashpad::CrashReportDatabase::Report& completed_report :
completed_reports) {
if (completed_report.uploaded) {
uploaded_reports.push_back(
UploadReportResult(static_cast<int>(completed_report.creation_time),
completed_report.id));
}
}
auto sort_by_time = [](const UploadReportResult& a,
const UploadReportResult& b) {return a.first >= b.first;};
std::sort(uploaded_reports.begin(), uploaded_reports.end(), sort_by_time);
return uploaded_reports;
}
// static
CrashReporterMac* CrashReporterMac::GetInstance() {
return Singleton<CrashReporterMac>::get();

View File

@@ -14,7 +14,7 @@ getOrCreateArchive = (p) ->
# Clean cache on quit.
process.on 'exit', ->
archive.destroy() for p, archive of cachedArchives
archive.destroy() for own p, archive of cachedArchives
# Separate asar package's path from full path.
splitPath = (p) ->
@@ -310,6 +310,38 @@ exports.wrapFsWithAsar = (fs) ->
files
internalModuleReadFile = process.binding('fs').internalModuleReadFile
process.binding('fs').internalModuleReadFile = (p) ->
[isAsar, asarPath, filePath] = splitPath p
return internalModuleReadFile p unless isAsar
archive = getOrCreateArchive asarPath
return undefined unless archive
info = archive.getFileInfo filePath
return undefined unless info
return '' if info.size is 0
buffer = new Buffer(info.size)
fd = archive.getFd()
retrun undefined unless fd >= 0
fs.readSync fd, buffer, 0, info.size, info.offset
buffer.toString 'utf8'
internalModuleStat = process.binding('fs').internalModuleStat
process.binding('fs').internalModuleStat = (p) ->
[isAsar, asarPath, filePath] = splitPath p
return internalModuleStat p unless isAsar
archive = getOrCreateArchive asarPath
return -34 unless archive # -ENOENT
stats = archive.stat filePath
return -34 unless stats # -ENOENT
if stats.isDirectory then return 1 else return 0
overrideAPI fs, 'open'
overrideAPI child_process, 'execFile'
overrideAPISync process, 'dlopen', 1

View File

@@ -23,6 +23,13 @@ bool Converter<base::DictionaryValue>::FromV8(v8::Isolate* isolate,
}
}
v8::Local<v8::Value> Converter<base::DictionaryValue>::ToV8(
v8::Isolate* isolate,
const base::DictionaryValue& val) {
scoped_ptr<atom::V8ValueConverter> converter(new atom::V8ValueConverter);
return converter->ToV8Value(&val, isolate->GetCurrentContext());
}
bool Converter<base::ListValue>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::ListValue* out) {

View File

@@ -19,6 +19,8 @@ struct Converter<base::DictionaryValue> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::DictionaryValue* out);
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::DictionaryValue& val);
};
template<>
@@ -27,7 +29,7 @@ struct Converter<base::ListValue> {
v8::Local<v8::Value> val,
base::ListValue* out);
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::ListValue& val);
const base::ListValue& val);
};
} // namespace mate

View File

@@ -178,6 +178,9 @@ void NodeBindings::LoadEnvironment(node::Environment* env) {
if (node::use_debug_agent)
node::EnableDebug(env);
v8::Local<v8::Value> msg = mate::StringToV8(env->isolate(), "loaded");
node::MakeCallback(env->isolate(), env->process_object(), "emit", 1, &msg);
}
void NodeBindings::PrepareMessageLoop() {

View File

@@ -87,6 +87,9 @@ const char kDisableAutoHideCursor[] = "disable-auto-hide-cursor";
// Use the OS X's standard window instead of the textured window.
const char kStandardWindow[] = "standard-window";
// Path to client certificate.
const char kClientCertificate[] = "client-certificate";
// Web runtime features.
const char kExperimentalFeatures[] = "experimental-features";
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";
@@ -95,6 +98,9 @@ const char kOverlayScrollbars[] = "overlay-scrollbars";
const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video";
const char kSharedWorker[] = "shared-worker";
// Set page visiblity to always visible.
const char kPageVisibility[] = "page-visibility";
// Disable HTTP cache.
const char kDisableHttpCache[] = "disable-http-cache";

View File

@@ -45,6 +45,7 @@ extern const char kTransparent[];
extern const char kType[];
extern const char kDisableAutoHideCursor[];
extern const char kStandardWindow[];
extern const char kClientCertificate[];
extern const char kExperimentalFeatures[];
extern const char kExperimentalCanvasFeatures[];
@@ -52,6 +53,7 @@ extern const char kSubpixelFontScaling[];
extern const char kOverlayScrollbars[];
extern const char kOverlayFullscreenVideo[];
extern const char kSharedWorker[];
extern const char kPageVisibility[];
extern const char kDisableHttpCache[];

View File

@@ -30,7 +30,9 @@ RenderView* GetCurrentRenderView() {
return RenderView::FromWebView(view);
}
void Send(const base::string16& channel, const base::ListValue& arguments) {
void Send(v8::Isolate* isolate,
const base::string16& channel,
const base::ListValue& arguments) {
RenderView* render_view = GetCurrentRenderView();
if (render_view == NULL)
return;
@@ -39,10 +41,11 @@ void Send(const base::string16& channel, const base::ListValue& arguments) {
render_view->GetRoutingID(), channel, arguments));
if (!success)
node::ThrowError("Unable to send AtomViewHostMsg_Message");
node::ThrowError(isolate, "Unable to send AtomViewHostMsg_Message");
}
base::string16 SendSync(const base::string16& channel,
base::string16 SendSync(v8::Isolate* isolate,
const base::string16& channel,
const base::ListValue& arguments) {
base::string16 json;
@@ -57,7 +60,7 @@ base::string16 SendSync(const base::string16& channel,
bool success = render_view->Send(message);
if (!success)
node::ThrowError("Unable to send AtomViewHostMsg_Message_Sync");
node::ThrowError(isolate, "Unable to send AtomViewHostMsg_Message_Sync");
return json;
}

View File

@@ -10,9 +10,11 @@
#define USE(WTF_FEATURE) (defined WTF_USE_##WTF_FEATURE && WTF_USE_##WTF_FEATURE) // NOLINT
#define ENABLE(WTF_FEATURE) (defined ENABLE_##WTF_FEATURE && ENABLE_##WTF_FEATURE) // NOLINT
#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 "native_mate/callback.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "third_party/WebKit/public/web/WebDocument.h"
@@ -78,6 +80,14 @@ v8::Local<v8::Value> WebFrame::RegisterEmbedderCustomElement(
return web_frame_->document().registerEmbedderCustomElement(name, options, c);
}
void WebFrame::RegisterElementResizeCallback(
int element_instance_id,
const GuestViewContainer::ResizeCallback& callback) {
auto guest_view_container = GuestViewContainer::FromID(element_instance_id);
if (guest_view_container)
guest_view_container->RegisterElementResizeCallback(callback);
}
void WebFrame::AttachGuest(int id) {
content::RenderFrame::FromWebFrame(web_frame_)->AttachGuest(id);
}
@@ -106,6 +116,8 @@ mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder(
.SetMethod("getZoomFactor", &WebFrame::GetZoomFactor)
.SetMethod("registerEmbedderCustomElement",
&WebFrame::RegisterEmbedderCustomElement)
.SetMethod("registerElementResizeCallback",
&WebFrame::RegisterElementResizeCallback)
.SetMethod("attachGuest", &WebFrame::AttachGuest)
.SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider)
.SetMethod("registerUrlSchemeAsSecure",

View File

@@ -7,6 +7,7 @@
#include <string>
#include "atom/renderer/guest_view_container.h"
#include "base/memory/scoped_ptr.h"
#include "native_mate/handle.h"
#include "native_mate/wrappable.h"
@@ -42,6 +43,9 @@ class WebFrame : public mate::Wrappable {
v8::Local<v8::Value> RegisterEmbedderCustomElement(
const base::string16& name, v8::Local<v8::Object> options);
void RegisterElementResizeCallback(
int element_instance_id,
const GuestViewContainer::ResizeCallback& callback);
void AttachGuest(int element_instance_id);
// Set the provider that will be used by SpellCheckClient for spell check.

View File

@@ -10,6 +10,8 @@ wrapArgs = (args) ->
valueToMeta = (value) ->
if Array.isArray value
type: 'array', value: wrapArgs(value)
else if Buffer.isBuffer value
type: 'buffer', value: Array::slice.call(value, 0)
else if value? and typeof value is 'object' and v8Util.getHiddenValue value, 'atomId'
type: 'remote-object', id: v8Util.getHiddenValue value, 'atomId'
else if value? and typeof value is 'object'
@@ -30,6 +32,7 @@ metaToValue = (meta) ->
switch meta.type
when 'value' then meta.value
when 'array' then (metaToValue(el) for el in meta.members)
when 'buffer' then new Buffer(meta.value)
when 'error'
throw new Error("#{meta.message}\n#{meta.stack}")
else

View File

@@ -191,6 +191,21 @@ content::BrowserPluginDelegate* AtomRendererClient::CreateBrowserPluginDelegate(
}
}
bool AtomRendererClient::ShouldOverridePageVisibilityState(
const content::RenderFrame* render_frame,
blink::WebPageVisibilityState* override_state) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
bool b;
if (IsSwitchEnabled(command_line, switches::kPageVisibility, &b)
&& b) {
*override_state = blink::WebPageVisibilityStateVisible;
return true;
}
return false;
}
void AtomRendererClient::EnableWebRuntimeFeatures() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
bool b;

View File

@@ -55,6 +55,9 @@ class AtomRendererClient : public content::ContentRendererClient,
content::RenderFrame* render_frame,
const std::string& mime_type,
const GURL& original_url) override;
bool ShouldOverridePageVisibilityState(
const content::RenderFrame* render_frame,
blink::WebPageVisibilityState* override_state) override;
void EnableWebRuntimeFeatures();

View File

@@ -4,12 +4,54 @@
#include "atom/renderer/guest_view_container.h"
#include <map>
#include "base/lazy_instance.h"
namespace atom {
GuestViewContainer::GuestViewContainer(content::RenderFrame* render_frame) {
namespace {
using GuestViewContainerMap = std::map<int, GuestViewContainer*>;
static base::LazyInstance<GuestViewContainerMap> g_guest_view_container_map =
LAZY_INSTANCE_INITIALIZER;
} // namespace
GuestViewContainer::GuestViewContainer(content::RenderFrame* render_frame)
: render_frame_(render_frame) {
}
GuestViewContainer::~GuestViewContainer() {
if (element_instance_id_ > 0)
g_guest_view_container_map.Get().erase(element_instance_id_);
}
// static
GuestViewContainer* GuestViewContainer::FromID(int element_instance_id) {
GuestViewContainerMap* guest_view_containers =
g_guest_view_container_map.Pointer();
auto it = guest_view_containers->find(element_instance_id);
return it == guest_view_containers->end() ? nullptr : it->second;
}
void GuestViewContainer::RegisterElementResizeCallback(
const ResizeCallback& callback) {
element_resize_callback_ = callback;
}
void GuestViewContainer::SetElementInstanceID(int element_instance_id) {
element_instance_id_ = element_instance_id;
g_guest_view_container_map.Get().insert(
std::make_pair(element_instance_id, this));
}
void GuestViewContainer::DidResizeElement(const gfx::Size& old_size,
const gfx::Size& new_size) {
if (element_resize_callback_.is_null())
return;
element_resize_callback_.Run(old_size, new_size);
}
} // namespace atom

View File

@@ -5,17 +5,38 @@
#ifndef ATOM_RENDERER_GUEST_VIEW_CONTAINER_H_
#define ATOM_RENDERER_GUEST_VIEW_CONTAINER_H_
#include "base/callback.h"
#include "content/public/renderer/browser_plugin_delegate.h"
#include "v8/include/v8.h"
namespace gfx {
class Size;
}
namespace atom {
class GuestViewContainer : public content::BrowserPluginDelegate {
public:
typedef base::Callback<void(const gfx::Size&, const gfx::Size&)>
ResizeCallback;
explicit GuestViewContainer(content::RenderFrame* render_frame);
~GuestViewContainer() override;
static GuestViewContainer* FromID(int element_instance_id);
void RegisterElementResizeCallback(const ResizeCallback& callback);
// content::BrowserPluginDelegate:
void SetElementInstanceID(int element_instance_id) final;
void DidResizeElement(const gfx::Size& old_size,
const gfx::Size& new_size) final;
private:
int element_instance_id_;
content::RenderFrame* render_frame_;
ResizeCallback element_resize_callback_;
DISALLOW_COPY_AND_ASSIGN(GuestViewContainer);
};

View File

@@ -88,12 +88,8 @@ if nodeIntegration in ['true', 'all', 'except-iframe', 'manual-enable-iframe']
window.addEventListener 'unload', ->
process.emit 'exit'
else
# The Module.runMain will run process._tickCallck() immediately, so we are
# able to delete the symbols in this tick even though we used process.nextTick
# to schedule it.
# It is important that we put this in process.nextTick, if we delete them now
# some code in node.js will complain about "process not defined".
process.nextTick ->
# Delete Node's symbols after the Environment has been loaded.
process.once 'loaded', ->
delete global.process
delete global.setImmediate
delete global.clearImmediate

View File

@@ -62,6 +62,7 @@ window.open = (url, frameName='', features='') ->
window.alert = (message, title='') ->
dialog = remote.require 'dialog'
buttons = ['OK']
message = message.toString()
dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons}
# And the confirm().

View File

@@ -55,9 +55,9 @@ module.exports =
ipc.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}"
ipc.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}"
createGuest: (type, params, callback) ->
createGuest: (params, callback) ->
requestId++
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', type, params, requestId
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', params, requestId
ipc.once "ATOM_SHELL_RESPONSE_#{requestId}", callback
attachGuest: (elementInstanceId, guestInstanceId, params) ->
@@ -67,8 +67,8 @@ module.exports =
destroyGuest: (guestInstanceId) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId
setAutoSize: (guestInstanceId, params) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', guestInstanceId, params
setSize: (guestInstanceId, params) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', guestInstanceId, params
setAllowTransparency: (guestInstanceId, allowtransparency) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', guestInstanceId, allowtransparency

View File

@@ -28,7 +28,7 @@ class WebViewAttribute
# Changes the attribute's value without triggering its mutation handler.
setValueIgnoreMutation: (value) ->
@ignoreMutation = true
@webViewImpl.webviewNode.setAttribute(@name, value || '')
@setValue value
@ignoreMutation = false
# Defines this attribute as a property on the webview node.
@@ -72,7 +72,7 @@ class AutosizeDimensionAttribute extends WebViewAttribute
handleMutation: (oldValue, newValue) ->
return unless @webViewImpl.guestInstanceId
guestViewInternal.setAutoSize @webViewImpl.guestInstanceId,
guestViewInternal.setSize @webViewImpl.guestInstanceId,
enableAutoSize: @webViewImpl.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue()
min:
width: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0
@@ -119,6 +119,14 @@ class SrcAttribute extends WebViewAttribute
else
''
setValueIgnoreMutation: (value) ->
WebViewAttribute::setValueIgnoreMutation value
# takeRecords() is needed to clear queued up src mutations. Without it, it
# is possible for this change to get picked up asyncronously by src's
# mutation observer |observer|, and then get handled even though we do not
# want to handle this mutation.
@observer.takeRecords()
handleMutation: (oldValue, newValue) ->
# Once we have navigated, we don't allow clearing the src attribute.
# Once <webview> enters a navigated state, it cannot return to a
@@ -138,7 +146,10 @@ class SrcAttribute extends WebViewAttribute
setupMutationObserver: ->
@observer = new MutationObserver (mutations) =>
for mutation in mutations
@handleMutation mutation.oldValue, @getValue()
oldValue = mutation.oldValue
newValue = @getValue()
return if oldValue isnt newValue
@handleMutation oldValue, newValue
params =
attributes: true,
attributeOldValue: true,
@@ -160,10 +171,10 @@ class SrcAttribute extends WebViewAttribute
# Navigate to |this.src|.
opts = {}
httpreferrer = @webViewImpl.attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue()
if httpreferrer then opts.httpreferrer = httpreferrer
if httpreferrer then opts.httpReferrer = httpreferrer
useragent = @webViewImpl.attributes[webViewConstants.ATTRIBUTE_USERAGENT].getValue()
if useragent then opts.useragent = useragent
if useragent then opts.userAgent = useragent
guestContents = remote.getGuestWebContents(@webViewImpl.guestInstanceId)
guestContents.loadUrl @getValue(), opts

View File

@@ -13,7 +13,6 @@ class WebViewImpl
constructor: (@webviewNode) ->
v8Util.setHiddenValue @webviewNode, 'internal', this
@attached = false
@pendingGuestCreation = false
@elementAttached = false
@beforeFirstNavigation = true
@@ -87,9 +86,12 @@ class WebViewImpl
@browserPluginNode.removeAttribute webViewConstants.ATTRIBUTE_INTERNALINSTANCEID
@internalInstanceId = parseInt newValue
# Track when the element resizes using the element resize callback.
webFrame.registerElementResizeCallback @internalInstanceId, @onElementResize.bind(this)
return unless @guestInstanceId
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildAttachParams()
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildParams()
onSizeChanged: (webViewEvent) ->
newWidth = webViewEvent.newWidth
@@ -107,6 +109,9 @@ class WebViewImpl
minWidth = @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() | width
minHeight = @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() | width
minWidth = Math.min minWidth, maxWidth
minHeight = Math.min minHeight, maxHeight
if not @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() or
(newWidth >= minWidth and
newWidth <= maxWidth and
@@ -118,17 +123,21 @@ class WebViewImpl
# changed.
@dispatchEvent webViewEvent
onElementResize: (oldSize, newSize) ->
# Dispatch the 'resize' event.
resizeEvent = new Event('resize', bubbles: true)
resizeEvent.oldWidth = oldSize.width
resizeEvent.oldHeight = oldSize.height
resizeEvent.newWidth = newSize.width
resizeEvent.newHeight = newSize.height
@dispatchEvent resizeEvent
if @guestInstanceId
guestViewInternal.setSize @guestInstanceId, normal: newSize
createGuest: ->
return if @pendingGuestCreation
params =
storagePartitionId: @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue()
guestViewInternal.createGuest 'webview', params, (guestInstanceId) =>
@pendingGuestCreation = false
unless @elementAttached
guestViewInternal.destroyGuest guestInstanceId
return
guestViewInternal.createGuest @buildParams(), (guestInstanceId) =>
@attachWindow guestInstanceId
@pendingGuestCreation = true
dispatchEvent: (webViewEvent) ->
@webviewNode.dispatchEvent webViewEvent
@@ -160,21 +169,30 @@ class WebViewImpl
onAttach: (storagePartitionId) ->
@attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue storagePartitionId
buildAttachParams: ->
buildParams: ->
params =
instanceId: @viewInstanceId
userAgentOverride: @userAgentOverride
for attributeName, attribute of @attributes
for own attributeName, attribute of @attributes
params[attributeName] = attribute.getValue()
# When the WebView is not participating in layout (display:none)
# then getBoundingClientRect() would report a width and height of 0.
# However, in the case where the WebView has a fixed size we can
# use that value to initially size the guest so as to avoid a relayout of
# the on display:block.
css = window.getComputedStyle @webviewNode, null
elementRect = @webviewNode.getBoundingClientRect()
params.elementWidth = parseInt(elementRect.width) ||
parseInt(css.getPropertyValue('width'))
params.elementHeight = parseInt(elementRect.height) ||
parseInt(css.getPropertyValue('height'))
params
attachWindow: (guestInstanceId) ->
@guestInstanceId = guestInstanceId
params = @buildAttachParams()
return true unless @internalInstanceId
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildParams()
# Registers browser plugin <object> custom element.
registerBrowserPluginElement = ->

View File

@@ -31,8 +31,11 @@ class PdfFunctions {
render_pdf_to_dc_func_(NULL) {}
bool Init() {
base::FilePath pdf_module_path(FILE_PATH_LITERAL("pdf.dll"));
pdf_lib_.Reset(base::LoadNativeLibrary(pdf_module_path, NULL));
base::FilePath module_path;
if (!PathService::Get(base::DIR_MODULE, &module_path))
return false;
base::FilePath::StringType name(FILE_PATH_LITERAL("pdf.dll"));
pdf_lib_.Reset(base::LoadNativeLibrary(module_path.Append(name), NULL));
if (!pdf_lib_.is_valid()) {
LOG(WARNING) << "Couldn't load PDF plugin";
return false;

View File

@@ -9,6 +9,7 @@
'component%': 'static_library',
'python': 'python',
'openssl_no_asm': 1,
'node_target_type': 'shared_library',
'node_install_npm': 'false',
'node_prefix': '',
'node_shared_cares': 'false',
@@ -26,6 +27,7 @@
'uv_library': 'static_library',
'uv_parent_path': 'vendor/node/deps/uv',
'uv_use_dtrace': 'false',
'V8_BASE': '',
'v8_postmortem_support': 'false',
'v8_enable_i18n_support': 'false',
# Required by Linux (empty for now, should support it in future).
@@ -99,7 +101,10 @@
],
}],
['_target_name=="node"', {
'include_dirs': [ '<(libchromiumcontent_src_dir)/v8/include' ],
'include_dirs': [
'<(libchromiumcontent_src_dir)/v8',
'<(libchromiumcontent_src_dir)/v8/include',
],
'conditions': [
['OS=="mac" and libchromiumcontent_component==0', {
# -all_load is the "whole-archive" on OS X.

View File

@@ -43,7 +43,7 @@ You can also create a window without chrome by using
other windows
* `fullscreen` Boolean - Whether the window should show in fullscreen, when
set to `false` the fullscreen button would also be hidden on OS X
* `skip-taskbar` Boolean - Do not show window in Taskbar
* `skip-taskbar` Boolean - Do not show window in taskbar
* `zoom-factor` Number - The default zoom factor of the page, zoom factor is
zoom percent / 100, so `3.0` represents `300%`
* `kiosk` Boolean - The kiosk mode
@@ -97,6 +97,10 @@ You can also create a window without chrome by using
* `shared-worker` Boolean
* `direct-write` Boolean - Whether the DirectWrite font rendering system on
Windows is enabled
* `page-visibility` Boolean - Page would be forced to be always in visible
or hidden state once set, instead of reflecting current window's
visibility. Users can set it to `true` to prevent throttling of DOM
timers.
Creates a new `BrowserWindow` with native properties set by the `options`.
Usually you only need to set the `width` and `height`, other properties will
@@ -127,9 +131,9 @@ window.onbeforeunload = function(e) {
console.log('I do not want to be closed');
// Unlike usual browsers, in which a string should be returned and the user is
// prompted to confirm the page unload. Electron gives the power completely
// to the developers, return empty string or false would prevent the unloading
// now. You can also use the dialog API to let user confirm it.
// prompted to confirm the page unload, Electron gives developers more options.
// Returning empty string or false would prevent the unloading now.
// You can also use the dialog API to let the user confirm closing the application.
return false;
};
```
@@ -460,7 +464,7 @@ Starts or stops flashing the window to attract user's attention.
* `skip` Boolean
Makes the window do not show in Taskbar.
Makes the window not show in the taskbar.
### BrowserWindow.setKiosk(flag)
@@ -479,13 +483,13 @@ Returns whether the window is in kiosk mode.
Sets the pathname of the file the window represents, and the icon of the file
will show in window's title bar.
__Note__: This API is available only on OS X.
__Note__: This API is only available on OS X.
### BrowserWindow.getRepresentedFilename()
Returns the pathname of the file the window represents.
__Note__: This API is available only on OS X.
__Note__: This API is only available on OS X.
### BrowserWindow.setDocumentEdited(edited)
@@ -494,13 +498,13 @@ __Note__: This API is available only on OS X.
Specifies whether the windows document has been edited, and the icon in title
bar will become grey when set to `true`.
__Note__: This API is available only on OS X.
__Note__: This API is only available on OS X.
### BrowserWindow.IsDocumentEdited()
Whether the window's document has been edited.
__Note__: This API is available only on OS X.
__Note__: This API is only available on OS X.
### BrowserWindow.openDevTools([options])
@@ -567,9 +571,9 @@ Calling `window.print()` in web page is equivalent to call
doesn't need print feature, you can safely remove `pdf.dll` in saving binary
size.
### BrowserWindow.loadUrl(url)
### BrowserWindow.loadUrl(url, [options])
Same with `webContents.loadUrl(url)`.
Same with `webContents.loadUrl(url, [options])`.
### BrowserWindow.reload()
@@ -579,7 +583,8 @@ Same with `webContents.reload`.
* `menu` Menu
Sets the `menu` as the window top menu.
Sets the `menu` as the window's menu bar, setting it to `null` will remove the
menu bar.
__Note:__ This API is not available on OS X.
@@ -599,20 +604,20 @@ it will assume `app.getName().desktop`.
### BrowserWindow.setOverlayIcon(overlay, description)
* `overlay` [NativeImage](native-image.md) - the icon to display on the bottom
right corner of the Taskbar icon. If this parameter is `null`, the overlay is
right corner of the taskbar icon. If this parameter is `null`, the overlay is
cleared
* `description` String - a description that will be provided to Accessibility
screen readers
Sets a 16px overlay onto the current Taskbar icon, usually used to convey some sort of application status or to passively notify the user.
Sets a 16px overlay onto the current taskbar icon, usually used to convey some sort of application status or to passively notify the user.
__Note:__ This API is only available on Windows, Win7 or above
__Note:__ This API is only available on Windows (Windows 7 and above)
### BrowserWindow.showDefinitionForSelection()
Shows pop-up dictionary that searches the selected word on the page.
__Note__: This API is available only on OS X.
__Note__: This API is only available on OS X.
### BrowserWindow.setAutoHideMenuBar(hide)
@@ -748,7 +753,7 @@ Calling `event.preventDefault()` can prevent creating new windows.
Emitted when user or the page wants to start an navigation, it can happen when
`window.location` object is changed or user clicks a link in the page.
This event will not emit when the navigation is started programmely with APIs
This event will not emit when the navigation is started programmatically with APIs
like `WebContents.loadUrl` and `WebContents.back`.
Calling `event.preventDefault()` can prevent the navigation.
@@ -773,9 +778,12 @@ Emitted when a plugin process is crashed.
Emitted when the WebContents is destroyed.
### WebContents.loadUrl(url)
### WebContents.loadUrl(url, [options])
* `url` URL
* `options` URL
* `httpReferrer` String - A HTTP Referer url
* `userAgent` String - A user agent originating the request
Loads the `url` in the window, the `url` must contains the protocol prefix,
e.g. the `http://` or `file://`.

View File

@@ -1,6 +1,6 @@
# Supported Chrome command line switches
Following command lines switches in Chrome browser are also Supported in
The following command lines switches in Chrome browser are also supported in
Electron, you can use [app.commandLine.appendSwitch][append-switch] to append
them in your app's main script before the [ready][ready] event of [app][app]
module is emitted:
@@ -11,9 +11,14 @@ 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`
Sets `path` of client certificate file.
## --disable-http-cache
Disables the disk cache for HTTP requests.
@@ -60,15 +65,19 @@ Like `--host-rules` but these `rules` only apply to the host resolver.
## --ignore-certificate-errors
Ignore certificate related errors.
Ignores certificate related errors.
## --ppapi-flash-path
## --ppapi-flash-path=`path`
Set path to pepper flash plugin for use.
Sets `path` of pepper flash plugin.
## --ppapi-flash-version
## --ppapi-flash-version=`version`
Set the pepper flash version.
Sets `version` of pepper flash plugin.
## --log-net-log=`path`
Enables saving net log events and writes them to `path`.
## --v=`log_level`

View File

@@ -27,11 +27,23 @@ crashReporter.start({
* Only string properties are send correctly.
* Nested objects are not supported.
Developers are required to call the API before using other crashReporter APIs.
**Note:** On OS X, electron uses a new `crashpad` client, which is different
with the `breakpad` on Windows and Linux. To enable crash collection feature,
you are required to call `crashReporter.start` API to initiliaze `crashpad` in
main process, even you only collect crash report in renderer process.
## crashReporter.getLastCrashReport()
Returns the date and ID of last crash report, when there was no crash report
sent or the crash reporter is not started, `null` will be returned.
## crashReporter.getUploadedReports()
Returns all uploaded crash reports, each report contains date and uploaded ID.
# crash-reporter payload
The crash reporter will send the following data to the `submitUrl` as `POST`:

View File

@@ -1,7 +1,7 @@
# dialog
The `dialog` module provides APIs to show native system dialogs, so web
applications can get the same user experience with native applications.
applications can deliver the same user experience as native applications.
An example of showing a dialog to select multiple files and directories:
@@ -11,7 +11,7 @@ var dialog = require('dialog');
console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]}));
```
**Note for OS X**: If you want to present dialogs as sheets, the only thing you have to do is to provide a `BrowserWindow` reference in the `browserWindow` parameter.
**Note for OS X**: If you want to present dialogs as sheets, the only thing you have to do is provide a `BrowserWindow` reference in the `browserWindow` parameter.
## dialog.showOpenDialog([browserWindow], [options], [callback])
@@ -36,18 +36,17 @@ selected, an example is:
filters: [
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
{ name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
{ name: 'Custom File Type', extensions: ['as'] },
],
{ name: 'Custom File Type', extensions: ['as'] }
]
}
```
If a `callback` is passed, the API call would be asynchronous and the result
would be passed via `callback(filenames)`
**Note:** On Windows and Linux, an open dialog could not be both file selector
and directory selector at the same time, so if you set `properties` to
`['openFile', 'openDirectory']` on these platforms, a directory selector would
be showed.
**Note:** On Windows and Linux, an open dialog can not be both a file selector
and a directory selector, so if you set `properties` to
`['openFile', 'openDirectory']` on these platforms, a directory selector will be shown.
## dialog.showSaveDialog([browserWindow], [options], [callback])
@@ -58,14 +57,14 @@ be showed.
* `filters` Array
* `callback` Function
On success, returns the path of file chosen by the user, otherwise returns
On success, returns the path of the file chosen by the user, otherwise returns
`undefined`.
The `filters` specifies an array of file types that can be displayed, see
`dialog.showOpenDialog` for an example.
If a `callback` is passed, the API call would be asynchronous and the result
would be passed via `callback(filename)`
If a `callback` is passed, the API call will be asynchronous and the result
will be passed via `callback(filename)`
## dialog.showMessageBox([browserWindow], options, [callback])
@@ -82,8 +81,8 @@ would be passed via `callback(filename)`
Shows a message box, it will block until the message box is closed. It returns
the index of the clicked button.
If a `callback` is passed, the API call would be asynchronous and the result
would be passed via `callback(response)`
If a `callback` is passed, the API call will be asynchronous and the result
will be passed via `callback(response)`
## dialog.showErrorBox(title, content)

View File

@@ -28,7 +28,7 @@ var win = new BrowserWindow({ transparent: true, frame: false });
API to set window shape to solve this, but currently blocked at an
[upstream bug](https://code.google.com/p/chromium/issues/detail?id=387234).
* Transparent window is not resizable, setting `resizable` to `true` may make
transprent window stop working on some platforms.
transparent window stop working on some platforms.
* The `blur` filter only applies to the web page, so there is no way to apply
blur effect to the content below the window.
* On Windows transparent window will not work when DWM is disabled.

View File

@@ -1,16 +1,18 @@
# global-shortcut
The `global-shortcut` module can register/unregister a global keyboard shortcut
in operating system, so that you can custom the operations for various shortcuts.
Note that it is global, even the app does not get focused, it still works.
in operating system, so that you can customize the operations for various shortcuts.
Note that the shortcut is global, even if the app does not get focused, it will still work.
```javascript
var globalShortcut = require('global-shortcut');
// Register a 'ctrl+x' shortcut listener.
var ret = globalShortcut.register('ctrl+x', function() { console.log('ctrl+x is pressed'); })
if (!ret)
console.log('registerion fails');
if (!ret) {
console.log('registration failed');
}
// Check whether a shortcut is registered.
console.log(globalShortcut.isRegistered('ctrl+x'));
@@ -34,7 +36,7 @@ the registered shortcut is pressed by user.
* `accelerator` [Accelerator](accelerator.md)
Returns whether shortcut of `accelerator` is registered.
Returns `true` or `false` depending on if the shortcut `accelerator` is registered.
## globalShortcut.unregister(accelerator)

View File

@@ -29,8 +29,11 @@ window.addEventListener('contextmenu', function (e) {
Another example of creating the application menu with the simple template API:
```javascript
// main.js
```html
<!-- index.html -->
<script>
var remote = require('remote');
var Menu = remote.require('menu');
var template = [
{
label: 'Electron',
@@ -69,7 +72,7 @@ var template = [
{
label: 'Quit',
accelerator: 'Command+Q',
click: function() { app.quit(); }
selector: 'terminate:'
},
]
},
@@ -108,7 +111,7 @@ var template = [
label: 'Select All',
accelerator: 'Command+A',
selector: 'selectAll:'
},
}
]
},
{
@@ -117,12 +120,12 @@ var template = [
{
label: 'Reload',
accelerator: 'Command+R',
click: function() { BrowserWindow.getFocusedWindow().reloadIgnoringCache(); }
click: function() { remote.getCurrentWindow().reload(); }
},
{
label: 'Toggle DevTools',
accelerator: 'Alt+Command+I',
click: function() { BrowserWindow.getFocusedWindow().toggleDevTools(); }
click: function() { remote.getCurrentWindow().toggleDevTools(); }
},
]
},
@@ -145,18 +148,19 @@ var template = [
{
label: 'Bring All to Front',
selector: 'arrangeInFront:'
},
}
]
},
{
label: 'Help',
submenu: []
},
}
];
menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu); // Must be called within app.on('ready', function(){ ... });
Menu.setApplicationMenu(menu);
</script>
```
## Class: Menu
@@ -281,10 +285,10 @@ Template:
```javascript
[
{label: '4', id: '4'}
{label: '5', id: '5'}
{label: '1', id: '1', position: 'before=4'}
{label: '2', id: '2'}
{label: '4', id: '4'},
{label: '5', id: '5'},
{label: '1', id: '1', position: 'before=4'},
{label: '2', id: '2'},
{label: '3', id: '3'}
]
```
@@ -303,11 +307,11 @@ Template:
```javascript
[
{label: 'a', position: 'endof=letters'}
{label: '1', position: 'endof=numbers'}
{label: 'b', position: 'endof=letters'}
{label: '2', position: 'endof=numbers'}
{label: 'c', position: 'endof=letters'}
{label: 'a', position: 'endof=letters'},
{label: '1', position: 'endof=numbers'},
{label: 'b', position: 'endof=letters'},
{label: '2', position: 'endof=numbers'},
{label: 'c', position: 'endof=letters'},
{label: '3', position: 'endof=numbers'}
]
```

View File

@@ -1,6 +1,6 @@
# Process object
The `process` object in Electron has following differences between the one in
The `process` object in Electron has the following differences from the one in
upstream node:
* `process.type` String - Process's type, can be `browser` (i.e. main process) or `renderer`.

View File

@@ -7,8 +7,8 @@ An example of implementing a protocol that has the same effect with the
`file://` protocol:
```javascript
var app = require('app'),
path = require('path');
var app = require('app');
var path = require('path');
app.on('ready', function() {
var protocol = require('protocol');

View File

@@ -20,6 +20,8 @@ var win = new BrowserWindow({ width: 800, height: 600 });
win.loadUrl('https://github.com');
```
Note: for the reverse (access renderer process from main process), you can use [webContents.executeJavascript](https://github.com/atom/electron/blob/master/docs/api/browser-window.md#browserwindowwebcontents).
## Remote objects
Each object (including functions) returned by the `remote` module represents an
@@ -97,7 +99,8 @@ returns a `Buffer` by calling the passed callback:
```javascript
var remote = require('remote');
var fs = require('fs');
remote.getCurrentWindow().capturePage(function(buf) {
remote.getCurrentWindow().capturePage(function(image) {
var buf = image.toPng();
fs.writeFile('/tmp/screenshot.png', buf, function(err) {
console.log(err);
});
@@ -115,7 +118,8 @@ The work-around is to write the `buf` in the main process, where it is a real
```javascript
var remote = require('remote');
remote.getCurrentWindow().capturePage(function(buf) {
remote.getCurrentWindow().capturePage(function(image) {
var buf = image.toPng();
remote.require('fs').writeFile('/tmp/screenshot.png', buf, function(err) {
console.log(err);
});

View File

@@ -15,7 +15,7 @@ app.on('ready', function(){
{ label: 'Item1', type: 'radio' },
{ label: 'Item2', type: 'radio' },
{ label: 'Item3', type: 'radio', checked: true },
{ label: 'Item4', type: 'radio' },
{ label: 'Item4', type: 'radio' }
]);
appIcon.setToolTip('This is my application.');
appIcon.setContextMenu(contextMenu);
@@ -55,7 +55,7 @@ Creates a new tray icon associated with the `image`.
Emitted when the tray icon is clicked.
__Note:__ The `bounds` payload is only implemented on OS X.
__Note:__ The `bounds` payload is only implemented on OS X and Windows 7 or newer.
### Event: 'double-clicked'

View File

@@ -18,7 +18,7 @@ form, the `webview` tag includes the `src` of the web page and css styles that
control the appearance of the `webview` container:
```html
<webview id="foo" src="https://www.github.com/" style="width:640px; height:480px"></webview>
<webview id="foo" src="https://www.github.com/" style="display:inline-block; width:640px; height:480px"></webview>
```
If you want to control the guest content in any way, you can write JavaScript
@@ -390,7 +390,7 @@ without regard for log level or other properties.
```javascript
webview.addEventListener('console-message', function(e) {
console.log('Guest page logged a message: ', e.message);
console.log('Guest page logged a message:', e.message);
});
```
@@ -448,7 +448,7 @@ webview.send('ping');
var ipc = require('ipc');
ipc.on('ping', function() {
ipc.sendToHost('pong');
})
});
```
### crashed

View File

@@ -2,30 +2,33 @@
## Prerequisites
* [Node.js](http://nodejs.org)
* Python 2.7.x. Some distributions like CentOS still use Python 2.6.x
so you may need to check your Python version with `python -V`.
* Node.js v0.12.x. There are various ways to install Node. One can download
source code from [Node.js] (http://nodejs.org) and compile from source.
Doing so permits installing Node to your own home directory as a standard user.
Or try repositories such as [NodeSource] (https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories)
* Clang 3.4 or later
* Development headers of GTK+ and libnotify
On Ubuntu you could install the libraries via:
On Ubuntu, install the following libraries:
```bash
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \
libnotify-dev libgnome-keyring-dev libgconf2-dev \
libasound2-dev libcap-dev libcups2-dev libxtst-dev \
gcc-multilib g++-multilib
libxss1 gcc-multilib g++-multilib
```
Latest Node.js could be installed via ppa:
Other distributions may offer similar packages for installation via package
managers such as yum. Or one can compile from source code.
```bash
$ sudo apt-get install python-software-properties software-properties-common
$ sudo add-apt-repository ppa:chris-lea/node.js
$ sudo apt-get update
$ sudo apt-get install nodejs
# Update to latest npm
$ sudo npm install npm -g
```
## If You Use Virtual Machines For Building
If you plan to build electron on a virtual machine, you will need a fixed-size
device container of at least 25 gigabytes in size.
## Getting the code
@@ -36,8 +39,9 @@ $ git clone https://github.com/atom/electron.git
## Bootstrapping
The bootstrap script will download all necessary build dependencies and create
build project files. Notice that we're using `ninja` to build Electron so
there is no `Makefile` generated.
build project files. You must have Python 2.7.x for the script to succeed.
Downloading certain files could take a long time. Notice that we are using
`ninja` to build Electron so there is no `Makefile` generated.
```bash
$ cd electron
@@ -46,76 +50,48 @@ $ ./script/bootstrap.py -v
## Building
Build both `Release` and `Debug` targets:
If you would like to build both `Release` and `Debug` targets:
```bash
$ ./script/build.py
```
You can also only build the `Debug` target:
This script will cause a very large Electron executable to be placed in
the directory `out/R`. The file size is in excess of 1.3 gigabytes. This
happens because the Release target binary contains debugging symbols.
To reduce the file size, run the `create-dist.py` script:
```bash
$ ./script/create-dist.py
```
This will put a working distribution with much smaller file sizes in
the `dist` directory. After running the create-dist.py script, you
may want to remove the 1.3+ gigabyte binary which is still in out/R.
You can also build the `Debug` target only:
```bash
$ ./script/build.py -c D
```
After building is done, you can find `atom` under `out/D`.
After building is done, you can find the `electron` debug binary
under `out/D`.
## Cleaning
To clean the build files:
```bash
$ ./script/clean.py
```
## Troubleshooting
### fatal error: bits/predefs.h: No such file or directory
If you got an error like this:
````
In file included from /usr/include/stdio.h:28:0,
from ../../../svnsrc/libgcc/../gcc/tsystem.h:88,
from ../../../svnsrc/libgcc/libgcc2.c:29:
/usr/include/features.h:324:26: fatal error: bits/predefs.h: No such file or directory
#include <bits/predefs.h>
````
Then you need to install `gcc-multilib` and `g++-multilib`, on Ubuntu you can do
this:
```bash
$ sudo apt-get install gcc-multilib g++-multilib
```
### error adding symbols: DSO missing from command line
If you got an error like this:
````
/usr/bin/ld: vendor/download/libchromiumcontent/Release/libchromiumcontent.so: undefined reference to symbol 'gconf_client_get'
//usr/lib/x86_64-linux-gnu/libgconf-2.so.4: error adding symbols: DSO missing from command line
````
libchromiumcontent.so is build with clang 3.0 which is incompatible with newer
versions of clang. Try using clang 3.0, default version in Ubuntu 12.04.
### libudev.so.0 missing
If you get an error like:
````
/usr/bin/ld: warning: libudev.so.0, needed by .../vendor/brightray/vendor/download/libchromiumcontent/Release/libchromiumcontent.so, not found (try using -rpath or -rpath-link)
````
and you are on Ubuntu 13.04+, 64 bit system, try doing
```bash
sudo ln -s /lib/x86_64-linux-gnu/libudev.so.1.3.5 /usr/lib/libudev.so.0
```
for ubuntu 13.04+ 32 bit systems, try doing
```bash
sudo ln -s /lib/i386-linux-gnu/libudev.so.1.3.5 /usr/lib/libudev.so.0
```
also see
https://github.com/nwjs/nw.js/wiki/The-solution-of-lacking-libudev.so.0
Make sure you have installed all the build dependencies.
## Tests

View File

@@ -35,7 +35,7 @@ exposing your app's source code to users.
To use an `asar` archive to replace the `app` folder, you need to rename the
archive to `app.asar`, and put it under Electron's resources directory like
bellow, and Electron will then try read the archive and start from it.
below, and Electron will then try read the archive and start from it.
On OS X:

View File

@@ -70,9 +70,9 @@ var dockMenu = Menu.buildFromTemplate([
{ label: 'New Window', click: function() { console.log('New Window'); } },
{ label: 'New Window with Settings', submenu: [
{ label: 'Basic' },
{ label: 'Pro'},
{ label: 'Pro'}
]},
{ label: 'New Command...'},
{ label: 'New Command...'}
]);
app.dock.setMenu(dockMenu);
```
@@ -119,7 +119,7 @@ app.setUserTasks([
iconPath: process.execPath,
iconIndex: 0,
title: 'New Window',
description: 'Create a new window',
description: 'Create a new window'
}
]);
```
@@ -149,8 +149,8 @@ On Windows, a taskbar button can be used to display a progress bar. This enables
a window to provide progress information to the user without that user having to
switch to the window itself.
The Unity DE also has a simililar feature that allows you to specify progress
bar in the lancher.
The Unity DE also has a similar feature that allows you to specify the progress
bar in the launcher.
__Progress bar in taskbar button:__

View File

@@ -1,14 +1,14 @@
# DevTools extension
To make debugging more easy, Electron has added basic support for
To make debugging easier, Electron has basic support for
[Chrome DevTools Extension][devtools-extension].
For most devtools extensions, you can simply download their source codes and use
For most devtools extensions, you can simply download the source code and use
the `BrowserWindow.addDevToolsExtension` API to load them, the loaded extensions
will be remembered so you don't need to call the API every time when creating
a window.
For example to use the React DevTools Extension, first you need to download its
For example to use the [React DevTools Extension](https://github.com/facebook/react-devtools), first you need to download its
source code:
```bash
@@ -16,41 +16,37 @@ $ cd /some-directory
$ git clone --recursive https://github.com/facebook/react-devtools.git
```
Then you can load it in Electron by opening the devtools in arbitray window,
and run this code in the console of devtools:
Then you can load the extension in Electron by opening devtools in any window,
and then running the following code in the devtools console:
```javascript
require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools')
require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools');
```
To unload the extension, you can call `BrowserWindow.removeDevToolsExtension`
API with its name and it will disappear the next time you open the devtools:
API with its name and it will not load the next time you open the devtools:
```javascript
require('remote').require('browser-window').removeDevToolsExtension('React Developer Tools')
require('remote').require('browser-window').removeDevToolsExtension('React Developer Tools');
```
## Format of devtools extension
Ideally all devtools extension written for Chrome browser can be loaded by
Electron, but they have to be in a plain directory, for those packaged `crx`
extensions, there is no way in Electron to load them unless you find a way to
extensions, there is no way for Electron to load them unless you find a way to
extract them into a directory.
## Background pages
Currently Electron doesn't support the background pages of chrome extensions,
so for some devtools extensions that rely on this feature, they may not work
well in Electron
Currently Electron doesn't support the background pages feature in chrome extensions,
so for some devtools extensions that rely on this feature, they may not work in Electron.
## `chrome.*` APIs
Some chrome extensions use `chrome.*` APIs for some features, there is some
effort to implement those APIs in Electron to make them work, but we have
only implemented few for now.
Some chrome extensions use `chrome.*` APIs for some features, there has been some
effort to implement those APIs in Electron, however not all are implemented.
So if the devtools extension is using APIs other than `chrome.devtools.*`, it is
very likely to fail, but you can report those extensions in the issues tracker
so we can add support for those APIs.
Given that not all `chrome.*` APIs are implemented if the devtools extension is using APIs other than `chrome.devtools.*`, the extension is very likely not to work. You can report failing extensions in the issue tracker so that we can add support for those APIs.
[devtools-extension]: https://developer.chrome.com/extensions/devtools

View File

@@ -82,8 +82,9 @@ var mainWindow = null;
// Quit when all windows are closed.
app.on('window-all-closed', function() {
if (process.platform != 'darwin')
if (process.platform != 'darwin') {
app.quit();
}
});
// This method will be called when Electron has done everything

View File

@@ -23,8 +23,9 @@ var mainWindow = null;
// Quit when all windows are closed.
app.on('window-all-closed', function() {
if (process.platform != 'darwin')
if (process.platform != 'darwin') {
app.quit();
}
});
// Specify flash path.

View File

@@ -49,14 +49,14 @@ and where to find Electron's binary:
```javascript
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder().
// The "9515" is the port opened by chrome driver.
usingServer('http://localhost:9515').
withCapabilities({chromeOptions: {
// Here is the path to your Electron binary.
binary: '/Path-to-Your-App.app/Contents/MacOS/Atom'}}).
forBrowser('electron').
build();
var driver = new webdriver.Builder()
// The "9515" is the port opened by chrome driver.
.usingServer('http://localhost:9515')
.withCapabilities({chromeOptions: {
// Here is the path to your Electron binary.
binary: '/Path-to-Your-App.app/Contents/MacOS/Atom'}})
.forBrowser('electron')
.build();
driver.get('http://www.google.com');
driver.findElement(webdriver.By.name('q')).sendKeys('webdriver');
@@ -70,4 +70,10 @@ driver.wait(function() {
driver.quit();
```
## Workflow
To test your application without rebuilding Electron, simply [place](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md) your app source into Electron's resource directory.
[chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/

View File

@@ -115,8 +115,6 @@
'atom/browser/atom_javascript_dialog_manager.h',
'atom/browser/atom_quota_permission_context.cc',
'atom/browser/atom_quota_permission_context.h',
'atom/browser/atom_resource_dispatcher_host_delegate.cc',
'atom/browser/atom_resource_dispatcher_host_delegate.h',
'atom/browser/atom_speech_recognition_manager_delegate.cc',
'atom/browser/atom_speech_recognition_manager_delegate.h',
'atom/browser/browser.cc',
@@ -125,6 +123,8 @@
'atom/browser/browser_mac.mm',
'atom/browser/browser_win.cc',
'atom/browser/browser_observer.h',
'atom/browser/common_web_contents_delegate.cc',
'atom/browser/common_web_contents_delegate.h',
'atom/browser/javascript_environment.cc',
'atom/browser/javascript_environment.h',
'atom/browser/mac/atom_application.h',

View File

@@ -38,6 +38,7 @@ TARGET_BINARIES = {
'msvcp120.dll',
'msvcr120.dll',
'node.dll',
'pdf.dll',
'content_resources_200_percent.pak',
'ui_resources_200_percent.pak',
'xinput1_3.dll',

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python
import os
import platform
import subprocess
import sys
@@ -43,10 +44,19 @@ def run_gyp(target_arch, component):
defines = [
'-Dlibchromiumcontent_component={0}'.format(component),
'-Dtarget_arch={0}'.format(target_arch),
'-Dhost_arch={0}'.format(target_arch),
'-Dlibrary=static_library',
]
return subprocess.call([python, gyp, '-f', 'ninja', '--depth', '.',
'atom.gyp', '-Icommon.gypi'] + defines)
def get_host_arch():
if platform.architecture()[0] == '32bit':
return 'ia32'
else:
return 'x64'
if __name__ == '__main__':
sys.exit(main())

View File

@@ -188,6 +188,7 @@ describe 'browser-window module', ->
w.loadUrl 'file://' + path.join(fixtures, 'api', 'close-beforeunload-empty-string.html')
describe 'new-window event', ->
return if isCI and process.platform is 'darwin'
it 'emits when window.open is called', (done) ->
w.webContents.once 'new-window', (e, url, frameName) ->
e.preventDefault()
@@ -230,6 +231,7 @@ describe 'browser-window module', ->
w.minimize()
describe 'will-navigate event', ->
return if isCI and process.platform is 'darwin'
it 'emits when user starts a navigation', (done) ->
@timeout 10000
w.webContents.on 'will-navigate', (event, url) ->
@@ -239,6 +241,7 @@ describe 'browser-window module', ->
w.loadUrl "file://#{fixtures}/pages/will-navigate.html"
describe 'dom-ready event', ->
return if isCI and process.platform is 'darwin'
it 'emits when document is loaded', (done) ->
ipc = remote.require 'ipc'
server = http.createServer (req, res) ->

View File

@@ -25,8 +25,10 @@ describe 'clipboard module', ->
markup =
if process.platform is 'darwin'
'<meta charset=\'utf-8\'><string>Hi</string>'
else
else if process.platform is 'linux'
'<meta http-equiv="content-type" ' +
'content="text/html; charset=utf-8"><string>Hi</string>'
else
'<string>Hi</string>'
clipboard.writeHtml text
assert.equal clipboard.readHtml(), markup

View File

@@ -5,12 +5,10 @@ url = require 'url'
remote = require 'remote'
formidable = require 'formidable'
crashReporter = remote.require 'crash-reporter'
BrowserWindow = remote.require 'browser-window'
describe 'crash-reporter module', ->
# We have trouble makeing crash reporter work on Yosemite.
return if process.platform is 'darwin'
fixtures = path.resolve __dirname, 'fixtures'
w = null
@@ -41,10 +39,15 @@ describe 'crash-reporter module', ->
res.end('abc-123-def')
server.close()
done()
server.listen 0, '127.0.0.1', ->
# Server port is generated randomly for the first run, it will be reused
# when page is refreshed.
port = remote.process.port
server.listen port, '127.0.0.1', ->
{port} = server.address()
remote.process.port = port
url = url.format
protocol: 'file'
pathname: path.join fixtures, 'api', 'crash.html'
search: "?port=#{port}"
crashReporter.start {'submitUrl': 'http://127.0.0.1:' + port}
w.loadUrl url

View File

@@ -5,6 +5,7 @@ var BrowserWindow = require('browser-window');
var Menu = require('menu');
var window = null;
process.port = 0; // will be used by crash-reporter spec.
app.commandLine.appendSwitch('js-flags', '--expose_gc');
app.commandLine.appendSwitch('ignore-certificate-errors');

View File

@@ -54,7 +54,7 @@ describe '<webview> tag', ->
assert.equal e.message, 'function'
done()
webview.addEventListener 'console-message', listener2
webview.src = "file://#{fixtures}/pages/native-module.html"
webview.reload()
webview.addEventListener 'did-finish-load', listener
webview.setAttribute 'nodeintegration', 'on'
webview.src = "file://#{fixtures}/pages/native-module.html"

1
vendor/crashpad vendored Submodule

Submodule vendor/crashpad added at e6a0d433b0

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