mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
452 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40066ca343 | ||
|
|
6671e78f5d | ||
|
|
0480e32f99 | ||
|
|
ead94b7b1f | ||
|
|
288ef13fb5 | ||
|
|
4765445b4f | ||
|
|
03ec5ced05 | ||
|
|
e2e18200fb | ||
|
|
328583575d | ||
|
|
704b8335aa | ||
|
|
d25d1f3f8b | ||
|
|
abd466ee4a | ||
|
|
fcc1f4d7ed | ||
|
|
c1267b2320 | ||
|
|
ee61ab2d26 | ||
|
|
0ec7f35c24 | ||
|
|
377a8eefb2 | ||
|
|
1ee4caae2d | ||
|
|
ebf509bbe4 | ||
|
|
4c45c80fb4 | ||
|
|
b40a0e6e0c | ||
|
|
51f60d8d73 | ||
|
|
0b8c2545b9 | ||
|
|
5efb88e7ea | ||
|
|
937668097a | ||
|
|
da0a1eac24 | ||
|
|
c3b058cea3 | ||
|
|
2e9fd7ce77 | ||
|
|
4c9f5b71f7 | ||
|
|
418efbe660 | ||
|
|
006c77a00f | ||
|
|
f109591d03 | ||
|
|
c47ad29124 | ||
|
|
6e3cb9e8eb | ||
|
|
70aa9b06ee | ||
|
|
c8a2246952 | ||
|
|
d35996b4a0 | ||
|
|
a9c40de393 | ||
|
|
549cccfce4 | ||
|
|
1da75f5c18 | ||
|
|
68c413c391 | ||
|
|
83111ad84c | ||
|
|
89328c873c | ||
|
|
0c92d44077 | ||
|
|
6f221cb6b1 | ||
|
|
11f64b714d | ||
|
|
4c23e3950a | ||
|
|
44376374b0 | ||
|
|
022c2c0d8c | ||
|
|
0dba0b9cad | ||
|
|
97930fcd84 | ||
|
|
9c88a5c1ab | ||
|
|
7692edf50e | ||
|
|
8215d661ca | ||
|
|
8f820e09be | ||
|
|
145d5abe80 | ||
|
|
b90c0c7895 | ||
|
|
dda7740399 | ||
|
|
3f4455a79d | ||
|
|
f47851f1e7 | ||
|
|
eb064240f8 | ||
|
|
7b881ebc23 | ||
|
|
2bfc7aa152 | ||
|
|
eae5cc9d2c | ||
|
|
03434f45bb | ||
|
|
4ded709307 | ||
|
|
4b6639c9fd | ||
|
|
4b65610d40 | ||
|
|
755c1f5238 | ||
|
|
04c8bc38b2 | ||
|
|
ad3f4a26fd | ||
|
|
7de37859f0 | ||
|
|
993b878925 | ||
|
|
38acc7090b | ||
|
|
4ec79d5d18 | ||
|
|
1c68aae43e | ||
|
|
686af28f54 | ||
|
|
6725523042 | ||
|
|
aa8dbbf6b6 | ||
|
|
0e2ac2d802 | ||
|
|
68b453770b | ||
|
|
2a0be28111 | ||
|
|
f9f20957a4 | ||
|
|
d93ccd47a8 | ||
|
|
e152b8850c | ||
|
|
5bb2c2c5c9 | ||
|
|
816b10d8f3 | ||
|
|
b7a40f3097 | ||
|
|
2515425cd5 | ||
|
|
a0c39c64cc | ||
|
|
114801d412 | ||
|
|
2be368bded | ||
|
|
f5d79677fa | ||
|
|
5f95fea3e2 | ||
|
|
c0b87c1a62 | ||
|
|
054c55a9bb | ||
|
|
23b92ef9ec | ||
|
|
d5f5cdb45a | ||
|
|
33978455b8 | ||
|
|
2bd167663d | ||
|
|
bda5bb4a74 | ||
|
|
67edcc8f91 | ||
|
|
73f6162f5c | ||
|
|
fe9e026f9e | ||
|
|
3230927f10 | ||
|
|
f460d81dd0 | ||
|
|
610a503188 | ||
|
|
a9e22801e9 | ||
|
|
ee1f69062e | ||
|
|
20e9a87158 | ||
|
|
a4e04e6083 | ||
|
|
63294892f0 | ||
|
|
be67dca686 | ||
|
|
b1eefbdcd9 | ||
|
|
fed77d1837 | ||
|
|
b46fc8bc4c | ||
|
|
b4c48664f8 | ||
|
|
b6958e5221 | ||
|
|
f02affbc18 | ||
|
|
46c6233b62 | ||
|
|
d6144d63fb | ||
|
|
c4049cb393 | ||
|
|
eaac67ac60 | ||
|
|
9c7bb0b370 | ||
|
|
24ae9b0ea9 | ||
|
|
2d11b1d9eb | ||
|
|
e3dde12c45 | ||
|
|
681a772f5f | ||
|
|
5839d7dcd5 | ||
|
|
a06392459e | ||
|
|
fd11b7e7db | ||
|
|
bb42c85df8 | ||
|
|
bb0ac688b2 | ||
|
|
7de97a55f7 | ||
|
|
b25c8ca621 | ||
|
|
db46e9c203 | ||
|
|
ebfc127628 | ||
|
|
070772b4b9 | ||
|
|
d9ad51e989 | ||
|
|
fce641aab6 | ||
|
|
a21e095a59 | ||
|
|
a67b29d8d2 | ||
|
|
795ac86266 | ||
|
|
8a744255fa | ||
|
|
a3b8e81c21 | ||
|
|
4bfa03e5f4 | ||
|
|
3f0d598a59 | ||
|
|
1235907835 | ||
|
|
9a0372b61b | ||
|
|
6f45678e9c | ||
|
|
0ea80f674b | ||
|
|
316e6850ae | ||
|
|
8386baf267 | ||
|
|
a734326907 | ||
|
|
2b547bd44a | ||
|
|
a1a17b7ee8 | ||
|
|
d00490271b | ||
|
|
fee56df400 | ||
|
|
d2b48b2aa7 | ||
|
|
467870deb6 | ||
|
|
6fcc197db8 | ||
|
|
f3c7965cea | ||
|
|
8ff30a2abc | ||
|
|
bb1e4c2208 | ||
|
|
820c72af55 | ||
|
|
a63193c826 | ||
|
|
3a3a95b0a9 | ||
|
|
367d12402a | ||
|
|
49f995925c | ||
|
|
bdfc19ad20 | ||
|
|
1b3b35926a | ||
|
|
23268531ae | ||
|
|
f47ae3c02f | ||
|
|
9c6ab6f1e0 | ||
|
|
331bc42d57 | ||
|
|
39bb670719 | ||
|
|
537ead8917 | ||
|
|
96b2705bd3 | ||
|
|
6753fcc1b4 | ||
|
|
593a79ce20 | ||
|
|
d4c954870a | ||
|
|
59d6e7d6ef | ||
|
|
2b04af4349 | ||
|
|
fe7462b352 | ||
|
|
c65cfadd09 | ||
|
|
34658473c9 | ||
|
|
f610e332b3 | ||
|
|
67324ce732 | ||
|
|
9e1da8f097 | ||
|
|
361b9cad0f | ||
|
|
f63532fa95 | ||
|
|
4a47deafc2 | ||
|
|
cad26fa606 | ||
|
|
078c7bf8ab | ||
|
|
a05e98f463 | ||
|
|
f64dc5f57d | ||
|
|
1db72f8010 | ||
|
|
060d06d396 | ||
|
|
a737e15ddb | ||
|
|
e45e246027 | ||
|
|
45739ce434 | ||
|
|
777ff450cf | ||
|
|
85800256de | ||
|
|
4b18317e7c | ||
|
|
54a7eefa28 | ||
|
|
bd2c13527d | ||
|
|
daffb4881e | ||
|
|
cd30308711 | ||
|
|
632c18ab37 | ||
|
|
2a6fcf48e5 | ||
|
|
d5f4a32435 | ||
|
|
d3c6075841 | ||
|
|
1c37731065 | ||
|
|
9b373f2e15 | ||
|
|
4d011057b0 | ||
|
|
de37de1785 | ||
|
|
1520b2271a | ||
|
|
793527f82e | ||
|
|
db1c29f2f9 | ||
|
|
d48a61fdff | ||
|
|
c4859c3dc6 | ||
|
|
cc6ba0fd10 | ||
|
|
8ce3ab1e26 | ||
|
|
68f48c9456 | ||
|
|
aa03a9d0ef | ||
|
|
0d77fd4a2c | ||
|
|
35815387ab | ||
|
|
a8cd435e30 | ||
|
|
0446f07884 | ||
|
|
12569f2c9d | ||
|
|
9c9759a683 | ||
|
|
25156dbd53 | ||
|
|
1e894df102 | ||
|
|
b13a2fe260 | ||
|
|
651264d098 | ||
|
|
5f42429af1 | ||
|
|
233961ea29 | ||
|
|
1f248e6ea6 | ||
|
|
f81f4479b6 | ||
|
|
2610aa60e9 | ||
|
|
7bf17f2541 | ||
|
|
a252b9b570 | ||
|
|
31028ab636 | ||
|
|
54d7c580bd | ||
|
|
8a9395101e | ||
|
|
12adaa0570 | ||
|
|
e63c3c727a | ||
|
|
709661156a | ||
|
|
b3ac48cf52 | ||
|
|
3f42909ecf | ||
|
|
04517caf36 | ||
|
|
5e5313d8b1 | ||
|
|
42041cd402 | ||
|
|
f5bed87199 | ||
|
|
52db43eee5 | ||
|
|
d8679b3899 | ||
|
|
3d3fc18a3a | ||
|
|
7fece7e9b3 | ||
|
|
57f322a818 | ||
|
|
28635e5f2c | ||
|
|
723acfa1a1 | ||
|
|
01ede11cb8 | ||
|
|
c02a49a1db | ||
|
|
baf44c7a41 | ||
|
|
7810f4293f | ||
|
|
ee0cac7d54 | ||
|
|
407bef5727 | ||
|
|
3e3e593366 | ||
|
|
ccef805e9b | ||
|
|
175449f096 | ||
|
|
2346caf6fb | ||
|
|
73518cdc8d | ||
|
|
959c08a1ec | ||
|
|
0ba86b9716 | ||
|
|
18e7825ff3 | ||
|
|
afacca252e | ||
|
|
61a9316f67 | ||
|
|
e47a815c38 | ||
|
|
25ac6f0f37 | ||
|
|
5b4f29e7ed | ||
|
|
aaca93046c | ||
|
|
bce11c8913 | ||
|
|
44260634af | ||
|
|
7ca09de386 | ||
|
|
55642d257d | ||
|
|
81ffde3c2a | ||
|
|
95d8716ffa | ||
|
|
fded8d80b1 | ||
|
|
2b406ccaf7 | ||
|
|
f58bab70c5 | ||
|
|
b8e8e4c930 | ||
|
|
2aff0c47d0 | ||
|
|
63578f9d2b | ||
|
|
40a0a6aa8e | ||
|
|
d035fc2816 | ||
|
|
3c4043fd39 | ||
|
|
66bb6a8534 | ||
|
|
ed1966ac76 | ||
|
|
367a3524b9 | ||
|
|
1232a285e6 | ||
|
|
f3f6fa958e | ||
|
|
08e5c1f6fe | ||
|
|
e244d0db0c | ||
|
|
7c7e6ffc77 | ||
|
|
18f31d7db9 | ||
|
|
a141d6b3d4 | ||
|
|
2c6e5d0464 | ||
|
|
17603d5dfb | ||
|
|
09b658b50a | ||
|
|
f63d8b4d5e | ||
|
|
ef290ffcf2 | ||
|
|
efd25efaf4 | ||
|
|
a69341f551 | ||
|
|
940c325e7f | ||
|
|
adf89a1e0e | ||
|
|
d76f6fe8e0 | ||
|
|
440eccb7ee | ||
|
|
e71eeda73c | ||
|
|
2677dc6844 | ||
|
|
f36e2841bf | ||
|
|
91c96559fa | ||
|
|
03dd94d2b2 | ||
|
|
a2b0e30714 | ||
|
|
3adcaa7681 | ||
|
|
c09ff40916 | ||
|
|
9d6344704e | ||
|
|
042825e8fb | ||
|
|
9609b36b3c | ||
|
|
da6ebac742 | ||
|
|
bad4816976 | ||
|
|
674af4211c | ||
|
|
42a8674cea | ||
|
|
8cacd0b931 | ||
|
|
6bc48ba123 | ||
|
|
a4d21cadfa | ||
|
|
174a492cdb | ||
|
|
704bd4d191 | ||
|
|
3e399d09d7 | ||
|
|
c94f1fc857 | ||
|
|
cead84d5d1 | ||
|
|
4828835998 | ||
|
|
55d4db1387 | ||
|
|
dbb4e21684 | ||
|
|
6d2ad5ae58 | ||
|
|
5a8bebc2f8 | ||
|
|
fd30ed0edd | ||
|
|
a8e6e24e58 | ||
|
|
03482a4427 | ||
|
|
16594d6ed0 | ||
|
|
38e8208639 | ||
|
|
f8fd5dc2a3 | ||
|
|
3ab14e14e9 | ||
|
|
7da4c3acf7 | ||
|
|
6617592224 | ||
|
|
c842ca1f12 | ||
|
|
3af20729bd | ||
|
|
157a290e38 | ||
|
|
664f95a7b4 | ||
|
|
a8ae14e94f | ||
|
|
d5bdb17144 | ||
|
|
756aeffe03 | ||
|
|
1d0179b192 | ||
|
|
5911c45b54 | ||
|
|
702455674b | ||
|
|
fa734d7824 | ||
|
|
18631df88b | ||
|
|
d0d336eee7 | ||
|
|
252b12be13 | ||
|
|
027b5345f8 | ||
|
|
bf03be3541 | ||
|
|
45ce16b73f | ||
|
|
fa4ad9d95f | ||
|
|
acd5d40ab0 | ||
|
|
f482ea4902 | ||
|
|
b74dd43ff5 | ||
|
|
312182e0bd | ||
|
|
69687c92e9 | ||
|
|
2e96cab6aa | ||
|
|
8df3856c8f | ||
|
|
2b5cbe825a | ||
|
|
55950281e8 | ||
|
|
6c8d9a5ccf | ||
|
|
e9aa24e340 | ||
|
|
48c6692311 | ||
|
|
00261a5571 | ||
|
|
adfa4844d1 | ||
|
|
6252511b7f | ||
|
|
5714ae0b73 | ||
|
|
8bd07af5e5 | ||
|
|
b9e2806042 | ||
|
|
a0792237a0 | ||
|
|
ff6bf92ee4 | ||
|
|
5b8b167cbb | ||
|
|
86ed7ca725 | ||
|
|
77d005c5c8 | ||
|
|
47de3f3f24 | ||
|
|
bc196c016b | ||
|
|
ffcf609de1 | ||
|
|
4b67ff9534 | ||
|
|
808b02edda | ||
|
|
50d69fd9bb | ||
|
|
eaa60e9c17 | ||
|
|
12d311fd29 | ||
|
|
65cf85808f | ||
|
|
f1f91828ba | ||
|
|
f624800881 | ||
|
|
2819af9586 | ||
|
|
fabd897d49 | ||
|
|
c69971c381 | ||
|
|
b2d44a94ce | ||
|
|
aadb131bc7 | ||
|
|
683f9745ad | ||
|
|
1a3c01efca | ||
|
|
ce2ea963b9 | ||
|
|
9341f9a6bc | ||
|
|
035c1dd5a1 | ||
|
|
045e42a10c | ||
|
|
a575192c5f | ||
|
|
7d68ca21c8 | ||
|
|
159fb857f4 | ||
|
|
69f93a7528 | ||
|
|
ff5fb512b8 | ||
|
|
b575cd0ef9 | ||
|
|
9d2cc4f2cc | ||
|
|
6c282775a9 | ||
|
|
45eada306f | ||
|
|
d8086b6532 | ||
|
|
e450d1586e | ||
|
|
d2ec311c55 | ||
|
|
db26dcaf4c | ||
|
|
745253a369 | ||
|
|
7fdff522d6 | ||
|
|
e16154889a | ||
|
|
ea2f170b7d | ||
|
|
d471952adf | ||
|
|
457c7f55e6 | ||
|
|
04c3e083fb | ||
|
|
1d629640bf | ||
|
|
066c189249 | ||
|
|
0f539adab9 | ||
|
|
07721c28b6 | ||
|
|
61e0219e91 | ||
|
|
f9efdc4435 | ||
|
|
f7556de9fb | ||
|
|
0aa0efa439 | ||
|
|
2a278ceb8f | ||
|
|
0c9174bc7c | ||
|
|
e22cb0ca9f | ||
|
|
6a643ec3c8 | ||
|
|
7a370ccd0f | ||
|
|
f32bf08eb3 | ||
|
|
85e13333c3 |
2
ISSUE_TEMPLATE.md
Normal file
2
ISSUE_TEMPLATE.md
Normal file
@@ -0,0 +1,2 @@
|
||||
* Electron version:
|
||||
* Operating system:
|
||||
@@ -57,6 +57,7 @@ API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝
|
||||
- [중국어 번체](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||
- [우크라이나어](https://github.com/atom/electron/tree/master/docs-translations/uk-UA)
|
||||
- [러시아어](https://github.com/atom/electron/tree/master/docs-translations/ru-RU)
|
||||
- [프랑스어](https://github.com/atom/electron/tree/master/docs-translations/fr-FR)
|
||||
|
||||
## 시작하기
|
||||
|
||||
@@ -70,8 +71,9 @@ API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝
|
||||
- Atom 포럼의 [`electron`](http://discuss.atom.io/c/electron) 카테고리
|
||||
- Freenode 채팅의 `#atom-shell` 채널
|
||||
- Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널
|
||||
- [`electron-br`](https://electron-br.slack.com) *(브라질 포르투갈어)* 커뮤니티
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(한국어)* 커뮤니티
|
||||
- [`electron-br`](https://electron-br.slack.com) *(브라질)* 커뮤니티
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(한국)* 커뮤니티
|
||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(일본)* 커뮤니티
|
||||
|
||||
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에
|
||||
커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 한번 참고해 보시기
|
||||
|
||||
@@ -54,6 +54,7 @@ contains documents describing how to build and contribute to Electron.
|
||||
- [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||
- [Ukrainian](https://github.com/atom/electron/tree/master/docs-translations/uk-UA)
|
||||
- [Russian](https://github.com/atom/electron/tree/master/docs-translations/ru-RU)
|
||||
- [French](https://github.com/atom/electron/tree/master/docs-translations/fr-FR)
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -70,6 +71,7 @@ forums
|
||||
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(Japanese)*
|
||||
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
for a community maintained list of useful example apps, tools and resources.
|
||||
|
||||
11
atom.gyp
11
atom.gyp
@@ -4,7 +4,7 @@
|
||||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '0.36.7',
|
||||
'version%': '0.36.12',
|
||||
},
|
||||
'includes': [
|
||||
'filenames.gypi',
|
||||
@@ -69,7 +69,7 @@
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/<(product_name).app/Contents/Resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
'default_app',
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -144,6 +144,7 @@
|
||||
}, {
|
||||
'copied_libraries': [
|
||||
'<(libchromiumcontent_dir)/pdf.dll',
|
||||
'<(libchromiumcontent_dir)/ffmpeg.dll',
|
||||
],
|
||||
}],
|
||||
],
|
||||
@@ -170,7 +171,7 @@
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
'default_app',
|
||||
]
|
||||
},
|
||||
],
|
||||
@@ -193,6 +194,7 @@
|
||||
}, {
|
||||
'copied_libraries': [
|
||||
'<(PRODUCT_DIR)/lib/libnode.so',
|
||||
'<(libchromiumcontent_dir)/libffmpeg.so',
|
||||
],
|
||||
}],
|
||||
],
|
||||
@@ -210,7 +212,7 @@
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
'default_app',
|
||||
]
|
||||
},
|
||||
],
|
||||
@@ -461,6 +463,7 @@
|
||||
}, {
|
||||
'copied_libraries': [
|
||||
'<(PRODUCT_DIR)/libnode.dylib',
|
||||
'<(libchromiumcontent_dir)/libffmpeg.dylib',
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
||||
@@ -132,19 +132,20 @@ void OnClientCertificateSelected(
|
||||
std::shared_ptr<content::ClientCertificateDelegate> delegate,
|
||||
mate::Arguments* args) {
|
||||
mate::Dictionary cert_data;
|
||||
if (!(args->Length() == 1 && args->GetNext(&cert_data))) {
|
||||
if (!args->GetNext(&cert_data)) {
|
||||
args->ThrowError();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string encoded_data;
|
||||
cert_data.Get("data", &encoded_data);
|
||||
v8::Local<v8::Object> data;
|
||||
if (!cert_data.Get("data", &data))
|
||||
return;
|
||||
|
||||
auto certs =
|
||||
net::X509Certificate::CreateCertificateListFromBytes(
|
||||
encoded_data.data(), encoded_data.size(),
|
||||
net::X509Certificate::FORMAT_AUTO);
|
||||
delegate->ContinueWithCertificate(certs[0].get());
|
||||
auto certs = net::X509Certificate::CreateCertificateListFromBytes(
|
||||
node::Buffer::Data(data), node::Buffer::Length(data),
|
||||
net::X509Certificate::FORMAT_AUTO);
|
||||
if (certs.size() > 0)
|
||||
delegate->ContinueWithCertificate(certs[0].get());
|
||||
}
|
||||
|
||||
void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
|
||||
@@ -282,6 +283,12 @@ void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
|
||||
Emit("gpu-process-crashed");
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void App::OnPlatformThemeChanged() {
|
||||
Emit("platform-theme-changed");
|
||||
}
|
||||
#endif
|
||||
|
||||
base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
|
||||
bool succeed = false;
|
||||
base::FilePath path;
|
||||
@@ -367,6 +374,12 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
|
||||
base::Bind(&Browser::ClearRecentDocuments, browser))
|
||||
.SetMethod("setAppUserModelId",
|
||||
base::Bind(&Browser::SetAppUserModelID, browser))
|
||||
#if defined(OS_MACOSX)
|
||||
.SetMethod("hide", base::Bind(&Browser::Hide, browser))
|
||||
.SetMethod("show", base::Bind(&Browser::Show, browser))
|
||||
.SetMethod("isDarkMode",
|
||||
base::Bind(&Browser::IsDarkMode, browser))
|
||||
#endif
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("setUserTasks",
|
||||
base::Bind(&Browser::SetUserTasks, browser))
|
||||
|
||||
@@ -71,6 +71,10 @@ class App : public AtomBrowserClient::Delegate,
|
||||
// content::GpuDataManagerObserver:
|
||||
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void OnPlatformThemeChanged() override;
|
||||
#endif
|
||||
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/memory/linked_ptr.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "net/base/filename_util.h"
|
||||
@@ -47,80 +48,49 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
// The wrapDownloadItem funtion which is implemented in JavaScript
|
||||
using WrapDownloadItemCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
WrapDownloadItemCallback g_wrap_download_item;
|
||||
|
||||
char kDownloadItemSavePathKey[] = "DownloadItemSavePathKey";
|
||||
|
||||
std::map<uint32, linked_ptr<v8::Global<v8::Value>>> g_download_item_objects;
|
||||
|
||||
} // namespace
|
||||
|
||||
DownloadItem::SavePathData::SavePathData(const base::FilePath& path) :
|
||||
path_(path) {
|
||||
}
|
||||
|
||||
const base::FilePath& DownloadItem::SavePathData::path() {
|
||||
return path_;
|
||||
}
|
||||
|
||||
DownloadItem::DownloadItem(content::DownloadItem* download_item) :
|
||||
download_item_(download_item) {
|
||||
DownloadItem::DownloadItem(content::DownloadItem* download_item)
|
||||
: download_item_(download_item) {
|
||||
download_item_->AddObserver(this);
|
||||
AttachAsUserData(download_item);
|
||||
}
|
||||
|
||||
DownloadItem::~DownloadItem() {
|
||||
if (download_item_)
|
||||
OnDownloadDestroyed(download_item_);
|
||||
if (download_item_) {
|
||||
// Destroyed by either garbage collection or destroy().
|
||||
download_item_->RemoveObserver(this);
|
||||
download_item_->Remove();
|
||||
}
|
||||
|
||||
// Remove from the global map.
|
||||
auto iter = g_download_item_objects.find(weak_map_id());
|
||||
if (iter != g_download_item_objects.end())
|
||||
g_download_item_objects.erase(iter);
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
|
||||
download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated");
|
||||
if (download_item_->IsDone()) {
|
||||
Emit("done", item->GetState());
|
||||
|
||||
// Destroy the item once item is downloaded.
|
||||
base::MessageLoop::current()->PostTask(FROM_HERE, GetDestroyClosure());
|
||||
} else {
|
||||
Emit("updated");
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) {
|
||||
download_item_->RemoveObserver(this);
|
||||
auto iter = g_download_item_objects.find(download_item_->GetId());
|
||||
if (iter != g_download_item_objects.end())
|
||||
g_download_item_objects.erase(iter);
|
||||
download_item_ = nullptr;
|
||||
}
|
||||
|
||||
int64 DownloadItem::GetReceivedBytes() {
|
||||
return download_item_->GetReceivedBytes();
|
||||
}
|
||||
|
||||
int64 DownloadItem::GetTotalBytes() {
|
||||
return download_item_->GetTotalBytes();
|
||||
}
|
||||
|
||||
const GURL& DownloadItem::GetURL() {
|
||||
return download_item_->GetURL();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetMimeType() {
|
||||
return download_item_->GetMimeType();
|
||||
}
|
||||
|
||||
bool DownloadItem::HasUserGesture() {
|
||||
return download_item_->HasUserGesture();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetFilename() {
|
||||
return base::UTF16ToUTF8(net::GenerateFileName(GetURL(),
|
||||
GetContentDisposition(),
|
||||
std::string(),
|
||||
download_item_->GetSuggestedFilename(),
|
||||
GetMimeType(),
|
||||
std::string()).LossyDisplayName());
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetContentDisposition() {
|
||||
return download_item_->GetContentDisposition();
|
||||
}
|
||||
|
||||
void DownloadItem::SetSavePath(const base::FilePath& path) {
|
||||
download_item_->SetUserData(UserDataKey(), new SavePathData(path));
|
||||
// Destroy the native class immediately when downloadItem is destroyed.
|
||||
delete this;
|
||||
}
|
||||
|
||||
void DownloadItem::Pause() {
|
||||
@@ -133,6 +103,48 @@ void DownloadItem::Resume() {
|
||||
|
||||
void DownloadItem::Cancel() {
|
||||
download_item_->Cancel(true);
|
||||
download_item_->Remove();
|
||||
}
|
||||
|
||||
int64 DownloadItem::GetReceivedBytes() const {
|
||||
return download_item_->GetReceivedBytes();
|
||||
}
|
||||
|
||||
int64 DownloadItem::GetTotalBytes() const {
|
||||
return download_item_->GetTotalBytes();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetMimeType() const {
|
||||
return download_item_->GetMimeType();
|
||||
}
|
||||
|
||||
bool DownloadItem::HasUserGesture() const {
|
||||
return download_item_->HasUserGesture();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetFilename() const {
|
||||
return base::UTF16ToUTF8(net::GenerateFileName(GetURL(),
|
||||
GetContentDisposition(),
|
||||
std::string(),
|
||||
download_item_->GetSuggestedFilename(),
|
||||
GetMimeType(),
|
||||
std::string()).LossyDisplayName());
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetContentDisposition() const {
|
||||
return download_item_->GetContentDisposition();
|
||||
}
|
||||
|
||||
const GURL& DownloadItem::GetURL() const {
|
||||
return download_item_->GetURL();
|
||||
}
|
||||
|
||||
void DownloadItem::SetSavePath(const base::FilePath& path) {
|
||||
save_path_ = path;
|
||||
}
|
||||
|
||||
base::FilePath DownloadItem::GetSavePath() const {
|
||||
return save_path_;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -145,29 +157,31 @@ void DownloadItem::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("cancel", &DownloadItem::Cancel)
|
||||
.SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes)
|
||||
.SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes)
|
||||
.SetMethod("getURL", &DownloadItem::GetURL)
|
||||
.SetMethod("getMimeType", &DownloadItem::GetMimeType)
|
||||
.SetMethod("hasUserGesture", &DownloadItem::HasUserGesture)
|
||||
.SetMethod("getFilename", &DownloadItem::GetFilename)
|
||||
.SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition)
|
||||
.SetMethod("setSavePath", &DownloadItem::SetSavePath);
|
||||
.SetMethod("getURL", &DownloadItem::GetURL)
|
||||
.SetMethod("setSavePath", &DownloadItem::SetSavePath)
|
||||
.SetMethod("getSavePath", &DownloadItem::GetSavePath);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<DownloadItem> DownloadItem::Create(
|
||||
v8::Isolate* isolate, content::DownloadItem* item) {
|
||||
auto existing = TrackableObject::FromWrappedClass(isolate, item);
|
||||
if (existing)
|
||||
return mate::CreateHandle(isolate, static_cast<DownloadItem*>(existing));
|
||||
|
||||
auto handle = mate::CreateHandle(isolate, new DownloadItem(item));
|
||||
g_wrap_download_item.Run(handle.ToV8());
|
||||
g_download_item_objects[item->GetId()] = make_linked_ptr(
|
||||
|
||||
// Reference this object in case it got garbage collected.
|
||||
g_download_item_objects[handle->weak_map_id()] = make_linked_ptr(
|
||||
new v8::Global<v8::Value>(isolate, handle.ToV8()));
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
void* DownloadItem::UserDataKey() {
|
||||
return &kDownloadItemSavePathKey;
|
||||
}
|
||||
|
||||
void ClearWrapDownloadItem() {
|
||||
g_wrap_download_item.Reset();
|
||||
}
|
||||
|
||||
@@ -20,22 +20,26 @@ namespace api {
|
||||
class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||
public content::DownloadItem::Observer {
|
||||
public:
|
||||
class SavePathData : public base::SupportsUserData::Data {
|
||||
public:
|
||||
explicit SavePathData(const base::FilePath& path);
|
||||
const base::FilePath& path();
|
||||
private:
|
||||
base::FilePath path_;
|
||||
};
|
||||
|
||||
static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
|
||||
content::DownloadItem* item);
|
||||
static void* UserDataKey();
|
||||
|
||||
// mate::TrackableObject:
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
void Pause();
|
||||
void Resume();
|
||||
void Cancel();
|
||||
int64 GetReceivedBytes() const;
|
||||
int64 GetTotalBytes() const;
|
||||
std::string GetMimeType() const;
|
||||
bool HasUserGesture() const;
|
||||
std::string GetFilename() const;
|
||||
std::string GetContentDisposition() const;
|
||||
const GURL& GetURL() const;
|
||||
void SetSavePath(const base::FilePath& path);
|
||||
base::FilePath GetSavePath() const;
|
||||
|
||||
protected:
|
||||
explicit DownloadItem(content::DownloadItem* download_item);
|
||||
~DownloadItem();
|
||||
@@ -44,19 +48,8 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||
void OnDownloadUpdated(content::DownloadItem* download) override;
|
||||
void OnDownloadDestroyed(content::DownloadItem* download) override;
|
||||
|
||||
void Pause();
|
||||
void Resume();
|
||||
void Cancel();
|
||||
int64 GetReceivedBytes();
|
||||
int64 GetTotalBytes();
|
||||
std::string GetMimeType();
|
||||
bool HasUserGesture();
|
||||
std::string GetFilename();
|
||||
std::string GetContentDisposition();
|
||||
const GURL& GetURL();
|
||||
void SetSavePath(const base::FilePath& path);
|
||||
|
||||
private:
|
||||
base::FilePath save_path_;
|
||||
content::DownloadItem* download_item_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DownloadItem);
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
#include "atom/browser/api/save_page_handler.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/atom_permission_manager.h"
|
||||
#include "atom/browser/net/atom_cert_verifier.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/content_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
@@ -34,6 +36,7 @@
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/base/load_flags.h"
|
||||
#include "net/disk_cache/disk_cache.h"
|
||||
#include "net/dns/host_cache.h"
|
||||
#include "net/proxy/proxy_service.h"
|
||||
#include "net/proxy/proxy_config_service_fixed.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
@@ -269,6 +272,19 @@ void SetProxyInIO(net::URLRequestContextGetter* getter,
|
||||
RunCallbackInUI(callback);
|
||||
}
|
||||
|
||||
void ClearHostResolverCacheInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
const base::Closure& callback) {
|
||||
auto request_context = context_getter->GetURLRequestContext();
|
||||
auto cache = request_context->host_resolver()->GetHostCache();
|
||||
if (cache) {
|
||||
cache->clear();
|
||||
DCHECK_EQ(0u, cache->size());
|
||||
if (!callback.is_null())
|
||||
RunCallbackInUI(callback);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Session::Session(AtomBrowserContext* browser_context)
|
||||
@@ -397,6 +413,28 @@ void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
|
||||
browser_context_->cert_verifier()->SetVerifyProc(proc);
|
||||
}
|
||||
|
||||
void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args) {
|
||||
AtomPermissionManager::RequestHandler handler;
|
||||
if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &handler))) {
|
||||
args->ThrowError("Must pass null or function");
|
||||
return;
|
||||
}
|
||||
auto permission_manager = static_cast<AtomPermissionManager*>(
|
||||
browser_context()->GetPermissionManager());
|
||||
permission_manager->SetPermissionRequestHandler(handler);
|
||||
}
|
||||
|
||||
void Session::ClearHostResolverCache(mate::Arguments* args) {
|
||||
base::Closure callback;
|
||||
args->GetNext(&callback);
|
||||
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&ClearHostResolverCacheInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
callback));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
|
||||
if (cookies_.IsEmpty()) {
|
||||
auto handle = atom::api::Cookies::Create(isolate, browser_context());
|
||||
@@ -448,6 +486,9 @@ void Session::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
|
||||
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
|
||||
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
|
||||
.SetMethod("setPermissionRequestHandler",
|
||||
&Session::SetPermissionRequestHandler)
|
||||
.SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
|
||||
.SetProperty("cookies", &Session::Cookies)
|
||||
.SetProperty("webRequest", &Session::WebRequest);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,9 @@ class Session: public mate::TrackableObject<Session>,
|
||||
void EnableNetworkEmulation(const mate::Dictionary& options);
|
||||
void DisableNetworkEmulation();
|
||||
void SetCertVerifyProc(v8::Local<v8::Value> proc, mate::Arguments* args);
|
||||
void SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args);
|
||||
void ClearHostResolverCache(mate::Arguments* args);
|
||||
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/web_contents_permission_helper.h"
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
#include "atom/browser/web_view_guest_delegate.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
@@ -27,6 +28,7 @@
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/mouse_util.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
@@ -216,7 +218,8 @@ WebContents::WebContents(content::WebContents* web_contents)
|
||||
|
||||
WebContents::WebContents(v8::Isolate* isolate,
|
||||
const mate::Dictionary& options)
|
||||
: request_id_(0) {
|
||||
: embedder_(nullptr),
|
||||
request_id_(0) {
|
||||
// Whether it is a guest WebContents.
|
||||
bool is_guest = false;
|
||||
options.Get("isGuest", &is_guest);
|
||||
@@ -262,16 +265,19 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
// Save the preferences in C++.
|
||||
new WebContentsPreferences(web_contents, options);
|
||||
|
||||
// Intialize permission helper.
|
||||
WebContentsPermissionHelper::CreateForWebContents(web_contents);
|
||||
|
||||
web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent());
|
||||
|
||||
if (is_guest) {
|
||||
guest_delegate_->Initialize(this);
|
||||
|
||||
NativeWindow* owner_window = nullptr;
|
||||
WebContents* embedder = nullptr;
|
||||
if (options.Get("embedder", &embedder) && embedder) {
|
||||
if (options.Get("embedder", &embedder_) && embedder_) {
|
||||
// New WebContents's owner_window is the embedder's owner_window.
|
||||
auto relay = NativeWindowRelay::FromWebContents(embedder->web_contents());
|
||||
auto relay =
|
||||
NativeWindowRelay::FromWebContents(embedder_->web_contents());
|
||||
if (relay)
|
||||
owner_window = relay->window.get();
|
||||
}
|
||||
@@ -291,6 +297,7 @@ WebContents::~WebContents() {
|
||||
// The WebContentsDestroyed will not be called automatically because we
|
||||
// unsubscribe from webContents before destroying it. So we have to manually
|
||||
// call it here to make sure "destroyed" event is emitted.
|
||||
RenderViewDeleted(web_contents()->GetRenderViewHost());
|
||||
WebContentsDestroyed();
|
||||
}
|
||||
}
|
||||
@@ -386,6 +393,18 @@ void WebContents::HandleKeyboardEvent(
|
||||
|
||||
void WebContents::EnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin) {
|
||||
auto permission_helper =
|
||||
WebContentsPermissionHelper::FromWebContents(source);
|
||||
auto callback = base::Bind(&WebContents::OnEnterFullscreenModeForTab,
|
||||
base::Unretained(this), source, origin);
|
||||
permission_helper->RequestFullscreenPermission(callback);
|
||||
}
|
||||
|
||||
void WebContents::OnEnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin,
|
||||
bool allowed) {
|
||||
if (!allowed)
|
||||
return;
|
||||
CommonWebContentsDelegate::EnterFullscreenModeForTab(source, origin);
|
||||
Emit("enter-html-full-screen");
|
||||
}
|
||||
@@ -444,23 +463,38 @@ void WebContents::FindReply(content::WebContents* web_contents,
|
||||
}
|
||||
}
|
||||
|
||||
bool WebContents::CheckMediaAccessPermission(
|
||||
content::WebContents* web_contents,
|
||||
const GURL& security_origin,
|
||||
content::MediaStreamType type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebContents::RequestMediaAccessPermission(
|
||||
content::WebContents* web_contents,
|
||||
const content::MediaStreamRequest& request,
|
||||
const content::MediaResponseCallback& callback) {
|
||||
auto permission_helper =
|
||||
WebContentsPermissionHelper::FromWebContents(web_contents);
|
||||
permission_helper->RequestMediaAccessPermission(request, callback);
|
||||
}
|
||||
|
||||
void WebContents::RequestToLockMouse(
|
||||
content::WebContents* web_contents,
|
||||
bool user_gesture,
|
||||
bool last_unlocked_by_target) {
|
||||
auto permission_helper =
|
||||
WebContentsPermissionHelper::FromWebContents(web_contents);
|
||||
permission_helper->RequestPointerLockPermission(user_gesture);
|
||||
}
|
||||
|
||||
void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
|
||||
// Do nothing, we override this method just to avoid compilation error since
|
||||
// there are two virtual functions named BeforeUnloadFired.
|
||||
}
|
||||
|
||||
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
|
||||
int process_id = render_view_host->GetProcess()->GetID();
|
||||
Emit("render-view-deleted", process_id);
|
||||
|
||||
// process.emit('ATOM_BROWSER_RELEASE_RENDER_VIEW', processId);
|
||||
// Tell the rpc server that a render view has been deleted and we need to
|
||||
// release all objects owned by it.
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
node::Environment* env = node::Environment::GetCurrent(isolate());
|
||||
mate::EmitEvent(isolate(), env->process_object(),
|
||||
"ATOM_BROWSER_RELEASE_RENDER_VIEW", process_id);
|
||||
Emit("render-view-deleted", render_view_host->GetProcess()->GetID());
|
||||
}
|
||||
|
||||
void WebContents::RenderProcessGone(base::TerminationStatus status) {
|
||||
@@ -619,6 +653,8 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) {
|
||||
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync,
|
||||
OnRendererMessageSync)
|
||||
IPC_MESSAGE_HANDLER_CODE(ViewHostMsg_SetCursor, OnCursorChange,
|
||||
handled = false)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
|
||||
@@ -638,9 +674,6 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) {
|
||||
// be destroyed on close, and WebContentsDestroyed would be called for it, so
|
||||
// we need to make sure the api::WebContents is also deleted.
|
||||
void WebContents::WebContentsDestroyed() {
|
||||
// The RenderViewDeleted was not called when the WebContents is destroyed.
|
||||
RenderViewDeleted(web_contents()->GetRenderViewHost());
|
||||
|
||||
// This event is only for internal use, which is emitted when WebContents is
|
||||
// being destroyed.
|
||||
Emit("will-destroy");
|
||||
@@ -673,6 +706,14 @@ bool WebContents::Equal(const WebContents* web_contents) const {
|
||||
}
|
||||
|
||||
void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
|
||||
if (!url.is_valid()) {
|
||||
Emit("did-fail-load",
|
||||
static_cast<int>(net::ERR_INVALID_URL),
|
||||
net::ErrorToShortString(net::ERR_INVALID_URL),
|
||||
url.possibly_invalid_spec());
|
||||
return;
|
||||
}
|
||||
|
||||
content::NavigationController::LoadURLParams params(url);
|
||||
|
||||
GURL http_referrer;
|
||||
@@ -1028,7 +1069,7 @@ void WebContents::BeginFrameSubscription(
|
||||
const auto view = web_contents()->GetRenderWidgetHostView();
|
||||
if (view) {
|
||||
scoped_ptr<FrameSubscriber> frame_subscriber(new FrameSubscriber(
|
||||
isolate(), view->GetVisibleViewportSize(), callback));
|
||||
isolate(), view, callback));
|
||||
view->BeginFrameSubscription(frame_subscriber.Pass());
|
||||
}
|
||||
}
|
||||
@@ -1039,6 +1080,19 @@ void WebContents::EndFrameSubscription() {
|
||||
view->EndFrameSubscription();
|
||||
}
|
||||
|
||||
void WebContents::OnCursorChange(const content::WebCursor& cursor) {
|
||||
content::WebCursor::CursorInfo info;
|
||||
cursor.GetCursorInfo(&info);
|
||||
|
||||
if (cursor.IsCustom()) {
|
||||
Emit("cursor-changed", CursorTypeToString(info),
|
||||
gfx::Image::CreateFrom1xBitmap(info.custom_image),
|
||||
info.image_scale_factor);
|
||||
} else {
|
||||
Emit("cursor-changed", CursorTypeToString(info));
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::SetSize(const SetSizeParams& params) {
|
||||
if (guest_delegate_)
|
||||
guest_delegate_->SetSize(params);
|
||||
@@ -1070,6 +1124,12 @@ v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
|
||||
return v8::Local<v8::Value>::New(isolate, session_);
|
||||
}
|
||||
|
||||
content::WebContents* WebContents::HostWebContents() {
|
||||
if (!embedder_)
|
||||
return nullptr;
|
||||
return embedder_->web_contents();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::DevToolsWebContents(v8::Isolate* isolate) {
|
||||
if (devtools_web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
@@ -1153,6 +1213,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
|
||||
.SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
|
||||
.SetProperty("session", &WebContents::Session)
|
||||
.SetProperty("hostWebContents", &WebContents::HostWebContents)
|
||||
.SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents)
|
||||
.SetProperty("debugger", &WebContents::Debugger);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "atom/browser/common_web_contents_delegate.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/common/favicon_url.h"
|
||||
#include "content/common/cursors/webcursor.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
@@ -133,6 +134,11 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void SetAllowTransparency(bool allow);
|
||||
bool IsGuest() const;
|
||||
|
||||
// Callback triggered on permission response.
|
||||
void OnEnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin,
|
||||
bool allowed);
|
||||
|
||||
// Returns the web preferences of current WebContents.
|
||||
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);
|
||||
|
||||
@@ -141,6 +147,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
|
||||
// Properties.
|
||||
v8::Local<v8::Value> Session(v8::Isolate* isolate);
|
||||
content::WebContents* HostWebContents();
|
||||
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> Debugger(v8::Isolate* isolate);
|
||||
|
||||
@@ -195,6 +202,18 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
const gfx::Rect& selection_rect,
|
||||
int active_match_ordinal,
|
||||
bool final_update) override;
|
||||
bool CheckMediaAccessPermission(
|
||||
content::WebContents* web_contents,
|
||||
const GURL& security_origin,
|
||||
content::MediaStreamType type) override;
|
||||
void RequestMediaAccessPermission(
|
||||
content::WebContents* web_contents,
|
||||
const content::MediaStreamRequest& request,
|
||||
const content::MediaResponseCallback& callback) override;
|
||||
void RequestToLockMouse(
|
||||
content::WebContents* web_contents,
|
||||
bool user_gesture,
|
||||
bool last_unlocked_by_target) override;
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
|
||||
@@ -255,6 +274,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
return ++request_id_;
|
||||
}
|
||||
|
||||
// Called when we receive a CursorChange message from chromium.
|
||||
void OnCursorChange(const content::WebCursor& cursor);
|
||||
|
||||
// Called when received a message from renderer.
|
||||
void OnRendererMessage(const base::string16& channel,
|
||||
const base::ListValue& args);
|
||||
@@ -270,6 +292,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
|
||||
scoped_ptr<WebViewGuestDelegate> guest_delegate_;
|
||||
|
||||
// The host webcontents that may contain this webcontents.
|
||||
WebContents* embedder_;
|
||||
|
||||
// The type of current WebContents.
|
||||
Type type_;
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ void TranslateOldOptions(v8::Isolate* isolate, v8::Local<v8::Object> options) {
|
||||
|
||||
// Converts binary data to Buffer.
|
||||
v8::Local<v8::Value> ToBuffer(v8::Isolate* isolate, void* val, int size) {
|
||||
auto buffer = node::Buffer::New(isolate, static_cast<char*>(val), size);
|
||||
auto buffer = node::Buffer::Copy(isolate, static_cast<char*>(val), size);
|
||||
if (buffer.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
else
|
||||
@@ -191,6 +191,14 @@ void Window::OnWindowFocus() {
|
||||
Emit("focus");
|
||||
}
|
||||
|
||||
void Window::OnWindowShow() {
|
||||
Emit("show");
|
||||
}
|
||||
|
||||
void Window::OnWindowHide() {
|
||||
Emit("hide");
|
||||
}
|
||||
|
||||
void Window::OnWindowMaximize() {
|
||||
Emit("maximize");
|
||||
}
|
||||
@@ -294,6 +302,10 @@ void Window::Focus() {
|
||||
window_->Focus(true);
|
||||
}
|
||||
|
||||
void Window::Blur() {
|
||||
window_->Focus(false);
|
||||
}
|
||||
|
||||
bool Window::IsFocused() {
|
||||
return window_->IsFocused();
|
||||
}
|
||||
@@ -688,6 +700,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.MakeDestroyable()
|
||||
.SetMethod("close", &Window::Close)
|
||||
.SetMethod("focus", &Window::Focus)
|
||||
.SetMethod("blur", &Window::Blur)
|
||||
.SetMethod("isFocused", &Window::IsFocused)
|
||||
.SetMethod("show", &Window::Show)
|
||||
.SetMethod("showInactive", &Window::ShowInactive)
|
||||
|
||||
@@ -58,6 +58,8 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void OnWindowClosed() override;
|
||||
void OnWindowBlur() override;
|
||||
void OnWindowFocus() override;
|
||||
void OnWindowShow() override;
|
||||
void OnWindowHide() override;
|
||||
void OnWindowMaximize() override;
|
||||
void OnWindowUnmaximize() override;
|
||||
void OnWindowMinimize() override;
|
||||
@@ -83,6 +85,7 @@ class Window : public mate::TrackableObject<Window>,
|
||||
// APIs for NativeWindow.
|
||||
void Close();
|
||||
void Focus();
|
||||
void Blur();
|
||||
bool IsFocused();
|
||||
void Show();
|
||||
void ShowInactive();
|
||||
|
||||
@@ -4,19 +4,18 @@
|
||||
|
||||
#include "atom/browser/api/frame_subscriber.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/bind.h"
|
||||
#include "media/base/video_frame.h"
|
||||
#include "media/base/yuv_convert.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "content/public/browser/render_widget_host.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
FrameSubscriber::FrameSubscriber(v8::Isolate* isolate,
|
||||
const gfx::Size& size,
|
||||
content::RenderWidgetHostView* view,
|
||||
const FrameCaptureCallback& callback)
|
||||
: isolate_(isolate), size_(size), callback_(callback) {
|
||||
: isolate_(isolate), view_(view), callback_(callback), weak_factory_(this) {
|
||||
}
|
||||
|
||||
bool FrameSubscriber::ShouldCaptureFrame(
|
||||
@@ -24,39 +23,39 @@ bool FrameSubscriber::ShouldCaptureFrame(
|
||||
base::TimeTicks present_time,
|
||||
scoped_refptr<media::VideoFrame>* storage,
|
||||
DeliverFrameCallback* callback) {
|
||||
*storage = media::VideoFrame::CreateFrame(
|
||||
media::PIXEL_FORMAT_YV12,
|
||||
size_, gfx::Rect(size_), size_, base::TimeDelta());
|
||||
*callback = base::Bind(&FrameSubscriber::OnFrameDelivered,
|
||||
base::Unretained(this), *storage);
|
||||
return true;
|
||||
const auto host = view_ ? view_->GetRenderWidgetHost() : nullptr;
|
||||
if (!view_ || !host)
|
||||
return false;
|
||||
|
||||
const auto size = view_->GetVisibleViewportSize();
|
||||
|
||||
host->CopyFromBackingStore(
|
||||
gfx::Rect(size),
|
||||
size,
|
||||
base::Bind(&FrameSubscriber::OnFrameDelivered,
|
||||
weak_factory_.GetWeakPtr(), callback_),
|
||||
kBGRA_8888_SkColorType);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FrameSubscriber::OnFrameDelivered(
|
||||
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool result) {
|
||||
if (!result)
|
||||
void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
|
||||
const SkBitmap& bitmap, content::ReadbackResponse response) {
|
||||
if (bitmap.computeSize64() == 0)
|
||||
return;
|
||||
|
||||
v8::Locker locker(isolate_);
|
||||
v8::HandleScope handle_scope(isolate_);
|
||||
|
||||
gfx::Rect rect = frame->visible_rect();
|
||||
size_t rgb_arr_size = rect.width() * rect.height() * 4;
|
||||
size_t rgb_arr_size = bitmap.width() * bitmap.height() *
|
||||
bitmap.bytesPerPixel();
|
||||
v8::MaybeLocal<v8::Object> buffer = node::Buffer::New(isolate_, rgb_arr_size);
|
||||
if (buffer.IsEmpty())
|
||||
return;
|
||||
|
||||
// Convert a frame of YUV to 32 bit ARGB.
|
||||
media::ConvertYUVToRGB32(frame->data(media::VideoFrame::kYPlane),
|
||||
frame->data(media::VideoFrame::kUPlane),
|
||||
frame->data(media::VideoFrame::kVPlane),
|
||||
reinterpret_cast<uint8*>(
|
||||
node::Buffer::Data(buffer.ToLocalChecked())),
|
||||
rect.width(), rect.height(),
|
||||
frame->stride(media::VideoFrame::kYPlane),
|
||||
frame->stride(media::VideoFrame::kUVPlane),
|
||||
rect.width() * 4,
|
||||
media::YV12);
|
||||
bitmap.copyPixelsTo(
|
||||
reinterpret_cast<uint8*>(node::Buffer::Data(buffer.ToLocalChecked())),
|
||||
rgb_arr_size);
|
||||
|
||||
callback_.Run(buffer.ToLocalChecked());
|
||||
}
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
#define ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
|
||||
#include "content/public/browser/readback_types.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
@@ -19,7 +23,7 @@ class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
|
||||
using FrameCaptureCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
|
||||
FrameSubscriber(v8::Isolate* isolate,
|
||||
const gfx::Size& size,
|
||||
content::RenderWidgetHostView* view,
|
||||
const FrameCaptureCallback& callback);
|
||||
|
||||
bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
|
||||
@@ -28,13 +32,15 @@ class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
|
||||
DeliverFrameCallback* callback) override;
|
||||
|
||||
private:
|
||||
void OnFrameDelivered(
|
||||
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool);
|
||||
void OnFrameDelivered(const FrameCaptureCallback& callback,
|
||||
const SkBitmap& bitmap, content::ReadbackResponse response);
|
||||
|
||||
v8::Isolate* isolate_;
|
||||
gfx::Size size_;
|
||||
content::RenderWidgetHostView* view_;
|
||||
FrameCaptureCallback callback_;
|
||||
|
||||
base::WeakPtrFactory<FrameSubscriber> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FrameSubscriber);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const app = require('electron').app;
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const squirrelUpdate = require('./squirrel-update-win');
|
||||
|
||||
class AutoUpdater extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
quitAndInstall() {
|
||||
squirrelUpdate.processStart();
|
||||
return app.quit();
|
||||
}
|
||||
|
||||
setFeedURL(updateURL) {
|
||||
return this.updateURL = updateURL;
|
||||
}
|
||||
|
||||
checkForUpdates() {
|
||||
if (!this.updateURL) {
|
||||
return this.emitError('Update URL is not set');
|
||||
}
|
||||
if (!squirrelUpdate.supported()) {
|
||||
return this.emitError('Can not find Squirrel');
|
||||
}
|
||||
this.emit('checking-for-update');
|
||||
return squirrelUpdate.download(this.updateURL, (function(_this) {
|
||||
return function(error, update) {
|
||||
if (error != null) {
|
||||
return _this.emitError(error);
|
||||
}
|
||||
if (update == null) {
|
||||
return _this.emit('update-not-available');
|
||||
}
|
||||
_this.emit('update-available');
|
||||
return squirrelUpdate.update(_this.updateURL, function(error) {
|
||||
var date, releaseNotes, version;
|
||||
if (error != null) {
|
||||
return _this.emitError(error);
|
||||
}
|
||||
releaseNotes = update.releaseNotes, version = update.version;
|
||||
|
||||
// Following information is not available on Windows, so fake them.
|
||||
date = new Date;
|
||||
return _this.emit('update-downloaded', {}, releaseNotes, version, date, _this.updateURL, function() {
|
||||
return _this.quitAndInstall();
|
||||
});
|
||||
});
|
||||
};
|
||||
})(this));
|
||||
}
|
||||
|
||||
// Private: Emit both error object and message, this is to keep compatibility
|
||||
// with Old APIs.
|
||||
emitError(message) {
|
||||
return this.emit('error', new Error(message), message);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new AutoUpdater;
|
||||
@@ -15,6 +15,7 @@
|
||||
#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_contents_permission_helper.h"
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
@@ -281,6 +282,24 @@ brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
|
||||
return new AtomBrowserMainParts;
|
||||
}
|
||||
|
||||
void AtomBrowserClient::WebNotificationAllowed(
|
||||
int render_process_id,
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
content::WebContents* web_contents = content::WebContents::FromRenderViewHost(
|
||||
content::RenderViewHost::FromID(render_process_id, kDefaultRoutingID));
|
||||
if (!web_contents) {
|
||||
callback.Run(false);
|
||||
return;
|
||||
}
|
||||
auto permission_helper =
|
||||
WebContentsPermissionHelper::FromWebContents(web_contents);
|
||||
if (!permission_helper) {
|
||||
callback.Run(false);
|
||||
return;
|
||||
}
|
||||
permission_helper->RequestWebNotificationPermission(callback);
|
||||
}
|
||||
|
||||
void AtomBrowserClient::RenderProcessHostDestroyed(
|
||||
content::RenderProcessHost* host) {
|
||||
int process_id = host->GetID();
|
||||
|
||||
@@ -81,6 +81,9 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||
// brightray::BrowserClient:
|
||||
brightray::BrowserMainParts* OverrideCreateBrowserMainParts(
|
||||
const content::MainFunctionParams&) override;
|
||||
void WebNotificationAllowed(
|
||||
int render_process_id,
|
||||
const base::Callback<void(bool)>& callback) override;
|
||||
|
||||
// content::RenderProcessHostObserver:
|
||||
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "atom/browser/net/atom_url_request_job_factory.h"
|
||||
#include "atom/browser/net/asar/asar_protocol_handler.h"
|
||||
#include "atom/browser/net/http_protocol_handler.h"
|
||||
#include "atom/browser/atom_permission_manager.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/common/atom_version.h"
|
||||
#include "atom/common/chrome_version.h"
|
||||
@@ -169,6 +170,12 @@ content::BrowserPluginGuestManager* AtomBrowserContext::GetGuestManager() {
|
||||
return guest_manager_.get();
|
||||
}
|
||||
|
||||
content::PermissionManager* AtomBrowserContext::GetPermissionManager() {
|
||||
if (!permission_manager_.get())
|
||||
permission_manager_.reset(new AtomPermissionManager);
|
||||
return permission_manager_.get();
|
||||
}
|
||||
|
||||
scoped_ptr<net::CertVerifier> AtomBrowserContext::CreateCertVerifier() {
|
||||
DCHECK(!cert_verifier_);
|
||||
cert_verifier_ = new AtomCertVerifier;
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace atom {
|
||||
class AtomDownloadManagerDelegate;
|
||||
class AtomCertVerifier;
|
||||
class AtomNetworkDelegate;
|
||||
class AtomPermissionManager;
|
||||
class AtomURLRequestJobFactory;
|
||||
class WebViewManager;
|
||||
|
||||
@@ -37,6 +38,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
// content::BrowserContext:
|
||||
content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
|
||||
content::BrowserPluginGuestManager* GetGuestManager() override;
|
||||
content::PermissionManager* GetPermissionManager() override;
|
||||
|
||||
// brightray::BrowserContext:
|
||||
void RegisterPrefs(PrefRegistrySimple* pref_registry) override;
|
||||
@@ -52,6 +54,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
private:
|
||||
scoped_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
|
||||
scoped_ptr<WebViewManager> guest_manager_;
|
||||
scoped_ptr<AtomPermissionManager> permission_manager_;
|
||||
|
||||
// Managed by brightray::BrowserContext.
|
||||
AtomCertVerifier* cert_verifier_;
|
||||
|
||||
@@ -31,7 +31,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
||||
|
||||
static AtomBrowserMainParts* Get();
|
||||
|
||||
// Sets the exit code, will fail if the the message loop is not ready.
|
||||
// Sets the exit code, will fail if the message loop is not ready.
|
||||
bool SetExitCode(int code);
|
||||
|
||||
// Gets the exit code
|
||||
|
||||
@@ -109,16 +109,24 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget(
|
||||
download->GetForcedFilePath());
|
||||
return true;
|
||||
}
|
||||
base::SupportsUserData::Data* save_path = download->GetUserData(
|
||||
atom::api::DownloadItem::UserDataKey());
|
||||
if (save_path) {
|
||||
const base::FilePath& default_download_path =
|
||||
static_cast<api::DownloadItem::SavePathData*>(save_path)->path();
|
||||
callback.Run(default_download_path,
|
||||
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
|
||||
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||
default_download_path);
|
||||
return true;
|
||||
|
||||
// Try to get the save path from JS wrapper.
|
||||
{
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
api::DownloadItem* download_item = api::DownloadItem::FromWrappedClass(
|
||||
isolate, download);
|
||||
if (download_item) {
|
||||
base::FilePath save_path = download_item->GetSavePath();
|
||||
if (!save_path.empty()) {
|
||||
callback.Run(save_path,
|
||||
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
|
||||
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||
save_path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
|
||||
|
||||
136
atom/browser/atom_permission_manager.cc
Normal file
136
atom/browser/atom_permission_manager.cc
Normal file
@@ -0,0 +1,136 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/atom_permission_manager.h"
|
||||
|
||||
#include "content/public/browser/child_process_security_policy.h"
|
||||
#include "content/public/browser/permission_type.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/web_contents.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// Must be kept in sync with atom_browser_client.cc
|
||||
int kDefaultRoutingID = 2;
|
||||
|
||||
bool WebContentsDestroyed(int process_id) {
|
||||
auto rvh = content::RenderViewHost::FromID(process_id, kDefaultRoutingID);
|
||||
if (rvh) {
|
||||
auto contents = content::WebContents::FromRenderViewHost(rvh);
|
||||
return contents->IsBeingDestroyed();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomPermissionManager::AtomPermissionManager()
|
||||
: request_id_(0) {
|
||||
}
|
||||
|
||||
AtomPermissionManager::~AtomPermissionManager() {
|
||||
}
|
||||
|
||||
void AtomPermissionManager::SetPermissionRequestHandler(
|
||||
const RequestHandler& handler) {
|
||||
if (handler.is_null() && !pending_requests_.empty()) {
|
||||
for (const auto& request : pending_requests_) {
|
||||
if (!WebContentsDestroyed(request.second.render_process_id))
|
||||
request.second.callback.Run(content::PERMISSION_STATUS_DENIED);
|
||||
}
|
||||
pending_requests_.clear();
|
||||
}
|
||||
request_handler_ = handler;
|
||||
}
|
||||
|
||||
int AtomPermissionManager::RequestPermission(
|
||||
content::PermissionType permission,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
bool user_gesture,
|
||||
const ResponseCallback& response_callback) {
|
||||
int process_id = render_frame_host->GetProcess()->GetID();
|
||||
|
||||
if (permission == content::PermissionType::MIDI_SYSEX) {
|
||||
content::ChildProcessSecurityPolicy::GetInstance()->
|
||||
GrantSendMidiSysExMessage(process_id);
|
||||
}
|
||||
|
||||
if (!request_handler_.is_null()) {
|
||||
auto web_contents =
|
||||
content::WebContents::FromRenderFrameHost(render_frame_host);
|
||||
++request_id_;
|
||||
auto callback = base::Bind(&AtomPermissionManager::OnPermissionResponse,
|
||||
base::Unretained(this),
|
||||
request_id_,
|
||||
requesting_origin,
|
||||
response_callback);
|
||||
pending_requests_[request_id_] = { process_id, callback };
|
||||
request_handler_.Run(web_contents, permission, callback);
|
||||
return request_id_;
|
||||
}
|
||||
|
||||
response_callback.Run(content::PERMISSION_STATUS_GRANTED);
|
||||
return kNoPendingOperation;
|
||||
}
|
||||
|
||||
void AtomPermissionManager::OnPermissionResponse(
|
||||
int request_id,
|
||||
const GURL& origin,
|
||||
const ResponseCallback& callback,
|
||||
content::PermissionStatus status) {
|
||||
auto request = pending_requests_.find(request_id);
|
||||
if (request != pending_requests_.end()) {
|
||||
if (!WebContentsDestroyed(request->second.render_process_id))
|
||||
callback.Run(status);
|
||||
pending_requests_.erase(request);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomPermissionManager::CancelPermissionRequest(int request_id) {
|
||||
auto request = pending_requests_.find(request_id);
|
||||
if (request != pending_requests_.end()) {
|
||||
if (!WebContentsDestroyed(request->second.render_process_id))
|
||||
request->second.callback.Run(content::PERMISSION_STATUS_DENIED);
|
||||
pending_requests_.erase(request);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomPermissionManager::ResetPermission(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) {
|
||||
}
|
||||
|
||||
content::PermissionStatus AtomPermissionManager::GetPermissionStatus(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) {
|
||||
return content::PERMISSION_STATUS_GRANTED;
|
||||
}
|
||||
|
||||
void AtomPermissionManager::RegisterPermissionUsage(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) {
|
||||
}
|
||||
|
||||
int AtomPermissionManager::SubscribePermissionStatusChange(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
const ResponseCallback& callback) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void AtomPermissionManager::UnsubscribePermissionStatusChange(
|
||||
int subscription_id) {
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
84
atom/browser/atom_permission_manager.h
Normal file
84
atom/browser/atom_permission_manager.h
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_ATOM_PERMISSION_MANAGER_H_
|
||||
#define ATOM_BROWSER_ATOM_PERMISSION_MANAGER_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "content/public/browser/permission_manager.h"
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomPermissionManager : public content::PermissionManager {
|
||||
public:
|
||||
AtomPermissionManager();
|
||||
~AtomPermissionManager() override;
|
||||
|
||||
using ResponseCallback =
|
||||
base::Callback<void(content::PermissionStatus)>;
|
||||
using RequestHandler =
|
||||
base::Callback<void(content::WebContents*,
|
||||
content::PermissionType,
|
||||
const ResponseCallback&)>;
|
||||
|
||||
// Handler to dispatch permission requests in JS.
|
||||
void SetPermissionRequestHandler(const RequestHandler& handler);
|
||||
|
||||
// content::PermissionManager:
|
||||
int RequestPermission(
|
||||
content::PermissionType permission,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
bool user_gesture,
|
||||
const ResponseCallback& callback) override;
|
||||
|
||||
protected:
|
||||
void OnPermissionResponse(int request_id,
|
||||
const GURL& url,
|
||||
const ResponseCallback& callback,
|
||||
content::PermissionStatus status);
|
||||
|
||||
// content::PermissionManager:
|
||||
void CancelPermissionRequest(int request_id) override;
|
||||
void ResetPermission(content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) override;
|
||||
content::PermissionStatus GetPermissionStatus(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) override;
|
||||
void RegisterPermissionUsage(content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) override;
|
||||
int SubscribePermissionStatusChange(
|
||||
content::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin,
|
||||
const base::Callback<void(content::PermissionStatus)>& callback) override;
|
||||
void UnsubscribePermissionStatusChange(int subscription_id) override;
|
||||
|
||||
private:
|
||||
struct RequestInfo {
|
||||
int render_process_id;
|
||||
ResponseCallback callback;
|
||||
};
|
||||
|
||||
RequestHandler request_handler_;
|
||||
|
||||
std::map<int, RequestInfo> pending_requests_;
|
||||
|
||||
int request_id_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomPermissionManager);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_ATOM_PERMISSION_MANAGER_H_
|
||||
@@ -26,7 +26,8 @@ bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol(
|
||||
bool has_user_gesture) {
|
||||
GURL escaped_url(net::EscapeExternalHandlerValue(url.spec()));
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(base::IgnoreResult(platform_util::OpenExternal), escaped_url));
|
||||
base::Bind(
|
||||
base::IgnoreResult(platform_util::OpenExternal), escaped_url, true));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -181,4 +181,8 @@ void Browser::OnWindowAllClosed() {
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWindowAllClosed());
|
||||
}
|
||||
|
||||
void Browser::PlatformThemeChanged() {
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnPlatformThemeChanged());
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -77,6 +77,15 @@ class Browser : public WindowListObserver {
|
||||
void SetAppUserModelID(const base::string16& name);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Hide the application.
|
||||
void Hide();
|
||||
|
||||
// Show the application.
|
||||
void Show();
|
||||
|
||||
// Check if the system is in Dark Mode.
|
||||
bool IsDarkMode();
|
||||
|
||||
// Bounce the dock icon.
|
||||
enum BounceType {
|
||||
BOUNCE_CRITICAL = 0,
|
||||
@@ -136,6 +145,9 @@ class Browser : public WindowListObserver {
|
||||
// Request basic auth login.
|
||||
void RequestLogin(LoginHandler* login_handler);
|
||||
|
||||
// Tell the application that plaform's theme changed.
|
||||
void PlatformThemeChanged();
|
||||
|
||||
void AddObserver(BrowserObserver* obs) {
|
||||
observers_.AddObserver(obs);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,19 @@ void Browser::Focus() {
|
||||
[[AtomApplication sharedApplication] activateIgnoringOtherApps:YES];
|
||||
}
|
||||
|
||||
void Browser::Hide() {
|
||||
[[AtomApplication sharedApplication] hide:nil];
|
||||
}
|
||||
|
||||
void Browser::Show() {
|
||||
[[AtomApplication sharedApplication] unhide:nil];
|
||||
}
|
||||
|
||||
bool Browser::IsDarkMode() {
|
||||
NSString *mode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
|
||||
return [mode isEqualToString: @"Dark"];
|
||||
}
|
||||
|
||||
void Browser::AddRecentDocument(const base::FilePath& path) {
|
||||
NSString* path_string = base::mac::FilePathToNSString(path);
|
||||
if (!path_string)
|
||||
@@ -103,7 +116,7 @@ void Browser::DockSetMenu(ui::MenuModel* model) {
|
||||
}
|
||||
|
||||
void Browser::DockSetIcon(const gfx::Image& image) {
|
||||
[[NSApplication sharedApplication]
|
||||
[[AtomApplication sharedApplication]
|
||||
setApplicationIconImage:image.AsNSImage()];
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ class BrowserObserver {
|
||||
// The browser requests HTTP login.
|
||||
virtual void OnLogin(LoginHandler* login_handler) {}
|
||||
|
||||
virtual void OnPlatformThemeChanged() {}
|
||||
|
||||
protected:
|
||||
virtual ~BrowserObserver() {}
|
||||
};
|
||||
|
||||
@@ -181,13 +181,6 @@ content::WebContents* CommonWebContentsDelegate::OpenURLFromTab(
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
#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"
|
||||
#include "brightray/browser/inspectable_web_contents_view_delegate.h"
|
||||
#include "content/public/browser/web_contents_delegate.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -21,7 +21,7 @@ class NativeWindow;
|
||||
class WebDialogHelper;
|
||||
|
||||
class CommonWebContentsDelegate
|
||||
: public brightray::DefaultWebContentsDelegate,
|
||||
: public content::WebContentsDelegate,
|
||||
public brightray::InspectableWebContentsDelegate,
|
||||
public brightray::InspectableWebContentsViewDelegate {
|
||||
public:
|
||||
@@ -59,9 +59,6 @@ class CommonWebContentsDelegate
|
||||
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;
|
||||
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
|
||||
content::WebContents* source) override;
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
const electron = require('electron');
|
||||
const app = electron.app;
|
||||
const BrowserWindow = electron.BrowserWindow;
|
||||
|
||||
var mainWindow = null;
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function() {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
app.on('ready', function() {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
autoHideMenuBar: true,
|
||||
useContentSize: true,
|
||||
});
|
||||
mainWindow.loadURL('file://' + __dirname + '/index.html');
|
||||
mainWindow.focus();
|
||||
});
|
||||
@@ -1,109 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const v8Util = process.atomBinding('v8_util');
|
||||
|
||||
class ObjectsRegistry extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.setMaxListeners(Number.MAX_VALUE);
|
||||
this.nextId = 0;
|
||||
|
||||
// Stores all objects by ref-counting.
|
||||
// (id) => {object, count}
|
||||
this.storage = {};
|
||||
|
||||
// Stores the IDs of objects referenced by WebContents.
|
||||
// (webContentsId) => {(id) => (count)}
|
||||
this.owners = {};
|
||||
}
|
||||
|
||||
// Register a new object, the object would be kept referenced until you release
|
||||
// it explicitly.
|
||||
add(webContentsId, obj) {
|
||||
var base, base1, id;
|
||||
id = this.saveToStorage(obj);
|
||||
|
||||
// Remember the owner.
|
||||
if ((base = this.owners)[webContentsId] == null) {
|
||||
base[webContentsId] = {};
|
||||
}
|
||||
if ((base1 = this.owners[webContentsId])[id] == null) {
|
||||
base1[id] = 0;
|
||||
}
|
||||
this.owners[webContentsId][id]++;
|
||||
|
||||
// Returns object's id
|
||||
return id;
|
||||
}
|
||||
|
||||
// Get an object according to its ID.
|
||||
get(id) {
|
||||
var ref;
|
||||
return (ref = this.storage[id]) != null ? ref.object : void 0;
|
||||
}
|
||||
|
||||
// Dereference an object according to its ID.
|
||||
remove(webContentsId, id) {
|
||||
var pointer;
|
||||
this.dereference(id, 1);
|
||||
|
||||
// Also reduce the count in owner.
|
||||
pointer = this.owners[webContentsId];
|
||||
if (pointer == null) {
|
||||
return;
|
||||
}
|
||||
--pointer[id];
|
||||
if (pointer[id] === 0) {
|
||||
return delete pointer[id];
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all references to objects refrenced by the WebContents.
|
||||
clear(webContentsId) {
|
||||
var count, id, ref;
|
||||
this.emit("clear-" + webContentsId);
|
||||
if (this.owners[webContentsId] == null) {
|
||||
return;
|
||||
}
|
||||
ref = this.owners[webContentsId];
|
||||
for (id in ref) {
|
||||
count = ref[id];
|
||||
this.dereference(id, count);
|
||||
}
|
||||
return delete this.owners[webContentsId];
|
||||
}
|
||||
|
||||
// Private: Saves the object into storage and assigns an ID for it.
|
||||
saveToStorage(object) {
|
||||
var id;
|
||||
id = v8Util.getHiddenValue(object, 'atomId');
|
||||
if (!id) {
|
||||
id = ++this.nextId;
|
||||
this.storage[id] = {
|
||||
count: 0,
|
||||
object: object
|
||||
};
|
||||
v8Util.setHiddenValue(object, 'atomId', id);
|
||||
}
|
||||
++this.storage[id].count;
|
||||
return id;
|
||||
}
|
||||
|
||||
// Private: Dereference the object from store.
|
||||
dereference(id, count) {
|
||||
var pointer;
|
||||
pointer = this.storage[id];
|
||||
if (pointer == null) {
|
||||
return;
|
||||
}
|
||||
pointer.count -= count;
|
||||
if (pointer.count === 0) {
|
||||
v8Util.deleteHiddenValue(pointer.object, 'atomId');
|
||||
return delete this.storage[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ObjectsRegistry;
|
||||
@@ -24,6 +24,9 @@
|
||||
// Don't add the "Enter Full Screen" menu item automatically.
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
|
||||
|
||||
// Add observer to monitor the system's Dark Mode theme.
|
||||
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(platformThemeChanged:) name:@"AppleInterfaceThemeChangedNotification" object:nil];
|
||||
|
||||
atom::Browser::Get()->WillFinishLaunching();
|
||||
}
|
||||
|
||||
@@ -59,4 +62,8 @@
|
||||
return flag;
|
||||
}
|
||||
|
||||
- (void)platformThemeChanged:(NSNotification *)notify {
|
||||
atom::Browser::Get()->PlatformThemeChanged();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -115,6 +115,12 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
||||
} else {
|
||||
SetSizeConstraints(size_constraints);
|
||||
}
|
||||
#if defined(USE_X11)
|
||||
bool resizable;
|
||||
if (options.Get(options::kResizable, &resizable)) {
|
||||
SetResizable(resizable);
|
||||
}
|
||||
#endif
|
||||
#if defined(OS_WIN) || defined(USE_X11)
|
||||
bool closable;
|
||||
if (options.Get(options::kClosable, &closable)) {
|
||||
@@ -133,12 +139,17 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
||||
if (options.Get(options::kAlwaysOnTop, &top) && top) {
|
||||
SetAlwaysOnTop(true);
|
||||
}
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
bool fullscreen;
|
||||
if (options.Get(options::kFullscreen, &fullscreen) && fullscreen) {
|
||||
// Disable fullscreen button if 'fullscreen' is specified to false.
|
||||
bool fullscreenable = true;
|
||||
bool fullscreen = false;
|
||||
if (options.Get(options::kFullscreen, &fullscreen) && !fullscreen)
|
||||
fullscreenable = false;
|
||||
// Overriden by 'fullscreenable'.
|
||||
options.Get(options::kFullScreenable, &fullscreenable);
|
||||
SetFullScreenable(fullscreenable);
|
||||
if (fullscreen) {
|
||||
SetFullScreen(true);
|
||||
}
|
||||
#endif
|
||||
bool skip;
|
||||
if (options.Get(options::kSkipTaskbar, &skip) && skip) {
|
||||
SetSkipTaskbar(skip);
|
||||
@@ -417,6 +428,14 @@ void NativeWindow::NotifyWindowFocus() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowFocus());
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowShow() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowShow());
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowHide() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowHide());
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowMaximize() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowMaximize());
|
||||
}
|
||||
|
||||
@@ -210,6 +210,8 @@ class NativeWindow : public base::SupportsUserData,
|
||||
void NotifyWindowClosed();
|
||||
void NotifyWindowBlur();
|
||||
void NotifyWindowFocus();
|
||||
void NotifyWindowShow();
|
||||
void NotifyWindowHide();
|
||||
void NotifyWindowMaximize();
|
||||
void NotifyWindowUnmaximize();
|
||||
void NotifyWindowMinimize();
|
||||
|
||||
@@ -79,6 +79,21 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)windowDidChangeOcclusionState:(NSNotification *)notification {
|
||||
// notification.object is the window that changed its state.
|
||||
// It's safe to use self.window instead if you don't assign one delegate to many windows
|
||||
NSWindow *window = notification.object;
|
||||
|
||||
// check occlusion binary flag
|
||||
if (window.occlusionState & NSWindowOcclusionStateVisible) {
|
||||
// The app is visible
|
||||
shell_->NotifyWindowShow();
|
||||
} else {
|
||||
// The app is not visible
|
||||
shell_->NotifyWindowHide();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeMain:(NSNotification*)notification {
|
||||
content::WebContents* web_contents = shell_->web_contents();
|
||||
if (!web_contents)
|
||||
@@ -482,19 +497,9 @@ NativeWindowMac::NativeWindowMac(
|
||||
options.Get(options::kDisableAutoHideCursor, &disableAutoHideCursor);
|
||||
[window_ setDisableAutoHideCursor:disableAutoHideCursor];
|
||||
|
||||
// Disable fullscreen button when 'fullscreenable' is false or 'fullscreen'
|
||||
// is specified to false.
|
||||
bool fullscreenable = true;
|
||||
options.Get(options::kFullScreenable, &fullscreenable);
|
||||
bool fullscreen = false;
|
||||
if (options.Get(options::kFullscreen, &fullscreen) && !fullscreen)
|
||||
fullscreenable = false;
|
||||
SetFullScreenable(fullscreenable);
|
||||
|
||||
// Disable zoom button if window is not resizable
|
||||
if (!maximizable) {
|
||||
// Disable zoom button if window is not resizable.
|
||||
if (!maximizable)
|
||||
SetMaximizable(false);
|
||||
}
|
||||
|
||||
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
|
||||
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
@@ -583,7 +588,16 @@ void NativeWindowMac::Unmaximize() {
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsMaximized() {
|
||||
return [window_ isZoomed];
|
||||
if (([window_ styleMask] & NSResizableWindowMask) != 0) {
|
||||
return [window_ isZoomed];
|
||||
} else {
|
||||
NSRect rectScreen = [[NSScreen mainScreen] visibleFrame];
|
||||
NSRect rectWindow = [window_ frame];
|
||||
return (rectScreen.origin.x == rectWindow.origin.x &&
|
||||
rectScreen.origin.y == rectWindow.origin.y &&
|
||||
rectScreen.size.width == rectWindow.size.width &&
|
||||
rectScreen.size.height == rectWindow.size.height);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::Minimize() {
|
||||
@@ -892,12 +906,15 @@ void NativeWindowMac::HandleKeyboardEvent(
|
||||
return;
|
||||
|
||||
BOOL handled = [[NSApp mainMenu] performKeyEquivalent:event.os_event];
|
||||
if (!handled && event.os_event.window != window_.get()) {
|
||||
// The event comes from detached devtools view, and it has already been
|
||||
if (!handled && (event.os_event.modifierFlags & NSCommandKeyMask) &&
|
||||
(event.os_event.keyCode == 50 /* ~ key */)) {
|
||||
// Handle the cmd+~ shortcut.
|
||||
Focus(true);
|
||||
if (!handled && event.os_event.window) {
|
||||
// Handle the cmd+~ shortcut.
|
||||
if ((event.os_event.modifierFlags & NSCommandKeyMask) /* cmd */ &&
|
||||
(event.os_event.keyCode == 50 /* ~ */)) {
|
||||
if (event.os_event.modifierFlags & NSShiftKeyMask) {
|
||||
[NSApp sendAction:@selector(_cycleWindowsReversed:) to:nil from:nil];
|
||||
} else {
|
||||
[NSApp sendAction:@selector(_cycleWindows:) to:nil from:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,12 @@ class NativeWindowObserver {
|
||||
// Called when window gains focus.
|
||||
virtual void OnWindowFocus() {}
|
||||
|
||||
// Called when window is shown.
|
||||
virtual void OnWindowShow() {}
|
||||
|
||||
// Called when window is hidden.
|
||||
virtual void OnWindowHide() {}
|
||||
|
||||
// Called when window state changed.
|
||||
virtual void OnWindowMaximize() {}
|
||||
virtual void OnWindowUnmaximize() {}
|
||||
|
||||
@@ -117,7 +117,8 @@ NativeWindowViews::NativeWindowViews(
|
||||
movable_(true),
|
||||
resizable_(true),
|
||||
maximizable_(true),
|
||||
minimizable_(true) {
|
||||
minimizable_(true),
|
||||
fullscreenable_(true) {
|
||||
options.Get(options::kTitle, &title_);
|
||||
options.Get(options::kAutoHideMenuBar, &menu_bar_autohide_);
|
||||
|
||||
@@ -300,14 +301,35 @@ bool NativeWindowViews::IsFocused() {
|
||||
|
||||
void NativeWindowViews::Show() {
|
||||
window_->native_widget_private()->ShowWithWindowState(GetRestoredState());
|
||||
|
||||
NotifyWindowShow();
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (global_menu_bar_)
|
||||
global_menu_bar_->OnWindowMapped();
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::ShowInactive() {
|
||||
window_->ShowInactive();
|
||||
|
||||
NotifyWindowShow();
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (global_menu_bar_)
|
||||
global_menu_bar_->OnWindowMapped();
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::Hide() {
|
||||
window_->Hide();
|
||||
|
||||
NotifyWindowHide();
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (global_menu_bar_)
|
||||
global_menu_bar_->OnWindowUnmapped();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsVisible() {
|
||||
@@ -347,6 +369,9 @@ bool NativeWindowViews::IsMinimized() {
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetFullScreen(bool fullscreen) {
|
||||
if (!IsFullScreenable())
|
||||
return;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// There is no native fullscreen state on Windows.
|
||||
if (fullscreen) {
|
||||
@@ -490,11 +515,12 @@ bool NativeWindowViews::IsMaximizable() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetFullScreenable(bool maximizable) {
|
||||
void NativeWindowViews::SetFullScreenable(bool fullscreenable) {
|
||||
fullscreenable_ = fullscreenable;
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsFullScreenable() {
|
||||
return true;
|
||||
return fullscreenable_;
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetClosable(bool closable) {
|
||||
|
||||
@@ -212,6 +212,7 @@ class NativeWindowViews : public NativeWindow,
|
||||
bool resizable_;
|
||||
bool maximizable_;
|
||||
bool minimizable_;
|
||||
bool fullscreenable_;
|
||||
std::string title_;
|
||||
gfx::Size widget_size_;
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>atom.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.36.7</string>
|
||||
<string>0.36.12</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.36.7</string>
|
||||
<string>0.36.12</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@@ -56,8 +56,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,36,7,0
|
||||
PRODUCTVERSION 0,36,7,0
|
||||
FILEVERSION 0,36,12,0
|
||||
PRODUCTVERSION 0,36,12,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -74,12 +74,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "0.36.7"
|
||||
VALUE "FileVersion", "0.36.12"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "0.36.7"
|
||||
VALUE "ProductVersion", "0.36.12"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/keyboad_util.h"
|
||||
#include "atom/common/keyboard_util.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_split.h"
|
||||
@@ -18,13 +18,12 @@
|
||||
|
||||
namespace accelerator_util {
|
||||
|
||||
bool StringToAccelerator(const std::string& description,
|
||||
bool StringToAccelerator(const std::string& shortcut,
|
||||
ui::Accelerator* accelerator) {
|
||||
if (!base::IsStringASCII(description)) {
|
||||
if (!base::IsStringASCII(shortcut)) {
|
||||
LOG(ERROR) << "The accelerator string can only contain ASCII characters";
|
||||
return false;
|
||||
}
|
||||
std::string shortcut(base::ToLowerASCII(description));
|
||||
|
||||
std::vector<std::string> tokens = base::SplitString(
|
||||
shortcut, "+", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
@@ -33,95 +32,35 @@ bool StringToAccelerator(const std::string& description,
|
||||
int modifiers = ui::EF_NONE;
|
||||
ui::KeyboardCode key = ui::VKEY_UNKNOWN;
|
||||
for (size_t i = 0; i < tokens.size(); i++) {
|
||||
// We use straight comparing instead of map because the accelerator tends
|
||||
// to be correct and usually only uses few special tokens.
|
||||
if (tokens[i].size() == 1) {
|
||||
bool shifted = false;
|
||||
key = atom::KeyboardCodeFromCharCode(tokens[i][0], &shifted);
|
||||
if (shifted)
|
||||
bool shifted = false;
|
||||
ui::KeyboardCode code = atom::KeyboardCodeFromStr(tokens[i], &shifted);
|
||||
if (shifted)
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
switch (code) {
|
||||
// The token can be a modifier.
|
||||
case ui::VKEY_SHIFT:
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
} else if (tokens[i] == "ctrl" || tokens[i] == "control") {
|
||||
modifiers |= ui::EF_CONTROL_DOWN;
|
||||
} else if (tokens[i] == "super") {
|
||||
modifiers |= ui::EF_COMMAND_DOWN;
|
||||
#if defined(OS_MACOSX)
|
||||
} else if (tokens[i] == "cmd" || tokens[i] == "command") {
|
||||
modifiers |= ui::EF_COMMAND_DOWN;
|
||||
#endif
|
||||
} else if (tokens[i] == "commandorcontrol" || tokens[i] == "cmdorctrl") {
|
||||
#if defined(OS_MACOSX)
|
||||
modifiers |= ui::EF_COMMAND_DOWN;
|
||||
#else
|
||||
modifiers |= ui::EF_CONTROL_DOWN;
|
||||
#endif
|
||||
} else if (tokens[i] == "alt") {
|
||||
modifiers |= ui::EF_ALT_DOWN;
|
||||
} else if (tokens[i] == "shift") {
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
} else if (tokens[i] == "plus") {
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
key = ui::VKEY_OEM_PLUS;
|
||||
} else if (tokens[i] == "tab") {
|
||||
key = ui::VKEY_TAB;
|
||||
} else if (tokens[i] == "space") {
|
||||
key = ui::VKEY_SPACE;
|
||||
} else if (tokens[i] == "backspace") {
|
||||
key = ui::VKEY_BACK;
|
||||
} else if (tokens[i] == "delete") {
|
||||
key = ui::VKEY_DELETE;
|
||||
} else if (tokens[i] == "insert") {
|
||||
key = ui::VKEY_INSERT;
|
||||
} else if (tokens[i] == "enter" || tokens[i] == "return") {
|
||||
key = ui::VKEY_RETURN;
|
||||
} else if (tokens[i] == "up") {
|
||||
key = ui::VKEY_UP;
|
||||
} else if (tokens[i] == "down") {
|
||||
key = ui::VKEY_DOWN;
|
||||
} else if (tokens[i] == "left") {
|
||||
key = ui::VKEY_LEFT;
|
||||
} else if (tokens[i] == "right") {
|
||||
key = ui::VKEY_RIGHT;
|
||||
} else if (tokens[i] == "home") {
|
||||
key = ui::VKEY_HOME;
|
||||
} else if (tokens[i] == "end") {
|
||||
key = ui::VKEY_END;
|
||||
} else if (tokens[i] == "pageup") {
|
||||
key = ui::VKEY_PRIOR;
|
||||
} else if (tokens[i] == "pagedown") {
|
||||
key = ui::VKEY_NEXT;
|
||||
} else if (tokens[i] == "esc" || tokens[i] == "escape") {
|
||||
key = ui::VKEY_ESCAPE;
|
||||
} else if (tokens[i] == "volumemute") {
|
||||
key = ui::VKEY_VOLUME_MUTE;
|
||||
} else if (tokens[i] == "volumeup") {
|
||||
key = ui::VKEY_VOLUME_UP;
|
||||
} else if (tokens[i] == "volumedown") {
|
||||
key = ui::VKEY_VOLUME_DOWN;
|
||||
} else if (tokens[i] == "medianexttrack") {
|
||||
key = ui::VKEY_MEDIA_NEXT_TRACK;
|
||||
} else if (tokens[i] == "mediaprevioustrack") {
|
||||
key = ui::VKEY_MEDIA_PREV_TRACK;
|
||||
} else if (tokens[i] == "mediastop") {
|
||||
key = ui::VKEY_MEDIA_STOP;
|
||||
} else if (tokens[i] == "mediaplaypause") {
|
||||
key = ui::VKEY_MEDIA_PLAY_PAUSE;
|
||||
} else if (tokens[i].size() > 1 && tokens[i][0] == 'f') {
|
||||
// F1 - F24.
|
||||
int n;
|
||||
if (base::StringToInt(tokens[i].c_str() + 1, &n) && n > 0 && n < 25) {
|
||||
key = static_cast<ui::KeyboardCode>(ui::VKEY_F1 + n - 1);
|
||||
} else {
|
||||
LOG(WARNING) << tokens[i] << "is not available on keyboard";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG(WARNING) << "Invalid accelerator token: " << tokens[i];
|
||||
return false;
|
||||
break;
|
||||
case ui::VKEY_CONTROL:
|
||||
modifiers |= ui::EF_CONTROL_DOWN;
|
||||
break;
|
||||
case ui::VKEY_MENU:
|
||||
modifiers |= ui::EF_ALT_DOWN;
|
||||
break;
|
||||
case ui::VKEY_COMMAND:
|
||||
modifiers |= ui::EF_COMMAND_DOWN;
|
||||
break;
|
||||
case ui::VKEY_ALTGR:
|
||||
modifiers |= ui::EF_ALTGR_DOWN;
|
||||
break;
|
||||
// Or it is a normal key.
|
||||
default:
|
||||
key = code;
|
||||
}
|
||||
}
|
||||
|
||||
if (key == ui::VKEY_UNKNOWN) {
|
||||
LOG(WARNING) << "The accelerator doesn't contain a valid key";
|
||||
LOG(WARNING) << shortcut << " doesn't contain a valid key";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,12 @@ Role kRolesMap[] = {
|
||||
{ @selector(cut:), "cut" },
|
||||
{ @selector(copy:), "copy" },
|
||||
{ @selector(paste:), "paste" },
|
||||
{ @selector(delete:), "delete" },
|
||||
{ @selector(pasteAndMatchStyle:), "paste-and-match-style" },
|
||||
{ @selector(selectAll:), "selectall" },
|
||||
{ @selector(performMiniaturize:), "minimize" },
|
||||
{ @selector(performClose:), "close" },
|
||||
{ @selector(performZoom:), "zoom" },
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/mac/mac_util.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "skia/ext/skia_utils_mac.h"
|
||||
|
||||
@interface ModalDelegate : NSObject {
|
||||
@private
|
||||
@@ -57,7 +59,8 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window,
|
||||
int default_id,
|
||||
const std::string& title,
|
||||
const std::string& message,
|
||||
const std::string& detail) {
|
||||
const std::string& detail,
|
||||
const gfx::ImageSkia& icon) {
|
||||
// Ignore the title; it's the window title on other platforms and ignorable.
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
[alert setMessageText:base::SysUTF8ToNSString(message)];
|
||||
@@ -92,6 +95,12 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window,
|
||||
[[ns_buttons objectAtIndex:default_id] setKeyEquivalent:@"\r"];
|
||||
}
|
||||
|
||||
if (!icon.isNull()) {
|
||||
NSImage* image = gfx::SkBitmapToNSImageWithColorSpace(
|
||||
*icon.bitmap(), base::mac::GetGenericRGBColorSpace());
|
||||
[alert setIcon:image];
|
||||
}
|
||||
|
||||
return alert;
|
||||
}
|
||||
|
||||
@@ -113,7 +122,7 @@ int ShowMessageBox(NativeWindow* parent_window,
|
||||
const gfx::ImageSkia& icon) {
|
||||
NSAlert* alert = CreateNSAlert(
|
||||
parent_window, type, buttons, default_id, title, message,
|
||||
detail);
|
||||
detail, icon);
|
||||
|
||||
// Use runModal for synchronous alert without parent, since we don't have a
|
||||
// window to wait for.
|
||||
@@ -149,7 +158,7 @@ void ShowMessageBox(NativeWindow* parent_window,
|
||||
const MessageBoxCallback& callback) {
|
||||
NSAlert* alert = CreateNSAlert(
|
||||
parent_window, type, buttons, default_id, title, message,
|
||||
detail);
|
||||
detail, icon);
|
||||
ModalDelegate* delegate = [[ModalDelegate alloc] initWithCallback:callback
|
||||
andAlert:alert
|
||||
callEndModal:false];
|
||||
|
||||
@@ -210,6 +210,14 @@ void GlobalMenuBarX11::InitServer(gfx::AcceleratedWidget xid) {
|
||||
server_ = server_new(path.c_str());
|
||||
}
|
||||
|
||||
void GlobalMenuBarX11::OnWindowMapped() {
|
||||
GlobalMenuBarRegistrarX11::GetInstance()->OnWindowMapped(xid_);
|
||||
}
|
||||
|
||||
void GlobalMenuBarX11::OnWindowUnmapped() {
|
||||
GlobalMenuBarRegistrarX11::GetInstance()->OnWindowUnmapped(xid_);
|
||||
}
|
||||
|
||||
void GlobalMenuBarX11::BuildMenuFromModel(ui::MenuModel* model,
|
||||
DbusmenuMenuitem* parent) {
|
||||
for (int i = 0; i < model->GetItemCount(); ++i) {
|
||||
|
||||
@@ -40,12 +40,16 @@ class GlobalMenuBarX11 {
|
||||
explicit GlobalMenuBarX11(NativeWindowViews* window);
|
||||
virtual ~GlobalMenuBarX11();
|
||||
|
||||
// Creates the object path for DbusemenuServer which is attached to |xid|.
|
||||
// Creates the object path for DbusmenuServer which is attached to |xid|.
|
||||
static std::string GetPathForWindow(gfx::AcceleratedWidget xid);
|
||||
|
||||
void SetMenu(ui::MenuModel* menu_model);
|
||||
bool IsServerStarted() const;
|
||||
|
||||
// Called by NativeWindow when it show/hides.
|
||||
void OnWindowMapped();
|
||||
void OnWindowUnmapped();
|
||||
|
||||
private:
|
||||
// Creates a DbusmenuServer.
|
||||
void InitServer(gfx::AcceleratedWidget xid);
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace atom {
|
||||
namespace {
|
||||
|
||||
// Filter out the "&" in menu label.
|
||||
base::string16 FilterAccecelator(const base::string16& label) {
|
||||
base::string16 FilterAccelerator(const base::string16& label) {
|
||||
base::string16 out;
|
||||
base::RemoveChars(label, base::ASCIIToUTF16("&").c_str(), &out);
|
||||
return out;
|
||||
@@ -26,7 +26,7 @@ base::string16 FilterAccecelator(const base::string16& label) {
|
||||
SubmenuButton::SubmenuButton(views::ButtonListener* listener,
|
||||
const base::string16& title,
|
||||
views::MenuButtonListener* menu_button_listener)
|
||||
: views::MenuButton(listener, FilterAccecelator(title),
|
||||
: views::MenuButton(listener, FilterAccelerator(title),
|
||||
menu_button_listener, false),
|
||||
accelerator_(0),
|
||||
show_underline_(false),
|
||||
|
||||
94
atom/browser/web_contents_permission_helper.cc
Normal file
94
atom/browser/web_contents_permission_helper.cc
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/web_contents_permission_helper.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/atom_permission_manager.h"
|
||||
#include "brightray/browser/media/media_stream_devices_controller.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
|
||||
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::WebContentsPermissionHelper);
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
void MediaAccessAllowed(
|
||||
const content::MediaStreamRequest& request,
|
||||
const content::MediaResponseCallback& callback,
|
||||
bool allowed) {
|
||||
brightray::MediaStreamDevicesController controller(request, callback);
|
||||
if (allowed)
|
||||
controller.TakeAction();
|
||||
else
|
||||
controller.Deny(content::MEDIA_DEVICE_PERMISSION_DENIED);
|
||||
}
|
||||
|
||||
void OnPointerLockResponse(content::WebContents* web_contents, bool allowed) {
|
||||
if (web_contents)
|
||||
web_contents->GotResponseToLockMouseRequest(allowed);
|
||||
}
|
||||
|
||||
void OnPermissionResponse(const base::Callback<void(bool)>& callback,
|
||||
content::PermissionStatus status) {
|
||||
if (status == content::PERMISSION_STATUS_GRANTED)
|
||||
callback.Run(true);
|
||||
else
|
||||
callback.Run(false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WebContentsPermissionHelper::WebContentsPermissionHelper(
|
||||
content::WebContents* web_contents)
|
||||
: web_contents_(web_contents) {
|
||||
}
|
||||
|
||||
WebContentsPermissionHelper::~WebContentsPermissionHelper() {
|
||||
}
|
||||
|
||||
void WebContentsPermissionHelper::RequestPermission(
|
||||
content::PermissionType permission,
|
||||
const base::Callback<void(bool)>& callback,
|
||||
bool user_gesture) {
|
||||
auto rfh = web_contents_->GetMainFrame();
|
||||
auto permission_manager = static_cast<AtomPermissionManager*>(
|
||||
web_contents_->GetBrowserContext()->GetPermissionManager());
|
||||
auto origin = web_contents_->GetLastCommittedURL();
|
||||
permission_manager->RequestPermission(
|
||||
permission, rfh, origin, user_gesture,
|
||||
base::Bind(&OnPermissionResponse, callback));
|
||||
}
|
||||
|
||||
void WebContentsPermissionHelper::RequestFullscreenPermission(
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
RequestPermission((content::PermissionType)(PermissionType::FULLSCREEN),
|
||||
callback);
|
||||
}
|
||||
|
||||
void WebContentsPermissionHelper::RequestMediaAccessPermission(
|
||||
const content::MediaStreamRequest& request,
|
||||
const content::MediaResponseCallback& response_callback) {
|
||||
auto callback = base::Bind(&MediaAccessAllowed, request, response_callback);
|
||||
// The permission type doesn't matter here, AUDIO_CAPTURE/VIDEO_CAPTURE
|
||||
// are presented as same type in content_converter.h.
|
||||
RequestPermission(content::PermissionType::AUDIO_CAPTURE, callback);
|
||||
}
|
||||
|
||||
void WebContentsPermissionHelper::RequestWebNotificationPermission(
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
RequestPermission(content::PermissionType::NOTIFICATIONS, callback);
|
||||
}
|
||||
|
||||
void WebContentsPermissionHelper::RequestPointerLockPermission(
|
||||
bool user_gesture) {
|
||||
RequestPermission((content::PermissionType)(PermissionType::POINTER_LOCK),
|
||||
base::Bind(&OnPointerLockResponse, web_contents_),
|
||||
user_gesture);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
50
atom/browser/web_contents_permission_helper.h
Normal file
50
atom/browser/web_contents_permission_helper.h
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_WEB_CONTENTS_PERMISSION_HELPER_H_
|
||||
#define ATOM_BROWSER_WEB_CONTENTS_PERMISSION_HELPER_H_
|
||||
|
||||
#include "content/public/browser/permission_type.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
#include "content/public/common/media_stream_request.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Applies the permission requested for WebContents.
|
||||
class WebContentsPermissionHelper
|
||||
: public content::WebContentsUserData<WebContentsPermissionHelper> {
|
||||
public:
|
||||
~WebContentsPermissionHelper() override;
|
||||
|
||||
enum class PermissionType {
|
||||
POINTER_LOCK = static_cast<int>(content::PermissionType::NUM) + 1,
|
||||
FULLSCREEN
|
||||
};
|
||||
|
||||
void RequestFullscreenPermission(
|
||||
const base::Callback<void(bool)>& callback);
|
||||
void RequestMediaAccessPermission(
|
||||
const content::MediaStreamRequest& request,
|
||||
const content::MediaResponseCallback& callback);
|
||||
void RequestWebNotificationPermission(
|
||||
const base::Callback<void(bool)>& callback);
|
||||
void RequestPointerLockPermission(bool user_gesture);
|
||||
|
||||
private:
|
||||
explicit WebContentsPermissionHelper(content::WebContents* web_contents);
|
||||
friend class content::WebContentsUserData<WebContentsPermissionHelper>;
|
||||
|
||||
void RequestPermission(
|
||||
content::PermissionType permission,
|
||||
const base::Callback<void(bool)>& callback,
|
||||
bool user_gesture = false);
|
||||
|
||||
content::WebContents* web_contents_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebContentsPermissionHelper);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_WEB_CONTENTS_PERMISSION_HELPER_H_
|
||||
@@ -60,6 +60,11 @@ void Write(const mate::Dictionary& data,
|
||||
if (data.Get("text", &text))
|
||||
writer.WriteText(text);
|
||||
|
||||
if (data.Get("rtf", &text)) {
|
||||
std::string rtf = base::UTF16ToUTF8(text);
|
||||
writer.WriteRTF(rtf);
|
||||
}
|
||||
|
||||
if (data.Get("html", &html))
|
||||
writer.WriteHTML(html, std::string());
|
||||
|
||||
@@ -88,6 +93,18 @@ void WriteText(const base::string16& text, mate::Arguments* args) {
|
||||
writer.WriteText(text);
|
||||
}
|
||||
|
||||
base::string16 ReadRtf(mate::Arguments* args) {
|
||||
std::string data;
|
||||
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
|
||||
clipboard->ReadRTF(GetClipboardType(args), &data);
|
||||
return base::UTF8ToUTF16(data);
|
||||
}
|
||||
|
||||
void WriteRtf(const std::string& text, mate::Arguments* args) {
|
||||
ui::ScopedClipboardWriter writer(GetClipboardType(args));
|
||||
writer.WriteRTF(text);
|
||||
}
|
||||
|
||||
base::string16 ReadHtml(mate::Arguments* args) {
|
||||
base::string16 data;
|
||||
base::string16 html;
|
||||
@@ -129,6 +146,8 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
dict.SetMethod("write", &Write);
|
||||
dict.SetMethod("readText", &ReadText);
|
||||
dict.SetMethod("writeText", &WriteText);
|
||||
dict.SetMethod("readRtf", &ReadRtf);
|
||||
dict.SetMethod("writeRtf", &WriteRtf);
|
||||
dict.SetMethod("readHtml", &ReadHtml);
|
||||
dict.SetMethod("writeHtml", &WriteHtml);
|
||||
dict.SetMethod("readImage", &ReadImage);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/base64.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/pattern.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
@@ -119,6 +120,20 @@ bool PopulateImageSkiaRepsFromPath(gfx::ImageSkia* image,
|
||||
return succeed;
|
||||
}
|
||||
|
||||
base::FilePath NormalizePath(const base::FilePath& path) {
|
||||
if (!path.ReferencesParent()) {
|
||||
return path;
|
||||
}
|
||||
|
||||
base::FilePath absolute_path = MakeAbsoluteFilePath(path);
|
||||
// MakeAbsoluteFilePath returns an empty path on failures so use original path
|
||||
if (absolute_path.empty()) {
|
||||
return path;
|
||||
} else {
|
||||
return absolute_path;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool IsTemplateFilename(const base::FilePath& path) {
|
||||
return (base::MatchPattern(path.value(), "*Template.*") ||
|
||||
@@ -254,17 +269,19 @@ mate::Handle<NativeImage> NativeImage::CreateFromJPEG(
|
||||
mate::Handle<NativeImage> NativeImage::CreateFromPath(
|
||||
v8::Isolate* isolate, const base::FilePath& path) {
|
||||
gfx::ImageSkia image_skia;
|
||||
if (path.MatchesExtension(FILE_PATH_LITERAL(".ico"))) {
|
||||
base::FilePath image_path = NormalizePath(path);
|
||||
|
||||
if (image_path.MatchesExtension(FILE_PATH_LITERAL(".ico"))) {
|
||||
#if defined(OS_WIN)
|
||||
ReadImageSkiaFromICO(&image_skia, path);
|
||||
ReadImageSkiaFromICO(&image_skia, image_path);
|
||||
#endif
|
||||
} else {
|
||||
PopulateImageSkiaRepsFromPath(&image_skia, path);
|
||||
PopulateImageSkiaRepsFromPath(&image_skia, image_path);
|
||||
}
|
||||
gfx::Image image(image_skia);
|
||||
mate::Handle<NativeImage> handle = Create(isolate, image);
|
||||
#if defined(OS_MACOSX)
|
||||
if (IsTemplateFilename(path))
|
||||
if (IsTemplateFilename(image_path))
|
||||
handle->SetTemplateImage(true);
|
||||
#endif
|
||||
return handle;
|
||||
|
||||
@@ -12,12 +12,23 @@
|
||||
|
||||
namespace {
|
||||
|
||||
bool OpenExternal(const GURL& url, mate::Arguments* args) {
|
||||
bool activate = true;
|
||||
if (args->Length() == 2) {
|
||||
mate::Dictionary options;
|
||||
if (args->GetNext(&options)) {
|
||||
options.Get("activate", &activate);
|
||||
}
|
||||
}
|
||||
return platform_util::OpenExternal(url, activate);
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("showItemInFolder", &platform_util::ShowItemInFolder);
|
||||
dict.SetMethod("openItem", &platform_util::OpenItem);
|
||||
dict.SetMethod("openExternal", &platform_util::OpenExternal);
|
||||
dict.SetMethod("openExternal", &OpenExternal);
|
||||
dict.SetMethod("moveItemToTrash", &platform_util::MoveItemToTrash);
|
||||
dict.SetMethod("beep", &platform_util::Beep);
|
||||
}
|
||||
|
||||
@@ -2,49 +2,15 @@
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/api/object_life_monitor.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "v8/include/v8-profiler.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// A Persistent that can be copied and will not free itself.
|
||||
template<class T>
|
||||
struct LeakedPersistentTraits {
|
||||
typedef v8::Persistent<T, LeakedPersistentTraits<T> > LeakedPersistent;
|
||||
static const bool kResetInDestructor = false;
|
||||
template<class S, class M>
|
||||
static V8_INLINE void Copy(const v8::Persistent<S, M>& source,
|
||||
LeakedPersistent* dest) {
|
||||
// do nothing, just allow copy
|
||||
}
|
||||
};
|
||||
|
||||
// The handles are leaked on purpose.
|
||||
using FunctionTemplateHandle =
|
||||
LeakedPersistentTraits<v8::FunctionTemplate>::LeakedPersistent;
|
||||
std::map<std::string, FunctionTemplateHandle> function_templates_;
|
||||
|
||||
v8::Local<v8::Object> CreateObjectWithName(v8::Isolate* isolate,
|
||||
const std::string& name) {
|
||||
if (name == "Object")
|
||||
return v8::Object::New(isolate);
|
||||
|
||||
if (ContainsKey(function_templates_, name))
|
||||
return v8::Local<v8::FunctionTemplate>::New(
|
||||
isolate, function_templates_[name])->GetFunction()->NewInstance();
|
||||
|
||||
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
|
||||
t->SetClassName(mate::StringToV8(isolate, name));
|
||||
function_templates_[name] = FunctionTemplateHandle(isolate, t);
|
||||
return t->GetFunction()->NewInstance();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> GetHiddenValue(v8::Local<v8::Object> object,
|
||||
v8::Local<v8::String> key) {
|
||||
return object->GetHiddenValue(key);
|
||||
@@ -78,7 +44,6 @@ void TakeHeapSnapshot(v8::Isolate* isolate) {
|
||||
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("createObjectWithName", &CreateObjectWithName);
|
||||
dict.SetMethod("getHiddenValue", &GetHiddenValue);
|
||||
dict.SetMethod("setHiddenValue", &SetHiddenValue);
|
||||
dict.SetMethod("deleteHiddenValue", &DeleteHiddenValue);
|
||||
|
||||
@@ -31,16 +31,16 @@ ObjectLifeMonitor::ObjectLifeMonitor(v8::Isolate* isolate,
|
||||
// static
|
||||
void ObjectLifeMonitor::OnObjectGC(
|
||||
const v8::WeakCallbackInfo<ObjectLifeMonitor>& data) {
|
||||
// Usually FirstWeakCallback should do nothing other than reset |object_|
|
||||
// and then set a second weak callback to run later. We can sidestep that,
|
||||
// because posting a task to the current message loop is all but free - but
|
||||
// DO NOT add any more work to this method. The only acceptable place to add
|
||||
// code is RunCallback.
|
||||
ObjectLifeMonitor* self = data.GetParameter();
|
||||
self->target_.Reset();
|
||||
base::MessageLoop::current()->PostTask(
|
||||
FROM_HERE, base::Bind(&ObjectLifeMonitor::RunCallback,
|
||||
self->weak_ptr_factory_.GetWeakPtr()));
|
||||
self->RunCallback();
|
||||
data.SetSecondPassCallback(Free);
|
||||
}
|
||||
|
||||
// static
|
||||
void ObjectLifeMonitor::Free(
|
||||
const v8::WeakCallbackInfo<ObjectLifeMonitor>& data) {
|
||||
delete data.GetParameter();
|
||||
}
|
||||
|
||||
void ObjectLifeMonitor::RunCallback() {
|
||||
@@ -50,7 +50,6 @@ void ObjectLifeMonitor::RunCallback() {
|
||||
v8::Context::Scope context_scope(context);
|
||||
v8::Local<v8::Function>::New(isolate_, destructor_)->Call(
|
||||
context->Global(), 0, nullptr);
|
||||
delete this;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -23,6 +23,7 @@ class ObjectLifeMonitor {
|
||||
v8::Local<v8::Function> destructor);
|
||||
|
||||
static void OnObjectGC(const v8::WeakCallbackInfo<ObjectLifeMonitor>& data);
|
||||
static void Free(const v8::WeakCallbackInfo<ObjectLifeMonitor>& data);
|
||||
|
||||
void RunCallback();
|
||||
|
||||
|
||||
@@ -140,7 +140,10 @@ Archive::~Archive() {
|
||||
|
||||
bool Archive::Init() {
|
||||
if (!file_.IsValid()) {
|
||||
LOG(ERROR) << base::File::ErrorToString(file_.error_details());
|
||||
if (file_.error_details() != base::File::FILE_ERROR_NOT_FOUND) {
|
||||
LOG(WARNING) << "Opening " << path_.value()
|
||||
<< ": " << base::File::ErrorToString(file_.error_details());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#define ATOM_MAJOR_VERSION 0
|
||||
#define ATOM_MINOR_VERSION 36
|
||||
#define ATOM_PATCH_VERSION 7
|
||||
#define ATOM_PATCH_VERSION 12
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ bool CrashService::Initialize(const base::string16& application_name,
|
||||
std::wstring pipe_name = kTestPipeName;
|
||||
int max_reports = -1;
|
||||
|
||||
// The checkpoint file allows CrashReportSender to enforce the the maximum
|
||||
// The checkpoint file allows CrashReportSender to enforce the maximum
|
||||
// reports per day quota. Does not seem to serve any other purpose.
|
||||
base::FilePath checkpoint_path = operating_dir.Append(kCheckPointFile);
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <string>
|
||||
#include "atom/common/keyboad_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Return key code of the char.
|
||||
ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted) {
|
||||
*shifted = false;
|
||||
switch (c) {
|
||||
case 0x08: return ui::VKEY_BACK;
|
||||
case 0x7F: return ui::VKEY_DELETE;
|
||||
case 0x09: return ui::VKEY_TAB;
|
||||
case 0x0D: return ui::VKEY_RETURN;
|
||||
case 0x1B: return ui::VKEY_ESCAPE;
|
||||
case ' ': return ui::VKEY_SPACE;
|
||||
|
||||
case 'a': return ui::VKEY_A;
|
||||
case 'b': return ui::VKEY_B;
|
||||
case 'c': return ui::VKEY_C;
|
||||
case 'd': return ui::VKEY_D;
|
||||
case 'e': return ui::VKEY_E;
|
||||
case 'f': return ui::VKEY_F;
|
||||
case 'g': return ui::VKEY_G;
|
||||
case 'h': return ui::VKEY_H;
|
||||
case 'i': return ui::VKEY_I;
|
||||
case 'j': return ui::VKEY_J;
|
||||
case 'k': return ui::VKEY_K;
|
||||
case 'l': return ui::VKEY_L;
|
||||
case 'm': return ui::VKEY_M;
|
||||
case 'n': return ui::VKEY_N;
|
||||
case 'o': return ui::VKEY_O;
|
||||
case 'p': return ui::VKEY_P;
|
||||
case 'q': return ui::VKEY_Q;
|
||||
case 'r': return ui::VKEY_R;
|
||||
case 's': return ui::VKEY_S;
|
||||
case 't': return ui::VKEY_T;
|
||||
case 'u': return ui::VKEY_U;
|
||||
case 'v': return ui::VKEY_V;
|
||||
case 'w': return ui::VKEY_W;
|
||||
case 'x': return ui::VKEY_X;
|
||||
case 'y': return ui::VKEY_Y;
|
||||
case 'z': return ui::VKEY_Z;
|
||||
|
||||
case ')': *shifted = true; case '0': return ui::VKEY_0;
|
||||
case '!': *shifted = true; case '1': return ui::VKEY_1;
|
||||
case '@': *shifted = true; case '2': return ui::VKEY_2;
|
||||
case '#': *shifted = true; case '3': return ui::VKEY_3;
|
||||
case '$': *shifted = true; case '4': return ui::VKEY_4;
|
||||
case '%': *shifted = true; case '5': return ui::VKEY_5;
|
||||
case '^': *shifted = true; case '6': return ui::VKEY_6;
|
||||
case '&': *shifted = true; case '7': return ui::VKEY_7;
|
||||
case '*': *shifted = true; case '8': return ui::VKEY_8;
|
||||
case '(': *shifted = true; case '9': return ui::VKEY_9;
|
||||
|
||||
case ':': *shifted = true; case ';': return ui::VKEY_OEM_1;
|
||||
case '+': *shifted = true; case '=': return ui::VKEY_OEM_PLUS;
|
||||
case '<': *shifted = true; case ',': return ui::VKEY_OEM_COMMA;
|
||||
case '_': *shifted = true; case '-': return ui::VKEY_OEM_MINUS;
|
||||
case '>': *shifted = true; case '.': return ui::VKEY_OEM_PERIOD;
|
||||
case '?': *shifted = true; case '/': return ui::VKEY_OEM_2;
|
||||
case '~': *shifted = true; case '`': return ui::VKEY_OEM_3;
|
||||
case '{': *shifted = true; case '[': return ui::VKEY_OEM_4;
|
||||
case '|': *shifted = true; case '\\': return ui::VKEY_OEM_5;
|
||||
case '}': *shifted = true; case ']': return ui::VKEY_OEM_6;
|
||||
case '"': *shifted = true; case '\'': return ui::VKEY_OEM_7;
|
||||
|
||||
default: return ui::VKEY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// Return key code of the char.
|
||||
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& chr) {
|
||||
if (chr == "enter") return ui::VKEY_RETURN;
|
||||
if (chr == "backspace") return ui::VKEY_BACK;
|
||||
if (chr == "delete") return ui::VKEY_DELETE;
|
||||
if (chr == "tab") return ui::VKEY_TAB;
|
||||
if (chr == "escape") return ui::VKEY_ESCAPE;
|
||||
if (chr == "control") return ui::VKEY_CONTROL;
|
||||
if (chr == "alt") return ui::VKEY_MENU;
|
||||
if (chr == "shift") return ui::VKEY_SHIFT;
|
||||
if (chr == "end") return ui::VKEY_END;
|
||||
if (chr == "home") return ui::VKEY_HOME;
|
||||
if (chr == "insert") return ui::VKEY_INSERT;
|
||||
if (chr == "left") return ui::VKEY_LEFT;
|
||||
if (chr == "up") return ui::VKEY_UP;
|
||||
if (chr == "right") return ui::VKEY_RIGHT;
|
||||
if (chr == "down") return ui::VKEY_DOWN;
|
||||
if (chr == "pageup") return ui::VKEY_PRIOR;
|
||||
if (chr == "pagedown") return ui::VKEY_NEXT;
|
||||
if (chr == "printscreen") return ui::VKEY_SNAPSHOT;
|
||||
|
||||
return ui::VKEY_UNKNOWN;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_COMMON_KEYBOAD_UTIL_H_
|
||||
#define ATOM_COMMON_KEYBOAD_UTIL_H_
|
||||
|
||||
#include <string>
|
||||
#include "ui/events/keycodes/keyboard_codes.h"
|
||||
#include "base/strings/string_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Return key code of the char, and also determine whether the SHIFT key is
|
||||
// pressed.
|
||||
ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted);
|
||||
|
||||
// Return key code of the char from a string representation of the char
|
||||
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& chr);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_COMMON_KEYBOAD_UTIL_H_
|
||||
176
atom/common/keyboard_util.cc
Normal file
176
atom/common/keyboard_util.cc
Normal file
@@ -0,0 +1,176 @@
|
||||
// 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 <string>
|
||||
|
||||
#include "atom/common/keyboard_util.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// Return key code of the char, and also determine whether the SHIFT key is
|
||||
// pressed.
|
||||
ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted) {
|
||||
c = base::ToLowerASCII(c);
|
||||
*shifted = false;
|
||||
switch (c) {
|
||||
case 0x08: return ui::VKEY_BACK;
|
||||
case 0x7F: return ui::VKEY_DELETE;
|
||||
case 0x09: return ui::VKEY_TAB;
|
||||
case 0x0D: return ui::VKEY_RETURN;
|
||||
case 0x1B: return ui::VKEY_ESCAPE;
|
||||
case ' ': return ui::VKEY_SPACE;
|
||||
|
||||
case 'a': return ui::VKEY_A;
|
||||
case 'b': return ui::VKEY_B;
|
||||
case 'c': return ui::VKEY_C;
|
||||
case 'd': return ui::VKEY_D;
|
||||
case 'e': return ui::VKEY_E;
|
||||
case 'f': return ui::VKEY_F;
|
||||
case 'g': return ui::VKEY_G;
|
||||
case 'h': return ui::VKEY_H;
|
||||
case 'i': return ui::VKEY_I;
|
||||
case 'j': return ui::VKEY_J;
|
||||
case 'k': return ui::VKEY_K;
|
||||
case 'l': return ui::VKEY_L;
|
||||
case 'm': return ui::VKEY_M;
|
||||
case 'n': return ui::VKEY_N;
|
||||
case 'o': return ui::VKEY_O;
|
||||
case 'p': return ui::VKEY_P;
|
||||
case 'q': return ui::VKEY_Q;
|
||||
case 'r': return ui::VKEY_R;
|
||||
case 's': return ui::VKEY_S;
|
||||
case 't': return ui::VKEY_T;
|
||||
case 'u': return ui::VKEY_U;
|
||||
case 'v': return ui::VKEY_V;
|
||||
case 'w': return ui::VKEY_W;
|
||||
case 'x': return ui::VKEY_X;
|
||||
case 'y': return ui::VKEY_Y;
|
||||
case 'z': return ui::VKEY_Z;
|
||||
|
||||
case ')': *shifted = true; case '0': return ui::VKEY_0;
|
||||
case '!': *shifted = true; case '1': return ui::VKEY_1;
|
||||
case '@': *shifted = true; case '2': return ui::VKEY_2;
|
||||
case '#': *shifted = true; case '3': return ui::VKEY_3;
|
||||
case '$': *shifted = true; case '4': return ui::VKEY_4;
|
||||
case '%': *shifted = true; case '5': return ui::VKEY_5;
|
||||
case '^': *shifted = true; case '6': return ui::VKEY_6;
|
||||
case '&': *shifted = true; case '7': return ui::VKEY_7;
|
||||
case '*': *shifted = true; case '8': return ui::VKEY_8;
|
||||
case '(': *shifted = true; case '9': return ui::VKEY_9;
|
||||
|
||||
case ':': *shifted = true; case ';': return ui::VKEY_OEM_1;
|
||||
case '+': *shifted = true; case '=': return ui::VKEY_OEM_PLUS;
|
||||
case '<': *shifted = true; case ',': return ui::VKEY_OEM_COMMA;
|
||||
case '_': *shifted = true; case '-': return ui::VKEY_OEM_MINUS;
|
||||
case '>': *shifted = true; case '.': return ui::VKEY_OEM_PERIOD;
|
||||
case '?': *shifted = true; case '/': return ui::VKEY_OEM_2;
|
||||
case '~': *shifted = true; case '`': return ui::VKEY_OEM_3;
|
||||
case '{': *shifted = true; case '[': return ui::VKEY_OEM_4;
|
||||
case '|': *shifted = true; case '\\': return ui::VKEY_OEM_5;
|
||||
case '}': *shifted = true; case ']': return ui::VKEY_OEM_6;
|
||||
case '"': *shifted = true; case '\'': return ui::VKEY_OEM_7;
|
||||
|
||||
default: return ui::VKEY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// Return key code represented by |str|.
|
||||
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& s,
|
||||
bool* shifted) {
|
||||
std::string str = base::ToLowerASCII(s);
|
||||
if (str == "ctrl" || str == "control") {
|
||||
return ui::VKEY_CONTROL;
|
||||
} else if (str == "super" || str == "cmd" || str == "command" ||
|
||||
str == "meta") {
|
||||
return ui::VKEY_COMMAND;
|
||||
} else if (str == "commandorcontrol" || str == "cmdorctrl") {
|
||||
#if defined(OS_MACOSX)
|
||||
return ui::VKEY_COMMAND;
|
||||
#else
|
||||
return ui::VKEY_CONTROL;
|
||||
#endif
|
||||
} else if (str == "alt" || str == "option") {
|
||||
return ui::VKEY_MENU;
|
||||
} else if (str == "shift") {
|
||||
return ui::VKEY_SHIFT;
|
||||
} else if (str == "altgr") {
|
||||
return ui::VKEY_ALTGR;
|
||||
} else if (str == "plus") {
|
||||
*shifted = true;
|
||||
return ui::VKEY_OEM_PLUS;
|
||||
} else if (str == "tab") {
|
||||
return ui::VKEY_TAB;
|
||||
} else if (str == "space") {
|
||||
return ui::VKEY_SPACE;
|
||||
} else if (str == "backspace") {
|
||||
return ui::VKEY_BACK;
|
||||
} else if (str == "delete") {
|
||||
return ui::VKEY_DELETE;
|
||||
} else if (str == "insert") {
|
||||
return ui::VKEY_INSERT;
|
||||
} else if (str == "enter" || str == "return") {
|
||||
return ui::VKEY_RETURN;
|
||||
} else if (str == "up") {
|
||||
return ui::VKEY_UP;
|
||||
} else if (str == "down") {
|
||||
return ui::VKEY_DOWN;
|
||||
} else if (str == "left") {
|
||||
return ui::VKEY_LEFT;
|
||||
} else if (str == "right") {
|
||||
return ui::VKEY_RIGHT;
|
||||
} else if (str == "home") {
|
||||
return ui::VKEY_HOME;
|
||||
} else if (str == "end") {
|
||||
return ui::VKEY_END;
|
||||
} else if (str == "pageup") {
|
||||
return ui::VKEY_PRIOR;
|
||||
} else if (str == "pagedown") {
|
||||
return ui::VKEY_NEXT;
|
||||
} else if (str == "esc" || str == "escape") {
|
||||
return ui::VKEY_ESCAPE;
|
||||
} else if (str == "volumemute") {
|
||||
return ui::VKEY_VOLUME_MUTE;
|
||||
} else if (str == "volumeup") {
|
||||
return ui::VKEY_VOLUME_UP;
|
||||
} else if (str == "volumedown") {
|
||||
return ui::VKEY_VOLUME_DOWN;
|
||||
} else if (str == "medianexttrack") {
|
||||
return ui::VKEY_MEDIA_NEXT_TRACK;
|
||||
} else if (str == "mediaprevioustrack") {
|
||||
return ui::VKEY_MEDIA_PREV_TRACK;
|
||||
} else if (str == "mediastop") {
|
||||
return ui::VKEY_MEDIA_STOP;
|
||||
} else if (str == "mediaplaypause") {
|
||||
return ui::VKEY_MEDIA_PLAY_PAUSE;
|
||||
} else if (str == "printscreen") {
|
||||
return ui::VKEY_SNAPSHOT;
|
||||
} else if (str.size() > 1 && str[0] == 'f') {
|
||||
// F1 - F24.
|
||||
int n;
|
||||
if (base::StringToInt(str.c_str() + 1, &n) && n > 0 && n < 25) {
|
||||
return static_cast<ui::KeyboardCode>(ui::VKEY_F1 + n - 1);
|
||||
} else {
|
||||
LOG(WARNING) << str << "is not available on keyboard";
|
||||
return ui::VKEY_UNKNOWN;
|
||||
}
|
||||
} else {
|
||||
LOG(WARNING) << "Invalid accelerator token: " << str;
|
||||
return ui::VKEY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ui::KeyboardCode KeyboardCodeFromStr(const std::string& str, bool* shifted) {
|
||||
if (str.size() == 1)
|
||||
return KeyboardCodeFromCharCode(str[0], shifted);
|
||||
else
|
||||
return KeyboardCodeFromKeyIdentifier(str, shifted);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
20
atom/common/keyboard_util.h
Normal file
20
atom/common/keyboard_util.h
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_COMMON_KEYBOARD_UTIL_H_
|
||||
#define ATOM_COMMON_KEYBOARD_UTIL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ui/events/keycodes/keyboard_codes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Return key code of the |str|, and also determine whether the SHIFT key is
|
||||
// pressed.
|
||||
ui::KeyboardCode KeyboardCodeFromStr(const std::string& str, bool* shifted);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_COMMON_KEYBOARD_UTIL_H_
|
||||
62
atom/common/mouse_util.cc
Normal file
62
atom/common/mouse_util.cc
Normal file
@@ -0,0 +1,62 @@
|
||||
// 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 <string>
|
||||
#include "atom/common/mouse_util.h"
|
||||
|
||||
using Cursor = blink::WebCursorInfo::Type;
|
||||
|
||||
namespace atom {
|
||||
|
||||
std::string CursorTypeToString(const content::WebCursor::CursorInfo& info) {
|
||||
switch (info.type) {
|
||||
case Cursor::TypePointer: return "default";
|
||||
case Cursor::TypeCross: return "crosshair";
|
||||
case Cursor::TypeHand: return "pointer";
|
||||
case Cursor::TypeIBeam: return "text";
|
||||
case Cursor::TypeWait: return "wait";
|
||||
case Cursor::TypeHelp: return "help";
|
||||
case Cursor::TypeEastResize: return "e-resize";
|
||||
case Cursor::TypeNorthResize: return "n-resize";
|
||||
case Cursor::TypeNorthEastResize: return "ne-resize";
|
||||
case Cursor::TypeNorthWestResize: return "nw-resize";
|
||||
case Cursor::TypeSouthResize: return "s-resize";
|
||||
case Cursor::TypeSouthEastResize: return "se-resize";
|
||||
case Cursor::TypeSouthWestResize: return "sw-resize";
|
||||
case Cursor::TypeWestResize: return "w-resize";
|
||||
case Cursor::TypeNorthSouthResize: return "ns-resize";
|
||||
case Cursor::TypeEastWestResize: return "ew-resize";
|
||||
case Cursor::TypeNorthEastSouthWestResize: return "nesw-resize";
|
||||
case Cursor::TypeNorthWestSouthEastResize: return "nwse-resize";
|
||||
case Cursor::TypeColumnResize: return "col-resize";
|
||||
case Cursor::TypeRowResize: return "row-resize";
|
||||
case Cursor::TypeMiddlePanning: return "m-panning";
|
||||
case Cursor::TypeEastPanning: return "e-panning";
|
||||
case Cursor::TypeNorthPanning: return "n-panning";
|
||||
case Cursor::TypeNorthEastPanning: return "ne-panning";
|
||||
case Cursor::TypeNorthWestPanning: return "nw-panning";
|
||||
case Cursor::TypeSouthPanning: return "s-panning";
|
||||
case Cursor::TypeSouthEastPanning: return "se-panning";
|
||||
case Cursor::TypeSouthWestPanning: return "sw-panning";
|
||||
case Cursor::TypeWestPanning: return "w-panning";
|
||||
case Cursor::TypeMove: return "move";
|
||||
case Cursor::TypeVerticalText: return "vertical-text";
|
||||
case Cursor::TypeCell: return "cell";
|
||||
case Cursor::TypeContextMenu: return "context-menu";
|
||||
case Cursor::TypeAlias: return "alias";
|
||||
case Cursor::TypeProgress: return "progress";
|
||||
case Cursor::TypeNoDrop: return "nodrop";
|
||||
case Cursor::TypeCopy: return "copy";
|
||||
case Cursor::TypeNone: return "none";
|
||||
case Cursor::TypeNotAllowed: return "not-allowed";
|
||||
case Cursor::TypeZoomIn: return "zoom-in";
|
||||
case Cursor::TypeZoomOut: return "zoom-out";
|
||||
case Cursor::TypeGrab: return "grab";
|
||||
case Cursor::TypeGrabbing: return "grabbing";
|
||||
case Cursor::TypeCustom: return "custom";
|
||||
default: return "default";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
36
atom/common/mouse_util.h
Normal file
36
atom/common/mouse_util.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_COMMON_MOUSE_UTIL_H_
|
||||
#define ATOM_COMMON_MOUSE_UTIL_H_
|
||||
|
||||
#include <string>
|
||||
#include "content/common/cursors/webcursor.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
|
||||
// IPC macros similar to the already existing ones in the chromium source.
|
||||
// We need these to listen to the cursor change IPC message while still
|
||||
// letting chromium handle the actual cursor change by setting handled = false.
|
||||
#define IPC_MESSAGE_HANDLER_CODE(msg_class, member_func, code) \
|
||||
IPC_MESSAGE_FORWARD_CODE(msg_class, this, \
|
||||
_IpcMessageHandlerClass::member_func, code)
|
||||
|
||||
#define IPC_MESSAGE_FORWARD_CODE(msg_class, obj, member_func, code) \
|
||||
case msg_class::ID: { \
|
||||
TRACK_RUN_IN_THIS_SCOPED_REGION(member_func); \
|
||||
if (!msg_class::Dispatch(&ipc_message__, obj, this, param__, \
|
||||
&member_func)) \
|
||||
ipc_message__.set_dispatch_error(); \
|
||||
code; \
|
||||
} \
|
||||
break;
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Returns the cursor's type as a string.
|
||||
std::string CursorTypeToString(const content::WebCursor::CursorInfo& info);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_COMMON_MOUSE_UTIL_H_
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/keyboad_util.h"
|
||||
#include "atom/common/keyboard_util.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/public/browser/native_web_keyboard_event.h"
|
||||
@@ -159,25 +159,22 @@ bool Converter<blink::WebKeyboardEvent>::FromV8(
|
||||
return false;
|
||||
if (!ConvertFromV8(isolate, val, static_cast<blink::WebInputEvent*>(out)))
|
||||
return false;
|
||||
base::char16 code;
|
||||
std::string identifier;
|
||||
bool shifted = false;
|
||||
|
||||
if (dict.Get("keyCode", &code))
|
||||
out->windowsKeyCode = atom::KeyboardCodeFromCharCode(code, &shifted);
|
||||
else if (dict.Get("keyCode", &identifier))
|
||||
out->windowsKeyCode = atom::KeyboardCodeFromKeyIdentifier(
|
||||
base::ToLowerASCII(identifier));
|
||||
std::string str;
|
||||
bool shifted = false;
|
||||
if (dict.Get("keyCode", &str))
|
||||
out->windowsKeyCode = atom::KeyboardCodeFromStr(str, &shifted);
|
||||
else
|
||||
return false;
|
||||
|
||||
if (shifted)
|
||||
out->modifiers |= blink::WebInputEvent::ShiftKey;
|
||||
out->setKeyIdentifierFromWindowsKeyCode();
|
||||
if (out->type == blink::WebInputEvent::Char ||
|
||||
out->type == blink::WebInputEvent::RawKeyDown) {
|
||||
out->text[0] = code;
|
||||
out->unmodifiedText[0] = code;
|
||||
if ((out->type == blink::WebInputEvent::Char ||
|
||||
out->type == blink::WebInputEvent::RawKeyDown) &&
|
||||
str.size() == 1) {
|
||||
out->text[0] = str[0];
|
||||
out->unmodifiedText[0] = str[0];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/web_contents_permission_helper.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
@@ -98,6 +100,55 @@ v8::Local<v8::Value> Converter<ContextMenuParamsWithWebContents>::ToV8(
|
||||
return mate::ConvertToV8(isolate, dict);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Converter<content::PermissionStatus>::FromV8(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
content::PermissionStatus* out) {
|
||||
bool result;
|
||||
if (!ConvertFromV8(isolate, val, &result))
|
||||
return false;
|
||||
|
||||
if (result)
|
||||
*out = content::PERMISSION_STATUS_GRANTED;
|
||||
else
|
||||
*out = content::PERMISSION_STATUS_DENIED;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> Converter<content::PermissionType>::ToV8(
|
||||
v8::Isolate* isolate, const content::PermissionType& val) {
|
||||
using PermissionType = atom::WebContentsPermissionHelper::PermissionType;
|
||||
switch (val) {
|
||||
case content::PermissionType::MIDI_SYSEX:
|
||||
return StringToV8(isolate, "midiSysex");
|
||||
case content::PermissionType::PUSH_MESSAGING:
|
||||
return StringToV8(isolate, "pushMessaging");
|
||||
case content::PermissionType::NOTIFICATIONS:
|
||||
return StringToV8(isolate, "notifications");
|
||||
case content::PermissionType::GEOLOCATION:
|
||||
return StringToV8(isolate, "geolocation");
|
||||
case content::PermissionType::AUDIO_CAPTURE:
|
||||
case content::PermissionType::VIDEO_CAPTURE:
|
||||
return StringToV8(isolate, "media");
|
||||
case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
|
||||
return StringToV8(isolate, "mediaKeySystem");
|
||||
case content::PermissionType::MIDI:
|
||||
return StringToV8(isolate, "midi");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (val == (content::PermissionType)(PermissionType::POINTER_LOCK))
|
||||
return StringToV8(isolate, "pointerLock");
|
||||
else if (val == (content::PermissionType)(PermissionType::FULLSCREEN))
|
||||
return StringToV8(isolate, "fullscreen");
|
||||
|
||||
return StringToV8(isolate, "unknown");
|
||||
}
|
||||
|
||||
// static
|
||||
bool Converter<content::StopFindAction>::FromV8(
|
||||
v8::Isolate* isolate,
|
||||
@@ -119,4 +170,12 @@ bool Converter<content::StopFindAction>::FromV8(
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> Converter<content::WebContents*>::ToV8(
|
||||
v8::Isolate* isolate, content::WebContents* val) {
|
||||
if (!val)
|
||||
return v8::Null(isolate);
|
||||
return atom::api::WebContents::CreateFrom(isolate, val).ToV8();
|
||||
}
|
||||
|
||||
} // namespace mate
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "content/public/browser/permission_type.h"
|
||||
#include "content/public/common/menu_item.h"
|
||||
#include "content/public/common/permission_status.mojom.h"
|
||||
#include "content/public/common/stop_find_action.h"
|
||||
#include "native_mate/converter.h"
|
||||
|
||||
@@ -33,12 +35,30 @@ struct Converter<ContextMenuParamsWithWebContents> {
|
||||
const ContextMenuParamsWithWebContents& val);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<content::PermissionStatus> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
content::PermissionStatus* out);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<content::PermissionType> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const content::PermissionType& val);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<content::StopFindAction> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
content::StopFindAction* out);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<content::WebContents*> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
content::WebContents* val);
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_
|
||||
|
||||
@@ -27,7 +27,9 @@ v8::Local<v8::Value> Converter<const net::URLRequest*>::ToV8(
|
||||
v8::Isolate* isolate, const net::URLRequest* val) {
|
||||
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
|
||||
dict->SetString("method", val->method());
|
||||
dict->SetStringWithoutPathExpansion("url", val->url().spec());
|
||||
std::string url;
|
||||
if (!val->url_chain().empty()) url = val->url().spec();
|
||||
dict->SetStringWithoutPathExpansion("url", url);
|
||||
dict->SetString("referrer", val->referrer());
|
||||
scoped_ptr<base::ListValue> list(new base::ListValue);
|
||||
atom::GetUploadData(list.get(), val);
|
||||
|
||||
@@ -76,15 +76,10 @@ class V8ValueConverter::FromV8ValueState {
|
||||
};
|
||||
|
||||
V8ValueConverter::V8ValueConverter()
|
||||
: date_allowed_(false),
|
||||
reg_exp_allowed_(false),
|
||||
: reg_exp_allowed_(false),
|
||||
function_allowed_(false),
|
||||
strip_null_from_objects_(false) {}
|
||||
|
||||
void V8ValueConverter::SetDateAllowed(bool val) {
|
||||
date_allowed_ = val;
|
||||
}
|
||||
|
||||
void V8ValueConverter::SetRegExpAllowed(bool val) {
|
||||
reg_exp_allowed_ = val;
|
||||
}
|
||||
@@ -243,12 +238,17 @@ base::Value* V8ValueConverter::FromV8ValueImpl(
|
||||
return NULL;
|
||||
|
||||
if (val->IsDate()) {
|
||||
if (!date_allowed_)
|
||||
// JSON.stringify would convert this to a string, but an object is more
|
||||
// consistent within this class.
|
||||
return FromV8Object(val->ToObject(), state, isolate);
|
||||
v8::Date* date = v8::Date::Cast(*val);
|
||||
return new base::FundamentalValue(date->NumberValue() / 1000.0);
|
||||
v8::Local<v8::Value> toISOString =
|
||||
date->Get(v8::String::NewFromUtf8(isolate, "toISOString"));
|
||||
if (toISOString->IsFunction()) {
|
||||
v8::Local<v8::Value> result =
|
||||
toISOString.As<v8::Function>()->Call(val, 0, nullptr);
|
||||
if (!result.IsEmpty()) {
|
||||
v8::String::Utf8Value utf8(result->ToString());
|
||||
return new base::StringValue(std::string(*utf8, utf8.length()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (val->IsRegExp()) {
|
||||
|
||||
@@ -22,7 +22,6 @@ class V8ValueConverter {
|
||||
public:
|
||||
V8ValueConverter();
|
||||
|
||||
void SetDateAllowed(bool val);
|
||||
void SetRegExpAllowed(bool val);
|
||||
void SetFunctionAllowed(bool val);
|
||||
void SetStripNullFromObjects(bool val);
|
||||
@@ -58,9 +57,6 @@ class V8ValueConverter {
|
||||
FromV8ValueState* state,
|
||||
v8::Isolate* isolate) const;
|
||||
|
||||
// If true, we will convert Date JavaScript objects to doubles.
|
||||
bool date_allowed_;
|
||||
|
||||
// If true, we will convert RegExp JavaScript objects to string.
|
||||
bool reg_exp_allowed_;
|
||||
|
||||
|
||||
@@ -165,7 +165,6 @@ node::Environment* NodeBindings::CreateEnvironment(
|
||||
base::FilePath script_path =
|
||||
resources_path.Append(FILE_PATH_LITERAL("atom.asar"))
|
||||
.Append(process_type)
|
||||
.Append(FILE_PATH_LITERAL("lib"))
|
||||
.Append(FILE_PATH_LITERAL("init.js"));
|
||||
std::string script_path_str = script_path.AsUTF8Unsafe();
|
||||
args.insert(args.begin() + 1, script_path_str.c_str());
|
||||
|
||||
@@ -23,7 +23,7 @@ void OpenItem(const base::FilePath& full_path);
|
||||
|
||||
// Open the given external protocol URL in the desktop's default manner.
|
||||
// (For example, mailto: URLs in the default mail user agent.)
|
||||
bool OpenExternal(const GURL& url);
|
||||
bool OpenExternal(const GURL& url, bool activate);
|
||||
|
||||
// Move a file to trash.
|
||||
bool MoveItemToTrash(const base::FilePath& full_path);
|
||||
|
||||
@@ -64,7 +64,7 @@ void OpenItem(const base::FilePath& full_path) {
|
||||
XDGOpen(full_path.value());
|
||||
}
|
||||
|
||||
bool OpenExternal(const GURL& url) {
|
||||
bool OpenExternal(const GURL& url, bool activate) {
|
||||
if (url.SchemeIs("mailto"))
|
||||
return XDGEmail(url.spec());
|
||||
else
|
||||
|
||||
@@ -119,7 +119,7 @@ void OpenItem(const base::FilePath& full_path) {
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenExternal(const GURL& url) {
|
||||
bool OpenExternal(const GURL& url, bool activate) {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
NSURL* ns_url = net::NSURLWithGURL(url);
|
||||
if (!ns_url) {
|
||||
@@ -136,7 +136,15 @@ bool OpenExternal(const GURL& url) {
|
||||
}
|
||||
CFRelease(openingApp); // NOT A BUG; LSGetApplicationForURL retains for us
|
||||
|
||||
return [[NSWorkspace sharedWorkspace] openURL:ns_url];
|
||||
NSUInteger launchOptions = NSWorkspaceLaunchDefault;
|
||||
if (!activate)
|
||||
launchOptions |= NSWorkspaceLaunchWithoutActivation;
|
||||
|
||||
return [[NSWorkspace sharedWorkspace] openURLs: @[ns_url]
|
||||
withAppBundleIdentifier: nil
|
||||
options: launchOptions
|
||||
additionalEventParamDescriptor: NULL
|
||||
launchIdentifiers: NULL];
|
||||
}
|
||||
|
||||
bool MoveItemToTrash(const base::FilePath& full_path) {
|
||||
|
||||
@@ -301,7 +301,7 @@ void OpenItem(const base::FilePath& full_path) {
|
||||
ui::win::OpenFileViaShell(full_path);
|
||||
}
|
||||
|
||||
bool OpenExternal(const GURL& url) {
|
||||
bool OpenExternal(const GURL& url, bool activate) {
|
||||
// Quote the input scheme to be sure that the command does not have
|
||||
// parameters unexpected by the external program. This url should already
|
||||
// have been escaped.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "third_party/WebKit/public/web/WebDocument.h"
|
||||
#include "third_party/WebKit/public/web/WebLocalFrame.h"
|
||||
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
|
||||
#include "third_party/WebKit/public/web/WebScriptExecutionCallback.h"
|
||||
#include "third_party/WebKit/public/web/WebScriptSource.h"
|
||||
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
|
||||
#include "third_party/WebKit/public/web/WebView.h"
|
||||
@@ -26,6 +26,34 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
class ScriptExecutionCallback : public blink::WebScriptExecutionCallback {
|
||||
public:
|
||||
using CompletionCallback =
|
||||
base::Callback<void(
|
||||
const v8::Local<v8::Value>& result)>;
|
||||
|
||||
explicit ScriptExecutionCallback(const CompletionCallback& callback)
|
||||
: callback_(callback) {}
|
||||
~ScriptExecutionCallback() {}
|
||||
|
||||
void completed(
|
||||
const blink::WebVector<v8::Local<v8::Value>>& result) override {
|
||||
if (!callback_.is_null() && !result.isEmpty() && !result[0].IsEmpty())
|
||||
// Right now only single results per frame is supported.
|
||||
callback_.Run(result[0]);
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
CompletionCallback callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScriptExecutionCallback);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
WebFrame::WebFrame()
|
||||
: web_frame_(blink::WebLocalFrame::frameForCurrentContext()) {
|
||||
}
|
||||
@@ -124,9 +152,14 @@ void WebFrame::ExecuteJavaScript(const base::string16& code,
|
||||
mate::Arguments* args) {
|
||||
bool has_user_gesture = false;
|
||||
args->GetNext(&has_user_gesture);
|
||||
scoped_ptr<blink::WebScopedUserGesture> gesture(
|
||||
has_user_gesture ? new blink::WebScopedUserGesture : nullptr);
|
||||
web_frame_->executeScriptAndReturnValue(blink::WebScriptSource(code));
|
||||
ScriptExecutionCallback::CompletionCallback completion_callback;
|
||||
args->GetNext(&completion_callback);
|
||||
scoped_ptr<blink::WebScriptExecutionCallback> callback(
|
||||
new ScriptExecutionCallback(completion_callback));
|
||||
web_frame_->requestExecuteScriptAndReturnValue(
|
||||
blink::WebScriptSource(code),
|
||||
has_user_gesture,
|
||||
callback.release());
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder(
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
@@ -47,17 +48,27 @@ class AtomRenderFrameObserver : public content::RenderFrameObserver {
|
||||
AtomRenderFrameObserver(content::RenderFrame* frame,
|
||||
AtomRendererClient* renderer_client)
|
||||
: content::RenderFrameObserver(frame),
|
||||
world_id_(-1),
|
||||
renderer_client_(renderer_client) {}
|
||||
|
||||
// content::RenderFrameObserver:
|
||||
void DidCreateScriptContext(v8::Handle<v8::Context> context,
|
||||
int extension_group,
|
||||
int world_id) {
|
||||
renderer_client_->DidCreateScriptContext(
|
||||
render_frame()->GetWebFrame(), context);
|
||||
int world_id) override {
|
||||
if (world_id_ != -1 && world_id_ != world_id)
|
||||
return;
|
||||
world_id_ = world_id;
|
||||
renderer_client_->DidCreateScriptContext(context);
|
||||
}
|
||||
void WillReleaseScriptContext(v8::Local<v8::Context> context,
|
||||
int world_id) override {
|
||||
if (world_id_ != world_id)
|
||||
return;
|
||||
renderer_client_->WillReleaseScriptContext(context);
|
||||
}
|
||||
|
||||
private:
|
||||
int world_id_;
|
||||
AtomRendererClient* renderer_client_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomRenderFrameObserver);
|
||||
@@ -108,10 +119,15 @@ void AtomRendererClient::RenderThreadStarted() {
|
||||
void AtomRendererClient::RenderFrameCreated(
|
||||
content::RenderFrame* render_frame) {
|
||||
new PepperHelper(render_frame);
|
||||
new AtomRenderFrameObserver(render_frame, this);
|
||||
|
||||
// Allow file scheme to handle service worker by default.
|
||||
blink::WebSecurityPolicy::registerURLSchemeAsAllowingServiceWorkers("file");
|
||||
|
||||
// Only insert node integration for the main frame.
|
||||
if (!render_frame->IsMainFrame())
|
||||
return;
|
||||
|
||||
new AtomRenderFrameObserver(render_frame, this);
|
||||
}
|
||||
|
||||
void AtomRendererClient::RenderViewCreated(content::RenderView* render_view) {
|
||||
@@ -139,12 +155,7 @@ bool AtomRendererClient::OverrideCreatePlugin(
|
||||
}
|
||||
|
||||
void AtomRendererClient::DidCreateScriptContext(
|
||||
blink::WebFrame* frame,
|
||||
v8::Handle<v8::Context> context) {
|
||||
// Only insert node integration for the main frame.
|
||||
if (frame->parent())
|
||||
return;
|
||||
|
||||
// Give the node loop a run to make sure everything is ready.
|
||||
node_bindings_->RunMessageLoop();
|
||||
|
||||
@@ -162,6 +173,12 @@ void AtomRendererClient::DidCreateScriptContext(
|
||||
node_bindings_->LoadEnvironment(env);
|
||||
}
|
||||
|
||||
void AtomRendererClient::WillReleaseScriptContext(
|
||||
v8::Handle<v8::Context> context) {
|
||||
node::Environment* env = node::Environment::GetCurrent(context);
|
||||
mate::EmitEvent(env->isolate(), env->process_object(), "exit");
|
||||
}
|
||||
|
||||
bool AtomRendererClient::ShouldFork(blink::WebLocalFrame* frame,
|
||||
const GURL& url,
|
||||
const std::string& http_method,
|
||||
|
||||
@@ -22,8 +22,8 @@ class AtomRendererClient : public content::ContentRendererClient,
|
||||
AtomRendererClient();
|
||||
virtual ~AtomRendererClient();
|
||||
|
||||
void DidCreateScriptContext(blink::WebFrame* frame,
|
||||
v8::Handle<v8::Context> context);
|
||||
void DidCreateScriptContext(v8::Handle<v8::Context> context);
|
||||
void WillReleaseScriptContext(v8::Handle<v8::Context> context);
|
||||
|
||||
private:
|
||||
enum NodeIntegration {
|
||||
|
||||
@@ -32,7 +32,7 @@ enum NotificationType {
|
||||
NOTIFICATION_BROWSER_CLOSING,
|
||||
|
||||
// This message is sent after a window has been closed. The source is a
|
||||
// Source<Browser> containing the affected Browser. No details are exptected.
|
||||
// Source<Browser> containing the affected Browser. No details are expected.
|
||||
NOTIFICATION_BROWSER_CLOSED,
|
||||
|
||||
// This message is sent when closing a browser has been cancelled, either by
|
||||
@@ -411,7 +411,7 @@ enum NotificationType {
|
||||
// the source is a Profile.
|
||||
NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
|
||||
|
||||
// An error occured while attempting to load an extension. The details are a
|
||||
// An error occurred while attempting to load an extension. The details are a
|
||||
// string with details about why the load failed.
|
||||
NOTIFICATION_EXTENSION_LOAD_ERROR,
|
||||
|
||||
@@ -434,7 +434,7 @@ enum NotificationType {
|
||||
// The details are an InstalledExtensionInfo, and the source is a Profile.
|
||||
NOTIFICATION_EXTENSION_INSTALLED,
|
||||
|
||||
// An error occured during extension install. The details are a string with
|
||||
// An error occurred during extension install. The details are a string with
|
||||
// details about why the install failed.
|
||||
NOTIFICATION_EXTENSION_INSTALL_ERROR,
|
||||
|
||||
@@ -625,7 +625,7 @@ enum NotificationType {
|
||||
// TabSpecificContentSettings object, there are no details.
|
||||
NOTIFICATION_COLLECTED_COOKIES_SHOWN,
|
||||
|
||||
// Sent when a non-default setting in the the notification content settings
|
||||
// Sent when a non-default setting in the notification content settings
|
||||
// map has changed. The source is the DesktopNotificationService, the
|
||||
// details are None.
|
||||
NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
|
||||
@@ -776,7 +776,7 @@ enum NotificationType {
|
||||
NOTIFICATION_USER_LIST_CHANGED,
|
||||
|
||||
// Sent when the screen lock state has changed. The source is
|
||||
// ScreenLocker and the details is a bool specifing that the
|
||||
// ScreenLocker and the details is a bool specifying that the
|
||||
// screen is locked. When details is a false, the source object
|
||||
// is being deleted, so the receiver shouldn't use the screen locker
|
||||
// object.
|
||||
@@ -838,7 +838,7 @@ enum NotificationType {
|
||||
// which was installed.
|
||||
NOTIFICATION_APP_INSTALLED_TO_NTP,
|
||||
|
||||
// Similar to NOTIFICATION_APP_INSTALLED_TO_NTP but used to nofity ash AppList
|
||||
// Similar to NOTIFICATION_APP_INSTALLED_TO_NTP but used to notify ash AppList
|
||||
// about installed app. Source is the profile in which the app is installed
|
||||
// and Details is the string ID of the extension.
|
||||
NOTIFICATION_APP_INSTALLED_TO_APPLIST,
|
||||
|
||||
23
default_app/default_app.js
Normal file
23
default_app/default_app.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const electron = require('electron');
|
||||
const app = electron.app;
|
||||
const BrowserWindow = electron.BrowserWindow;
|
||||
|
||||
var mainWindow = null;
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function() {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
exports.load = function(appUrl) {
|
||||
app.on('ready', function() {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
autoHideMenuBar: true,
|
||||
useContentSize: true,
|
||||
});
|
||||
mainWindow.loadURL(appUrl);
|
||||
mainWindow.focus();
|
||||
});
|
||||
};
|
||||
@@ -3,31 +3,39 @@
|
||||
<title>Electron</title>
|
||||
<style>
|
||||
body {
|
||||
color: #555;
|
||||
font-family: 'Open Sans',Helvetica,Arial,sans-serif;
|
||||
padding: 30px;
|
||||
color: #45828E;
|
||||
background-color: #A5ECFA;
|
||||
font-family: 'Helvetica Neue', 'Open Sans', Helvetica, Arial, sans-serif;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 15px 30px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #2b6cc2;
|
||||
font-family: "Crimson Text",Georgia,serif;
|
||||
background-color: #76C7D7;
|
||||
color: #FAF7F3;
|
||||
font-weight: 400;
|
||||
line-height: 1.1;
|
||||
letter-spacing: -0.015em;
|
||||
padding: 15px 30px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #2b6cc2;
|
||||
color: #39AEC6;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
font-family: "Menlo","Lucida Console",monospace;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #f8f8f8;
|
||||
border: 1px solid #076274;
|
||||
background-color: #076274;
|
||||
color: #C5F3FC;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
@@ -39,19 +47,24 @@
|
||||
padding: 6px 10px;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 1px 4px 1px 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
#holder {
|
||||
border: 4px dashed #ccc;
|
||||
border: 2px dashed #448691;
|
||||
margin: 0 auto;
|
||||
height: 300px;
|
||||
color: #ccc;
|
||||
color: #45828E;
|
||||
font-size: 40px;
|
||||
line-height: 300px;
|
||||
text-align: center;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
#holder.hover {
|
||||
border: 4px dashed #999;
|
||||
color: #eee;
|
||||
background-color: #7BDCEF;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@@ -78,40 +91,47 @@
|
||||
|
||||
<h2>
|
||||
<script>
|
||||
document.write(`Welcome to Electron (v${process.versions.electron})`)
|
||||
document.write(`Welcome to Electron ${process.versions.electron}`)
|
||||
</script>
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
To run your app with Electron, execute the following command under your
|
||||
Console (or Terminal):
|
||||
</p>
|
||||
<div class="container">
|
||||
|
||||
<script>document.write('<pre>' + command + '</pre>')</script>
|
||||
<p>
|
||||
To run your app with Electron, execute the following command in your
|
||||
Console (or Terminal):
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>path-to-your-app</code> should be the path to your own Electron
|
||||
app, you can read the
|
||||
<script>
|
||||
document.write(
|
||||
`<a href='https://github.com/atom/electron/blob/v${process.versions.electron}/docs/tutorial/quick-start.md'>quick start</a>`
|
||||
);
|
||||
</script>
|
||||
guide in Electron's
|
||||
<script>
|
||||
document.write(
|
||||
`<a href='https://github.com/atom/electron/tree/v${process.versions.electron}/docs#readme'>docs</a>`
|
||||
);
|
||||
</script>
|
||||
on how to write one.
|
||||
</p>
|
||||
<script>document.write('<pre>' + command + '</pre>')</script>
|
||||
|
||||
<p>
|
||||
Or you can just drag your app here to run it:
|
||||
</p>
|
||||
<p>
|
||||
The <code>path-to-your-app</code> should be the path to your own Electron
|
||||
app.
|
||||
</p>
|
||||
|
||||
<p>You can read the
|
||||
<script>
|
||||
document.write(
|
||||
`<a href='https://github.com/atom/electron/blob/v${process.versions.electron}/docs/tutorial/quick-start.md'>quick start</a>`
|
||||
);
|
||||
</script>
|
||||
guide in Electron's
|
||||
<script>
|
||||
document.write(
|
||||
`<a href='https://github.com/atom/electron/tree/v${process.versions.electron}/docs#readme'>docs</a>`
|
||||
);
|
||||
</script>
|
||||
to learn how to write one.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Or you can just drag your app here to run it:
|
||||
</p>
|
||||
|
||||
<div id="holder">
|
||||
Drag your app here to run it
|
||||
</div>
|
||||
|
||||
<div id="holder">
|
||||
Drag your app here to run it
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -4,8 +4,9 @@ const dialog = electron.dialog;
|
||||
const shell = electron.shell;
|
||||
const Menu = electron.Menu;
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const url = require('url');
|
||||
|
||||
// Quit when all windows are closed and no other one is listening to this.
|
||||
app.on('window-all-closed', function() {
|
||||
@@ -234,12 +235,10 @@ if (option.modules.length > 0) {
|
||||
require('module')._preloadModules(option.modules);
|
||||
}
|
||||
|
||||
// Start the specified app if there is one specified in command line, otherwise
|
||||
// start the default app.
|
||||
if (option.file && !option.webdriver) {
|
||||
function loadApplicationPackage(packagePath) {
|
||||
try {
|
||||
// Override app name and version.
|
||||
var packagePath = path.resolve(option.file);
|
||||
packagePath = path.resolve(packagePath);
|
||||
var packageJsonPath = path.join(packagePath, 'package.json');
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
var packageJson = JSON.parse(fs.readFileSync(packageJsonPath));
|
||||
@@ -270,20 +269,44 @@ if (option.file && !option.webdriver) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadApplicationByUrl(appUrl) {
|
||||
require('./default_app').load(appUrl);
|
||||
}
|
||||
|
||||
// Start the specified app if there is one specified in command line, otherwise
|
||||
// start the default app.
|
||||
if (option.file && !option.webdriver) {
|
||||
var file = option.file;
|
||||
var protocol = url.parse(file).protocol;
|
||||
var extension = path.extname(file);
|
||||
if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:') {
|
||||
loadApplicationByUrl(file);
|
||||
} else if (extension === '.html' || extension === '.htm') {
|
||||
loadApplicationByUrl('file://' + path.resolve(file));
|
||||
} else {
|
||||
loadApplicationPackage(file);
|
||||
}
|
||||
} else if (option.version) {
|
||||
console.log('v' + process.versions.electron);
|
||||
process.exit(0);
|
||||
} else if (option.help) {
|
||||
var helpMessage = "Electron v" + process.versions.electron + " - Cross Platform Desktop Application Shell\n\n";
|
||||
helpMessage += "Usage: electron [options] [path]\n\n";
|
||||
helpMessage += "A path to an Electron application may be specified. The path must be to \n";
|
||||
helpMessage += "an index.js file or to a folder containing a package.json or index.js file.\n\n";
|
||||
helpMessage += "Options:\n";
|
||||
helpMessage += "A path to an Electron application may be specified.\n";
|
||||
helpMessage += "The path must be one of the following:\n\n";
|
||||
helpMessage += " - index.js file.\n";
|
||||
helpMessage += " - Folder containing a package.json file.\n";
|
||||
helpMessage += " - Folder containing an index.js file.\n";
|
||||
helpMessage += " - .html/.htm file.\n";
|
||||
helpMessage += " - http://, https://, or file:// URL.\n";
|
||||
helpMessage += "\nOptions:\n";
|
||||
helpMessage += " -r, --require Module to preload (option can be repeated)\n";
|
||||
helpMessage += " -h, --help Print this usage message.\n";
|
||||
helpMessage += " -v, --version Print the version.";
|
||||
console.log(helpMessage);
|
||||
process.exit(0);
|
||||
} else {
|
||||
require('./default_app');
|
||||
loadApplicationByUrl('file://' + __dirname + '/index.html');
|
||||
}
|
||||
@@ -61,8 +61,7 @@ de distribuirlo a los usuarios.
|
||||
### Windows
|
||||
|
||||
Puedes renombrar `electron.exe` a cualquier nombre que desees, y editar su ícono
|
||||
y otra información con herramientas como [rcedit](https://github.com/atom/rcedit)
|
||||
o [ResEdit](http://www.resedit.net).
|
||||
y otra información con herramientas como [rcedit](https://github.com/atom/rcedit).
|
||||
|
||||
### OSX
|
||||
|
||||
|
||||
91
docs-translations/fr-FR/README.md
Normal file
91
docs-translations/fr-FR/README.md
Normal file
@@ -0,0 +1,91 @@
|
||||
Vérifiez que vous utilisez la bonne version de la documentation.
|
||||
Le numéro de version devrait faire partie de l'URL de la page.
|
||||
Si ce n'est pas le cas, vous utilisez probablement la documentation d'une
|
||||
branche de développement qui peut contenir des changements API qui ne sont pas
|
||||
compatibles avec votre version d'Electron. Si c'est le cas, vous pouvez changer
|
||||
de version sur la liste [versions disponibles](http://electron.atom.io/docs/),
|
||||
ou, si vous utilisez l'interface de GitHub, ouvrez la liste déroulante "Switch
|
||||
branches/tags" afin de sélectionner le tag de votre version.
|
||||
|
||||
## FAQ
|
||||
|
||||
Avant de créer un ticket, vérifiez que votre problème n'a pas déjà sa réponse
|
||||
dans la FAQ :
|
||||
|
||||
* [Electron FAQ](faq/electron-faq.md)
|
||||
|
||||
## Guides
|
||||
|
||||
* [Plateformes supportées](tutorial/supported-platforms.md)
|
||||
* [Distribution de l'Application](tutorial/application-distribution.md)
|
||||
* [Guide de Soumission Mac App Store](tutorial/mac-app-store-submission-guide.md)
|
||||
* [Créer une archive](tutorial/application-packaging.md)
|
||||
* [Utiliser Modules Natifs de Node](tutorial/using-native-node-modules.md)
|
||||
* [Debugger Processus Principal](tutorial/debugging-main-process.md)
|
||||
* [Utiliser Selenium et WebDriver](tutorial/using-selenium-and-webdriver.md)
|
||||
* [Extension DevTools](tutorial/devtools-extension.md)
|
||||
* [Utiliser le Plugin Pepper Flash](tutorial/using-pepper-flash-plugin.md)
|
||||
* [Utiliser le Plugin Widevine CDM](tutorial/using-widevine-cdm-plugin.md)
|
||||
|
||||
## Tutoriels
|
||||
|
||||
* [Démarrage Rapide](tutorial/quick-start.md)
|
||||
* [Intégration Environnement de Bureau](tutorial/desktop-environment-integration.md)
|
||||
* [Détection des Evènements En ligne/Hors ligne](tutorial/online-offline-events.md)
|
||||
|
||||
## Références API
|
||||
|
||||
* [Synopsis](api/synopsis.md)
|
||||
* [L'objet Process](api/process.md)
|
||||
* [Commandes Chromes Supportées](api/chrome-command-line-switches.md)
|
||||
* [Variables d'Environnement](api/environment-variables.md)
|
||||
|
||||
### Eléments DOM Personnalisés:
|
||||
|
||||
* [Objet `File`](api/file-object.md)
|
||||
* [Tag `<webview>`](api/web-view-tag.md)
|
||||
* [Fonction `window.open`](api/window-open.md)
|
||||
|
||||
### Modules pour le Processus Principal :
|
||||
|
||||
* [app](api/app.md)
|
||||
* [autoUpdater](api/auto-updater.md)
|
||||
* [BrowserWindow](api/browser-window.md)
|
||||
* [contentTracing](api/content-tracing.md)
|
||||
* [dialog](api/dialog.md)
|
||||
* [globalShortcut](api/global-shortcut.md)
|
||||
* [ipcMain](api/ipc-main.md)
|
||||
* [Menu](api/menu.md)
|
||||
* [MenuItem](api/menu-item.md)
|
||||
* [powerMonitor](api/power-monitor.md)
|
||||
* [powerSaveBlocker](api/power-save-blocker.md)
|
||||
* [protocol](api/protocol.md)
|
||||
* [session](api/session.md)
|
||||
* [webContents](api/web-contents.md)
|
||||
* [Tray](api/tray.md)
|
||||
|
||||
### Modules pour le Processus d'Affichage (Page Web) :
|
||||
|
||||
* [desktopCapturer](api/desktop-capturer.md)
|
||||
* [ipcRenderer](api/ipc-renderer.md)
|
||||
* [remote](api/remote.md)
|
||||
* [webFrame](api/web-frame.md)
|
||||
|
||||
### Modules pour les deux Processus :
|
||||
|
||||
* [clipboard](api/clipboard.md)
|
||||
* [crashReporter](api/crash-reporter.md)
|
||||
* [nativeImage](api/native-image.md)
|
||||
* [screen](api/screen.md)
|
||||
* [shell](api/shell.md)
|
||||
|
||||
## Développement
|
||||
|
||||
* [Style de Code](development/coding-style.md)
|
||||
* [Hiérarchie du Code Source](development/source-code-directory-structure.md)
|
||||
* [Différences Techniques par rapport à NW.js (anciennement node-webkit)](development/atom-shell-vs-node-webkit.md)
|
||||
* [Aperçu du Système de Build](development/build-system-overview.md)
|
||||
* [Instructions de Build (OS X)](development/build-instructions-osx.md)
|
||||
* [Instructions de Build (Windows)](development/build-instructions-windows.md)
|
||||
* [Instructions de Build (Linux)](development/build-instructions-linux.md)
|
||||
* [Installer un Serveur de Symbol dans le debugger](development/setting-up-symbol-server.md)
|
||||
129
docs-translations/fr-FR/faq/electron-faq.md
Normal file
129
docs-translations/fr-FR/faq/electron-faq.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Electron FAQ
|
||||
|
||||
## Quand est mise à jour la version de Chrome utilisée par Electron ?
|
||||
|
||||
La version de Chrome qu'utilise Electron est en général mise à jour une ou deux
|
||||
semaines après la sortie d'une nouvelle version stable de Chrome.
|
||||
|
||||
Etant donné que nous n'utilisons que les versions stables de Chrome, si un fix
|
||||
important est en beta ou en dev, nous l'intégrerons à la version que nous
|
||||
utilisons.
|
||||
|
||||
## Quand est mise à jour la version de Node.js utilisée par Electron ?
|
||||
|
||||
Quand une nouvelle version de Node.js sort, nous attendons en général un mois
|
||||
avant de mettre à jour celle que nous utilisons dans Electron. Ceci afin
|
||||
d'éviter les bugs introduits par les nouvelles versions, ce qui arrive très
|
||||
souvent.
|
||||
|
||||
Les nouvelles fonctionnalités de Node.js arrivant la plupart du temps via V8,
|
||||
et Electron utilisant le V8 du navigateur Chrome, la nouvelle fonctionnalité
|
||||
JavaScript de la nouvelle version de Node.js est bien souvent déjà dans
|
||||
Electron.
|
||||
|
||||
## La fenêtre/barre d'état de mon application disparait après quelques minutes.
|
||||
|
||||
Cela se produit quand la variable qui est utilisée pour stocker la fenêtre/barre
|
||||
d'état est libérée par le ramasse-miettes.
|
||||
|
||||
Nous vous recommandons de lire les articles suivants quand vous rencontrez le
|
||||
problème :
|
||||
|
||||
* [Management de la Mémoire][memory-management] (Anglais)
|
||||
* [Portée d'une Variable][variable-scope] (Anglais)
|
||||
|
||||
Si vous voulez corriger rapidement le problème, vous pouvez rendre les variables
|
||||
globales en changeant votre code de ça :
|
||||
|
||||
```javascript
|
||||
app.on('ready', function() {
|
||||
var tray = new Tray('/path/to/icon.png');
|
||||
})
|
||||
```
|
||||
|
||||
à ça :
|
||||
|
||||
```javascript
|
||||
var tray = null;
|
||||
app.on('ready', function() {
|
||||
tray = new Tray('/path/to/icon.png');
|
||||
})
|
||||
```
|
||||
|
||||
## Je n'arrive pas à utiliser jQuery/RequireJS/Meteor/AngularJS dans Electron.
|
||||
|
||||
A cause de l'intégration de Node.js dans Electron, certains mots-clés sont
|
||||
insérés dans la DOM, comme `module`, `exports`, `require`. Ceci pose des
|
||||
problèmes pour certaines bibliothèques qui utilisent les mêmes mots-clés.
|
||||
|
||||
Pour résoudre ce problème, vous pouvez désactiver l'intégration de node dans
|
||||
Electron :
|
||||
|
||||
```javascript
|
||||
// Dans le processus principal.
|
||||
var mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nodeIntegration: false
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Mais si vous voulez garder la possibilité d'utiliser Node.js et les APIs
|
||||
Electron, vous devez renommer les mots-clés dans la page avant d'inclure
|
||||
d'autres bibliothèques :
|
||||
|
||||
```html
|
||||
<head>
|
||||
<script>
|
||||
window.nodeRequire = require;
|
||||
delete window.require;
|
||||
delete window.exports;
|
||||
delete window.module;
|
||||
</script>
|
||||
<script type="text/javascript" src="jquery.js"></script>
|
||||
</head>
|
||||
```
|
||||
|
||||
## `require('electron').xxx` is undefined.
|
||||
|
||||
Lors de l'utilisation des modules d'Electron, vous pouvez avoir une erreur :
|
||||
|
||||
```
|
||||
> require('electron').webFrame.setZoomFactor(1.0);
|
||||
Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined
|
||||
```
|
||||
|
||||
Ceci se produit quand vous avez le [module npm `electron`][electron-module]
|
||||
d'installé, soit en local ou en global, ce qui a pour effet d'écraser les
|
||||
modules de base d'Electron.
|
||||
|
||||
Vous vérifiez que vous utilisez les bons modules, vous pouvez afficher le
|
||||
chemin du module `electron` :
|
||||
|
||||
```javascript
|
||||
console.log(require.resolve('electron'));
|
||||
```
|
||||
|
||||
et vérifier si il est de la forme :
|
||||
|
||||
```
|
||||
"/path/to/Electron.app/Contents/Resources/atom.asar/renderer/api/lib/exports/electron.js"
|
||||
```
|
||||
|
||||
S'il est de la forme `node_modules/electron/index.js`, vous devez supprimer le
|
||||
module npm `electron`, ou le renommer.
|
||||
|
||||
```bash
|
||||
npm uninstall electron
|
||||
npm uninstall -g electron
|
||||
```
|
||||
|
||||
Si vous utilisez le module de base mais que vous continuez d'avoir
|
||||
l'erreur, ça vient probablement du fait que vous utilisez le module dans le
|
||||
mauvais processus. Par exemple `electron.app` peut uniquement être utilisé
|
||||
dans le processus principal, tandis que `electron.webFrame` est uniquement
|
||||
disponible dans le processus d'affichage.
|
||||
|
||||
[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
|
||||
[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx
|
||||
[electron-module]: https://www.npmjs.com/package/electron
|
||||
101
docs-translations/fr-FR/styleguide.md
Normal file
101
docs-translations/fr-FR/styleguide.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Règles de style pour la documentation d'Electron
|
||||
|
||||
Choisissez la section appropriée : [lire la documentation d'Electron](#reading-electron-documentation)
|
||||
ou [écrire de la documentation pour Electron](#writing-electron-documentation).
|
||||
|
||||
## Ecrire de la documentation pour Electron
|
||||
|
||||
La documentation d'Electron a été écrite en suivant les règles ci-dessous :
|
||||
|
||||
- Maximum un titre `h1` par page.
|
||||
- Utilisation de `bash` au lieu de `cmd` dans les blocs de code (à cause de la
|
||||
coloration syntaxique).
|
||||
- Les titres `h1` devraient reprendre le nom de l'objet (i.e. `browser-window` →
|
||||
`BrowserWindow`).
|
||||
- Cependant, les traits d'union sont acceptés pour les noms de fichier.
|
||||
- Pas de titre directement après un autre, ajoutez au minimum une ligne de
|
||||
description entre les deux.
|
||||
- Les entêtes des méthodes sont entre accents graves (backquotes) `code`.
|
||||
- Les entêtes des évènements sont entre des apostrophes 'quotation'.
|
||||
- Les listes ne doivent pas dépasser 2 niveaux (à cause du formattage du
|
||||
markdown).
|
||||
- Ajouter des titres de section: Evènements, Méthodes de classe, et Méthodes
|
||||
d'instance.
|
||||
- Utiliser 'will' au lieu de 'would' lors de la description du retour.
|
||||
- Les évènements et méthodes sont des titres `h3`.
|
||||
- Les arguments optionnels sont notés `function (required[, optional])`.
|
||||
- Les arguments optionnels sont indiqués quand appelés dans la liste.
|
||||
- La longueur des lignes ne dépasse pas 80 caractères.
|
||||
- Les méthodes spécifiques à une plateforme sont notées en italique.
|
||||
- ```### `method(foo, bar)` _OS X_```
|
||||
- Préférer 'in the ___ process' au lieu de 'on'
|
||||
|
||||
### Traductions de la Documentation
|
||||
|
||||
Les traductions de la documentation d'Electron sont dans le dossier
|
||||
`docs-translations`.
|
||||
|
||||
Pour ajouter une nouvelle langue (ou commencer) :
|
||||
|
||||
- Créer un sous-dossier avec comme nom le code langage.
|
||||
- A l'intérieur de ce dossier, dupliquer le dossier `docs`, en gardant le même
|
||||
nom de dossiers et de fichiers.
|
||||
- Traduire les fichiers.
|
||||
- Mettre à jour le `README.md` à l'intérieur du dossier de langue en mettant les
|
||||
liens vers les fichiers traduits.
|
||||
- Ajouter un lien vers le nouveau dossier de langue dans le [README](https://github.com/atom/electron#documentation-translations)
|
||||
principal d'Electron.
|
||||
|
||||
## Lire la documentation d'Electron
|
||||
|
||||
Quelques indications pour comprendre la syntaxe de la documentation d'Electron.
|
||||
|
||||
### Méthodes
|
||||
|
||||
Un exemple de la documentation d'une [méthode](https://developer.mozilla.org/en-US/docs/Glossary/Method)
|
||||
(Anglais)
|
||||
|
||||
---
|
||||
|
||||
`methodName(required[, optional]))`
|
||||
|
||||
* `require` String (**required**)
|
||||
* `optional` Integer
|
||||
|
||||
---
|
||||
|
||||
Le nom de la méthode est suivi des arguments de celle-ci. Les arguments
|
||||
optionnels sont notés entre crochets, avec une virgule si ceux-ci suivent un
|
||||
autre argument.
|
||||
|
||||
En-dessous de la méthode, chaque argument est détaillé avec son type.
|
||||
Celui-ci peut être un type générique :
|
||||
[`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String),
|
||||
[`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number),
|
||||
[`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object),
|
||||
[`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
|
||||
ou un type personnalisé comme le [`webContent`](api/web-content.md) d'Electron.
|
||||
|
||||
### Evènements
|
||||
|
||||
Un exemple d'une documentation d'un [évènement](https://developer.mozilla.org/en-US/docs/Web/API/Event)
|
||||
(Anglais)
|
||||
---
|
||||
|
||||
Event: 'wake-up'
|
||||
|
||||
Returns:
|
||||
|
||||
* `time` String
|
||||
|
||||
---
|
||||
|
||||
L'évènement est une chaine utilisée après un listener `.on`. Si il retourne une
|
||||
valeur, elle est écrite en dessous ainsi que son type. Si vous voulez écouter et
|
||||
répondre à l'évènement wake-up, ça donne quelque chose comme :
|
||||
|
||||
```javascript
|
||||
Alarm.on('wake-up', function(time) {
|
||||
console.log(time)
|
||||
})
|
||||
```
|
||||
@@ -3,6 +3,7 @@
|
||||
そうでない場合、おそらくご使用の Electron のバージョンと互換性のない API 変更を含んだ development ブランチのドキュメントを使っているものと思われます。
|
||||
その場合、atom.io の [available versions](http://electron.atom.io/docs/) リストにある別のバージョンのドキュメントに切り替えることができます。また GitHub で閲覧している場合、"Switch branches/tags" ドロップダウンを開いて、バージョンに対応したタグを選ぶこともできます。
|
||||
|
||||
_リンクになっていないリストは未翻訳のものです。_
|
||||
## FAQ
|
||||
|
||||
頻繁に聞かれる質問がありますので、issueを作成する前にこれをチェックしてください。
|
||||
@@ -31,3 +32,57 @@
|
||||
## API リファレンス
|
||||
|
||||
* [概要](api/synopsis.md)
|
||||
* [Process Object](api/process.md)
|
||||
* [サポートしているChromeコマンドラインスイッチ](api/chrome-command-line-switches.md)
|
||||
* [環境変数](api/environment-variables.md)
|
||||
|
||||
### カスタムDOM要素:
|
||||
|
||||
* [`File` Object](api/file-object.md)
|
||||
* `<webview>` Tag
|
||||
* [`window.open` 関数](api/window-open.md)
|
||||
|
||||
### Main Processのモジュール:
|
||||
|
||||
* [app](api/app.md)
|
||||
* [autoUpdater](api/auto-updater.md)
|
||||
* BrowserWindow
|
||||
* [フレームの無いウィンドウ](api/frameless-window.md)
|
||||
* [contentTracing](api/content-tracing.md)
|
||||
* [dialog](api/dialog.md)
|
||||
* [globalShortcut](api/global-shortcut.md)
|
||||
* [ipcMain](api/ipc-main.md)
|
||||
* [Menu](api/menu.md)
|
||||
* [MenuItem](api/menu-item.md)
|
||||
* [powerMonitor](api/power-monitor.md)
|
||||
* [powerSaveBlocker](api/power-save-blocker.md)
|
||||
* [protocol](api/protocol.md)
|
||||
* [session](api/session.md)
|
||||
* webContents
|
||||
* [Tray](api/tray.md)
|
||||
|
||||
### Renderer Processのモジュール (Web Page):
|
||||
|
||||
* [desktopCapturer](api/desktop-capturer.md)
|
||||
* [ipcRenderer](api/ipc-renderer.md)
|
||||
* [remote](api/remote.md)
|
||||
* [webFrame](api/web-frame.md)
|
||||
|
||||
### 両方のProcessのモジュール :
|
||||
|
||||
* [clipboard](api/clipboard.md)
|
||||
* [crashReporter](api/crash-reporter.md)
|
||||
* [nativeImage](api/native-image.md)
|
||||
* [screen](api/screen.md)
|
||||
* [shell](api/shell.md)
|
||||
|
||||
## 開発
|
||||
|
||||
* Coding Style
|
||||
* Source Code Directory Structure
|
||||
* Technical Differences to NW.js (formerly node-webkit)
|
||||
* Build System Overview
|
||||
* Build Instructions (OS X)
|
||||
* Build Instructions (Windows)
|
||||
* Build Instructions (Linux)
|
||||
* Setting Up Symbol Server in debugger
|
||||
|
||||
@@ -378,6 +378,7 @@ if (browserOptions.transparent) {
|
||||
// No transparency, so we load a fallback that uses basic styles.
|
||||
win.loadURL('file://' + __dirname + '/fallback.html');
|
||||
}
|
||||
```
|
||||
|
||||
### `app.commandLine.appendSwitch(switch[, value])`
|
||||
|
||||
@@ -431,6 +432,12 @@ dock アイコンを表示します。
|
||||
|
||||
アプリケーションの[dock menu][dock-menu]を設定します。
|
||||
|
||||
### `app.dock.setIcon(image)` _OS X_
|
||||
|
||||
* `image` [NativeImage](native-image.md)
|
||||
|
||||
dock アイコンに紐づいた`image`を設定します。
|
||||
|
||||
[dock-menu]:https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/concepts/dockconcepts.html#//apple_ref/doc/uid/TP30000986-CH2-TPXREF103
|
||||
[tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks
|
||||
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
|
||||
|
||||
@@ -24,6 +24,11 @@ Windows コンソール上:
|
||||
|
||||
Chromeのインターナルログをコンソールに出力します。
|
||||
|
||||
|
||||
## `ELECTRON_LOG_ASAR_READS`
|
||||
|
||||
ASARファイルからElectronが読み込んだとき、システム`tmpdir`へ読み込みオフセットとファイルのパスを記録します。ファイルの順序を最適化するために、得られたファイルはASARモジュールに提供されます。
|
||||
|
||||
## `ELECTRON_ENABLE_STACK_DUMPING`
|
||||
|
||||
Electronがクラッシュしたとき、コンソールにスタックとレースを出力します。
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
* `channel` String - イベント名
|
||||
* `arg` (optional)
|
||||
|
||||
`channel`経由でメインプロセスに非同期にイベントを送信し、任意の引数を送信できます。
|
||||
`channel`経由でメインプロセスに同期的にイベントを送信し、任意の引数を送信できます。
|
||||
|
||||
メインプロセスは`ipcMain`で`channel`を受信することでハンドルし、 `event.returnValue`を設定してリプライします。
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ var template = [
|
||||
];
|
||||
|
||||
if (process.platform == 'darwin') {
|
||||
var name = require('electron').app.getName();
|
||||
var name = require('electron').remote.app.getName();
|
||||
template.unshift({
|
||||
label: name,
|
||||
submenu: [
|
||||
|
||||
@@ -45,9 +45,22 @@ app.on('ready', function() {
|
||||
|
||||
レスポンスとしてファイルを送信する`scheme`のプロトコルを登録します。`scheme`で`request`が生成された時、`handler`は`handler(request, callback)`で呼び出されます。`scheme` 登録が成功したり、`completion(error)`が失敗したときに、`completion` は`completion(null)`で呼び出されます。
|
||||
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` Array (オプション)
|
||||
* `callback` Function
|
||||
|
||||
`uploadData` は `data` オブジェクトの配列です:
|
||||
|
||||
* `data` Object
|
||||
* `bytes` Buffer - 送信するコンテンツ
|
||||
* `file` String - アップロードするファイルパス
|
||||
|
||||
`request`をハンドルするために、`callback`はファイルパスまたは`path`プロパティを持つオブジェクトで呼び出すべきです。例えば、`callback(filePath)` または`callback({path: filePath})`です。
|
||||
|
||||
何もなし、数字、`error`プロパティを持つオブジェクトで、`callback`が呼び出された時、 `request`は指定した`error`番号で失敗します。使用できる提供されているエラー番号は、[net error list](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h)を参照してください。
|
||||
何もなし、数字、`error`プロパティを持つオブジェクトで、`callback`が呼び出された時、 `request`は指定した`error`番号で失敗します。使用できる提供されているエラー番号は、[net error list][net-error]を参照してください。
|
||||
|
||||
既定では、`scheme`は、`file:`のような一般的なURIの構文に続くプロトコルと違う解析がされ、`http:`のように扱われます。なので、恐らく標準的なスキーマーのように扱われるスキーマーを持つために、`protocol.registerStandardSchemes` を呼び出したくなります。
|
||||
|
||||
@@ -57,7 +70,9 @@ app.on('ready', function() {
|
||||
* `handler` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
レスポンスとして`Buffer`を送信する`scheme`プロトコルを登録します。`callback`は、`Buffer`オブジェクトまたは`data`と `mimeType`、`chart`プロパティを持つオブジェクトを呼び出す必要があります。
|
||||
レスポンスとして`Buffer`を送信する`scheme`プロトコルを登録します。
|
||||
|
||||
`callback`は、`Buffer`オブジェクトまたは、`data`と`mimeType`、 `charset`プロパティを持つオブジェクトのどちらかで呼ばれる必要があることを除いて、この使用方法は、`registerFileProtocol`と同じです。
|
||||
|
||||
例:
|
||||
|
||||
@@ -76,7 +91,9 @@ protocol.registerBufferProtocol('atom', function(request, callback) {
|
||||
* `handler` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
レスポンスとして`String`を送信する`scheme`プロトコルを登録します。`callback`は、`String`または`data`と `mimeType`、`chart`プロパティを持つオブジェクトを呼び出す必要があります。
|
||||
レスポンスとして`String`を送信する`scheme`プロトコルを登録します。
|
||||
|
||||
`callback`は、`String`または`data`と `mimeType`、`chart`プロパティを持つオブジェクトを呼び出す必要があることを除いて、使用方法は`registerFileProtocol`と同じです。
|
||||
|
||||
### `protocol.registerHttpProtocol(scheme, handler[, completion])`
|
||||
|
||||
@@ -84,14 +101,22 @@ protocol.registerBufferProtocol('atom', function(request, callback) {
|
||||
* `handler` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
レスポンスとしてHTTPリクエストを送信する`scheme`プロトコルを登録します。`callback`は、`url`と`method`、`referrer`、`uploadData`、`session`プロパティを持つオブジェクトを呼び出す必要があります。
|
||||
レスポンスとしてHTTPリクエストを送信する`scheme`プロトコルを登録します。
|
||||
|
||||
`callback`は、`url`と`method`、`referrer`、`uploadData`、`session`プロパティを持つオブジェクトを呼び出す必要があることを除いて、使用方法は`registerFileProtocol`と同じです。
|
||||
|
||||
* `redirectRequest` Object
|
||||
* `url` String
|
||||
* `method` String
|
||||
* `session` Object (オプション)
|
||||
* `uploadData` Object (オプション)
|
||||
|
||||
既定では、HTTPリクエストは現在のセッションを再利用します。別のセッションでリクエストをしたい場合、`session` に `null`を設定する必要があります。
|
||||
|
||||
POSTリクエストは`uploadData`オブジェクトを提供する必要があります。
|
||||
* `uploadData` object
|
||||
* `contentType` String - コンテンツのMIMEタイプ
|
||||
* `data` String - 送信されるコンテンツ
|
||||
* `data` String - 送信されるコンテンツ
|
||||
|
||||
### `protocol.unregisterProtocol(scheme[, completion])`
|
||||
|
||||
@@ -139,12 +164,12 @@ POSTリクエストは`uploadData`オブジェクトを提供する必要があ
|
||||
|
||||
`scheme`プロトコルをインターセプタ―し、レスポンスとして新しいHTTPリクエストを送信するプロトコルの新しいハンドラーとして`handler`を使います。
|
||||
|
||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||
which sends a new HTTP request as a response.
|
||||
|
||||
### `protocol.uninterceptProtocol(scheme[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `completion` Function
|
||||
|
||||
インターセプタ―したインストールされた`scheme`を削除し、オリジナルハンドラーをリストアします。
|
||||
|
||||
|
||||
[net-error]: https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h
|
||||
|
||||
@@ -197,6 +197,7 @@ proxyURL = [<proxyScheme>"://"]<proxyHost>[":"<proxyPort>]
|
||||
```
|
||||
|
||||
具体例:
|
||||
|
||||
* `http=foopy:80;ftp=foopy2` - `http://`URLは`foopy:80`HTTPプロキシを使用し、`ftp://`URLは`foopy2:80` HTTPプロキシを使用します。
|
||||
* `foopy:80` - 全てのURLで`foopy:80`を使用します。
|
||||
* `foopy:80,bar,direct://` - 全てのURLで`foopy:80`HTTPプロキシを使用し、`foopy:80`が提供されていなければ`bar`を使用し、さらに使えない場合はプロキシを使いません。
|
||||
@@ -296,6 +297,14 @@ session.defaultSession.webRequest.onBeforeSendHeaders(filter, function(details,
|
||||
* `method` String
|
||||
* `resourceType` String
|
||||
* `timestamp` Double
|
||||
* `uploadData` Array (オプション)
|
||||
* `callback` Function
|
||||
|
||||
`uploadData`は `data`オブジェクトの配列です。
|
||||
|
||||
* `data` Object
|
||||
* `bytes` Buffer - 送信されるコンテンツ
|
||||
* `file` String - アップロードされるファイルパス
|
||||
|
||||
`callback`は`response`オブジェクトでコールされる必要があります:
|
||||
|
||||
@@ -317,6 +326,7 @@ session.defaultSession.webRequest.onBeforeSendHeaders(filter, function(details,
|
||||
* `resourceType` String
|
||||
* `timestamp` Double
|
||||
* `requestHeaders` Object
|
||||
* `callback` Function
|
||||
|
||||
The `callback` has to be called with an `response` object:
|
||||
|
||||
@@ -355,6 +365,7 @@ The `callback` has to be called with an `response` object:
|
||||
* `statusLine` String
|
||||
* `statusCode` Integer
|
||||
* `responseHeaders` Object
|
||||
* `callback` Function
|
||||
|
||||
`callback`は`response`オブジェクトでコールされる必要があります:
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Electron では全ての [Node.js のビルトインモジュール](http://node
|
||||
|
||||
Electron はネイティブのデスクトップアプリケーション開発のための幾つかの追加のビルトインモジュールも提供しています。メインプロセスでだけ使えるモジュールもあれば、レンダラプロセス(ウェブページ)でだけ使えるモジュール、あるいはメインプロセス、レンダラプロセスどちらでも使えるモジュールもあります。
|
||||
|
||||
基本的なルールは:[GUI][gui]、または低レベルのシステムに関連するモジュールはメインモジュールでだけ利用できるべきです。これらのモジュールを使用できるようにするためには [メインプロセス対レンダラプロセス][main-process] スクリプトの概念を理解する必要があります。
|
||||
基本的なルールは:[GUI][gui]、または低レベルのシステムに関連するモジュールはメインモジュールでだけ利用できるべきです。これらのモジュールを使用できるようにするためには [メインプロセス対レンダラプロセス](../tutorial/quick-start.md#メインプロセス)スクリプトの概念を理解する必要があります。
|
||||
|
||||
メインプロセススクリプトは普通の Node.js スクリプトのようなものです:
|
||||
|
||||
@@ -64,6 +64,5 @@ require('electron').hideInternalModules()
|
||||
```
|
||||
|
||||
[gui]: https://en.wikipedia.org/wiki/Graphical_user_interface
|
||||
[main-process]: ../tutorial/quick-start.md#メインプロセス
|
||||
[desctructuring-assignment]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
|
||||
[issue-387]: https://github.com/atom/electron/issues/387
|
||||
|
||||
@@ -12,6 +12,27 @@ Node.js の新しいバージョンがリリースされたとき、私たちは
|
||||
|
||||
通常、Node.js の新しい機能は V8 のアップグレードによってもたらされますが、Electron は Chrome ブラウザーに搭載されている V8 を使用しているので、新しい Node.js に入ったばかりのピカピカに新しい JavaScript 機能は Electron ではたいてい既に導入されています。
|
||||
|
||||
## ウェブページ間のデータを共有する方法は?
|
||||
|
||||
ウェブページ(レンダラープロセス)間のデータを共有するために最も単純な方法は、ブラウザで、すでに提供されているHTML5 APIを使用することです。もっとも良い方法は、[Storage API][storage]、[`localStorage`][local-storage]、[`sessionStorage`][session-storage]、[IndexedDB][indexed-db]です。
|
||||
|
||||
```javascript
|
||||
// In the main process.
|
||||
global.sharedObject = {
|
||||
someProperty: 'default value'
|
||||
};
|
||||
```
|
||||
|
||||
```javascript
|
||||
// In page 1.
|
||||
require('remote').getGlobal('sharedObject').someProperty = 'new value';
|
||||
```
|
||||
|
||||
```javascript
|
||||
// In page 2.
|
||||
console.log(require('remote').getGlobal('sharedObject').someProperty);
|
||||
```
|
||||
|
||||
## 何分か経つと、アプリの Window/tray が消えてしまいます
|
||||
|
||||
これは、Window/trayを格納するのに使用している変数がガベージコレクトされたときに発生します。
|
||||
@@ -69,5 +90,42 @@ delete window.module;
|
||||
</head>
|
||||
```
|
||||
|
||||
## `require('electron').xxx` は定義されていません。
|
||||
|
||||
Electronの組み込みモジュールを使うとに、次のようなエラーに遭遇するかもしれません。
|
||||
|
||||
```
|
||||
> require('electron').webFrame.setZoomFactor(1.0);
|
||||
Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined
|
||||
```
|
||||
|
||||
これは、ローカルまたはグローバルのどちらかで [npm `electron` module][electron-module] をインストールしたことが原因で、Electronの組み込みモジュールを上書きしてしまいます。
|
||||
|
||||
正しい組み込みモジュールを使用しているかを確認するために、`electron`モジュールのパスを出力します。
|
||||
|
||||
```javascript
|
||||
console.log(require.resolve('electron'));
|
||||
```
|
||||
|
||||
そして、次の形式かどうかを確認します。
|
||||
|
||||
```
|
||||
"/path/to/Electron.app/Contents/Resources/atom.asar/renderer/api/lib/exports/electron.js"
|
||||
```
|
||||
|
||||
If it is something like もし、`node_modules/electron/index.js` のような形式の場合は、npm `electron` モジュールを削除するか、それをリネームします。
|
||||
|
||||
```bash
|
||||
npm uninstall electron
|
||||
npm uninstall -g electron
|
||||
```
|
||||
|
||||
しかし、組み込みモジュールを使用しているのに、まだこのエラーが出る場合、不適切なプロセスでモジュールを使用しようとしている可能性が高いです。例えば、`electron.app`はメインプロセスのみで使え、一方で`electron.webFrame`はレンダラープロセスのみに提供されています。
|
||||
|
||||
[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
|
||||
[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx
|
||||
[electron-module]: https://www.npmjs.com/package/electron
|
||||
[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage
|
||||
[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
|
||||
[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
|
||||
[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
|
||||
|
||||
@@ -51,8 +51,8 @@ Electronにバンドルした後、ユーザーに配布する前に、 Electron
|
||||
|
||||
### Windows
|
||||
|
||||
`electron.exe`を任意の名前に変更でき、[rcedit](https://github.com/atom/rcedit) または
|
||||
[ResEdit](http://www.resedit.net)のようなツールでアイコンやその他の情報を編集できます。
|
||||
`electron.exe`を任意の名前に変更でき、[rcedit](https://github.com/atom/rcedit)
|
||||
のようなツールでアイコンやその他の情報を編集できます。
|
||||
|
||||
### OS X
|
||||
|
||||
|
||||
@@ -55,13 +55,13 @@ $ electron --debug=5858 your/app
|
||||
$ electron --debug-brk=5858 your/app
|
||||
```
|
||||
|
||||
### 5. Electronを使用して、[node-inspector][node-inspector] サーバーを開始する
|
||||
### 6. Electronを使用して、[node-inspector][node-inspector] サーバーを開始する
|
||||
|
||||
```bash
|
||||
$ ELECTRON_RUN_AS_NODE=true path/to/electron.exe node_modules/node-inspector/bin/inspector.js
|
||||
```
|
||||
|
||||
### 6. デバッグUIを読み込みます
|
||||
### 7. デバッグUIを読み込みます
|
||||
|
||||
Chromeブラウザで、 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858 を開きます。エントリーラインを見るために、debug-brkを始めるには、ポーズをクリックします。
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user