mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
1641 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73158a6419 | ||
|
|
9e62197713 | ||
|
|
1d93989d26 | ||
|
|
94f7cbe1dc | ||
|
|
d29afb5f49 | ||
|
|
60d85d03a4 | ||
|
|
4ff0b8d6b5 | ||
|
|
b37884cb5e | ||
|
|
36f7974e18 | ||
|
|
08d8c16720 | ||
|
|
439e9d61d6 | ||
|
|
dd4b688b5f | ||
|
|
0082e8083c | ||
|
|
b398305cdd | ||
|
|
94a53cdb30 | ||
|
|
438a7d8e1e | ||
|
|
cdb7eed21d | ||
|
|
98d7b61a4a | ||
|
|
72ff292302 | ||
|
|
c0c179fad0 | ||
|
|
b450e51319 | ||
|
|
753683ad22 | ||
|
|
34a68725a0 | ||
|
|
8ab1309215 | ||
|
|
440a3fa6d8 | ||
|
|
3b61384c26 | ||
|
|
ce33169b71 | ||
|
|
6d5b225ac5 | ||
|
|
bb28fa8e8e | ||
|
|
42acbec1c8 | ||
|
|
3c97c90621 | ||
|
|
1e27157de2 | ||
|
|
95c73eebb2 | ||
|
|
03e051cfbb | ||
|
|
84f3470032 | ||
|
|
cbf5274a96 | ||
|
|
22a7f57293 | ||
|
|
9b6eab1b42 | ||
|
|
8733c2d6c6 | ||
|
|
8f629a2f31 | ||
|
|
ece0487228 | ||
|
|
edf2938ca5 | ||
|
|
79e55e5e85 | ||
|
|
27bfeb6148 | ||
|
|
55e9c211f8 | ||
|
|
8db09e26b1 | ||
|
|
17c00954bd | ||
|
|
034ea3cdfb | ||
|
|
4913fc81d1 | ||
|
|
846b43d7bd | ||
|
|
d644eb4164 | ||
|
|
dc4057bb48 | ||
|
|
c3867ba6d5 | ||
|
|
aa57be70a0 | ||
|
|
9d24d28816 | ||
|
|
75a21678d7 | ||
|
|
7f0056f683 | ||
|
|
02eeef4dc0 | ||
|
|
7d8c59deda | ||
|
|
1e9a75d9f2 | ||
|
|
e7688723f9 | ||
|
|
6fb569cc6c | ||
|
|
349f10d779 | ||
|
|
9f6bee704f | ||
|
|
e6668f60c8 | ||
|
|
409b58525a | ||
|
|
ea83871cf6 | ||
|
|
53ace2e099 | ||
|
|
38fc10f068 | ||
|
|
03b9f0db58 | ||
|
|
aea44b9227 | ||
|
|
eb9e468bcc | ||
|
|
936d088210 | ||
|
|
9490a9f9ba | ||
|
|
3c4cd3f662 | ||
|
|
15f8d15b1b | ||
|
|
9f472acf80 | ||
|
|
0043acf70a | ||
|
|
e25f8c1a08 | ||
|
|
e2be247579 | ||
|
|
9de5965bb7 | ||
|
|
67af030df7 | ||
|
|
f0b47b2541 | ||
|
|
97ffaf058f | ||
|
|
a4a0eff1e7 | ||
|
|
1ad67754c0 | ||
|
|
8408136082 | ||
|
|
56f7359ed3 | ||
|
|
5dc15fc5d9 | ||
|
|
17481882d0 | ||
|
|
b23b72f9c3 | ||
|
|
957ac493e6 | ||
|
|
5ddc2fb6e7 | ||
|
|
31d5e9bbe1 | ||
|
|
386e356ed6 | ||
|
|
250a09a43f | ||
|
|
3ed5a24c72 | ||
|
|
5d05f1c72a | ||
|
|
0fa449f5f4 | ||
|
|
05ffcbdb3b | ||
|
|
4abf55801f | ||
|
|
d5a6bb665b | ||
|
|
4305657858 | ||
|
|
e391b7df69 | ||
|
|
82e7bd3f22 | ||
|
|
eb30cc2ede | ||
|
|
d9efaa946b | ||
|
|
3f99cf4f1d | ||
|
|
a0a9d9d159 | ||
|
|
7165fb181d | ||
|
|
67cf0eb9b0 | ||
|
|
e9823f07be | ||
|
|
c272f5fc56 | ||
|
|
48ebebcafe | ||
|
|
ae9f4ef425 | ||
|
|
5c14992e43 | ||
|
|
53b871ecbd | ||
|
|
ec6fe27fca | ||
|
|
8566f8712c | ||
|
|
08ec270b90 | ||
|
|
b2822ed800 | ||
|
|
6bec85f30c | ||
|
|
6d658b319b | ||
|
|
5c853b681c | ||
|
|
7b0959ed2b | ||
|
|
3e8b854975 | ||
|
|
fd97fcf6f0 | ||
|
|
809534dca0 | ||
|
|
b2763cad9f | ||
|
|
b6b9966162 | ||
|
|
a41e919b95 | ||
|
|
bdda248194 | ||
|
|
41e86efda0 | ||
|
|
88b1f7d9c8 | ||
|
|
dcdbc87ef4 | ||
|
|
9e03783781 | ||
|
|
8208296143 | ||
|
|
518467cf4c | ||
|
|
648bf54bb3 | ||
|
|
8dce40137c | ||
|
|
dab77256d2 | ||
|
|
c7501bd7ca | ||
|
|
203c47f038 | ||
|
|
02cd96875d | ||
|
|
9349b0a273 | ||
|
|
1c42715e1d | ||
|
|
ef4a7e22fd | ||
|
|
ead294fe13 | ||
|
|
f119e4cc4b | ||
|
|
00489e6106 | ||
|
|
a7c34b8a0a | ||
|
|
906436f31b | ||
|
|
b208fcbf0d | ||
|
|
6899ac9bde | ||
|
|
72c033299f | ||
|
|
7fb6b3bda8 | ||
|
|
1d79840025 | ||
|
|
07deaaa502 | ||
|
|
259f0a62e8 | ||
|
|
4f78df9cfa | ||
|
|
b2be093bd3 | ||
|
|
4f666bb6ac | ||
|
|
12f75832b8 | ||
|
|
6f54d58e2a | ||
|
|
8716f718a9 | ||
|
|
714f3ffd29 | ||
|
|
4a5d2117ba | ||
|
|
5cb50b0e33 | ||
|
|
7283b78aa2 | ||
|
|
049381c6ac | ||
|
|
22597474e0 | ||
|
|
760def6147 | ||
|
|
70d4644742 | ||
|
|
f6b7f547bb | ||
|
|
9bb3701f7e | ||
|
|
d7fe65b9bd | ||
|
|
eb8546c8d1 | ||
|
|
6719f66d5a | ||
|
|
b78fb5aa93 | ||
|
|
502b0b988e | ||
|
|
3d8af9d279 | ||
|
|
524bb99948 | ||
|
|
8f743e6fbe | ||
|
|
6c085cda74 | ||
|
|
73935bc5dd | ||
|
|
bf928ee443 | ||
|
|
ee6de82c08 | ||
|
|
8d362150e0 | ||
|
|
385b08881e | ||
|
|
5cd24a4e81 | ||
|
|
9ab77adc94 | ||
|
|
d808423975 | ||
|
|
3979315517 | ||
|
|
35cb671529 | ||
|
|
0f291f9d63 | ||
|
|
8574a55bd8 | ||
|
|
05a429075e | ||
|
|
7eb1c3fb1b | ||
|
|
db0384116e | ||
|
|
0f8fb86e1b | ||
|
|
0c3cfc50a7 | ||
|
|
8d87dffe01 | ||
|
|
9bb6c9dc99 | ||
|
|
e405103880 | ||
|
|
34c202518d | ||
|
|
e5d84e84c2 | ||
|
|
18857f494d | ||
|
|
d417759885 | ||
|
|
46c467a1f6 | ||
|
|
0b3b508eca | ||
|
|
e3195413aa | ||
|
|
96c47ef537 | ||
|
|
89148bcf8d | ||
|
|
7e5815c180 | ||
|
|
f924a16055 | ||
|
|
2a113e512b | ||
|
|
02b1069fd8 | ||
|
|
3348e5162f | ||
|
|
64c8c27575 | ||
|
|
e76a976347 | ||
|
|
8d27657fa5 | ||
|
|
5e81d8dad9 | ||
|
|
b23acab456 | ||
|
|
8950caaa85 | ||
|
|
1b920c25af | ||
|
|
8fd31a3e07 | ||
|
|
893f866c05 | ||
|
|
d36b14a322 | ||
|
|
27a33cc1cf | ||
|
|
7835bceabd | ||
|
|
af4f08e030 | ||
|
|
03dac078d7 | ||
|
|
d3d44bdbc6 | ||
|
|
a370b6982d | ||
|
|
03ef5c25f7 | ||
|
|
3bc6652833 | ||
|
|
664371245a | ||
|
|
08270e6817 | ||
|
|
8f74a77a64 | ||
|
|
85c8ada99a | ||
|
|
b15a3ee2be | ||
|
|
7b043ac554 | ||
|
|
89a6f1efbb | ||
|
|
ce592a5705 | ||
|
|
12087b74e8 | ||
|
|
d365078022 | ||
|
|
3dbd84c224 | ||
|
|
2e479ff799 | ||
|
|
a341ae450a | ||
|
|
0aec308681 | ||
|
|
8e9c5b8338 | ||
|
|
6bc1e37156 | ||
|
|
7da7dd85e3 | ||
|
|
ccf8a797dc | ||
|
|
3301e05f33 | ||
|
|
b1c22ba531 | ||
|
|
873f39b159 | ||
|
|
11864e9e08 | ||
|
|
c8a21dbb92 | ||
|
|
97058837e7 | ||
|
|
ff539c1d61 | ||
|
|
9237d40e09 | ||
|
|
4721dc0856 | ||
|
|
1f7fd985dd | ||
|
|
d432e420ae | ||
|
|
635c3f53d8 | ||
|
|
ba703deee2 | ||
|
|
b03178105d | ||
|
|
ef0a6d9a1c | ||
|
|
4c7af6a429 | ||
|
|
d1886c5d22 | ||
|
|
c558dc2d7d | ||
|
|
be68cfd4ea | ||
|
|
115a15c356 | ||
|
|
d4fb904450 | ||
|
|
c7f7bdab8a | ||
|
|
de7cb9524a | ||
|
|
5d17e48490 | ||
|
|
058c03fdab | ||
|
|
bd0d6b1a02 | ||
|
|
0783eb9881 | ||
|
|
4e3aa2e061 | ||
|
|
92f3d47ab3 | ||
|
|
2a7ec7e051 | ||
|
|
bf465dc233 | ||
|
|
00cf45609f | ||
|
|
26f4190102 | ||
|
|
5d6382270a | ||
|
|
2162c996eb | ||
|
|
2945be4b9b | ||
|
|
c066a51bfe | ||
|
|
ff7dfe4a11 | ||
|
|
6d17663a0b | ||
|
|
bd4334e2b4 | ||
|
|
0f937c2300 | ||
|
|
2ecdf4a0eb | ||
|
|
44b0245ac4 | ||
|
|
c4d6484264 | ||
|
|
ef2ad40bd9 | ||
|
|
2642e064a2 | ||
|
|
daf23288bc | ||
|
|
8eec8e150d | ||
|
|
2af61cbe95 | ||
|
|
32ffb0ba17 | ||
|
|
69caea38c1 | ||
|
|
b5bfd9867b | ||
|
|
fb2afe8656 | ||
|
|
c926f3f6dc | ||
|
|
5aa247a627 | ||
|
|
67d202eaf6 | ||
|
|
98033e4f45 | ||
|
|
3d89185396 | ||
|
|
1f430259ce | ||
|
|
ff86cf5f6a | ||
|
|
274a53654c | ||
|
|
8f5fafb636 | ||
|
|
bfbd4a2540 | ||
|
|
1926eab172 | ||
|
|
9818378e2d | ||
|
|
ad2d35c7cf | ||
|
|
13d3a055fa | ||
|
|
07b93d475d | ||
|
|
c9da2d7669 | ||
|
|
a9a5766804 | ||
|
|
a62cb1e84c | ||
|
|
2bdb7a5047 | ||
|
|
29f70d7e35 | ||
|
|
91af624cb1 | ||
|
|
b08df88b7c | ||
|
|
b659ff2de3 | ||
|
|
3ad6abc5cc | ||
|
|
a880e0222f | ||
|
|
95c69e660c | ||
|
|
4333020157 | ||
|
|
f4ff97038c | ||
|
|
967577c335 | ||
|
|
8bd5c1f858 | ||
|
|
2955b0168c | ||
|
|
04b7c77951 | ||
|
|
136cf389e8 | ||
|
|
8d9775b0b1 | ||
|
|
9237d46dba | ||
|
|
8f8d198c5a | ||
|
|
fcdbb8c4a7 | ||
|
|
b49b071a1f | ||
|
|
1feb45da29 | ||
|
|
2c43dbdb25 | ||
|
|
7eff91dde1 | ||
|
|
780483ff35 | ||
|
|
c2f770df02 | ||
|
|
74e6e063d4 | ||
|
|
7702cc1090 | ||
|
|
97319e5a3a | ||
|
|
041c952574 | ||
|
|
6c9b6f9cac | ||
|
|
c4884da601 | ||
|
|
59b05ed661 | ||
|
|
e3204a5ec1 | ||
|
|
adf49daaac | ||
|
|
9431677e79 | ||
|
|
0141c083d0 | ||
|
|
96b2c08293 | ||
|
|
d6f2c26b0f | ||
|
|
d478906f9c | ||
|
|
85526c7f21 | ||
|
|
f6ae438005 | ||
|
|
5e51e608db | ||
|
|
97248a7a56 | ||
|
|
8639466c75 | ||
|
|
31e2166cea | ||
|
|
c2f4144996 | ||
|
|
f63e5ffa65 | ||
|
|
32e40cb4c3 | ||
|
|
8585372e11 | ||
|
|
2e2289d701 | ||
|
|
f6229d9489 | ||
|
|
bace4890c8 | ||
|
|
0a3211c387 | ||
|
|
7d27c91400 | ||
|
|
93edf2edd3 | ||
|
|
ec993214a2 | ||
|
|
509120acde | ||
|
|
b472a69279 | ||
|
|
7f3620bee3 | ||
|
|
21d4ef5eab | ||
|
|
4f6b6b044f | ||
|
|
02026279be | ||
|
|
6fd1f7ecb1 | ||
|
|
922cf08ab4 | ||
|
|
7f8cd51f63 | ||
|
|
31e5b046a4 | ||
|
|
957f008726 | ||
|
|
4cada5e845 | ||
|
|
2069eb1972 | ||
|
|
e15ffd96eb | ||
|
|
e57f7edd37 | ||
|
|
df62fb7788 | ||
|
|
9b09d103fd | ||
|
|
453edb42b4 | ||
|
|
1b2a85436c | ||
|
|
c7d4d2d18f | ||
|
|
d1a0eb3d11 | ||
|
|
a0e37d1383 | ||
|
|
128a03450a | ||
|
|
d34c7396ef | ||
|
|
cdbd4792e3 | ||
|
|
b0f6c3ab65 | ||
|
|
d2508faea8 | ||
|
|
9bda7d0b73 | ||
|
|
fc12b5cab3 | ||
|
|
04a7a34c42 | ||
|
|
f643ce4f66 | ||
|
|
3044607746 | ||
|
|
10df019075 | ||
|
|
295c823a1b | ||
|
|
d367b75680 | ||
|
|
e683af1eb6 | ||
|
|
794fe741e9 | ||
|
|
c598272891 | ||
|
|
137aaf2429 | ||
|
|
13f97b4cae | ||
|
|
9e8f83e25c | ||
|
|
e177117fa5 | ||
|
|
dd6c776a19 | ||
|
|
36c1e4cd75 | ||
|
|
faef453df5 | ||
|
|
cba3a9fcce | ||
|
|
9a79889692 | ||
|
|
0219ef0feb | ||
|
|
be29a1973b | ||
|
|
0fdcc5d485 | ||
|
|
a3bc989426 | ||
|
|
c58fa02e58 | ||
|
|
d2a950e054 | ||
|
|
5151a04613 | ||
|
|
bbc8d50799 | ||
|
|
bcbcb4c643 | ||
|
|
d5d5386017 | ||
|
|
f0e2da7089 | ||
|
|
906ef3da6a | ||
|
|
2720fa751b | ||
|
|
42c37cc26d | ||
|
|
56ae882bb8 | ||
|
|
9d18be8fde | ||
|
|
ed1f8d3646 | ||
|
|
efdf4f44c8 | ||
|
|
650631421f | ||
|
|
518f0005ad | ||
|
|
5a28759fea | ||
|
|
6c604e1eb3 | ||
|
|
25e5c174f5 | ||
|
|
b70ca6309c | ||
|
|
8f4d6a1995 | ||
|
|
ad74fb9210 | ||
|
|
da7cfba357 | ||
|
|
10c5141da0 | ||
|
|
10160b369b | ||
|
|
76f26341bf | ||
|
|
8200a132be | ||
|
|
c4f80a6d89 | ||
|
|
10e0d9b198 | ||
|
|
e70b93ad91 | ||
|
|
bc8525d2f3 | ||
|
|
c882b37a40 | ||
|
|
d9ec885dbc | ||
|
|
f43eafb94e | ||
|
|
de5bdc8be4 | ||
|
|
b7d00e26bf | ||
|
|
9b37e7d988 | ||
|
|
0b12e425bd | ||
|
|
a64def5745 | ||
|
|
0c69b0e224 | ||
|
|
03a63a485f | ||
|
|
e96d8b664d | ||
|
|
1fae6a321c | ||
|
|
f4a9575193 | ||
|
|
792bb9b4a8 | ||
|
|
67558d65a6 | ||
|
|
caed1c37e0 | ||
|
|
de6a5de914 | ||
|
|
cd428a047f | ||
|
|
417fe29dc0 | ||
|
|
a7d2f7531c | ||
|
|
c786abf1e9 | ||
|
|
622544a902 | ||
|
|
6481161ef2 | ||
|
|
6e11494d0b | ||
|
|
7886cfe408 | ||
|
|
368734b8ab | ||
|
|
e240a16a20 | ||
|
|
4a08779bc8 | ||
|
|
3ca288aba4 | ||
|
|
6c0b5cd76c | ||
|
|
c3ccd42a23 | ||
|
|
f9278e518c | ||
|
|
40bf582c81 | ||
|
|
81398c1fde | ||
|
|
08ee965270 | ||
|
|
65b8dd48d8 | ||
|
|
91d16c9b3a | ||
|
|
60ba2013c4 | ||
|
|
b9413fe59d | ||
|
|
ca8843102a | ||
|
|
9b9a818c43 | ||
|
|
7e4c0b304b | ||
|
|
90c3d87e21 | ||
|
|
dd444fd429 | ||
|
|
58b9203b9b | ||
|
|
ddaf2cfdc5 | ||
|
|
1321e8a6df | ||
|
|
6d7e281dc8 | ||
|
|
32ff2ff8fb | ||
|
|
a45b1a9205 | ||
|
|
123b35a7f1 | ||
|
|
77ae8b65f7 | ||
|
|
5656cb34b8 | ||
|
|
7616cb38a7 | ||
|
|
a9eb267f92 | ||
|
|
496dbb6b7e | ||
|
|
3e6e01eb94 | ||
|
|
42d84bbd70 | ||
|
|
650f7a920a | ||
|
|
7b17f15703 | ||
|
|
8f00240c73 | ||
|
|
3ac4c1f03f | ||
|
|
a45862c93f | ||
|
|
623ed84b23 | ||
|
|
000bbd45b8 | ||
|
|
016ac8ff6e | ||
|
|
aaef07e637 | ||
|
|
101cd90d37 | ||
|
|
32ebd9e221 | ||
|
|
bbd6b478ac | ||
|
|
7ca1b0704d | ||
|
|
1ac0ab2b71 | ||
|
|
d6ffbc0148 | ||
|
|
4a38c2d800 | ||
|
|
f6648a0d4d | ||
|
|
82d204e932 | ||
|
|
97414cc931 | ||
|
|
5451635df0 | ||
|
|
1de1ca906a | ||
|
|
28f6e10e5a | ||
|
|
ac33694028 | ||
|
|
9e3011dbcd | ||
|
|
c97706de50 | ||
|
|
844ef4291c | ||
|
|
43ca4d5bfd | ||
|
|
3f7bb61b7f | ||
|
|
39b30b76ea | ||
|
|
37d64e6a00 | ||
|
|
4236c17654 | ||
|
|
24db18f34e | ||
|
|
405adb938b | ||
|
|
4068a62fa6 | ||
|
|
c4b8e106c0 | ||
|
|
f1e2304585 | ||
|
|
77f427acc8 | ||
|
|
e1f25253db | ||
|
|
a218c9696c | ||
|
|
5df0362361 | ||
|
|
2f7c413199 | ||
|
|
66058c8cfe | ||
|
|
d386ec0a2b | ||
|
|
3ad0639b2e | ||
|
|
ea7e273a06 | ||
|
|
383b21e20a | ||
|
|
a5bdb8103b | ||
|
|
0cbffb15cc | ||
|
|
27cb84eee0 | ||
|
|
b268e37663 | ||
|
|
c9f20516ac | ||
|
|
a1683eb4e8 | ||
|
|
eab4227cbf | ||
|
|
11fc8374c0 | ||
|
|
8968c447f4 | ||
|
|
7b47d69efe | ||
|
|
3da6450b0c | ||
|
|
2ea26cd4d7 | ||
|
|
100291ec42 | ||
|
|
2047929cb5 | ||
|
|
7732da41ba | ||
|
|
93fc60720a | ||
|
|
bb150185ac | ||
|
|
c75f6f408e | ||
|
|
4bb3e0da15 | ||
|
|
576bf8f6c0 | ||
|
|
1a11bb936b | ||
|
|
4602d940cf | ||
|
|
38f18d9aa2 | ||
|
|
b7bc3ec20d | ||
|
|
409ff41c03 | ||
|
|
23f7ccbdda | ||
|
|
2c4bbacec1 | ||
|
|
343c42e4ef | ||
|
|
37168c0a95 | ||
|
|
d3c6aa12d1 | ||
|
|
bb36a26950 | ||
|
|
6b77fa5b3b | ||
|
|
5e320994f4 | ||
|
|
160b165358 | ||
|
|
7fc8814d13 | ||
|
|
4e580d5b39 | ||
|
|
a315d6330c | ||
|
|
48c3340d95 | ||
|
|
341f698ace | ||
|
|
e3c580e905 | ||
|
|
6d241e972b | ||
|
|
83632f15a9 | ||
|
|
bbb2393031 | ||
|
|
c31d7ef70a | ||
|
|
3666935c06 | ||
|
|
8e125b2953 | ||
|
|
026e7bff40 | ||
|
|
bf55d856d2 | ||
|
|
806acbdf12 | ||
|
|
fba2ab0996 | ||
|
|
529ced80f2 | ||
|
|
01fdfc4574 | ||
|
|
f6665edc73 | ||
|
|
c29f08c53e | ||
|
|
bf620363b9 | ||
|
|
f32e59d4b2 | ||
|
|
deb8cd458d | ||
|
|
7c95100180 | ||
|
|
079e5df740 | ||
|
|
2f11870970 | ||
|
|
11b96c214d | ||
|
|
cb604026d6 | ||
|
|
8020cd9994 | ||
|
|
70cc5d87af | ||
|
|
408b62bcc2 | ||
|
|
5a2de2108e | ||
|
|
c7691d8a40 | ||
|
|
f5b68b8950 | ||
|
|
260908cb06 | ||
|
|
79010b9e06 | ||
|
|
06410202d0 | ||
|
|
0c0d31e13a | ||
|
|
17b5870ca1 | ||
|
|
72c7fe5e56 | ||
|
|
a9db673cdf | ||
|
|
ab24a1e36d | ||
|
|
adea26bd8f | ||
|
|
b4cce8e240 | ||
|
|
c65844a7d0 | ||
|
|
994f613450 | ||
|
|
90911a423a | ||
|
|
314071d79f | ||
|
|
fe94bf7c1d | ||
|
|
78e199b5d7 | ||
|
|
a564744cd0 | ||
|
|
18dde0a0bd | ||
|
|
a11182ca84 | ||
|
|
70e17b5f8f | ||
|
|
c8e8cb86ce | ||
|
|
ba3700141f | ||
|
|
2eb5b751f3 | ||
|
|
28fd571d0c | ||
|
|
2c2e8317de | ||
|
|
4dec5ec5f9 | ||
|
|
79c2d22c25 | ||
|
|
8d5fc61c12 | ||
|
|
e023035393 | ||
|
|
c5c571f8ec | ||
|
|
0ef0e69f03 | ||
|
|
a0d252870c | ||
|
|
ef1e2d6fe0 | ||
|
|
83dc8cc13b | ||
|
|
a67c992c36 | ||
|
|
1647c12c73 | ||
|
|
c4942d931c | ||
|
|
2d15b8fe78 | ||
|
|
fa79b40946 | ||
|
|
91559191c9 | ||
|
|
832b5a36fa | ||
|
|
38ebf5ac9f | ||
|
|
6a59b37bea | ||
|
|
dee9aef975 | ||
|
|
6ff111a141 | ||
|
|
1b3cd01851 | ||
|
|
fa1a5f2a42 | ||
|
|
fc1469175b | ||
|
|
6ad0a22602 | ||
|
|
370d790776 | ||
|
|
1b8790aeb2 | ||
|
|
828545c128 | ||
|
|
fd6eeed5c4 | ||
|
|
6301582e77 | ||
|
|
0d5e98a201 | ||
|
|
4321db401c | ||
|
|
c7d1f95240 | ||
|
|
1eddb5cf98 | ||
|
|
b89fe86fa1 | ||
|
|
cb9ab213bb | ||
|
|
326e379154 | ||
|
|
8a15231475 | ||
|
|
886230f64f | ||
|
|
d907f43e6e | ||
|
|
d40cce92bf | ||
|
|
442ec7113e | ||
|
|
2660859434 | ||
|
|
6935addd38 | ||
|
|
2275625e1a | ||
|
|
61fac1bbc1 | ||
|
|
0a614217ce | ||
|
|
57cda797f3 | ||
|
|
b0f1b5f65b | ||
|
|
b621321ea0 | ||
|
|
066b92c7cd | ||
|
|
57ad506cde | ||
|
|
7f64dbc1ba | ||
|
|
e943cce125 | ||
|
|
ac03b81624 | ||
|
|
bb4979a82e | ||
|
|
0f1fcc3f4b | ||
|
|
562831ec1a | ||
|
|
45e78728bd | ||
|
|
ec44fb79d8 | ||
|
|
86fcdd0bae | ||
|
|
104fa96d4d | ||
|
|
8bb7525fe0 | ||
|
|
b7e245aba1 | ||
|
|
265aa3da29 | ||
|
|
5beadd90ee | ||
|
|
fd25f594cd | ||
|
|
01a9b32637 | ||
|
|
46ed623dad | ||
|
|
de30defb62 | ||
|
|
b0b31e67da | ||
|
|
8ea864d6eb | ||
|
|
8bf7ec0c21 | ||
|
|
4cfe5ecaa4 | ||
|
|
a798a40026 | ||
|
|
0f7c25fc63 | ||
|
|
2c8dc9e0bd | ||
|
|
322bde526c | ||
|
|
55c8aa7f1c | ||
|
|
322a303683 | ||
|
|
5f5322c64e | ||
|
|
bc10be3de6 | ||
|
|
fb4a8e9cb9 | ||
|
|
22fed0c798 | ||
|
|
94e825378c | ||
|
|
4a90056462 | ||
|
|
3deffa859d | ||
|
|
003a5a0160 | ||
|
|
72c63a10ee | ||
|
|
cc30f4c4fd | ||
|
|
438ac61ff7 | ||
|
|
b3edfd7d89 | ||
|
|
6dff60b899 | ||
|
|
93bee69266 | ||
|
|
c320da5ec8 | ||
|
|
560c0e72e6 | ||
|
|
2337237d58 | ||
|
|
ee57c95aa6 | ||
|
|
42ec7b317f | ||
|
|
6f076f7433 | ||
|
|
ef7947d176 | ||
|
|
595b0663b2 | ||
|
|
300c7a4b04 | ||
|
|
3b81312cf7 | ||
|
|
51db1efb8a | ||
|
|
aeeb2a259f | ||
|
|
fd4a0626c5 | ||
|
|
7c2303c758 | ||
|
|
b842a4b133 | ||
|
|
7c19ae302e | ||
|
|
8b2bffcf9e | ||
|
|
156a97b80d | ||
|
|
a0a5e4abb2 | ||
|
|
91173320e6 | ||
|
|
f087f8e205 | ||
|
|
7177e941eb | ||
|
|
3fbc3869dc | ||
|
|
cda13e5e79 | ||
|
|
022ffe69e0 | ||
|
|
5a5eb43359 | ||
|
|
5f461cd5cd | ||
|
|
850051463b | ||
|
|
ddec87224c | ||
|
|
d7b8cce162 | ||
|
|
83993fede8 | ||
|
|
d2653e8192 | ||
|
|
f068ed9ee7 | ||
|
|
e8735cc005 | ||
|
|
b160093b91 | ||
|
|
da0fd10423 | ||
|
|
2a161e1725 | ||
|
|
04855bc499 | ||
|
|
2b26206ea2 | ||
|
|
9488ef4867 | ||
|
|
e1c374de6e | ||
|
|
6feec2e2a5 | ||
|
|
211d7825d3 | ||
|
|
9d9d6ca20b | ||
|
|
73eb5af2cc | ||
|
|
8fa48d1c04 | ||
|
|
c4134c3516 | ||
|
|
136105e353 | ||
|
|
0fb6dc79d8 | ||
|
|
7a36322432 | ||
|
|
6a4d9309b2 | ||
|
|
9fc6b9dda2 | ||
|
|
2f3fcb9dbe | ||
|
|
ea97f43145 | ||
|
|
bb2715e7a5 | ||
|
|
2b24b26e59 | ||
|
|
640877ebf8 | ||
|
|
5a320222e2 | ||
|
|
e058d11657 | ||
|
|
874af5c982 | ||
|
|
56cdf94f95 | ||
|
|
fc34076c2b | ||
|
|
cc2cd95ec5 | ||
|
|
54a506c8eb | ||
|
|
d5dfb19508 | ||
|
|
fe7947da90 | ||
|
|
14f4108e55 | ||
|
|
6248aaf8dd | ||
|
|
0fd8513c80 | ||
|
|
aec3c3fb66 | ||
|
|
5d3692c16f | ||
|
|
5df0fd9dc8 | ||
|
|
ce8af7d499 | ||
|
|
c6bf39b283 | ||
|
|
f1fd457411 | ||
|
|
eae0674f61 | ||
|
|
0bb29e092d | ||
|
|
bbba9ff906 | ||
|
|
c2282ce4bd | ||
|
|
5354e804d0 | ||
|
|
bdae243552 | ||
|
|
8a69a09868 | ||
|
|
13877ce2c8 | ||
|
|
8acbfca06b | ||
|
|
cf6d36cb72 | ||
|
|
e79751c8d4 | ||
|
|
2c87dfef8a | ||
|
|
8f7a0ca90c | ||
|
|
3c76cc21ec | ||
|
|
9aa18d29a5 | ||
|
|
cc386f2345 | ||
|
|
72057bf7ef | ||
|
|
87d0175c76 | ||
|
|
3090550e53 | ||
|
|
f2b1b3f6b8 | ||
|
|
26f5390ac0 | ||
|
|
73ac019882 | ||
|
|
1cc5492784 | ||
|
|
fd8e330760 | ||
|
|
daf75dd375 | ||
|
|
4d078fdb03 | ||
|
|
86d023b02f | ||
|
|
c13d1e8ae6 | ||
|
|
82dd5fee12 | ||
|
|
428f10f9ee | ||
|
|
52e3d5e4f0 | ||
|
|
5b5c161601 | ||
|
|
811ae1a936 | ||
|
|
9c8952aef0 | ||
|
|
118da36b52 | ||
|
|
022b6973b2 | ||
|
|
7aa101ba8b | ||
|
|
dac584f7d6 | ||
|
|
48fe013549 | ||
|
|
f67c625e6a | ||
|
|
b280ea5579 | ||
|
|
7be30bb249 | ||
|
|
9b56ca3961 | ||
|
|
a2c3db666e | ||
|
|
5547df6073 | ||
|
|
28fc58067b | ||
|
|
a9709a635c | ||
|
|
ada884a129 | ||
|
|
3aba515bbc | ||
|
|
94ffd4bfc0 | ||
|
|
208374afa4 | ||
|
|
664e14b91f | ||
|
|
e1dcd79e48 | ||
|
|
1f29124d11 | ||
|
|
a08b4f780c | ||
|
|
6646ef71da | ||
|
|
3fd0ec99ae | ||
|
|
0a2dc1efb0 | ||
|
|
cdc5022305 | ||
|
|
5ba9f6a966 | ||
|
|
091ddb3c34 | ||
|
|
1b8b73ce71 | ||
|
|
82329124ff | ||
|
|
36c4519d7e | ||
|
|
c81dac774a | ||
|
|
1957eb9429 | ||
|
|
63d670c286 | ||
|
|
94e6be6cae | ||
|
|
f1c7df8c28 | ||
|
|
78ab97ab04 | ||
|
|
d355bf0267 | ||
|
|
2cecc6ec2c | ||
|
|
49cab41fdf | ||
|
|
b0a8d825b3 | ||
|
|
af60a2fdf6 | ||
|
|
b602714e06 | ||
|
|
013a28a527 | ||
|
|
d46aa92f0b | ||
|
|
55a7f6f0ce | ||
|
|
c67d1b62e3 | ||
|
|
e00b128a50 | ||
|
|
400fb79dc2 | ||
|
|
7c5b70d304 | ||
|
|
221b103721 | ||
|
|
c0dc2d0238 | ||
|
|
37a68aebcf | ||
|
|
a332930cdf | ||
|
|
e44b62d5a3 | ||
|
|
d76b0223d9 | ||
|
|
338a816ffd | ||
|
|
c1381ac598 | ||
|
|
51b7322a0f | ||
|
|
b90ff86f8c | ||
|
|
089428857c | ||
|
|
e07ea24610 | ||
|
|
2225cc9608 | ||
|
|
727cd68cee | ||
|
|
6d18bd0633 | ||
|
|
ee2c3607ad | ||
|
|
21ffcbddad | ||
|
|
21e5a2e071 | ||
|
|
4cd7d11391 | ||
|
|
cc98bd6b6d | ||
|
|
dd7e0f80fe | ||
|
|
1a64b9f0c2 | ||
|
|
4fcd178c36 | ||
|
|
152422af81 | ||
|
|
cf70267871 | ||
|
|
7733b87431 | ||
|
|
5e48dd9d45 | ||
|
|
39242c978f | ||
|
|
75a624434c | ||
|
|
7c4964fae6 | ||
|
|
9c65abd746 | ||
|
|
2579071b98 | ||
|
|
975964f9f0 | ||
|
|
bf2b4814e0 | ||
|
|
12a57ff1c2 | ||
|
|
94236bf4eb | ||
|
|
f9ee24f8f0 | ||
|
|
28b85762fd | ||
|
|
ff571f3b5d | ||
|
|
aa5c80f8a6 | ||
|
|
c44279bb10 | ||
|
|
569967ac21 | ||
|
|
f6a7e5ea23 | ||
|
|
8e9667d86c | ||
|
|
ce54fd334d | ||
|
|
1c6c75da4f | ||
|
|
9bc79f840e | ||
|
|
37a7df49d6 | ||
|
|
fcc82ebd35 | ||
|
|
c7a0b419a9 | ||
|
|
032b7c68d8 | ||
|
|
55e2dbdbc8 | ||
|
|
6d0ac6593c | ||
|
|
30f1d0991b | ||
|
|
7c5fcecbec | ||
|
|
eb7ccf8afa | ||
|
|
f3c00e96aa | ||
|
|
27cee90e5e | ||
|
|
f1587da480 | ||
|
|
6c26bb1cf8 | ||
|
|
e6695cf2ec | ||
|
|
a635f078c6 | ||
|
|
667c43398c | ||
|
|
cd407d1c3f | ||
|
|
6c9f3066fd | ||
|
|
7473b612c5 | ||
|
|
1340b17424 | ||
|
|
e38f511737 | ||
|
|
71ebd99dfa | ||
|
|
cfed9fa4b9 | ||
|
|
e7bb7dd78b | ||
|
|
f7d4437b3f | ||
|
|
8cc81509d7 | ||
|
|
c090dd2f81 | ||
|
|
47826a1262 | ||
|
|
89d909ab43 | ||
|
|
35a4a07320 | ||
|
|
ec35966715 | ||
|
|
9f7a8832a1 | ||
|
|
c6f4bbd143 | ||
|
|
53bdf22c85 | ||
|
|
717f55b012 | ||
|
|
f8e523b277 | ||
|
|
49c8c31220 | ||
|
|
284aca68c0 | ||
|
|
ca406637af | ||
|
|
a254f3d02c | ||
|
|
7a8a0f6b4b | ||
|
|
40ff17c9f9 | ||
|
|
354f872919 | ||
|
|
a19ddfc578 | ||
|
|
875706f660 | ||
|
|
59527165ec | ||
|
|
d06c79f5d3 | ||
|
|
d0c80b5b55 | ||
|
|
90a7b5ebce | ||
|
|
91f97ca02f | ||
|
|
1e2828b80e | ||
|
|
4cb41ac425 | ||
|
|
8a94d4fcf9 | ||
|
|
b180f18b7e | ||
|
|
82cbd4327f | ||
|
|
bb2fb93355 | ||
|
|
a10564c3b1 | ||
|
|
7cc3b877dc | ||
|
|
cd8278dceb | ||
|
|
06892775d4 | ||
|
|
43a9092c16 | ||
|
|
1727a9eca9 | ||
|
|
8b4a89c445 | ||
|
|
e606a74de3 | ||
|
|
858828d343 | ||
|
|
de1eae288c | ||
|
|
03d119d539 | ||
|
|
7acbbf2ef3 | ||
|
|
23bb3bd963 | ||
|
|
a0cac05555 | ||
|
|
3edb1eed8d | ||
|
|
ad2baccefa | ||
|
|
9e5c264012 | ||
|
|
d722008367 | ||
|
|
3dce1dd240 | ||
|
|
b05932310b | ||
|
|
97fb15ac49 | ||
|
|
dd45473356 | ||
|
|
558d36c1f3 | ||
|
|
311d730bce | ||
|
|
d706a30849 | ||
|
|
2b5bde4071 | ||
|
|
5a95aaaa54 | ||
|
|
cfd8ea8eb0 | ||
|
|
56735d4ff5 | ||
|
|
13473ee138 | ||
|
|
97e8800677 | ||
|
|
e20cf8687e | ||
|
|
6fc819dae1 | ||
|
|
d7a003b0bc | ||
|
|
eca0436f58 | ||
|
|
6b5e09478c | ||
|
|
0e5aaab0b5 | ||
|
|
41134f52d9 | ||
|
|
2131dc839a | ||
|
|
4c51c03779 | ||
|
|
dabd61bf80 | ||
|
|
6bfb122cd1 | ||
|
|
89f2eb1023 | ||
|
|
970f79e32f | ||
|
|
82f8914f9e | ||
|
|
65e8199a93 | ||
|
|
f8b8dc1494 | ||
|
|
cad8eed6e4 | ||
|
|
f0d08f4da1 | ||
|
|
4316949a1d | ||
|
|
7a01ff11cd | ||
|
|
c1439bb02b | ||
|
|
a14ebc80d2 | ||
|
|
5486a65702 | ||
|
|
52b1065b3b | ||
|
|
c1404ff2c1 | ||
|
|
c75dd93b92 | ||
|
|
3a45d541f3 | ||
|
|
200388ff96 | ||
|
|
9d570dc645 | ||
|
|
8fc5c6c862 | ||
|
|
1a649a6ac3 | ||
|
|
a7352e57d5 | ||
|
|
fbff355742 | ||
|
|
02693839ca | ||
|
|
894c96f39f | ||
|
|
171230e45d | ||
|
|
fc00a2ba32 | ||
|
|
a677c22e1f | ||
|
|
5f7c6ccfe4 | ||
|
|
22da843efa | ||
|
|
2e5cb930de | ||
|
|
cfd91a3b56 | ||
|
|
6a3d238b7e | ||
|
|
31206cfa0a | ||
|
|
95cbd69e48 | ||
|
|
f41cce96a3 | ||
|
|
c50a460ce6 | ||
|
|
642f5a84d4 | ||
|
|
9d1527b1df | ||
|
|
67f052a6e1 | ||
|
|
05fcec829e | ||
|
|
0abbedcdae | ||
|
|
6df2326a30 | ||
|
|
001275339b | ||
|
|
3d47a8a2fd | ||
|
|
887bc12350 | ||
|
|
9772777919 | ||
|
|
d323ce2c42 | ||
|
|
7c0c798c90 | ||
|
|
05dc04dacc | ||
|
|
0d7becff87 | ||
|
|
6fa4ec22c5 | ||
|
|
37eccbcd33 | ||
|
|
e3dfffb77b | ||
|
|
060b592fc8 | ||
|
|
cd30a4e2d4 | ||
|
|
c70150847d | ||
|
|
2e94a730cc | ||
|
|
a9cdd6614a | ||
|
|
0ad8815bbc | ||
|
|
d4969783d7 | ||
|
|
f5e1ee010b | ||
|
|
e24c0dda5d | ||
|
|
4b39d17e5f | ||
|
|
c1908147a9 | ||
|
|
6aebae5a98 | ||
|
|
714a793a0e | ||
|
|
94fce43ed9 | ||
|
|
c3f8f6bc42 | ||
|
|
97fcf7079b | ||
|
|
cb4c54eec1 | ||
|
|
9702898dcd | ||
|
|
97eb7f2c98 | ||
|
|
f9de29ed8c | ||
|
|
246f6318e4 | ||
|
|
d5ecbfc539 | ||
|
|
750c3d05aa | ||
|
|
dfc4dbdbd3 | ||
|
|
d58b366123 | ||
|
|
d90b600bc1 | ||
|
|
d3afb595dc | ||
|
|
639be7f7bc | ||
|
|
b6b7707dc3 | ||
|
|
624e09533c | ||
|
|
42938de973 | ||
|
|
e6d38cb64e | ||
|
|
524f56354c | ||
|
|
5e9da04ab7 | ||
|
|
f4ee48eaf4 | ||
|
|
d141d2445d | ||
|
|
b08d086b0f | ||
|
|
7e7634d344 | ||
|
|
ecefe41728 | ||
|
|
34cb9cf1fe | ||
|
|
76ef6e3ecc | ||
|
|
0f9f04e4ec | ||
|
|
aa25381651 | ||
|
|
5f71fbc6b3 | ||
|
|
ecd0f9d0e7 | ||
|
|
f2116c50c0 | ||
|
|
c15e09b71e | ||
|
|
f68cba0c71 | ||
|
|
80772c2419 | ||
|
|
b9bb4dfc06 | ||
|
|
719980a948 | ||
|
|
5684f8886f | ||
|
|
b552ad7065 | ||
|
|
1f2d229862 | ||
|
|
fa3d9d32ae | ||
|
|
e35b128fa3 | ||
|
|
6de49f515e | ||
|
|
007ea500d0 | ||
|
|
490b1e2532 | ||
|
|
8269a6dc37 | ||
|
|
78266db427 | ||
|
|
b0fe23072d | ||
|
|
a21e0c652c | ||
|
|
0b6293e2f5 | ||
|
|
9181db1304 | ||
|
|
dcece31519 | ||
|
|
aab6f27503 | ||
|
|
74cedd3255 | ||
|
|
d1061692d5 | ||
|
|
481c70311a | ||
|
|
4d234e3abc | ||
|
|
37a321a601 | ||
|
|
7c8be94a6e | ||
|
|
1c648f9714 | ||
|
|
fdc7c183e8 | ||
|
|
f80b328937 | ||
|
|
5a2f85600d | ||
|
|
7356be0164 | ||
|
|
a8e013dcb6 | ||
|
|
c3dec709ab | ||
|
|
6402b23041 | ||
|
|
1158d35021 | ||
|
|
e65815e34c | ||
|
|
021e383418 | ||
|
|
0291dc8214 | ||
|
|
ce755483ba | ||
|
|
de2981a767 | ||
|
|
41b9825f00 | ||
|
|
6f695b93d5 | ||
|
|
f2edd5d068 | ||
|
|
f0ef11b856 | ||
|
|
12066a60f3 | ||
|
|
4666879f94 | ||
|
|
fb55db665c | ||
|
|
7f50c3d08e | ||
|
|
461e33104e | ||
|
|
ed992ae6a1 | ||
|
|
b608152c41 | ||
|
|
5cf1ef7be0 | ||
|
|
6649a82776 | ||
|
|
0ac883c6d4 | ||
|
|
20a0508a16 | ||
|
|
42934a1006 | ||
|
|
3b8ddd0997 | ||
|
|
377e6c3210 | ||
|
|
61160ff9e5 | ||
|
|
9599615b23 | ||
|
|
6b80865bfe | ||
|
|
ed1c84445c | ||
|
|
f993888424 | ||
|
|
6f6f388f38 | ||
|
|
558ef7352d | ||
|
|
31d688ad3d | ||
|
|
84ce3a9ea1 | ||
|
|
792837bd71 | ||
|
|
e93c587b8e | ||
|
|
bb73a0e2cb | ||
|
|
243ab45111 | ||
|
|
71c3483f55 | ||
|
|
4b476f13bb | ||
|
|
2681e769a6 | ||
|
|
c2673aa970 | ||
|
|
f54c94d6c9 | ||
|
|
9aeb61181a | ||
|
|
1f8de33e75 | ||
|
|
9ed9885c8d | ||
|
|
e7181eb89c | ||
|
|
90dc897f71 | ||
|
|
8993a2c6ed | ||
|
|
704af29543 | ||
|
|
134872e9c1 | ||
|
|
e741bc0577 | ||
|
|
e62349cffb | ||
|
|
8664dd2139 | ||
|
|
ee67211035 | ||
|
|
582ef30b4a | ||
|
|
1b3568e66e | ||
|
|
3575dae75c | ||
|
|
673335de4b | ||
|
|
48dd8f96b7 | ||
|
|
72579f9bab | ||
|
|
5a81cfbbc6 | ||
|
|
c3bcb606a9 | ||
|
|
8e07e7483f | ||
|
|
e400585a0e | ||
|
|
e648662cfd | ||
|
|
2d90e763ad | ||
|
|
379bd79de4 | ||
|
|
e4d5ae53fc | ||
|
|
71795ecc62 | ||
|
|
685948bcaa | ||
|
|
dd2c2660b9 | ||
|
|
86af20ded0 | ||
|
|
9d090e00f2 | ||
|
|
e085c01a2e | ||
|
|
9c0e579bd3 | ||
|
|
06bf72da67 | ||
|
|
4673c67835 | ||
|
|
f685e389d3 | ||
|
|
94299f6cd8 | ||
|
|
2bf1131dab | ||
|
|
3cfe66e4c3 | ||
|
|
0d12fc3033 | ||
|
|
30405a3441 | ||
|
|
e79b18762e | ||
|
|
83f01096c0 | ||
|
|
5d2452608d | ||
|
|
50a5a69c46 | ||
|
|
1882b88c78 | ||
|
|
3fea581ec8 | ||
|
|
c8ef15cf40 | ||
|
|
e3bb3c3906 | ||
|
|
d88fa8b787 | ||
|
|
068f0cce96 | ||
|
|
cf36fdecbf | ||
|
|
a9dcce82ed | ||
|
|
5f48f91d94 | ||
|
|
15503a3b9e | ||
|
|
5c15d263e0 | ||
|
|
cde0c1d418 | ||
|
|
44c66fc284 | ||
|
|
3885674877 | ||
|
|
0937b84b01 | ||
|
|
51f89048d6 | ||
|
|
134d3f98c9 | ||
|
|
ba24920fec | ||
|
|
569b87ff83 | ||
|
|
8c138e74be | ||
|
|
2f4fd3324b | ||
|
|
69e7afee26 | ||
|
|
fdab98aa59 | ||
|
|
35a512310a | ||
|
|
3b2a494033 | ||
|
|
b0820e4886 | ||
|
|
4ab7b2d2b1 | ||
|
|
c31bf8474c | ||
|
|
cc6bcb6c81 | ||
|
|
65ee977a86 | ||
|
|
f170914def | ||
|
|
ea9d33374f | ||
|
|
7f664aa18c | ||
|
|
1413f22095 | ||
|
|
a3e33a313a | ||
|
|
411da169ac | ||
|
|
78468098c5 | ||
|
|
9000bd6679 | ||
|
|
413fdc6f0d | ||
|
|
9c7854aef6 | ||
|
|
bf862d1d07 | ||
|
|
8bbe28e998 | ||
|
|
702f1631a3 | ||
|
|
eea4e60b73 | ||
|
|
5a4c2fb61d | ||
|
|
498f5d65fd | ||
|
|
3b3e69f8b2 | ||
|
|
503b0ba1b1 | ||
|
|
bc34ca9e25 | ||
|
|
7d4ff3b061 | ||
|
|
8a1884c407 | ||
|
|
e7f175d578 | ||
|
|
4c7b48e596 | ||
|
|
1681ee35db | ||
|
|
7b8890a4c9 | ||
|
|
2eaa6d0874 | ||
|
|
cad3d694ab | ||
|
|
e73326a324 | ||
|
|
90bd1fd7e9 | ||
|
|
ca42325ade | ||
|
|
7516b059fe | ||
|
|
d8f16f4116 | ||
|
|
26a071ea00 | ||
|
|
7dec3c9320 | ||
|
|
731240e0e9 | ||
|
|
a5a068b2ee | ||
|
|
2435ffaf09 | ||
|
|
795447f61a | ||
|
|
a3d4d461a3 | ||
|
|
3635872f37 | ||
|
|
199cf31b9e | ||
|
|
dc29b3add1 | ||
|
|
642dc96956 | ||
|
|
e9808d138f | ||
|
|
b530d70a7b | ||
|
|
1005a63130 | ||
|
|
52c0864cb8 | ||
|
|
3a55e5b384 | ||
|
|
847cf17b77 | ||
|
|
e9de194b89 | ||
|
|
e76d5bc7cf | ||
|
|
6d82966ebe | ||
|
|
efeabfe3ef | ||
|
|
738b10adea | ||
|
|
dfa1dc43df | ||
|
|
bf491de9fe | ||
|
|
2abc69780e | ||
|
|
1db05a2655 | ||
|
|
b05d818f45 | ||
|
|
837a2d4bbd | ||
|
|
35cbe9d140 | ||
|
|
b722150d87 | ||
|
|
5336b4a89c | ||
|
|
e84d7c0cda | ||
|
|
53229e3d6c | ||
|
|
fdd66bd76d | ||
|
|
ccf30e0934 | ||
|
|
25f04d5b03 | ||
|
|
f7786a9e48 | ||
|
|
cc608a3fb0 | ||
|
|
da9f12d1e2 | ||
|
|
35cc197d0b | ||
|
|
18362eb948 | ||
|
|
3948323a8c | ||
|
|
7e3b690257 | ||
|
|
b9ab2fe0fb | ||
|
|
81c23b84e7 | ||
|
|
b25175a19a | ||
|
|
39e0433570 | ||
|
|
9d05c59600 | ||
|
|
2fcf2c81bf | ||
|
|
9fec1a3cb4 | ||
|
|
b7b40d9c3a | ||
|
|
653ceb9860 | ||
|
|
0e5b6f9300 | ||
|
|
31eb5e26e3 | ||
|
|
12b37c7386 | ||
|
|
7cad5d0cd2 | ||
|
|
e6bad6e183 | ||
|
|
f5d207f8f0 | ||
|
|
da7fc54e37 | ||
|
|
0ec2eba2a3 | ||
|
|
dcb369ee46 | ||
|
|
041b32b01f | ||
|
|
cdab073614 | ||
|
|
fbd5e4c2b3 | ||
|
|
5eb0a89579 | ||
|
|
9fa08fdbc0 | ||
|
|
6f00e4a014 | ||
|
|
f52f752acd | ||
|
|
d846c9006e | ||
|
|
69ca6ccdc1 | ||
|
|
25d966110e | ||
|
|
e03f7baa60 | ||
|
|
62635f43f4 | ||
|
|
248d572077 | ||
|
|
60f69ad77b | ||
|
|
b02edd014a | ||
|
|
024f84f1be | ||
|
|
5d870837cf | ||
|
|
de576fa82e | ||
|
|
412b9e9ad8 | ||
|
|
8f78bd3307 | ||
|
|
91a339b625 | ||
|
|
1a9b056e93 | ||
|
|
abc6003640 | ||
|
|
76683c0af5 | ||
|
|
128cb7f5b2 | ||
|
|
8c0c1e4ded | ||
|
|
e59f788c43 | ||
|
|
8d6c7955ad | ||
|
|
233679865b | ||
|
|
6a61ec7763 | ||
|
|
1b866e20c6 | ||
|
|
75c17cf846 | ||
|
|
8250dbd172 | ||
|
|
0d83b69fe2 | ||
|
|
a6412d0690 | ||
|
|
dda64bd652 | ||
|
|
9d6db65c7c | ||
|
|
5783ce0b3c | ||
|
|
8ef705ad10 | ||
|
|
381cf55434 | ||
|
|
15ce235eed | ||
|
|
3be92f550c | ||
|
|
366638b1b9 | ||
|
|
fa6510a90c | ||
|
|
816a96c2cc | ||
|
|
c87fc2426d | ||
|
|
c611eb061d | ||
|
|
aa3eafcea1 | ||
|
|
66fab65a1a | ||
|
|
a25b49a127 | ||
|
|
a3124e8873 | ||
|
|
bffb31c337 | ||
|
|
44e7282b4b | ||
|
|
c2aa312e0c | ||
|
|
384b03d49b | ||
|
|
6650a06339 | ||
|
|
c256a43139 | ||
|
|
0d9a157914 | ||
|
|
47950f7b97 | ||
|
|
f9c48e1fb0 | ||
|
|
973647eaa2 | ||
|
|
3bda63c350 | ||
|
|
88b887fe47 | ||
|
|
58e15c7755 | ||
|
|
7365a45948 | ||
|
|
e8a57376f0 | ||
|
|
8e51659237 | ||
|
|
c403968230 | ||
|
|
9d4c68d272 | ||
|
|
8268afdf33 | ||
|
|
975e6e6194 | ||
|
|
99d9e262eb | ||
|
|
037ee0cff3 | ||
|
|
91ee99ab8a | ||
|
|
64fc523977 | ||
|
|
b869471068 | ||
|
|
322f7dadc7 | ||
|
|
191463397b | ||
|
|
683e02fbcd | ||
|
|
ebbecce56d | ||
|
|
e98637596d | ||
|
|
3c66e810c0 | ||
|
|
20ca6b4a55 | ||
|
|
69b0a358f3 | ||
|
|
8dd44f66ca | ||
|
|
eeb5845aac | ||
|
|
fe4762588c | ||
|
|
c3362c7617 | ||
|
|
ffd607bb52 | ||
|
|
d7360e3203 | ||
|
|
879d21c80e | ||
|
|
3623cf9729 | ||
|
|
8d219e94dc | ||
|
|
d552af97c3 | ||
|
|
fc7e50dce2 | ||
|
|
bdc0cd4418 | ||
|
|
cdcd031192 | ||
|
|
a38fb5df41 | ||
|
|
66c0d6620b | ||
|
|
29b03fc242 | ||
|
|
e0b77db46f | ||
|
|
f0d9b93ede | ||
|
|
f398b5d843 | ||
|
|
b8259a82c1 | ||
|
|
7bcea57241 | ||
|
|
3cd6c2e9eb | ||
|
|
455a61d210 | ||
|
|
83e94f3de1 | ||
|
|
ffdd6ab821 | ||
|
|
60fe728c0f | ||
|
|
b209620514 | ||
|
|
e5f4916e31 | ||
|
|
5212b98c87 | ||
|
|
88fa343387 | ||
|
|
40bd3336a5 | ||
|
|
bf92fa88b7 | ||
|
|
6ea2755095 | ||
|
|
f047bb61bb | ||
|
|
747495e77c | ||
|
|
159a25d8e7 | ||
|
|
c8cc021ea1 | ||
|
|
7d9c1a80f0 | ||
|
|
ff8f439afd | ||
|
|
fd0e7dc4ab | ||
|
|
ed909cd54c | ||
|
|
ad0fd82566 | ||
|
|
d2b9766886 | ||
|
|
f56ec818fb | ||
|
|
11a1b824c0 | ||
|
|
db542f2a26 | ||
|
|
eb109cf905 | ||
|
|
7197368c6d | ||
|
|
400d6c3de5 | ||
|
|
c78a6fa7d4 | ||
|
|
6b7e73db92 | ||
|
|
70092b493e | ||
|
|
912307386c | ||
|
|
03b4f57d23 | ||
|
|
b5e5de626c | ||
|
|
8155da152f | ||
|
|
1dbaec0edd | ||
|
|
fa483e1fe0 | ||
|
|
4dbe051494 | ||
|
|
3a7a6efffb | ||
|
|
2d26eebca8 | ||
|
|
a259d10bcb | ||
|
|
0a48af9ff7 | ||
|
|
d55c3c5030 | ||
|
|
ab62755a88 | ||
|
|
bd20bde1a2 | ||
|
|
d9bfe6a49d | ||
|
|
8a31e2d9c0 | ||
|
|
a1efa28520 | ||
|
|
e75f2aa087 | ||
|
|
4ad6ecd196 | ||
|
|
ea07d4c6c8 | ||
|
|
0df2d882ea | ||
|
|
553326b006 | ||
|
|
309887c444 | ||
|
|
38834cb997 | ||
|
|
16270fa080 | ||
|
|
e719eab878 | ||
|
|
26520c5cf4 | ||
|
|
a3dcf8ced6 | ||
|
|
5e70868fd0 | ||
|
|
e859228db1 | ||
|
|
9398494100 | ||
|
|
21cda4e7fc | ||
|
|
b7387da085 | ||
|
|
8ca005eb41 | ||
|
|
f5e34deb1a | ||
|
|
b41635e809 | ||
|
|
24d31e2046 | ||
|
|
7160054927 | ||
|
|
b6c353ee80 | ||
|
|
67d9eaa215 | ||
|
|
ebcf4c0224 | ||
|
|
656e403f01 | ||
|
|
41cd6d13c9 | ||
|
|
7b9926807d | ||
|
|
cc4e2fcd94 | ||
|
|
cad1fa50a9 | ||
|
|
0586822808 | ||
|
|
f310222ce1 | ||
|
|
ad207eeabb | ||
|
|
1696237a3f | ||
|
|
269be86998 | ||
|
|
047a8de934 | ||
|
|
39fae3a480 | ||
|
|
40da835cbb | ||
|
|
38aba07290 | ||
|
|
a636fad51e | ||
|
|
d0db7bfb58 | ||
|
|
8d537ee2b6 | ||
|
|
3387f33a8e | ||
|
|
1116a36c15 | ||
|
|
bcf87fd3c9 | ||
|
|
753d5675dd | ||
|
|
be2934d9b5 | ||
|
|
4a1d11b2be | ||
|
|
b1f7cfa9da | ||
|
|
cc9d222923 | ||
|
|
c5b39126ee | ||
|
|
12f4e9b7ea | ||
|
|
742923c73d | ||
|
|
980036b78a | ||
|
|
1387d3969e | ||
|
|
5d6921ff2a | ||
|
|
cbb5004ff9 | ||
|
|
9145a08395 | ||
|
|
3d713baa4c | ||
|
|
14c851e9f8 | ||
|
|
e6db1875d0 | ||
|
|
8e056672bc | ||
|
|
6f574c3802 | ||
|
|
a5c4a2c7c6 | ||
|
|
bfd5f5d221 | ||
|
|
94044b2950 | ||
|
|
51a55810b9 | ||
|
|
1884b9a235 | ||
|
|
730acd59c7 | ||
|
|
c79aecf64d | ||
|
|
f033e23ea3 | ||
|
|
3d219b4be6 | ||
|
|
d950fe3736 | ||
|
|
9cc90ac7d5 | ||
|
|
94dec0ff85 | ||
|
|
c9fa29ef64 | ||
|
|
213ac43721 | ||
|
|
d0bf1a842f | ||
|
|
2d3af6fc38 | ||
|
|
ace550d6b2 | ||
|
|
ac5be7dad7 | ||
|
|
bdfbef41c6 | ||
|
|
e2e1faa225 | ||
|
|
78ab726ec7 | ||
|
|
caa5ea0316 | ||
|
|
a20e02ee23 | ||
|
|
6ac926aa32 | ||
|
|
4cada31f80 | ||
|
|
ff65b7dae1 |
@@ -1,103 +1,159 @@
|
||||
build-steps: &build-steps
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install Node.js 10 on MacOS
|
||||
command: |
|
||||
if [ "$INSTALL_MACOS_NODE" == "true" ]; then
|
||||
echo 'Installing Node.js 10 for MacOS'
|
||||
brew update
|
||||
brew install node@10
|
||||
echo 'export PATH="/usr/local/opt/node@10/bin:$PATH"' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 UPLOAD_TO_S3=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo "Bootstrapping Electron for release build for $TARGET_ARCH"
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo "Bootstrapping Electron for debug build for $TARGET_ARCH"
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run:
|
||||
name: Lint
|
||||
command: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$UPLOAD_TO_S3" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$UPLOAD_TO_S3" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Setup for headless testing
|
||||
command: |
|
||||
if [ "$RUN_HEADLESS_TESTS" == "true" ]; then
|
||||
echo 'Setup for headless testing'
|
||||
sh -e /etc/init.d/xvfb start
|
||||
else
|
||||
echo 'Headless testing not needed'
|
||||
fi
|
||||
|
||||
- run:
|
||||
name: Verify mksnapshot
|
||||
command: |
|
||||
if [ "$RUN_TESTS" == "true" ] && [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Verifying mksnapshot on release build'
|
||||
script/verify-mksnapshot.py
|
||||
else
|
||||
echo 'Skipping mksnapshot tests due to configuration'
|
||||
fi
|
||||
|
||||
- run:
|
||||
name: Test
|
||||
environment:
|
||||
MOCHA_FILE: junit/test-results.xml
|
||||
MOCHA_REPORTER: mocha-junit-reporter
|
||||
command: |
|
||||
if [ "$RUN_TESTS" == "true" ]; then
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Testing Electron debug build'
|
||||
mkdir junit
|
||||
script/test.py --ci --rebuild_native_modules
|
||||
else
|
||||
if [ "$UPLOAD_TO_S3" == "1" ]; then
|
||||
echo 'Testing Electron release build'
|
||||
mkdir junit
|
||||
script/test.py --ci --rebuild_native_modules -c R
|
||||
else
|
||||
echo 'Skipping tests on GitHub release'
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo 'Skipping tests due to configuration'
|
||||
fi
|
||||
- run:
|
||||
name: Verify FFmpeg
|
||||
command: |
|
||||
if [ "$RUN_TESTS" == "true" ]; then
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Verifying ffmpeg on debug build'
|
||||
script/verify-ffmpeg.py
|
||||
else
|
||||
echo 'Verifying ffmpeg on release build'
|
||||
script/verify-ffmpeg.py -R
|
||||
fi
|
||||
else
|
||||
echo 'Skipping tests due to configuration'
|
||||
fi
|
||||
|
||||
- run:
|
||||
name: Generate Typescript Definitions
|
||||
command: |
|
||||
if [ "$CREATE_TYPESCRIPT_DEFS" == "true" ]; then
|
||||
npm run create-typescript-definitions
|
||||
fi
|
||||
- persist_to_workspace:
|
||||
root: out
|
||||
paths:
|
||||
- "*"
|
||||
- store_test_results:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: out
|
||||
|
||||
build-defaults: &build-defaults
|
||||
docker:
|
||||
- image: electronbuilds/electron:0.0.8
|
||||
<<: *build-steps
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
electron-linux-arm:
|
||||
docker:
|
||||
- image: electronbuilds/electron:0.0.7
|
||||
environment:
|
||||
TARGET_ARCH: arm
|
||||
environment:
|
||||
TARGET_ARCH: arm
|
||||
<<: *build-defaults
|
||||
resource_class: 2xlarge
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Bootstrapping Electron for release build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo 'Bootstrapping Electron for debug build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Optionally finish release
|
||||
shell: /bin/sh
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
|
||||
echo 'Trying to finish release'
|
||||
node script/release.js --validateRelease --automaticRelease
|
||||
releaseExitCode=$?
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release is ready to go; releasing'
|
||||
node script/release.js--automaticRelease
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
fi
|
||||
else
|
||||
echo 'Release is not complete, skipping publish for now'
|
||||
fi
|
||||
else
|
||||
echo 'Skipping finishing release because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Zip out directory
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
zip -r electron.zip out/D
|
||||
fi
|
||||
- persist_to_workspace:
|
||||
root: /home/builduser
|
||||
paths:
|
||||
- project/out
|
||||
- store_artifacts:
|
||||
path: electron.zip
|
||||
|
||||
electron-linux-arm-test:
|
||||
machine: true
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
at: /tmp/workspace/project/out
|
||||
- checkout
|
||||
- run:
|
||||
name: Test in ARM docker container
|
||||
@@ -117,103 +173,25 @@ jobs:
|
||||
else
|
||||
echo "Skipping test for release build"
|
||||
fi
|
||||
electron-linux-arm64:
|
||||
docker:
|
||||
- image: electronbuilds/electron:0.0.7
|
||||
environment:
|
||||
TARGET_ARCH: arm64
|
||||
|
||||
electron-linux-arm-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: arm
|
||||
RUN_RELEASE_BUILD: true
|
||||
<<: *build-defaults
|
||||
resource_class: 2xlarge
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Bootstrapping Electron for release build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo 'Bootstrapping Electron for debug build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Optionally finish release
|
||||
shell: /bin/sh
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
|
||||
echo 'Trying to finish release'
|
||||
node script/release.js --validateRelease --automaticRelease
|
||||
releaseExitCode=$?
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release is ready to go; releasing'
|
||||
node script/release.js--automaticRelease
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
fi
|
||||
else
|
||||
echo 'Release is not complete, skipping publish for now'
|
||||
fi
|
||||
else
|
||||
echo 'Skipping finishing release because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Zip out directory
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
zip -r electron.zip out/D
|
||||
fi
|
||||
- persist_to_workspace:
|
||||
root: /home/builduser
|
||||
paths:
|
||||
- project/out
|
||||
- store_artifacts:
|
||||
path: electron.zip
|
||||
|
||||
electron-linux-arm64:
|
||||
environment:
|
||||
TARGET_ARCH: arm64
|
||||
<<: *build-defaults
|
||||
resource_class: 2xlarge
|
||||
|
||||
electron-linux-arm64-test:
|
||||
machine: true
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
at: /tmp/workspace/project/out
|
||||
- checkout
|
||||
- run:
|
||||
name: Test in ARM64 docker container
|
||||
@@ -233,506 +211,91 @@ jobs:
|
||||
else
|
||||
echo "Skipping test for release build"
|
||||
fi
|
||||
|
||||
electron-linux-arm64-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: arm64
|
||||
RUN_RELEASE_BUILD: true
|
||||
<<: *build-defaults
|
||||
resource_class: 2xlarge
|
||||
|
||||
electron-linux-ia32:
|
||||
docker:
|
||||
- image: electronbuilds/electron:0.0.7
|
||||
environment:
|
||||
TARGET_ARCH: ia32
|
||||
DISPLAY: ':99.0'
|
||||
environment:
|
||||
TARGET_ARCH: ia32
|
||||
DISPLAY: ':99.0'
|
||||
RUN_TESTS: true
|
||||
RUN_HEADLESS_TESTS: true
|
||||
<<: *build-defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Setup for headless testing
|
||||
command: sh -e /etc/init.d/xvfb start
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Bootstrapping Electron for release build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo 'Bootstrapping Electron for debug build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Optionally finish release
|
||||
shell: /bin/sh
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
|
||||
echo 'Trying to finish release'
|
||||
node script/release.js --validateRelease --automaticRelease
|
||||
releaseExitCode=$?
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release is ready to go; releasing'
|
||||
node script/release.js--automaticRelease
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
fi
|
||||
else
|
||||
echo 'Release is not complete, skipping publish for now'
|
||||
fi
|
||||
else
|
||||
echo 'Skipping finishing release because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Test
|
||||
environment:
|
||||
MOCHA_FILE: junit/test-results.xml
|
||||
MOCHA_REPORTER: mocha-junit-reporter
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Testing Electron debug build'
|
||||
out/D/electron --version
|
||||
mkdir junit
|
||||
script/test.py --ci --rebuild_native_modules
|
||||
else
|
||||
echo 'Skipping testing on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Verify FFmpeg
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Verifying ffmpeg on debug build'
|
||||
script/verify-ffmpeg.py
|
||||
else
|
||||
echo 'Skipping verify ffmpeg on release build'
|
||||
fi
|
||||
|
||||
electron-linux-ia32-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: ia32
|
||||
RUN_RELEASE_BUILD: true
|
||||
<<: *build-defaults
|
||||
resource_class: xlarge
|
||||
|
||||
electron-linux-mips64el:
|
||||
docker:
|
||||
- image: electronbuilds/electron:0.0.7
|
||||
environment:
|
||||
TARGET_ARCH: mips64el
|
||||
environment:
|
||||
TARGET_ARCH: mips64el
|
||||
<<: *build-defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Bootstrapping Electron for release build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo 'Bootstrapping Electron for debug build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Optionally finish release
|
||||
shell: /bin/sh
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
|
||||
echo 'Trying to finish release'
|
||||
node script/release.js --validateRelease --automaticRelease
|
||||
releaseExitCode=$?
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release is ready to go; releasing'
|
||||
node script/release.js--automaticRelease
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
fi
|
||||
else
|
||||
echo 'Release is not complete, skipping publish for now'
|
||||
fi
|
||||
else
|
||||
echo 'Skipping finishing release because build is not for release'
|
||||
fi
|
||||
|
||||
electron-linux-x64:
|
||||
docker:
|
||||
- image: electronbuilds/electron:0.0.7
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
DISPLAY: ':99.0'
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
DISPLAY: ':99.0'
|
||||
RUN_TESTS: true
|
||||
RUN_HEADLESS_TESTS: true
|
||||
CREATE_TYPESCRIPT_DEFS: true
|
||||
<<: *build-defaults
|
||||
resource_class: xlarge
|
||||
|
||||
electron-linux-x64-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
RUN_RELEASE_BUILD: true
|
||||
<<: *build-defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Setup for headless testing
|
||||
command: sh -e /etc/init.d/xvfb start
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Bootstrapping Electron for release build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo 'Bootstrapping Electron for debug build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Optionally finish release
|
||||
shell: /bin/sh
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
|
||||
echo 'Trying to finish release'
|
||||
node script/release.js --validateRelease --automaticRelease
|
||||
releaseExitCode=$?
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release is ready to go; releasing'
|
||||
node script/release.js--automaticRelease
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
fi
|
||||
else
|
||||
echo 'Release is not complete, skipping publish for now'
|
||||
fi
|
||||
else
|
||||
echo 'Skipping finishing release because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Test
|
||||
environment:
|
||||
MOCHA_FILE: junit/test-results.xml
|
||||
MOCHA_REPORTER: mocha-junit-reporter
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Testing Electron debug build'
|
||||
mkdir junit
|
||||
script/test.py --ci --rebuild_native_modules
|
||||
else
|
||||
echo 'Skipping testing on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Verify FFmpeg
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Verifying ffmpeg on debug build'
|
||||
script/verify-ffmpeg.py
|
||||
else
|
||||
echo 'Skipping verify ffmpeg on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Generate Typescript Definitions
|
||||
command: npm run create-typescript-definitions
|
||||
- store_test_results:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: out/electron.d.ts
|
||||
- store_artifacts:
|
||||
path: out/electron-api.json
|
||||
|
||||
electron-osx-x64:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
RUN_TESTS: true
|
||||
INSTALL_MACOS_NODE: true
|
||||
macos:
|
||||
xcode: "9.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Reclaim disk space
|
||||
command: |
|
||||
df -h
|
||||
sudo rm -rf /Library/Developer/CoreSimulator
|
||||
df -h
|
||||
sysctl -n hw.ncpu
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Bootstrapping Electron for release build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo 'Bootstrapping Electron for debug build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Test
|
||||
environment:
|
||||
MOCHA_FILE: junit/test-results.xml
|
||||
MOCHA_REPORTER: mocha-junit-reporter
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Testing Electron debug build'
|
||||
mkdir junit
|
||||
script/test.py --ci --rebuild_native_modules
|
||||
else
|
||||
echo 'Skipping testing on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Verify FFmpeg
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Verifying ffmpeg on debug build'
|
||||
script/verify-ffmpeg.py
|
||||
else
|
||||
echo 'Skipping verify ffmpeg on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Generate Typescript Definitions
|
||||
command: npm run create-typescript-definitions
|
||||
- store_test_results:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: out/electron.d.ts
|
||||
- store_artifacts:
|
||||
path: out/electron-api.json
|
||||
xcode: "8.3.3"
|
||||
<<: *build-steps
|
||||
|
||||
electron-osx-x64-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
RUN_RELEASE_BUILD: true
|
||||
INSTALL_MACOS_NODE: true
|
||||
macos:
|
||||
xcode: "8.3.3"
|
||||
<<: *build-steps
|
||||
|
||||
electron-mas-x64:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
MAS_BUILD: 1
|
||||
RUN_TESTS: true
|
||||
INSTALL_MACOS_NODE: true
|
||||
macos:
|
||||
xcode: "9.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Reclaim disk space
|
||||
command: |
|
||||
df -h
|
||||
sudo rm -rf /Library/Developer/CoreSimulator
|
||||
df -h
|
||||
sysctl -n hw.ncpu
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Bootstrapping Electron for release build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo 'Bootstrapping Electron for debug build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Test
|
||||
environment:
|
||||
MOCHA_FILE: junit/test-results.xml
|
||||
MOCHA_REPORTER: mocha-junit-reporter
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Testing Electron debug build'
|
||||
mkdir junit
|
||||
script/test.py --ci --rebuild_native_modules
|
||||
else
|
||||
echo 'Skipping testing on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Verify FFmpeg
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Verifying ffmpeg on debug build'
|
||||
script/verify-ffmpeg.py
|
||||
else
|
||||
echo 'Skipping verify ffmpeg on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Generate Typescript Definitions
|
||||
command: npm run create-typescript-definitions
|
||||
- store_test_results:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: out/electron.d.ts
|
||||
- store_artifacts:
|
||||
path: out/electron-api.json
|
||||
xcode: "8.3.3"
|
||||
<<: *build-steps
|
||||
|
||||
electron-mas-x64-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
MAS_BUILD: 1
|
||||
RUN_RELEASE_BUILD: true
|
||||
INSTALL_MACOS_NODE: true
|
||||
macos:
|
||||
xcode: "8.3.3"
|
||||
<<: *build-steps
|
||||
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
@@ -760,3 +323,29 @@ workflows:
|
||||
build-mas-x64:
|
||||
jobs:
|
||||
- electron-mas-x64
|
||||
|
||||
nightly-release-test:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "0 0 * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- 2-0-x
|
||||
- 1-8-x
|
||||
- 1-7-x
|
||||
jobs:
|
||||
- electron-linux-arm-release-nightly
|
||||
- electron-linux-arm64-release-nightly
|
||||
- electron-linux-ia32-release-nightly
|
||||
- electron-linux-x64-release-nightly
|
||||
|
||||
experimental:
|
||||
notify:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- 2-0-x
|
||||
- 1-8-x
|
||||
- 1-7-x
|
||||
|
||||
7
.env.example
Normal file
7
.env.example
Normal file
@@ -0,0 +1,7 @@
|
||||
# These env vars are only necessary for creating Electron releases.
|
||||
# See docs/development/releasing.md
|
||||
|
||||
APPVEYOR_TOKEN=
|
||||
CIRCLE_TOKEN=
|
||||
ELECTRON_GITHUB_TOKEN=
|
||||
VSTS_TOKEN=
|
||||
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@@ -14,8 +14,8 @@
|
||||
*updater* @electron/updater
|
||||
|
||||
# directories
|
||||
/.github/ @electron/hubbers
|
||||
/.github/ @electron/electrocats
|
||||
/default_app/ @electron/docs
|
||||
/docs/ @electron/docs
|
||||
/docs-translations/ @electron/i18n
|
||||
/npm/ @electron/hubbers
|
||||
/npm/ @electron/electrocats
|
||||
3
.github/ISSUE_TEMPLATE.md
vendored
3
.github/ISSUE_TEMPLATE.md
vendored
@@ -10,6 +10,9 @@ Thanks for opening an issue! A few things to keep in mind:
|
||||
* Electron version:
|
||||
* Operating system:
|
||||
|
||||
<!-- If this used to work -->
|
||||
* Last known working Electron version:
|
||||
|
||||
### Expected behavior
|
||||
|
||||
<!-- What do you think should happen? -->
|
||||
|
||||
32
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
32
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve Electron
|
||||
|
||||
---
|
||||
|
||||
* Electron Version:
|
||||
* Operating System (Platform and Version):
|
||||
* Last known working Electron version:
|
||||
|
||||
**Expected Behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Actual behavior**
|
||||
A clear and concise description of what actually happened.
|
||||
|
||||
**To Reproduce**
|
||||
Your best chance of getting this bug looked at quickly is to provide a REPOSITORY that can be cloned and run.
|
||||
|
||||
You can fork [electron-quick-start](https://github.com/electron/electron-quick-start) and include a link to the branch with your changes.
|
||||
|
||||
If you provide a URL, please list the commands required to clone/setup/run your repo e.g.
|
||||
```sh
|
||||
$ git clone $YOUR_URL -b $BRANCH
|
||||
$ npm install
|
||||
$ npm start || electron .
|
||||
```
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional Information**
|
||||
Add any other context about the problem here.
|
||||
17
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for Electron
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is.
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
13
.github/PULL_REQUEST_TEMPLATE.md
vendored
13
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -2,7 +2,14 @@
|
||||
Thank you for your Pull Request. Please provide a description above and review
|
||||
the requirements below.
|
||||
|
||||
Bug fixes and new features should include tests and possibly benchmarks.
|
||||
|
||||
Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTING.md
|
||||
-->
|
||||
-->
|
||||
|
||||
##### Checklist
|
||||
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->
|
||||
|
||||
- [ ] PR description included and stakeholders cc'd
|
||||
- [ ] `npm test` passes
|
||||
- [ ] tests are [changed or added](https://github.com/electron/electron/blob/master/docs/development/testing.md)
|
||||
- [ ] relevant documentation is changed or added
|
||||
- [ ] commit messages or PR title follow semantic [commit guidelines](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines)
|
||||
30
.github/config.yml
vendored
30
.github/config.yml
vendored
@@ -4,7 +4,7 @@
|
||||
newIssueWelcomeComment: |
|
||||
👋 Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.
|
||||
|
||||
To help make it easier for us to investigate your issue, please follow the [contributing guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md#submitting-issues).
|
||||
To help make it easier for us to investigate your issue, please follow the [contributing guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md).
|
||||
|
||||
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
|
||||
|
||||
@@ -12,14 +12,22 @@ newIssueWelcomeComment: |
|
||||
newPRWelcomeComment: |
|
||||
💖 Thanks for opening this pull request! 💖
|
||||
|
||||

|
||||
We use [semantic commit messages](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines) to streamline the release process. Before your pull request can be merged, you should **update your pull request title** to start with a semantic prefix, OR prefix at least one of your commit messages.
|
||||
|
||||
Examples of commit messages with semantic prefixes:
|
||||
|
||||
- `fix: don't overwrite prevent_default if default wasn't prevented`
|
||||
- `feat: add app.isPackaged() method`
|
||||
- `docs: app.isDefaultProtocolClient is now available on Linux`
|
||||
|
||||
Things that will help get your PR across the finish line:
|
||||
|
||||
Here is a list of things that will help get it across the finish line:
|
||||
- Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/master/docs/development/coding-style.md).
|
||||
- Run `npm run lint` locally to catch formatting errors earlier.
|
||||
- Document any user-facing changes you've made following the [documentation styleguide](https://github.com/electron/electron/blob/master/docs/styleguide.md).
|
||||
- Include tests when adding/changing behavior.
|
||||
- Include screenshots and animated GIFs whenever possible.
|
||||
|
||||
We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can.
|
||||
|
||||
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
|
||||
@@ -28,4 +36,18 @@ newPRWelcomeComment: |
|
||||
firstPRMergeComment: >
|
||||
Congrats on merging your first pull request! 🎉🎉🎉
|
||||
|
||||
# It is recommend to include as many gifs and emojis as possible
|
||||
# Configuration for trop - https://github.com/codebytere/trop
|
||||
|
||||
watchedProject:
|
||||
name: Backports
|
||||
|
||||
authorizedUsers:
|
||||
- alexeykuzmin
|
||||
- ckerr
|
||||
- codebytere
|
||||
- deepak1556
|
||||
- jkleinsc
|
||||
- MarshallOfSound
|
||||
- nitsakh
|
||||
- nornagon
|
||||
- zcbenz
|
||||
|
||||
20
.gitignore
vendored
20
.gitignore
vendored
@@ -23,19 +23,15 @@
|
||||
/brightray/brightray.v12.suo
|
||||
/brightray/brightray.vcxproj*
|
||||
/brightray/brightray.xcodeproj/
|
||||
/build/
|
||||
/dist/
|
||||
/external_binaries/
|
||||
/out/
|
||||
/vendor/.gclient
|
||||
/vendor/debian_jessie_amd64-sysroot/
|
||||
/vendor/debian_jessie_arm-sysroot/
|
||||
/vendor/debian_jessie_arm64-sysroot/
|
||||
/vendor/debian_jessie_i386-sysroot/
|
||||
/vendor/debian_jessie_mips64-sysroot/
|
||||
/vendor/debian_wheezy_amd64-sysroot/
|
||||
/vendor/debian_wheezy_arm-sysroot/
|
||||
/vendor/debian_wheezy_i386-sysroot/
|
||||
/vendor/debian_stretch_amd64-sysroot/
|
||||
/vendor/debian_stretch_arm-sysroot/
|
||||
/vendor/debian_stretch_arm64-sysroot/
|
||||
/vendor/debian_stretch_i386-sysroot/
|
||||
/vendor/gcc-4.8.3-d197-n64-loongson/
|
||||
/vendor/readme-gcc483-loongson.txt
|
||||
/vendor/download/
|
||||
@@ -47,4 +43,10 @@
|
||||
/vendor/LICENSES.chromium.html
|
||||
node_modules/
|
||||
SHASUMS256.txt
|
||||
**/package-lock.json
|
||||
**/yarn.lock
|
||||
compile_commands.json
|
||||
.envrc
|
||||
|
||||
# npm package
|
||||
/npm/dist
|
||||
/npm/path.txt
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -7,9 +7,6 @@
|
||||
[submodule "vendor/breakpad"]
|
||||
path = vendor/breakpad
|
||||
url = https://github.com/electron/chromium-breakpad.git
|
||||
[submodule "vendor/native_mate"]
|
||||
path = vendor/native_mate
|
||||
url = https://github.com/electron/native-mate.git
|
||||
[submodule "vendor/crashpad"]
|
||||
path = vendor/crashpad
|
||||
url = https://github.com/electron/crashpad.git
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
v8.2.1
|
||||
592
BUILD.gn
Normal file
592
BUILD.gn
Normal file
@@ -0,0 +1,592 @@
|
||||
import("//build/config/locales.gni")
|
||||
import("//tools/grit/repack.gni")
|
||||
import("build/asar.gni")
|
||||
import("build/npm.gni")
|
||||
|
||||
if (is_mac) {
|
||||
import("//build/config/mac/rules.gni")
|
||||
import("//third_party/icu/config.gni")
|
||||
import("//v8/gni/v8.gni")
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
import("//build/config/linux/pkg_config.gni")
|
||||
|
||||
pkg_config("gio_unix") {
|
||||
packages = [ "gio-unix-2.0" ]
|
||||
}
|
||||
}
|
||||
|
||||
declare_args() {
|
||||
electron_project_name = "electron"
|
||||
electron_product_name = "Electron"
|
||||
electron_company_name = "GitHub, Inc"
|
||||
electron_company_abbr = "github"
|
||||
electron_version = "0.0.0-dev"
|
||||
|
||||
enable_desktop_capturer = true
|
||||
enable_run_as_node = true
|
||||
enable_osr = true
|
||||
|
||||
# Provide a fake location provider for mocking
|
||||
# the geolocation responses. Disable it if you
|
||||
# need to test with chromium's location provider.
|
||||
# Should not be enabled for release build.
|
||||
enable_fake_location_provider = !is_official_build
|
||||
}
|
||||
|
||||
filenames_gypi = exec_script(
|
||||
"//build/gypi_to_gn.py",
|
||||
[
|
||||
rebase_path("filenames.gypi"),
|
||||
"--replace=<(SHARED_INTERMEDIATE_DIR)=$target_gen_dir",
|
||||
],
|
||||
"scope",
|
||||
[ "filenames.gypi" ]
|
||||
)
|
||||
|
||||
config("branding") {
|
||||
defines = [
|
||||
"ATOM_PRODUCT_NAME=\"$electron_product_name\"",
|
||||
"ATOM_PROJECT_NAME=\"$electron_project_name\"",
|
||||
]
|
||||
}
|
||||
|
||||
config("features") {
|
||||
defines = []
|
||||
if (enable_desktop_capturer) {
|
||||
defines += [ "ENABLE_DESKTOP_CAPTURER=1" ]
|
||||
}
|
||||
if (enable_run_as_node) {
|
||||
defines += [ "ENABLE_RUN_AS_NODE=1" ]
|
||||
}
|
||||
if (enable_osr) {
|
||||
defines += [ "ENABLE_OSR=1" ]
|
||||
}
|
||||
}
|
||||
|
||||
config("native_mate_config") {
|
||||
include_dirs = [
|
||||
"//third_party/native_mate",
|
||||
]
|
||||
cflags_cc = [
|
||||
"-Wno-deprecated-declarations",
|
||||
]
|
||||
cflags_objcc = cflags_cc
|
||||
}
|
||||
|
||||
source_set("native_mate") {
|
||||
deps = [
|
||||
"//base",
|
||||
"//net",
|
||||
"//v8:v8_headers",
|
||||
"build/node",
|
||||
]
|
||||
public_configs = [ ":native_mate_config" ]
|
||||
sources = [
|
||||
"//third_party/native_mate/native_mate/arguments.cc",
|
||||
"//third_party/native_mate/native_mate/arguments.h",
|
||||
"//third_party/native_mate/native_mate/compat.h",
|
||||
"//third_party/native_mate/native_mate/constructor.h",
|
||||
"//third_party/native_mate/native_mate/converter.cc",
|
||||
"//third_party/native_mate/native_mate/converter.h",
|
||||
"//third_party/native_mate/native_mate/dictionary.cc",
|
||||
"//third_party/native_mate/native_mate/dictionary.h",
|
||||
"//third_party/native_mate/native_mate/function_template.cc",
|
||||
"//third_party/native_mate/native_mate/function_template.h",
|
||||
"//third_party/native_mate/native_mate/handle.h",
|
||||
"//third_party/native_mate/native_mate/object_template_builder.cc",
|
||||
"//third_party/native_mate/native_mate/object_template_builder.h",
|
||||
"//third_party/native_mate/native_mate/persistent_dictionary.cc",
|
||||
"//third_party/native_mate/native_mate/persistent_dictionary.h",
|
||||
"//third_party/native_mate/native_mate/scoped_persistent.h",
|
||||
"//third_party/native_mate/native_mate/wrappable.cc",
|
||||
"//third_party/native_mate/native_mate/wrappable.h",
|
||||
"//third_party/native_mate/native_mate/wrappable_base.h",
|
||||
]
|
||||
}
|
||||
|
||||
npm_action("atom_browserify_sandbox") {
|
||||
deps = [ ":atom_js2c_copy" ]
|
||||
|
||||
sandbox_args = [
|
||||
"lib/sandboxed_renderer/init.js",
|
||||
"-r", "./lib/sandboxed_renderer/api/exports/electron.js:electron",
|
||||
"-r", "./lib/sandboxed_renderer/api/exports/fs.js:fs",
|
||||
"-r", "./lib/sandboxed_renderer/api/exports/os.js:os",
|
||||
"-r", "./lib/sandboxed_renderer/api/exports/path.js:path",
|
||||
"-r", "./lib/sandboxed_renderer/api/exports/child_process.js:child_process",
|
||||
]
|
||||
|
||||
inputs = [
|
||||
"lib/sandboxed_renderer/init.js",
|
||||
"lib/sandboxed_renderer/api/exports/electron.js",
|
||||
"lib/sandboxed_renderer/api/exports/fs.js",
|
||||
"lib/sandboxed_renderer/api/exports/os.js",
|
||||
"lib/sandboxed_renderer/api/exports/path.js",
|
||||
"lib/sandboxed_renderer/api/exports/child_process.js",
|
||||
]
|
||||
outputs = [ "$target_gen_dir/js2c/preload_bundle.js" ]
|
||||
|
||||
script = "browserify"
|
||||
args = sandbox_args + [
|
||||
"-o", rebase_path(outputs[0])
|
||||
]
|
||||
}
|
||||
|
||||
npm_action("atom_browserify_isolated") {
|
||||
deps = [ ":atom_js2c_copy" ]
|
||||
|
||||
inputs = [ "lib/isolated_renderer/init.js" ]
|
||||
outputs = [ "$target_gen_dir/js2c/isolated_bundle.js" ]
|
||||
|
||||
script = "browserify"
|
||||
args = inputs + [
|
||||
"-o", rebase_path(outputs[0])
|
||||
]
|
||||
}
|
||||
|
||||
copy("atom_js2c_copy") {
|
||||
sources = [
|
||||
"lib/common/asar.js",
|
||||
"lib/common/asar_init.js",
|
||||
]
|
||||
outputs = [ "$target_gen_dir/js2c/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
action("atom_js2c") {
|
||||
deps = [
|
||||
":atom_js2c_copy",
|
||||
":atom_browserify_sandbox",
|
||||
":atom_browserify_isolated",
|
||||
]
|
||||
|
||||
js2c_sources = filenames_gypi.js2c_sources
|
||||
|
||||
browserify_sources = [
|
||||
"$target_gen_dir/js2c/isolated_bundle.js",
|
||||
"$target_gen_dir/js2c/preload_bundle.js",
|
||||
]
|
||||
|
||||
inputs = js2c_sources + browserify_sources
|
||||
|
||||
outputs = [ "$target_gen_dir/atom_natives.h" ]
|
||||
|
||||
script = "tools/js2c.py"
|
||||
args = [
|
||||
rebase_path("//third_party/electron_node")
|
||||
] + rebase_path(outputs, root_build_dir) + [
|
||||
rebase_path("$target_gen_dir/js2c", root_build_dir)
|
||||
]
|
||||
}
|
||||
|
||||
asar("js2asar") {
|
||||
sources = filenames_gypi.js_sources
|
||||
outputs = [ "$root_out_dir/resources/electron.asar" ]
|
||||
root = "lib"
|
||||
}
|
||||
|
||||
asar("app2asar") {
|
||||
sources = filenames_gypi.default_app_sources
|
||||
outputs = [ "$root_out_dir/resources/default_app.asar" ]
|
||||
root = "default_app"
|
||||
}
|
||||
|
||||
group("electron") {
|
||||
deps = [ ":electron_lib" ]
|
||||
}
|
||||
|
||||
static_library("electron_lib") {
|
||||
configs += [
|
||||
"//v8:external_startup_data",
|
||||
]
|
||||
public_configs = [
|
||||
":branding",
|
||||
":features",
|
||||
]
|
||||
deps = [
|
||||
"//chrome/common:constants",
|
||||
"//components/cdm/renderer",
|
||||
"//components/network_session_configurator/common",
|
||||
"//components/prefs",
|
||||
"//components/printing/common",
|
||||
"//components/security_state/content",
|
||||
"//content/public/browser",
|
||||
"//device/geolocation",
|
||||
"//gin",
|
||||
"//net:net_resources",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/shared_impl",
|
||||
"//printing",
|
||||
"//services/device/wake_lock/power_save_blocker", # TODO: this requires a visibility patch to chromium src
|
||||
"//skia",
|
||||
"//third_party/WebKit/public:blink",
|
||||
"//third_party/boringssl",
|
||||
"//third_party/crashpad/crashpad/client",
|
||||
"//third_party/leveldatabase",
|
||||
"//third_party/libyuv",
|
||||
"//third_party/webrtc/modules/desktop_capture",
|
||||
"//third_party/webrtc/modules/desktop_capture:primitives",
|
||||
"//ui/events:dom_keycode_converter",
|
||||
"//ui/views",
|
||||
"//v8",
|
||||
":atom_js2c",
|
||||
":native_mate",
|
||||
"brightray",
|
||||
"build/node",
|
||||
]
|
||||
if (is_mac) {
|
||||
deps += [
|
||||
"//ui/accelerated_widget_mac",
|
||||
"//base/allocator:features",
|
||||
]
|
||||
}
|
||||
if (is_linux) {
|
||||
deps += [
|
||||
"//build/config/linux/gtk3",
|
||||
"//chrome/browser/ui/libgtkui",
|
||||
"//device/bluetooth",
|
||||
"//third_party/breakpad:client",
|
||||
"//ui/events/devices/x11",
|
||||
"//ui/events/platform/x11",
|
||||
"//ui/native_theme",
|
||||
"//ui/views/controls/webview",
|
||||
"//ui/wm",
|
||||
]
|
||||
configs += [ ":gio_unix" ]
|
||||
}
|
||||
defines = [
|
||||
# This is defined in skia/skia_common.gypi.
|
||||
"SK_SUPPORT_LEGACY_GETTOPDEVICE",
|
||||
# Disable warnings for g_settings_list_schemas.
|
||||
"GLIB_DISABLE_DEPRECATION_WARNINGS",
|
||||
|
||||
# Import V8 symbols from shared library (node.dll / libnode.so)
|
||||
"USING_V8_SHARED",
|
||||
"USING_V8_PLATFORM_SHARED",
|
||||
"USING_V8_BASE_SHARED",
|
||||
|
||||
# Enables SkBitmap size 64 operations
|
||||
#"SK_SUPPORT_LEGACY_SAFESIZE64", # doesn't seem to be needed to build?
|
||||
]
|
||||
include_dirs = [
|
||||
"chromium_src",
|
||||
".",
|
||||
"$target_gen_dir",
|
||||
# TODO(nornagon): replace usage of SchemeRegistry by an actually exported
|
||||
# API of blink, then delete this include dir.
|
||||
"//third_party/WebKit/Source",
|
||||
# NOTE(nornagon): other chromium files use the full path to include
|
||||
# crashpad; this is just here for compatibility between GN and GYP, so that
|
||||
# the #includes can be agnostic about where crashpad is vendored.
|
||||
"//third_party/crashpad",
|
||||
]
|
||||
if (is_linux) {
|
||||
include_dirs += [
|
||||
"//third_party/breakpad",
|
||||
]
|
||||
}
|
||||
|
||||
extra_source_filters = []
|
||||
if (!is_linux) {
|
||||
extra_source_filters += [
|
||||
"*\bx/*",
|
||||
"*_x11.h",
|
||||
"*_x11.cc",
|
||||
"*_gtk.h",
|
||||
"*_gtk.cc",
|
||||
]
|
||||
}
|
||||
if (!is_win) {
|
||||
extra_source_filters += [
|
||||
"*\bwin_*.h",
|
||||
"*\bwin_*.cc",
|
||||
]
|
||||
}
|
||||
if (is_mac) {
|
||||
extra_source_filters += [
|
||||
"*_views.cc",
|
||||
"*_views.h",
|
||||
"*\bviews/*",
|
||||
"*/autofill_popup.cc",
|
||||
"*/autofill_popup.h",
|
||||
]
|
||||
}
|
||||
|
||||
set_sources_assignment_filter(sources_assignment_filter + extra_source_filters)
|
||||
sources = filenames_gypi.lib_sources
|
||||
set_sources_assignment_filter(sources_assignment_filter)
|
||||
|
||||
if (enable_fake_location_provider) {
|
||||
defines += [
|
||||
"OVERRIDE_LOCATION_PROVIDER"
|
||||
]
|
||||
sources += filenames_gypi.lib_sources_location_provider
|
||||
}
|
||||
|
||||
if (enable_run_as_node) {
|
||||
sources += [
|
||||
"atom/app/node_main.cc",
|
||||
"atom/app/node_main.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_osr) {
|
||||
sources += [
|
||||
"atom/browser/api/atom_api_web_contents_osr.cc",
|
||||
"atom/browser/osr/osr_output_device.cc",
|
||||
"atom/browser/osr/osr_output_device.h",
|
||||
"atom/browser/osr/osr_render_widget_host_view.cc",
|
||||
"atom/browser/osr/osr_render_widget_host_view.h",
|
||||
"atom/browser/osr/osr_render_widget_host_view_mac.mm",
|
||||
"atom/browser/osr/osr_view_proxy.cc",
|
||||
"atom/browser/osr/osr_view_proxy.h",
|
||||
"atom/browser/osr/osr_web_contents_view.cc",
|
||||
"atom/browser/osr/osr_web_contents_view.h",
|
||||
"atom/browser/osr/osr_web_contents_view_mac.mm",
|
||||
]
|
||||
deps += [
|
||||
"//ui/compositor",
|
||||
"//components/viz/service",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_desktop_capturer) {
|
||||
sources += [
|
||||
"atom/browser/api/atom_api_desktop_capturer.cc",
|
||||
"atom/browser/api/atom_api_desktop_capturer.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
libs = [
|
||||
"Squirrel.framework",
|
||||
"ReactiveCocoa.framework",
|
||||
"Mantle.framework",
|
||||
]
|
||||
cflags_objcc = [
|
||||
"-F", rebase_path("external_binaries", root_build_dir)
|
||||
]
|
||||
if (true) { # !is_mas_build
|
||||
# ReactiveCocoa which is used by Squirrel requires using __weak.
|
||||
cflags_objcc += [ "-fobjc-weak" ]
|
||||
}
|
||||
}
|
||||
if (is_linux) {
|
||||
sources += filenames_gypi.lib_sources_linux
|
||||
sources += filenames_gypi.lib_sources_nss
|
||||
}
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
electron_framework_name = electron_product_name + " Framework"
|
||||
electron_helper_name = electron_product_name + " Helper"
|
||||
electron_framework_version = "A"
|
||||
electron_mac_bundle_id = "com.$electron_company_abbr.$electron_project_name"
|
||||
|
||||
mac_xib_bundle_data("electron_xibs") {
|
||||
sources = [ "atom/common/resources/mac/MainMenu.xib" ]
|
||||
}
|
||||
|
||||
bundle_data("electron_framework_resources") {
|
||||
public_deps = [
|
||||
"//content/shell:pak",
|
||||
":electron_locales",
|
||||
]
|
||||
sources = [
|
||||
"$root_out_dir/content_shell.pak",
|
||||
]
|
||||
if (icu_use_data_file) {
|
||||
sources += [ "$root_out_dir/icudtl.dat" ]
|
||||
public_deps += [ "//third_party/icu:icudata" ]
|
||||
}
|
||||
if (v8_use_external_startup_data) {
|
||||
sources += [
|
||||
"$root_out_dir/natives_blob.bin",
|
||||
"$root_out_dir/snapshot_blob.bin",
|
||||
]
|
||||
public_deps += [ "//v8" ]
|
||||
}
|
||||
outputs = [
|
||||
"{{bundle_resources_dir}}/{{source_file_part}}",
|
||||
]
|
||||
}
|
||||
|
||||
bundle_data("electron_framework_libraries") {
|
||||
public_deps = [ "build/node" ]
|
||||
sources = [
|
||||
"$root_out_dir/libnode.dylib"
|
||||
]
|
||||
outputs = [
|
||||
"{{bundle_contents_dir}}/Libraries/{{source_file_part}}"
|
||||
]
|
||||
}
|
||||
|
||||
bundle_data("electron_framework_helpers") {
|
||||
sources = [
|
||||
"$root_out_dir/crashpad_handler",
|
||||
]
|
||||
|
||||
outputs = [
|
||||
"{{bundle_resources_dir}}/{{source_file_part}}",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
"//third_party/crashpad/crashpad/handler:crashpad_handler",
|
||||
]
|
||||
}
|
||||
|
||||
mac_framework_bundle("electron_framework") {
|
||||
output_name = electron_framework_name
|
||||
framework_version = electron_framework_version
|
||||
framework_contents = [ "Resources" ]
|
||||
public_deps = [ ":electron_lib" ]
|
||||
deps = [
|
||||
"//base",
|
||||
"//base:i18n",
|
||||
":electron_framework_helpers",
|
||||
":electron_framework_libraries",
|
||||
":electron_framework_resources",
|
||||
":electron_xibs",
|
||||
]
|
||||
info_plist = "atom/common/resources/mac/Info.plist"
|
||||
extra_substitutions = [
|
||||
"ATOM_BUNDLE_ID=$electron_mac_bundle_id.framework",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
".",
|
||||
]
|
||||
sources = filenames_gypi.framework_sources
|
||||
|
||||
libs = [
|
||||
"Carbon.framework",
|
||||
"QuartzCore.framework",
|
||||
"Quartz.framework",
|
||||
"Security.framework",
|
||||
"SecurityInterface.framework",
|
||||
"ServiceManagement.framework",
|
||||
"StoreKit.framework",
|
||||
]
|
||||
ldflags = [
|
||||
"-F", rebase_path("external_binaries", root_build_dir),
|
||||
"-Wl,-install_name,@rpath/$output_name.framework/$output_name",
|
||||
"-rpath",
|
||||
"@loader_path/Libraries",
|
||||
]
|
||||
if (is_component_build) {
|
||||
ldflags += [
|
||||
"-rpath",
|
||||
"@executable_path/../../../../../.."
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
mac_app_bundle("electron_helper_app") {
|
||||
output_name = electron_helper_name
|
||||
deps = [ ":electron_framework+link" ]
|
||||
sources = filenames_gypi.app_sources
|
||||
include_dirs = [ "." ]
|
||||
info_plist = "atom/renderer/resources/mac/Info.plist"
|
||||
extra_substitutions = [
|
||||
"ATOM_BUNDLE_ID=$electron_mac_bundle_id.helper",
|
||||
]
|
||||
ldflags = [
|
||||
"-rpath",
|
||||
"@executable_path/../../..",
|
||||
]
|
||||
}
|
||||
|
||||
bundle_data("electron_app_framework_bundle_data") {
|
||||
sources = [
|
||||
"$root_out_dir/$electron_framework_name.framework",
|
||||
"$root_out_dir/$electron_helper_name.app",
|
||||
"external_binaries/Squirrel.framework",
|
||||
"external_binaries/ReactiveCocoa.framework",
|
||||
"external_binaries/Mantle.framework",
|
||||
]
|
||||
outputs = [
|
||||
"{{bundle_contents_dir}}/Frameworks/{{source_file_part}}",
|
||||
]
|
||||
public_deps = [
|
||||
":electron_framework+link",
|
||||
":electron_helper_app",
|
||||
]
|
||||
}
|
||||
|
||||
bundle_data("electron_app_resources") {
|
||||
public_deps = [
|
||||
":js2asar",
|
||||
":app2asar",
|
||||
]
|
||||
sources = [
|
||||
"$root_out_dir/resources/electron.asar",
|
||||
"$root_out_dir/resources/default_app.asar",
|
||||
]
|
||||
outputs = [
|
||||
"{{bundle_resources_dir}}/{{source_file_part}}"
|
||||
]
|
||||
}
|
||||
|
||||
repack_locales("electron_locales") {
|
||||
source_patterns = [
|
||||
"${root_gen_dir}/content/app/strings/content_strings_",
|
||||
]
|
||||
deps = [
|
||||
"//content/app/strings",
|
||||
]
|
||||
|
||||
input_locales = locales
|
||||
|
||||
if (is_mac) {
|
||||
output_locales = locales_as_mac_outputs
|
||||
} else {
|
||||
output_locales = locales
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
output_dir = "$root_gen_dir/repack"
|
||||
copy_data_to_bundle = true
|
||||
} else {
|
||||
output_dir = root_out_dir
|
||||
}
|
||||
}
|
||||
|
||||
mac_app_bundle("electron_app") {
|
||||
output_name = electron_product_name
|
||||
sources = filenames_gypi.app_sources
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
":electron_app_framework_bundle_data",
|
||||
":electron_app_resources",
|
||||
]
|
||||
info_plist = "atom/browser/resources/mac/Info.plist"
|
||||
extra_substitutions = [
|
||||
"ATOM_BUNDLE_ID=$electron_mac_bundle_id",
|
||||
]
|
||||
ldflags = [
|
||||
"-rpath",
|
||||
"@executable_path/../Frameworks",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
executable("electron_app") {
|
||||
output_name = electron_project_name
|
||||
sources = filenames_gypi.app_sources
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
":app2asar",
|
||||
":electron_lib",
|
||||
":js2asar",
|
||||
"//build/config:exe_and_shlib_deps",
|
||||
"//chrome:packed_resources",
|
||||
"//content/shell:copy_shell_resources",
|
||||
"//content/shell:pak",
|
||||
"//third_party/WebKit/public:image_resources",
|
||||
"//ui/strings",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -54,3 +54,7 @@ dependencies, and tools contained in the `electron/electron` repository.
|
||||
|
||||
See [Coding Style](https://electronjs.org/docs/development/coding-style) for information about which standards Electron adheres to in different parts of its codebase.
|
||||
|
||||
## Further Reading
|
||||
|
||||
For more in-depth guides on developing Electron, see
|
||||
[/docs/development](/docs/development/README.md)
|
||||
73
DEPS
Normal file
73
DEPS
Normal file
@@ -0,0 +1,73 @@
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'63.0.3239.150',
|
||||
'libchromiumcontent_revision':
|
||||
'5ff272e25eb552d8c0e7f07f919ed0bad804500b',
|
||||
'node_version':
|
||||
'v9.7.0-33-g538a5023af',
|
||||
'native_mate_revision':
|
||||
'4cd7d113915de0cc08e9a218be35bff9c7361906',
|
||||
|
||||
'chromium_git':
|
||||
'https://chromium.googlesource.com',
|
||||
|
||||
'electron_git':
|
||||
'https://github.com/electron',
|
||||
}
|
||||
|
||||
deps = {
|
||||
'src':
|
||||
(Var("chromium_git")) + '/chromium/src.git@' + (Var("chromium_version")),
|
||||
'src/libchromiumcontent':
|
||||
(Var("electron_git")) + '/libchromiumcontent.git@' + (Var("libchromiumcontent_revision")),
|
||||
'src/third_party/electron_node':
|
||||
(Var("electron_git")) + '/node.git@' + (Var("node_version")),
|
||||
'src/third_party/native_mate':
|
||||
(Var("electron_git")) + '/native-mate.git@' + (Var("native_mate_revision")),
|
||||
}
|
||||
|
||||
hooks = [
|
||||
{
|
||||
'action': [
|
||||
'src/libchromiumcontent/script/apply-patches'
|
||||
],
|
||||
'pattern':
|
||||
'src/libchromiumcontent',
|
||||
'name':
|
||||
'patch_chromium'
|
||||
},
|
||||
{
|
||||
'action': [
|
||||
'src/electron/script/update-external-binaries.py'
|
||||
],
|
||||
'pattern':
|
||||
'src/electron/script/update-external-binaries.py',
|
||||
'name':
|
||||
'electron_external_binaries'
|
||||
},
|
||||
{
|
||||
'action': [
|
||||
'bash',
|
||||
'-c',
|
||||
# NOTE(nornagon): this ridiculous {{}} stuff is because these strings get
|
||||
# variable-substituted twice by gclient.
|
||||
'echo -e "#\\n{{{{\'variables\':{{{{}}}}}}}}" > src/third_party/electron_node/config.gypi',
|
||||
],
|
||||
'pattern': 'src/third_party/electron_node',
|
||||
'name': 'touch_node_config_gypi'
|
||||
},
|
||||
{
|
||||
'action': [
|
||||
'bash',
|
||||
'-c',
|
||||
'cd src/electron; npm install',
|
||||
],
|
||||
'pattern': 'src/electron/package.json',
|
||||
'name': 'electron_npm_deps'
|
||||
},
|
||||
]
|
||||
|
||||
recursedeps = [
|
||||
'src',
|
||||
'src/libchromiumcontent',
|
||||
]
|
||||
@@ -7,8 +7,8 @@ ENV HOME=/home
|
||||
RUN chmod a+rwx /home
|
||||
|
||||
# Install node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
|
||||
RUN apt-get update && apt-get install -y nodejs
|
||||
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
|
||||
RUN apt-get install -y nodejs
|
||||
|
||||
# Install wget used by crash reporter
|
||||
RUN apt-get install -y wget
|
||||
|
||||
@@ -3,8 +3,8 @@ FROM electronbuilds/libchromiumcontent:0.0.4
|
||||
USER root
|
||||
|
||||
# Install node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
|
||||
RUN apt-get update && apt-get install -y nodejs
|
||||
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
|
||||
RUN apt-get install -y nodejs
|
||||
|
||||
# Install wget used by crash reporter
|
||||
RUN apt-get install -y wget
|
||||
|
||||
48
Jenkinsfile
vendored
48
Jenkinsfile
vendored
@@ -1,48 +0,0 @@
|
||||
pipeline {
|
||||
agent none
|
||||
stages {
|
||||
stage('Build') {
|
||||
parallel {
|
||||
stage('electron-osx-x64') {
|
||||
agent {
|
||||
label 'osx'
|
||||
}
|
||||
steps {
|
||||
timeout(60) {
|
||||
sh 'script/bootstrap.py --target_arch=x64 --dev'
|
||||
sh 'npm run lint'
|
||||
sh 'script/build.py -c D'
|
||||
sh 'script/test.py --ci --rebuild_native_modules'
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('electron-mas-x64') {
|
||||
agent {
|
||||
label 'osx'
|
||||
}
|
||||
environment {
|
||||
MAS_BUILD = '1'
|
||||
}
|
||||
steps {
|
||||
timeout(60) {
|
||||
sh 'script/bootstrap.py --target_arch=x64 --dev'
|
||||
sh 'npm run lint'
|
||||
sh 'script/build.py -c D'
|
||||
sh 'script/test.py --ci --rebuild_native_modules'
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
pipeline {
|
||||
agent {
|
||||
docker {
|
||||
image 'electronbuilds/arm64v8:0.0.2'
|
||||
args '--privileged'
|
||||
}
|
||||
}
|
||||
environment {
|
||||
TARGET_ARCH='arm64'
|
||||
DISPLAY=':99.0'
|
||||
MOCHA_TIMEOUT='60000'
|
||||
}
|
||||
stages {
|
||||
stage('Bootstrap') {
|
||||
steps {
|
||||
sh 'script/bootstrap.py -v --dev --target_arch=$TARGET_ARCH'
|
||||
}
|
||||
}
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh 'script/build.py -c D --ninja-path /usr/local/ninja/ninja'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh '/etc/init.d/xvfb start'
|
||||
sh 'script/test.py --ci'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
}
|
||||
}
|
||||
11
README.md
11
README.md
@@ -3,12 +3,11 @@
|
||||
|
||||
[](https://circleci.com/gh/electron/electron/tree/master)
|
||||
[](https://windows-ci.electronjs.org/project/AppVeyor/electron/branch/master)
|
||||
[](https://mac-ci.electronjs.org/blue/organizations/jenkins/Electron%20org%2Felectron/activity?branch=master)
|
||||
[](https://david-dm.org/electron/electron?type=dev)
|
||||
[](https://atom-slack.herokuapp.com/)
|
||||
|
||||
:memo: Available Translations: 🇨🇳 🇹🇼 🇧🇷 🇪🇸 🇰🇷 🇯🇵 🇷🇺 🇫🇷 🇹🇭 🇳🇱 🇹🇷 🇮🇩 🇺🇦 🇨🇿 🇮🇹.
|
||||
View these docs in other languages at [electron/electron-i18n](https://github.com/electron/electron-i18n/tree/master/content/).
|
||||
View these docs in other languages at [electron/i18n](https://github.com/electron/i18n/tree/master/content/).
|
||||
|
||||
The Electron framework lets you write cross-platform desktop applications
|
||||
using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and
|
||||
@@ -30,11 +29,11 @@ The preferred method is to install Electron as a development dependency in your
|
||||
app:
|
||||
|
||||
```sh
|
||||
npm install electron --save-dev --save-exact
|
||||
npm install electron --save-dev [--save-exact]
|
||||
```
|
||||
|
||||
The `--save-exact` flag is recommended as Electron does not follow semantic
|
||||
versioning. For info on how to manage Electron versions in your apps, see
|
||||
The `--save-exact` flag is recommended for Electron prior to version 2, as it does not follow semantic
|
||||
versioning. As of version 2.0.0, Electron follows semver, so you don't need `--save-exact` flag. For info on how to manage Electron versions in your apps, see
|
||||
[Electron versioning](docs/tutorial/electron-versioning.md).
|
||||
|
||||
For more installation options and troubleshooting tips, see
|
||||
@@ -85,7 +84,7 @@ const child = proc.spawn(electron)
|
||||
|
||||
## Documentation Translations
|
||||
|
||||
Find documentation translations in [electron/electron-i18n](https://github.com/electron/electron-i18n).
|
||||
Find documentation translations in [electron/i18n](https://github.com/electron/i18n).
|
||||
|
||||
## Community
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
build_cloud: electron-16
|
||||
image: electron-16-vs2015
|
||||
build_script:
|
||||
- ps: >-
|
||||
if(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
Write-warning "Skipping PR build for branch"; Exit-AppveyorBuild
|
||||
} else {
|
||||
Add-Path "$env:ProgramFiles (x86)\Windows Kits\10\Debuggers\x64"
|
||||
$env:path = "$env:ProgramFiles (x86)\Windows Kits\10\Debuggers\x64;$env:path"
|
||||
if($env:APPVEYOR_SCHEDULED_BUILD -eq 'True') {
|
||||
$env:RUN_RELEASE_BUILD = "1"
|
||||
}
|
||||
$Message = (git log --format=%B -n 1 HEAD) | Out-String
|
||||
if ((Test-Path Env:\RUN_RELEASE_BUILD)) {
|
||||
$env:ELECTRON_RELEASE = '1'
|
||||
Write-Output "release build triggered from api"
|
||||
}
|
||||
if ((Test-Path Env:\ELECTRON_RELEASE)) {
|
||||
Write-Output "Running release build"
|
||||
python script\bootstrap.py --target_arch=$env:TARGET_ARCH
|
||||
python script\build.py -c R
|
||||
python script\create-dist.py
|
||||
} else {
|
||||
Write-Output "Running debug build"
|
||||
python script\bootstrap.py --target_arch=$env:TARGET_ARCH --dev
|
||||
python script\build.py -c D
|
||||
}
|
||||
if ($? -ne 'True') {
|
||||
throw "Build failed with exit code $?"
|
||||
} else {
|
||||
"Build succeeded."
|
||||
}
|
||||
Push-AppveyorArtifact out
|
||||
}
|
||||
test_script:
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
Write-Output "Skipping tests for release build"
|
||||
} else {
|
||||
Write-Output "Running tests for debug build"
|
||||
python script\test.py --ci --rebuild_native_modules
|
||||
if ($LASTEXITCODE -ne '0') {
|
||||
throw "Tests failed with exit code $LASTEXITCODE"
|
||||
} else {
|
||||
Write-Output "Tests succeeded."
|
||||
}
|
||||
python script\verify-ffmpeg.py
|
||||
if ($LASTEXITCODE -ne '0') {
|
||||
throw "Verify ffmpeg failed with exit code $LASTEXITCODE"
|
||||
} else {
|
||||
"Verify ffmpeg succeeded."
|
||||
}
|
||||
}
|
||||
artifacts:
|
||||
- path: test-results.xml
|
||||
name: test-results.xml
|
||||
deploy_script:
|
||||
- ps: "if (Test-Path Env:\\ELECTRON_RELEASE) {\n if (Test-Path Env:\\RUN_RELEASE_BUILD) {\n Write-Output \"Uploading Electron release distribution to s3\"\n & python script\\upload.py --upload_to_s3\n } else {\n Write-Output \"Uploading Electron release distribution to github releases\"\n & python script\\upload.py\n if (Test-Path Env:\\AUTO_RELEASE) {\n node script\\release.js --validateRelease --automaticRelease\n if ($? -eq 'True') {\n echo 'Release is ready to go; now running release'\n node script\\release.js --automaticRelease\n if ($? -eq 'True') { \n echo 'Release successful, now publishing to npm' \n $npmfile = \"$HOME\\.npmrc\"\n \"//registry.npmjs.org/:_authToken=$env:ELECTRON_NPM_TOKEN\" > $npmfile\n npm run publish-to-npm\n }\n } else {\n echo 'Release is not complete, skipping publish for now.'\n }\n }\n }\n} else {\n Write-Output \"Skipping upload distribution because build is not for release\"\n}"
|
||||
64
appveyor.yml
Normal file
64
appveyor.yml
Normal file
@@ -0,0 +1,64 @@
|
||||
build_cloud: electron-16
|
||||
image: electron-16-vs2017-15.4.5
|
||||
build_script:
|
||||
- ps: >-
|
||||
echo "Build worker image $env:APPVEYOR_BUILD_WORKER_IMAGE"
|
||||
|
||||
&"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
|
||||
if($env:SKIP_GYP_BUILD -eq "true") {
|
||||
Write-warning "Skipping debug build for older branch"; Exit-AppveyorBuild
|
||||
} elseif(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
Write-warning "Skipping PR build for branch"; Exit-AppveyorBuild
|
||||
} else {
|
||||
Add-Path "$env:ProgramFiles (x86)\Windows Kits\10\Debuggers\x64"
|
||||
$env:path = "$env:ProgramFiles (x86)\Windows Kits\10\Debuggers\x64;$env:path"
|
||||
if($env:APPVEYOR_SCHEDULED_BUILD -eq 'True') {
|
||||
$env:RUN_RELEASE_BUILD = "1"
|
||||
}
|
||||
$Message = (git log --format=%B -n 1 HEAD) | Out-String
|
||||
if ((Test-Path Env:\RUN_RELEASE_BUILD)) {
|
||||
$env:ELECTRON_RELEASE = '1'
|
||||
Write-Output "release build triggered from api"
|
||||
}
|
||||
if ((Test-Path Env:\ELECTRON_RELEASE)) {
|
||||
Write-Output "Running release build"
|
||||
python script\bootstrap.py --target_arch=$env:TARGET_ARCH
|
||||
python script\build.py -c R
|
||||
python script\create-dist.py
|
||||
} else {
|
||||
Write-Output "Running debug build"
|
||||
python script\bootstrap.py --target_arch=$env:TARGET_ARCH --dev
|
||||
python script\build.py -c D
|
||||
}
|
||||
if ($? -ne 'True') {
|
||||
throw "Build failed with exit code $?"
|
||||
} else {
|
||||
"Build succeeded."
|
||||
}
|
||||
Push-AppveyorArtifact out
|
||||
}
|
||||
test_script:
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
Write-Output "Skipping tests for release build"
|
||||
} else {
|
||||
$env:RUN_TESTS="true"
|
||||
Write-Output "Running tests for debug build"
|
||||
}
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running test suite & python script\test.py --ci --rebuild_native_modules)
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running verify ffmpeg & python script\verify-ffmpeg.py)
|
||||
artifacts:
|
||||
- path: test-results.xml
|
||||
name: test-results.xml
|
||||
deploy_script:
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\RUN_RELEASE_BUILD) {
|
||||
Write-Output "Uploading Electron release distribution to s3"
|
||||
& python script\upload.py --upload_to_s3
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\upload.py
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
filter=+build/include_alpha
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/atom_constants.h"
|
||||
#include "atom/common/atom_version.h"
|
||||
#include "atom/common/chrome_version.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
@@ -19,20 +18,90 @@
|
||||
#include "content/public/common/content_constants.h"
|
||||
#include "content/public/common/pepper_plugin_info.h"
|
||||
#include "content/public/common/user_agent.h"
|
||||
#include "pdf/pdf.h"
|
||||
#include "media/media_features.h"
|
||||
#include "ppapi/shared_impl/ppapi_permissions.h"
|
||||
#include "third_party/widevine/cdm/stub/widevine_cdm_version.h"
|
||||
#include "third_party/widevine/cdm/widevine_cdm_common.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "url/url_constants.h"
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE)
|
||||
#include "base/native_library.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "chrome/common/widevine_cdm_constants.h"
|
||||
#endif
|
||||
#include "content/public/common/cdm_info.h"
|
||||
#include "media/base/video_codecs.h"
|
||||
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
||||
|
||||
#if defined(ENABLE_PDF_VIEWER)
|
||||
#include "atom/common/atom_constants.h"
|
||||
#include "pdf/pdf.h"
|
||||
#endif // defined(ENABLE_PDF_VIEWER)
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE)
|
||||
bool IsWidevineAvailable(base::FilePath* adapter_path,
|
||||
base::FilePath* cdm_path,
|
||||
std::vector<media::VideoCodec>* codecs_supported) {
|
||||
static enum {
|
||||
NOT_CHECKED,
|
||||
FOUND,
|
||||
NOT_FOUND,
|
||||
} widevine_cdm_file_check = NOT_CHECKED;
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
*adapter_path = command_line->GetSwitchValuePath(switches::kWidevineCdmPath);
|
||||
if (!adapter_path->empty()) {
|
||||
*cdm_path = adapter_path->DirName().AppendASCII(
|
||||
base::GetNativeLibraryName(kWidevineCdmLibraryName));
|
||||
if (widevine_cdm_file_check == NOT_CHECKED) {
|
||||
widevine_cdm_file_check =
|
||||
(base::PathExists(*adapter_path) && base::PathExists(*cdm_path))
|
||||
? FOUND
|
||||
: NOT_FOUND;
|
||||
}
|
||||
if (widevine_cdm_file_check == FOUND) {
|
||||
// Add the supported codecs as if they came from the component manifest.
|
||||
// This list must match the CDM that is being bundled with Chrome.
|
||||
codecs_supported->push_back(media::VideoCodec::kCodecVP8);
|
||||
codecs_supported->push_back(media::VideoCodec::kCodecVP9);
|
||||
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
|
||||
codecs_supported->push_back(media::VideoCodec::kCodecH264);
|
||||
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void AddWidevineAdapterFromCommandLine(
|
||||
base::CommandLine* command_line,
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
base::FilePath adapter_path;
|
||||
base::FilePath cdm_path;
|
||||
std::vector<media::VideoCodec> video_codecs_supported;
|
||||
if (IsWidevineAvailable(&adapter_path, &cdm_path, &video_codecs_supported)) {
|
||||
auto cdm_version_string =
|
||||
command_line->GetSwitchValueASCII(switches::kWidevineCdmVersion);
|
||||
content::PepperPluginInfo info;
|
||||
info.is_out_of_process = true;
|
||||
info.path = adapter_path;
|
||||
info.name = kWidevineCdmDisplayName;
|
||||
info.description =
|
||||
base::StringPrintf("%s (version: %s)", kWidevineCdmDescription,
|
||||
cdm_version_string.c_str());
|
||||
info.version = cdm_version_string;
|
||||
info.permissions = kWidevineCdmPluginPermissions;
|
||||
content::WebPluginMimeType mime_type(kWidevineCdmPluginMimeType,
|
||||
kWidevineCdmPluginExtension,
|
||||
kWidevineCdmPluginMimeTypeDescription);
|
||||
info.mime_types.push_back(mime_type);
|
||||
plugins->push_back(info);
|
||||
}
|
||||
}
|
||||
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
||||
|
||||
#if defined(ENABLE_PEPPER_FLASH)
|
||||
content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||
const std::string& version) {
|
||||
content::PepperPluginInfo plugin;
|
||||
@@ -57,60 +126,38 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||
flash_version_numbers.push_back("999");
|
||||
// E.g., "Shockwave Flash 10.2 r154":
|
||||
plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
|
||||
flash_version_numbers[1] + " r" + flash_version_numbers[2];
|
||||
flash_version_numbers[1] + " r" +
|
||||
flash_version_numbers[2];
|
||||
plugin.version = base::JoinString(flash_version_numbers, ".");
|
||||
content::WebPluginMimeType swf_mime_type(
|
||||
content::kFlashPluginSwfMimeType,
|
||||
content::kFlashPluginSwfExtension,
|
||||
content::kFlashPluginSwfDescription);
|
||||
content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType,
|
||||
content::kFlashPluginSwfExtension,
|
||||
content::kFlashPluginSwfDescription);
|
||||
plugin.mime_types.push_back(swf_mime_type);
|
||||
content::WebPluginMimeType spl_mime_type(
|
||||
content::kFlashPluginSplMimeType,
|
||||
content::kFlashPluginSplExtension,
|
||||
content::kFlashPluginSplDescription);
|
||||
content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType,
|
||||
content::kFlashPluginSplExtension,
|
||||
content::kFlashPluginSplDescription);
|
||||
plugin.mime_types.push_back(spl_mime_type);
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
|
||||
content::PepperPluginInfo CreateWidevineCdmInfo(const base::FilePath& path,
|
||||
const std::string& version) {
|
||||
content::PepperPluginInfo widevine_cdm;
|
||||
widevine_cdm.is_out_of_process = true;
|
||||
widevine_cdm.path = path;
|
||||
widevine_cdm.name = kWidevineCdmDisplayName;
|
||||
widevine_cdm.description = kWidevineCdmDescription +
|
||||
std::string(" (version: ") +
|
||||
version + ")";
|
||||
widevine_cdm.version = version;
|
||||
content::WebPluginMimeType widevine_cdm_mime_type(
|
||||
kWidevineCdmPluginMimeType,
|
||||
kWidevineCdmPluginExtension,
|
||||
kWidevineCdmPluginMimeTypeDescription);
|
||||
void AddPepperFlashFromCommandLine(
|
||||
base::CommandLine* command_line,
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
base::FilePath flash_path =
|
||||
command_line->GetSwitchValuePath(switches::kPpapiFlashPath);
|
||||
if (flash_path.empty())
|
||||
return;
|
||||
|
||||
// Add the supported codecs as if they came from the component manifest.
|
||||
std::vector<std::string> codecs;
|
||||
codecs.push_back(kCdmSupportedCodecVp8);
|
||||
codecs.push_back(kCdmSupportedCodecVp9);
|
||||
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
|
||||
codecs.push_back(kCdmSupportedCodecAvc1);
|
||||
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
|
||||
std::string codec_string = base::JoinString(
|
||||
codecs, std::string(1, kCdmSupportedCodecsValueDelimiter));
|
||||
widevine_cdm_mime_type.additional_param_names.push_back(
|
||||
base::ASCIIToUTF16(kCdmSupportedCodecsParamName));
|
||||
widevine_cdm_mime_type.additional_param_values.push_back(
|
||||
base::ASCIIToUTF16(codec_string));
|
||||
auto flash_version =
|
||||
command_line->GetSwitchValueASCII(switches::kPpapiFlashVersion);
|
||||
|
||||
widevine_cdm.mime_types.push_back(widevine_cdm_mime_type);
|
||||
widevine_cdm.permissions = kWidevineCdmPluginPermissions;
|
||||
|
||||
return widevine_cdm;
|
||||
plugins->push_back(CreatePepperFlashInfo(flash_path, flash_version));
|
||||
}
|
||||
#endif
|
||||
#endif // defined(ENABLE_PEPPER_FLASH)
|
||||
|
||||
void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
|
||||
#if defined(ENABLE_PDF_VIEWER)
|
||||
content::PepperPluginInfo pdf_info;
|
||||
pdf_info.is_internal = true;
|
||||
pdf_info.is_out_of_process = true;
|
||||
@@ -127,71 +174,33 @@ void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
|
||||
chrome_pdf::PPP_ShutdownModule;
|
||||
pdf_info.permissions = ppapi::PERMISSION_PRIVATE | ppapi::PERMISSION_DEV;
|
||||
plugins->push_back(pdf_info);
|
||||
#endif // defined(ENABLE_PDF_VIEWER)
|
||||
}
|
||||
|
||||
void ConvertStringWithSeparatorToVector(std::vector<std::string>* vec,
|
||||
const char* separator,
|
||||
const char* cmd_switch) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto string_with_separator = command_line->GetSwitchValueASCII(cmd_switch);
|
||||
if (!string_with_separator.empty())
|
||||
*vec = base::SplitString(string_with_separator, separator,
|
||||
base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void AddPepperFlashFromCommandLine(
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
base::FilePath flash_path = command_line->GetSwitchValuePath(
|
||||
switches::kPpapiFlashPath);
|
||||
if (flash_path.empty())
|
||||
return;
|
||||
AtomContentClient::AtomContentClient() {}
|
||||
|
||||
auto flash_version = command_line->GetSwitchValueASCII(
|
||||
switches::kPpapiFlashVersion);
|
||||
|
||||
plugins->push_back(CreatePepperFlashInfo(flash_path, flash_version));
|
||||
}
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
|
||||
void AddWidevineCdmFromCommandLine(
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
base::FilePath widevine_cdm_path = command_line->GetSwitchValuePath(
|
||||
switches::kWidevineCdmPath);
|
||||
if (widevine_cdm_path.empty())
|
||||
return;
|
||||
|
||||
if (!base::PathExists(widevine_cdm_path))
|
||||
return;
|
||||
|
||||
auto widevine_cdm_version = command_line->GetSwitchValueASCII(
|
||||
switches::kWidevineCdmVersion);
|
||||
if (widevine_cdm_version.empty())
|
||||
return;
|
||||
|
||||
plugins->push_back(CreateWidevineCdmInfo(widevine_cdm_path,
|
||||
widevine_cdm_version));
|
||||
}
|
||||
#endif
|
||||
|
||||
AtomContentClient::AtomContentClient() {
|
||||
}
|
||||
|
||||
AtomContentClient::~AtomContentClient() {
|
||||
}
|
||||
AtomContentClient::~AtomContentClient() {}
|
||||
|
||||
std::string AtomContentClient::GetProduct() const {
|
||||
return "Chrome/" CHROME_VERSION_STRING;
|
||||
}
|
||||
|
||||
std::string AtomContentClient::GetUserAgent() const {
|
||||
return content::BuildUserAgentFromProduct(
|
||||
"Chrome/" CHROME_VERSION_STRING " "
|
||||
ATOM_PRODUCT_NAME "/" ATOM_VERSION_STRING);
|
||||
return content::BuildUserAgentFromProduct("Chrome/" CHROME_VERSION_STRING
|
||||
" " ATOM_PRODUCT_NAME
|
||||
"/" ATOM_VERSION_STRING);
|
||||
}
|
||||
|
||||
base::string16 AtomContentClient::GetLocalizedString(int message_id) const {
|
||||
@@ -215,11 +224,43 @@ void AtomContentClient::AddAdditionalSchemes(Schemes* schemes) {
|
||||
|
||||
void AtomContentClient::AddPepperPlugins(
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
AddPepperFlashFromCommandLine(plugins);
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
|
||||
AddWidevineCdmFromCommandLine(plugins);
|
||||
#endif
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
#if defined(ENABLE_PEPPER_FLASH)
|
||||
AddPepperFlashFromCommandLine(command_line, plugins);
|
||||
#endif // defined(ENABLE_PEPPER_FLASH)
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE)
|
||||
AddWidevineAdapterFromCommandLine(command_line, plugins);
|
||||
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
||||
ComputeBuiltInPlugins(plugins);
|
||||
}
|
||||
|
||||
void AtomContentClient::AddContentDecryptionModules(
|
||||
std::vector<content::CdmInfo>* cdms,
|
||||
std::vector<media::CdmHostFilePath>* cdm_host_file_paths) {
|
||||
if (cdms) {
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE)
|
||||
base::FilePath adapter_path;
|
||||
base::FilePath cdm_path;
|
||||
std::vector<media::VideoCodec> video_codecs_supported;
|
||||
bool supports_persistent_license = false;
|
||||
if (IsWidevineAvailable(&adapter_path, &cdm_path,
|
||||
&video_codecs_supported)) {
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto cdm_version_string =
|
||||
command_line->GetSwitchValueASCII(switches::kWidevineCdmVersion);
|
||||
// CdmInfo needs |path| to be the actual Widevine library,
|
||||
// not the adapter, so adjust as necessary. It will be in the
|
||||
// same directory as the installed adapter.
|
||||
const base::Version version(cdm_version_string);
|
||||
DCHECK(version.IsValid());
|
||||
|
||||
cdms->push_back(content::CdmInfo(
|
||||
kWidevineCdmDisplayName, kWidevineCdmGuid, version, cdm_path,
|
||||
kWidevineCdmFileSystemId, video_codecs_supported,
|
||||
supports_persistent_license, kWidevineKeySystem, false));
|
||||
}
|
||||
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace atom {
|
||||
class AtomContentClient : public brightray::ContentClient {
|
||||
public:
|
||||
AtomContentClient();
|
||||
virtual ~AtomContentClient();
|
||||
~AtomContentClient() override;
|
||||
|
||||
protected:
|
||||
// content::ContentClient:
|
||||
@@ -26,6 +26,9 @@ class AtomContentClient : public brightray::ContentClient {
|
||||
void AddAdditionalSchemes(Schemes* schemes) override;
|
||||
void AddPepperPlugins(
|
||||
std::vector<content::PepperPluginInfo>* plugins) override;
|
||||
void AddContentDecryptionModules(
|
||||
std::vector<content::CdmInfo>* cdms,
|
||||
std::vector<media::CdmHostFilePath>* cdm_host_file_paths) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
extern "C" {
|
||||
__attribute__((visibility("default")))
|
||||
int AtomMain(int argc, char* argv[]);
|
||||
__attribute__((visibility("default"))) int AtomMain(int argc, char* argv[]);
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
int AtomInitializeICUandStartNode(int argc, char *argv[]);
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
__attribute__((visibility("default"))) int AtomInitializeICUandStartNode(
|
||||
int argc,
|
||||
char* argv[]);
|
||||
#endif
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "brightray/common/mac/main_application_bundle.h"
|
||||
#include "content/public/app/content_main.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
int AtomMain(int argc, char* argv[]) {
|
||||
atom::AtomMainDelegate delegate;
|
||||
content::ContentMainParams params(&delegate);
|
||||
@@ -24,7 +23,8 @@ int AtomMain(int argc, char* argv[]) {
|
||||
return content::ContentMain(params);
|
||||
}
|
||||
|
||||
int AtomInitializeICUandStartNode(int argc, char *argv[]) {
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
int AtomInitializeICUandStartNode(int argc, char* argv[]) {
|
||||
base::AtExitManager atexit_manager;
|
||||
base::mac::ScopedNSAutoreleasePool pool;
|
||||
base::mac::SetOverrideFrameworkBundlePath(
|
||||
@@ -35,4 +35,4 @@ int AtomInitializeICUandStartNode(int argc, char *argv[]) {
|
||||
base::i18n::InitializeICU();
|
||||
return atom::NodeMain(argc, argv);
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
int main(int argc, char* argv[]) {
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
NSArray* pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents];
|
||||
pathComponents = [pathComponents subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)];
|
||||
pathComponents = [pathComponents
|
||||
subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)];
|
||||
NSString* path = [NSString pathWithComponents:pathComponents];
|
||||
[[NSWorkspace sharedWorkspace] launchApplication:path];
|
||||
[pool drain];
|
||||
|
||||
@@ -25,9 +25,13 @@
|
||||
#include "content/public/app/sandbox_helper_win.h"
|
||||
#include "sandbox/win/src/sandbox_types.h"
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include "atom/app/atom_main_delegate.h" // NOLINT
|
||||
#include "content/public/app/content_main.h"
|
||||
#else // defined(OS_LINUX)
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include "atom/app/atom_library_main.h"
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
@@ -39,9 +43,10 @@
|
||||
namespace {
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
const auto kRunAsNode = "ELECTRON_RUN_AS_NODE";
|
||||
const char kRunAsNode[] = "ELECTRON_RUN_AS_NODE";
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_RUN_AS_NODE) || defined(OS_WIN)
|
||||
bool IsEnvSet(const char* name) {
|
||||
#if defined(OS_WIN)
|
||||
size_t required_size;
|
||||
@@ -52,6 +57,26 @@ bool IsEnvSet(const char* name) {
|
||||
return indicator && indicator[0] != '\0';
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
void FixStdioStreams() {
|
||||
// libuv may mark stdin/stdout/stderr as close-on-exec, which interferes
|
||||
// with chromium's subprocess spawning. As a workaround, we detect if these
|
||||
// streams are closed on startup, and reopen them as /dev/null if necessary.
|
||||
// Otherwise, an unrelated file descriptor will be assigned as stdout/stderr
|
||||
// which may cause various errors when attempting to write to them.
|
||||
//
|
||||
// For details see https://github.com/libuv/libuv/issues/2062
|
||||
struct stat st;
|
||||
if (fstat(STDIN_FILENO, &st) < 0 && errno == EBADF)
|
||||
freopen("/dev/null", "r", stdin);
|
||||
if (fstat(STDOUT_FILENO, &st) < 0 && errno == EBADF)
|
||||
freopen("/dev/null", "w", stdout);
|
||||
if (fstat(STDERR_FILENO, &st) < 0 && errno == EBADF)
|
||||
freopen("/dev/null", "w", stderr);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -115,9 +140,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
// from within the CRT's atexit facility, ensuring the heap functions are
|
||||
// still active. The second invocation from the OS loader will be a no-op.
|
||||
extern void NTAPI OnThreadExit(PVOID module, DWORD reason, PVOID reserved);
|
||||
atexit([]() {
|
||||
OnThreadExit(nullptr, DLL_THREAD_DETACH, nullptr);
|
||||
});
|
||||
atexit([]() { OnThreadExit(nullptr, DLL_THREAD_DETACH, nullptr); });
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
@@ -157,6 +180,8 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
FixStdioStreams();
|
||||
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
base::i18n::InitializeICU();
|
||||
base::AtExitManager atexit_manager;
|
||||
@@ -176,6 +201,8 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
FixStdioStreams();
|
||||
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
return AtomInitializeICUandStartNode(argc, argv);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "ipc/ipc_features.h"
|
||||
#include "services/service_manager/sandbox/switches.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/base/resource/resource_bundle.h"
|
||||
|
||||
@@ -45,22 +46,23 @@ bool IsBrowserProcess(base::CommandLine* cmd) {
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void InvalidParameterHandler(const wchar_t*, const wchar_t*, const wchar_t*,
|
||||
unsigned int, uintptr_t) {
|
||||
void InvalidParameterHandler(const wchar_t*,
|
||||
const wchar_t*,
|
||||
const wchar_t*,
|
||||
unsigned int,
|
||||
uintptr_t) {
|
||||
// noop.
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomMainDelegate::AtomMainDelegate() {
|
||||
}
|
||||
AtomMainDelegate::AtomMainDelegate() {}
|
||||
|
||||
AtomMainDelegate::~AtomMainDelegate() {
|
||||
}
|
||||
AtomMainDelegate::~AtomMainDelegate() {}
|
||||
|
||||
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
|
||||
logging::LoggingSettings settings;
|
||||
#if defined(OS_WIN)
|
||||
@@ -77,12 +79,12 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
#else
|
||||
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
#endif // defined(DEBUG)
|
||||
#else // defined(OS_WIN)
|
||||
#else // defined(OS_WIN)
|
||||
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
#endif // !defined(OS_WIN)
|
||||
|
||||
// Only enable logging when --enable-logging is specified.
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
auto env = base::Environment::Create();
|
||||
if (!command_line->HasSwitch(::switches::kEnableLogging) &&
|
||||
!env->HasVar("ELECTRON_ENABLE_LOGGING")) {
|
||||
settings.logging_dest = logging::LOG_NONE;
|
||||
@@ -99,6 +101,11 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
bool enable_stack_dumping = true;
|
||||
#else
|
||||
bool enable_stack_dumping = env->HasVar("ELECTRON_ENABLE_STACK_DUMPING");
|
||||
#endif
|
||||
#if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
|
||||
// For 32bit ARM enabling stack printing would end up crashing.
|
||||
// https://github.com/electron/electron/pull/11230#issuecomment-363232482
|
||||
enable_stack_dumping = false;
|
||||
#endif
|
||||
if (enable_stack_dumping)
|
||||
base::debug::EnableInProcessStackDumping();
|
||||
@@ -123,14 +130,9 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
void AtomMainDelegate::PreSandboxStartup() {
|
||||
brightray::MainDelegate::PreSandboxStartup();
|
||||
|
||||
// Set google API key.
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (!env->HasVar("GOOGLE_API_KEY"))
|
||||
env->SetVar("GOOGLE_API_KEY", GOOGLEAPIS_API_KEY);
|
||||
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string process_type = command_line->GetSwitchValueASCII(
|
||||
::switches::kProcessType);
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string process_type =
|
||||
command_line->GetSwitchValueASCII(::switches::kProcessType);
|
||||
|
||||
// Only append arguments for browser process.
|
||||
if (!IsBrowserProcess(command_line))
|
||||
@@ -140,7 +142,8 @@ void AtomMainDelegate::PreSandboxStartup() {
|
||||
if (command_line->HasSwitch(switches::kEnableSandbox)) {
|
||||
// Disable setuid sandbox since it is not longer required on
|
||||
// linux(namespace sandbox is available on most distros).
|
||||
command_line->AppendSwitch(::switches::kDisableSetuidSandbox);
|
||||
command_line->AppendSwitch(
|
||||
service_manager::switches::kDisableSetuidSandbox);
|
||||
} else {
|
||||
// Disable renderer sandbox for most of node's functions.
|
||||
command_line->AppendSwitch(::switches::kNoSandbox);
|
||||
@@ -162,11 +165,11 @@ content::ContentBrowserClient* AtomMainDelegate::CreateContentBrowserClient() {
|
||||
}
|
||||
|
||||
content::ContentRendererClient*
|
||||
AtomMainDelegate::CreateContentRendererClient() {
|
||||
AtomMainDelegate::CreateContentRendererClient() {
|
||||
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kEnableSandbox) ||
|
||||
switches::kEnableSandbox) ||
|
||||
!base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
::switches::kNoSandbox)) {
|
||||
::switches::kNoSandbox)) {
|
||||
renderer_client_.reset(new AtomSandboxedRendererClient);
|
||||
} else {
|
||||
renderer_client_.reset(new AtomRendererClient);
|
||||
@@ -202,7 +205,7 @@ bool AtomMainDelegate::DelaySandboxInitialization(
|
||||
|
||||
std::unique_ptr<brightray::ContentClient>
|
||||
AtomMainDelegate::CreateContentClient() {
|
||||
return std::unique_ptr<brightray::ContentClient>(new AtomContentClient);
|
||||
return std::make_unique<AtomContentClient>();
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace atom {
|
||||
class AtomMainDelegate : public brightray::MainDelegate {
|
||||
public:
|
||||
AtomMainDelegate();
|
||||
~AtomMainDelegate();
|
||||
~AtomMainDelegate() override;
|
||||
|
||||
protected:
|
||||
// content::ContentMainDelegate:
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
#include "atom/app/atom_main_delegate.h"
|
||||
|
||||
#include "base/mac/bundle_locations.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/mac/bundle_locations.h"
|
||||
#include "base/mac/foundation_util.h"
|
||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||
#include "base/path_service.h"
|
||||
@@ -20,16 +20,17 @@ namespace atom {
|
||||
namespace {
|
||||
|
||||
base::FilePath GetFrameworksPath() {
|
||||
return brightray::MainApplicationBundlePath().Append("Contents")
|
||||
.Append("Frameworks");
|
||||
return brightray::MainApplicationBundlePath()
|
||||
.Append("Contents")
|
||||
.Append("Frameworks");
|
||||
}
|
||||
|
||||
base::FilePath GetHelperAppPath(const base::FilePath& frameworks_path,
|
||||
const std::string& name) {
|
||||
return frameworks_path.Append(name + " Helper.app")
|
||||
.Append("Contents")
|
||||
.Append("MacOS")
|
||||
.Append(name + " Helper");
|
||||
.Append("Contents")
|
||||
.Append("MacOS")
|
||||
.Append(name + " Helper");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -41,11 +42,11 @@ void AtomMainDelegate::OverrideFrameworkBundlePath() {
|
||||
|
||||
void AtomMainDelegate::OverrideChildProcessPath() {
|
||||
base::FilePath frameworks_path = GetFrameworksPath();
|
||||
base::FilePath helper_path = GetHelperAppPath(frameworks_path,
|
||||
ATOM_PRODUCT_NAME);
|
||||
base::FilePath helper_path =
|
||||
GetHelperAppPath(frameworks_path, ATOM_PRODUCT_NAME);
|
||||
if (!base::PathExists(helper_path))
|
||||
helper_path = GetHelperAppPath(frameworks_path,
|
||||
brightray::GetApplicationName());
|
||||
helper_path =
|
||||
GetHelperAppPath(frameworks_path, brightray::GetApplicationName());
|
||||
if (!base::PathExists(helper_path))
|
||||
LOG(FATAL) << "Unable to find helper app";
|
||||
PathService::Override(content::CHILD_PROCESS_EXE, helper_path);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,4 +14,3 @@ bool CheckCommandLineArguments(int argc, base::CommandLine::CharType** argv);
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_APP_COMMAND_LINE_ARGS_H_
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/crash_reporter/crash_reporter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/task_scheduler/task_scheduler.h"
|
||||
@@ -25,7 +26,7 @@
|
||||
|
||||
namespace atom {
|
||||
|
||||
int NodeMain(int argc, char *argv[]) {
|
||||
int NodeMain(int argc, char* argv[]) {
|
||||
base::CommandLine::Init(argc, argv);
|
||||
|
||||
int exit_code = 1;
|
||||
@@ -37,11 +38,12 @@ int NodeMain(int argc, char *argv[]) {
|
||||
base::ThreadTaskRunnerHandle handle(uv_task_runner);
|
||||
|
||||
// Initialize feature list.
|
||||
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
|
||||
auto feature_list = std::make_unique<base::FeatureList>();
|
||||
feature_list->InitializeFromCommandLine("", "");
|
||||
base::FeatureList::SetInstance(std::move(feature_list));
|
||||
|
||||
gin::V8Initializer::LoadV8Snapshot();
|
||||
gin::V8Initializer::LoadV8Snapshot(
|
||||
gin::V8Initializer::V8SnapshotFileType::kWithAdditionalContext);
|
||||
gin::V8Initializer::LoadV8Natives();
|
||||
|
||||
// V8 requires a task scheduler apparently
|
||||
@@ -50,14 +52,16 @@ int NodeMain(int argc, char *argv[]) {
|
||||
// Initialize gin::IsolateHolder.
|
||||
JavascriptEnvironment gin_env;
|
||||
|
||||
// Explicitly register electron's builtin modules.
|
||||
NodeBindings::RegisterBuiltinModules();
|
||||
|
||||
int exec_argc;
|
||||
const char** exec_argv;
|
||||
node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
|
||||
|
||||
node::IsolateData isolate_data(gin_env.isolate(), loop);
|
||||
node::Environment* env = node::CreateEnvironment(
|
||||
&isolate_data, gin_env.context(), argc, argv,
|
||||
exec_argc, exec_argv);
|
||||
node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform()),
|
||||
gin_env.context(), argc, argv, exec_argc, exec_argv);
|
||||
|
||||
// Enable support for v8 inspector.
|
||||
NodeDebugger node_debugger(env);
|
||||
@@ -79,6 +83,7 @@ int NodeMain(int argc, char *argv[]) {
|
||||
bool more;
|
||||
do {
|
||||
more = uv_run(env->event_loop(), UV_RUN_ONCE);
|
||||
gin_env.platform()->DrainBackgroundTasks(env->isolate());
|
||||
if (more == false) {
|
||||
node::EmitBeforeExit(env);
|
||||
|
||||
@@ -92,6 +97,8 @@ int NodeMain(int argc, char *argv[]) {
|
||||
|
||||
exit_code = node::EmitExit(env);
|
||||
node::RunAtExit(env);
|
||||
gin_env.platform()->DrainBackgroundTasks(env->isolate());
|
||||
gin_env.platform()->CancelPendingDelayedTasks(env->isolate());
|
||||
|
||||
node::FreeEnvironment(env);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace atom {
|
||||
|
||||
int NodeMain(int argc, char *argv[]);
|
||||
int NodeMain(int argc, char* argv[]);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
|
||||
namespace atom {
|
||||
|
||||
UvTaskRunner::UvTaskRunner(uv_loop_t* loop) : loop_(loop) {
|
||||
}
|
||||
UvTaskRunner::UvTaskRunner(uv_loop_t* loop) : loop_(loop) {}
|
||||
|
||||
UvTaskRunner::~UvTaskRunner() {
|
||||
for (auto& iter : tasks_) {
|
||||
@@ -20,7 +19,7 @@ UvTaskRunner::~UvTaskRunner() {
|
||||
}
|
||||
}
|
||||
|
||||
bool UvTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
bool UvTaskRunner::PostDelayedTask(const base::Location& from_here,
|
||||
base::OnceClosure task,
|
||||
base::TimeDelta delay) {
|
||||
auto* timer = new uv_timer_t;
|
||||
@@ -35,10 +34,9 @@ bool UvTaskRunner::RunsTasksInCurrentSequence() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UvTaskRunner::PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
base::OnceClosure task,
|
||||
base::TimeDelta delay) {
|
||||
bool UvTaskRunner::PostNonNestableDelayedTask(const base::Location& from_here,
|
||||
base::OnceClosure task,
|
||||
base::TimeDelta delay) {
|
||||
return PostDelayedTask(from_here, std::move(task), delay);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
#include <map>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/location.h"
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "vendor/node/deps/uv/include/uv.h"
|
||||
#include "uv.h" // NOLINT(build/include)
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -17,19 +18,18 @@ namespace atom {
|
||||
class UvTaskRunner : public base::SingleThreadTaskRunner {
|
||||
public:
|
||||
explicit UvTaskRunner(uv_loop_t* loop);
|
||||
~UvTaskRunner() override;
|
||||
|
||||
// base::SingleThreadTaskRunner:
|
||||
bool PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
bool PostDelayedTask(const base::Location& from_here,
|
||||
base::OnceClosure task,
|
||||
base::TimeDelta delay) override;
|
||||
bool RunsTasksInCurrentSequence() const override;
|
||||
bool PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
base::OnceClosure task,
|
||||
base::TimeDelta delay) override;
|
||||
bool PostNonNestableDelayedTask(const base::Location& from_here,
|
||||
base::OnceClosure task,
|
||||
base::TimeDelta delay) override;
|
||||
|
||||
private:
|
||||
~UvTaskRunner() override;
|
||||
static void OnTimeout(uv_timer_t* timer);
|
||||
static void OnClose(uv_handle_t* handle);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "atom/common/native_mate_converters/network_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
@@ -47,6 +48,7 @@
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/ssl/client_cert_identity.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
#include "services/network/public/cpp/network_switches.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
@@ -64,9 +66,10 @@ using atom::Browser;
|
||||
namespace mate {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<Browser::UserTask> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
Browser::UserTask* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
@@ -83,13 +86,14 @@ struct Converter<Browser::UserTask> {
|
||||
}
|
||||
};
|
||||
|
||||
using atom::JumpListItem;
|
||||
using atom::JumpListCategory;
|
||||
using atom::JumpListItem;
|
||||
using atom::JumpListResult;
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<JumpListItem::Type> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
JumpListItem::Type* out) {
|
||||
std::string item_type;
|
||||
if (!ConvertFromV8(isolate, val, &item_type))
|
||||
@@ -127,9 +131,10 @@ struct Converter<JumpListItem::Type> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<JumpListItem> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
JumpListItem* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
@@ -189,9 +194,10 @@ struct Converter<JumpListItem> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<JumpListCategory::Type> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
JumpListCategory::Type* out) {
|
||||
std::string category_type;
|
||||
if (!ConvertFromV8(isolate, val, &category_type))
|
||||
@@ -235,9 +241,10 @@ struct Converter<JumpListCategory::Type> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<JumpListCategory> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
JumpListCategory* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
@@ -264,7 +271,7 @@ struct Converter<JumpListCategory> {
|
||||
};
|
||||
|
||||
// static
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<JumpListResult> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, JumpListResult val) {
|
||||
std::string result_code;
|
||||
@@ -298,9 +305,10 @@ struct Converter<JumpListResult> {
|
||||
};
|
||||
#endif
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<Browser::LoginItemSettings> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
Browser::LoginItemSettings* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
@@ -325,15 +333,16 @@ struct Converter<Browser::LoginItemSettings> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<content::CertificateRequestResultType> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
content::CertificateRequestResultType* out) {
|
||||
bool b;
|
||||
if (!ConvertFromV8(isolate, val, &b))
|
||||
return false;
|
||||
*out = b ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE :
|
||||
content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
|
||||
*out = b ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
|
||||
: content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -342,6 +351,16 @@ struct Converter<content::CertificateRequestResultType> {
|
||||
|
||||
namespace atom {
|
||||
|
||||
ProcessMetric::ProcessMetric(int type,
|
||||
base::ProcessId pid,
|
||||
std::unique_ptr<base::ProcessMetrics> metrics) {
|
||||
this->type = type;
|
||||
this->pid = pid;
|
||||
this->metrics = std::move(metrics);
|
||||
}
|
||||
|
||||
ProcessMetric::~ProcessMetric() = default;
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
@@ -405,7 +424,9 @@ int GetPathConstant(const std::string& name) {
|
||||
}
|
||||
|
||||
bool NotificationCallbackWrapper(
|
||||
const ProcessSingleton::NotificationCallback& callback,
|
||||
const base::Callback<
|
||||
void(const base::CommandLine::StringVector& command_line,
|
||||
const base::FilePath& current_directory)>& callback,
|
||||
const base::CommandLine::StringVector& cmd,
|
||||
const base::FilePath& cwd) {
|
||||
// Make sure the callback is called after app gets ready.
|
||||
@@ -415,7 +436,7 @@ bool NotificationCallbackWrapper(
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner(
|
||||
base::ThreadTaskRunnerHandle::Get());
|
||||
task_runner->PostTask(
|
||||
FROM_HERE, base::Bind(base::IgnoreResult(callback), cmd, cwd));
|
||||
FROM_HERE, base::BindOnce(base::IgnoreResult(callback), cmd, cwd));
|
||||
}
|
||||
// ProcessSingleton needs to know whether current process is quiting.
|
||||
return !Browser::Get()->is_shutting_down();
|
||||
@@ -479,12 +500,11 @@ void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
|
||||
}
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
int ImportIntoCertStore(
|
||||
CertificateManagerModel* model,
|
||||
const base::DictionaryValue& options) {
|
||||
int ImportIntoCertStore(CertificateManagerModel* model,
|
||||
const base::DictionaryValue& options) {
|
||||
std::string file_data, cert_path;
|
||||
base::string16 password;
|
||||
net::CertificateList imported_certs;
|
||||
net::ScopedCERTCertificateList imported_certs;
|
||||
int rv = -1;
|
||||
options.GetString("certificate", &cert_path);
|
||||
options.GetString("password", &password);
|
||||
@@ -492,17 +512,13 @@ int ImportIntoCertStore(
|
||||
if (!cert_path.empty()) {
|
||||
if (base::ReadFileToString(base::FilePath(cert_path), &file_data)) {
|
||||
auto module = model->cert_db()->GetPrivateSlot();
|
||||
rv = model->ImportFromPKCS12(module.get(),
|
||||
file_data,
|
||||
password,
|
||||
true,
|
||||
rv = model->ImportFromPKCS12(module.get(), file_data, password, true,
|
||||
&imported_certs);
|
||||
if (imported_certs.size() > 1) {
|
||||
auto it = imported_certs.begin();
|
||||
++it; // skip first which would be the client certificate.
|
||||
for (; it != imported_certs.end(); ++it)
|
||||
rv &= model->SetCertTrust(it->get(),
|
||||
net::CA_CERT,
|
||||
rv &= model->SetCertTrust(it->get(), net::CA_CERT,
|
||||
net::NSSCertDatabase::TRUSTED_SSL);
|
||||
}
|
||||
}
|
||||
@@ -521,7 +537,7 @@ void OnIconDataAvailable(v8::Isolate* isolate,
|
||||
callback.Run(v8::Null(isolate), *icon);
|
||||
} else {
|
||||
v8::Local<v8::String> error_message =
|
||||
v8::String::NewFromUtf8(isolate, "Failed to get file icon.");
|
||||
v8::String::NewFromUtf8(isolate, "Failed to get file icon.");
|
||||
callback.Run(v8::Exception::Error(error_message), gfx::Image());
|
||||
}
|
||||
}
|
||||
@@ -533,29 +549,31 @@ App::App(v8::Isolate* isolate) {
|
||||
Browser::Get()->AddObserver(this);
|
||||
content::GpuDataManager::GetInstance()->AddObserver(this);
|
||||
base::ProcessId pid = base::GetCurrentProcId();
|
||||
std::unique_ptr<atom::ProcessMetric> process_metric(
|
||||
new atom::ProcessMetric(
|
||||
content::PROCESS_TYPE_BROWSER,
|
||||
pid,
|
||||
base::ProcessMetrics::CreateCurrentProcessMetrics()));
|
||||
auto process_metric = std::make_unique<atom::ProcessMetric>(
|
||||
content::PROCESS_TYPE_BROWSER, pid,
|
||||
base::ProcessMetrics::CreateCurrentProcessMetrics());
|
||||
app_metrics_[pid] = std::move(process_metric);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
App::~App() {
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(
|
||||
nullptr);
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())
|
||||
->set_delegate(nullptr);
|
||||
Browser::Get()->RemoveObserver(this);
|
||||
content::GpuDataManager::GetInstance()->RemoveObserver(this);
|
||||
content::BrowserChildProcessObserver::Remove(this);
|
||||
}
|
||||
|
||||
void App::OnBeforeQuit(bool* prevent_default) {
|
||||
*prevent_default = Emit("before-quit");
|
||||
if (Emit("before-quit")) {
|
||||
*prevent_default = true;
|
||||
}
|
||||
}
|
||||
|
||||
void App::OnWillQuit(bool* prevent_default) {
|
||||
*prevent_default = Emit("will-quit");
|
||||
if (Emit("will-quit")) {
|
||||
*prevent_default = true;
|
||||
}
|
||||
}
|
||||
|
||||
void App::OnWindowAllClosed() {
|
||||
@@ -573,7 +591,9 @@ void App::OnQuit() {
|
||||
}
|
||||
|
||||
void App::OnOpenFile(bool* prevent_default, const std::string& file_path) {
|
||||
*prevent_default = Emit("open-file", file_path);
|
||||
if (Emit("open-file", file_path)) {
|
||||
*prevent_default = true;
|
||||
}
|
||||
}
|
||||
|
||||
void App::OnOpenURL(const std::string& url) {
|
||||
@@ -609,36 +629,37 @@ void App::OnAccessibilitySupportChanged() {
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void App::OnWillContinueUserActivity(
|
||||
bool* prevent_default,
|
||||
const std::string& type) {
|
||||
*prevent_default = Emit("will-continue-activity", type);
|
||||
void App::OnWillContinueUserActivity(bool* prevent_default,
|
||||
const std::string& type) {
|
||||
if (Emit("will-continue-activity", type)) {
|
||||
*prevent_default = true;
|
||||
}
|
||||
}
|
||||
|
||||
void App::OnDidFailToContinueUserActivity(
|
||||
const std::string& type,
|
||||
const std::string& error) {
|
||||
void App::OnDidFailToContinueUserActivity(const std::string& type,
|
||||
const std::string& error) {
|
||||
Emit("continue-activity-error", type, error);
|
||||
}
|
||||
|
||||
void App::OnContinueUserActivity(
|
||||
bool* prevent_default,
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) {
|
||||
*prevent_default = Emit("continue-activity", type, user_info);
|
||||
void App::OnContinueUserActivity(bool* prevent_default,
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) {
|
||||
if (Emit("continue-activity", type, user_info)) {
|
||||
*prevent_default = true;
|
||||
}
|
||||
}
|
||||
|
||||
void App::OnUserActivityWasContinued(
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) {
|
||||
void App::OnUserActivityWasContinued(const std::string& type,
|
||||
const base::DictionaryValue& user_info) {
|
||||
Emit("activity-was-continued", type, user_info);
|
||||
}
|
||||
|
||||
void App::OnUpdateUserActivityState(
|
||||
bool* prevent_default,
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) {
|
||||
*prevent_default = Emit("update-activity-state", type, user_info);
|
||||
void App::OnUpdateUserActivityState(bool* prevent_default,
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) {
|
||||
if (Emit("update-activity-state", type, user_info)) {
|
||||
*prevent_default = true;
|
||||
}
|
||||
}
|
||||
|
||||
void App::OnNewWindowForTab() {
|
||||
@@ -646,20 +667,17 @@ void App::OnNewWindowForTab() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void App::OnLogin(LoginHandler* login_handler,
|
||||
void App::OnLogin(scoped_refptr<LoginHandler> login_handler,
|
||||
const base::DictionaryValue& request_details) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
bool prevent_default = false;
|
||||
content::WebContents* web_contents = login_handler->GetWebContents();
|
||||
if (web_contents) {
|
||||
prevent_default =
|
||||
Emit("login",
|
||||
WebContents::CreateFrom(isolate(), web_contents),
|
||||
request_details,
|
||||
login_handler->auth_info(),
|
||||
base::Bind(&PassLoginInformation,
|
||||
make_scoped_refptr(login_handler)));
|
||||
prevent_default = Emit(
|
||||
"login", WebContents::CreateFrom(isolate(), web_contents),
|
||||
request_details, login_handler->auth_info(),
|
||||
base::Bind(&PassLoginInformation, base::RetainedRef(login_handler)));
|
||||
}
|
||||
|
||||
// Default behavior is to always cancel the auth.
|
||||
@@ -679,7 +697,7 @@ bool App::CanCreateWindow(
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
const std::vector<std::string>& additional_features,
|
||||
const scoped_refptr<content::ResourceRequestBody>& body,
|
||||
const scoped_refptr<network::ResourceRequestBody>& body,
|
||||
bool user_gesture,
|
||||
bool opener_suppressed,
|
||||
bool* no_javascript_access) {
|
||||
@@ -689,8 +707,8 @@ bool App::CanCreateWindow(
|
||||
content::WebContents::FromRenderFrameHost(opener);
|
||||
if (web_contents) {
|
||||
auto api_web_contents = WebContents::CreateFrom(isolate(), web_contents);
|
||||
api_web_contents->OnCreateWindow(target_url, frame_name, disposition,
|
||||
additional_features, body);
|
||||
api_web_contents->OnCreateWindow(target_url, referrer, frame_name,
|
||||
disposition, additional_features, body);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -702,19 +720,15 @@ void App::AllowCertificateError(
|
||||
const net::SSLInfo& ssl_info,
|
||||
const GURL& request_url,
|
||||
content::ResourceType resource_type,
|
||||
bool overridable,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(content::CertificateRequestResultType)>&
|
||||
callback) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
bool prevent_default = Emit("certificate-error",
|
||||
WebContents::CreateFrom(isolate(), web_contents),
|
||||
request_url,
|
||||
net::ErrorToString(cert_error),
|
||||
ssl_info.cert,
|
||||
callback);
|
||||
bool prevent_default = Emit(
|
||||
"certificate-error", WebContents::CreateFrom(isolate(), web_contents),
|
||||
request_url, net::ErrorToString(cert_error), ssl_info.cert, callback);
|
||||
|
||||
// Deny the certificate by default.
|
||||
if (!prevent_default)
|
||||
@@ -726,8 +740,8 @@ void App::SelectClientCertificate(
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
net::ClientCertIdentityList identities,
|
||||
std::unique_ptr<content::ClientCertificateDelegate> delegate) {
|
||||
std::shared_ptr<content::ClientCertificateDelegate>
|
||||
shared_delegate(delegate.release());
|
||||
std::shared_ptr<content::ClientCertificateDelegate> shared_delegate(
|
||||
delegate.release());
|
||||
|
||||
// Convert the ClientCertIdentityList to a CertificateList
|
||||
// to avoid changes in the API.
|
||||
@@ -757,7 +771,7 @@ void App::SelectClientCertificate(
|
||||
|
||||
void App::OnGpuProcessCrashed(base::TerminationStatus status) {
|
||||
Emit("gpu-process-crashed",
|
||||
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
|
||||
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
|
||||
}
|
||||
|
||||
void App::BrowserChildProcessLaunchedAndConnected(
|
||||
@@ -799,9 +813,8 @@ void App::ChildProcessLaunched(int process_type, base::ProcessHandle handle) {
|
||||
std::unique_ptr<base::ProcessMetrics> metrics(
|
||||
base::ProcessMetrics::CreateProcessMetrics(handle));
|
||||
#endif
|
||||
std::unique_ptr<atom::ProcessMetric> process_metric(
|
||||
new atom::ProcessMetric(process_type, pid, std::move(metrics)));
|
||||
app_metrics_[pid] = std::move(process_metric);
|
||||
app_metrics_[pid] = std::make_unique<atom::ProcessMetric>(process_type, pid,
|
||||
std::move(metrics));
|
||||
}
|
||||
|
||||
void App::ChildProcessDisconnected(base::ProcessId pid) {
|
||||
@@ -854,30 +867,43 @@ std::string App::GetLocale() {
|
||||
return g_browser_process->GetApplicationLocale();
|
||||
}
|
||||
|
||||
bool App::MakeSingleInstance(
|
||||
const ProcessSingleton::NotificationCallback& callback) {
|
||||
void App::OnSecondInstance(const base::CommandLine::StringVector& cmd,
|
||||
const base::FilePath& cwd) {
|
||||
Emit("second-instance", cmd, cwd);
|
||||
}
|
||||
|
||||
bool App::HasSingleInstanceLock() const {
|
||||
if (process_singleton_)
|
||||
return false;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool App::RequestSingleInstanceLock() {
|
||||
if (HasSingleInstanceLock())
|
||||
return true;
|
||||
|
||||
base::FilePath user_dir;
|
||||
PathService::Get(brightray::DIR_USER_DATA, &user_dir);
|
||||
|
||||
auto cb = base::Bind(&App::OnSecondInstance, base::Unretained(this));
|
||||
|
||||
process_singleton_.reset(new ProcessSingleton(
|
||||
user_dir, base::Bind(NotificationCallbackWrapper, callback)));
|
||||
user_dir, base::Bind(NotificationCallbackWrapper, cb)));
|
||||
|
||||
switch (process_singleton_->NotifyOtherProcessOrCreate()) {
|
||||
case ProcessSingleton::NotifyResult::LOCK_ERROR:
|
||||
case ProcessSingleton::NotifyResult::PROFILE_IN_USE:
|
||||
case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: {
|
||||
process_singleton_.reset();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
case ProcessSingleton::NotifyResult::PROCESS_NONE:
|
||||
default: // Shouldn't be needed, but VS warns if it is not there.
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void App::ReleaseSingleInstance() {
|
||||
void App::ReleaseSingleInstanceLock() {
|
||||
if (process_singleton_) {
|
||||
process_singleton_->Cleanup();
|
||||
process_singleton_.reset();
|
||||
@@ -919,8 +945,9 @@ bool App::Relaunch(mate::Arguments* js_args) {
|
||||
|
||||
void App::DisableHardwareAcceleration(mate::Arguments* args) {
|
||||
if (Browser::Get()->is_ready()) {
|
||||
args->ThrowError("app.disableHardwareAcceleration() can only be called "
|
||||
"before app is ready");
|
||||
args->ThrowError(
|
||||
"app.disableHardwareAcceleration() can only be called "
|
||||
"before app is ready");
|
||||
return;
|
||||
}
|
||||
content::GpuDataManager::GetInstance()->DisableHardwareAcceleration();
|
||||
@@ -938,12 +965,12 @@ void App::DisableDomainBlockingFor3DAPIs(mate::Arguments* args) {
|
||||
}
|
||||
|
||||
bool App::IsAccessibilitySupportEnabled() {
|
||||
auto ax_state = content::BrowserAccessibilityState::GetInstance();
|
||||
auto* ax_state = content::BrowserAccessibilityState::GetInstance();
|
||||
return ax_state->IsAccessibleBrowser();
|
||||
}
|
||||
|
||||
void App::SetAccessibilitySupportEnabled(bool enabled) {
|
||||
auto ax_state = content::BrowserAccessibilityState::GetInstance();
|
||||
auto* ax_state = content::BrowserAccessibilityState::GetInstance();
|
||||
if (enabled) {
|
||||
ax_state->OnScreenReaderDetected();
|
||||
} else {
|
||||
@@ -959,18 +986,15 @@ Browser::LoginItemSettings App::GetLoginItemSettings(mate::Arguments* args) {
|
||||
}
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
void App::ImportCertificate(
|
||||
const base::DictionaryValue& options,
|
||||
const net::CompletionCallback& callback) {
|
||||
void App::ImportCertificate(const base::DictionaryValue& options,
|
||||
const net::CompletionCallback& callback) {
|
||||
auto browser_context = AtomBrowserContext::From("", false);
|
||||
if (!certificate_manager_model_) {
|
||||
std::unique_ptr<base::DictionaryValue> copy = options.CreateDeepCopy();
|
||||
CertificateManagerModel::Create(
|
||||
browser_context.get(),
|
||||
base::Bind(&App::OnCertificateManagerModelCreated,
|
||||
base::Unretained(this),
|
||||
base::Passed(©),
|
||||
callback));
|
||||
base::Unretained(this), base::Passed(©), callback));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -983,8 +1007,8 @@ void App::OnCertificateManagerModelCreated(
|
||||
const net::CompletionCallback& callback,
|
||||
std::unique_ptr<CertificateManagerModel> model) {
|
||||
certificate_manager_model_ = std::move(model);
|
||||
int rv = ImportIntoCertStore(certificate_manager_model_.get(),
|
||||
*(options.get()));
|
||||
int rv =
|
||||
ImportIntoCertStore(certificate_manager_model_.get(), *(options.get()));
|
||||
callback.Run(rv);
|
||||
}
|
||||
#endif
|
||||
@@ -1013,7 +1037,7 @@ JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
|
||||
std::vector<JumpListCategory> categories;
|
||||
bool delete_jump_list = val->IsNull();
|
||||
if (!delete_jump_list &&
|
||||
!mate::ConvertFromV8(args->isolate(), val, &categories)) {
|
||||
!mate::ConvertFromV8(args->isolate(), val, &categories)) {
|
||||
args->ThrowError("Argument must be null or an array of categories");
|
||||
return JumpListResult::ARGUMENT_ERROR;
|
||||
}
|
||||
@@ -1021,9 +1045,8 @@ JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
|
||||
JumpList jump_list(Browser::Get()->GetAppUserModelID());
|
||||
|
||||
if (delete_jump_list) {
|
||||
return jump_list.Delete()
|
||||
? JumpListResult::SUCCESS
|
||||
: JumpListResult::GENERIC_ERROR;
|
||||
return jump_list.Delete() ? JumpListResult::SUCCESS
|
||||
: JumpListResult::GENERIC_ERROR;
|
||||
}
|
||||
|
||||
// Start a transaction that updates the JumpList of this application.
|
||||
@@ -1046,8 +1069,7 @@ JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
void App::GetFileIcon(const base::FilePath& path,
|
||||
mate::Arguments* args) {
|
||||
void App::GetFileIcon(const base::FilePath& path, mate::Arguments* args) {
|
||||
mate::Dictionary options;
|
||||
IconLoader::IconSize icon_size;
|
||||
FileIconCallback callback;
|
||||
@@ -1070,7 +1092,7 @@ void App::GetFileIcon(const base::FilePath& path,
|
||||
return;
|
||||
}
|
||||
|
||||
auto icon_manager = g_browser_process->GetIconManager();
|
||||
auto* icon_manager = g_browser_process->GetIconManager();
|
||||
gfx::Image* icon =
|
||||
icon_manager->LookupIconFromFilepath(normalized_path, icon_size);
|
||||
if (icon) {
|
||||
@@ -1092,10 +1114,12 @@ std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
|
||||
mate::Dictionary memory_dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
mate::Dictionary cpu_dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
|
||||
memory_dict.Set("workingSetSize",
|
||||
memory_dict.Set(
|
||||
"workingSetSize",
|
||||
static_cast<double>(
|
||||
process_metric.second->metrics->GetWorkingSetSize() >> 10));
|
||||
memory_dict.Set("peakWorkingSetSize",
|
||||
memory_dict.Set(
|
||||
"peakWorkingSetSize",
|
||||
static_cast<double>(
|
||||
process_metric.second->metrics->GetPeakWorkingSetSize() >> 10));
|
||||
|
||||
@@ -1107,13 +1131,14 @@ std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
pid_dict.Set("memory", memory_dict);
|
||||
cpu_dict.Set("percentCPUUsage",
|
||||
process_metric.second->metrics->GetPlatformIndependentCPUUsage()
|
||||
/ processor_count);
|
||||
cpu_dict.Set(
|
||||
"percentCPUUsage",
|
||||
process_metric.second->metrics->GetPlatformIndependentCPUUsage() /
|
||||
processor_count);
|
||||
|
||||
#if !defined(OS_WIN)
|
||||
cpu_dict.Set("idleWakeupsPerSecond",
|
||||
process_metric.second->metrics->GetIdleWakeupsPerSecond());
|
||||
process_metric.second->metrics->GetIdleWakeupsPerSecond());
|
||||
#else
|
||||
// Chrome's underlying process_metrics.cc will throw a non-fatal warning
|
||||
// that this method isn't implemented on Windows, so set it to 0 instead
|
||||
@@ -1123,8 +1148,8 @@ std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
|
||||
|
||||
pid_dict.Set("cpu", cpu_dict);
|
||||
pid_dict.Set("pid", process_metric.second->pid);
|
||||
pid_dict.Set("type",
|
||||
content::GetProcessTypeNameInEnglish(process_metric.second->type));
|
||||
pid_dict.Set("type", content::GetProcessTypeNameInEnglish(
|
||||
process_metric.second->type));
|
||||
result.push_back(pid_dict);
|
||||
}
|
||||
|
||||
@@ -1133,18 +1158,19 @@ std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
|
||||
|
||||
v8::Local<v8::Value> App::GetGPUFeatureStatus(v8::Isolate* isolate) {
|
||||
auto status = content::GetFeatureStatus();
|
||||
return mate::ConvertToV8(isolate,
|
||||
status ? *status : base::DictionaryValue());
|
||||
base::DictionaryValue temp;
|
||||
return mate::ConvertToV8(isolate, status ? *status : temp);
|
||||
}
|
||||
|
||||
void App::EnableMixedSandbox(mate::Arguments* args) {
|
||||
if (Browser::Get()->is_ready()) {
|
||||
args->ThrowError("app.enableMixedSandbox() can only be called "
|
||||
"before app is ready");
|
||||
args->ThrowError(
|
||||
"app.enableMixedSandbox() can only be called "
|
||||
"before app is ready");
|
||||
return;
|
||||
}
|
||||
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
if (command_line->HasSwitch(::switches::kNoSandbox)) {
|
||||
#if defined(OS_WIN)
|
||||
const base::CommandLine::CharType* noSandboxArg = L"--no-sandbox";
|
||||
@@ -1180,8 +1206,8 @@ mate::Handle<App> App::Create(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
// static
|
||||
void App::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
void App::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "App"));
|
||||
auto browser = base::Unretained(Browser::Get());
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
@@ -1242,8 +1268,9 @@ void App::BuildPrototype(
|
||||
#if defined(USE_NSS_CERTS)
|
||||
.SetMethod("importCertificate", &App::ImportCertificate)
|
||||
#endif
|
||||
.SetMethod("makeSingleInstance", &App::MakeSingleInstance)
|
||||
.SetMethod("releaseSingleInstance", &App::ReleaseSingleInstance)
|
||||
.SetMethod("hasSingleInstanceLock", &App::HasSingleInstanceLock)
|
||||
.SetMethod("requestSingleInstanceLock", &App::RequestSingleInstanceLock)
|
||||
.SetMethod("releaseSingleInstanceLock", &App::ReleaseSingleInstanceLock)
|
||||
.SetMethod("relaunch", &App::Relaunch)
|
||||
.SetMethod("isAccessibilitySupportEnabled",
|
||||
&App::IsAccessibilitySupportEnabled)
|
||||
@@ -1256,15 +1283,15 @@ void App::BuildPrototype(
|
||||
.SetMethod("getFileIcon", &App::GetFileIcon)
|
||||
.SetMethod("getAppMetrics", &App::GetAppMetrics)
|
||||
.SetMethod("getGPUFeatureStatus", &App::GetGPUFeatureStatus)
|
||||
// TODO(juturu): Remove in 2.0, deprecate before then with warnings
|
||||
#if defined(OS_MACOSX)
|
||||
// TODO(juturu): Remove in 2.0, deprecate before then with warnings
|
||||
#if defined(OS_MACOSX)
|
||||
.SetMethod("moveToApplicationsFolder", &App::MoveToApplicationsFolder)
|
||||
.SetMethod("isInApplicationsFolder", &App::IsInApplicationsFolder)
|
||||
#endif
|
||||
#if defined(MAS_BUILD)
|
||||
#endif
|
||||
#if defined(MAS_BUILD)
|
||||
.SetMethod("startAccessingSecurityScopedResource",
|
||||
&App::StartAccessingSecurityScopedResource)
|
||||
#endif
|
||||
#endif
|
||||
.SetMethod("enableMixedSandbox", &App::EnableMixedSandbox);
|
||||
}
|
||||
|
||||
@@ -1272,15 +1299,14 @@ void App::BuildPrototype(
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void AppendSwitch(const std::string& switch_string, mate::Arguments* args) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
|
||||
if (base::EndsWith(switch_string, "-path",
|
||||
base::CompareCase::INSENSITIVE_ASCII) ||
|
||||
switch_string == switches::kLogNetLog) {
|
||||
switch_string == network::switches::kLogNetLog) {
|
||||
base::FilePath path;
|
||||
args->GetNext(&path);
|
||||
command_line->AppendSwitchPath(switch_string, path);
|
||||
@@ -1309,18 +1335,19 @@ void DockSetMenu(atom::api::Menu* menu) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("App", atom::api::App::GetConstructor(isolate)->GetFunction());
|
||||
dict.Set("app", atom::api::App::Create(isolate));
|
||||
dict.SetMethod("appendSwitch", &AppendSwitch);
|
||||
dict.SetMethod("appendArgument",
|
||||
base::Bind(&base::CommandLine::AppendArg,
|
||||
base::Unretained(command_line)));
|
||||
dict.SetMethod("appendArgument", base::Bind(&base::CommandLine::AppendArg,
|
||||
base::Unretained(command_line)));
|
||||
#if defined(OS_MACOSX)
|
||||
auto browser = base::Unretained(Browser::Get());
|
||||
dict.SetMethod("dockBounce", &DockBounce);
|
||||
@@ -1342,4 +1369,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_app, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_app, Initialize)
|
||||
|
||||
@@ -52,11 +52,8 @@ struct ProcessMetric {
|
||||
|
||||
ProcessMetric(int type,
|
||||
base::ProcessId pid,
|
||||
std::unique_ptr<base::ProcessMetrics> metrics) {
|
||||
this->type = type;
|
||||
this->pid = pid;
|
||||
this->metrics = std::move(metrics);
|
||||
}
|
||||
std::unique_ptr<base::ProcessMetrics> metrics);
|
||||
~ProcessMetric();
|
||||
};
|
||||
|
||||
namespace api {
|
||||
@@ -67,8 +64,8 @@ class App : public AtomBrowserClient::Delegate,
|
||||
public content::GpuDataManagerObserver,
|
||||
public content::BrowserChildProcessObserver {
|
||||
public:
|
||||
using FileIconCallback = base::Callback<void(v8::Local<v8::Value>,
|
||||
const gfx::Image&)>;
|
||||
using FileIconCallback =
|
||||
base::Callback<void(v8::Local<v8::Value>, const gfx::Image&)>;
|
||||
|
||||
static mate::Handle<App> Create(v8::Isolate* isolate);
|
||||
|
||||
@@ -101,21 +98,18 @@ class App : public AtomBrowserClient::Delegate,
|
||||
void OnActivate(bool has_visible_windows) override;
|
||||
void OnWillFinishLaunching() override;
|
||||
void OnFinishLaunching(const base::DictionaryValue& launch_info) override;
|
||||
void OnLogin(LoginHandler* login_handler,
|
||||
void OnLogin(scoped_refptr<LoginHandler> login_handler,
|
||||
const base::DictionaryValue& request_details) override;
|
||||
void OnAccessibilitySupportChanged() override;
|
||||
void OnPreMainMessageLoopRun() override;
|
||||
#if defined(OS_MACOSX)
|
||||
void OnWillContinueUserActivity(
|
||||
bool* prevent_default,
|
||||
const std::string& type) override;
|
||||
void OnDidFailToContinueUserActivity(
|
||||
const std::string& type,
|
||||
const std::string& error) override;
|
||||
void OnContinueUserActivity(
|
||||
bool* prevent_default,
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) override;
|
||||
void OnWillContinueUserActivity(bool* prevent_default,
|
||||
const std::string& type) override;
|
||||
void OnDidFailToContinueUserActivity(const std::string& type,
|
||||
const std::string& error) override;
|
||||
void OnContinueUserActivity(bool* prevent_default,
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) override;
|
||||
void OnUserActivityWasContinued(
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) override;
|
||||
@@ -133,7 +127,6 @@ class App : public AtomBrowserClient::Delegate,
|
||||
const net::SSLInfo& ssl_info,
|
||||
const GURL& request_url,
|
||||
content::ResourceType resource_type,
|
||||
bool overridable,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(content::CertificateRequestResultType)>&
|
||||
@@ -154,7 +147,7 @@ class App : public AtomBrowserClient::Delegate,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
const std::vector<std::string>& additional_features,
|
||||
const scoped_refptr<content::ResourceRequestBody>& body,
|
||||
const scoped_refptr<network::ResourceRequestBody>& body,
|
||||
bool user_gesture,
|
||||
bool opener_suppressed,
|
||||
bool* no_javascript_access) override;
|
||||
@@ -167,10 +160,10 @@ class App : public AtomBrowserClient::Delegate,
|
||||
const content::ChildProcessData& data) override;
|
||||
void BrowserChildProcessHostDisconnected(
|
||||
const content::ChildProcessData& data) override;
|
||||
void BrowserChildProcessCrashed(
|
||||
const content::ChildProcessData& data, int exit_code) override;
|
||||
void BrowserChildProcessKilled(
|
||||
const content::ChildProcessData& data, int exit_code) override;
|
||||
void BrowserChildProcessCrashed(const content::ChildProcessData& data,
|
||||
int exit_code) override;
|
||||
void BrowserChildProcessKilled(const content::ChildProcessData& data,
|
||||
int exit_code) override;
|
||||
|
||||
private:
|
||||
void SetAppPath(const base::FilePath& app_path);
|
||||
@@ -185,9 +178,11 @@ class App : public AtomBrowserClient::Delegate,
|
||||
|
||||
void SetDesktopName(const std::string& desktop_name);
|
||||
std::string GetLocale();
|
||||
bool MakeSingleInstance(
|
||||
const ProcessSingleton::NotificationCallback& callback);
|
||||
void ReleaseSingleInstance();
|
||||
void OnSecondInstance(const base::CommandLine::StringVector& cmd,
|
||||
const base::FilePath& cwd);
|
||||
bool HasSingleInstanceLock() const;
|
||||
bool RequestSingleInstanceLock();
|
||||
void ReleaseSingleInstanceLock();
|
||||
bool Relaunch(mate::Arguments* args);
|
||||
void DisableHardwareAcceleration(mate::Arguments* args);
|
||||
void DisableDomainBlockingFor3DAPIs(mate::Arguments* args);
|
||||
@@ -198,8 +193,7 @@ class App : public AtomBrowserClient::Delegate,
|
||||
void ImportCertificate(const base::DictionaryValue& options,
|
||||
const net::CompletionCallback& callback);
|
||||
#endif
|
||||
void GetFileIcon(const base::FilePath& path,
|
||||
mate::Arguments* args);
|
||||
void GetFileIcon(const base::FilePath& path, mate::Arguments* args);
|
||||
|
||||
std::vector<mate::Dictionary> GetAppMetrics(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> GetGPUFeatureStatus(v8::Isolate* isolate);
|
||||
@@ -211,7 +205,7 @@ class App : public AtomBrowserClient::Delegate,
|
||||
#endif
|
||||
#if defined(MAS_BUILD)
|
||||
base::Callback<void()> StartAccessingSecurityScopedResource(
|
||||
mate::Arguments* args);
|
||||
mate::Arguments* args);
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -234,8 +228,7 @@ class App : public AtomBrowserClient::Delegate,
|
||||
base::FilePath app_path_;
|
||||
|
||||
using ProcessMetricMap =
|
||||
std::unordered_map<base::ProcessId,
|
||||
std::unique_ptr<atom::ProcessMetric>>;
|
||||
std::unordered_map<base::ProcessId, std::unique_ptr<atom::ProcessMetric>>;
|
||||
ProcessMetricMap app_metrics_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(App);
|
||||
|
||||
@@ -19,23 +19,27 @@ void OnStopAccessingSecurityScopedResource(NSURL* bookmarkUrl) {
|
||||
}
|
||||
|
||||
// Get base64 encoded NSData, create a bookmark for it and start accessing it.
|
||||
base::Callback<void ()> App::StartAccessingSecurityScopedResource(mate::Arguments* args) {
|
||||
base::Callback<void()> App::StartAccessingSecurityScopedResource(
|
||||
mate::Arguments* args) {
|
||||
std::string data;
|
||||
args->GetNext(&data);
|
||||
NSString *base64str = base::SysUTF8ToNSString(data);
|
||||
NSData *bookmarkData = [[NSData alloc] initWithBase64EncodedString: base64str options: 0];
|
||||
NSString* base64str = base::SysUTF8ToNSString(data);
|
||||
NSData* bookmarkData =
|
||||
[[NSData alloc] initWithBase64EncodedString:base64str options:0];
|
||||
|
||||
// Create bookmarkUrl from NSData.
|
||||
BOOL isStale = false;
|
||||
NSError *error = nil;
|
||||
NSURL *bookmarkUrl = [NSURL URLByResolvingBookmarkData: bookmarkData
|
||||
options: NSURLBookmarkResolutionWithSecurityScope
|
||||
relativeToURL: nil
|
||||
bookmarkDataIsStale: &isStale
|
||||
error: &error];
|
||||
NSError* error = nil;
|
||||
NSURL* bookmarkUrl =
|
||||
[NSURL URLByResolvingBookmarkData:bookmarkData
|
||||
options:NSURLBookmarkResolutionWithSecurityScope
|
||||
relativeToURL:nil
|
||||
bookmarkDataIsStale:&isStale
|
||||
error:&error];
|
||||
|
||||
if (error != nil) {
|
||||
NSString *err = [NSString stringWithFormat: @"NSError: %@ %@", error, [error userInfo]];
|
||||
NSString* err =
|
||||
[NSString stringWithFormat:@"NSError: %@ %@", error, [error userInfo]];
|
||||
args->ThrowError(base::SysNSStringToUTF8(err));
|
||||
}
|
||||
|
||||
@@ -54,6 +58,6 @@ base::Callback<void ()> App::StartAccessingSecurityScopedResource(mate::Argument
|
||||
return base::Bind(&OnStopAccessingSecurityScopedResource, bookmarkUrl);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
} // namespace atom
|
||||
|
||||
} // namespace api
|
||||
} // namespace api
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<base::Time> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const base::Time& val) {
|
||||
v8::MaybeLocal<v8::Value> date = v8::Date::New(
|
||||
isolate->GetCurrentContext(), val.ToJsTime());
|
||||
v8::MaybeLocal<v8::Value> date =
|
||||
v8::Date::New(isolate->GetCurrentContext(), val.ToJsTime());
|
||||
if (date.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
else
|
||||
@@ -49,21 +49,20 @@ void AutoUpdater::OnError(const std::string& message) {
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto error = v8::Exception::Error(mate::StringToV8(isolate(), message));
|
||||
mate::EmitEvent(
|
||||
isolate(),
|
||||
GetWrapper(),
|
||||
"error",
|
||||
isolate(), GetWrapper(), "error",
|
||||
error->ToObject(isolate()->GetCurrentContext()).ToLocalChecked(),
|
||||
// Message is also emitted to keep compatibility with old code.
|
||||
message);
|
||||
}
|
||||
|
||||
void AutoUpdater::OnError(const std::string& message,
|
||||
const int code, const std::string& domain) {
|
||||
const int code,
|
||||
const std::string& domain) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto error = v8::Exception::Error(mate::StringToV8(isolate(), message));
|
||||
auto errorObject = error->ToObject(
|
||||
isolate()->GetCurrentContext()).ToLocalChecked();
|
||||
auto errorObject =
|
||||
error->ToObject(isolate()->GetCurrentContext()).ToLocalChecked();
|
||||
|
||||
// add two new params for better error handling
|
||||
errorObject->Set(mate::StringToV8(isolate(), "code"),
|
||||
@@ -104,6 +103,8 @@ void AutoUpdater::SetFeedURL(mate::Arguments* args) {
|
||||
}
|
||||
|
||||
void AutoUpdater::QuitAndInstall() {
|
||||
Emit("before-quit-for-update");
|
||||
|
||||
// If we don't have any window then quitAndInstall immediately.
|
||||
if (WindowList::IsEmpty()) {
|
||||
auto_updater::AutoUpdater::QuitAndInstall();
|
||||
@@ -121,8 +122,8 @@ mate::Handle<AutoUpdater> AutoUpdater::Create(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
// static
|
||||
void AutoUpdater::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
void AutoUpdater::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "AutoUpdater"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
|
||||
@@ -135,13 +136,14 @@ void AutoUpdater::BuildPrototype(
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::AutoUpdater;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("autoUpdater", AutoUpdater::Create(isolate));
|
||||
@@ -150,4 +152,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_auto_updater, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_auto_updater, Initialize)
|
||||
|
||||
@@ -32,8 +32,9 @@ class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
|
||||
|
||||
// Delegate implementations.
|
||||
void OnError(const std::string& error) override;
|
||||
void OnError(const std::string& message, const int code,
|
||||
const std::string& domain);
|
||||
void OnError(const std::string& message,
|
||||
const int code,
|
||||
const std::string& domain) override;
|
||||
void OnCheckingForUpdate() override;
|
||||
void OnUpdateAvailable() override;
|
||||
void OnUpdateNotAvailable() override;
|
||||
|
||||
87
atom/browser/api/atom_api_box_layout.cc
Normal file
87
atom/browser/api/atom_api_box_layout.cc
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_box_layout.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_view.h"
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<views::BoxLayout::Orientation> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Handle<v8::Value> val,
|
||||
views::BoxLayout::Orientation* out) {
|
||||
std::string orientation;
|
||||
if (!ConvertFromV8(isolate, val, &orientation))
|
||||
return false;
|
||||
if (orientation == "horizontal")
|
||||
*out = views::BoxLayout::kHorizontal;
|
||||
else if (orientation == "vertical")
|
||||
*out = views::BoxLayout::kVertical;
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
BoxLayout::BoxLayout(views::BoxLayout::Orientation orientation)
|
||||
: LayoutManager(new views::BoxLayout(orientation)) {}
|
||||
|
||||
BoxLayout::~BoxLayout() {}
|
||||
|
||||
void BoxLayout::SetFlexForView(mate::Handle<View> view, int flex) {
|
||||
auto* box_layout = static_cast<views::BoxLayout*>(layout_manager());
|
||||
box_layout->SetFlexForView(view->view(), flex);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* BoxLayout::New(mate::Arguments* args,
|
||||
views::BoxLayout::Orientation orientation) {
|
||||
auto* layout = new BoxLayout(orientation);
|
||||
layout->InitWith(args->isolate(), args->GetThis());
|
||||
return layout;
|
||||
}
|
||||
|
||||
// static
|
||||
void BoxLayout::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "BoxLayout"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("setFlexForView", &BoxLayout::SetFlexForView);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::BoxLayout;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("BoxLayout", mate::CreateConstructor<BoxLayout>(
|
||||
isolate, base::Bind(&BoxLayout::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_box_layout, Initialize)
|
||||
40
atom/browser/api/atom_api_box_layout.h
Normal file
40
atom/browser/api/atom_api_box_layout.h
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_BOX_LAYOUT_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_BOX_LAYOUT_H_
|
||||
|
||||
#include "atom/browser/api/atom_api_layout_manager.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class View;
|
||||
|
||||
class BoxLayout : public LayoutManager {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args,
|
||||
views::BoxLayout::Orientation orientation);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
void SetFlexForView(mate::Handle<View> view, int flex);
|
||||
|
||||
protected:
|
||||
explicit BoxLayout(views::BoxLayout::Orientation orientation);
|
||||
~BoxLayout() override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(BoxLayout);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_BOX_LAYOUT_H_
|
||||
@@ -51,8 +51,7 @@ namespace api {
|
||||
|
||||
BrowserView::BrowserView(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options)
|
||||
: api_web_contents_(nullptr) {
|
||||
const mate::Dictionary& options) {
|
||||
Init(isolate, wrapper, options);
|
||||
}
|
||||
|
||||
@@ -153,13 +152,13 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
mate::Dictionary browser_view(
|
||||
isolate, BrowserView::GetConstructor(isolate)->GetFunction());
|
||||
browser_view.SetMethod("fromId",
|
||||
&mate::TrackableObject<BrowserView>::FromWeakMapID);
|
||||
&mate::TrackableObject<BrowserView>::FromWeakMapID);
|
||||
browser_view.SetMethod("getAllViews",
|
||||
&mate::TrackableObject<BrowserView>::GetAll);
|
||||
&mate::TrackableObject<BrowserView>::GetAll);
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("BrowserView", browser_view);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_browser_view, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_browser_view, Initialize)
|
||||
|
||||
@@ -59,7 +59,7 @@ class BrowserView : public mate::TrackableObject<BrowserView> {
|
||||
v8::Local<v8::Value> GetWebContents();
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
class WebContents* api_web_contents_;
|
||||
class WebContents* api_web_contents_ = nullptr;
|
||||
|
||||
std::unique_ptr<NativeBrowserView> view_;
|
||||
|
||||
|
||||
459
atom/browser/api/atom_api_browser_window.cc
Normal file
459
atom/browser/api/atom_api_browser_window.cc
Normal file
@@ -0,0 +1,459 @@
|
||||
// Copyright (c) 2013 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_browser_window.h"
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "atom/common/color_util.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/gl/gpu_switching_manager.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
BrowserWindow::BrowserWindow(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options)
|
||||
: TopLevelWindow(isolate, options), weak_factory_(this) {
|
||||
mate::Handle<class WebContents> web_contents;
|
||||
|
||||
// Use options.webPreferences in WebContents.
|
||||
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
|
||||
options.Get(options::kWebPreferences, &web_preferences);
|
||||
|
||||
// Copy the backgroundColor to webContents.
|
||||
v8::Local<v8::Value> value;
|
||||
if (options.Get(options::kBackgroundColor, &value))
|
||||
web_preferences.Set(options::kBackgroundColor, value);
|
||||
|
||||
v8::Local<v8::Value> transparent;
|
||||
if (options.Get("transparent", &transparent))
|
||||
web_preferences.Set("transparent", transparent);
|
||||
|
||||
if (options.Get("webContents", &web_contents) && !web_contents.IsEmpty()) {
|
||||
// Set webPreferences from options if using an existing webContents.
|
||||
// These preferences will be used when the webContent launches new
|
||||
// render processes.
|
||||
auto* existing_preferences =
|
||||
WebContentsPreferences::From(web_contents->web_contents());
|
||||
base::DictionaryValue web_preferences_dict;
|
||||
if (mate::ConvertFromV8(isolate, web_preferences.GetHandle(),
|
||||
&web_preferences_dict)) {
|
||||
existing_preferences->dict()->Clear();
|
||||
existing_preferences->Merge(web_preferences_dict);
|
||||
}
|
||||
} else {
|
||||
// Creates the WebContents used by BrowserWindow.
|
||||
web_contents = WebContents::Create(isolate, web_preferences);
|
||||
}
|
||||
|
||||
web_contents_.Reset(isolate, web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
api_web_contents_->AddObserver(this);
|
||||
Observe(api_web_contents_->web_contents());
|
||||
|
||||
// Keep a copy of the options for later use.
|
||||
mate::Dictionary(isolate, web_contents->GetWrapper())
|
||||
.Set("browserWindowOptions", options);
|
||||
|
||||
// Tell the content module to initialize renderer widget with transparent
|
||||
// mode.
|
||||
ui::GpuSwitchingManager::SetTransparent(window()->transparent());
|
||||
|
||||
// Associate with BrowserWindow.
|
||||
web_contents->SetOwnerWindow(window());
|
||||
|
||||
auto* host = web_contents->web_contents()->GetRenderViewHost();
|
||||
if (host)
|
||||
host->GetWidget()->AddInputEventObserver(this);
|
||||
|
||||
InitWith(isolate, wrapper);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
if (!window()->has_frame())
|
||||
OverrideNSWindowContentView(web_contents->managed_web_contents());
|
||||
#endif
|
||||
|
||||
// Init window after everything has been setup.
|
||||
window()->InitFromOptions(options);
|
||||
}
|
||||
|
||||
BrowserWindow::~BrowserWindow() {
|
||||
api_web_contents_->RemoveObserver(this);
|
||||
// Note that the OnWindowClosed will not be called after the destructor runs,
|
||||
// since the window object is managed by the TopLevelWindow class.
|
||||
if (web_contents())
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnInputEvent(const blink::WebInputEvent& event) {
|
||||
switch (event.GetType()) {
|
||||
case blink::WebInputEvent::kGestureScrollBegin:
|
||||
case blink::WebInputEvent::kGestureScrollUpdate:
|
||||
case blink::WebInputEvent::kGestureScrollEnd:
|
||||
Emit("scroll-touch-edge");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindow::RenderViewHostChanged(content::RenderViewHost* old_host,
|
||||
content::RenderViewHost* new_host) {
|
||||
if (old_host)
|
||||
old_host->GetWidget()->RemoveInputEventObserver(this);
|
||||
if (new_host)
|
||||
new_host->GetWidget()->AddInputEventObserver(this);
|
||||
}
|
||||
|
||||
void BrowserWindow::RenderViewCreated(
|
||||
content::RenderViewHost* render_view_host) {
|
||||
if (!window()->transparent())
|
||||
return;
|
||||
|
||||
content::RenderWidgetHostImpl* impl = content::RenderWidgetHostImpl::FromID(
|
||||
render_view_host->GetProcess()->GetID(),
|
||||
render_view_host->GetRoutingID());
|
||||
if (impl)
|
||||
impl->SetBackgroundOpaque(false);
|
||||
}
|
||||
|
||||
void BrowserWindow::DidFirstVisuallyNonEmptyPaint() {
|
||||
if (window()->IsVisible())
|
||||
return;
|
||||
|
||||
// When there is a non-empty first paint, resize the RenderWidget to force
|
||||
// Chromium to draw.
|
||||
auto* const view = web_contents()->GetRenderWidgetHostView();
|
||||
view->Show();
|
||||
view->SetSize(window()->GetContentSize());
|
||||
|
||||
// Emit the ReadyToShow event in next tick in case of pending drawing work.
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, base::BindOnce(
|
||||
[](base::WeakPtr<BrowserWindow> self) {
|
||||
if (self)
|
||||
self->Emit("ready-to-show");
|
||||
},
|
||||
GetWeakPtr()));
|
||||
}
|
||||
|
||||
void BrowserWindow::BeforeUnloadDialogCancelled() {
|
||||
WindowList::WindowCloseCancelled(window());
|
||||
// Cancel unresponsive event when window close is cancelled.
|
||||
window_unresponsive_closure_.Cancel();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnRendererUnresponsive(content::RenderProcessHost*) {
|
||||
// Schedule the unresponsive shortly later, since we may receive the
|
||||
// responsive event soon. This could happen after the whole application had
|
||||
// blocked for a while.
|
||||
// Also notice that when closing this event would be ignored because we have
|
||||
// explicitly started a close timeout counter. This is on purpose because we
|
||||
// don't want the unresponsive event to be sent too early when user is closing
|
||||
// the window.
|
||||
ScheduleUnresponsiveEvent(50);
|
||||
}
|
||||
|
||||
bool BrowserWindow::OnMessageReceived(const IPC::Message& message,
|
||||
content::RenderFrameHost* rfh) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserWindow, message, rfh)
|
||||
IPC_MESSAGE_HANDLER(AtomFrameHostMsg_UpdateDraggableRegions,
|
||||
UpdateDraggableRegions)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
}
|
||||
|
||||
void BrowserWindow::OnCloseContents() {
|
||||
// On some machines it may happen that the window gets destroyed for twice,
|
||||
// checking web_contents() can effectively guard against that.
|
||||
// https://github.com/electron/electron/issues/16202.
|
||||
//
|
||||
// TODO(zcbenz): We should find out the root cause and improve the closing
|
||||
// procedure of BrowserWindow.
|
||||
if (!web_contents())
|
||||
return;
|
||||
|
||||
// Close all child windows before closing current window.
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
for (v8::Local<v8::Value> value : child_windows_.Values(isolate())) {
|
||||
mate::Handle<BrowserWindow> child;
|
||||
if (mate::ConvertFromV8(isolate(), value, &child) && !child.IsEmpty())
|
||||
child->window()->CloseImmediately();
|
||||
}
|
||||
|
||||
// When the web contents is gone, close the window immediately, but the
|
||||
// memory will not be freed until you call delete.
|
||||
// In this way, it would be safe to manage windows via smart pointers. If you
|
||||
// want to free memory when the window is closed, you can do deleting by
|
||||
// overriding the OnWindowClosed method in the observer.
|
||||
window()->CloseImmediately();
|
||||
|
||||
// Do not sent "unresponsive" event after window is closed.
|
||||
window_unresponsive_closure_.Cancel();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnRendererResponsive() {
|
||||
window_unresponsive_closure_.Cancel();
|
||||
Emit("responsive");
|
||||
}
|
||||
|
||||
void BrowserWindow::RequestPreferredWidth(int* width) {
|
||||
*width = web_contents()->GetPreferredSize().width();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
|
||||
// When user tries to close the window by clicking the close button, we do
|
||||
// not close the window immediately, instead we try to close the web page
|
||||
// first, and when the web page is closed the window will also be closed.
|
||||
*prevent_default = true;
|
||||
|
||||
// Assume the window is not responding if it doesn't cancel the close and is
|
||||
// not closed in 5s, in this way we can quickly show the unresponsive
|
||||
// dialog when the window is busy executing some script withouth waiting for
|
||||
// the unresponsive timeout.
|
||||
if (window_unresponsive_closure_.IsCancelled())
|
||||
ScheduleUnresponsiveEvent(5000);
|
||||
|
||||
if (!web_contents())
|
||||
// Already closed by renderer
|
||||
return;
|
||||
|
||||
if (web_contents()->NeedToFireBeforeUnload())
|
||||
web_contents()->DispatchBeforeUnload();
|
||||
else
|
||||
web_contents()->Close();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowClosed() {
|
||||
Cleanup();
|
||||
TopLevelWindow::OnWindowClosed();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowBlur() {
|
||||
web_contents()->StoreFocus();
|
||||
#if defined(OS_MACOSX)
|
||||
auto* rwhv = web_contents()->GetRenderWidgetHostView();
|
||||
if (rwhv)
|
||||
rwhv->SetActive(false);
|
||||
#endif
|
||||
|
||||
TopLevelWindow::OnWindowBlur();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowFocus() {
|
||||
web_contents()->RestoreFocus();
|
||||
#if defined(OS_MACOSX)
|
||||
auto* rwhv = web_contents()->GetRenderWidgetHostView();
|
||||
if (rwhv)
|
||||
rwhv->SetActive(true);
|
||||
#else
|
||||
if (!api_web_contents_->IsDevToolsOpened())
|
||||
web_contents()->Focus();
|
||||
#endif
|
||||
|
||||
TopLevelWindow::OnWindowFocus();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowResize() {
|
||||
#if defined(OS_MACOSX)
|
||||
if (!draggable_regions_.empty())
|
||||
UpdateDraggableRegions(nullptr, draggable_regions_);
|
||||
#endif
|
||||
TopLevelWindow::OnWindowResize();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowLeaveFullScreen() {
|
||||
TopLevelWindow::OnWindowLeaveFullScreen();
|
||||
#if defined(OS_MACOSX)
|
||||
if (web_contents()->IsFullscreenForCurrentTab())
|
||||
web_contents()->ExitFullscreen(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BrowserWindow::Focus() {
|
||||
if (api_web_contents_->IsOffScreen())
|
||||
FocusOnWebView();
|
||||
else
|
||||
TopLevelWindow::Focus();
|
||||
}
|
||||
|
||||
void BrowserWindow::Blur() {
|
||||
if (api_web_contents_->IsOffScreen())
|
||||
BlurWebView();
|
||||
else
|
||||
TopLevelWindow::Blur();
|
||||
}
|
||||
|
||||
void BrowserWindow::SetBackgroundColor(const std::string& color_name) {
|
||||
TopLevelWindow::SetBackgroundColor(color_name);
|
||||
auto* view = web_contents()->GetRenderWidgetHostView();
|
||||
if (view)
|
||||
view->SetBackgroundColor(ParseHexColor(color_name));
|
||||
}
|
||||
|
||||
void BrowserWindow::SetBrowserView(v8::Local<v8::Value> value) {
|
||||
TopLevelWindow::SetBrowserView(value);
|
||||
#if defined(OS_MACOSX)
|
||||
UpdateDraggableRegions(nullptr, draggable_regions_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BrowserWindow::SetVibrancy(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> value) {
|
||||
std::string type = mate::V8ToString(value);
|
||||
|
||||
auto* render_view_host = web_contents()->GetRenderViewHost();
|
||||
if (render_view_host) {
|
||||
auto* impl = content::RenderWidgetHostImpl::FromID(
|
||||
render_view_host->GetProcess()->GetID(),
|
||||
render_view_host->GetRoutingID());
|
||||
if (impl)
|
||||
impl->SetBackgroundOpaque(type.empty() ? !window_->transparent() : false);
|
||||
}
|
||||
|
||||
TopLevelWindow::SetVibrancy(isolate, value);
|
||||
}
|
||||
|
||||
void BrowserWindow::FocusOnWebView() {
|
||||
web_contents()->GetRenderViewHost()->GetWidget()->Focus();
|
||||
}
|
||||
|
||||
void BrowserWindow::BlurWebView() {
|
||||
web_contents()->GetRenderViewHost()->GetWidget()->Blur();
|
||||
}
|
||||
|
||||
bool BrowserWindow::IsWebViewFocused() {
|
||||
auto* host_view = web_contents()->GetRenderViewHost()->GetWidget()->GetView();
|
||||
return host_view && host_view->HasFocus();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> BrowserWindow::GetWebContents(v8::Isolate* isolate) {
|
||||
if (web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
return v8::Local<v8::Value>::New(isolate, web_contents_);
|
||||
}
|
||||
|
||||
// Convert draggable regions in raw format to SkRegion format.
|
||||
std::unique_ptr<SkRegion> BrowserWindow::DraggableRegionsToSkRegion(
|
||||
const std::vector<DraggableRegion>& regions) {
|
||||
auto sk_region = std::make_unique<SkRegion>();
|
||||
for (const DraggableRegion& region : regions) {
|
||||
sk_region->op(
|
||||
region.bounds.x(), region.bounds.y(), region.bounds.right(),
|
||||
region.bounds.bottom(),
|
||||
region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
|
||||
}
|
||||
return sk_region;
|
||||
}
|
||||
|
||||
void BrowserWindow::ScheduleUnresponsiveEvent(int ms) {
|
||||
if (!window_unresponsive_closure_.IsCancelled())
|
||||
return;
|
||||
|
||||
window_unresponsive_closure_.Reset(
|
||||
base::Bind(&BrowserWindow::NotifyWindowUnresponsive, GetWeakPtr()));
|
||||
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
||||
FROM_HERE, window_unresponsive_closure_.callback(),
|
||||
base::TimeDelta::FromMilliseconds(ms));
|
||||
}
|
||||
|
||||
void BrowserWindow::NotifyWindowUnresponsive() {
|
||||
window_unresponsive_closure_.Cancel();
|
||||
if (!window_->IsClosed() && window_->IsEnabled() &&
|
||||
!IsUnresponsiveEventSuppressed()) {
|
||||
Emit("unresponsive");
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindow::Cleanup() {
|
||||
auto* host = web_contents()->GetRenderViewHost();
|
||||
if (host)
|
||||
host->GetWidget()->RemoveInputEventObserver(this);
|
||||
|
||||
api_web_contents_->DestroyWebContents(true /* async */);
|
||||
Observe(nullptr);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* BrowserWindow::New(mate::Arguments* args) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Cannot create BrowserWindow before app is ready");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (args->Length() > 1) {
|
||||
args->ThrowError();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mate::Dictionary options;
|
||||
if (!(args->Length() == 1 && args->GetNext(&options))) {
|
||||
options = mate::Dictionary::CreateEmpty(args->isolate());
|
||||
}
|
||||
|
||||
return new BrowserWindow(args->isolate(), args->GetThis(), options);
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserWindow::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "BrowserWindow"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("focusOnWebView", &BrowserWindow::FocusOnWebView)
|
||||
.SetMethod("blurWebView", &BrowserWindow::BlurWebView)
|
||||
.SetMethod("isWebViewFocused", &BrowserWindow::IsWebViewFocused)
|
||||
.SetProperty("webContents", &BrowserWindow::GetWebContents);
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> BrowserWindow::From(v8::Isolate* isolate,
|
||||
NativeWindow* native_window) {
|
||||
auto* existing = TrackableObject::FromWrappedClass(isolate, native_window);
|
||||
if (existing)
|
||||
return existing->GetWrapper();
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::BrowserWindow;
|
||||
using atom::api::TopLevelWindow;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("BrowserWindow", mate::CreateConstructor<BrowserWindow>(
|
||||
isolate, base::Bind(&BrowserWindow::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_window, Initialize)
|
||||
126
atom/browser/api/atom_api_browser_window.h
Normal file
126
atom/browser/api/atom_api_browser_window.h
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2013 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/atom_api_top_level_window.h"
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "base/cancelable_callback.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class BrowserWindow : public TopLevelWindow,
|
||||
public content::RenderWidgetHost::InputEventObserver,
|
||||
public content::WebContentsObserver,
|
||||
public ExtendedWebContentsObserver {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Returns the BrowserWindow object from |native_window|.
|
||||
static v8::Local<v8::Value> From(v8::Isolate* isolate,
|
||||
NativeWindow* native_window);
|
||||
|
||||
base::WeakPtr<BrowserWindow> GetWeakPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
protected:
|
||||
BrowserWindow(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options);
|
||||
~BrowserWindow() override;
|
||||
|
||||
// content::RenderWidgetHost::InputEventObserver:
|
||||
void OnInputEvent(const blink::WebInputEvent& event) override;
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void RenderViewHostChanged(content::RenderViewHost* old_host,
|
||||
content::RenderViewHost* new_host) override;
|
||||
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
|
||||
void DidFirstVisuallyNonEmptyPaint() override;
|
||||
void BeforeUnloadDialogCancelled() override;
|
||||
void OnRendererUnresponsive(content::RenderProcessHost*) override;
|
||||
bool OnMessageReceived(const IPC::Message& message,
|
||||
content::RenderFrameHost* rfh) override;
|
||||
|
||||
// ExtendedWebContentsObserver:
|
||||
void OnCloseContents() override;
|
||||
void OnRendererResponsive() override;
|
||||
|
||||
// NativeWindowObserver:
|
||||
void RequestPreferredWidth(int* width) override;
|
||||
void OnCloseButtonClicked(bool* prevent_default) override;
|
||||
|
||||
// TopLevelWindow:
|
||||
void OnWindowClosed() override;
|
||||
void OnWindowBlur() override;
|
||||
void OnWindowFocus() override;
|
||||
void OnWindowResize() override;
|
||||
void OnWindowLeaveFullScreen() override;
|
||||
void Focus() override;
|
||||
void Blur() override;
|
||||
void SetBackgroundColor(const std::string& color_name) override;
|
||||
void SetBrowserView(v8::Local<v8::Value> value) override;
|
||||
void SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value) override;
|
||||
|
||||
// BrowserWindow APIs.
|
||||
void FocusOnWebView();
|
||||
void BlurWebView();
|
||||
bool IsWebViewFocused();
|
||||
v8::Local<v8::Value> GetWebContents(v8::Isolate* isolate);
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
void OverrideNSWindowContentView(brightray::InspectableWebContents* iwc);
|
||||
#endif
|
||||
|
||||
// Helpers.
|
||||
|
||||
// Called when the window needs to update its draggable region.
|
||||
void UpdateDraggableRegions(content::RenderFrameHost* rfh,
|
||||
const std::vector<DraggableRegion>& regions);
|
||||
|
||||
// Convert draggable regions in raw format to SkRegion format.
|
||||
std::unique_ptr<SkRegion> DraggableRegionsToSkRegion(
|
||||
const std::vector<DraggableRegion>& regions);
|
||||
|
||||
// Schedule a notification unresponsive event.
|
||||
void ScheduleUnresponsiveEvent(int ms);
|
||||
|
||||
// Dispatch unresponsive event to observers.
|
||||
void NotifyWindowUnresponsive();
|
||||
|
||||
// Cleanup our WebContents observers.
|
||||
void Cleanup();
|
||||
|
||||
// Closure that would be called when window is unresponsive when closing,
|
||||
// it should be cancelled when we can prove that the window is responsive.
|
||||
base::CancelableClosure window_unresponsive_closure_;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
std::vector<DraggableRegion> draggable_regions_;
|
||||
#endif
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
api::WebContents* api_web_contents_;
|
||||
|
||||
base::WeakPtrFactory<BrowserWindow> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserWindow);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
|
||||
135
atom/browser/api/atom_api_browser_window_mac.mm
Normal file
135
atom/browser/api/atom_api_browser_window_mac.mm
Normal file
@@ -0,0 +1,135 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_browser_window.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "atom/browser/native_browser_view.h"
|
||||
#include "atom/browser/native_window_mac.h"
|
||||
#include "atom/common/draggable_region.h"
|
||||
#include "base/mac/scoped_nsobject.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
|
||||
@interface NSView (WebContentsView)
|
||||
- (void)setMouseDownCanMoveWindow:(BOOL)can_move;
|
||||
@end
|
||||
|
||||
@interface ControlRegionView : NSView
|
||||
@end
|
||||
|
||||
@implementation ControlRegionView
|
||||
|
||||
- (BOOL)mouseDownCanMoveWindow {
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSView*)hitTest:(NSPoint)aPoint {
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
// Return a vector of non-draggable regions that fill a window of size
|
||||
// |width| by |height|, but leave gaps where the window should be draggable.
|
||||
std::vector<gfx::Rect> CalculateNonDraggableRegions(
|
||||
std::unique_ptr<SkRegion> draggable,
|
||||
int width,
|
||||
int height) {
|
||||
std::vector<gfx::Rect> result;
|
||||
SkRegion non_draggable;
|
||||
non_draggable.op(0, 0, width, height, SkRegion::kUnion_Op);
|
||||
non_draggable.op(*draggable, SkRegion::kDifference_Op);
|
||||
for (SkRegion::Iterator it(non_draggable); !it.done(); it.next()) {
|
||||
result.push_back(gfx::SkIRectToRect(it.rect()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void BrowserWindow::OverrideNSWindowContentView(
|
||||
brightray::InspectableWebContents* iwc) {
|
||||
// Make NativeWindow use a NSView as content view.
|
||||
static_cast<NativeWindowMac*>(window())->OverrideNSWindowContentView();
|
||||
// Add webview to contentView.
|
||||
NSView* webView = iwc->GetView()->GetNativeView();
|
||||
NSView* contentView = [window()->GetNativeWindow() contentView];
|
||||
[webView setFrame:[contentView bounds]];
|
||||
|
||||
// ensure that buttons view is floated to top of view hierarchy
|
||||
NSArray* subviews = [contentView subviews];
|
||||
NSView* last = subviews.lastObject;
|
||||
[contentView addSubview:webView positioned:NSWindowBelow relativeTo:last];
|
||||
|
||||
[contentView viewDidMoveToWindow];
|
||||
}
|
||||
|
||||
void BrowserWindow::UpdateDraggableRegions(
|
||||
content::RenderFrameHost* rfh,
|
||||
const std::vector<DraggableRegion>& regions) {
|
||||
if (window_->has_frame())
|
||||
return;
|
||||
|
||||
// All ControlRegionViews should be added as children of the WebContentsView,
|
||||
// because WebContentsView will be removed and re-added when entering and
|
||||
// leaving fullscreen mode.
|
||||
NSView* webView = web_contents()->GetNativeView();
|
||||
NSInteger webViewWidth = NSWidth([webView bounds]);
|
||||
NSInteger webViewHeight = NSHeight([webView bounds]);
|
||||
|
||||
if ([webView respondsToSelector:@selector(setMouseDownCanMoveWindow:)]) {
|
||||
[webView setMouseDownCanMoveWindow:YES];
|
||||
}
|
||||
|
||||
// Remove all ControlRegionViews that are added last time.
|
||||
// Note that [webView subviews] returns the view's mutable internal array and
|
||||
// it should be copied to avoid mutating the original array while enumerating
|
||||
// it.
|
||||
base::scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
|
||||
for (NSView* subview in subviews.get())
|
||||
if ([subview isKindOfClass:[ControlRegionView class]])
|
||||
[subview removeFromSuperview];
|
||||
|
||||
// Draggable regions is implemented by having the whole web view draggable
|
||||
// (mouseDownCanMoveWindow) and overlaying regions that are not draggable.
|
||||
draggable_regions_ = regions;
|
||||
std::vector<gfx::Rect> drag_exclude_rects;
|
||||
if (regions.empty()) {
|
||||
drag_exclude_rects.push_back(gfx::Rect(0, 0, webViewWidth, webViewHeight));
|
||||
} else {
|
||||
drag_exclude_rects = CalculateNonDraggableRegions(
|
||||
DraggableRegionsToSkRegion(regions), webViewWidth, webViewHeight);
|
||||
}
|
||||
|
||||
if (window_->browser_view())
|
||||
window_->browser_view()->UpdateDraggableRegions(drag_exclude_rects);
|
||||
|
||||
// Create and add a ControlRegionView for each region that needs to be
|
||||
// excluded from the dragging.
|
||||
for (const auto& rect : drag_exclude_rects) {
|
||||
base::scoped_nsobject<NSView> controlRegion(
|
||||
[[ControlRegionView alloc] initWithFrame:NSZeroRect]);
|
||||
[controlRegion setFrame:NSMakeRect(rect.x(), webViewHeight - rect.bottom(),
|
||||
rect.width(), rect.height())];
|
||||
[webView addSubview:controlRegion];
|
||||
}
|
||||
|
||||
// AppKit will not update its cache of mouseDownCanMoveWindow unless something
|
||||
// changes. Previously we tried adding an NSView and removing it, but for some
|
||||
// reason it required reposting the mouse-down event, and didn't always work.
|
||||
// Calling the below seems to be an effective solution.
|
||||
[[webView window] setMovableByWindowBackground:NO];
|
||||
[[webView window] setMovableByWindowBackground:YES];
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
24
atom/browser/api/atom_api_browser_window_views.cc
Normal file
24
atom/browser/api/atom_api_browser_window_views.cc
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_browser_window.h"
|
||||
|
||||
#include "atom/browser/native_window_views.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
void BrowserWindow::UpdateDraggableRegions(
|
||||
content::RenderFrameHost* rfh,
|
||||
const std::vector<DraggableRegion>& regions) {
|
||||
if (window_->has_frame())
|
||||
return;
|
||||
static_cast<NativeWindowViews*>(window_.get())
|
||||
->UpdateDraggableRegions(DraggableRegionsToSkRegion(regions));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
58
atom/browser/api/atom_api_button.cc
Normal file
58
atom/browser/api/atom_api_button.cc
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_button.h"
|
||||
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Button::Button(views::Button* button) : View(button) {
|
||||
view()->set_owned_by_client();
|
||||
}
|
||||
|
||||
Button::~Button() {}
|
||||
|
||||
void Button::ButtonPressed(views::Button* sender, const ui::Event& event) {
|
||||
Emit("click");
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Button::New(mate::Arguments* args) {
|
||||
args->ThrowError("Button can not be created directly");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
void Button::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Button"));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Button;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("Button",
|
||||
mate::CreateConstructor<Button>(isolate, base::Bind(&Button::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_button, Initialize)
|
||||
38
atom/browser/api/atom_api_button.h
Normal file
38
atom/browser/api/atom_api_button.h
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_BUTTON_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_BUTTON_H_
|
||||
|
||||
#include "atom/browser/api/atom_api_view.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/views/controls/button/button.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Button : public View, public views::ButtonListener {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit Button(views::Button* view);
|
||||
~Button() override;
|
||||
|
||||
// views::ButtonListener:
|
||||
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Button);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_BUTTON_H_
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "content/public/browser/tracing_controller.h"
|
||||
@@ -18,20 +19,32 @@ using content::TracingController;
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<base::trace_event::TraceConfig> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
base::trace_event::TraceConfig* out) {
|
||||
// (alexeykuzmin): A combination of "categoryFilter" and "traceOptions"
|
||||
// has to be checked first because none of the fields
|
||||
// in the `memory_dump_config` dict below are mandatory
|
||||
// and we cannot check the config format.
|
||||
Dictionary options;
|
||||
if (!ConvertFromV8(isolate, val, &options))
|
||||
return false;
|
||||
std::string category_filter, trace_options;
|
||||
if (!options.Get("categoryFilter", &category_filter) ||
|
||||
!options.Get("traceOptions", &trace_options))
|
||||
return false;
|
||||
*out = base::trace_event::TraceConfig(category_filter, trace_options);
|
||||
return true;
|
||||
if (ConvertFromV8(isolate, val, &options)) {
|
||||
std::string category_filter, trace_options;
|
||||
if (options.Get("categoryFilter", &category_filter) &&
|
||||
options.Get("traceOptions", &trace_options)) {
|
||||
*out = base::trace_event::TraceConfig(category_filter, trace_options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
base::DictionaryValue memory_dump_config;
|
||||
if (ConvertFromV8(isolate, val, &memory_dump_config)) {
|
||||
*out = base::trace_event::TraceConfig(memory_dump_config);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,36 +54,39 @@ namespace {
|
||||
|
||||
using CompletionCallback = base::Callback<void(const base::FilePath&)>;
|
||||
|
||||
scoped_refptr<TracingController::TraceDataSink> GetTraceDataSink(
|
||||
const base::FilePath& path, const CompletionCallback& callback) {
|
||||
scoped_refptr<TracingController::TraceDataEndpoint> GetTraceDataEndpoint(
|
||||
const base::FilePath& path,
|
||||
const CompletionCallback& callback) {
|
||||
base::FilePath result_file_path = path;
|
||||
if (result_file_path.empty() && !base::CreateTemporaryFile(&result_file_path))
|
||||
LOG(ERROR) << "Creating temporary file failed";
|
||||
|
||||
return TracingController::CreateFileSink(result_file_path,
|
||||
base::Bind(callback,
|
||||
result_file_path));
|
||||
return TracingController::CreateFileEndpoint(
|
||||
result_file_path, base::Bind(callback, result_file_path));
|
||||
}
|
||||
|
||||
void StopRecording(const base::FilePath& path,
|
||||
const CompletionCallback& callback) {
|
||||
TracingController::GetInstance()->StopTracing(
|
||||
GetTraceDataSink(path, callback));
|
||||
GetTraceDataEndpoint(path, callback));
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
auto controller = base::Unretained(TracingController::GetInstance());
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("getCategories", base::Bind(
|
||||
&TracingController::GetCategories, controller));
|
||||
dict.SetMethod("startRecording", base::Bind(
|
||||
&TracingController::StartTracing, controller));
|
||||
dict.SetMethod("getCategories",
|
||||
base::Bind(&TracingController::GetCategories, controller));
|
||||
dict.SetMethod("startRecording",
|
||||
base::Bind(&TracingController::StartTracing, controller));
|
||||
dict.SetMethod("stopRecording", &StopRecording);
|
||||
dict.SetMethod("getTraceBufferUsage", base::Bind(
|
||||
&TracingController::GetTraceBufferUsage, controller));
|
||||
dict.SetMethod(
|
||||
"getTraceBufferUsage",
|
||||
base::Bind(&TracingController::GetTraceBufferUsage, controller));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_content_tracing, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_content_tracing, Initialize)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "atom/browser/api/atom_api_cookies.h"
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/cookie_change_notifier.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
@@ -14,18 +15,17 @@
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/cookies/cookie_monster.h"
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
#include "net/cookies/cookie_store.h"
|
||||
#include "net/cookies/cookie_util.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
using atom::AtomCookieDelegate;
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<atom::api::Cookies::Error> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
atom::api::Cookies::Error val) {
|
||||
@@ -36,7 +36,7 @@ struct Converter<atom::api::Cookies::Error> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<net::CanonicalCookie> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const net::CanonicalCookie& val) {
|
||||
@@ -55,25 +55,22 @@ struct Converter<net::CanonicalCookie> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<net::CookieStore::ChangeCause> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const net::CookieStore::ChangeCause& val) {
|
||||
template <>
|
||||
struct Converter<network::mojom::CookieChangeCause> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
const network::mojom::CookieChangeCause& val) {
|
||||
switch (val) {
|
||||
case net::CookieStore::ChangeCause::INSERTED:
|
||||
case net::CookieStore::ChangeCause::EXPLICIT:
|
||||
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_BETWEEN:
|
||||
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_PREDICATE:
|
||||
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_SINGLE:
|
||||
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_CANONICAL:
|
||||
case network::mojom::CookieChangeCause::INSERTED:
|
||||
case network::mojom::CookieChangeCause::EXPLICIT:
|
||||
return mate::StringToV8(isolate, "explicit");
|
||||
case net::CookieStore::ChangeCause::OVERWRITE:
|
||||
case network::mojom::CookieChangeCause::OVERWRITE:
|
||||
return mate::StringToV8(isolate, "overwrite");
|
||||
case net::CookieStore::ChangeCause::EXPIRED:
|
||||
case network::mojom::CookieChangeCause::EXPIRED:
|
||||
return mate::StringToV8(isolate, "expired");
|
||||
case net::CookieStore::ChangeCause::EVICTED:
|
||||
case network::mojom::CookieChangeCause::EVICTED:
|
||||
return mate::StringToV8(isolate, "evicted");
|
||||
case net::CookieStore::ChangeCause::EXPIRED_OVERWRITE:
|
||||
case network::mojom::CookieChangeCause::EXPIRED_OVERWRITE:
|
||||
return mate::StringToV8(isolate, "expired-overwrite");
|
||||
default:
|
||||
return mate::StringToV8(isolate, "unknown");
|
||||
@@ -166,15 +163,16 @@ void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
GetCookieStore(getter)->GetAllCookiesAsync(filtered_callback);
|
||||
else
|
||||
GetCookieStore(getter)->GetAllCookiesForURLAsync(GURL(url),
|
||||
filtered_callback);
|
||||
filtered_callback);
|
||||
}
|
||||
|
||||
// Removes cookie with |url| and |name| in IO thread.
|
||||
void RemoveCookieOnIOThread(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const GURL& url, const std::string& name,
|
||||
const GURL& url,
|
||||
const std::string& name,
|
||||
const base::Closure& callback) {
|
||||
GetCookieStore(getter)->DeleteCookieAsync(
|
||||
url, name, base::Bind(RunCallbackInUI, callback));
|
||||
url, name, base::BindOnce(RunCallbackInUI, callback));
|
||||
}
|
||||
|
||||
// Callback of SetCookie.
|
||||
@@ -187,7 +185,7 @@ void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
|
||||
void FlushCookieStoreOnIOThread(
|
||||
scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const base::Closure& callback) {
|
||||
GetCookieStore(getter)->FlushStore(base::Bind(RunCallbackInUI, callback));
|
||||
GetCookieStore(getter)->FlushStore(base::BindOnce(RunCallbackInUI, callback));
|
||||
}
|
||||
|
||||
// Sets cookie with |details| in IO thread.
|
||||
@@ -210,90 +208,105 @@ void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
|
||||
base::Time creation_time;
|
||||
if (details->GetDouble("creationDate", &creation_date)) {
|
||||
creation_time = (creation_date == 0) ?
|
||||
base::Time::UnixEpoch() :
|
||||
base::Time::FromDoubleT(creation_date);
|
||||
creation_time = (creation_date == 0)
|
||||
? base::Time::UnixEpoch()
|
||||
: base::Time::FromDoubleT(creation_date);
|
||||
}
|
||||
|
||||
base::Time expiration_time;
|
||||
if (details->GetDouble("expirationDate", &expiration_date)) {
|
||||
expiration_time = (expiration_date == 0) ?
|
||||
base::Time::UnixEpoch() :
|
||||
base::Time::FromDoubleT(expiration_date);
|
||||
expiration_time = (expiration_date == 0)
|
||||
? base::Time::UnixEpoch()
|
||||
: base::Time::FromDoubleT(expiration_date);
|
||||
}
|
||||
|
||||
base::Time last_access_time;
|
||||
if (details->GetDouble("lastAccessDate", &last_access_date)) {
|
||||
last_access_time = (last_access_date == 0) ?
|
||||
base::Time::UnixEpoch() :
|
||||
base::Time::FromDoubleT(last_access_date);
|
||||
last_access_time = (last_access_date == 0)
|
||||
? base::Time::UnixEpoch()
|
||||
: base::Time::FromDoubleT(last_access_date);
|
||||
}
|
||||
|
||||
GetCookieStore(getter)->SetCookieWithDetailsAsync(
|
||||
GURL(url), name, value, domain, path, creation_time,
|
||||
expiration_time, last_access_time, secure, http_only,
|
||||
net::CookieSameSite::DEFAULT_MODE, net::COOKIE_PRIORITY_DEFAULT,
|
||||
base::Bind(OnSetCookie, callback));
|
||||
std::unique_ptr<net::CanonicalCookie> canonical_cookie(
|
||||
net::CanonicalCookie::CreateSanitizedCookie(
|
||||
GURL(url), name, value, domain, path, creation_time, expiration_time,
|
||||
last_access_time, secure, http_only,
|
||||
net::CookieSameSite::DEFAULT_MODE, net::COOKIE_PRIORITY_DEFAULT));
|
||||
auto completion_callback = base::BindOnce(OnSetCookie, callback);
|
||||
if (!canonical_cookie || !canonical_cookie->IsCanonical()) {
|
||||
std::move(completion_callback).Run(false);
|
||||
return;
|
||||
}
|
||||
if (url.empty()) {
|
||||
std::move(completion_callback).Run(false);
|
||||
return;
|
||||
}
|
||||
if (name.empty()) {
|
||||
std::move(completion_callback).Run(false);
|
||||
return;
|
||||
}
|
||||
GetCookieStore(getter)->SetCanonicalCookieAsync(
|
||||
std::move(canonical_cookie), secure, http_only,
|
||||
std::move(completion_callback));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Cookies::Cookies(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context)
|
||||
: request_context_getter_(browser_context->url_request_context_getter()),
|
||||
cookie_delegate_(browser_context->cookie_delegate()) {
|
||||
Cookies::Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context) {
|
||||
Init(isolate);
|
||||
cookie_delegate_->AddObserver(this);
|
||||
cookie_change_subscription_ =
|
||||
browser_context_->cookie_change_notifier()->RegisterCookieChangeCallback(
|
||||
base::Bind(&Cookies::OnCookieChanged, base::Unretained(this)));
|
||||
}
|
||||
|
||||
Cookies::~Cookies() {
|
||||
cookie_delegate_->RemoveObserver(this);
|
||||
}
|
||||
Cookies::~Cookies() {}
|
||||
|
||||
void Cookies::Get(const base::DictionaryValue& filter,
|
||||
const GetCallback& callback) {
|
||||
std::unique_ptr<base::DictionaryValue> copied(filter.CreateDeepCopy());
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(GetCookiesOnIO, getter, Passed(&copied), callback));
|
||||
base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter),
|
||||
std::move(copied), callback));
|
||||
}
|
||||
|
||||
void Cookies::Remove(const GURL& url, const std::string& name,
|
||||
void Cookies::Remove(const GURL& url,
|
||||
const std::string& name,
|
||||
const base::Closure& callback) {
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(RemoveCookieOnIOThread, getter, url, name, callback));
|
||||
base::BindOnce(RemoveCookieOnIOThread, base::RetainedRef(getter), url,
|
||||
name, callback));
|
||||
}
|
||||
|
||||
void Cookies::Set(const base::DictionaryValue& details,
|
||||
const SetCallback& callback) {
|
||||
std::unique_ptr<base::DictionaryValue> copied(details.CreateDeepCopy());
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(SetCookieOnIO, getter, Passed(&copied), callback));
|
||||
base::BindOnce(SetCookieOnIO, base::RetainedRef(getter),
|
||||
std::move(copied), callback));
|
||||
}
|
||||
|
||||
void Cookies::FlushStore(const base::Closure& callback) {
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(FlushCookieStoreOnIOThread, getter, callback));
|
||||
base::BindOnce(FlushCookieStoreOnIOThread, base::RetainedRef(getter),
|
||||
callback));
|
||||
}
|
||||
|
||||
void Cookies::OnCookieChanged(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
net::CookieStore::ChangeCause cause) {
|
||||
Emit("changed", cookie, cause, removed);
|
||||
void Cookies::OnCookieChanged(const CookieDetails* details) {
|
||||
Emit("changed", *(details->cookie), details->cause, details->removed);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
mate::Handle<Cookies> Cookies::Create(
|
||||
v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
mate::Handle<Cookies> Cookies::Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
return mate::CreateHandle(isolate, new Cookies(isolate, browser_context));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/net/atom_cookie_delegate.h"
|
||||
#include "base/callback.h"
|
||||
#include "atom/browser/net/cookie_details.h"
|
||||
#include "base/callback_list.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
|
||||
@@ -27,8 +27,7 @@ class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class Cookies : public mate::TrackableObject<Cookies>,
|
||||
public AtomCookieDelegate::Observer {
|
||||
class Cookies : public mate::TrackableObject<Cookies> {
|
||||
public:
|
||||
enum Error {
|
||||
SUCCESS,
|
||||
@@ -50,19 +49,19 @@ class Cookies : public mate::TrackableObject<Cookies>,
|
||||
~Cookies() override;
|
||||
|
||||
void Get(const base::DictionaryValue& filter, const GetCallback& callback);
|
||||
void Remove(const GURL& url, const std::string& name,
|
||||
void Remove(const GURL& url,
|
||||
const std::string& name,
|
||||
const base::Closure& callback);
|
||||
void Set(const base::DictionaryValue& details, const SetCallback& callback);
|
||||
void FlushStore(const base::Closure& callback);
|
||||
|
||||
// AtomCookieDelegate::Observer:
|
||||
void OnCookieChanged(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
net::CookieStore::ChangeCause cause) override;
|
||||
// CookieChangeNotifier subscription:
|
||||
void OnCookieChanged(const CookieDetails*);
|
||||
|
||||
private:
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
scoped_refptr<AtomCookieDelegate> cookie_delegate_;
|
||||
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
|
||||
cookie_change_subscription_;
|
||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Cookies);
|
||||
};
|
||||
|
||||
@@ -6,16 +6,13 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "content/public/browser/devtools_agent_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
@@ -26,25 +23,22 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents)
|
||||
: web_contents_(web_contents),
|
||||
previous_request_id_(0) {
|
||||
: content::WebContentsObserver(web_contents), web_contents_(web_contents) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Debugger::~Debugger() {
|
||||
}
|
||||
Debugger::~Debugger() {}
|
||||
|
||||
void Debugger::AgentHostClosed(DevToolsAgentHost* agent_host,
|
||||
bool replaced_with_another_client) {
|
||||
std::string detach_reason = "target closed";
|
||||
if (replaced_with_another_client)
|
||||
detach_reason = "replaced with devtools";
|
||||
Emit("detach", detach_reason);
|
||||
void Debugger::AgentHostClosed(DevToolsAgentHost* agent_host) {
|
||||
DCHECK(agent_host == agent_host_);
|
||||
agent_host_ = nullptr;
|
||||
ClearPendingRequests();
|
||||
Emit("detach", "target closed");
|
||||
}
|
||||
|
||||
void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
|
||||
const std::string& message) {
|
||||
DCHECK(agent_host == agent_host_.get());
|
||||
DCHECK(agent_host == agent_host_);
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
@@ -82,42 +76,52 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::RenderFrameHostChanged(content::RenderFrameHost* old_rfh,
|
||||
content::RenderFrameHost* new_rfh) {
|
||||
if (agent_host_) {
|
||||
agent_host_->DisconnectWebContents();
|
||||
auto* web_contents = content::WebContents::FromRenderFrameHost(new_rfh);
|
||||
agent_host_->ConnectWebContents(web_contents);
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::Attach(mate::Arguments* args) {
|
||||
std::string protocol_version;
|
||||
args->GetNext(&protocol_version);
|
||||
|
||||
if (agent_host_) {
|
||||
args->ThrowError("Debugger is already attached to the target");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!protocol_version.empty() &&
|
||||
!DevToolsAgentHost::IsSupportedProtocolVersion(protocol_version)) {
|
||||
args->ThrowError("Requested protocol version is not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents_);
|
||||
if (!agent_host_.get()) {
|
||||
if (!agent_host_) {
|
||||
args->ThrowError("No target available");
|
||||
return;
|
||||
}
|
||||
if (agent_host_->IsAttached()) {
|
||||
args->ThrowError("Another debugger is already attached to this target");
|
||||
return;
|
||||
}
|
||||
|
||||
agent_host_->AttachClient(this);
|
||||
}
|
||||
|
||||
bool Debugger::IsAttached() {
|
||||
return agent_host_.get() ? agent_host_->IsAttached() : false;
|
||||
return agent_host_ && agent_host_->IsAttached();
|
||||
}
|
||||
|
||||
void Debugger::Detach() {
|
||||
if (!agent_host_.get())
|
||||
if (!agent_host_)
|
||||
return;
|
||||
agent_host_->DetachClient(this);
|
||||
AgentHostClosed(agent_host_.get(), false);
|
||||
agent_host_ = nullptr;
|
||||
AgentHostClosed(agent_host_.get());
|
||||
}
|
||||
|
||||
void Debugger::SendCommand(mate::Arguments* args) {
|
||||
if (!agent_host_.get())
|
||||
if (!agent_host_)
|
||||
return;
|
||||
|
||||
std::string method;
|
||||
@@ -143,10 +147,19 @@ void Debugger::SendCommand(mate::Arguments* args) {
|
||||
agent_host_->DispatchProtocolMessage(this, json_args);
|
||||
}
|
||||
|
||||
void Debugger::ClearPendingRequests() {
|
||||
if (pending_requests_.empty())
|
||||
return;
|
||||
base::Value error(base::Value::Type::DICTIONARY);
|
||||
base::Value error_msg("target closed while handling command");
|
||||
error.SetKey("message", std::move(error_msg));
|
||||
for (const auto& it : pending_requests_)
|
||||
it.second.Run(error, base::Value());
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Debugger> Debugger::Create(
|
||||
v8::Isolate* isolate,
|
||||
content::WebContents* web_contents) {
|
||||
mate::Handle<Debugger> Debugger::Create(v8::Isolate* isolate,
|
||||
content::WebContents* web_contents) {
|
||||
return mate::CreateHandle(isolate, new Debugger(isolate, web_contents));
|
||||
}
|
||||
|
||||
@@ -169,8 +182,10 @@ namespace {
|
||||
|
||||
using atom::api::Debugger;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary(isolate, exports)
|
||||
.Set("Debugger", Debugger::GetConstructor(isolate)->GetFunction());
|
||||
@@ -178,4 +193,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_debugger, Initialize);
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_debugger, Initialize);
|
||||
|
||||
@@ -12,12 +12,13 @@
|
||||
#include "base/callback.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/devtools_agent_host_client.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace content {
|
||||
class DevToolsAgentHost;
|
||||
class WebContents;
|
||||
}
|
||||
} // namespace content
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
@@ -27,15 +28,15 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Debugger: public mate::TrackableObject<Debugger>,
|
||||
public content::DevToolsAgentHostClient {
|
||||
class Debugger : public mate::TrackableObject<Debugger>,
|
||||
public content::DevToolsAgentHostClient,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
using SendCommandCallback =
|
||||
base::Callback<void(const base::DictionaryValue&,
|
||||
const base::DictionaryValue&)>;
|
||||
base::Callback<void(const base::Value&, const base::Value&)>;
|
||||
|
||||
static mate::Handle<Debugger> Create(
|
||||
v8::Isolate* isolate, content::WebContents* web_contents);
|
||||
static mate::Handle<Debugger> Create(v8::Isolate* isolate,
|
||||
content::WebContents* web_contents);
|
||||
|
||||
// mate::TrackableObject:
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
@@ -46,11 +47,14 @@ class Debugger: public mate::TrackableObject<Debugger>,
|
||||
~Debugger() override;
|
||||
|
||||
// content::DevToolsAgentHostClient:
|
||||
void AgentHostClosed(content::DevToolsAgentHost* agent_host,
|
||||
bool replaced_with_another_client) override;
|
||||
void AgentHostClosed(content::DevToolsAgentHost* agent_host) override;
|
||||
void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host,
|
||||
const std::string& message) override;
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void RenderFrameHostChanged(content::RenderFrameHost* old_rfh,
|
||||
content::RenderFrameHost* new_rfh) override;
|
||||
|
||||
private:
|
||||
using PendingRequestMap = std::map<int, SendCommandCallback>;
|
||||
|
||||
@@ -58,12 +62,13 @@ class Debugger: public mate::TrackableObject<Debugger>,
|
||||
bool IsAttached();
|
||||
void Detach();
|
||||
void SendCommand(mate::Arguments* args);
|
||||
void ClearPendingRequests();
|
||||
|
||||
content::WebContents* web_contents_; // Weak Reference.
|
||||
scoped_refptr<content::DevToolsAgentHost> agent_host_;
|
||||
|
||||
PendingRequestMap pending_requests_;
|
||||
int previous_request_id_;
|
||||
int previous_request_id_ = 0;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Debugger);
|
||||
};
|
||||
|
||||
@@ -4,85 +4,172 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_desktop_capturer.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using base::PlatformThreadRef;
|
||||
|
||||
#include "atom/common/api/atom_api_native_image.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/task_scheduler/post_task.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "chrome/browser/media/desktop_media_list.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/desktop_capture.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
|
||||
#if defined(OS_WIN)
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
|
||||
#include "ui/display/win/display_info.h"
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<DesktopMediaList::Source> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const DesktopMediaList::Source& source) {
|
||||
template <>
|
||||
struct Converter<atom::api::DesktopCapturer::Source> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
const atom::api::DesktopCapturer::Source& source) {
|
||||
mate::Dictionary dict(isolate, v8::Object::New(isolate));
|
||||
content::DesktopMediaID id = source.id;
|
||||
dict.Set("name", base::UTF16ToUTF8(source.name));
|
||||
content::DesktopMediaID id = source.media_list_source.id;
|
||||
dict.Set("name", base::UTF16ToUTF8(source.media_list_source.name));
|
||||
dict.Set("id", id.ToString());
|
||||
dict.Set(
|
||||
"thumbnail",
|
||||
atom::api::NativeImage::Create(isolate, gfx::Image(source.thumbnail)));
|
||||
dict.Set("thumbnail",
|
||||
atom::api::NativeImage::Create(
|
||||
isolate, gfx::Image(source.media_list_source.thumbnail)));
|
||||
dict.Set("display_id", source.display_id);
|
||||
return ConvertToV8(isolate, dict);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace {
|
||||
|
||||
void EmitFinished(
|
||||
const std::vector<atom::api::DesktopCapturer::Source>& sources,
|
||||
atom::api::DesktopCapturer* cap) {
|
||||
cap->Emit("finished", sources);
|
||||
}
|
||||
|
||||
void StartHandlingTask(bool capture_window,
|
||||
bool capture_screen,
|
||||
const gfx::Size& thumbnail_size,
|
||||
atom::api::DesktopCapturer* cap) {
|
||||
#if defined(OS_WIN)
|
||||
if (content::desktop_capture::CreateDesktopCaptureOptions()
|
||||
.allow_directx_capturer()) {
|
||||
// DxgiDuplicatorController should be alive in this scope according to
|
||||
// screen_capturer_win.cc.
|
||||
auto duplicator = webrtc::DxgiDuplicatorController::Instance();
|
||||
cap->using_directx_capturer_ =
|
||||
webrtc::ScreenCapturerWinDirectx::IsSupported();
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
|
||||
capture_screen ? content::desktop_capture::CreateScreenCapturer()
|
||||
: nullptr);
|
||||
std::unique_ptr<webrtc::DesktopCapturer> window_capturer(
|
||||
capture_window ? content::desktop_capture::CreateWindowCapturer()
|
||||
: nullptr);
|
||||
cap->media_list_.reset(new NativeDesktopMediaList(
|
||||
std::move(screen_capturer), std::move(window_capturer)));
|
||||
|
||||
cap->media_list_->SetThumbnailSize(thumbnail_size);
|
||||
cap->media_list_->StartUpdating(cap);
|
||||
}
|
||||
|
||||
void OnRefreshFinishedTask(atom::api::DesktopCapturer* cap) {
|
||||
const auto media_list_sources = cap->media_list_->GetSources();
|
||||
std::vector<atom::api::DesktopCapturer::Source> sources;
|
||||
for (const auto& media_list_source : media_list_sources) {
|
||||
sources.emplace_back(
|
||||
atom::api::DesktopCapturer::Source{media_list_source, std::string()});
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Gather the same unique screen IDs used by the electron.screen API in order
|
||||
// to provide an association between it and desktopCapturer/getUserMedia.
|
||||
// This is only required when using the DirectX capturer, otherwise the IDs
|
||||
// across the APIs already match.
|
||||
if (cap->using_directx_capturer_) {
|
||||
std::vector<std::string> device_names;
|
||||
// Crucially, this list of device names will be in the same order as
|
||||
// |media_list_sources|.
|
||||
webrtc::DxgiDuplicatorController::Instance()->GetDeviceNames(&device_names);
|
||||
int device_name_index = 0;
|
||||
for (auto& source : sources) {
|
||||
if (source.media_list_source.id.type ==
|
||||
content::DesktopMediaID::TYPE_SCREEN) {
|
||||
const auto& device_name = device_names[device_name_index++];
|
||||
std::wstring wide_device_name;
|
||||
base::UTF8ToWide(device_name.c_str(), device_name.size(),
|
||||
&wide_device_name);
|
||||
const int64_t device_id =
|
||||
display::win::DisplayInfo::DeviceIdFromDeviceName(
|
||||
wide_device_name.c_str());
|
||||
source.display_id = base::Int64ToString(device_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(OS_MACOSX)
|
||||
// On Mac, the IDs across the APIs match.
|
||||
for (auto& source : sources) {
|
||||
if (source.media_list_source.id.type ==
|
||||
content::DesktopMediaID::TYPE_SCREEN) {
|
||||
source.display_id = base::Int64ToString(source.media_list_source.id.id);
|
||||
}
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
// TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome only
|
||||
// supports capturing the entire desktop on Linux. Revisit this if individual
|
||||
// screen support is added.
|
||||
|
||||
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(EmitFinished, sources, cap));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
capture_thread_ = base::CreateSequencedTaskRunnerWithTraits(
|
||||
{base::WithBaseSyncPrimitives(), base::MayBlock(),
|
||||
base::TaskPriority::USER_VISIBLE});
|
||||
}
|
||||
|
||||
DesktopCapturer::~DesktopCapturer() {
|
||||
}
|
||||
DesktopCapturer::~DesktopCapturer() {}
|
||||
|
||||
void DesktopCapturer::StartHandling(bool capture_window,
|
||||
bool capture_screen,
|
||||
const gfx::Size& thumbnail_size) {
|
||||
webrtc::DesktopCaptureOptions options =
|
||||
content::CreateDesktopCaptureOptions();
|
||||
|
||||
std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
|
||||
capture_screen ? webrtc::DesktopCapturer::CreateScreenCapturer(options)
|
||||
: nullptr);
|
||||
std::unique_ptr<webrtc::DesktopCapturer> window_capturer(
|
||||
capture_window ? webrtc::DesktopCapturer::CreateWindowCapturer(options)
|
||||
: nullptr);
|
||||
media_list_.reset(new NativeDesktopMediaList(
|
||||
std::move(screen_capturer), std::move(window_capturer)));
|
||||
|
||||
media_list_->SetThumbnailSize(thumbnail_size);
|
||||
media_list_->StartUpdating(this);
|
||||
capture_thread_->PostTask(
|
||||
FROM_HERE, base::BindOnce(StartHandlingTask, capture_window,
|
||||
capture_screen, thumbnail_size, this));
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceAdded(int index) {
|
||||
}
|
||||
void DesktopCapturer::OnSourceAdded(int index) {}
|
||||
|
||||
void DesktopCapturer::OnSourceRemoved(int index) {
|
||||
}
|
||||
void DesktopCapturer::OnSourceRemoved(int index) {}
|
||||
|
||||
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {
|
||||
}
|
||||
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {}
|
||||
|
||||
void DesktopCapturer::OnSourceNameChanged(int index) {
|
||||
}
|
||||
void DesktopCapturer::OnSourceNameChanged(int index) {}
|
||||
|
||||
void DesktopCapturer::OnSourceThumbnailChanged(int index) {
|
||||
}
|
||||
void DesktopCapturer::OnSourceThumbnailChanged(int index) {}
|
||||
|
||||
bool DesktopCapturer::OnRefreshFinished() {
|
||||
Emit("finished", media_list_->GetSources());
|
||||
capture_thread_->PostTask(FROM_HERE,
|
||||
base::BindOnce(OnRefreshFinishedTask, this));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -93,7 +180,8 @@ mate::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
|
||||
|
||||
// static
|
||||
void DesktopCapturer::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "DesktopCapturer"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("startHandling", &DesktopCapturer::StartHandling);
|
||||
@@ -105,8 +193,10 @@ void DesktopCapturer::BuildPrototype(
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("desktopCapturer", atom::api::DesktopCapturer::Create(isolate));
|
||||
@@ -114,4 +204,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_desktop_capturer, Initialize);
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_desktop_capturer, Initialize);
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "chrome/browser/media/desktop_media_list_observer.h"
|
||||
#include "chrome/browser/media/native_desktop_media_list.h"
|
||||
@@ -14,9 +16,15 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class DesktopCapturer: public mate::EventEmitter<DesktopCapturer>,
|
||||
public DesktopMediaListObserver {
|
||||
class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
|
||||
public DesktopMediaListObserver {
|
||||
public:
|
||||
struct Source {
|
||||
DesktopMediaList::Source media_list_source;
|
||||
// Will be an empty string if not available.
|
||||
std::string display_id;
|
||||
};
|
||||
|
||||
static mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
@@ -26,6 +34,11 @@ class DesktopCapturer: public mate::EventEmitter<DesktopCapturer>,
|
||||
bool capture_screen,
|
||||
const gfx::Size& thumbnail_size);
|
||||
|
||||
std::unique_ptr<DesktopMediaList> media_list_;
|
||||
#if defined(OS_WIN)
|
||||
bool using_directx_capturer_ = false;
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
protected:
|
||||
explicit DesktopCapturer(v8::Isolate* isolate);
|
||||
~DesktopCapturer() override;
|
||||
@@ -39,7 +52,7 @@ class DesktopCapturer: public mate::EventEmitter<DesktopCapturer>,
|
||||
bool OnRefreshFinished() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<DesktopMediaList> media_list_;
|
||||
scoped_refptr<base::SequencedTaskRunner> capture_thread_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DesktopCapturer);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/atom_api_window.h"
|
||||
#include "atom/browser/api/atom_api_browser_window.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/ui/certificate_trust.h"
|
||||
#include "atom/browser/ui/file_dialog.h"
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<file_dialog::Filter> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
@@ -37,7 +37,7 @@ struct Converter<file_dialog::Filter> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<file_dialog::DialogSettings> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
@@ -54,9 +54,9 @@ struct Converter<file_dialog::DialogSettings> {
|
||||
dict.Get("filters", &(out->filters));
|
||||
dict.Get("properties", &(out->properties));
|
||||
dict.Get("showsTagField", &(out->shows_tag_field));
|
||||
#if defined(MAS_BUILD)
|
||||
#if defined(MAS_BUILD)
|
||||
dict.Get("securityScopedBookmarks", &(out->security_scoped_bookmarks));
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -80,8 +80,7 @@ void ShowMessageBox(int type,
|
||||
mate::Arguments* args) {
|
||||
v8::Local<v8::Value> peek = args->PeekNext();
|
||||
atom::MessageBoxCallback callback;
|
||||
if (mate::Converter<atom::MessageBoxCallback>::FromV8(args->isolate(),
|
||||
peek,
|
||||
if (mate::Converter<atom::MessageBoxCallback>::FromV8(args->isolate(), peek,
|
||||
&callback)) {
|
||||
atom::ShowMessageBox(window, static_cast<atom::MessageBoxType>(type),
|
||||
buttons, default_id, cancel_id, options, title,
|
||||
@@ -99,9 +98,8 @@ void ShowOpenDialog(const file_dialog::DialogSettings& settings,
|
||||
mate::Arguments* args) {
|
||||
v8::Local<v8::Value> peek = args->PeekNext();
|
||||
file_dialog::OpenDialogCallback callback;
|
||||
if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(args->isolate(),
|
||||
peek,
|
||||
&callback)) {
|
||||
if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(
|
||||
args->isolate(), peek, &callback)) {
|
||||
file_dialog::ShowOpenDialog(settings, callback);
|
||||
} else {
|
||||
std::vector<base::FilePath> paths;
|
||||
@@ -114,9 +112,8 @@ void ShowSaveDialog(const file_dialog::DialogSettings& settings,
|
||||
mate::Arguments* args) {
|
||||
v8::Local<v8::Value> peek = args->PeekNext();
|
||||
file_dialog::SaveDialogCallback callback;
|
||||
if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(args->isolate(),
|
||||
peek,
|
||||
&callback)) {
|
||||
if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(
|
||||
args->isolate(), peek, &callback)) {
|
||||
file_dialog::ShowSaveDialog(settings, callback);
|
||||
} else {
|
||||
base::FilePath path;
|
||||
@@ -125,8 +122,10 @@ void ShowSaveDialog(const file_dialog::DialogSettings& settings,
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
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("showMessageBox", &ShowMessageBox);
|
||||
dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
|
||||
@@ -140,4 +139,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_dialog, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_dialog, Initialize)
|
||||
|
||||
@@ -19,22 +19,23 @@
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<content::DownloadItem::DownloadState> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
content::DownloadItem::DownloadState state) {
|
||||
template <>
|
||||
struct Converter<download::DownloadItem::DownloadState> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
download::DownloadItem::DownloadState state) {
|
||||
std::string download_state;
|
||||
switch (state) {
|
||||
case content::DownloadItem::IN_PROGRESS:
|
||||
case download::DownloadItem::IN_PROGRESS:
|
||||
download_state = "progressing";
|
||||
break;
|
||||
case content::DownloadItem::COMPLETE:
|
||||
case download::DownloadItem::COMPLETE:
|
||||
download_state = "completed";
|
||||
break;
|
||||
case content::DownloadItem::CANCELLED:
|
||||
case download::DownloadItem::CANCELLED:
|
||||
download_state = "cancelled";
|
||||
break;
|
||||
case content::DownloadItem::INTERRUPTED:
|
||||
case download::DownloadItem::INTERRUPTED:
|
||||
download_state = "interrupted";
|
||||
break;
|
||||
default:
|
||||
@@ -57,7 +58,7 @@ std::map<uint32_t, v8::Global<v8::Object>> g_download_item_objects;
|
||||
} // namespace
|
||||
|
||||
DownloadItem::DownloadItem(v8::Isolate* isolate,
|
||||
content::DownloadItem* download_item)
|
||||
download::DownloadItem* download_item)
|
||||
: download_item_(download_item) {
|
||||
download_item_->AddObserver(this);
|
||||
Init(isolate);
|
||||
@@ -75,18 +76,18 @@ DownloadItem::~DownloadItem() {
|
||||
g_download_item_objects.erase(weak_map_id());
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
|
||||
void DownloadItem::OnDownloadUpdated(download::DownloadItem* item) {
|
||||
if (download_item_->IsDone()) {
|
||||
Emit("done", item->GetState());
|
||||
// Destroy the item once item is downloaded.
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, GetDestroyClosure());
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
|
||||
GetDestroyClosure());
|
||||
} else {
|
||||
Emit("updated", item->GetState());
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) {
|
||||
void DownloadItem::OnDownloadDestroyed(download::DownloadItem* download_item) {
|
||||
download_item_ = nullptr;
|
||||
// Destroy the native class immediately when downloadItem is destroyed.
|
||||
delete this;
|
||||
@@ -129,12 +130,11 @@ bool DownloadItem::HasUserGesture() const {
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetFilename() const {
|
||||
return base::UTF16ToUTF8(net::GenerateFileName(GetURL(),
|
||||
GetContentDisposition(),
|
||||
std::string(),
|
||||
download_item_->GetSuggestedFilename(),
|
||||
GetMimeType(),
|
||||
"download").LossyDisplayName());
|
||||
return base::UTF16ToUTF8(
|
||||
net::GenerateFileName(GetURL(), GetContentDisposition(), std::string(),
|
||||
download_item_->GetSuggestedFilename(),
|
||||
GetMimeType(), "download")
|
||||
.LossyDisplayName());
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetContentDisposition() const {
|
||||
@@ -149,7 +149,7 @@ const std::vector<GURL>& DownloadItem::GetURLChain() const {
|
||||
return download_item_->GetUrlChain();
|
||||
}
|
||||
|
||||
content::DownloadItem::DownloadState DownloadItem::GetState() const {
|
||||
download::DownloadItem::DownloadState DownloadItem::GetState() const {
|
||||
return download_item_->GetState();
|
||||
}
|
||||
|
||||
@@ -206,9 +206,9 @@ void DownloadItem::BuildPrototype(v8::Isolate* isolate,
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<DownloadItem> DownloadItem::Create(
|
||||
v8::Isolate* isolate, content::DownloadItem* item) {
|
||||
auto existing = TrackableObject::FromWrappedClass(isolate, item);
|
||||
mate::Handle<DownloadItem> DownloadItem::Create(v8::Isolate* isolate,
|
||||
download::DownloadItem* item) {
|
||||
auto* existing = TrackableObject::FromWrappedClass(isolate, item);
|
||||
if (existing)
|
||||
return mate::CreateHandle(isolate, static_cast<DownloadItem*>(existing));
|
||||
|
||||
@@ -226,8 +226,10 @@ mate::Handle<DownloadItem> DownloadItem::Create(
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary(isolate, exports)
|
||||
.Set("DownloadItem",
|
||||
@@ -236,4 +238,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_download_item, Initialize);
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_download_item, Initialize);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "content/public/browser/download_item.h"
|
||||
#include "components/download/public/common/download_item.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
@@ -19,10 +19,10 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||
public content::DownloadItem::Observer {
|
||||
public download::DownloadItem::Observer {
|
||||
public:
|
||||
static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
|
||||
content::DownloadItem* item);
|
||||
download::DownloadItem* item);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
@@ -40,7 +40,7 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||
std::string GetContentDisposition() const;
|
||||
const GURL& GetURL() const;
|
||||
const std::vector<GURL>& GetURLChain() const;
|
||||
content::DownloadItem::DownloadState GetState() const;
|
||||
download::DownloadItem::DownloadState GetState() const;
|
||||
bool IsDone() const;
|
||||
void SetSavePath(const base::FilePath& path);
|
||||
base::FilePath GetSavePath() const;
|
||||
@@ -49,16 +49,16 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||
double GetStartTime() const;
|
||||
|
||||
protected:
|
||||
DownloadItem(v8::Isolate* isolate, content::DownloadItem* download_item);
|
||||
~DownloadItem();
|
||||
DownloadItem(v8::Isolate* isolate, download::DownloadItem* download_item);
|
||||
~DownloadItem() override;
|
||||
|
||||
// Override content::DownloadItem::Observer methods
|
||||
void OnDownloadUpdated(content::DownloadItem* download) override;
|
||||
void OnDownloadDestroyed(content::DownloadItem* download) override;
|
||||
// Override download::DownloadItem::Observer methods
|
||||
void OnDownloadUpdated(download::DownloadItem* download) override;
|
||||
void OnDownloadDestroyed(download::DownloadItem* download) override;
|
||||
|
||||
private:
|
||||
base::FilePath save_path_;
|
||||
content::DownloadItem* download_item_;
|
||||
download::DownloadItem* download_item_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DownloadItem);
|
||||
};
|
||||
|
||||
@@ -6,15 +6,45 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_system_preferences.h"
|
||||
#include "atom/common/native_mate_converters/accelerator_converter.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/platform_util.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "base/mac/mac_util.h"
|
||||
#endif
|
||||
|
||||
using extensions::GlobalShortcutListener;
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool RegisteringMediaKeyForUntrustedClient(const ui::Accelerator& accelerator) {
|
||||
if (platform_util::IsAtLeastOS10_14()) {
|
||||
constexpr ui::KeyboardCode mediaKeys[] = {
|
||||
ui::VKEY_MEDIA_PLAY_PAUSE, ui::VKEY_MEDIA_NEXT_TRACK,
|
||||
ui::VKEY_MEDIA_PREV_TRACK, ui::VKEY_MEDIA_STOP};
|
||||
|
||||
if (std::find(std::begin(mediaKeys), std::end(mediaKeys),
|
||||
accelerator.key_code()) != std::end(mediaKeys)) {
|
||||
bool trusted =
|
||||
atom::api::SystemPreferences::IsTrustedAccessibilityClient(false);
|
||||
if (!trusted)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
@@ -31,7 +61,7 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
|
||||
if (accelerator_callback_map_.find(accelerator) ==
|
||||
accelerator_callback_map_.end()) {
|
||||
// This should never occur, because if it does, GlobalGlobalShortcutListener
|
||||
// notifes us with wrong accelerator.
|
||||
// notifies us with wrong accelerator.
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
@@ -40,8 +70,13 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
|
||||
|
||||
bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
|
||||
const base::Closure& callback) {
|
||||
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(
|
||||
accelerator, this)) {
|
||||
#if defined(OS_MACOSX)
|
||||
if (RegisteringMediaKeyForUntrustedClient(accelerator))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(accelerator,
|
||||
this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -54,8 +89,8 @@ void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
|
||||
return;
|
||||
|
||||
accelerator_callback_map_.erase(accelerator);
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(
|
||||
accelerator, this);
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(accelerator,
|
||||
this);
|
||||
}
|
||||
|
||||
bool GlobalShortcut::IsRegistered(const ui::Accelerator& accelerator) {
|
||||
@@ -73,8 +108,8 @@ mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
// static
|
||||
void GlobalShortcut::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
void GlobalShortcut::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "GlobalShortcut"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("register", &GlobalShortcut::Register)
|
||||
@@ -89,8 +124,10 @@ void GlobalShortcut::BuildPrototype(
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("globalShortcut", atom::api::GlobalShortcut::Create(isolate));
|
||||
@@ -98,4 +135,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_global_shortcut, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_global_shortcut, Initialize)
|
||||
|
||||
@@ -45,6 +45,29 @@ struct Converter<in_app_purchase::Transaction> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<in_app_purchase::Product> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const in_app_purchase::Product& val) {
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.SetHidden("simple", true);
|
||||
dict.Set("productIdentifier", val.productIdentifier);
|
||||
dict.Set("localizedDescription", val.localizedDescription);
|
||||
dict.Set("localizedTitle", val.localizedTitle);
|
||||
dict.Set("contentVersion", val.localizedTitle);
|
||||
dict.Set("contentLengths", val.contentLengths);
|
||||
|
||||
// Pricing Information
|
||||
dict.Set("price", val.price);
|
||||
dict.Set("formattedPrice", val.formattedPrice);
|
||||
|
||||
// Downloadable Content Information
|
||||
dict.Set("isDownloadable", val.downloadable);
|
||||
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
@@ -64,15 +87,19 @@ void InAppPurchase::BuildPrototype(v8::Isolate* isolate,
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("canMakePayments", &in_app_purchase::CanMakePayments)
|
||||
.SetMethod("getReceiptURL", &in_app_purchase::GetReceiptURL)
|
||||
.SetMethod("purchaseProduct", &InAppPurchase::PurchaseProduct);
|
||||
.SetMethod("purchaseProduct", &InAppPurchase::PurchaseProduct)
|
||||
.SetMethod("finishAllTransactions",
|
||||
&in_app_purchase::FinishAllTransactions)
|
||||
.SetMethod("finishTransactionByDate",
|
||||
&in_app_purchase::FinishTransactionByDate)
|
||||
.SetMethod("getProducts", &in_app_purchase::GetProducts);
|
||||
}
|
||||
|
||||
InAppPurchase::InAppPurchase(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
InAppPurchase::~InAppPurchase() {
|
||||
}
|
||||
InAppPurchase::~InAppPurchase() {}
|
||||
|
||||
void InAppPurchase::PurchaseProduct(const std::string& product_id,
|
||||
mate::Arguments* args) {
|
||||
@@ -112,4 +139,4 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_in_app_purchase, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_in_app_purchase, Initialize)
|
||||
|
||||
@@ -11,14 +11,15 @@
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/browser/mac/in_app_purchase.h"
|
||||
#include "atom/browser/mac/in_app_purchase_observer.h"
|
||||
#include "atom/browser/mac/in_app_purchase_product.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class InAppPurchase: public mate::EventEmitter<InAppPurchase>,
|
||||
public in_app_purchase::TransactionObserver {
|
||||
class InAppPurchase : public mate::EventEmitter<InAppPurchase>,
|
||||
public in_app_purchase::TransactionObserver {
|
||||
public:
|
||||
static mate::Handle<InAppPurchase> Create(v8::Isolate* isolate);
|
||||
|
||||
|
||||
58
atom/browser/api/atom_api_label_button.cc
Normal file
58
atom/browser/api/atom_api_label_button.cc
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_label_button.h"
|
||||
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/views/controls/button/label_button.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
LabelButton::LabelButton(const std::string& text)
|
||||
: Button(new views::LabelButton(this, base::UTF8ToUTF16(text))) {}
|
||||
|
||||
LabelButton::~LabelButton() {}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* LabelButton::New(mate::Arguments* args,
|
||||
const std::string& text) {
|
||||
// Constructor call.
|
||||
auto* view = new LabelButton(text);
|
||||
view->InitWith(args->isolate(), args->GetThis());
|
||||
return view;
|
||||
}
|
||||
|
||||
// static
|
||||
void LabelButton::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "LabelButton"));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::LabelButton;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("LabelButton", mate::CreateConstructor<LabelButton>(
|
||||
isolate, base::Bind(&LabelButton::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_label_button, Initialize)
|
||||
36
atom/browser/api/atom_api_label_button.h
Normal file
36
atom/browser/api/atom_api_label_button.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_LABEL_BUTTON_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_LABEL_BUTTON_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_button.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class LabelButton : public Button {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args,
|
||||
const std::string& text);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit LabelButton(const std::string& text);
|
||||
~LabelButton() override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(LabelButton);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_LABEL_BUTTON_H_
|
||||
63
atom/browser/api/atom_api_layout_manager.cc
Normal file
63
atom/browser/api/atom_api_layout_manager.cc
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_layout_manager.h"
|
||||
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
LayoutManager::LayoutManager(views::LayoutManager* layout_manager)
|
||||
: layout_manager_(layout_manager) {
|
||||
DCHECK(layout_manager_);
|
||||
}
|
||||
|
||||
LayoutManager::~LayoutManager() {
|
||||
if (managed_by_us_)
|
||||
delete layout_manager_;
|
||||
}
|
||||
|
||||
std::unique_ptr<views::LayoutManager> LayoutManager::TakeOver() {
|
||||
if (!managed_by_us_) // already taken over.
|
||||
return nullptr;
|
||||
managed_by_us_ = false;
|
||||
return std::unique_ptr<views::LayoutManager>(layout_manager_);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* LayoutManager::New(mate::Arguments* args) {
|
||||
args->ThrowError("LayoutManager can not be created directly");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
void LayoutManager::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::LayoutManager;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("LayoutManager", mate::CreateConstructor<LayoutManager>(
|
||||
isolate, base::Bind(&LayoutManager::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_layout_manager, Initialize)
|
||||
44
atom/browser/api/atom_api_layout_manager.h
Normal file
44
atom/browser/api/atom_api_layout_manager.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_LAYOUT_MANAGER_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_LAYOUT_MANAGER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "ui/views/layout/layout_manager.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class LayoutManager : public mate::TrackableObject<LayoutManager> {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Take over the ownership of the LayoutManager, and leave weak ref here.
|
||||
std::unique_ptr<views::LayoutManager> TakeOver();
|
||||
|
||||
views::LayoutManager* layout_manager() const { return layout_manager_; }
|
||||
|
||||
protected:
|
||||
explicit LayoutManager(views::LayoutManager* layout_manager);
|
||||
~LayoutManager() override;
|
||||
|
||||
private:
|
||||
bool managed_by_us_ = true;
|
||||
views::LayoutManager* layout_manager_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LayoutManager);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_LAYOUT_MANAGER_H_
|
||||
@@ -20,8 +20,7 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
Menu::Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
: model_(new AtomMenuModel(this)),
|
||||
parent_(nullptr) {
|
||||
: model_(new AtomMenuModel(this)) {
|
||||
InitWith(isolate, wrapper);
|
||||
model_->AddObserver(this);
|
||||
}
|
||||
@@ -42,6 +41,8 @@ void Menu::AfterInit(v8::Isolate* isolate) {
|
||||
delegate.Get("isCommandIdEnabled", &is_enabled_);
|
||||
delegate.Get("isCommandIdVisible", &is_visible_);
|
||||
delegate.Get("getAcceleratorForCommandId", &get_accelerator_);
|
||||
delegate.Get("shouldRegisterAcceleratorForCommandId",
|
||||
&should_register_accelerator_);
|
||||
delegate.Get("executeCommand", &execute_command_);
|
||||
delegate.Get("menuWillShow", &menu_will_show_);
|
||||
}
|
||||
@@ -70,18 +71,23 @@ bool Menu::GetAcceleratorForCommandIdWithParams(
|
||||
ui::Accelerator* accelerator) const {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
v8::Local<v8::Value> val = get_accelerator_.Run(
|
||||
GetWrapper(), command_id, use_default_accelerator);
|
||||
v8::Local<v8::Value> val =
|
||||
get_accelerator_.Run(GetWrapper(), command_id, use_default_accelerator);
|
||||
return mate::ConvertFromV8(isolate(), val, accelerator);
|
||||
}
|
||||
|
||||
bool Menu::ShouldRegisterAcceleratorForCommandId(int command_id) const {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
return should_register_accelerator_.Run(GetWrapper(), command_id);
|
||||
}
|
||||
|
||||
void Menu::ExecuteCommand(int command_id, int flags) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
execute_command_.Run(
|
||||
GetWrapper(),
|
||||
mate::internal::CreateEventFromFlags(isolate(), flags),
|
||||
command_id);
|
||||
execute_command_.Run(GetWrapper(),
|
||||
mate::internal::CreateEventFromFlags(isolate(), flags),
|
||||
command_id);
|
||||
}
|
||||
|
||||
void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
|
||||
@@ -90,8 +96,9 @@ void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
|
||||
menu_will_show_.Run(GetWrapper());
|
||||
}
|
||||
|
||||
void Menu::InsertItemAt(
|
||||
int index, int command_id, const base::string16& label) {
|
||||
void Menu::InsertItemAt(int index,
|
||||
int command_id,
|
||||
const base::string16& label) {
|
||||
model_->InsertItemAt(index, command_id, label);
|
||||
}
|
||||
|
||||
@@ -207,13 +214,14 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Menu;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
Menu::SetConstructor(isolate, base::Bind(&Menu::New));
|
||||
|
||||
@@ -228,4 +236,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_menu, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_menu, Initialize)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_window.h"
|
||||
#include "atom/browser/api/atom_api_top_level_window.h"
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/ui/atom_menu_model.h"
|
||||
#include "base/callback.h"
|
||||
@@ -18,8 +18,8 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
class Menu : public mate::TrackableObject<Menu>,
|
||||
public AtomMenuModel::Delegate,
|
||||
public AtomMenuModel::Observer {
|
||||
public AtomMenuModel::Delegate,
|
||||
public AtomMenuModel::Observer {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
@@ -51,15 +51,19 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
int command_id,
|
||||
bool use_default_accelerator,
|
||||
ui::Accelerator* accelerator) const override;
|
||||
bool ShouldRegisterAcceleratorForCommandId(int command_id) const override;
|
||||
void ExecuteCommand(int command_id, int event_flags) override;
|
||||
void MenuWillShow(ui::SimpleMenuModel* source) override;
|
||||
|
||||
virtual void PopupAt(Window* window, int x, int y, int positioning_item,
|
||||
virtual void PopupAt(TopLevelWindow* window,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
const base::Closure& callback) = 0;
|
||||
virtual void ClosePopupAt(int32_t window_id) = 0;
|
||||
|
||||
std::unique_ptr<AtomMenuModel> model_;
|
||||
Menu* parent_;
|
||||
Menu* parent_ = nullptr;
|
||||
|
||||
// Observable:
|
||||
void OnMenuWillClose() override;
|
||||
@@ -98,6 +102,7 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
base::Callback<bool(v8::Local<v8::Value>, int)> is_visible_;
|
||||
base::Callback<v8::Local<v8::Value>(v8::Local<v8::Value>, int, bool)>
|
||||
get_accelerator_;
|
||||
base::Callback<bool(v8::Local<v8::Value>, int)> should_register_accelerator_;
|
||||
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>, int)>
|
||||
execute_command_;
|
||||
base::Callback<void(v8::Local<v8::Value>)> menu_will_show_;
|
||||
@@ -109,12 +114,12 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<atom::AtomMenuModel*> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
atom::AtomMenuModel** out) {
|
||||
// null would be tranfered to NULL.
|
||||
if (val->IsNull()) {
|
||||
|
||||
@@ -21,8 +21,12 @@ namespace api {
|
||||
class MenuMac : public Menu {
|
||||
protected:
|
||||
MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
~MenuMac() override;
|
||||
|
||||
void PopupAt(Window* window, int x, int y, int positioning_item,
|
||||
void PopupAt(TopLevelWindow* window,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
const base::Closure& callback) override;
|
||||
void PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
int32_t window_id,
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include "base/mac/scoped_sending_event.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
@@ -29,19 +27,22 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
MenuMac::MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
: Menu(isolate, wrapper),
|
||||
weak_factory_(this) {
|
||||
}
|
||||
: Menu(isolate, wrapper), weak_factory_(this) {}
|
||||
|
||||
void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item,
|
||||
MenuMac::~MenuMac() = default;
|
||||
|
||||
void MenuMac::PopupAt(TopLevelWindow* window,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
const base::Closure& callback) {
|
||||
NativeWindow* native_window = window->window();
|
||||
if (!native_window)
|
||||
return;
|
||||
|
||||
auto popup = base::Bind(&MenuMac::PopupOnUI, weak_factory_.GetWeakPtr(),
|
||||
native_window->GetWeakPtr(), window->ID(), x, y,
|
||||
positioning_item, callback);
|
||||
native_window->GetWeakPtr(), window->weak_map_id(), x,
|
||||
y, positioning_item, callback);
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, popup);
|
||||
}
|
||||
|
||||
@@ -53,18 +54,15 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
base::Closure callback) {
|
||||
if (!native_window)
|
||||
return;
|
||||
brightray::InspectableWebContents* web_contents =
|
||||
native_window->inspectable_web_contents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
NSWindow* nswindow = native_window->GetNativeWindow();
|
||||
|
||||
auto close_callback = base::Bind(
|
||||
&MenuMac::OnClosed, weak_factory_.GetWeakPtr(), window_id, callback);
|
||||
popup_controllers_[window_id] = base::scoped_nsobject<AtomMenuController>(
|
||||
[[AtomMenuController alloc] initWithModel:model()
|
||||
useDefaultAccelerator:NO]);
|
||||
popup_controllers_[window_id] = base::scoped_nsobject<AtomMenuController>([
|
||||
[AtomMenuController alloc] initWithModel:model()
|
||||
useDefaultAccelerator:NO]);
|
||||
NSMenu* menu = [popup_controllers_[window_id] menu];
|
||||
NSView* view = web_contents->GetView()->GetNativeView();
|
||||
NSView* view = [nswindow contentView];
|
||||
|
||||
// Which menu item to show.
|
||||
NSMenuItem* item = nil;
|
||||
@@ -74,7 +72,6 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
// (-1, -1) means showing on mouse location.
|
||||
NSPoint position;
|
||||
if (x == -1 || y == -1) {
|
||||
NSWindow* nswindow = native_window->GetNativeWindow();
|
||||
position = [view convertPoint:[nswindow mouseLocationOutsideOfEventStream]
|
||||
fromView:nil];
|
||||
} else {
|
||||
@@ -138,9 +135,9 @@ void MenuMac::OnClosed(int32_t window_id, base::Closure callback) {
|
||||
// static
|
||||
void Menu::SetApplicationMenu(Menu* base_menu) {
|
||||
MenuMac* menu = static_cast<MenuMac*>(base_menu);
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:menu->model_.get()
|
||||
useDefaultAccelerator:YES]);
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller([
|
||||
[AtomMenuController alloc] initWithModel:menu->model_.get()
|
||||
useDefaultAccelerator:YES]);
|
||||
|
||||
NSRunLoop* currentRunLoop = [NSRunLoop currentRunLoop];
|
||||
[currentRunLoop cancelPerformSelector:@selector(setMainMenu:)
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
using views::MenuRunner;
|
||||
@@ -17,11 +15,14 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
MenuViews::MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
: Menu(isolate, wrapper),
|
||||
weak_factory_(this) {
|
||||
}
|
||||
: Menu(isolate, wrapper), weak_factory_(this) {}
|
||||
|
||||
void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item,
|
||||
MenuViews::~MenuViews() = default;
|
||||
|
||||
void MenuViews::PopupAt(TopLevelWindow* window,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
const base::Closure& callback) {
|
||||
auto* native_window = static_cast<NativeWindowViews*>(window->window());
|
||||
if (!native_window)
|
||||
@@ -42,17 +43,14 @@ void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item,
|
||||
atom::UnresponsiveSuppressor suppressor;
|
||||
|
||||
// Show the menu.
|
||||
int32_t window_id = window->ID();
|
||||
int32_t window_id = window->weak_map_id();
|
||||
auto close_callback = base::Bind(
|
||||
&MenuViews::OnClosed, weak_factory_.GetWeakPtr(), window_id, callback);
|
||||
menu_runners_[window_id] = std::unique_ptr<MenuRunner>(new MenuRunner(
|
||||
model(), flags, close_callback));
|
||||
menu_runners_[window_id] =
|
||||
std::make_unique<MenuRunner>(model(), flags, close_callback);
|
||||
menu_runners_[window_id]->RunMenuAt(
|
||||
native_window->widget(),
|
||||
NULL,
|
||||
gfx::Rect(location, gfx::Size()),
|
||||
views::MENU_ANCHOR_TOPLEFT,
|
||||
ui::MENU_SOURCE_MOUSE);
|
||||
native_window->widget(), NULL, gfx::Rect(location, gfx::Size()),
|
||||
views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_MOUSE);
|
||||
}
|
||||
|
||||
void MenuViews::ClosePopupAt(int32_t window_id) {
|
||||
|
||||
@@ -19,9 +19,13 @@ namespace api {
|
||||
class MenuViews : public Menu {
|
||||
public:
|
||||
MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
~MenuViews() override;
|
||||
|
||||
protected:
|
||||
void PopupAt(Window* window, int x, int y, int positioning_item,
|
||||
void PopupAt(TopLevelWindow* window,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
const base::Closure& callback) override;
|
||||
void ClosePopupAt(int32_t window_id) override;
|
||||
|
||||
|
||||
@@ -58,4 +58,4 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_net, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_net, Initialize)
|
||||
|
||||
137
atom/browser/api/atom_api_net_log.cc
Normal file
137
atom/browser/api/atom_api_net_log.cc
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_net_log.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "base/command_line.h"
|
||||
#include "components/net_log/chrome_net_log.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
NetLog::NetLog(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context) {
|
||||
Init(isolate);
|
||||
|
||||
net_log_writer_ =
|
||||
atom::AtomBrowserMainParts::Get()->net_log()->net_export_file_writer();
|
||||
net_log_writer_->AddObserver(this);
|
||||
}
|
||||
|
||||
NetLog::~NetLog() {
|
||||
net_log_writer_->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void NetLog::StartLogging(mate::Arguments* args) {
|
||||
base::FilePath log_path;
|
||||
if (!args->GetNext(&log_path) || log_path.empty()) {
|
||||
args->ThrowError("The first parameter must be a valid string");
|
||||
return;
|
||||
}
|
||||
|
||||
net_log::NetExportFileWriter::URLRequestContextGetterList context_getters = {
|
||||
browser_context_->GetRequestContext()};
|
||||
|
||||
// TODO(deepak1556): Provide more flexibility to this module
|
||||
// by allowing customizations on the capturing options.
|
||||
net_log_writer_->StartNetLog(
|
||||
log_path, net::NetLogCaptureMode::Default(),
|
||||
net_log::NetExportFileWriter::kNoLimit /* file size limit */,
|
||||
base::CommandLine::ForCurrentProcess()->GetCommandLineString(),
|
||||
std::string(), context_getters);
|
||||
}
|
||||
|
||||
std::string NetLog::GetLoggingState() const {
|
||||
if (!net_log_state_)
|
||||
return std::string();
|
||||
const base::Value* current_log_state =
|
||||
net_log_state_->FindKeyOfType("state", base::Value::Type::STRING);
|
||||
if (!current_log_state)
|
||||
return std::string();
|
||||
return current_log_state->GetString();
|
||||
}
|
||||
|
||||
bool NetLog::IsCurrentlyLogging() const {
|
||||
const std::string log_state = GetLoggingState();
|
||||
return (log_state == "STARTING_LOG") || (log_state == "LOGGING");
|
||||
}
|
||||
|
||||
std::string NetLog::GetCurrentlyLoggingPath() const {
|
||||
// Net log exporter has a default path which will be used
|
||||
// when no log path is provided, but since we don't allow
|
||||
// net log capture without user provided file path, this
|
||||
// check is completely safe.
|
||||
if (IsCurrentlyLogging()) {
|
||||
const base::Value* current_log_path =
|
||||
net_log_state_->FindKeyOfType("file", base::Value::Type::STRING);
|
||||
if (current_log_path)
|
||||
return current_log_path->GetString();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void NetLog::StopLogging(mate::Arguments* args) {
|
||||
net_log::NetExportFileWriter::FilePathCallback callback;
|
||||
if (!args->GetNext(&callback)) {
|
||||
args->ThrowError("Invalid callback function");
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsCurrentlyLogging()) {
|
||||
stop_callback_queue_.emplace_back(callback);
|
||||
net_log_writer_->StopNetLog(nullptr, nullptr);
|
||||
} else {
|
||||
callback.Run(base::FilePath());
|
||||
}
|
||||
}
|
||||
|
||||
void NetLog::OnNewState(const base::DictionaryValue& state) {
|
||||
net_log_state_ = state.CreateDeepCopy();
|
||||
|
||||
if (stop_callback_queue_.empty())
|
||||
return;
|
||||
|
||||
if (GetLoggingState() == "NOT_LOGGING") {
|
||||
for (auto& callback : stop_callback_queue_) {
|
||||
if (!callback.is_null())
|
||||
net_log_writer_->GetFilePathToCompletedLog(callback);
|
||||
}
|
||||
stop_callback_queue_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<NetLog> NetLog::Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
return mate::CreateHandle(isolate, new NetLog(isolate, browser_context));
|
||||
}
|
||||
|
||||
// static
|
||||
void NetLog::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "NetLog"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetProperty("currentlyLogging", &NetLog::IsCurrentlyLogging)
|
||||
.SetProperty("currentlyLoggingPath", &NetLog::GetCurrentlyLoggingPath)
|
||||
.SetMethod("startLogging", &NetLog::StartLogging)
|
||||
.SetMethod("stopLogging", &NetLog::StopLogging);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
60
atom/browser/api/atom_api_net_log.h
Normal file
60
atom/browser/api/atom_api_net_log.h
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_NET_LOG_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_NET_LOG_H_
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/values.h"
|
||||
#include "components/net_log/net_export_file_writer.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class NetLog : public mate::TrackableObject<NetLog>,
|
||||
public net_log::NetExportFileWriter::StateObserver {
|
||||
public:
|
||||
static mate::Handle<NetLog> Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
void StartLogging(mate::Arguments* args);
|
||||
std::string GetLoggingState() const;
|
||||
bool IsCurrentlyLogging() const;
|
||||
std::string GetCurrentlyLoggingPath() const;
|
||||
void StopLogging(mate::Arguments* args);
|
||||
|
||||
protected:
|
||||
explicit NetLog(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~NetLog() override;
|
||||
|
||||
// net_log::NetExportFileWriter::StateObserver implementation
|
||||
void OnNewState(const base::DictionaryValue& state) override;
|
||||
|
||||
private:
|
||||
AtomBrowserContext* browser_context_;
|
||||
net_log::NetExportFileWriter* net_log_writer_;
|
||||
std::list<net_log::NetExportFileWriter::FilePathCallback>
|
||||
stop_callback_queue_;
|
||||
std::unique_ptr<base::DictionaryValue> net_log_state_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NetLog);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_NET_LOG_H_
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "base/guid.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "brightray/browser/browser_client.h"
|
||||
#include "native_mate/constructor.h"
|
||||
@@ -20,10 +21,11 @@
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<brightray::NotificationAction> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
brightray::NotificationAction* out) {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
brightray::NotificationAction* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
@@ -36,7 +38,7 @@ struct Converter<brightray::NotificationAction> {
|
||||
}
|
||||
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
brightray::NotificationAction val) {
|
||||
brightray::NotificationAction val) {
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("text", val.text);
|
||||
dict.Set("type", val.type);
|
||||
@@ -155,7 +157,7 @@ void Notification::SetSound(const base::string16& new_sound) {
|
||||
}
|
||||
|
||||
void Notification::SetActions(
|
||||
const std::vector<brightray::NotificationAction>& actions) {
|
||||
const std::vector<brightray::NotificationAction>& actions) {
|
||||
actions_ = actions;
|
||||
}
|
||||
|
||||
@@ -179,8 +181,7 @@ void Notification::NotificationDisplayed() {
|
||||
Emit("show");
|
||||
}
|
||||
|
||||
void Notification::NotificationDestroyed() {
|
||||
}
|
||||
void Notification::NotificationDestroyed() {}
|
||||
|
||||
void Notification::NotificationClosed() {
|
||||
Emit("close");
|
||||
@@ -197,7 +198,7 @@ void Notification::Close() {
|
||||
void Notification::Show() {
|
||||
Close();
|
||||
if (presenter_) {
|
||||
notification_ = presenter_->CreateNotification(this);
|
||||
notification_ = presenter_->CreateNotification(this, base::GenerateGUID());
|
||||
if (notification_) {
|
||||
brightray::NotificationOptions options;
|
||||
options.title = title_;
|
||||
@@ -232,14 +233,12 @@ void Notification::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetProperty("subtitle", &Notification::GetSubtitle,
|
||||
&Notification::SetSubtitle)
|
||||
.SetProperty("body", &Notification::GetBody, &Notification::SetBody)
|
||||
.SetProperty("silent", &Notification::GetSilent,
|
||||
&Notification::SetSilent)
|
||||
.SetProperty("silent", &Notification::GetSilent, &Notification::SetSilent)
|
||||
.SetProperty("hasReply", &Notification::GetHasReply,
|
||||
&Notification::SetHasReply)
|
||||
.SetProperty("replyPlaceholder", &Notification::GetReplyPlaceholder,
|
||||
&Notification::SetReplyPlaceholder)
|
||||
.SetProperty("sound", &Notification::GetSound,
|
||||
&Notification::SetSound)
|
||||
.SetProperty("sound", &Notification::GetSound, &Notification::SetSound)
|
||||
.SetProperty("actions", &Notification::GetActions,
|
||||
&Notification::SetActions)
|
||||
.SetProperty("closeButtonText", &Notification::GetCloseButtonText,
|
||||
@@ -270,4 +269,4 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_notification, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_notification, Initialize)
|
||||
|
||||
@@ -5,26 +5,50 @@
|
||||
#include "atom/browser/api/atom_api_power_monitor.h"
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "base/power_monitor/power_monitor.h"
|
||||
#include "base/power_monitor/power_monitor_device_source.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
template <>
|
||||
struct Converter<ui::IdleState> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const ui::IdleState& in) {
|
||||
switch (in) {
|
||||
case ui::IDLE_STATE_ACTIVE:
|
||||
return mate::StringToV8(isolate, "active");
|
||||
case ui::IDLE_STATE_IDLE:
|
||||
return mate::StringToV8(isolate, "idle");
|
||||
case ui::IDLE_STATE_LOCKED:
|
||||
return mate::StringToV8(isolate, "locked");
|
||||
case ui::IDLE_STATE_UNKNOWN:
|
||||
default:
|
||||
return mate::StringToV8(isolate, "unknown");
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
PowerMonitor::PowerMonitor(v8::Isolate* isolate) {
|
||||
#if defined(OS_LINUX)
|
||||
SetShutdownHandler(base::Bind(&PowerMonitor::ShouldShutdown,
|
||||
base::Unretained(this)));
|
||||
SetShutdownHandler(
|
||||
base::Bind(&PowerMonitor::ShouldShutdown, base::Unretained(this)));
|
||||
#elif defined(OS_MACOSX)
|
||||
Browser::Get()->SetShutdownHandler(base::Bind(&PowerMonitor::ShouldShutdown,
|
||||
base::Unretained(this)));
|
||||
Browser::Get()->SetShutdownHandler(
|
||||
base::Bind(&PowerMonitor::ShouldShutdown, base::Unretained(this)));
|
||||
#endif
|
||||
base::PowerMonitor::Get()->AddObserver(this);
|
||||
Init(isolate);
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
InitPlatformSpecificMonitors();
|
||||
#endif
|
||||
}
|
||||
|
||||
PowerMonitor::~PowerMonitor() {
|
||||
@@ -60,6 +84,21 @@ void PowerMonitor::OnResume() {
|
||||
Emit("resume");
|
||||
}
|
||||
|
||||
void PowerMonitor::QuerySystemIdleState(v8::Isolate* isolate,
|
||||
int idle_threshold,
|
||||
const ui::IdleCallback& callback) {
|
||||
if (idle_threshold > 0) {
|
||||
ui::CalculateIdleState(idle_threshold, callback);
|
||||
} else {
|
||||
isolate->ThrowException(v8::Exception::TypeError(mate::StringToV8(
|
||||
isolate, "Invalid idle threshold, must be greater than 0")));
|
||||
}
|
||||
}
|
||||
|
||||
void PowerMonitor::QuerySystemIdleTime(const ui::IdleTimeCallback& callback) {
|
||||
ui::CalculateIdleTime(callback);
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
@@ -73,27 +112,32 @@ v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
// static
|
||||
void PowerMonitor::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
void PowerMonitor::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "PowerMonitor"));
|
||||
#if defined(OS_LINUX)
|
||||
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.MakeDestroyable()
|
||||
#if defined(OS_LINUX)
|
||||
.SetMethod("blockShutdown", &PowerMonitor::BlockShutdown)
|
||||
.SetMethod("unblockShutdown", &PowerMonitor::UnblockShutdown);
|
||||
.SetMethod("unblockShutdown", &PowerMonitor::UnblockShutdown)
|
||||
#endif
|
||||
.SetMethod("querySystemIdleState", &PowerMonitor::QuerySystemIdleState)
|
||||
.SetMethod("querySystemIdleTime", &PowerMonitor::QuerySystemIdleTime);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::PowerMonitor;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("powerMonitor", PowerMonitor::Create(isolate));
|
||||
@@ -103,4 +147,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_power_monitor, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_power_monitor, Initialize)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "atom/browser/lib/power_observer.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/base/idle/idle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -35,12 +36,43 @@ class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
|
||||
void UnblockShutdown();
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
void InitPlatformSpecificMonitors();
|
||||
#endif
|
||||
|
||||
// base::PowerObserver implementations:
|
||||
void OnPowerStateChange(bool on_battery_power) override;
|
||||
void OnSuspend() override;
|
||||
void OnResume() override;
|
||||
|
||||
private:
|
||||
void QuerySystemIdleState(v8::Isolate* isolate,
|
||||
int idle_threshold,
|
||||
const ui::IdleCallback& callback);
|
||||
void QuerySystemIdleTime(const ui::IdleTimeCallback& callback);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Static callback invoked when a message comes in to our messaging window.
|
||||
static LRESULT CALLBACK WndProcStatic(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
|
||||
// The window class of |window_|.
|
||||
ATOM atom_;
|
||||
|
||||
// The handle of the module that contains the window procedure of |window_|.
|
||||
HMODULE instance_;
|
||||
|
||||
// The window used for processing events.
|
||||
HWND window_;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PowerMonitor);
|
||||
};
|
||||
|
||||
|
||||
74
atom/browser/api/atom_api_power_monitor_mac.mm
Normal file
74
atom/browser/api/atom_api_power_monitor_mac.mm
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2013 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_power_monitor.h"
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface MacLockMonitor : NSObject {
|
||||
@private
|
||||
std::vector<atom::api::PowerMonitor*> emitters;
|
||||
}
|
||||
|
||||
- (void)addEmitter:(atom::api::PowerMonitor*)monitor_;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MacLockMonitor
|
||||
|
||||
- (id)init {
|
||||
if ((self = [super init])) {
|
||||
NSDistributedNotificationCenter* distCenter =
|
||||
[NSDistributedNotificationCenter defaultCenter];
|
||||
[distCenter addObserver:self
|
||||
selector:@selector(onScreenLocked:)
|
||||
name:@"com.apple.screenIsLocked"
|
||||
object:nil];
|
||||
[distCenter addObserver:self
|
||||
selector:@selector(onScreenUnlocked:)
|
||||
name:@"com.apple.screenIsUnlocked"
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)addEmitter:(atom::api::PowerMonitor*)monitor_ {
|
||||
self->emitters.push_back(monitor_);
|
||||
}
|
||||
|
||||
- (void)onScreenLocked:(NSNotification*)notification {
|
||||
for (auto*& emitter : self->emitters) {
|
||||
emitter->Emit("lock-screen");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onScreenUnlocked:(NSNotification*)notification {
|
||||
for (auto*& emitter : self->emitters) {
|
||||
emitter->Emit("unlock-screen");
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
static MacLockMonitor* g_lock_monitor = nil;
|
||||
|
||||
void PowerMonitor::InitPlatformSpecificMonitors() {
|
||||
if (!g_lock_monitor)
|
||||
g_lock_monitor = [[MacLockMonitor alloc] init];
|
||||
[g_lock_monitor addEmitter:this];
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
71
atom/browser/api/atom_api_power_monitor_win.cc
Normal file
71
atom/browser/api/atom_api_power_monitor_win.cc
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2013 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_power_monitor.h"
|
||||
|
||||
#include "base/win/wrapped_window_proc.h"
|
||||
#include "ui/base/win/shell.h"
|
||||
#include "ui/gfx/win/hwnd_util.h"
|
||||
#include "Wtsapi32.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const wchar_t kPowerMonitorWindowClass[] =
|
||||
L"Electron_PowerMonitorHostWindow";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace api {
|
||||
|
||||
void PowerMonitor::InitPlatformSpecificMonitors() {
|
||||
WNDCLASSEX window_class;
|
||||
base::win::InitializeWindowClass(
|
||||
kPowerMonitorWindowClass,
|
||||
&base::win::WrappedWindowProc<PowerMonitor::WndProcStatic>, 0, 0, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, &window_class);
|
||||
instance_ = window_class.hInstance;
|
||||
atom_ = RegisterClassEx(&window_class);
|
||||
|
||||
// Create an offscreen window for receiving broadcast messages for the
|
||||
// session lock and unlock events.
|
||||
window_ = CreateWindow(MAKEINTATOM(atom_), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0,
|
||||
instance_, 0);
|
||||
gfx::CheckWindowCreated(window_);
|
||||
gfx::SetWindowUserData(window_, this);
|
||||
|
||||
// Tel windows we want to be notified with session events
|
||||
WTSRegisterSessionNotification(window_, NOTIFY_FOR_THIS_SESSION);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK PowerMonitor::WndProcStatic(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
PowerMonitor* msg_wnd = reinterpret_cast<PowerMonitor*>(
|
||||
GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (msg_wnd)
|
||||
return msg_wnd->WndProc(hwnd, message, wparam, lparam);
|
||||
else
|
||||
return ::DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK PowerMonitor::WndProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
if (message == WM_WTSSESSION_CHANGE) {
|
||||
if (wparam == WTS_SESSION_LOCK) {
|
||||
Emit("lock-screen");
|
||||
} else if (wparam == WTS_SESSION_UNLOCK) {
|
||||
Emit("unlock-screen");
|
||||
}
|
||||
}
|
||||
return ::DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
@@ -6,28 +6,26 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "base/task_scheduler/post_task.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<device::PowerSaveBlocker::PowerSaveBlockerType> {
|
||||
template <>
|
||||
struct Converter<device::mojom::WakeLockType> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType* out) {
|
||||
using device::PowerSaveBlocker;
|
||||
device::mojom::WakeLockType* out) {
|
||||
std::string type;
|
||||
if (!ConvertFromV8(isolate, val, &type))
|
||||
return false;
|
||||
if (type == "prevent-app-suspension")
|
||||
*out = PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
|
||||
*out = device::mojom::WakeLockType::kPreventAppSuspension;
|
||||
else if (type == "prevent-display-sleep")
|
||||
*out = PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
|
||||
*out = device::mojom::WakeLockType::kPreventDisplaySleep;
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
@@ -42,12 +40,11 @@ namespace api {
|
||||
|
||||
PowerSaveBlocker::PowerSaveBlocker(v8::Isolate* isolate)
|
||||
: current_blocker_type_(
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
|
||||
device::mojom::WakeLockType::kPreventAppSuspension) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
PowerSaveBlocker::~PowerSaveBlocker() {
|
||||
}
|
||||
PowerSaveBlocker::~PowerSaveBlocker() {}
|
||||
|
||||
void PowerSaveBlocker::UpdatePowerSaveBlocker() {
|
||||
if (power_save_blocker_types_.empty()) {
|
||||
@@ -55,38 +52,39 @@ void PowerSaveBlocker::UpdatePowerSaveBlocker() {
|
||||
return;
|
||||
}
|
||||
|
||||
// |kPowerSaveBlockPreventAppSuspension| keeps system active, but allows
|
||||
// |WakeLockType::kPreventAppSuspension| keeps system active, but allows
|
||||
// screen to be turned off.
|
||||
// |kPowerSaveBlockPreventDisplaySleep| keeps system and screen active, has a
|
||||
// higher precedence level than |kPowerSaveBlockPreventAppSuspension|.
|
||||
// |WakeLockType::kPreventDisplaySleep| keeps system and screen active, has a
|
||||
// higher precedence level than |WakeLockType::kPreventAppSuspension|.
|
||||
//
|
||||
// Only the highest-precedence blocker type takes effect.
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType new_blocker_type =
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
|
||||
device::mojom::WakeLockType new_blocker_type =
|
||||
device::mojom::WakeLockType::kPreventAppSuspension;
|
||||
for (const auto& element : power_save_blocker_types_) {
|
||||
if (element.second ==
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep) {
|
||||
device::mojom::WakeLockType::kPreventDisplaySleep) {
|
||||
new_blocker_type =
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
|
||||
device::mojom::WakeLockType::kPreventDisplaySleep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!power_save_blocker_ || new_blocker_type != current_blocker_type_) {
|
||||
std::unique_ptr<device::PowerSaveBlocker> new_blocker(
|
||||
new device::PowerSaveBlocker(
|
||||
new_blocker_type,
|
||||
device::PowerSaveBlocker::kReasonOther,
|
||||
ATOM_PRODUCT_NAME,
|
||||
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
|
||||
BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)));
|
||||
auto new_blocker = std::make_unique<device::PowerSaveBlocker>(
|
||||
new_blocker_type, device::mojom::WakeLockReason::kOther,
|
||||
ATOM_PRODUCT_NAME, base::ThreadTaskRunnerHandle::Get(),
|
||||
// This task runner may be used by some device service
|
||||
// implementation bits to interface with dbus client code, which in
|
||||
// turn imposes some subtle thread affinity on the clients. We
|
||||
// therefore require a single-thread runner.
|
||||
base::CreateSingleThreadTaskRunnerWithTraits(
|
||||
{base::MayBlock(), base::TaskPriority::BACKGROUND}));
|
||||
power_save_blocker_.swap(new_blocker);
|
||||
current_blocker_type_ = new_blocker_type;
|
||||
}
|
||||
}
|
||||
|
||||
int PowerSaveBlocker::Start(
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType type) {
|
||||
int PowerSaveBlocker::Start(device::mojom::WakeLockType type) {
|
||||
static int count = 0;
|
||||
power_save_blocker_types_[count] = type;
|
||||
UpdatePowerSaveBlocker();
|
||||
@@ -110,7 +108,8 @@ mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
|
||||
|
||||
// static
|
||||
void PowerSaveBlocker::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "PowerSaveBlocker"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("start", &PowerSaveBlocker::Start)
|
||||
@@ -124,8 +123,10 @@ void PowerSaveBlocker::BuildPrototype(
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("powerSaveBlocker", atom::api::PowerSaveBlocker::Create(isolate));
|
||||
@@ -133,4 +134,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_power_save_blocker, Initialize);
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_power_save_blocker, Initialize);
|
||||
|
||||
@@ -33,19 +33,18 @@ class PowerSaveBlocker : public mate::TrackableObject<PowerSaveBlocker> {
|
||||
|
||||
private:
|
||||
void UpdatePowerSaveBlocker();
|
||||
int Start(device::PowerSaveBlocker::PowerSaveBlockerType type);
|
||||
int Start(device::mojom::WakeLockType type);
|
||||
bool Stop(int id);
|
||||
bool IsStarted(int id);
|
||||
|
||||
std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
|
||||
|
||||
// Currnet blocker type used by |power_save_blocker_|
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType current_blocker_type_;
|
||||
// Current blocker type used by |power_save_blocker_|
|
||||
device::mojom::WakeLockType current_blocker_type_;
|
||||
|
||||
// Map from id to the corresponding blocker type for each request.
|
||||
using PowerSaveBlockerTypeMap =
|
||||
std::map<int, device::PowerSaveBlocker::PowerSaveBlockerType>;
|
||||
PowerSaveBlockerTypeMap power_save_blocker_types_;
|
||||
using WakeLockTypeMap = std::map<int, device::mojom::WakeLockType>;
|
||||
WakeLockTypeMap power_save_blocker_types_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PowerSaveBlocker);
|
||||
};
|
||||
|
||||
@@ -33,14 +33,6 @@ namespace {
|
||||
// List of registered custom standard schemes.
|
||||
std::vector<std::string> g_standard_schemes;
|
||||
|
||||
// Clear protocol handlers in IO thread.
|
||||
void ClearJobFactoryInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter) {
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
job_factory->Clear();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::vector<std::string> GetStandardSchemes() {
|
||||
@@ -71,45 +63,40 @@ void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
atom::switches::kStandardSchemes, base::JoinString(schemes, ","));
|
||||
if (secure) {
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kSecureSchemes, base::JoinString(schemes, ","));
|
||||
atom::switches::kSecureSchemes, base::JoinString(schemes, ","));
|
||||
}
|
||||
}
|
||||
|
||||
Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: request_context_getter_(browser_context->GetRequestContext()),
|
||||
weak_factory_(this) {
|
||||
: browser_context_(browser_context), weak_factory_(this) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Protocol::~Protocol() {
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(ClearJobFactoryInIO, request_context_getter_));
|
||||
}
|
||||
Protocol::~Protocol() {}
|
||||
|
||||
void Protocol::RegisterServiceWorkerSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
atom::AtomBrowserClient::SetCustomServiceWorkerSchemes(schemes);
|
||||
}
|
||||
|
||||
void Protocol::UnregisterProtocol(
|
||||
const std::string& scheme, mate::Arguments* args) {
|
||||
void Protocol::UnregisterProtocol(const std::string& scheme,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = static_cast<URLRequestContextGetter*>(
|
||||
browser_context_->GetRequestContext());
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::UnregisterProtocolInIO,
|
||||
request_context_getter_, scheme),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
base::BindOnce(&Protocol::UnregisterProtocolInIO,
|
||||
base::RetainedRef(getter), scheme),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
}
|
||||
|
||||
// static
|
||||
Protocol::ProtocolError Protocol::UnregisterProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
auto* job_factory = request_context_getter->job_factory();
|
||||
if (!job_factory->HasProtocolHandler(scheme))
|
||||
return PROTOCOL_NOT_REGISTERED;
|
||||
job_factory->SetProtocolHandler(scheme, nullptr);
|
||||
@@ -118,43 +105,46 @@ Protocol::ProtocolError Protocol::UnregisterProtocolInIO(
|
||||
|
||||
void Protocol::IsProtocolHandled(const std::string& scheme,
|
||||
const BooleanCallback& callback) {
|
||||
auto* getter = static_cast<URLRequestContextGetter*>(
|
||||
browser_context_->GetRequestContext());
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::IsProtocolHandledInIO,
|
||||
request_context_getter_, scheme),
|
||||
base::Bind(&Protocol::IsProtocolHandledInIO, base::RetainedRef(getter),
|
||||
scheme),
|
||||
callback);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Protocol::IsProtocolHandledInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
return request_context_getter->job_factory()->IsHandledProtocol(scheme);
|
||||
}
|
||||
|
||||
void Protocol::UninterceptProtocol(
|
||||
const std::string& scheme, mate::Arguments* args) {
|
||||
void Protocol::UninterceptProtocol(const std::string& scheme,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = static_cast<URLRequestContextGetter*>(
|
||||
browser_context_->GetRequestContext());
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::UninterceptProtocolInIO,
|
||||
request_context_getter_, scheme),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
base::BindOnce(&Protocol::UninterceptProtocolInIO,
|
||||
base::RetainedRef(getter), scheme),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
}
|
||||
|
||||
// static
|
||||
Protocol::ProtocolError Protocol::UninterceptProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
return static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory())->UninterceptProtocol(scheme) ?
|
||||
PROTOCOL_OK : PROTOCOL_NOT_INTERCEPTED;
|
||||
return request_context_getter->job_factory()->UninterceptProtocol(scheme)
|
||||
? PROTOCOL_OK
|
||||
: PROTOCOL_NOT_INTERCEPTED;
|
||||
}
|
||||
|
||||
void Protocol::OnIOCompleted(
|
||||
const CompletionCallback& callback, ProtocolError error) {
|
||||
void Protocol::OnIOCompleted(const CompletionCallback& callback,
|
||||
ProtocolError error) {
|
||||
// The completion callback is optional.
|
||||
if (callback.is_null())
|
||||
return;
|
||||
@@ -172,31 +162,30 @@ void Protocol::OnIOCompleted(
|
||||
|
||||
std::string Protocol::ErrorCodeToString(ProtocolError error) {
|
||||
switch (error) {
|
||||
case PROTOCOL_FAIL: return "Failed to manipulate protocol factory";
|
||||
case PROTOCOL_REGISTERED: return "The scheme has been registered";
|
||||
case PROTOCOL_NOT_REGISTERED: return "The scheme has not been registered";
|
||||
case PROTOCOL_INTERCEPTED: return "The scheme has been intercepted";
|
||||
case PROTOCOL_NOT_INTERCEPTED: return "The scheme has not been intercepted";
|
||||
default: return "Unexpected error";
|
||||
case PROTOCOL_FAIL:
|
||||
return "Failed to manipulate protocol factory";
|
||||
case PROTOCOL_REGISTERED:
|
||||
return "The scheme has been registered";
|
||||
case PROTOCOL_NOT_REGISTERED:
|
||||
return "The scheme has not been registered";
|
||||
case PROTOCOL_INTERCEPTED:
|
||||
return "The scheme has been intercepted";
|
||||
case PROTOCOL_NOT_INTERCEPTED:
|
||||
return "The scheme has not been intercepted";
|
||||
default:
|
||||
return "Unexpected error";
|
||||
}
|
||||
}
|
||||
|
||||
AtomURLRequestJobFactory* Protocol::GetJobFactoryInIO() const {
|
||||
request_context_getter_->GetURLRequestContext(); // Force init.
|
||||
return static_cast<AtomURLRequestJobFactory*>(
|
||||
static_cast<brightray::URLRequestContextGetter*>(
|
||||
request_context_getter_.get())->job_factory());
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Protocol> Protocol::Create(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context) {
|
||||
mate::Handle<Protocol> Protocol::Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
return mate::CreateHandle(isolate, new Protocol(isolate, browser_context));
|
||||
}
|
||||
|
||||
// static
|
||||
void Protocol::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
void Protocol::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Protocol"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("registerServiceWorkerSchemes",
|
||||
@@ -232,19 +221,22 @@ void Protocol::BuildPrototype(
|
||||
|
||||
namespace {
|
||||
|
||||
void RegisterStandardSchemes(
|
||||
const std::vector<std::string>& schemes, mate::Arguments* args) {
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args) {
|
||||
if (atom::Browser::Get()->is_ready()) {
|
||||
args->ThrowError("protocol.registerStandardSchemes should be called before "
|
||||
"app is ready");
|
||||
args->ThrowError(
|
||||
"protocol.registerStandardSchemes should be called before "
|
||||
"app is ready");
|
||||
return;
|
||||
}
|
||||
|
||||
atom::api::RegisterStandardSchemes(schemes, args);
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("registerStandardSchemes", &RegisterStandardSchemes);
|
||||
@@ -253,4 +245,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_protocol, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_protocol, Initialize)
|
||||
|
||||
@@ -39,20 +39,20 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
using CompletionCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
using BooleanCallback = base::Callback<void(bool)>;
|
||||
|
||||
static mate::Handle<Protocol> Create(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
static mate::Handle<Protocol> Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Protocol();
|
||||
~Protocol() override;
|
||||
|
||||
private:
|
||||
// Possible errors.
|
||||
enum ProtocolError {
|
||||
PROTOCOL_OK, // no error
|
||||
PROTOCOL_OK, // no error
|
||||
PROTOCOL_FAIL, // operation failed, should never occur
|
||||
PROTOCOL_REGISTERED,
|
||||
PROTOCOL_NOT_REGISTERED,
|
||||
@@ -62,14 +62,13 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
|
||||
// The protocol handler that will create a protocol handler for certain
|
||||
// request job.
|
||||
template<typename RequestJob>
|
||||
template <typename RequestJob>
|
||||
class CustomProtocolHandler
|
||||
: public net::URLRequestJobFactory::ProtocolHandler {
|
||||
public:
|
||||
CustomProtocolHandler(
|
||||
v8::Isolate* isolate,
|
||||
net::URLRequestContextGetter* request_context,
|
||||
const Handler& handler)
|
||||
CustomProtocolHandler(v8::Isolate* isolate,
|
||||
net::URLRequestContextGetter* request_context,
|
||||
const Handler& handler)
|
||||
: isolate_(isolate),
|
||||
request_context_(request_context),
|
||||
handler_(handler) {}
|
||||
@@ -79,13 +78,13 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
net::URLRequest* request,
|
||||
net::NetworkDelegate* network_delegate) const override {
|
||||
RequestJob* request_job = new RequestJob(request, network_delegate);
|
||||
request_job->SetHandlerInfo(isolate_, request_context_.get(), handler_);
|
||||
request_job->SetHandlerInfo(isolate_, request_context_, handler_);
|
||||
return request_job;
|
||||
}
|
||||
|
||||
private:
|
||||
v8::Isolate* isolate_;
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_;
|
||||
net::URLRequestContextGetter* request_context_;
|
||||
Protocol::Handler handler_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler);
|
||||
@@ -95,32 +94,31 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
void RegisterServiceWorkerSchemes(const std::vector<std::string>& schemes);
|
||||
|
||||
// Register the protocol with certain request job.
|
||||
template<typename RequestJob>
|
||||
template <typename RequestJob>
|
||||
void RegisterProtocol(const std::string& scheme,
|
||||
const Handler& handler,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = static_cast<URLRequestContextGetter*>(
|
||||
browser_context_->GetRequestContext());
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::RegisterProtocolInIO<RequestJob>,
|
||||
request_context_getter_, isolate(), scheme, handler),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
base::BindOnce(&Protocol::RegisterProtocolInIO<RequestJob>,
|
||||
base::RetainedRef(getter), isolate(), scheme, handler),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
}
|
||||
template<typename RequestJob>
|
||||
template <typename RequestJob>
|
||||
static ProtocolError RegisterProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
auto* job_factory = request_context_getter->job_factory();
|
||||
if (job_factory->IsHandledProtocol(scheme))
|
||||
return PROTOCOL_REGISTERED;
|
||||
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
new CustomProtocolHandler<RequestJob>(
|
||||
isolate, request_context_getter.get(), handler));
|
||||
auto protocol_handler = std::make_unique<CustomProtocolHandler<RequestJob>>(
|
||||
isolate, request_context_getter.get(), handler);
|
||||
if (job_factory->SetProtocolHandler(scheme, std::move(protocol_handler)))
|
||||
return PROTOCOL_OK;
|
||||
else
|
||||
@@ -130,46 +128,45 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
// Unregister the protocol handler that handles |scheme|.
|
||||
void UnregisterProtocol(const std::string& scheme, mate::Arguments* args);
|
||||
static ProtocolError UnregisterProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
|
||||
// Whether the protocol has handler registered.
|
||||
void IsProtocolHandled(const std::string& scheme,
|
||||
const BooleanCallback& callback);
|
||||
static bool IsProtocolHandledInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
|
||||
// Replace the protocol handler with a new one.
|
||||
template<typename RequestJob>
|
||||
template <typename RequestJob>
|
||||
void InterceptProtocol(const std::string& scheme,
|
||||
const Handler& handler,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = static_cast<URLRequestContextGetter*>(
|
||||
browser_context_->GetRequestContext());
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::InterceptProtocolInIO<RequestJob>,
|
||||
request_context_getter_, isolate(), scheme, handler),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
base::BindOnce(&Protocol::InterceptProtocolInIO<RequestJob>,
|
||||
base::RetainedRef(getter), isolate(), scheme, handler),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
}
|
||||
template<typename RequestJob>
|
||||
template <typename RequestJob>
|
||||
static ProtocolError InterceptProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
auto* job_factory = request_context_getter->job_factory();
|
||||
if (!job_factory->IsHandledProtocol(scheme))
|
||||
return PROTOCOL_NOT_REGISTERED;
|
||||
// It is possible a protocol is handled but can not be intercepted.
|
||||
if (!job_factory->HasProtocolHandler(scheme))
|
||||
return PROTOCOL_FAIL;
|
||||
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
new CustomProtocolHandler<RequestJob>(
|
||||
isolate, request_context_getter.get(), handler));
|
||||
auto protocol_handler = std::make_unique<CustomProtocolHandler<RequestJob>>(
|
||||
isolate, request_context_getter.get(), handler);
|
||||
if (!job_factory->InterceptProtocol(scheme, std::move(protocol_handler)))
|
||||
return PROTOCOL_INTERCEPTED;
|
||||
return PROTOCOL_OK;
|
||||
@@ -178,7 +175,7 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
// Restore the |scheme| to its original protocol handler.
|
||||
void UninterceptProtocol(const std::string& scheme, mate::Arguments* args);
|
||||
static ProtocolError UninterceptProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
|
||||
// Convert error code to JS exception and call the callback.
|
||||
@@ -187,13 +184,9 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
// Convert error code to string.
|
||||
std::string ErrorCodeToString(ProtocolError error);
|
||||
|
||||
AtomURLRequestJobFactory* GetJobFactoryInIO() const;
|
||||
base::WeakPtr<Protocol> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
|
||||
|
||||
base::WeakPtr<Protocol> GetWeakPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter_;
|
||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||
base::WeakPtrFactory<Protocol> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Protocol);
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace {
|
||||
|
||||
bool IsWebContents(v8::Isolate* isolate, content::RenderProcessHost* process) {
|
||||
content::WebContents* web_contents =
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->
|
||||
GetWebContentsFromProcessID(process->GetID());
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())
|
||||
->GetWebContentsFromProcessID(process->GetID());
|
||||
if (!web_contents)
|
||||
return false;
|
||||
|
||||
@@ -41,8 +41,7 @@ RenderProcessPreferences::RenderProcessPreferences(
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
RenderProcessPreferences::~RenderProcessPreferences() {
|
||||
}
|
||||
RenderProcessPreferences::~RenderProcessPreferences() {}
|
||||
|
||||
int RenderProcessPreferences::AddEntry(const base::DictionaryValue& entry) {
|
||||
return preferences_.AddEntry(entry);
|
||||
@@ -54,7 +53,8 @@ void RenderProcessPreferences::RemoveEntry(int id) {
|
||||
|
||||
// static
|
||||
void RenderProcessPreferences::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(
|
||||
mate::StringToV8(isolate, "RenderProcessPreferences"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
@@ -65,10 +65,9 @@ void RenderProcessPreferences::BuildPrototype(
|
||||
// static
|
||||
mate::Handle<RenderProcessPreferences>
|
||||
RenderProcessPreferences::ForAllWebContents(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(
|
||||
isolate,
|
||||
new RenderProcessPreferences(isolate,
|
||||
base::Bind(&IsWebContents, isolate)));
|
||||
return mate::CreateHandle(isolate,
|
||||
new RenderProcessPreferences(
|
||||
isolate, base::Bind(&IsWebContents, isolate)));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -77,8 +76,10 @@ RenderProcessPreferences::ForAllWebContents(v8::Isolate* isolate) {
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
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("forAllWebContents",
|
||||
&atom::api::RenderProcessPreferences::ForAllWebContents);
|
||||
@@ -86,5 +87,5 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_render_process_preferences,
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_render_process_preferences,
|
||||
Initialize)
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace api {
|
||||
class RenderProcessPreferences
|
||||
: public mate::Wrappable<RenderProcessPreferences> {
|
||||
public:
|
||||
static mate::Handle<RenderProcessPreferences>
|
||||
ForAllWebContents(v8::Isolate* isolate);
|
||||
static mate::Handle<RenderProcessPreferences> ForAllWebContents(
|
||||
v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_browser_window.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "base/bind.h"
|
||||
@@ -16,6 +17,10 @@
|
||||
#include "ui/display/screen.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/display/win/screen_win.h"
|
||||
#endif
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
@@ -25,9 +30,9 @@ namespace api {
|
||||
namespace {
|
||||
|
||||
// Find an item in container according to its ID.
|
||||
template<class T>
|
||||
template <class T>
|
||||
typename T::iterator FindById(T* container, int id) {
|
||||
auto predicate = [id] (const typename T::value_type& item) -> bool {
|
||||
auto predicate = [id](const typename T::value_type& item) -> bool {
|
||||
return item.id() == id;
|
||||
};
|
||||
return std::find_if(container->begin(), container->end(), predicate);
|
||||
@@ -79,6 +84,22 @@ display::Display Screen::GetDisplayMatching(const gfx::Rect& match_rect) {
|
||||
return screen_->GetDisplayMatching(match_rect);
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
static gfx::Rect ScreenToDIPRect(atom::NativeWindow* window,
|
||||
const gfx::Rect& rect) {
|
||||
HWND hwnd = window ? window->GetAcceleratedWidget() : nullptr;
|
||||
return display::win::ScreenWin::ScreenToDIPRect(hwnd, rect);
|
||||
}
|
||||
|
||||
static gfx::Rect DIPToScreenRect(atom::NativeWindow* window,
|
||||
const gfx::Rect& rect) {
|
||||
HWND hwnd = window ? window->GetAcceleratedWidget() : nullptr;
|
||||
return display::win::ScreenWin::DIPToScreenRect(hwnd, rect);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Screen::OnDisplayAdded(const display::Display& new_display) {
|
||||
Emit("display-added", new_display);
|
||||
}
|
||||
@@ -96,15 +117,14 @@ void Screen::OnDisplayMetricsChanged(const display::Display& display,
|
||||
v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate,
|
||||
"Cannot require \"screen\" module before app is ready")));
|
||||
isolate, "Cannot require \"screen\" module before app is ready")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
display::Screen* screen = display::Screen::GetScreen();
|
||||
if (!screen) {
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate, "Failed to get screen information")));
|
||||
isolate->ThrowException(v8::Exception::Error(
|
||||
mate::StringToV8(isolate, "Failed to get screen information")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
@@ -112,16 +132,19 @@ v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
// static
|
||||
void Screen::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
void Screen::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Screen"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint)
|
||||
.SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay)
|
||||
.SetMethod("getAllDisplays", &Screen::GetAllDisplays)
|
||||
.SetMethod("getDisplayNearestPoint", &Screen::GetDisplayNearestPoint)
|
||||
#if defined(OS_MACOSX)
|
||||
.SetMethod("getMenuBarHeight", &Screen::getMenuBarHeight)
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("screenToDipPoint", &display::win::ScreenWin::ScreenToDIPPoint)
|
||||
.SetMethod("dipToScreenPoint", &display::win::ScreenWin::DIPToScreenPoint)
|
||||
.SetMethod("screenToDipRect", &ScreenToDIPRect)
|
||||
.SetMethod("dipToScreenRect", &DIPToScreenRect)
|
||||
#endif
|
||||
.SetMethod("getDisplayMatching", &Screen::GetDisplayMatching);
|
||||
}
|
||||
@@ -134,8 +157,10 @@ namespace {
|
||||
|
||||
using atom::api::Screen;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("screen", Screen::Create(isolate));
|
||||
@@ -144,4 +169,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_screen, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_screen, Initialize)
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace gfx {
|
||||
class Point;
|
||||
class Rect;
|
||||
class Screen;
|
||||
}
|
||||
} // namespace gfx
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -40,10 +40,6 @@ class Screen : public mate::EventEmitter<Screen>,
|
||||
display::Display GetDisplayNearestPoint(const gfx::Point& point);
|
||||
display::Display GetDisplayMatching(const gfx::Rect& match_rect);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
int getMenuBarHeight();
|
||||
#endif
|
||||
|
||||
// display::DisplayObserver:
|
||||
void OnDisplayAdded(const display::Display& new_display) override;
|
||||
void OnDisplayRemoved(const display::Display& old_display) override;
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "atom/browser/api/atom_api_screen.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
//TODO(codebytere): deprecated; remove in 3.0
|
||||
int Screen::getMenuBarHeight() {
|
||||
return [[NSApp mainMenu] menuBarHeight];
|
||||
}
|
||||
|
||||
}// namespace api
|
||||
|
||||
}// namespace atom
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_cookies.h"
|
||||
#include "atom/browser/api/atom_api_download_item.h"
|
||||
#include "atom/browser/api/atom_api_net_log.h"
|
||||
#include "atom/browser/api/atom_api_protocol.h"
|
||||
#include "atom/browser/api/atom_api_web_request.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
@@ -30,12 +31,15 @@
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "brightray/browser/media/media_device_id_salt.h"
|
||||
#include "brightray/browser/net/devtools_network_conditions.h"
|
||||
#include "brightray/browser/net/devtools_network_controller_handle.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
#include "components/download/public/common/download_danger_type.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/prefs/value_map_pref_store.h"
|
||||
#include "components/proxy_config/proxy_config_dictionary.h"
|
||||
#include "components/proxy_config/proxy_config_pref_names.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/download_item_utils.h"
|
||||
#include "content/public/browser/download_manager_delegate.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
@@ -45,10 +49,13 @@
|
||||
#include "net/dns/host_cache.h"
|
||||
#include "net/http/http_auth_handler_factory.h"
|
||||
#include "net/http/http_auth_preferences.h"
|
||||
#include "net/proxy/proxy_config_service_fixed.h"
|
||||
#include "net/http/http_cache.h"
|
||||
#include "net/http/http_transaction_factory.h"
|
||||
#include "net/url_request/static_http_user_agent_settings.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
#include "services/network/throttling/network_conditions.h"
|
||||
#include "services/network/throttling/throttling_controller.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
using atom::api::Cookies;
|
||||
@@ -92,6 +99,8 @@ uint32_t GetStorageMask(const std::vector<std::string>& storage_types) {
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL;
|
||||
else if (type == "serviceworkers")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
|
||||
else if (type == "cachestorage")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE;
|
||||
}
|
||||
return storage_mask;
|
||||
}
|
||||
@@ -135,7 +144,7 @@ void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<ClearStorageDataOptions> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
@@ -174,37 +183,6 @@ struct Converter<ClearAuthCacheOptions> {
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<net::ProxyConfig> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
net::ProxyConfig* out) {
|
||||
std::string proxy_rules, proxy_bypass_rules;
|
||||
GURL pac_url;
|
||||
mate::Dictionary options;
|
||||
// Fallback to previous API when passed String.
|
||||
// https://git.io/vuhjj
|
||||
if (ConvertFromV8(isolate, val, &proxy_rules)) {
|
||||
pac_url = GURL(proxy_rules); // Assume it is PAC script if it is URL.
|
||||
} else if (ConvertFromV8(isolate, val, &options)) {
|
||||
options.Get("pacScript", &pac_url);
|
||||
options.Get("proxyRules", &proxy_rules);
|
||||
options.Get("proxyBypassRules", &proxy_bypass_rules);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// pacScript takes precedence over proxyRules.
|
||||
if (!pac_url.is_empty() && pac_url.is_valid()) {
|
||||
out->set_pac_url(pac_url);
|
||||
} else {
|
||||
out->proxy_rules().ParseFromString(proxy_rules);
|
||||
out->proxy_rules().bypass_rules.ParseFromString(proxy_bypass_rules);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<atom::VerifyRequestParams> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
atom::VerifyRequestParams val) {
|
||||
@@ -234,10 +212,10 @@ std::map<uint32_t, v8::Global<v8::Object>> g_sessions;
|
||||
void RunCallbackInUI(const base::Callback<void()>& callback) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
|
||||
}
|
||||
template<typename ...T>
|
||||
template <typename... T>
|
||||
void RunCallbackInUI(const base::Callback<void(T...)>& callback, T... result) {
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE, base::Bind(callback, result...));
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::BindOnce(callback, result...));
|
||||
}
|
||||
|
||||
// Callback of HttpCache::GetBackend.
|
||||
@@ -249,8 +227,8 @@ void OnGetBackend(disk_cache::Backend** backend_ptr,
|
||||
RunCallbackInUI(callback, result);
|
||||
} else if (backend_ptr && *backend_ptr) {
|
||||
if (action == Session::CacheAction::CLEAR) {
|
||||
(*backend_ptr)->DoomAllEntries(base::Bind(&RunCallbackInUI<int>,
|
||||
callback));
|
||||
(*backend_ptr)
|
||||
->DoomAllEntries(base::Bind(&RunCallbackInUI<int>, callback));
|
||||
} else if (action == Session::CacheAction::STATS) {
|
||||
base::StringPairs stats;
|
||||
(*backend_ptr)->GetStats(&stats);
|
||||
@@ -272,14 +250,14 @@ void DoCacheActionInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
Session::CacheAction action,
|
||||
const net::CompletionCallback& callback) {
|
||||
auto request_context = context_getter->GetURLRequestContext();
|
||||
auto http_cache = request_context->http_transaction_factory()->GetCache();
|
||||
auto* request_context = context_getter->GetURLRequestContext();
|
||||
auto* http_cache = request_context->http_transaction_factory()->GetCache();
|
||||
if (!http_cache)
|
||||
RunCallbackInUI<int>(callback, net::ERR_FAILED);
|
||||
|
||||
// Call GetBackend and make the backend's ptr accessable in OnGetBackend.
|
||||
using BackendPtr = disk_cache::Backend*;
|
||||
auto* backend_ptr = new BackendPtr(nullptr);
|
||||
auto** backend_ptr = new BackendPtr(nullptr);
|
||||
net::CompletionCallback on_get_backend =
|
||||
base::Bind(&OnGetBackend, base::Owned(backend_ptr), action, callback);
|
||||
int rv = http_cache->GetBackend(backend_ptr, on_get_backend);
|
||||
@@ -287,30 +265,19 @@ void DoCacheActionInIO(
|
||||
on_get_backend.Run(net::OK);
|
||||
}
|
||||
|
||||
void SetProxyInIO(net::URLRequestContextGetter* getter,
|
||||
const net::ProxyConfig& config,
|
||||
const base::Closure& callback) {
|
||||
auto proxy_service = getter->GetURLRequestContext()->proxy_service();
|
||||
proxy_service->ResetConfigService(base::WrapUnique(
|
||||
new net::ProxyConfigServiceFixed(config)));
|
||||
// Refetches and applies the new pac script if provided.
|
||||
proxy_service->ForceReloadProxyConfig();
|
||||
RunCallbackInUI(callback);
|
||||
}
|
||||
|
||||
void SetCertVerifyProcInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
const AtomCertVerifier::VerifyProc& proc) {
|
||||
auto request_context = context_getter->GetURLRequestContext();
|
||||
static_cast<AtomCertVerifier*>(request_context->cert_verifier())->
|
||||
SetVerifyProc(proc);
|
||||
auto* request_context = context_getter->GetURLRequestContext();
|
||||
static_cast<AtomCertVerifier*>(request_context->cert_verifier())
|
||||
->SetVerifyProc(proc);
|
||||
}
|
||||
|
||||
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();
|
||||
auto* request_context = context_getter->GetURLRequestContext();
|
||||
auto* cache = request_context->host_resolver()->GetHostCache();
|
||||
if (cache) {
|
||||
cache->clear();
|
||||
DCHECK_EQ(0u, cache->size());
|
||||
@@ -323,12 +290,12 @@ void ClearAuthCacheInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
const ClearAuthCacheOptions& options,
|
||||
const base::Closure& callback) {
|
||||
auto request_context = context_getter->GetURLRequestContext();
|
||||
auto network_session =
|
||||
auto* request_context = context_getter->GetURLRequestContext();
|
||||
auto* network_session =
|
||||
request_context->http_transaction_factory()->GetSession();
|
||||
if (network_session) {
|
||||
if (options.type == "password") {
|
||||
auto auth_cache = network_session->http_auth_cache();
|
||||
auto* auth_cache = network_session->http_auth_cache();
|
||||
if (!options.origin.is_empty()) {
|
||||
auth_cache->Remove(
|
||||
options.origin, options.realm, options.auth_scheme,
|
||||
@@ -337,7 +304,7 @@ void ClearAuthCacheInIO(
|
||||
auth_cache->ClearEntriesAddedWithin(base::TimeDelta::Max());
|
||||
}
|
||||
} else if (options.type == "clientCertificate") {
|
||||
auto client_auth_cache = network_session->ssl_client_auth_cache();
|
||||
auto* client_auth_cache = network_session->ssl_client_auth_cache();
|
||||
client_auth_cache->Remove(net::HostPortPair::FromURL(options.origin));
|
||||
}
|
||||
network_session->CloseAllConnections();
|
||||
@@ -349,13 +316,13 @@ void ClearAuthCacheInIO(
|
||||
void AllowNTLMCredentialsForDomainsInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
const std::string& domains) {
|
||||
auto request_context = context_getter->GetURLRequestContext();
|
||||
auto auth_handler = request_context->http_auth_handler_factory();
|
||||
auto* request_context = context_getter->GetURLRequestContext();
|
||||
auto* auth_handler = request_context->http_auth_handler_factory();
|
||||
if (auth_handler) {
|
||||
auto auth_preferences = const_cast<net::HttpAuthPreferences*>(
|
||||
auto* auth_preferences = const_cast<net::HttpAuthPreferences*>(
|
||||
auth_handler->http_auth_preferences());
|
||||
if (auth_preferences)
|
||||
auth_preferences->set_server_whitelist(domains);
|
||||
auth_preferences->SetServerWhitelist(domains);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,15 +345,14 @@ void DownloadIdCallback(content::DownloadManager* download_manager,
|
||||
base::GenerateGUID(), id, path, path, url_chain, GURL(), GURL(), GURL(),
|
||||
GURL(), mime_type, mime_type, start_time, base::Time(), etag,
|
||||
last_modified, offset, length, std::string(),
|
||||
content::DownloadItem::INTERRUPTED,
|
||||
content::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||
content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT, false,
|
||||
base::Time(), false,
|
||||
std::vector<content::DownloadItem::ReceivedSlice>());
|
||||
download::DownloadItem::INTERRUPTED,
|
||||
download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||
download::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT, false, base::Time(),
|
||||
false, std::vector<download::DownloadItem::ReceivedSlice>());
|
||||
}
|
||||
|
||||
void SetDevToolsNetworkEmulationClientIdInIO(
|
||||
brightray::URLRequestContextGetter* url_request_context_getter,
|
||||
net::URLRequestContextGetter* url_request_context_getter,
|
||||
const std::string& client_id) {
|
||||
if (!url_request_context_getter)
|
||||
return;
|
||||
@@ -397,14 +363,31 @@ void SetDevToolsNetworkEmulationClientIdInIO(
|
||||
network_delegate->SetDevToolsNetworkEmulationClientId(client_id);
|
||||
}
|
||||
|
||||
void DestroyGlobalHandle(v8::Isolate* isolate,
|
||||
const v8::Global<v8::Value>& global_handle) {
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
if (!global_handle.IsEmpty()) {
|
||||
v8::Local<v8::Value> local_handle = global_handle.Get(isolate);
|
||||
if (local_handle->IsObject()) {
|
||||
v8::Local<v8::Object> object = local_handle->ToObject();
|
||||
void* ptr = object->GetAlignedPointerFromInternalField(0);
|
||||
if (!ptr)
|
||||
return;
|
||||
delete static_cast<mate::WrappableBase*>(ptr);
|
||||
object->SetAlignedPointerInInternalField(0, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: devtools_network_emulation_client_id_(base::GenerateGUID()),
|
||||
browser_context_(browser_context) {
|
||||
// Observe DownloadManager to get download notifications.
|
||||
content::BrowserContext::GetDownloadManager(browser_context)->
|
||||
AddObserver(this);
|
||||
content::BrowserContext::GetDownloadManager(browser_context)
|
||||
->AddObserver(this);
|
||||
|
||||
new SessionPreferences(browser_context);
|
||||
|
||||
@@ -413,22 +396,28 @@ Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
}
|
||||
|
||||
Session::~Session() {
|
||||
content::BrowserContext::GetDownloadManager(browser_context())->
|
||||
RemoveObserver(this);
|
||||
content::BrowserContext::GetDownloadManager(browser_context())
|
||||
->RemoveObserver(this);
|
||||
DestroyGlobalHandle(isolate(), cookies_);
|
||||
DestroyGlobalHandle(isolate(), web_request_);
|
||||
DestroyGlobalHandle(isolate(), protocol_);
|
||||
DestroyGlobalHandle(isolate(), net_log_);
|
||||
g_sessions.erase(weak_map_id());
|
||||
}
|
||||
|
||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||
content::DownloadItem* item) {
|
||||
download::DownloadItem* item) {
|
||||
if (item->IsSavePackageDownload())
|
||||
return;
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto handle = DownloadItem::Create(isolate(), item);
|
||||
if (item->GetState() == content::DownloadItem::INTERRUPTED)
|
||||
if (item->GetState() == download::DownloadItem::INTERRUPTED)
|
||||
handle->SetSavePath(item->GetTargetFilePath());
|
||||
bool prevent_default = Emit("will-download", handle, item->GetWebContents());
|
||||
content::WebContents* web_contents =
|
||||
content::DownloadItemUtils::GetWebContents(item);
|
||||
bool prevent_default = Emit("will-download", handle, web_contents);
|
||||
if (prevent_default) {
|
||||
item->Cancel(true);
|
||||
item->Remove();
|
||||
@@ -441,13 +430,13 @@ void Session::ResolveProxy(
|
||||
browser_context_->GetResolveProxyHelper()->ResolveProxy(url, callback);
|
||||
}
|
||||
|
||||
template<Session::CacheAction action>
|
||||
template <Session::CacheAction action>
|
||||
void Session::DoCacheAction(const net::CompletionCallback& callback) {
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&DoCacheActionInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
action,
|
||||
callback));
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&DoCacheActionInIO,
|
||||
WrapRefCounted(browser_context_->GetRequestContext()),
|
||||
action, callback));
|
||||
}
|
||||
|
||||
void Session::ClearStorageData(mate::Arguments* args) {
|
||||
@@ -457,7 +446,7 @@ void Session::ClearStorageData(mate::Arguments* args) {
|
||||
args->GetNext(&options);
|
||||
args->GetNext(&callback);
|
||||
|
||||
auto storage_partition =
|
||||
auto* storage_partition =
|
||||
content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
|
||||
if (options.storage_types & StoragePartition::REMOVE_DATA_MASK_COOKIES) {
|
||||
// Reset media device id salt when cookies are cleared.
|
||||
@@ -466,66 +455,83 @@ void Session::ClearStorageData(mate::Arguments* args) {
|
||||
}
|
||||
storage_partition->ClearData(
|
||||
options.storage_types, options.quota_types, options.origin,
|
||||
content::StoragePartition::OriginMatcherFunction(),
|
||||
base::Time(), base::Time::Max(),
|
||||
base::Bind(&OnClearStorageDataDone, callback));
|
||||
content::StoragePartition::OriginMatcherFunction(), base::Time(),
|
||||
base::Time::Max(), base::Bind(&OnClearStorageDataDone, callback));
|
||||
}
|
||||
|
||||
void Session::FlushStorageData() {
|
||||
auto storage_partition =
|
||||
auto* storage_partition =
|
||||
content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
|
||||
storage_partition->Flush();
|
||||
}
|
||||
|
||||
void Session::SetProxy(const net::ProxyConfig& config,
|
||||
void Session::SetProxy(const mate::Dictionary& options,
|
||||
const base::Closure& callback) {
|
||||
auto getter = browser_context_->GetRequestContext();
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&SetProxyInIO, base::Unretained(getter), config, callback));
|
||||
if (!browser_context_->in_memory_pref_store()) {
|
||||
callback.Run();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string proxy_rules, bypass_list, pac_url;
|
||||
|
||||
options.Get("pacScript", &pac_url);
|
||||
options.Get("proxyRules", &proxy_rules);
|
||||
options.Get("proxyBypassRules", &bypass_list);
|
||||
|
||||
// pacScript takes precedence over proxyRules.
|
||||
if (!pac_url.empty()) {
|
||||
browser_context_->in_memory_pref_store()->SetValue(
|
||||
proxy_config::prefs::kProxy,
|
||||
ProxyConfigDictionary::CreatePacScript(pac_url,
|
||||
true /* pac_mandatory */),
|
||||
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
|
||||
} else {
|
||||
browser_context_->in_memory_pref_store()->SetValue(
|
||||
proxy_config::prefs::kProxy,
|
||||
ProxyConfigDictionary::CreateFixedServers(proxy_rules, bypass_list),
|
||||
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
|
||||
}
|
||||
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
|
||||
}
|
||||
|
||||
void Session::SetDownloadPath(const base::FilePath& path) {
|
||||
browser_context_->prefs()->SetFilePath(
|
||||
prefs::kDownloadDefaultDirectory, path);
|
||||
browser_context_->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
|
||||
path);
|
||||
}
|
||||
|
||||
void Session::EnableNetworkEmulation(const mate::Dictionary& options) {
|
||||
std::unique_ptr<brightray::DevToolsNetworkConditions> conditions;
|
||||
std::unique_ptr<network::NetworkConditions> conditions;
|
||||
bool offline = false;
|
||||
double latency = 0.0, download_throughput = 0.0, upload_throughput = 0.0;
|
||||
if (options.Get("offline", &offline) && offline) {
|
||||
conditions.reset(new brightray::DevToolsNetworkConditions(offline));
|
||||
conditions.reset(new network::NetworkConditions(offline));
|
||||
} else {
|
||||
options.Get("latency", &latency);
|
||||
options.Get("downloadThroughput", &download_throughput);
|
||||
options.Get("uploadThroughput", &upload_throughput);
|
||||
conditions.reset(
|
||||
new brightray::DevToolsNetworkConditions(false,
|
||||
latency,
|
||||
download_throughput,
|
||||
upload_throughput));
|
||||
conditions.reset(new network::NetworkConditions(
|
||||
false, latency, download_throughput, upload_throughput));
|
||||
}
|
||||
|
||||
browser_context_->network_controller_handle()->SetNetworkState(
|
||||
network::ThrottlingController::SetConditions(
|
||||
devtools_network_emulation_client_id_, std::move(conditions));
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(
|
||||
&SetDevToolsNetworkEmulationClientIdInIO,
|
||||
base::RetainedRef(browser_context_->url_request_context_getter()),
|
||||
devtools_network_emulation_client_id_));
|
||||
base::BindOnce(&SetDevToolsNetworkEmulationClientIdInIO,
|
||||
base::RetainedRef(browser_context_->GetRequestContext()),
|
||||
devtools_network_emulation_client_id_));
|
||||
}
|
||||
|
||||
void Session::DisableNetworkEmulation() {
|
||||
std::unique_ptr<brightray::DevToolsNetworkConditions> conditions;
|
||||
browser_context_->network_controller_handle()->SetNetworkState(
|
||||
auto conditions = std::make_unique<network::NetworkConditions>();
|
||||
network::ThrottlingController::SetConditions(
|
||||
devtools_network_emulation_client_id_, std::move(conditions));
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(
|
||||
&SetDevToolsNetworkEmulationClientIdInIO,
|
||||
base::RetainedRef(browser_context_->url_request_context_getter()),
|
||||
std::string()));
|
||||
base::BindOnce(&SetDevToolsNetworkEmulationClientIdInIO,
|
||||
base::RetainedRef(browser_context_->GetRequestContext()),
|
||||
std::string()));
|
||||
}
|
||||
|
||||
void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
|
||||
@@ -536,10 +542,11 @@ void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
|
||||
return;
|
||||
}
|
||||
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&SetCertVerifyProcInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
proc));
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&SetCertVerifyProcInIO,
|
||||
WrapRefCounted(browser_context_->GetRequestContext()),
|
||||
proc));
|
||||
}
|
||||
|
||||
void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
||||
@@ -549,7 +556,7 @@ void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
||||
args->ThrowError("Must pass null or function");
|
||||
return;
|
||||
}
|
||||
auto permission_manager = static_cast<AtomPermissionManager*>(
|
||||
auto* permission_manager = static_cast<AtomPermissionManager*>(
|
||||
browser_context()->GetPermissionManager());
|
||||
permission_manager->SetPermissionRequestHandler(handler);
|
||||
}
|
||||
@@ -558,10 +565,11 @@ 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));
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&ClearHostResolverCacheInIO,
|
||||
WrapRefCounted(browser_context_->GetRequestContext()),
|
||||
callback));
|
||||
}
|
||||
|
||||
void Session::ClearAuthCache(mate::Arguments* args) {
|
||||
@@ -575,16 +583,17 @@ void Session::ClearAuthCache(mate::Arguments* args) {
|
||||
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&ClearAuthCacheInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
options, callback));
|
||||
base::BindOnce(&ClearAuthCacheInIO,
|
||||
WrapRefCounted(browser_context_->GetRequestContext()),
|
||||
options, callback));
|
||||
}
|
||||
|
||||
void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AllowNTLMCredentialsForDomainsInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
domains));
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&AllowNTLMCredentialsForDomainsInIO,
|
||||
WrapRefCounted(browser_context_->GetRequestContext()),
|
||||
domains));
|
||||
}
|
||||
|
||||
void Session::SetUserAgent(const std::string& user_agent,
|
||||
@@ -594,30 +603,27 @@ void Session::SetUserAgent(const std::string& user_agent,
|
||||
std::string accept_lang = g_browser_process->GetApplicationLocale();
|
||||
args->GetNext(&accept_lang);
|
||||
|
||||
scoped_refptr<brightray::URLRequestContextGetter> getter(
|
||||
scoped_refptr<net::URLRequestContextGetter> getter(
|
||||
browser_context_->GetRequestContext());
|
||||
getter->GetNetworkTaskRunner()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&SetUserAgentInIO, getter, accept_lang, user_agent));
|
||||
base::BindOnce(&SetUserAgentInIO, getter, accept_lang, user_agent));
|
||||
}
|
||||
|
||||
std::string Session::GetUserAgent() {
|
||||
return browser_context_->GetUserAgent();
|
||||
}
|
||||
|
||||
void Session::GetBlobData(
|
||||
const std::string& uuid,
|
||||
const AtomBlobReader::CompletionCallback& callback) {
|
||||
void Session::GetBlobData(const std::string& uuid,
|
||||
const AtomBlobReader::CompletionCallback& callback) {
|
||||
if (callback.is_null())
|
||||
return;
|
||||
|
||||
AtomBlobReader* blob_reader =
|
||||
browser_context()->GetBlobReader();
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomBlobReader::StartReading,
|
||||
base::Unretained(blob_reader),
|
||||
uuid,
|
||||
callback));
|
||||
AtomBlobReader* blob_reader = browser_context()->GetBlobReader();
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&AtomBlobReader::StartReading,
|
||||
base::Unretained(blob_reader), uuid, callback));
|
||||
}
|
||||
|
||||
void Session::CreateInterruptedDownload(const mate::Dictionary& options) {
|
||||
@@ -644,7 +650,7 @@ void Session::CreateInterruptedDownload(const mate::Dictionary& options) {
|
||||
isolate(), "Must pass an offset value less than length.")));
|
||||
return;
|
||||
}
|
||||
auto download_manager =
|
||||
auto* download_manager =
|
||||
content::BrowserContext::GetDownloadManager(browser_context());
|
||||
download_manager->GetDelegate()->GetNextId(base::Bind(
|
||||
&DownloadIdCallback, download_manager, path, url_chain, mime_type, offset,
|
||||
@@ -688,15 +694,23 @@ v8::Local<v8::Value> Session::WebRequest(v8::Isolate* isolate) {
|
||||
return v8::Local<v8::Value>::New(isolate, web_request_);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Session::NetLog(v8::Isolate* isolate) {
|
||||
if (net_log_.IsEmpty()) {
|
||||
auto handle = atom::api::NetLog::Create(isolate, browser_context());
|
||||
net_log_.Reset(isolate, handle.ToV8());
|
||||
}
|
||||
return v8::Local<v8::Value>::New(isolate, net_log_);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Session> Session::CreateFrom(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context) {
|
||||
auto existing = TrackableObject::FromWrappedClass(isolate, browser_context);
|
||||
mate::Handle<Session> Session::CreateFrom(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
auto* existing = TrackableObject::FromWrappedClass(isolate, browser_context);
|
||||
if (existing)
|
||||
return mate::CreateHandle(isolate, static_cast<Session*>(existing));
|
||||
|
||||
auto handle = mate::CreateHandle(
|
||||
isolate, new Session(isolate, browser_context));
|
||||
auto handle =
|
||||
mate::CreateHandle(isolate, new Session(isolate, browser_context));
|
||||
|
||||
// The Sessions should never be garbage collected, since the common pattern is
|
||||
// to use partition strings, instead of using the Session object directly.
|
||||
@@ -708,7 +722,8 @@ mate::Handle<Session> Session::CreateFrom(
|
||||
|
||||
// static
|
||||
mate::Handle<Session> Session::FromPartition(
|
||||
v8::Isolate* isolate, const std::string& partition,
|
||||
v8::Isolate* isolate,
|
||||
const std::string& partition,
|
||||
const base::DictionaryValue& options) {
|
||||
scoped_refptr<AtomBrowserContext> browser_context;
|
||||
if (partition.empty()) {
|
||||
@@ -738,7 +753,7 @@ void Session::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
|
||||
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
|
||||
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
|
||||
.SetMethod("_setCertificateVerifyProc", &Session::SetCertVerifyProc)
|
||||
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
|
||||
.SetMethod("setPermissionRequestHandler",
|
||||
&Session::SetPermissionRequestHandler)
|
||||
.SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
|
||||
@@ -753,6 +768,7 @@ void Session::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setPreloads", &Session::SetPreloads)
|
||||
.SetMethod("getPreloads", &Session::GetPreloads)
|
||||
.SetProperty("cookies", &Session::Cookies)
|
||||
.SetProperty("netLog", &Session::NetLog)
|
||||
.SetProperty("protocol", &Session::Protocol)
|
||||
.SetProperty("webRequest", &Session::WebRequest);
|
||||
}
|
||||
@@ -765,8 +781,8 @@ namespace {
|
||||
|
||||
using atom::api::Session;
|
||||
|
||||
v8::Local<v8::Value> FromPartition(
|
||||
const std::string& partition, mate::Arguments* args) {
|
||||
v8::Local<v8::Value> FromPartition(const std::string& partition,
|
||||
mate::Arguments* args) {
|
||||
if (!atom::Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Session can only be received when app is ready");
|
||||
return v8::Null(args->isolate());
|
||||
@@ -776,8 +792,10 @@ v8::Local<v8::Value> FromPartition(
|
||||
return Session::FromPartition(args->isolate(), partition, options).ToV8();
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("Session", Session::GetConstructor(isolate)->GetFunction());
|
||||
@@ -787,4 +805,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_session, Initialize)
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_session, Initialize)
|
||||
|
||||
@@ -25,7 +25,7 @@ class FilePath;
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
}
|
||||
} // namespace mate
|
||||
|
||||
namespace net {
|
||||
class ProxyConfig;
|
||||
@@ -37,8 +37,8 @@ class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class Session: public mate::TrackableObject<Session>,
|
||||
public content::DownloadManager::Observer {
|
||||
class Session : public mate::TrackableObject<Session>,
|
||||
public content::DownloadManager::Observer {
|
||||
public:
|
||||
enum class CacheAction {
|
||||
CLEAR,
|
||||
@@ -46,12 +46,13 @@ class Session: public mate::TrackableObject<Session>,
|
||||
};
|
||||
|
||||
// Gets or creates Session from the |browser_context|.
|
||||
static mate::Handle<Session> CreateFrom(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
static mate::Handle<Session> CreateFrom(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context);
|
||||
|
||||
// Gets the Session of |partition|.
|
||||
static mate::Handle<Session> FromPartition(
|
||||
v8::Isolate* isolate, const std::string& partition,
|
||||
v8::Isolate* isolate,
|
||||
const std::string& partition,
|
||||
const base::DictionaryValue& options = base::DictionaryValue());
|
||||
|
||||
AtomBrowserContext* browser_context() const { return browser_context_.get(); }
|
||||
@@ -63,11 +64,11 @@ class Session: public mate::TrackableObject<Session>,
|
||||
// Methods.
|
||||
void ResolveProxy(const GURL& url,
|
||||
const ResolveProxyHelper::ResolveProxyCallback& callback);
|
||||
template<CacheAction action>
|
||||
template <CacheAction action>
|
||||
void DoCacheAction(const net::CompletionCallback& callback);
|
||||
void ClearStorageData(mate::Arguments* args);
|
||||
void FlushStorageData();
|
||||
void SetProxy(const net::ProxyConfig& config, const base::Closure& callback);
|
||||
void SetProxy(const mate::Dictionary& options, const base::Closure& callback);
|
||||
void SetDownloadPath(const base::FilePath& path);
|
||||
void EnableNetworkEmulation(const mate::Dictionary& options);
|
||||
void DisableNetworkEmulation();
|
||||
@@ -87,20 +88,22 @@ class Session: public mate::TrackableObject<Session>,
|
||||
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> NetLog(v8::Isolate* isolate);
|
||||
|
||||
protected:
|
||||
Session(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Session();
|
||||
~Session() override;
|
||||
|
||||
// content::DownloadManager::Observer:
|
||||
void OnDownloadCreated(content::DownloadManager* manager,
|
||||
content::DownloadItem* item) override;
|
||||
download::DownloadItem* item) override;
|
||||
|
||||
private:
|
||||
// Cached object.
|
||||
v8::Global<v8::Value> cookies_;
|
||||
v8::Global<v8::Value> protocol_;
|
||||
v8::Global<v8::Value> web_request_;
|
||||
v8::Global<v8::Value> net_log_;
|
||||
|
||||
// The X-DevTools-Emulate-Network-Conditions-Client-Id.
|
||||
std::string devtools_network_emulation_client_id_;
|
||||
|
||||
@@ -45,7 +45,8 @@ mate::Handle<SystemPreferences> SystemPreferences::Create(
|
||||
|
||||
// static
|
||||
void SystemPreferences::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "SystemPreferences"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
#if defined(OS_WIN)
|
||||
@@ -53,18 +54,23 @@ void SystemPreferences::BuildPrototype(
|
||||
.SetMethod("isAeroGlassEnabled", &SystemPreferences::IsAeroGlassEnabled)
|
||||
.SetMethod("getColor", &SystemPreferences::GetColor)
|
||||
#elif defined(OS_MACOSX)
|
||||
.SetMethod("postNotification",
|
||||
&SystemPreferences::PostNotification)
|
||||
.SetMethod("postLocalNotification",
|
||||
&SystemPreferences::PostLocalNotification)
|
||||
.SetMethod("postNotification", &SystemPreferences::PostNotification)
|
||||
.SetMethod("subscribeNotification",
|
||||
&SystemPreferences::SubscribeNotification)
|
||||
.SetMethod("unsubscribeNotification",
|
||||
&SystemPreferences::UnsubscribeNotification)
|
||||
.SetMethod("postLocalNotification",
|
||||
&SystemPreferences::PostLocalNotification)
|
||||
.SetMethod("subscribeLocalNotification",
|
||||
&SystemPreferences::SubscribeLocalNotification)
|
||||
.SetMethod("unsubscribeLocalNotification",
|
||||
&SystemPreferences::UnsubscribeLocalNotification)
|
||||
.SetMethod("postWorkspaceNotification",
|
||||
&SystemPreferences::PostWorkspaceNotification)
|
||||
.SetMethod("subscribeWorkspaceNotification",
|
||||
&SystemPreferences::SubscribeWorkspaceNotification)
|
||||
.SetMethod("unsubscribeWorkspaceNotification",
|
||||
&SystemPreferences::UnsubscribeWorkspaceNotification)
|
||||
.SetMethod("registerDefaults", &SystemPreferences::RegisterDefaults)
|
||||
.SetMethod("getUserDefault", &SystemPreferences::GetUserDefault)
|
||||
.SetMethod("setUserDefault", &SystemPreferences::SetUserDefault)
|
||||
@@ -85,8 +91,10 @@ namespace {
|
||||
|
||||
using atom::api::SystemPreferences;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("systemPreferences", SystemPreferences::Create(isolate));
|
||||
@@ -96,4 +104,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_system_preferences, Initialize);
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_system_preferences, Initialize);
|
||||
|
||||
@@ -26,12 +26,21 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
enum NotificationCenterKind {
|
||||
kNSDistributedNotificationCenter = 0,
|
||||
kNSNotificationCenter,
|
||||
kNSWorkspaceNotificationCenter,
|
||||
};
|
||||
#endif
|
||||
|
||||
class SystemPreferences : public mate::EventEmitter<SystemPreferences>
|
||||
#if defined(OS_WIN)
|
||||
, public BrowserObserver
|
||||
, public gfx::SysColorChangeListener
|
||||
,
|
||||
public BrowserObserver,
|
||||
public gfx::SysColorChangeListener
|
||||
#endif
|
||||
{
|
||||
{
|
||||
public:
|
||||
static mate::Handle<SystemPreferences> Create(v8::Isolate* isolate);
|
||||
|
||||
@@ -41,10 +50,10 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences>
|
||||
#if defined(OS_WIN)
|
||||
bool IsAeroGlassEnabled();
|
||||
|
||||
typedef HRESULT (STDAPICALLTYPE *DwmGetColorizationColor)(DWORD *, BOOL *);
|
||||
typedef HRESULT(STDAPICALLTYPE* DwmGetColorizationColor)(DWORD*, BOOL*);
|
||||
DwmGetColorizationColor dwmGetColorizationColor =
|
||||
(DwmGetColorizationColor) GetProcAddress(LoadLibraryW(L"dwmapi.dll"),
|
||||
"DwmGetColorizationColor");
|
||||
(DwmGetColorizationColor)GetProcAddress(LoadLibraryW(L"dwmapi.dll"),
|
||||
"DwmGetColorizationColor");
|
||||
|
||||
std::string GetAccentColor();
|
||||
std::string GetColor(const std::string& color, mate::Arguments* args);
|
||||
@@ -58,19 +67,24 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences>
|
||||
void OnFinishLaunching(const base::DictionaryValue& launch_info) override;
|
||||
|
||||
#elif defined(OS_MACOSX)
|
||||
using NotificationCallback = base::Callback<
|
||||
void(const std::string&, const base::DictionaryValue&)>;
|
||||
using NotificationCallback =
|
||||
base::Callback<void(const std::string&, const base::DictionaryValue&)>;
|
||||
|
||||
void PostNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info);
|
||||
void PostLocalNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info);
|
||||
int SubscribeNotification(const std::string& name,
|
||||
const NotificationCallback& callback);
|
||||
void UnsubscribeNotification(int id);
|
||||
void PostLocalNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info);
|
||||
int SubscribeLocalNotification(const std::string& name,
|
||||
const NotificationCallback& callback);
|
||||
void UnsubscribeLocalNotification(int request_id);
|
||||
void PostWorkspaceNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info);
|
||||
int SubscribeWorkspaceNotification(const std::string& name,
|
||||
const NotificationCallback& callback);
|
||||
void UnsubscribeWorkspaceNotification(int request_id);
|
||||
v8::Local<v8::Value> GetUserDefault(const std::string& name,
|
||||
const std::string& type);
|
||||
void RegisterDefaults(mate::Arguments* args);
|
||||
@@ -79,6 +93,8 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences>
|
||||
mate::Arguments* args);
|
||||
void RemoveUserDefault(const std::string& name);
|
||||
bool IsSwipeTrackingFromScrollEventsEnabled();
|
||||
|
||||
static bool IsTrustedAccessibilityClient(bool prompt);
|
||||
#endif
|
||||
bool IsDarkMode();
|
||||
bool IsInvertedColorScheme();
|
||||
@@ -90,21 +106,25 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences>
|
||||
#if defined(OS_MACOSX)
|
||||
void DoPostNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info,
|
||||
bool is_local);
|
||||
NotificationCenterKind kind);
|
||||
int DoSubscribeNotification(const std::string& name,
|
||||
const NotificationCallback& callback,
|
||||
bool is_local);
|
||||
void DoUnsubscribeNotification(int request_id, bool is_local);
|
||||
NotificationCenterKind kind);
|
||||
void DoUnsubscribeNotification(int request_id, NotificationCenterKind kind);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if defined(OS_WIN)
|
||||
// Static callback invoked when a message comes in to our messaging window.
|
||||
static LRESULT CALLBACK
|
||||
WndProcStatic(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
|
||||
static LRESULT CALLBACK WndProcStatic(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
|
||||
LRESULT CALLBACK
|
||||
WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
|
||||
LRESULT CALLBACK WndProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
|
||||
// The window class of |window_|.
|
||||
ATOM atom_;
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "atom/browser/mac/dict_util.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "base/values.h"
|
||||
#include "net/base/mac/url_conversions.h"
|
||||
@@ -28,94 +28,151 @@ std::map<int, id> g_id_map;
|
||||
|
||||
} // namespace
|
||||
|
||||
void SystemPreferences::PostNotification(const std::string& name,
|
||||
void SystemPreferences::PostNotification(
|
||||
const std::string& name,
|
||||
const base::DictionaryValue& user_info) {
|
||||
DoPostNotification(name, user_info, false);
|
||||
}
|
||||
|
||||
void SystemPreferences::PostLocalNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info) {
|
||||
DoPostNotification(name, user_info, true);
|
||||
}
|
||||
|
||||
void SystemPreferences::DoPostNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info, bool is_local) {
|
||||
NSNotificationCenter* center = is_local ?
|
||||
[NSNotificationCenter defaultCenter] :
|
||||
[NSDistributedNotificationCenter defaultCenter];
|
||||
[center
|
||||
postNotificationName:base::SysUTF8ToNSString(name)
|
||||
object:nil
|
||||
userInfo:DictionaryValueToNSDictionary(user_info)
|
||||
];
|
||||
DoPostNotification(name, user_info, kNSDistributedNotificationCenter);
|
||||
}
|
||||
|
||||
int SystemPreferences::SubscribeNotification(
|
||||
const std::string& name, const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback, false);
|
||||
const std::string& name,
|
||||
const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback,
|
||||
kNSDistributedNotificationCenter);
|
||||
}
|
||||
|
||||
void SystemPreferences::UnsubscribeNotification(int request_id) {
|
||||
DoUnsubscribeNotification(request_id, false);
|
||||
DoUnsubscribeNotification(request_id, kNSDistributedNotificationCenter);
|
||||
}
|
||||
|
||||
void SystemPreferences::PostLocalNotification(
|
||||
const std::string& name,
|
||||
const base::DictionaryValue& user_info) {
|
||||
DoPostNotification(name, user_info, kNSNotificationCenter);
|
||||
}
|
||||
|
||||
int SystemPreferences::SubscribeLocalNotification(
|
||||
const std::string& name, const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback, true);
|
||||
const std::string& name,
|
||||
const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback, kNSNotificationCenter);
|
||||
}
|
||||
|
||||
void SystemPreferences::UnsubscribeLocalNotification(int request_id) {
|
||||
DoUnsubscribeNotification(request_id, true);
|
||||
DoUnsubscribeNotification(request_id, kNSNotificationCenter);
|
||||
}
|
||||
|
||||
int SystemPreferences::DoSubscribeNotification(const std::string& name,
|
||||
const NotificationCallback& callback, bool is_local) {
|
||||
void SystemPreferences::PostWorkspaceNotification(
|
||||
const std::string& name,
|
||||
const base::DictionaryValue& user_info) {
|
||||
DoPostNotification(name, user_info, kNSWorkspaceNotificationCenter);
|
||||
}
|
||||
|
||||
int SystemPreferences::SubscribeWorkspaceNotification(
|
||||
const std::string& name,
|
||||
const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback,
|
||||
kNSWorkspaceNotificationCenter);
|
||||
}
|
||||
|
||||
void SystemPreferences::UnsubscribeWorkspaceNotification(int request_id) {
|
||||
DoUnsubscribeNotification(request_id, kNSWorkspaceNotificationCenter);
|
||||
}
|
||||
|
||||
void SystemPreferences::DoPostNotification(
|
||||
const std::string& name,
|
||||
const base::DictionaryValue& user_info,
|
||||
NotificationCenterKind kind) {
|
||||
NSNotificationCenter* center;
|
||||
switch (kind) {
|
||||
case kNSDistributedNotificationCenter:
|
||||
center = [NSDistributedNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSNotificationCenter:
|
||||
center = [NSNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSWorkspaceNotificationCenter:
|
||||
center = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[center postNotificationName:base::SysUTF8ToNSString(name)
|
||||
object:nil
|
||||
userInfo:DictionaryValueToNSDictionary(user_info)];
|
||||
}
|
||||
|
||||
int SystemPreferences::DoSubscribeNotification(
|
||||
const std::string& name,
|
||||
const NotificationCallback& callback,
|
||||
NotificationCenterKind kind) {
|
||||
int request_id = g_next_id++;
|
||||
__block NotificationCallback copied_callback = callback;
|
||||
NSNotificationCenter* center = is_local ?
|
||||
[NSNotificationCenter defaultCenter] :
|
||||
[NSDistributedNotificationCenter defaultCenter];
|
||||
NSNotificationCenter* center;
|
||||
switch (kind) {
|
||||
case kNSDistributedNotificationCenter:
|
||||
center = [NSDistributedNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSNotificationCenter:
|
||||
center = [NSNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSWorkspaceNotificationCenter:
|
||||
center = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_id_map[request_id] = [center
|
||||
addObserverForName:base::SysUTF8ToNSString(name)
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification* notification) {
|
||||
std::unique_ptr<base::DictionaryValue> user_info =
|
||||
NSDictionaryToDictionaryValue(notification.userInfo);
|
||||
if (user_info) {
|
||||
copied_callback.Run(
|
||||
base::SysNSStringToUTF8(notification.name),
|
||||
*user_info);
|
||||
} else {
|
||||
copied_callback.Run(
|
||||
base::SysNSStringToUTF8(notification.name),
|
||||
base::DictionaryValue());
|
||||
}
|
||||
}
|
||||
];
|
||||
addObserverForName:base::SysUTF8ToNSString(name)
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification* notification) {
|
||||
std::unique_ptr<base::DictionaryValue> user_info =
|
||||
NSDictionaryToDictionaryValue(notification.userInfo);
|
||||
if (user_info) {
|
||||
copied_callback.Run(
|
||||
base::SysNSStringToUTF8(notification.name), *user_info);
|
||||
} else {
|
||||
copied_callback.Run(
|
||||
base::SysNSStringToUTF8(notification.name),
|
||||
base::DictionaryValue());
|
||||
}
|
||||
}];
|
||||
return request_id;
|
||||
}
|
||||
|
||||
void SystemPreferences::DoUnsubscribeNotification(int request_id, bool is_local) {
|
||||
void SystemPreferences::DoUnsubscribeNotification(int request_id,
|
||||
NotificationCenterKind kind) {
|
||||
auto iter = g_id_map.find(request_id);
|
||||
if (iter != g_id_map.end()) {
|
||||
id observer = iter->second;
|
||||
NSNotificationCenter* center = is_local ?
|
||||
[NSNotificationCenter defaultCenter] :
|
||||
[NSDistributedNotificationCenter defaultCenter];
|
||||
NSNotificationCenter* center;
|
||||
switch (kind) {
|
||||
case kNSDistributedNotificationCenter:
|
||||
center = [NSDistributedNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSNotificationCenter:
|
||||
center = [NSNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSWorkspaceNotificationCenter:
|
||||
center = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[center removeObserver:observer];
|
||||
g_id_map.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> SystemPreferences::GetUserDefault(
|
||||
const std::string& name, const std::string& type) {
|
||||
const std::string& name,
|
||||
const std::string& type) {
|
||||
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSString* key = base::SysUTF8ToNSString(name);
|
||||
if (type == "string") {
|
||||
return mate::StringToV8(isolate(),
|
||||
base::SysNSStringToUTF8([defaults stringForKey:key]));
|
||||
return mate::StringToV8(
|
||||
isolate(), base::SysNSStringToUTF8([defaults stringForKey:key]));
|
||||
} else if (type == "boolean") {
|
||||
return v8::Boolean::New(isolate(), [defaults boolForKey:key]);
|
||||
} else if (type == "float") {
|
||||
@@ -126,7 +183,7 @@ v8::Local<v8::Value> SystemPreferences::GetUserDefault(
|
||||
return v8::Number::New(isolate(), [defaults doubleForKey:key]);
|
||||
} else if (type == "url") {
|
||||
return mate::ConvertToV8(isolate(),
|
||||
net::GURLWithNSURL([defaults URLForKey:key]));
|
||||
net::GURLWithNSURL([defaults URLForKey:key]));
|
||||
} else if (type == "array") {
|
||||
std::unique_ptr<base::ListValue> list =
|
||||
NSArrayToListValue([defaults arrayForKey:key]);
|
||||
@@ -147,7 +204,7 @@ v8::Local<v8::Value> SystemPreferences::GetUserDefault(
|
||||
void SystemPreferences::RegisterDefaults(mate::Arguments* args) {
|
||||
base::DictionaryValue value;
|
||||
|
||||
if(!args->GetNext(&value)) {
|
||||
if (!args->GetNext(&value)) {
|
||||
args->ThrowError("Invalid userDefault data provided");
|
||||
} else {
|
||||
@try {
|
||||
@@ -251,6 +308,12 @@ void SystemPreferences::SetUserDefault(const std::string& name,
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool SystemPreferences::IsTrustedAccessibilityClient(bool prompt) {
|
||||
NSDictionary* options = @{(id)kAXTrustedCheckOptionPrompt : @(prompt)};
|
||||
return AXIsProcessTrustedWithOptions((CFDictionaryRef)options);
|
||||
}
|
||||
|
||||
void SystemPreferences::RemoveUserDefault(const std::string& name) {
|
||||
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults removeObjectForKey:base::SysUTF8ToNSString(name)];
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace atom {
|
||||
namespace {
|
||||
|
||||
const wchar_t kSystemPreferencesWindowClass[] =
|
||||
L"Electron_SystemPreferencesHostWindow";
|
||||
L"Electron_SystemPreferencesHostWindow";
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -130,9 +130,8 @@ void SystemPreferences::InitializeWindow() {
|
||||
WNDCLASSEX window_class;
|
||||
base::win::InitializeWindowClass(
|
||||
kSystemPreferencesWindowClass,
|
||||
&base::win::WrappedWindowProc<SystemPreferences::WndProcStatic>,
|
||||
0, 0, 0, NULL, NULL, NULL, NULL, NULL,
|
||||
&window_class);
|
||||
&base::win::WrappedWindowProc<SystemPreferences::WndProcStatic>, 0, 0, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, &window_class);
|
||||
instance_ = window_class.hInstance;
|
||||
atom_ = RegisterClassEx(&window_class);
|
||||
|
||||
@@ -140,16 +139,16 @@ void SystemPreferences::InitializeWindow() {
|
||||
// colorization color. Create a hidden WS_POPUP window instead of an
|
||||
// HWND_MESSAGE window, because only top-level windows such as popups can
|
||||
// receive broadcast messages like "WM_DWMCOLORIZATIONCOLORCHANGED".
|
||||
window_ = CreateWindow(MAKEINTATOM(atom_),
|
||||
0, WS_POPUP, 0, 0, 0, 0, 0, 0, instance_, 0);
|
||||
window_ = CreateWindow(MAKEINTATOM(atom_), 0, WS_POPUP, 0, 0, 0, 0, 0, 0,
|
||||
instance_, 0);
|
||||
gfx::CheckWindowCreated(window_);
|
||||
gfx::SetWindowUserData(window_, this);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK SystemPreferences::WndProcStatic(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
SystemPreferences* msg_wnd = reinterpret_cast<SystemPreferences*>(
|
||||
GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (msg_wnd)
|
||||
@@ -159,11 +158,11 @@ LRESULT CALLBACK SystemPreferences::WndProcStatic(HWND hwnd,
|
||||
}
|
||||
|
||||
LRESULT CALLBACK SystemPreferences::WndProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
if (message == WM_DWMCOLORIZATIONCOLORCHANGED) {
|
||||
DWORD new_color = (DWORD) wparam;
|
||||
DWORD new_color = (DWORD)wparam;
|
||||
std::string new_color_string = hexColorDWORDToRGBA(new_color);
|
||||
if (new_color_string != current_color_) {
|
||||
Emit("accent-color-changed", hexColorDWORDToRGBA(new_color));
|
||||
|
||||
67
atom/browser/api/atom_api_text_field.cc
Normal file
67
atom/browser/api/atom_api_text_field.cc
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_text_field.h"
|
||||
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
TextField::TextField() : View(new views::Textfield()) {
|
||||
view()->set_owned_by_client();
|
||||
}
|
||||
|
||||
TextField::~TextField() {}
|
||||
|
||||
void TextField::SetText(const base::string16& new_text) {
|
||||
text_field()->SetText(new_text);
|
||||
}
|
||||
|
||||
base::string16 TextField::GetText() const {
|
||||
return text_field()->text();
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* TextField::New(mate::Arguments* args) {
|
||||
// Constructor call.
|
||||
auto* view = new TextField();
|
||||
view->InitWith(args->isolate(), args->GetThis());
|
||||
return view;
|
||||
}
|
||||
|
||||
// static
|
||||
void TextField::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "TextField"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("setText", &TextField::SetText)
|
||||
.SetMethod("getText", &TextField::GetText);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::TextField;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("TextField", mate::CreateConstructor<TextField>(
|
||||
isolate, base::Bind(&TextField::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_text_field, Initialize)
|
||||
42
atom/browser/api/atom_api_text_field.h
Normal file
42
atom/browser/api/atom_api_text_field.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_TEXT_FIELD_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_TEXT_FIELD_H_
|
||||
|
||||
#include "atom/browser/api/atom_api_view.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/views/controls/textfield/textfield.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class TextField : public View {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
void SetText(const base::string16& new_text);
|
||||
base::string16 GetText() const;
|
||||
|
||||
private:
|
||||
TextField();
|
||||
~TextField() override;
|
||||
|
||||
views::Textfield* text_field() const {
|
||||
return static_cast<views::Textfield*>(view());
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TextField);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_TEXT_FIELD_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user