mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
1558 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2cddb5bb4e | ||
|
|
b90e23306e | ||
|
|
8cc29c2e22 | ||
|
|
a3af6bd9f5 | ||
|
|
a23d8ed702 | ||
|
|
3766fb6652 | ||
|
|
a7891e584a | ||
|
|
e82b41724d | ||
|
|
6af7cfff33 | ||
|
|
057fda5352 | ||
|
|
71512ad244 | ||
|
|
edb3967a0f | ||
|
|
ade16a7823 | ||
|
|
f7bdf5d04e | ||
|
|
dcbc10ac38 | ||
|
|
feac8685f4 | ||
|
|
9ccc78c62f | ||
|
|
1d824d4645 | ||
|
|
b26428c43c | ||
|
|
815cb1b31c | ||
|
|
dcf9a395c2 | ||
|
|
2e62d81c24 | ||
|
|
13acf7a6a3 | ||
|
|
f35224b0e4 | ||
|
|
6bcfd0630c | ||
|
|
f4f0174746 | ||
|
|
37b7dda3c5 | ||
|
|
fbcbfbda6a | ||
|
|
de4be56b09 | ||
|
|
f3852c57fc | ||
|
|
2e6d08c652 | ||
|
|
bb260343de | ||
|
|
3f7b3c4bd7 | ||
|
|
95054f443f | ||
|
|
eef72647b4 | ||
|
|
33b6ab11f2 | ||
|
|
dacfb2f596 | ||
|
|
3ac6019f42 | ||
|
|
0f7af8043a | ||
|
|
14a1e673c6 | ||
|
|
802ed62d5b | ||
|
|
572fc058d3 | ||
|
|
b348cdeae8 | ||
|
|
ea2273dde5 | ||
|
|
ad3b837ad5 | ||
|
|
b56bdc83af | ||
|
|
2e7dbe6c6b | ||
|
|
309ac75284 | ||
|
|
4f5c725dde | ||
|
|
5b6397aaa6 | ||
|
|
2928fe5c43 | ||
|
|
5da4f032c3 | ||
|
|
c5e68ec165 | ||
|
|
78e0b80dc7 | ||
|
|
073d8c2177 | ||
|
|
d194a84ae4 | ||
|
|
4bca6fe672 | ||
|
|
cdf33ff3dc | ||
|
|
08b203fed1 | ||
|
|
736befe90f | ||
|
|
b6c5e9a126 | ||
|
|
4ebe54043a | ||
|
|
e6f5f60f3a | ||
|
|
48facf6343 | ||
|
|
170f2f61f9 | ||
|
|
0244a73c49 | ||
|
|
9089d55342 | ||
|
|
9e0547b98f | ||
|
|
b97db68f0c | ||
|
|
436a6d5c0f | ||
|
|
a64bdbd306 | ||
|
|
ac6aeae915 | ||
|
|
f92f851f11 | ||
|
|
99e21a2235 | ||
|
|
f7d3dc742d | ||
|
|
cf6e215a66 | ||
|
|
e4688f1c5a | ||
|
|
315daf1a10 | ||
|
|
75e81f00e2 | ||
|
|
ec71440f09 | ||
|
|
2a825310ea | ||
|
|
323edb9d53 | ||
|
|
726bab0293 | ||
|
|
b52367e3b2 | ||
|
|
9ff1f6bbde | ||
|
|
97dd680b32 | ||
|
|
8098ca3b66 | ||
|
|
8f63fdb278 | ||
|
|
c5da330cdf | ||
|
|
9e89ec041e | ||
|
|
070bbcfc3d | ||
|
|
cef9cd3cfc | ||
|
|
ed4f4b3954 | ||
|
|
cfb6069b83 | ||
|
|
caacc4580f | ||
|
|
f3b03908f9 | ||
|
|
c6ccf9f2b5 | ||
|
|
5204d6ce45 | ||
|
|
24b5abcc39 | ||
|
|
8ada7fe30b | ||
|
|
d8366115f5 | ||
|
|
e5aad9857d | ||
|
|
75a05c2814 | ||
|
|
64a36170a9 | ||
|
|
871c3fc11e | ||
|
|
6ef1a9150c | ||
|
|
222734b5f5 | ||
|
|
1f08634d62 | ||
|
|
52390120ae | ||
|
|
fb35f06114 | ||
|
|
bfafc6d5fd | ||
|
|
1f07977f09 | ||
|
|
fd23c7bf76 | ||
|
|
1944fdc962 | ||
|
|
12382f064b | ||
|
|
b942c54bea | ||
|
|
0a7dccbad8 | ||
|
|
5f862effaa | ||
|
|
d200cf2e77 | ||
|
|
eb533e04b9 | ||
|
|
58fa8add31 | ||
|
|
34afa3b8a5 | ||
|
|
17ef05672b | ||
|
|
c5fe173e47 | ||
|
|
456ea04683 | ||
|
|
0e5fc9c4e4 | ||
|
|
cf5689371a | ||
|
|
e788b9f959 | ||
|
|
d3d09ff25f | ||
|
|
2c259990da | ||
|
|
e2d60940a2 | ||
|
|
dc786996ef | ||
|
|
cc3ac9b1da | ||
|
|
431faf58ff | ||
|
|
63ae55be2b | ||
|
|
14d6a70fa8 | ||
|
|
1ff6fc6491 | ||
|
|
a376d09be5 | ||
|
|
02d7203b4f | ||
|
|
e65cc8a245 | ||
|
|
dc1eca14f0 | ||
|
|
0b7b2f5a57 | ||
|
|
6cff48112d | ||
|
|
fe0a577c8b | ||
|
|
91e93e6a5a | ||
|
|
a1ef49c26f | ||
|
|
339f4b8c31 | ||
|
|
406b0fdbcc | ||
|
|
349972368c | ||
|
|
4225524b6f | ||
|
|
aac916857d | ||
|
|
25246c6db7 | ||
|
|
800689fc81 | ||
|
|
d9fbead8ca | ||
|
|
496c741513 | ||
|
|
c392710802 | ||
|
|
b0886e2abf | ||
|
|
3d35f01bd1 | ||
|
|
d86662cb80 | ||
|
|
afa3bd2143 | ||
|
|
196cb2dda4 | ||
|
|
fc75080c28 | ||
|
|
f8d41f1f68 | ||
|
|
6ea1bacc73 | ||
|
|
6324270221 | ||
|
|
41afeb744a | ||
|
|
219693d91f | ||
|
|
25c80f314b | ||
|
|
5d505f9139 | ||
|
|
bc39964ece | ||
|
|
abea1196de | ||
|
|
1308f790ad | ||
|
|
095f304d7d | ||
|
|
5a54d90d72 | ||
|
|
003fdd2382 | ||
|
|
5b9b33f32d | ||
|
|
5ee3915c40 | ||
|
|
dcead89507 | ||
|
|
6f2f3ed1ac | ||
|
|
738c8c047e | ||
|
|
d224f5d998 | ||
|
|
f8a9f628ae | ||
|
|
6995b51f2c | ||
|
|
c989ea43f5 | ||
|
|
b0c4c79c49 | ||
|
|
eb4038d626 | ||
|
|
7562a8b662 | ||
|
|
c75a1f08fd | ||
|
|
1085c28612 | ||
|
|
eca9bffb01 | ||
|
|
b28a865436 | ||
|
|
57d682a050 | ||
|
|
8c5f26373b | ||
|
|
87f09131aa | ||
|
|
371b347ee9 | ||
|
|
ad2627b05a | ||
|
|
bb012c3db2 | ||
|
|
387dd67b60 | ||
|
|
b22eb0d65f | ||
|
|
ec46d57816 | ||
|
|
e296d4826f | ||
|
|
3cfe94c5ef | ||
|
|
7e82e12468 | ||
|
|
f81908711b | ||
|
|
2b955a5ae1 | ||
|
|
aeedd36168 | ||
|
|
e57cb713b2 | ||
|
|
a098bf30d4 | ||
|
|
f1692f3274 | ||
|
|
a39dc1b78a | ||
|
|
ead5275d63 | ||
|
|
4e8c21549b | ||
|
|
ed081c8834 | ||
|
|
f99dabbac6 | ||
|
|
707b1d1b79 | ||
|
|
026711e750 | ||
|
|
b9f569f7fb | ||
|
|
0a5f51fd03 | ||
|
|
d20e2ec349 | ||
|
|
f9417e3fcc | ||
|
|
41c352c306 | ||
|
|
1ef0f6beff | ||
|
|
c70eb81e32 | ||
|
|
38681d0a2b | ||
|
|
c5097ae483 | ||
|
|
5bb196dce3 | ||
|
|
cb47de5eca | ||
|
|
56a8e17b21 | ||
|
|
e3b23842dd | ||
|
|
12cb35ef61 | ||
|
|
2fb8839d31 | ||
|
|
6578498e31 | ||
|
|
2e1feb63e4 | ||
|
|
9e626c5fee | ||
|
|
78a89c666b | ||
|
|
6352afb07a | ||
|
|
683d8033f0 | ||
|
|
e2bb8088d4 | ||
|
|
64116e5d7c | ||
|
|
219a6b175b | ||
|
|
2a8b36c761 | ||
|
|
b853671132 | ||
|
|
2fbf560668 | ||
|
|
cd067bca37 | ||
|
|
98d4e186e3 | ||
|
|
8680a08a8d | ||
|
|
3b259b4243 | ||
|
|
25feb9232d | ||
|
|
590bde5e14 | ||
|
|
88dac36c91 | ||
|
|
7842040d9d | ||
|
|
3237c6751a | ||
|
|
7a5ec96d53 | ||
|
|
5ae80d541b | ||
|
|
25ac23ab17 | ||
|
|
a3b65ad481 | ||
|
|
9d2c9df992 | ||
|
|
7ceb8d1ab8 | ||
|
|
a609e52a14 | ||
|
|
39875c90f1 | ||
|
|
3290c6b335 | ||
|
|
0f93515ede | ||
|
|
dfc25d0ca5 | ||
|
|
db0beb6c36 | ||
|
|
7b240d82fd | ||
|
|
704433f3d6 | ||
|
|
8ae7d01d1a | ||
|
|
2bd8ef83d1 | ||
|
|
c108088110 | ||
|
|
cb7715a572 | ||
|
|
2e1e893675 | ||
|
|
3796d7a6a1 | ||
|
|
b08bc02cde | ||
|
|
04e873f78e | ||
|
|
04da9257ef | ||
|
|
cae601a682 | ||
|
|
f2aabeefd5 | ||
|
|
1d288b69e2 | ||
|
|
cac85d2a12 | ||
|
|
381f55b3cb | ||
|
|
04fa85f67f | ||
|
|
bacf6511a6 | ||
|
|
4e01ab59c1 | ||
|
|
a46040a4fa | ||
|
|
b458201874 | ||
|
|
99ea50649a | ||
|
|
9d2e23413e | ||
|
|
4b53cd9c3c | ||
|
|
ee88e0054b | ||
|
|
e77fa72d6d | ||
|
|
2fa9ca1f6d | ||
|
|
a2d1a5258b | ||
|
|
009c00cdc6 | ||
|
|
1a0fbf84f9 | ||
|
|
9ea391e03d | ||
|
|
6bcf4b1112 | ||
|
|
82bd1d98d5 | ||
|
|
de625bfb65 | ||
|
|
c751d42d1a | ||
|
|
198f5f237f | ||
|
|
dc5b27069a | ||
|
|
6a829e0179 | ||
|
|
4085ba309a | ||
|
|
975d677f55 | ||
|
|
21be9a3309 | ||
|
|
7456b9ae17 | ||
|
|
35349643af | ||
|
|
952e3bac2c | ||
|
|
d705f4cbac | ||
|
|
5d94221c61 | ||
|
|
f124732431 | ||
|
|
d944219b28 | ||
|
|
86961d0f44 | ||
|
|
3dde669ee8 | ||
|
|
ccdeb915fa | ||
|
|
5345b08d24 | ||
|
|
54d27a390b | ||
|
|
ba44dca34a | ||
|
|
61d91579df | ||
|
|
ea2e2def55 | ||
|
|
a7a06a483e | ||
|
|
388b601503 | ||
|
|
2b8b76a527 | ||
|
|
cbddbdb296 | ||
|
|
06701786c4 | ||
|
|
1c45285fe3 | ||
|
|
18c0cfa6f5 | ||
|
|
32ae3a52b8 | ||
|
|
e198b6945c | ||
|
|
f1f73eff04 | ||
|
|
9adb232d99 | ||
|
|
63bffbc460 | ||
|
|
3e128abb73 | ||
|
|
820fb3b82b | ||
|
|
03263bb5b6 | ||
|
|
b0a1e2988b | ||
|
|
571592a5a4 | ||
|
|
d1da48ff0f | ||
|
|
6c214ed386 | ||
|
|
b29f7b9acb | ||
|
|
c2f516067f | ||
|
|
58cae1d8de | ||
|
|
a9d4d9ad85 | ||
|
|
e043dabcb8 | ||
|
|
3de3fb53bd | ||
|
|
d6d85ade8e | ||
|
|
1278e8cebc | ||
|
|
de0ec9b33c | ||
|
|
3b99827540 | ||
|
|
635c909aab | ||
|
|
f894da13b0 | ||
|
|
c27633dff4 | ||
|
|
c1a02d6556 | ||
|
|
ec43dd067c | ||
|
|
f3d391e3f2 | ||
|
|
851f490168 | ||
|
|
07f99c06ea | ||
|
|
d0643250f7 | ||
|
|
f56b00718b | ||
|
|
af555bd879 | ||
|
|
b61e1fd69f | ||
|
|
c8ff67ab75 | ||
|
|
f72942bff1 | ||
|
|
36371357cd | ||
|
|
750bd9a88b | ||
|
|
5660b1e225 | ||
|
|
acfded9687 | ||
|
|
a9f4c208a0 | ||
|
|
bca7a6baa9 | ||
|
|
3cb3d8f981 | ||
|
|
9904da9a48 | ||
|
|
8d9328fbee | ||
|
|
eaa5d071ef | ||
|
|
d86f0a1686 | ||
|
|
f0566f3790 | ||
|
|
f5f790863d | ||
|
|
10386edea5 | ||
|
|
4ccc3d9fb3 | ||
|
|
77fa7ce977 | ||
|
|
2c8ab72269 | ||
|
|
df179ed28d | ||
|
|
3ec0e2f132 | ||
|
|
477ac313ab | ||
|
|
72e559458f | ||
|
|
21f0b2bd2a | ||
|
|
cc2936cfdf | ||
|
|
d20e664ea8 | ||
|
|
fee7683b86 | ||
|
|
d7e7c2b17f | ||
|
|
1afa41477d | ||
|
|
217848ca52 | ||
|
|
486b6b9096 | ||
|
|
18c49285a8 | ||
|
|
fb74f5576d | ||
|
|
4aa2b093ff | ||
|
|
446065b88c | ||
|
|
594aaec7bb | ||
|
|
07994f50f3 | ||
|
|
1c6e166af5 | ||
|
|
0b9a2f6be6 | ||
|
|
0c73140b07 | ||
|
|
02cbd24165 | ||
|
|
f4be3782a2 | ||
|
|
bb9876bd6e | ||
|
|
2bf6f28152 | ||
|
|
a7dedb3a13 | ||
|
|
4b61a4d3de | ||
|
|
285a36f9de | ||
|
|
5a1a2616aa | ||
|
|
0d1804b2a0 | ||
|
|
0b9530efd7 | ||
|
|
6bbd92368f | ||
|
|
7b8eb3e09c | ||
|
|
774b2f99f2 | ||
|
|
a7395118af | ||
|
|
3897a88082 | ||
|
|
0a61aad499 | ||
|
|
5abecadfd3 | ||
|
|
fff59271af | ||
|
|
d5a0dd39a1 | ||
|
|
ccabee764b | ||
|
|
5283b94bf9 | ||
|
|
6f6c5c07f0 | ||
|
|
3a29555772 | ||
|
|
145e40c2f6 | ||
|
|
41dea03007 | ||
|
|
3ac9858726 | ||
|
|
bbaab755e3 | ||
|
|
8fd6463ab0 | ||
|
|
92fe82a208 | ||
|
|
4ff7cf2bcc | ||
|
|
f6a6ca8a22 | ||
|
|
c9615a201c | ||
|
|
921b474919 | ||
|
|
06960704c4 | ||
|
|
f8b738e6c2 | ||
|
|
b036fdfee0 | ||
|
|
3930f17d9d | ||
|
|
9eb521fb38 | ||
|
|
27625d2665 | ||
|
|
0593696344 | ||
|
|
2cabfa5589 | ||
|
|
0134d62681 | ||
|
|
0799317ff5 | ||
|
|
686a26d948 | ||
|
|
cd5bfbfead | ||
|
|
9a7209d58e | ||
|
|
f89a045605 | ||
|
|
a353a94b70 | ||
|
|
5498a31493 | ||
|
|
6b34b97c29 | ||
|
|
6a8ee19bf0 | ||
|
|
cf690ae513 | ||
|
|
cd8b7f5219 | ||
|
|
37b18243f4 | ||
|
|
e356168c9a | ||
|
|
6f29d7211e | ||
|
|
414db313c6 | ||
|
|
63eec70350 | ||
|
|
c0d9175bc3 | ||
|
|
89965aa5db | ||
|
|
238beb72ee | ||
|
|
6c046704c7 | ||
|
|
5dc4b22d31 | ||
|
|
95ab4815de | ||
|
|
a7aed98d59 | ||
|
|
c4b68d88e9 | ||
|
|
d4368fabb9 | ||
|
|
9a5df9da41 | ||
|
|
756a338b05 | ||
|
|
e887fb69bd | ||
|
|
fb5bca8bc5 | ||
|
|
0d317a2e49 | ||
|
|
77e317c1eb | ||
|
|
db729b5b52 | ||
|
|
97b4f12112 | ||
|
|
926cabec78 | ||
|
|
621a934160 | ||
|
|
c65033a13b | ||
|
|
67f33cdb60 | ||
|
|
964c88a189 | ||
|
|
62b39d58ca | ||
|
|
3e85d7759b | ||
|
|
7445f9bdcc | ||
|
|
e2649ce7d8 | ||
|
|
71f94c7a3a | ||
|
|
41d6207376 | ||
|
|
82d17cb05d | ||
|
|
26137977cd | ||
|
|
cbffd598f9 | ||
|
|
2e35b1c855 | ||
|
|
ea6b53578f | ||
|
|
2fc46f638f | ||
|
|
a991570677 | ||
|
|
d4ba5b4638 | ||
|
|
b02c0e6f46 | ||
|
|
7916981da2 | ||
|
|
7896ee23a2 | ||
|
|
c5790e39dc | ||
|
|
8bc3dcd17a | ||
|
|
eab5376c25 | ||
|
|
56b15eadea | ||
|
|
61c31f8e21 | ||
|
|
8918770892 | ||
|
|
89e8ad4947 | ||
|
|
94988f89b0 | ||
|
|
b305020c1d | ||
|
|
782417b1fa | ||
|
|
38b14fc912 | ||
|
|
ac9e0b458d | ||
|
|
d6e3360aef | ||
|
|
1ee0efbe5c | ||
|
|
aac31159b8 | ||
|
|
0aa1c3c6c3 | ||
|
|
02a95a3eba | ||
|
|
996ddba715 | ||
|
|
88809b0e0b | ||
|
|
88959079bd | ||
|
|
0698b5f1be | ||
|
|
28c39d5151 | ||
|
|
5427ec4844 | ||
|
|
aef898ad93 | ||
|
|
c05ca68811 | ||
|
|
489d873306 | ||
|
|
3834f0c6a6 | ||
|
|
7c26ec8bd4 | ||
|
|
eb63bea87c | ||
|
|
5639faf069 | ||
|
|
090a5d9a61 | ||
|
|
622bad1cff | ||
|
|
5b260dbee3 | ||
|
|
f0ca9dff81 | ||
|
|
9382d48708 | ||
|
|
54222bdf28 | ||
|
|
2931c27395 | ||
|
|
31123f908d | ||
|
|
99a5258999 | ||
|
|
5e8059e0fa | ||
|
|
08a9af3a85 | ||
|
|
d186fd78e3 | ||
|
|
6524a33ffc | ||
|
|
21df08d536 | ||
|
|
cfd2a029ad | ||
|
|
c78567aba6 | ||
|
|
9ca684d87f | ||
|
|
128feb17cb | ||
|
|
3eb5f8d521 | ||
|
|
b266533dfc | ||
|
|
1b5b29901c | ||
|
|
468d8b7707 | ||
|
|
1da97f729e | ||
|
|
f9683ff99f | ||
|
|
a7fdd04751 | ||
|
|
5979dab13c | ||
|
|
c9739abf7f | ||
|
|
39330affda | ||
|
|
d6684c4dcd | ||
|
|
4770d2b526 | ||
|
|
2b689a21e7 | ||
|
|
b084dc29ea | ||
|
|
c4d74c48e4 | ||
|
|
436775b1e4 | ||
|
|
aa2824621a | ||
|
|
651eaec64f | ||
|
|
92577c37c8 | ||
|
|
04c68745db | ||
|
|
81f2e76e36 | ||
|
|
18fca785c4 | ||
|
|
a1066617a8 | ||
|
|
a1dfdbdde4 | ||
|
|
63a138b6de | ||
|
|
5167ccd147 | ||
|
|
cb0845fc49 | ||
|
|
11449b2e8c | ||
|
|
bee5ced8f4 | ||
|
|
bea1a0643c | ||
|
|
f111bb4107 | ||
|
|
f20ca63dd0 | ||
|
|
98e18a62e2 | ||
|
|
9624bc1403 | ||
|
|
fc1ce3eeab | ||
|
|
095d711848 | ||
|
|
a1dca8afc9 | ||
|
|
86321a2c60 | ||
|
|
2e5c92d41e | ||
|
|
f767f0f048 | ||
|
|
93ce2f7800 | ||
|
|
5d028f9163 | ||
|
|
446399c3c1 | ||
|
|
0ef6d4631d | ||
|
|
b87d86e9d5 | ||
|
|
35e000024c | ||
|
|
9e51c779e1 | ||
|
|
6f8eb282b7 | ||
|
|
301b8ec39a | ||
|
|
2986b7bc4a | ||
|
|
89feefac2c | ||
|
|
68a6b39920 | ||
|
|
eeffa42513 | ||
|
|
8b30439d7f | ||
|
|
01005688b6 | ||
|
|
00d9baa605 | ||
|
|
9e91f319c1 | ||
|
|
619bb31de2 | ||
|
|
dcb3a13361 | ||
|
|
c2663e48c1 | ||
|
|
621715e5e5 | ||
|
|
b9991f0494 | ||
|
|
c259b4294d | ||
|
|
4867475cee | ||
|
|
8822c7d87d | ||
|
|
06cfcd612d | ||
|
|
1404ea1c2c | ||
|
|
4deb7c6fa7 | ||
|
|
b9e950f5c7 | ||
|
|
134f8afbe6 | ||
|
|
50019f39e9 | ||
|
|
5f596b22c7 | ||
|
|
cbb68f6980 | ||
|
|
61576c39be | ||
|
|
9536ebc0ad | ||
|
|
723a3eda8b | ||
|
|
a5fd6507a9 | ||
|
|
dbe57c4ad4 | ||
|
|
ad5f944185 | ||
|
|
2044208fd6 | ||
|
|
2d7ceae320 | ||
|
|
0410a184ce | ||
|
|
7cfe1dd0af | ||
|
|
4de2493d89 | ||
|
|
b86dff45d7 | ||
|
|
fb8339830e | ||
|
|
ec7cae4a34 | ||
|
|
80a7835cdf | ||
|
|
50be8b65d1 | ||
|
|
174e51507d | ||
|
|
494afec01d | ||
|
|
aeefee7348 | ||
|
|
c1af62a3b3 | ||
|
|
11f8923c43 | ||
|
|
63ebc41778 | ||
|
|
1a9b4b4671 | ||
|
|
8a29604f1e | ||
|
|
483e007b69 | ||
|
|
2d8a61a775 | ||
|
|
5e62d28e50 | ||
|
|
2cf30c0d63 | ||
|
|
16253fe708 | ||
|
|
84a3fe50dc | ||
|
|
8ad50d1e35 | ||
|
|
ad638097b6 | ||
|
|
356d0520ae | ||
|
|
999b349e94 | ||
|
|
76375a83eb | ||
|
|
ea534aa564 | ||
|
|
055e49ab9c | ||
|
|
0d43e239d4 | ||
|
|
c04a0381dc | ||
|
|
5cebe65310 | ||
|
|
ab5a49b6ae | ||
|
|
7b463297c6 | ||
|
|
debdce1e66 | ||
|
|
8a2706d2f4 | ||
|
|
709dd0bf18 | ||
|
|
de78f3441e | ||
|
|
f23624755e | ||
|
|
0c265f8ed4 | ||
|
|
c1f2e30c5a | ||
|
|
3b415b2e99 | ||
|
|
bea9f78ddb | ||
|
|
95484a1b1a | ||
|
|
a0065e62fa | ||
|
|
3aab713d24 | ||
|
|
5d6f180413 | ||
|
|
a69ee76705 | ||
|
|
7971ce0dd9 | ||
|
|
4159a6a41d | ||
|
|
e49af23a7d | ||
|
|
30117816be | ||
|
|
b6ece7d16c | ||
|
|
6fda4fc45c | ||
|
|
18e1de105f | ||
|
|
133ad6e18b | ||
|
|
b84fed5cb2 | ||
|
|
a737732521 | ||
|
|
f454cb3408 | ||
|
|
d18a9eaf65 | ||
|
|
059433511c | ||
|
|
acacb3f551 | ||
|
|
0008bc5f82 | ||
|
|
a3e10aba95 | ||
|
|
73774f21b7 | ||
|
|
3c18de9c5a | ||
|
|
19a5d2ba2b | ||
|
|
16f57b219b | ||
|
|
0485069c7b | ||
|
|
e4d6aa30a1 | ||
|
|
89a26684e5 | ||
|
|
0e1c2b0fcb | ||
|
|
6eab14359c | ||
|
|
76f96bd99c | ||
|
|
48bcad87c2 | ||
|
|
712b15286c | ||
|
|
3053be345b | ||
|
|
8e834e9047 | ||
|
|
3e34760eef | ||
|
|
e0afb814aa | ||
|
|
0fd35cf768 | ||
|
|
0b86acfef4 | ||
|
|
36ee417d3b | ||
|
|
a1a07aed44 | ||
|
|
f0731be20b | ||
|
|
58278ee095 | ||
|
|
494a025fb8 | ||
|
|
ade8401b5b | ||
|
|
ef9d8fe9bd | ||
|
|
471b9980ec | ||
|
|
9c65b9a9f2 | ||
|
|
21105271a4 | ||
|
|
7e90bb47a5 | ||
|
|
ac68de6215 | ||
|
|
8e203592e2 | ||
|
|
9f18a6e65c | ||
|
|
857e1da6a3 | ||
|
|
75b010ce63 | ||
|
|
124fbdbd74 | ||
|
|
cf0cd5b50b | ||
|
|
0e9d973715 | ||
|
|
cc18670ae1 | ||
|
|
6228ce3f35 | ||
|
|
89511bb0cb | ||
|
|
11bc993344 | ||
|
|
9126ab6766 | ||
|
|
49cb675057 | ||
|
|
e8b119e636 | ||
|
|
e8bb79310c | ||
|
|
da3dbdcb9b | ||
|
|
b400edcc88 | ||
|
|
6580088574 | ||
|
|
794479519c | ||
|
|
97d468cf35 | ||
|
|
af6a3b3173 | ||
|
|
0c8160bfe3 | ||
|
|
a584acef46 | ||
|
|
691ad97abe | ||
|
|
836cd017a9 | ||
|
|
e70f8acf47 | ||
|
|
721924b749 | ||
|
|
7880d37d73 | ||
|
|
ba6bb45f70 | ||
|
|
379c3470c8 | ||
|
|
038718717c | ||
|
|
b8f09ecf4f | ||
|
|
e9a2792b55 | ||
|
|
aa3bc13ca3 | ||
|
|
ed3a2dae1b | ||
|
|
48eaee0c0e | ||
|
|
6b2848307d | ||
|
|
651a2d4399 | ||
|
|
7c48dd54e1 | ||
|
|
5968346c1e | ||
|
|
266d3b553b | ||
|
|
53ff706cd2 | ||
|
|
651b0c0f82 | ||
|
|
3f8e173452 | ||
|
|
078c924760 | ||
|
|
611614c649 | ||
|
|
dda3fcef91 | ||
|
|
92f8c105d9 | ||
|
|
4ee308fcc2 | ||
|
|
dfefa00a50 | ||
|
|
44146009ad | ||
|
|
b376c29937 | ||
|
|
c657186920 | ||
|
|
f613d8d0d0 | ||
|
|
a506df4d25 | ||
|
|
a0772dbbe9 | ||
|
|
f603e47226 | ||
|
|
4b0b875d6f | ||
|
|
d50cabddc0 | ||
|
|
cbda2a3e60 | ||
|
|
2006d64939 | ||
|
|
d9f3355dea | ||
|
|
c8263a9a18 | ||
|
|
6d2e9f5311 | ||
|
|
bb6d15ee10 | ||
|
|
56f7aceec7 | ||
|
|
933e013e7e | ||
|
|
a2b3abbf47 | ||
|
|
c61414e11b | ||
|
|
29470dd018 | ||
|
|
ed878b400e | ||
|
|
fbe4394bbd | ||
|
|
3e0d8841ea | ||
|
|
aeb774730b | ||
|
|
6d92457095 | ||
|
|
8fa3057e19 | ||
|
|
eed8f201e2 | ||
|
|
0add800240 | ||
|
|
9356843e27 | ||
|
|
02a7094529 | ||
|
|
76da80c5e9 | ||
|
|
7078ed80fa | ||
|
|
e97d3c21a3 | ||
|
|
9e266642f9 | ||
|
|
0f5bfadd2b | ||
|
|
d85c4da11b | ||
|
|
d982376fc4 | ||
|
|
d26601f695 | ||
|
|
0ec57cca32 | ||
|
|
cf5fc3f922 | ||
|
|
1f60aff73d | ||
|
|
9b19e6ee38 | ||
|
|
6bac17fb9a | ||
|
|
e759ce72b5 | ||
|
|
b44371f4bf | ||
|
|
9736dc3115 | ||
|
|
18ac4178fe | ||
|
|
2f7cceb11c | ||
|
|
002462ce7b | ||
|
|
4d305b06d1 | ||
|
|
9673cee4d7 | ||
|
|
526debb5ab | ||
|
|
fb444f646b | ||
|
|
26f76f8d41 | ||
|
|
9ae18c6194 | ||
|
|
9e425cd01e | ||
|
|
171b901c61 | ||
|
|
fbade9305c | ||
|
|
082cd9b72c | ||
|
|
e9db926b48 | ||
|
|
bdb3f4d4cb | ||
|
|
b44d5290e2 | ||
|
|
6a36deec3b | ||
|
|
6d7f179a9b | ||
|
|
61278f9ace | ||
|
|
7ffc1faf5b | ||
|
|
1c3b5835f4 | ||
|
|
1718697ef0 | ||
|
|
144a61c5a3 | ||
|
|
f7bf8c4fdc | ||
|
|
6f64ad30cb | ||
|
|
1c7d5df2fe | ||
|
|
65e6da2673 | ||
|
|
39a5c7dab9 | ||
|
|
b4cc3541a8 | ||
|
|
68c2c9825f | ||
|
|
3aad6a0c99 | ||
|
|
2556ed8744 | ||
|
|
f35536bdc5 | ||
|
|
775328d5d5 | ||
|
|
1a03e62717 | ||
|
|
31b4f61815 | ||
|
|
076e033236 | ||
|
|
2c50f14346 | ||
|
|
82e593b44f | ||
|
|
224d2ca93c | ||
|
|
0841c4291a | ||
|
|
271733fc53 | ||
|
|
a2a44621fd | ||
|
|
ad48aeeea4 | ||
|
|
83f47bc980 | ||
|
|
67a09d9fe0 | ||
|
|
189ae97732 | ||
|
|
632739ec6e | ||
|
|
88ac376382 | ||
|
|
b2559d7d28 | ||
|
|
98387e50cc | ||
|
|
93464b8100 | ||
|
|
52783bb67f | ||
|
|
c90d4abcf0 | ||
|
|
6f85d85c12 | ||
|
|
280235872b | ||
|
|
e93eaed5d0 | ||
|
|
32cff67fd4 | ||
|
|
d3f40212db | ||
|
|
11ad9e7f25 | ||
|
|
0c44d19249 | ||
|
|
7c17aeb6da | ||
|
|
8c19d3b210 | ||
|
|
9f15191280 | ||
|
|
69790bd7ed | ||
|
|
fdfa0f4a6d | ||
|
|
7f8b180f70 | ||
|
|
43ae784a40 | ||
|
|
6a4d9f8a87 | ||
|
|
e2c646a14b | ||
|
|
337db9fbb9 | ||
|
|
63267031e9 | ||
|
|
88b288502a | ||
|
|
b0fb0c6492 | ||
|
|
3a44663003 | ||
|
|
147addbce1 | ||
|
|
7549adcfce | ||
|
|
fddbde2fd5 | ||
|
|
6e5951b764 | ||
|
|
3b620b8c0c | ||
|
|
0d82fbcf37 | ||
|
|
5cd20a8e5d | ||
|
|
4ff73d8b56 | ||
|
|
f651b21cda | ||
|
|
7a73c0189f | ||
|
|
0345b62369 | ||
|
|
3a31f28f27 | ||
|
|
a5c62bb264 | ||
|
|
9bddc2cbaa | ||
|
|
43113fcfb4 | ||
|
|
6b207d65bf | ||
|
|
9d0d1c8341 | ||
|
|
82a16ee41f | ||
|
|
104f8d6057 | ||
|
|
9c9ba80978 | ||
|
|
a06a1fa262 | ||
|
|
c198828e58 | ||
|
|
cbe9768529 | ||
|
|
ce847fc3ca | ||
|
|
5cbbd6efe6 | ||
|
|
00d641aaf7 | ||
|
|
9b4e9c642a | ||
|
|
c6ae27c7c9 | ||
|
|
9ead3ad0a0 | ||
|
|
e7962c7ba2 | ||
|
|
194b14100e | ||
|
|
3dd8377218 | ||
|
|
bd34db256b | ||
|
|
6fdf40b038 | ||
|
|
988e2334f5 | ||
|
|
0e13b8dd01 | ||
|
|
ac9e6eda95 | ||
|
|
ba91bbd397 | ||
|
|
63e1b2fb46 | ||
|
|
c0c9e3ac3d | ||
|
|
4347ce4a53 | ||
|
|
9cc8bfae1c | ||
|
|
741ae488d5 | ||
|
|
10ef6749b3 | ||
|
|
32c3f17f5a | ||
|
|
ad45c084cc | ||
|
|
a13ed2a005 | ||
|
|
9367c764be | ||
|
|
4f57b685bd | ||
|
|
902a8c57bd | ||
|
|
21cfd330c0 | ||
|
|
c017a7a1c7 | ||
|
|
0756aa663b | ||
|
|
4ee94917a0 | ||
|
|
0df21afcdf | ||
|
|
de29f2dde5 | ||
|
|
6f5b0a28c5 | ||
|
|
433a825006 | ||
|
|
4f288e3ba2 | ||
|
|
392b59be4e | ||
|
|
6d8d211631 | ||
|
|
af17253a72 | ||
|
|
cfdea04c83 | ||
|
|
5cf03e68d4 | ||
|
|
20323e7032 | ||
|
|
78343a62b8 | ||
|
|
7584e73d70 | ||
|
|
eac5ba4c56 | ||
|
|
a9d5699a52 | ||
|
|
4e08264522 | ||
|
|
6b39e4a210 | ||
|
|
4a1c8f6cb7 | ||
|
|
468d5f6c7a | ||
|
|
a8382d6794 | ||
|
|
e899050500 | ||
|
|
b01fd9715b | ||
|
|
0417a3e51e | ||
|
|
0740b2f66b | ||
|
|
d686916fe2 | ||
|
|
fefc7c23f9 | ||
|
|
cef7525d00 | ||
|
|
b448b0c796 | ||
|
|
a97dc6d17a | ||
|
|
fcfc13c1ea | ||
|
|
1e4ef195bb | ||
|
|
566d76def2 | ||
|
|
f553d16539 | ||
|
|
8897a7a926 | ||
|
|
656ee0d9c3 | ||
|
|
ecc03fdd40 | ||
|
|
b290415bbd | ||
|
|
16069cd477 | ||
|
|
ae1c33b863 | ||
|
|
d21def7b8d | ||
|
|
bd5e622bec | ||
|
|
a5c508d2d7 | ||
|
|
b731ca50bc | ||
|
|
4eb9fc1bb6 | ||
|
|
9b94dfcbdc | ||
|
|
046f48db51 | ||
|
|
b57ffbf1ab | ||
|
|
42bae9d71d | ||
|
|
dcffb51e5e | ||
|
|
8c5751e9f7 | ||
|
|
a655cca0a1 | ||
|
|
e472d11761 | ||
|
|
ec1fc5a17b | ||
|
|
bde30b90e8 | ||
|
|
42adb2afd4 | ||
|
|
0588435882 | ||
|
|
08947682b0 | ||
|
|
cbbc4376ca | ||
|
|
9498a5738a | ||
|
|
fcaf9cb031 | ||
|
|
f7525d7877 | ||
|
|
2b3b41d5f9 | ||
|
|
2d9d4af98d | ||
|
|
81eab9887b | ||
|
|
7521aeea09 | ||
|
|
e8d4abe78f | ||
|
|
46cd8708a4 | ||
|
|
27e1938e9f | ||
|
|
17198c26d9 | ||
|
|
eaeebd3ebd | ||
|
|
253a383168 | ||
|
|
3e4a0705e9 | ||
|
|
7ef374477d | ||
|
|
4ae6103356 | ||
|
|
2e4322c230 | ||
|
|
6b7e375963 | ||
|
|
c46c1dbb1e | ||
|
|
af79f4793e | ||
|
|
774a15f4c8 | ||
|
|
b7c4cde11a | ||
|
|
9857aa25a3 | ||
|
|
d4a8a64ba7 | ||
|
|
af0098f064 | ||
|
|
37c53f2e09 | ||
|
|
a8e59ccd3d | ||
|
|
57852366bb | ||
|
|
a4832c304e | ||
|
|
156d823b7f | ||
|
|
45d9cc6405 | ||
|
|
0aeb53435e | ||
|
|
7dd1ebc734 | ||
|
|
ce694760bc | ||
|
|
c8189046fe | ||
|
|
2656812dea | ||
|
|
1978b39337 | ||
|
|
e7bfd1c959 | ||
|
|
663f8f4b54 | ||
|
|
9b0a32f62c | ||
|
|
06065d1c5d | ||
|
|
e84ae6e2aa | ||
|
|
13f9a6c273 | ||
|
|
d89b23c120 | ||
|
|
479451e7c7 | ||
|
|
ea8a4f2b51 | ||
|
|
e26189ba87 | ||
|
|
003522d6f7 | ||
|
|
4db6ccd579 | ||
|
|
39aa740c88 | ||
|
|
66f825beb1 | ||
|
|
75feeca0f0 | ||
|
|
120aa1c9ce | ||
|
|
7fa2ffc2a7 | ||
|
|
15fae91ac7 | ||
|
|
4ae190dab9 | ||
|
|
0baa60caab | ||
|
|
2a3bcdcaab | ||
|
|
619f74fa12 | ||
|
|
8aaf029e55 | ||
|
|
bcce7aff18 | ||
|
|
b575055d7e | ||
|
|
d5b3ef5380 | ||
|
|
58ef0bea17 | ||
|
|
7de6a06acf | ||
|
|
2cd10d339f | ||
|
|
38281f3364 | ||
|
|
25bcc2dd0d | ||
|
|
af27c62b07 | ||
|
|
8b16b82ce9 | ||
|
|
223e9d97a0 | ||
|
|
7b49d94e9f | ||
|
|
a677eb0f95 | ||
|
|
987579d391 | ||
|
|
99414065a9 | ||
|
|
e4b0577cb0 | ||
|
|
424afd3faf | ||
|
|
6fac14ad3f | ||
|
|
d69367aa9b | ||
|
|
2efb7a12cb | ||
|
|
9f616b934b | ||
|
|
c016e83eb3 | ||
|
|
7015dbf0d2 | ||
|
|
9f42c4c441 | ||
|
|
1841f826fe | ||
|
|
e24267d060 | ||
|
|
91591f37e6 | ||
|
|
8875296338 | ||
|
|
98eb8cd3c1 | ||
|
|
2acd7f4d12 | ||
|
|
4d49156dac | ||
|
|
c147e72c8e | ||
|
|
f872799f5c | ||
|
|
913bc8e198 | ||
|
|
c37740273f | ||
|
|
f09ed4b677 | ||
|
|
e52f5933a0 | ||
|
|
9339853448 | ||
|
|
12fb9f1f18 | ||
|
|
f3b182606b | ||
|
|
a0284a9bc5 | ||
|
|
09e5035ab5 | ||
|
|
b7e078e98d | ||
|
|
f80e81bf9f | ||
|
|
c34d868609 | ||
|
|
2b05c61ae3 | ||
|
|
b859afc118 | ||
|
|
03979936f3 | ||
|
|
4d7050553c | ||
|
|
c104858079 | ||
|
|
2c8781ed69 | ||
|
|
e38fc724f8 | ||
|
|
3bbfc4d420 | ||
|
|
217010a669 | ||
|
|
451cea4675 | ||
|
|
d39182b41a | ||
|
|
2cda2bd718 | ||
|
|
16e3991ffa | ||
|
|
fbbffe03a5 | ||
|
|
f61ace74bb | ||
|
|
4a8dcec63a | ||
|
|
30c6ca6751 | ||
|
|
84b7bb29f0 | ||
|
|
9d1d1f21e9 | ||
|
|
883c4b63d0 | ||
|
|
0380d3ae50 | ||
|
|
2fbb98a97c | ||
|
|
43702e0f8e | ||
|
|
56d9ce34e4 | ||
|
|
76abb2e18d | ||
|
|
a0db484510 | ||
|
|
b3b856f476 | ||
|
|
69a7025c96 | ||
|
|
773bfea386 | ||
|
|
eafc694bba | ||
|
|
81733a523e | ||
|
|
1afe501a36 | ||
|
|
f282b51c98 | ||
|
|
ac0658bbf1 | ||
|
|
116dbc0581 | ||
|
|
6af8a0fae4 | ||
|
|
79b5ae3d57 | ||
|
|
cb15181f43 | ||
|
|
9f342ebbd1 | ||
|
|
27795015ff | ||
|
|
79a5de3fd8 | ||
|
|
2624738534 | ||
|
|
10b91b1291 | ||
|
|
1781ceb25b | ||
|
|
051e5c27b3 | ||
|
|
5285b729be | ||
|
|
9bc6000cb5 | ||
|
|
fdf3f6ce30 | ||
|
|
0d930b65f1 | ||
|
|
16b3962b66 | ||
|
|
4b95f3a462 | ||
|
|
4ffae1d563 | ||
|
|
abffd98e29 | ||
|
|
56f9cc683a | ||
|
|
49cc00dedf | ||
|
|
9fa13710aa | ||
|
|
0eda33f057 | ||
|
|
2b4fff70d5 | ||
|
|
a80f4c1605 | ||
|
|
6aba4e916a | ||
|
|
6a7f0d70fd | ||
|
|
042684fb38 | ||
|
|
018575de71 | ||
|
|
8c0588d4e0 | ||
|
|
aaa8c56686 | ||
|
|
5e936a24ac | ||
|
|
edd80d88a9 | ||
|
|
25659e482e | ||
|
|
a097d17166 | ||
|
|
d4bbc24031 | ||
|
|
3dd41bc09a | ||
|
|
9490ec7686 | ||
|
|
a2b3cf95a7 | ||
|
|
cc7f4fedf6 | ||
|
|
22bd7c0271 | ||
|
|
3408c8038e | ||
|
|
5a4cdcfde1 | ||
|
|
0babe4a5ed | ||
|
|
a538b37854 | ||
|
|
ebaeec1677 | ||
|
|
1f1d9cefca | ||
|
|
a846088eac | ||
|
|
43f4eb76c4 | ||
|
|
29b9fbcc9a | ||
|
|
4d10b9a31b | ||
|
|
0727102c5e | ||
|
|
4c2590ed92 | ||
|
|
66ce176b22 | ||
|
|
a824ff479a | ||
|
|
c88c6b1323 | ||
|
|
b459f00bd3 | ||
|
|
00376c1d59 | ||
|
|
85a8b149bb | ||
|
|
3fcb57559a | ||
|
|
bf21892cfa | ||
|
|
c4576463e2 | ||
|
|
3af686daff | ||
|
|
c811188e22 | ||
|
|
ef88a06f08 | ||
|
|
cf050ff9e2 | ||
|
|
bb04069e83 | ||
|
|
a938859eb8 | ||
|
|
8d35576a36 | ||
|
|
9cae04edde | ||
|
|
11684c2c73 | ||
|
|
e258973490 | ||
|
|
00d57fa547 | ||
|
|
24106469c5 | ||
|
|
9c55280917 | ||
|
|
98333049ec | ||
|
|
63b45a873b | ||
|
|
ec34bfde26 | ||
|
|
8ae91ea2ee | ||
|
|
772c456513 | ||
|
|
3a4cd19226 | ||
|
|
4d8c1c61a5 | ||
|
|
bee3abe334 | ||
|
|
5d1c626a53 | ||
|
|
fb612075c4 | ||
|
|
7c5d3296e7 | ||
|
|
002b9b5d4b | ||
|
|
a0a23e04cf | ||
|
|
763fdb4be1 | ||
|
|
4d0cef5070 | ||
|
|
18c7ba94f8 | ||
|
|
5fb72b5e05 | ||
|
|
960971b195 | ||
|
|
b10a6422d4 | ||
|
|
2714f280f5 | ||
|
|
9c53d241fa | ||
|
|
f4d33e366d | ||
|
|
73cdf35c98 | ||
|
|
140651c258 | ||
|
|
ff6a8fac2a | ||
|
|
1807458c66 | ||
|
|
fb41474555 | ||
|
|
3f390c6849 | ||
|
|
4a186069d9 | ||
|
|
d942694695 | ||
|
|
766f5afabd | ||
|
|
e16fa08e61 | ||
|
|
b07d4eba11 | ||
|
|
f1d1070baa | ||
|
|
0c146de7dd | ||
|
|
5a56de501a | ||
|
|
11d16a7342 | ||
|
|
1b5db42ec6 | ||
|
|
0b6b4ca50d | ||
|
|
e7e8b3fdb6 | ||
|
|
5bfa898a02 | ||
|
|
770a3509cf | ||
|
|
b14870d9a1 | ||
|
|
52340b43f5 | ||
|
|
1323542373 | ||
|
|
24b9313958 | ||
|
|
0e1290fc10 | ||
|
|
8abe8fe01d | ||
|
|
77b35ba7ab | ||
|
|
96e48ac13c | ||
|
|
d83534d513 | ||
|
|
19c7ee0932 | ||
|
|
24bcf6ac16 | ||
|
|
5d23d165a9 | ||
|
|
b3b9994ce8 | ||
|
|
df0bda058f | ||
|
|
15b8449411 | ||
|
|
e1d68fa3cd | ||
|
|
2c9ce3f3e0 | ||
|
|
734f42b5f9 | ||
|
|
3cff64001d | ||
|
|
241297fb2e | ||
|
|
d4583006b3 | ||
|
|
d42e51e33a | ||
|
|
3bed19d70d | ||
|
|
fd6ef6712f | ||
|
|
c51982a231 | ||
|
|
53d4c36332 | ||
|
|
de76bf5f63 | ||
|
|
e0e47ea9a1 | ||
|
|
3989139378 | ||
|
|
ca68dfe097 | ||
|
|
5114d571df | ||
|
|
08808664b6 | ||
|
|
13de65d310 | ||
|
|
6728efe87e | ||
|
|
458c4dd129 | ||
|
|
ef45b67dbf | ||
|
|
604700187d | ||
|
|
7e1ae369ed | ||
|
|
9850af93c9 | ||
|
|
4c8d0ab804 | ||
|
|
47fd41715f | ||
|
|
a64978b812 | ||
|
|
524bab530a | ||
|
|
72154b64ed | ||
|
|
695509e267 | ||
|
|
0f7652dc85 | ||
|
|
1713200084 | ||
|
|
6afe8aa7f2 | ||
|
|
c8629019f5 | ||
|
|
a7b6332ed0 | ||
|
|
06cc9a44fe | ||
|
|
0b3b29938f | ||
|
|
1b1541fe1a | ||
|
|
1d228446db | ||
|
|
c783ec72bc | ||
|
|
90c5972fce | ||
|
|
1f677ed361 | ||
|
|
9c19b4e3d5 | ||
|
|
d4a1f396fb | ||
|
|
72e3816143 | ||
|
|
9dd181c206 | ||
|
|
9828926002 | ||
|
|
bb955b6202 | ||
|
|
1dd05ff520 | ||
|
|
19bd5ea8ba | ||
|
|
bcf7a86dc7 | ||
|
|
2fbdac1034 | ||
|
|
577585df63 | ||
|
|
f13bd655a1 | ||
|
|
81de0518d9 | ||
|
|
d93a86e8cc | ||
|
|
7e186cee55 | ||
|
|
97da066ae2 | ||
|
|
b58f73b5c9 | ||
|
|
ad1cb16a76 | ||
|
|
cd4a66dca5 | ||
|
|
cc282a1114 | ||
|
|
270d6f774a | ||
|
|
987a2e173a | ||
|
|
66efaa5e0f | ||
|
|
27a9f960de | ||
|
|
74e03d285e | ||
|
|
123f2a8265 | ||
|
|
d25c2d0f41 | ||
|
|
d2a701a465 | ||
|
|
1df30821db | ||
|
|
bf88fe32fd | ||
|
|
e21d5bd380 | ||
|
|
04bdc87283 | ||
|
|
177ccbc014 | ||
|
|
d6cd9e3034 | ||
|
|
d391f1b527 | ||
|
|
8c7a4de27b | ||
|
|
7cd7894878 | ||
|
|
d7fc7ef2ee | ||
|
|
6aef061362 | ||
|
|
e4943b3ab3 | ||
|
|
091136908d | ||
|
|
c6390e71d9 | ||
|
|
ab5e51c209 | ||
|
|
938b9e897a | ||
|
|
924033c2ba | ||
|
|
99e256f461 | ||
|
|
d2bcbafe73 | ||
|
|
5c07643d24 | ||
|
|
56d62ff589 | ||
|
|
62375663ab | ||
|
|
f5694daeb7 | ||
|
|
3a73625ece | ||
|
|
3b45f5a8e9 | ||
|
|
78791763cf | ||
|
|
81b55c1700 | ||
|
|
39a3ffdb9d | ||
|
|
df03c92249 | ||
|
|
c336cf59c1 | ||
|
|
fcd6fd9fd5 | ||
|
|
1ec173ad81 | ||
|
|
bce62622bb | ||
|
|
1290ddb5c9 | ||
|
|
ea42722918 | ||
|
|
aac09e5234 | ||
|
|
df3896b143 | ||
|
|
903bf444d9 | ||
|
|
3dad8734a0 | ||
|
|
762a5bbefa | ||
|
|
d3a175cea8 | ||
|
|
4e0f810148 | ||
|
|
32543997d4 | ||
|
|
c9a3ab3a81 | ||
|
|
3b4a071723 | ||
|
|
de9b01409b | ||
|
|
296a53536d | ||
|
|
783d47f78b | ||
|
|
b35bde662a | ||
|
|
ad783652c8 | ||
|
|
7ba947aee9 | ||
|
|
696e5e73bc | ||
|
|
a723d17f49 | ||
|
|
f8236c1a65 | ||
|
|
546c0e7822 | ||
|
|
e7c4d2523b | ||
|
|
fbb3a288ec | ||
|
|
cae15ad6b5 | ||
|
|
ed465208a2 | ||
|
|
c2c48c4079 | ||
|
|
dc7d2dab68 | ||
|
|
146970d29d | ||
|
|
ba2cb42f0d | ||
|
|
7dfe1a59b1 | ||
|
|
4343f762ac | ||
|
|
e2f53c6bcc | ||
|
|
5c22f2ca5d | ||
|
|
b6d4014bd5 | ||
|
|
6b8f5f5b7f | ||
|
|
b7e2f819a3 | ||
|
|
a8e0e8d7fd | ||
|
|
beea9a7c36 | ||
|
|
a44d7a3bc6 | ||
|
|
b45db70d21 | ||
|
|
8feff471ce | ||
|
|
00dec166e9 | ||
|
|
ebbbaf1ab0 | ||
|
|
29312186de | ||
|
|
e1d9e4ffcb | ||
|
|
b6c04c9e35 | ||
|
|
405b411a29 | ||
|
|
582fc50cf6 | ||
|
|
b74cfda7b9 | ||
|
|
805ce0dee9 | ||
|
|
f4a8fb9eb4 | ||
|
|
85702604c3 | ||
|
|
98999f4850 | ||
|
|
b5e1571204 | ||
|
|
d7934e7525 | ||
|
|
7fcba6ba0f | ||
|
|
ea1927f428 | ||
|
|
fa2aaa48b1 | ||
|
|
dee383db07 | ||
|
|
04a1dc8e1e | ||
|
|
ae31ded165 | ||
|
|
402e977b40 | ||
|
|
a65c8cae63 | ||
|
|
47a03d3ca1 | ||
|
|
b4a13fda3a | ||
|
|
e11672d42b | ||
|
|
30a6b597a5 | ||
|
|
c45ca254e3 | ||
|
|
143d7ab98f | ||
|
|
e3e450613d | ||
|
|
77fdc67235 | ||
|
|
61e50046bd | ||
|
|
1cdf8bbc10 | ||
|
|
a3d2cdaa2c | ||
|
|
159e2f2dab | ||
|
|
e8f3cf164b | ||
|
|
456f102cdc | ||
|
|
ba98109d33 | ||
|
|
9f94652792 | ||
|
|
1454510549 | ||
|
|
c0f8b4895d | ||
|
|
5dd5dbb3d8 | ||
|
|
48fd2bd35f | ||
|
|
29fa48d8c3 | ||
|
|
90bff4d9de | ||
|
|
b05254807b | ||
|
|
e504d82554 | ||
|
|
5bf746700e | ||
|
|
07a08077a2 | ||
|
|
26004f1a66 | ||
|
|
1c6586c4b9 | ||
|
|
0ac4b89a0a | ||
|
|
6de1eef078 | ||
|
|
1fd819e500 | ||
|
|
a260647b4f | ||
|
|
ffe931bde7 | ||
|
|
27bc6c7883 | ||
|
|
6c340cece8 | ||
|
|
64718173ef | ||
|
|
43f955194e | ||
|
|
8567f79e67 | ||
|
|
269a87b26f | ||
|
|
084110c56f | ||
|
|
47df447e4f | ||
|
|
1072519488 | ||
|
|
37de2301f7 | ||
|
|
fec5a7d67a | ||
|
|
8baaad4e0d | ||
|
|
10ea0268e5 | ||
|
|
b4c220613f | ||
|
|
d4b204799d | ||
|
|
12a2b144f3 | ||
|
|
7df86c48fa | ||
|
|
0c3ad527e3 | ||
|
|
37e30cef60 | ||
|
|
0fda86f79a | ||
|
|
e77d7e7f62 | ||
|
|
5d0f3534eb | ||
|
|
577394442b | ||
|
|
d1274bb79f | ||
|
|
da677b683b | ||
|
|
9dad9478fa | ||
|
|
ea244a5188 | ||
|
|
69d4cac760 | ||
|
|
e7f1265b64 | ||
|
|
94faaf7d58 | ||
|
|
d426d4ad90 | ||
|
|
64e53a17bd | ||
|
|
20d5a50ac9 | ||
|
|
9714348260 | ||
|
|
787bc85703 | ||
|
|
e62e62292a | ||
|
|
b84d29fb32 | ||
|
|
5be8104104 | ||
|
|
eef42770c6 | ||
|
|
f792c720f4 | ||
|
|
359ab2f9b3 | ||
|
|
bc13536208 | ||
|
|
0d4872755c | ||
|
|
4627311c34 | ||
|
|
dc2ced14b8 | ||
|
|
eafb6307d5 | ||
|
|
fbac635687 | ||
|
|
5ccd0a24e9 | ||
|
|
f8bdc7437d | ||
|
|
1de2b77ee4 | ||
|
|
18fd3e0329 | ||
|
|
a510642a25 | ||
|
|
30dd65e3a9 | ||
|
|
5708e86a05 | ||
|
|
937ae7ef8f | ||
|
|
4c56c1c2b2 | ||
|
|
6d8f900916 | ||
|
|
4aa292c7cd | ||
|
|
f28e8d7168 | ||
|
|
2e0a1a8a64 | ||
|
|
56b40ae6d2 | ||
|
|
9e8b0953f3 | ||
|
|
893fc2cd53 | ||
|
|
2435f1b660 | ||
|
|
afb551e94a | ||
|
|
5754f3aea0 | ||
|
|
d3dc66e308 | ||
|
|
313b2faa3c | ||
|
|
18585204b7 | ||
|
|
3d40c720dd | ||
|
|
8d201ae1ad | ||
|
|
67c89b68d3 | ||
|
|
5937d37fc5 | ||
|
|
56a644d49f | ||
|
|
0c54700b16 | ||
|
|
3a5bf51d1d | ||
|
|
7b85ca0301 | ||
|
|
5cbc8d5c71 | ||
|
|
be4bc6b7ef | ||
|
|
d2e40d4fc1 | ||
|
|
a23e7ecf8f | ||
|
|
0fb2339e3d | ||
|
|
2b0f632d51 |
35
.clang-format
Normal file
35
.clang-format
Normal file
@@ -0,0 +1,35 @@
|
||||
# Defines the Chromium style for automatic reformatting.
|
||||
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
BasedOnStyle: Chromium
|
||||
# This defaults to 'Auto'. Explicitly set it for a while, so that
|
||||
# 'vector<vector<int> >' in existing files gets formatted to
|
||||
# 'vector<vector<int>>'. ('Auto' means that clang-format will only use
|
||||
# 'int>>' if the file already contains at least one such instance.)
|
||||
Standard: Cpp11
|
||||
# Make sure code like:
|
||||
# IPC_BEGIN_MESSAGE_MAP()
|
||||
# IPC_MESSAGE_HANDLER(WidgetHostViewHost_Update, OnUpdate)
|
||||
# IPC_END_MESSAGE_MAP()
|
||||
# gets correctly indented.
|
||||
MacroBlockBegin: "^\
|
||||
BEGIN_MSG_MAP|\
|
||||
BEGIN_MSG_MAP_EX|\
|
||||
BEGIN_SAFE_MSG_MAP_EX|\
|
||||
CR_BEGIN_MSG_MAP_EX|\
|
||||
IPC_BEGIN_MESSAGE_MAP|\
|
||||
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM|\
|
||||
IPC_PROTOBUF_MESSAGE_TRAITS_BEGIN|\
|
||||
IPC_STRUCT_BEGIN|\
|
||||
IPC_STRUCT_BEGIN_WITH_PARENT|\
|
||||
IPC_STRUCT_TRAITS_BEGIN|\
|
||||
POLPARAMS_BEGIN|\
|
||||
PPAPI_BEGIN_MESSAGE_MAP$"
|
||||
MacroBlockEnd: "^\
|
||||
CR_END_MSG_MAP|\
|
||||
END_MSG_MAP|\
|
||||
IPC_END_MESSAGE_MAP|\
|
||||
IPC_PROTOBUF_MESSAGE_TRAITS_END|\
|
||||
IPC_STRUCT_END|\
|
||||
IPC_STRUCT_TRAITS_END|\
|
||||
POLPARAMS_END|\
|
||||
PPAPI_END_MESSAGE_MAP$"
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -26,5 +26,4 @@ node_modules/
|
||||
*.vcxproj.user
|
||||
*.vcxproj.filters
|
||||
*.sln
|
||||
debug.log
|
||||
npm-debug.log
|
||||
*.log
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -12,7 +12,7 @@
|
||||
url = https://github.com/electron/chromium-breakpad.git
|
||||
[submodule "vendor/native_mate"]
|
||||
path = vendor/native_mate
|
||||
url = https://github.com/zcbenz/native-mate.git
|
||||
url = https://github.com/electron/native-mate.git
|
||||
[submodule "vendor/crashpad"]
|
||||
path = vendor/crashpad
|
||||
url = https://github.com/electron/crashpad.git
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contributing to Electron
|
||||
|
||||
:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/CONTRIBUTING.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/CONTRIBUTING.md)
|
||||
:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/CONTRIBUTING.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/CONTRIBUTING.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/CONTRIBUTING.md) | [Dutch](https://github.com/electron/electron/tree/master/docs-translations/nl/project/CONTRIBUTING.md)
|
||||
|
||||
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
||||
|
||||
|
||||
@@ -1,2 +1,23 @@
|
||||
<!--
|
||||
Thanks for opening an issue! A few things to keep in mind:
|
||||
|
||||
- The issue tracker is only for bugs and feature requests.
|
||||
- Before reporting a bug, please try reproducing your issue against
|
||||
the latest version of Electron.
|
||||
- If you need general advice, join our Slack: http://atom-slack.herokuapp.com
|
||||
-->
|
||||
|
||||
* Electron version:
|
||||
* Operating system:
|
||||
|
||||
### Expected behavior
|
||||
|
||||
<!-- What do you think should happen? -->
|
||||
|
||||
### Actual behavior
|
||||
|
||||
<!-- What actually happens? -->
|
||||
|
||||
### How to reproduce
|
||||
|
||||
<!-- For bugs, provide sample code or a repo URL that demos the problem -->
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2014 GitHub Inc.
|
||||
Copyright (c) 2013-2017 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
28
README.md
28
README.md
@@ -2,10 +2,10 @@
|
||||
|
||||
[](https://travis-ci.org/electron/electron)
|
||||
[](https://ci.appveyor.com/project/Atom/electron)
|
||||
[](https://david-dm.org/electron/electron#info=devDependencies)
|
||||
[](https://david-dm.org/electron/electron?type=dev)
|
||||
[](http://atom-slack.herokuapp.com/)
|
||||
|
||||
:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md)
|
||||
:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md)
|
||||
|
||||
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
|
||||
@@ -21,20 +21,20 @@ behavior to electron@github.com.
|
||||
|
||||
## Downloads
|
||||
|
||||
Prebuilt binaries and debug symbols of Electron for Linux, Windows and macOS can
|
||||
be found on the [releases](https://github.com/electron/electron/releases) page.
|
||||
|
||||
You can also use [`npm`](https://docs.npmjs.com/) to install prebuilt electron
|
||||
binaries:
|
||||
To install prebuilt Electron binaries, use
|
||||
[`npm`](https://docs.npmjs.com/):
|
||||
|
||||
```sh
|
||||
# Install the `electron` command globally in your $PATH
|
||||
npm install electron -g
|
||||
|
||||
# Install as a development dependency
|
||||
npm install electron --save-dev
|
||||
|
||||
# Install the `electron` command globally in your $PATH
|
||||
npm install electron -g
|
||||
```
|
||||
|
||||
See the [releases page](https://github.com/electron/electron/releases) for
|
||||
prebuilt binaries, debug symbols, and more.
|
||||
|
||||
### Mirrors
|
||||
|
||||
- [China](https://npm.taobao.org/mirrors/electron)
|
||||
@@ -73,9 +73,15 @@ forums
|
||||
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(Japanese)*
|
||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
||||
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turkish)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
for a community maintained list of useful example apps, tools and resources.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/electron/electron/blob/master/LICENSE)
|
||||
|
||||
When using the Electron or other GitHub logos, be sure to follow the [GitHub logo guidelines](https://github.com/logos).
|
||||
|
||||
@@ -197,11 +197,20 @@ void AtomContentClient::AddServiceWorkerSchemes(
|
||||
std::vector<std::string> schemes;
|
||||
ConvertStringWithSeparatorToVector(&schemes, ",",
|
||||
switches::kRegisterServiceWorkerSchemes);
|
||||
if (!schemes.empty()) {
|
||||
for (const std::string& scheme : schemes)
|
||||
service_worker_schemes->insert(scheme);
|
||||
}
|
||||
for (const std::string& scheme : schemes)
|
||||
service_worker_schemes->insert(scheme);
|
||||
|
||||
service_worker_schemes->insert(url::kFileScheme);
|
||||
}
|
||||
|
||||
void AtomContentClient::AddSecureSchemesAndOrigins(
|
||||
std::set<std::string>* secure_schemes,
|
||||
std::set<GURL>* secure_origins) {
|
||||
std::vector<std::string> schemes;
|
||||
ConvertStringWithSeparatorToVector(&schemes, ",", switches::kSecureSchemes);
|
||||
for (const std::string& scheme : schemes)
|
||||
secure_schemes->insert(scheme);
|
||||
}
|
||||
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -31,6 +31,9 @@ class AtomContentClient : public brightray::ContentClient {
|
||||
std::vector<content::PepperPluginInfo>* plugins) override;
|
||||
void AddServiceWorkerSchemes(
|
||||
std::set<std::string>* service_worker_schemes) override;
|
||||
void AddSecureSchemesAndOrigins(
|
||||
std::set<std::string>* secure_schemes,
|
||||
std::set<GURL>* secure_origins) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/relauncher.h"
|
||||
#include "atom/common/google_api_key.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "atom/renderer/atom_renderer_client.h"
|
||||
#include "atom/renderer/atom_sandboxed_renderer_client.h"
|
||||
#include "atom/utility/atom_content_utility_client.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/debug/stack_trace.h"
|
||||
@@ -29,7 +31,7 @@ namespace {
|
||||
const char* kRelauncherProcess = "relauncher";
|
||||
|
||||
bool IsBrowserProcess(base::CommandLine* cmd) {
|
||||
std::string process_type = cmd->GetSwitchValueASCII(switches::kProcessType);
|
||||
std::string process_type = cmd->GetSwitchValueASCII(::switches::kProcessType);
|
||||
return process_type.empty();
|
||||
}
|
||||
|
||||
@@ -72,7 +74,7 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
|
||||
// Only enable logging when --enable-logging is specified.
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (!command_line->HasSwitch(switches::kEnableLogging) &&
|
||||
if (!command_line->HasSwitch(::switches::kEnableLogging) &&
|
||||
!env->HasVar("ELECTRON_ENABLE_LOGGING")) {
|
||||
settings.logging_dest = logging::LOG_NONE;
|
||||
logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES);
|
||||
@@ -115,17 +117,23 @@ void AtomMainDelegate::PreSandboxStartup() {
|
||||
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string process_type = command_line->GetSwitchValueASCII(
|
||||
switches::kProcessType);
|
||||
::switches::kProcessType);
|
||||
|
||||
// Only append arguments for browser process.
|
||||
if (!IsBrowserProcess(command_line))
|
||||
return;
|
||||
|
||||
// Disable renderer sandbox for most of node's functions.
|
||||
command_line->AppendSwitch(switches::kNoSandbox);
|
||||
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);
|
||||
} else {
|
||||
// Disable renderer sandbox for most of node's functions.
|
||||
command_line->AppendSwitch(::switches::kNoSandbox);
|
||||
}
|
||||
|
||||
// Allow file:// URIs to read other file:// URIs by default.
|
||||
command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
|
||||
command_line->AppendSwitch(::switches::kAllowFileAccessFromFiles);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Enable AVFoundation.
|
||||
@@ -140,7 +148,13 @@ content::ContentBrowserClient* AtomMainDelegate::CreateContentBrowserClient() {
|
||||
|
||||
content::ContentRendererClient*
|
||||
AtomMainDelegate::CreateContentRendererClient() {
|
||||
renderer_client_.reset(new AtomRendererClient);
|
||||
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kEnableSandbox)) {
|
||||
renderer_client_.reset(new AtomSandboxedRendererClient);
|
||||
} else {
|
||||
renderer_client_.reset(new AtomRendererClient);
|
||||
}
|
||||
|
||||
return renderer_client_.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
#include "gin/public/isolate_holder.h"
|
||||
#include "gin/v8_initializer.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#endif
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
@@ -51,6 +57,11 @@ int NodeMain(int argc, char *argv[]) {
|
||||
if (node_debugger.IsRunning())
|
||||
env->AssignToContext(v8::Debug::GetDebugContext());
|
||||
|
||||
#if defined(OS_WIN)
|
||||
mate::Dictionary process(gin_env.isolate(), env->process_object());
|
||||
process.SetMethod("log", &AtomBindings::Log);
|
||||
#endif
|
||||
|
||||
node::LoadEnvironment(env);
|
||||
|
||||
bool more;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "content/public/browser/gpu_data_manager.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "media/audio/audio_manager.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
@@ -377,9 +378,21 @@ void OnClientCertificateSelected(
|
||||
v8::Isolate* isolate,
|
||||
std::shared_ptr<content::ClientCertificateDelegate> delegate,
|
||||
mate::Arguments* args) {
|
||||
if (args->Length() == 2) {
|
||||
delegate->ContinueWithCertificate(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> val;
|
||||
args->GetNext(&val);
|
||||
if (val->IsNull()) {
|
||||
delegate->ContinueWithCertificate(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
mate::Dictionary cert_data;
|
||||
if (!args->GetNext(&cert_data)) {
|
||||
args->ThrowError();
|
||||
if (!mate::ConvertFromV8(isolate, val, &cert_data)) {
|
||||
args->ThrowError("Must pass valid certificate object.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -490,6 +503,11 @@ void App::OnWillFinishLaunching() {
|
||||
}
|
||||
|
||||
void App::OnFinishLaunching(const base::DictionaryValue& launch_info) {
|
||||
#if defined(OS_LINUX)
|
||||
// Set the application name for audio streams shown in external
|
||||
// applications. Only affects pulseaudio currently.
|
||||
media::AudioManager::SetGlobalAppName(Browser::Get()->GetName());
|
||||
#endif
|
||||
Emit("ready", launch_info);
|
||||
}
|
||||
|
||||
@@ -522,11 +540,14 @@ void App::OnLogin(LoginHandler* login_handler,
|
||||
login_handler->CancelAuth();
|
||||
}
|
||||
|
||||
void App::OnCreateWindow(const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
int render_process_id,
|
||||
int render_frame_id) {
|
||||
void App::OnCreateWindow(
|
||||
const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const std::vector<base::string16>& features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||
int render_process_id,
|
||||
int render_frame_id) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
content::RenderFrameHost* rfh =
|
||||
@@ -535,7 +556,11 @@ void App::OnCreateWindow(const GURL& target_url,
|
||||
content::WebContents::FromRenderFrameHost(rfh);
|
||||
if (web_contents) {
|
||||
auto api_web_contents = WebContents::CreateFrom(isolate(), web_contents);
|
||||
api_web_contents->OnCreateWindow(target_url, frame_name, disposition);
|
||||
api_web_contents->OnCreateWindow(target_url,
|
||||
frame_name,
|
||||
disposition,
|
||||
features,
|
||||
body);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,8 +610,9 @@ void App::SelectClientCertificate(
|
||||
cert_request_info->client_certs[0].get());
|
||||
}
|
||||
|
||||
void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
|
||||
Emit("gpu-process-crashed");
|
||||
void App::OnGpuProcessCrashed(base::TerminationStatus status) {
|
||||
Emit("gpu-process-crashed",
|
||||
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
|
||||
}
|
||||
|
||||
base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
|
||||
@@ -596,7 +622,7 @@ base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
|
||||
if (key >= 0)
|
||||
succeed = PathService::Get(key, &path);
|
||||
if (!succeed)
|
||||
args->ThrowError("Failed to get path");
|
||||
args->ThrowError("Failed to get '" + name + "' path");
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -604,7 +630,7 @@ void App::SetPath(mate::Arguments* args,
|
||||
const std::string& name,
|
||||
const base::FilePath& path) {
|
||||
if (!path.IsAbsolute()) {
|
||||
args->ThrowError("path must be absolute");
|
||||
args->ThrowError("Path must be absolute");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -839,6 +865,8 @@ void App::BuildPrototype(
|
||||
base::Bind(&Browser::SetUserActivity, browser))
|
||||
.SetMethod("getCurrentActivityType",
|
||||
base::Bind(&Browser::GetCurrentActivityType, browser))
|
||||
.SetMethod("setAboutPanelOptions",
|
||||
base::Bind(&Browser::SetAboutPanelOptions, browser))
|
||||
#endif
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("setUserTasks", base::Bind(&Browser::SetUserTasks, browser))
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define ATOM_BROWSER_API_ATOM_API_APP_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
@@ -47,11 +48,14 @@ class App : public AtomBrowserClient::Delegate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Called when window with disposition needs to be created.
|
||||
void OnCreateWindow(const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
int render_process_id,
|
||||
int render_frame_id);
|
||||
void OnCreateWindow(
|
||||
const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const std::vector<base::string16>& features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||
int render_process_id,
|
||||
int render_frame_id);
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
void OnCertificateManagerModelCreated(
|
||||
@@ -102,7 +106,7 @@ class App : public AtomBrowserClient::Delegate,
|
||||
std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
|
||||
// content::GpuDataManagerObserver:
|
||||
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
|
||||
void OnGpuProcessCrashed(base::TerminationStatus status) override;
|
||||
|
||||
private:
|
||||
// Get/Set the pre-defined path in PathService.
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "content/public/browser/tracing_controller.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::TracingController;
|
||||
|
||||
namespace mate {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#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 {
|
||||
@@ -54,6 +55,27 @@ struct Converter<net::CanonicalCookie> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<AtomCookieDelegate::ChangeCause> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const AtomCookieDelegate::ChangeCause& val) {
|
||||
switch (val) {
|
||||
case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EXPLICIT:
|
||||
return mate::StringToV8(isolate, "explicit");
|
||||
case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_OVERWRITE:
|
||||
return mate::StringToV8(isolate, "overwrite");
|
||||
case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EXPIRED:
|
||||
return mate::StringToV8(isolate, "expired");
|
||||
case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EVICTED:
|
||||
return mate::StringToV8(isolate, "evicted");
|
||||
case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EXPIRED_OVERWRITE:
|
||||
return mate::StringToV8(isolate, "expired-overwrite");
|
||||
default:
|
||||
return mate::StringToV8(isolate, "unknown");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
@@ -206,11 +228,14 @@ void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
|
||||
Cookies::Cookies(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context)
|
||||
: request_context_getter_(browser_context->url_request_context_getter()) {
|
||||
: request_context_getter_(browser_context->url_request_context_getter()),
|
||||
cookie_delegate_(browser_context->cookie_delegate()) {
|
||||
Init(isolate);
|
||||
cookie_delegate_->AddObserver(this);
|
||||
}
|
||||
|
||||
Cookies::~Cookies() {
|
||||
cookie_delegate_->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void Cookies::Get(const base::DictionaryValue& filter,
|
||||
@@ -239,6 +264,13 @@ void Cookies::Set(const base::DictionaryValue& details,
|
||||
base::Bind(SetCookieOnIO, getter, Passed(&copied), callback));
|
||||
}
|
||||
|
||||
void Cookies::OnCookieChanged(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
AtomCookieDelegate::ChangeCause cause) {
|
||||
Emit("changed", cookie, cause, removed);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
mate::Handle<Cookies> Cookies::Create(
|
||||
v8::Isolate* isolate,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/net/atom_cookie_delegate.h"
|
||||
#include "base/callback.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
@@ -26,7 +27,8 @@ class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class Cookies : public mate::TrackableObject<Cookies> {
|
||||
class Cookies : public mate::TrackableObject<Cookies>,
|
||||
public AtomCookieDelegate::Observer {
|
||||
public:
|
||||
enum Error {
|
||||
SUCCESS,
|
||||
@@ -52,8 +54,14 @@ class Cookies : public mate::TrackableObject<Cookies> {
|
||||
const base::Closure& callback);
|
||||
void Set(const base::DictionaryValue& details, const SetCallback& callback);
|
||||
|
||||
// AtomCookieDelegate::Observer:
|
||||
void OnCookieChanged(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
AtomCookieDelegate::ChangeCause cause) override;
|
||||
|
||||
private:
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
scoped_refptr<AtomCookieDelegate> cookie_delegate_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Cookies);
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#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 "atom/common/node_includes.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "content/public/browser/devtools_agent_host.h"
|
||||
@@ -17,6 +16,8 @@
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::DevToolsAgentHost;
|
||||
|
||||
namespace atom {
|
||||
@@ -107,7 +108,7 @@ bool Debugger::IsAttached() {
|
||||
void Debugger::Detach() {
|
||||
if (!agent_host_.get())
|
||||
return;
|
||||
agent_host_->DetachClient();
|
||||
agent_host_->DetachClient(this);
|
||||
AgentHostClosed(agent_host_.get(), false);
|
||||
agent_host_ = nullptr;
|
||||
}
|
||||
@@ -136,7 +137,7 @@ void Debugger::SendCommand(mate::Arguments* args) {
|
||||
|
||||
std::string json_args;
|
||||
base::JSONWriter::Write(request, &json_args);
|
||||
agent_host_->DispatchProtocolMessage(json_args);
|
||||
agent_host_->DispatchProtocolMessage(this, json_args);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "net/base/filename_util.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
@@ -134,7 +135,7 @@ std::string DownloadItem::GetFilename() const {
|
||||
std::string(),
|
||||
download_item_->GetSuggestedFilename(),
|
||||
GetMimeType(),
|
||||
std::string()).LossyDisplayName());
|
||||
"download").LossyDisplayName());
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetContentDisposition() const {
|
||||
@@ -145,6 +146,10 @@ const GURL& DownloadItem::GetURL() const {
|
||||
return download_item_->GetURL();
|
||||
}
|
||||
|
||||
const std::vector<GURL>& DownloadItem::GetURLChain() const {
|
||||
return download_item_->GetUrlChain();
|
||||
}
|
||||
|
||||
content::DownloadItem::DownloadState DownloadItem::GetState() const {
|
||||
return download_item_->GetState();
|
||||
}
|
||||
@@ -161,6 +166,18 @@ base::FilePath DownloadItem::GetSavePath() const {
|
||||
return save_path_;
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetLastModifiedTime() const {
|
||||
return download_item_->GetLastModifiedTime();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetETag() const {
|
||||
return download_item_->GetETag();
|
||||
}
|
||||
|
||||
double DownloadItem::GetStartTime() const {
|
||||
return download_item_->GetStartTime().ToDoubleT();
|
||||
}
|
||||
|
||||
// static
|
||||
void DownloadItem::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
@@ -179,10 +196,14 @@ void DownloadItem::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("getFilename", &DownloadItem::GetFilename)
|
||||
.SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition)
|
||||
.SetMethod("getURL", &DownloadItem::GetURL)
|
||||
.SetMethod("getURLChain", &DownloadItem::GetURLChain)
|
||||
.SetMethod("getState", &DownloadItem::GetState)
|
||||
.SetMethod("isDone", &DownloadItem::IsDone)
|
||||
.SetMethod("setSavePath", &DownloadItem::SetSavePath)
|
||||
.SetMethod("getSavePath", &DownloadItem::GetSavePath);
|
||||
.SetMethod("getSavePath", &DownloadItem::GetSavePath)
|
||||
.SetMethod("getLastModifiedTime", &DownloadItem::GetLastModifiedTime)
|
||||
.SetMethod("getETag", &DownloadItem::GetETag)
|
||||
.SetMethod("getStartTime", &DownloadItem::GetStartTime);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/files/file_path.h"
|
||||
@@ -38,10 +39,14 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||
std::string GetFilename() const;
|
||||
std::string GetContentDisposition() const;
|
||||
const GURL& GetURL() const;
|
||||
const std::vector<GURL>& GetURLChain() const;
|
||||
content::DownloadItem::DownloadState GetState() const;
|
||||
bool IsDone() const;
|
||||
void SetSavePath(const base::FilePath& path);
|
||||
base::FilePath GetSavePath() const;
|
||||
std::string GetLastModifiedTime() const;
|
||||
std::string GetETag() const;
|
||||
double GetStartTime() const;
|
||||
|
||||
protected:
|
||||
DownloadItem(v8::Isolate* isolate, content::DownloadItem* download_item);
|
||||
|
||||
61
atom/browser/api/atom_api_net.cc
Normal file
61
atom/browser/api/atom_api_net.cc
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_net.h"
|
||||
#include "atom/browser/api/atom_api_url_request.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Net::Net(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Net::~Net() {}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> Net::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new Net(isolate)).ToV8();
|
||||
}
|
||||
|
||||
// static
|
||||
void Net::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Net"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetProperty("URLRequest", &Net::URLRequest);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Net::URLRequest(v8::Isolate* isolate) {
|
||||
return URLRequest::GetConstructor(isolate)->GetFunction();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Net;
|
||||
using atom::api::URLRequest;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
|
||||
URLRequest::SetConstructor(isolate, base::Bind(URLRequest::New));
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("net", Net::Create(isolate));
|
||||
dict.Set("Net", Net::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_net, Initialize)
|
||||
35
atom/browser/api/atom_api_net.h
Normal file
35
atom/browser/api/atom_api_net.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_NET_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_NET_H_
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Net : public mate::EventEmitter<Net> {
|
||||
public:
|
||||
static v8::Local<v8::Value> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
v8::Local<v8::Value> URLRequest(v8::Isolate* isolate);
|
||||
|
||||
protected:
|
||||
explicit Net(v8::Isolate* isolate);
|
||||
~Net() override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Net);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_NET_H_
|
||||
@@ -5,11 +5,12 @@
|
||||
#include "atom/browser/api/atom_api_power_monitor.h"
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/node_includes.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 atom {
|
||||
|
||||
namespace api {
|
||||
@@ -43,7 +44,7 @@ v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate,
|
||||
"Cannot initialize \"power-monitor\" module before app is ready")));
|
||||
"Cannot require \"powerMonitor\" module before app is ready")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,18 +6,19 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "content/public/browser/power_save_blocker.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<content::PowerSaveBlocker::PowerSaveBlockerType> {
|
||||
struct Converter<device::PowerSaveBlocker::PowerSaveBlockerType> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType* out) {
|
||||
using content::PowerSaveBlocker;
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType* out) {
|
||||
using device::PowerSaveBlocker;
|
||||
std::string type;
|
||||
if (!ConvertFromV8(isolate, val, &type))
|
||||
return false;
|
||||
@@ -39,7 +40,7 @@ namespace api {
|
||||
|
||||
PowerSaveBlocker::PowerSaveBlocker(v8::Isolate* isolate)
|
||||
: current_blocker_type_(
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
@@ -58,30 +59,34 @@ void PowerSaveBlocker::UpdatePowerSaveBlocker() {
|
||||
// higher precedence level than |kPowerSaveBlockPreventAppSuspension|.
|
||||
//
|
||||
// Only the highest-precedence blocker type takes effect.
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType new_blocker_type =
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType new_blocker_type =
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
|
||||
for (const auto& element : power_save_blocker_types_) {
|
||||
if (element.second ==
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep) {
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep) {
|
||||
new_blocker_type =
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!power_save_blocker_ || new_blocker_type != current_blocker_type_) {
|
||||
std::unique_ptr<content::PowerSaveBlocker> new_blocker =
|
||||
content::PowerSaveBlocker::Create(
|
||||
std::unique_ptr<device::PowerSaveBlocker> new_blocker(
|
||||
new device::PowerSaveBlocker(
|
||||
new_blocker_type,
|
||||
content::PowerSaveBlocker::kReasonOther,
|
||||
ATOM_PRODUCT_NAME);
|
||||
device::PowerSaveBlocker::kReasonOther,
|
||||
ATOM_PRODUCT_NAME,
|
||||
content::BrowserThread::GetMessageLoopProxyForThread(
|
||||
content::BrowserThread::UI),
|
||||
content::BrowserThread::GetMessageLoopProxyForThread(
|
||||
content::BrowserThread::FILE)));
|
||||
power_save_blocker_.swap(new_blocker);
|
||||
current_blocker_type_ = new_blocker_type;
|
||||
}
|
||||
}
|
||||
|
||||
int PowerSaveBlocker::Start(
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType type) {
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType type) {
|
||||
static int count = 0;
|
||||
power_save_blocker_types_[count] = type;
|
||||
UpdatePowerSaveBlocker();
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "content/public/browser/power_save_blocker.h"
|
||||
#include "device/power_save_blocker/power_save_blocker.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace mate {
|
||||
@@ -33,18 +33,18 @@ class PowerSaveBlocker : public mate::TrackableObject<PowerSaveBlocker> {
|
||||
|
||||
private:
|
||||
void UpdatePowerSaveBlocker();
|
||||
int Start(content::PowerSaveBlocker::PowerSaveBlockerType type);
|
||||
int Start(device::PowerSaveBlocker::PowerSaveBlockerType type);
|
||||
bool Stop(int id);
|
||||
bool IsStarted(int id);
|
||||
|
||||
std::unique_ptr<content::PowerSaveBlocker> power_save_blocker_;
|
||||
std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
|
||||
|
||||
// Currnet blocker type used by |power_save_blocker_|
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType current_blocker_type_;
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType current_blocker_type_;
|
||||
|
||||
// Map from id to the corresponding blocker type for each request.
|
||||
using PowerSaveBlockerTypeMap =
|
||||
std::map<int, content::PowerSaveBlocker::PowerSaveBlockerType>;
|
||||
std::map<int, device::PowerSaveBlocker::PowerSaveBlockerType>;
|
||||
PowerSaveBlockerTypeMap power_save_blocker_types_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PowerSaveBlocker);
|
||||
|
||||
@@ -46,7 +46,8 @@ std::vector<std::string> GetStandardSchemes() {
|
||||
return g_standard_schemes;
|
||||
}
|
||||
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes) {
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args) {
|
||||
g_standard_schemes = schemes;
|
||||
|
||||
auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
|
||||
@@ -55,8 +56,17 @@ void RegisterStandardSchemes(const std::vector<std::string>& schemes) {
|
||||
policy->RegisterWebSafeScheme(scheme);
|
||||
}
|
||||
|
||||
// add switches to register as standard
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kStandardSchemes, base::JoinString(schemes, ","));
|
||||
|
||||
mate::Dictionary opts;
|
||||
bool secure = false;
|
||||
if (args->GetNext(&opts) && opts.Get("secure", &secure) && secure) {
|
||||
// add switches to register as secure
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kSecureSchemes, base::JoinString(schemes, ","));
|
||||
}
|
||||
}
|
||||
|
||||
Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
@@ -220,7 +230,7 @@ void RegisterStandardSchemes(
|
||||
return;
|
||||
}
|
||||
|
||||
atom::api::RegisterStandardSchemes(schemes);
|
||||
atom::api::RegisterStandardSchemes(schemes, args);
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
|
||||
@@ -29,7 +29,8 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
std::vector<std::string> GetStandardSchemes();
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes);
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args);
|
||||
|
||||
class Protocol : public mate::TrackableObject<Protocol> {
|
||||
public:
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
@@ -97,7 +97,7 @@ v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate,
|
||||
"Cannot initialize \"screen\" module before app is ready")));
|
||||
"Cannot require \"screen\" module before app is ready")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,13 @@
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/threading/thread_task_runner_handle.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/common/pref_names.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/download_manager_delegate.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
@@ -49,6 +51,7 @@
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
using atom::api::Cookies;
|
||||
using content::BrowserThread;
|
||||
using content::StoragePartition;
|
||||
|
||||
@@ -60,6 +63,15 @@ struct ClearStorageDataOptions {
|
||||
uint32_t quota_types = StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
|
||||
};
|
||||
|
||||
struct ClearAuthCacheOptions {
|
||||
std::string type;
|
||||
GURL origin;
|
||||
std::string realm;
|
||||
base::string16 username;
|
||||
base::string16 password;
|
||||
net::HttpAuth::Scheme auth_scheme;
|
||||
};
|
||||
|
||||
uint32_t GetStorageMask(const std::vector<std::string>& storage_types) {
|
||||
uint32_t storage_mask = 0;
|
||||
for (const auto& it : storage_types) {
|
||||
@@ -98,6 +110,18 @@ uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
|
||||
return quota_mask;
|
||||
}
|
||||
|
||||
net::HttpAuth::Scheme GetAuthSchemeFromString(const std::string& scheme) {
|
||||
if (scheme == "basic")
|
||||
return net::HttpAuth::AUTH_SCHEME_BASIC;
|
||||
if (scheme == "digest")
|
||||
return net::HttpAuth::AUTH_SCHEME_DIGEST;
|
||||
if (scheme == "ntlm")
|
||||
return net::HttpAuth::AUTH_SCHEME_NTLM;
|
||||
if (scheme == "negotiate")
|
||||
return net::HttpAuth::AUTH_SCHEME_NEGOTIATE;
|
||||
return net::HttpAuth::AUTH_SCHEME_MAX;
|
||||
}
|
||||
|
||||
void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const std::string& accept_lang,
|
||||
const std::string& user_agent) {
|
||||
@@ -129,7 +153,27 @@ struct Converter<ClearStorageDataOptions> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<ClearAuthCacheOptions> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
ClearAuthCacheOptions* out) {
|
||||
mate::Dictionary options;
|
||||
if (!ConvertFromV8(isolate, val, &options))
|
||||
return false;
|
||||
options.Get("type", &out->type);
|
||||
options.Get("origin", &out->origin);
|
||||
options.Get("realm", &out->realm);
|
||||
options.Get("username", &out->username);
|
||||
options.Get("password", &out->password);
|
||||
std::string scheme;
|
||||
if (options.Get("scheme", &scheme))
|
||||
out->auth_scheme = GetAuthSchemeFromString(scheme);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<net::ProxyConfig> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
@@ -312,6 +356,33 @@ void ClearHostResolverCacheInIO(
|
||||
}
|
||||
}
|
||||
|
||||
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 =
|
||||
request_context->http_transaction_factory()->GetSession();
|
||||
if (network_session) {
|
||||
if (options.type == "password") {
|
||||
auto auth_cache = network_session->http_auth_cache();
|
||||
if (!options.origin.is_empty()) {
|
||||
auth_cache->Remove(
|
||||
options.origin, options.realm, options.auth_scheme,
|
||||
net::AuthCredentials(options.username, options.password));
|
||||
} else {
|
||||
auth_cache->Clear();
|
||||
}
|
||||
} else if (options.type == "clientCertificate") {
|
||||
auto client_auth_cache = network_session->ssl_client_auth_cache();
|
||||
client_auth_cache->Remove(net::HostPortPair::FromURL(options.origin));
|
||||
}
|
||||
network_session->CloseAllConnections();
|
||||
}
|
||||
if (!callback.is_null())
|
||||
RunCallbackInUI(callback);
|
||||
}
|
||||
|
||||
void AllowNTLMCredentialsForDomainsInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
const std::string& domains) {
|
||||
@@ -330,12 +401,31 @@ void OnClearStorageDataDone(const base::Closure& callback) {
|
||||
callback.Run();
|
||||
}
|
||||
|
||||
void DownloadIdCallback(content::DownloadManager* download_manager,
|
||||
const base::FilePath& path,
|
||||
const std::vector<GURL>& url_chain,
|
||||
const std::string& mime_type,
|
||||
int64_t offset,
|
||||
int64_t length,
|
||||
const std::string& last_modified,
|
||||
const std::string& etag,
|
||||
const base::Time& start_time,
|
||||
uint32_t id) {
|
||||
download_manager->CreateDownloadItem(
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: devtools_network_emulation_client_id_(base::GenerateGUID()),
|
||||
browser_context_(browser_context) {
|
||||
// Observe DownloadManger to get download notifications.
|
||||
// Observe DownloadManager to get download notifications.
|
||||
content::BrowserContext::GetDownloadManager(browser_context)->
|
||||
AddObserver(this);
|
||||
|
||||
@@ -356,10 +446,10 @@ void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
bool prevent_default = Emit(
|
||||
"will-download",
|
||||
DownloadItem::Create(isolate(), item),
|
||||
item->GetWebContents());
|
||||
auto handle = DownloadItem::Create(isolate(), item);
|
||||
if (item->GetState() == content::DownloadItem::INTERRUPTED)
|
||||
handle->SetSavePath(item->GetTargetFilePath());
|
||||
bool prevent_default = Emit("will-download", handle, item->GetWebContents());
|
||||
if (prevent_default) {
|
||||
item->Cancel(true);
|
||||
item->Remove();
|
||||
@@ -388,6 +478,11 @@ void Session::ClearStorageData(mate::Arguments* args) {
|
||||
|
||||
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.
|
||||
// https://w3c.github.io/mediacapture-main/#dom-mediadeviceinfo-deviceid
|
||||
brightray::MediaDeviceIDSalt::Reset(browser_context()->prefs());
|
||||
}
|
||||
storage_partition->ClearData(
|
||||
options.storage_types, options.quota_types, options.origin,
|
||||
content::StoragePartition::OriginMatcherFunction(),
|
||||
@@ -480,6 +575,22 @@ void Session::ClearHostResolverCache(mate::Arguments* args) {
|
||||
callback));
|
||||
}
|
||||
|
||||
void Session::ClearAuthCache(mate::Arguments* args) {
|
||||
ClearAuthCacheOptions options;
|
||||
if (!args->GetNext(&options)) {
|
||||
args->ThrowError("Must specify options object");
|
||||
return;
|
||||
}
|
||||
base::Closure callback;
|
||||
args->GetNext(&callback);
|
||||
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&ClearAuthCacheInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
options, callback));
|
||||
}
|
||||
|
||||
void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AllowNTLMCredentialsForDomainsInIO,
|
||||
@@ -504,9 +615,55 @@ std::string Session::GetUserAgent() {
|
||||
return browser_context_->GetUserAgent();
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void Session::CreateInterruptedDownload(const mate::Dictionary& options) {
|
||||
int64_t offset = 0, length = 0;
|
||||
double start_time = 0.0;
|
||||
std::string mime_type, last_modified, etag;
|
||||
base::FilePath path;
|
||||
std::vector<GURL> url_chain;
|
||||
options.Get("path", &path);
|
||||
options.Get("urlChain", &url_chain);
|
||||
options.Get("mimeType", &mime_type);
|
||||
options.Get("offset", &offset);
|
||||
options.Get("length", &length);
|
||||
options.Get("lastModified", &last_modified);
|
||||
options.Get("eTag", &etag);
|
||||
options.Get("startTime", &start_time);
|
||||
if (path.empty() || url_chain.empty() || length == 0) {
|
||||
isolate()->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate(), "Must pass non-empty path, urlChain and length.")));
|
||||
return;
|
||||
}
|
||||
if (offset >= length) {
|
||||
isolate()->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate(), "Must pass an offset value less than length.")));
|
||||
return;
|
||||
}
|
||||
auto download_manager =
|
||||
content::BrowserContext::GetDownloadManager(browser_context());
|
||||
download_manager->GetDelegate()->GetNextId(base::Bind(
|
||||
&DownloadIdCallback, download_manager, path, url_chain, mime_type, offset,
|
||||
length, last_modified, etag, base::Time::FromDoubleT(start_time)));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
|
||||
if (cookies_.IsEmpty()) {
|
||||
auto handle = atom::api::Cookies::Create(isolate, browser_context());
|
||||
auto handle = Cookies::Create(isolate, browser_context());
|
||||
cookies_.Reset(isolate, handle.ToV8());
|
||||
}
|
||||
return v8::Local<v8::Value>::New(isolate, cookies_);
|
||||
@@ -582,10 +739,14 @@ void Session::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setPermissionRequestHandler",
|
||||
&Session::SetPermissionRequestHandler)
|
||||
.SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
|
||||
.SetMethod("clearAuthCache", &Session::ClearAuthCache)
|
||||
.SetMethod("allowNTLMCredentialsForDomains",
|
||||
&Session::AllowNTLMCredentialsForDomains)
|
||||
.SetMethod("setUserAgent", &Session::SetUserAgent)
|
||||
.SetMethod("getUserAgent", &Session::GetUserAgent)
|
||||
.SetMethod("getBlobData", &Session::GetBlobData)
|
||||
.SetMethod("createInterruptedDownload",
|
||||
&Session::CreateInterruptedDownload)
|
||||
.SetProperty("cookies", &Session::Cookies)
|
||||
.SetProperty("protocol", &Session::Protocol)
|
||||
.SetProperty("webRequest", &Session::WebRequest);
|
||||
@@ -615,6 +776,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("Session", Session::GetConstructor(isolate)->GetFunction());
|
||||
dict.Set("Cookies", Cookies::GetConstructor(isolate)->GetFunction());
|
||||
dict.SetMethod("fromPartition", &FromPartition);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/atom_blob_reader.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
#include "native_mate/handle.h"
|
||||
@@ -73,9 +74,13 @@ class Session: public mate::TrackableObject<Session>,
|
||||
void SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args);
|
||||
void ClearHostResolverCache(mate::Arguments* args);
|
||||
void ClearAuthCache(mate::Arguments* args);
|
||||
void AllowNTLMCredentialsForDomains(const std::string& domains);
|
||||
void SetUserAgent(const std::string& user_agent, mate::Arguments* args);
|
||||
std::string GetUserAgent();
|
||||
void GetBlobData(const std::string& uuid,
|
||||
const AtomBlobReader::CompletionCallback& callback);
|
||||
void CreateInterruptedDownload(const mate::Dictionary& options);
|
||||
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
|
||||
|
||||
@@ -8,34 +8,36 @@
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/base/win/shell.h"
|
||||
#endif
|
||||
#include "ui/gfx/color_utils.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
SystemPreferences::SystemPreferences(v8::Isolate* isolate) {
|
||||
SystemPreferences::SystemPreferences(v8::Isolate* isolate)
|
||||
#if defined(OS_WIN)
|
||||
: color_change_listener_(this)
|
||||
#endif
|
||||
{
|
||||
Init(isolate);
|
||||
#if defined(OS_WIN)
|
||||
InitializeWindow();
|
||||
#endif
|
||||
}
|
||||
|
||||
SystemPreferences::~SystemPreferences() {
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
bool SystemPreferences::IsAeroGlassEnabled() {
|
||||
return ui::win::IsAeroGlassEnabled();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
bool SystemPreferences::IsDarkMode() {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SystemPreferences::IsInvertedColorScheme() {
|
||||
return color_utils::IsInvertedColorScheme();
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<SystemPreferences> SystemPreferences::Create(
|
||||
v8::Isolate* isolate) {
|
||||
@@ -48,7 +50,9 @@ void SystemPreferences::BuildPrototype(
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "SystemPreferences"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("getAccentColor", &SystemPreferences::GetAccentColor)
|
||||
.SetMethod("isAeroGlassEnabled", &SystemPreferences::IsAeroGlassEnabled)
|
||||
.SetMethod("getColor", &SystemPreferences::GetColor)
|
||||
#elif defined(OS_MACOSX)
|
||||
.SetMethod("postNotification",
|
||||
&SystemPreferences::PostNotification)
|
||||
@@ -63,9 +67,12 @@ void SystemPreferences::BuildPrototype(
|
||||
.SetMethod("unsubscribeLocalNotification",
|
||||
&SystemPreferences::UnsubscribeLocalNotification)
|
||||
.SetMethod("getUserDefault", &SystemPreferences::GetUserDefault)
|
||||
.SetMethod("setUserDefault", &SystemPreferences::SetUserDefault)
|
||||
.SetMethod("isSwipeTrackingFromScrollEventsEnabled",
|
||||
&SystemPreferences::IsSwipeTrackingFromScrollEventsEnabled)
|
||||
#endif
|
||||
.SetMethod("isInvertedColorScheme",
|
||||
&SystemPreferences::IsInvertedColorScheme)
|
||||
.SetMethod("isDarkMode", &SystemPreferences::IsDarkMode);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
#include "base/values.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/gfx/sys_color_change_listener.h"
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
}
|
||||
@@ -20,7 +24,11 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
|
||||
class SystemPreferences : public mate::EventEmitter<SystemPreferences>
|
||||
#if defined(OS_WIN)
|
||||
, public gfx::SysColorChangeListener
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
static mate::Handle<SystemPreferences> Create(v8::Isolate* isolate);
|
||||
|
||||
@@ -29,6 +37,20 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
bool IsAeroGlassEnabled();
|
||||
|
||||
typedef HRESULT (STDAPICALLTYPE *DwmGetColorizationColor)(DWORD *, BOOL *);
|
||||
DwmGetColorizationColor dwmGetColorizationColor =
|
||||
(DwmGetColorizationColor) GetProcAddress(LoadLibraryW(L"dwmapi.dll"),
|
||||
"DwmGetColorizationColor");
|
||||
|
||||
std::string GetAccentColor();
|
||||
std::string GetColor(const std::string& color, mate::Arguments* args);
|
||||
|
||||
void InitializeWindow();
|
||||
|
||||
// gfx::SysColorChangeListener:
|
||||
void OnSysColorChange() override;
|
||||
|
||||
#elif defined(OS_MACOSX)
|
||||
using NotificationCallback = base::Callback<
|
||||
void(const std::string&, const base::DictionaryValue&)>;
|
||||
@@ -45,9 +67,13 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
|
||||
void UnsubscribeLocalNotification(int request_id);
|
||||
v8::Local<v8::Value> GetUserDefault(const std::string& name,
|
||||
const std::string& type);
|
||||
void SetUserDefault(const std::string& name,
|
||||
const std::string& type,
|
||||
mate::Arguments* args);
|
||||
bool IsSwipeTrackingFromScrollEventsEnabled();
|
||||
#endif
|
||||
bool IsDarkMode();
|
||||
bool IsInvertedColorScheme();
|
||||
|
||||
protected:
|
||||
explicit SystemPreferences(v8::Isolate* isolate);
|
||||
@@ -64,6 +90,29 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
|
||||
#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);
|
||||
|
||||
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_;
|
||||
|
||||
std::string current_color_;
|
||||
|
||||
bool invertered_color_scheme_;
|
||||
|
||||
gfx::ScopedSysColorChangeListener color_change_listener_;
|
||||
#endif
|
||||
DISALLOW_COPY_AND_ASSIGN(SystemPreferences);
|
||||
};
|
||||
|
||||
|
||||
@@ -28,17 +28,17 @@ 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,
|
||||
void SystemPreferences::PostLocalNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info) {
|
||||
DoPostNotification(name, user_info, true);
|
||||
}
|
||||
|
||||
void SystemPreferences::DoPostNotification(const std::string& name,
|
||||
void SystemPreferences::DoPostNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info, bool is_local) {
|
||||
NSNotificationCenter* center = is_local ?
|
||||
[NSNotificationCenter defaultCenter] :
|
||||
@@ -128,16 +128,107 @@ v8::Local<v8::Value> SystemPreferences::GetUserDefault(
|
||||
return mate::ConvertToV8(isolate(),
|
||||
net::GURLWithNSURL([defaults URLForKey:key]));
|
||||
} else if (type == "array") {
|
||||
return mate::ConvertToV8(isolate(),
|
||||
*NSArrayToListValue([defaults arrayForKey:key]));
|
||||
std::unique_ptr<base::ListValue> list =
|
||||
NSArrayToListValue([defaults arrayForKey:key]);
|
||||
if (list == nullptr)
|
||||
list.reset(new base::ListValue());
|
||||
return mate::ConvertToV8(isolate(), *list);
|
||||
} else if (type == "dictionary") {
|
||||
return mate::ConvertToV8(isolate(),
|
||||
*NSDictionaryToDictionaryValue([defaults dictionaryForKey:key]));
|
||||
std::unique_ptr<base::DictionaryValue> dictionary =
|
||||
NSDictionaryToDictionaryValue([defaults dictionaryForKey:key]);
|
||||
if (dictionary == nullptr)
|
||||
dictionary.reset(new base::DictionaryValue());
|
||||
return mate::ConvertToV8(isolate(), *dictionary);
|
||||
} else {
|
||||
return v8::Undefined(isolate());
|
||||
}
|
||||
}
|
||||
|
||||
void SystemPreferences::SetUserDefault(const std::string& name,
|
||||
const std::string& type,
|
||||
mate::Arguments* args) {
|
||||
const auto throwConversionError = [&] {
|
||||
args->ThrowError("Unable to convert value to: " + type);
|
||||
};
|
||||
|
||||
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSString* key = base::SysUTF8ToNSString(name);
|
||||
if (type == "string") {
|
||||
std::string value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
[defaults setObject:base::SysUTF8ToNSString(value) forKey:key];
|
||||
} else if (type == "boolean") {
|
||||
bool value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
[defaults setBool:value forKey:key];
|
||||
} else if (type == "float") {
|
||||
float value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
[defaults setFloat:value forKey:key];
|
||||
} else if (type == "integer") {
|
||||
int value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
[defaults setInteger:value forKey:key];
|
||||
} else if (type == "double") {
|
||||
double value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
[defaults setDouble:value forKey:key];
|
||||
} else if (type == "url") {
|
||||
GURL value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (NSURL* url = net::NSURLWithGURL(value)) {
|
||||
[defaults setURL:url forKey:key];
|
||||
}
|
||||
} else if (type == "array") {
|
||||
base::ListValue value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (NSArray* array = ListValueToNSArray(value)) {
|
||||
[defaults setObject:array forKey:key];
|
||||
}
|
||||
} else if (type == "dictionary") {
|
||||
base::DictionaryValue value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (NSDictionary* dict = DictionaryValueToNSDictionary(value)) {
|
||||
[defaults setObject:dict forKey:key];
|
||||
}
|
||||
} else {
|
||||
args->ThrowError("Invalid type: " + type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool SystemPreferences::IsDarkMode() {
|
||||
NSString* mode = [[NSUserDefaults standardUserDefaults]
|
||||
stringForKey:@"AppleInterfaceStyle"];
|
||||
|
||||
177
atom/browser/api/atom_api_system_preferences_win.cc
Normal file
177
atom/browser/api/atom_api_system_preferences_win.cc
Normal file
@@ -0,0 +1,177 @@
|
||||
// Copyright (c) 2014 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_system_preferences.h"
|
||||
|
||||
#include "atom/common/color_util.h"
|
||||
#include "base/win/wrapped_window_proc.h"
|
||||
#include "ui/base/win/shell.h"
|
||||
#include "ui/gfx/color_utils.h"
|
||||
#include "ui/gfx/win/hwnd_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const wchar_t kSystemPreferencesWindowClass[] =
|
||||
L"Electron_SystemPreferencesHostWindow";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace api {
|
||||
|
||||
bool SystemPreferences::IsAeroGlassEnabled() {
|
||||
return ui::win::IsAeroGlassEnabled();
|
||||
}
|
||||
|
||||
std::string hexColorDWORDToRGBA(DWORD color) {
|
||||
std::ostringstream stream;
|
||||
stream << std::hex << color;
|
||||
std::string hexColor = stream.str();
|
||||
return hexColor.substr(2) + hexColor.substr(0, 2);
|
||||
}
|
||||
|
||||
std::string SystemPreferences::GetAccentColor() {
|
||||
DWORD color = 0;
|
||||
BOOL opaque = FALSE;
|
||||
|
||||
if (FAILED(dwmGetColorizationColor(&color, &opaque))) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return hexColorDWORDToRGBA(color);
|
||||
}
|
||||
|
||||
std::string SystemPreferences::GetColor(const std::string& color,
|
||||
mate::Arguments* args) {
|
||||
int id;
|
||||
if (color == "3d-dark-shadow") {
|
||||
id = COLOR_3DDKSHADOW;
|
||||
} else if (color == "3d-face") {
|
||||
id = COLOR_3DFACE;
|
||||
} else if (color == "3d-highlight") {
|
||||
id = COLOR_3DHIGHLIGHT;
|
||||
} else if (color == "3d-light") {
|
||||
id = COLOR_3DLIGHT;
|
||||
} else if (color == "3d-shadow") {
|
||||
id = COLOR_3DSHADOW;
|
||||
} else if (color == "active-border") {
|
||||
id = COLOR_ACTIVEBORDER;
|
||||
} else if (color == "active-caption") {
|
||||
id = COLOR_ACTIVECAPTION;
|
||||
} else if (color == "active-caption-gradient") {
|
||||
id = COLOR_GRADIENTACTIVECAPTION;
|
||||
} else if (color == "app-workspace") {
|
||||
id = COLOR_APPWORKSPACE;
|
||||
} else if (color == "button-text") {
|
||||
id = COLOR_BTNTEXT;
|
||||
} else if (color == "caption-text") {
|
||||
id = COLOR_CAPTIONTEXT;
|
||||
} else if (color == "desktop") {
|
||||
id = COLOR_DESKTOP;
|
||||
} else if (color == "disabled-text") {
|
||||
id = COLOR_GRAYTEXT;
|
||||
} else if (color == "highlight") {
|
||||
id = COLOR_HIGHLIGHT;
|
||||
} else if (color == "highlight-text") {
|
||||
id = COLOR_HIGHLIGHTTEXT;
|
||||
} else if (color == "hotlight") {
|
||||
id = COLOR_HOTLIGHT;
|
||||
} else if (color == "inactive-border") {
|
||||
id = COLOR_INACTIVEBORDER;
|
||||
} else if (color == "inactive-caption") {
|
||||
id = COLOR_INACTIVECAPTION;
|
||||
} else if (color == "inactive-caption-gradient") {
|
||||
id = COLOR_GRADIENTINACTIVECAPTION;
|
||||
} else if (color == "inactive-caption-text") {
|
||||
id = COLOR_INACTIVECAPTIONTEXT;
|
||||
} else if (color == "info-background") {
|
||||
id = COLOR_INFOBK;
|
||||
} else if (color == "info-text") {
|
||||
id = COLOR_INFOTEXT;
|
||||
} else if (color == "menu") {
|
||||
id = COLOR_MENU;
|
||||
} else if (color == "menu-highlight") {
|
||||
id = COLOR_MENUHILIGHT;
|
||||
} else if (color == "menubar") {
|
||||
id = COLOR_MENUBAR;
|
||||
} else if (color == "menu-text") {
|
||||
id = COLOR_MENUTEXT;
|
||||
} else if (color == "scrollbar") {
|
||||
id = COLOR_SCROLLBAR;
|
||||
} else if (color == "window") {
|
||||
id = COLOR_WINDOW;
|
||||
} else if (color == "window-frame") {
|
||||
id = COLOR_WINDOWFRAME;
|
||||
} else if (color == "window-text") {
|
||||
id = COLOR_WINDOWTEXT;
|
||||
} else {
|
||||
args->ThrowError("Unknown color: " + color);
|
||||
return "";
|
||||
}
|
||||
|
||||
return ToRGBHex(color_utils::GetSysSkColor(id));
|
||||
}
|
||||
|
||||
void SystemPreferences::InitializeWindow() {
|
||||
invertered_color_scheme_ = IsInvertedColorScheme();
|
||||
|
||||
WNDCLASSEX window_class;
|
||||
base::win::InitializeWindowClass(
|
||||
kSystemPreferencesWindowClass,
|
||||
&base::win::WrappedWindowProc<SystemPreferences::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 system
|
||||
// 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);
|
||||
gfx::CheckWindowCreated(window_);
|
||||
gfx::SetWindowUserData(window_, this);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK SystemPreferences::WndProcStatic(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
SystemPreferences* msg_wnd = reinterpret_cast<SystemPreferences*>(
|
||||
GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (msg_wnd)
|
||||
return msg_wnd->WndProc(hwnd, message, wparam, lparam);
|
||||
else
|
||||
return ::DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK SystemPreferences::WndProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
if (message == WM_DWMCOLORIZATIONCOLORCHANGED) {
|
||||
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));
|
||||
current_color_ = new_color_string;
|
||||
}
|
||||
}
|
||||
return ::DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
void SystemPreferences::OnSysColorChange() {
|
||||
bool new_invertered_color_scheme = IsInvertedColorScheme();
|
||||
if (new_invertered_color_scheme != invertered_color_scheme_) {
|
||||
invertered_color_scheme_ = new_invertered_color_scheme;
|
||||
Emit("inverted-color-scheme-changed", new_invertered_color_scheme);
|
||||
}
|
||||
Emit("color-changed");
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
448
atom/browser/api/atom_api_url_request.cc
Normal file
448
atom/browser/api/atom_api_url_request.cc
Normal file
@@ -0,0 +1,448 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_url_request.h"
|
||||
#include <string>
|
||||
#include "atom/browser/api/atom_api_session.h"
|
||||
#include "atom/browser/net/atom_url_request.h"
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<scoped_refptr<const net::IOBufferWithSize>> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
scoped_refptr<const net::IOBufferWithSize> buffer) {
|
||||
return node::Buffer::Copy(isolate, buffer->data(), buffer->size())
|
||||
.ToLocalChecked();
|
||||
}
|
||||
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
scoped_refptr<const net::IOBufferWithSize>* out) {
|
||||
auto size = node::Buffer::Length(val);
|
||||
|
||||
if (size == 0) {
|
||||
// Support conversion from empty buffer. A use case is
|
||||
// a GET request without body.
|
||||
// Since zero-sized IOBuffer(s) are not supported, we set the
|
||||
// out pointer to null.
|
||||
*out = nullptr;
|
||||
return true;
|
||||
}
|
||||
auto data = node::Buffer::Data(val);
|
||||
if (!data) {
|
||||
// This is an error as size is positive but data is null.
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = new net::IOBufferWithSize(size);
|
||||
// We do a deep copy. We could have used Buffer's internal memory
|
||||
// but that is much more complicated to be properly handled.
|
||||
memcpy((*out)->data(), data, size);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
namespace api {
|
||||
|
||||
template <typename Flags>
|
||||
URLRequest::StateBase<Flags>::StateBase(Flags initialState)
|
||||
: state_(initialState) {}
|
||||
|
||||
template <typename Flags>
|
||||
void URLRequest::StateBase<Flags>::SetFlag(Flags flag) {
|
||||
state_ =
|
||||
static_cast<Flags>(static_cast<int>(state_) | static_cast<int>(flag));
|
||||
}
|
||||
|
||||
template <typename Flags>
|
||||
bool URLRequest::StateBase<Flags>::operator==(Flags flag) const {
|
||||
return state_ == flag;
|
||||
}
|
||||
|
||||
template <typename Flags>
|
||||
bool URLRequest::StateBase<Flags>::IsFlagSet(Flags flag) const {
|
||||
return static_cast<int>(state_) & static_cast<int>(flag);
|
||||
}
|
||||
|
||||
URLRequest::RequestState::RequestState()
|
||||
: StateBase(RequestStateFlags::kNotStarted) {}
|
||||
|
||||
bool URLRequest::RequestState::NotStarted() const {
|
||||
return *this == RequestStateFlags::kNotStarted;
|
||||
}
|
||||
|
||||
bool URLRequest::RequestState::Started() const {
|
||||
return IsFlagSet(RequestStateFlags::kStarted);
|
||||
}
|
||||
|
||||
bool URLRequest::RequestState::Finished() const {
|
||||
return IsFlagSet(RequestStateFlags::kFinished);
|
||||
}
|
||||
|
||||
bool URLRequest::RequestState::Canceled() const {
|
||||
return IsFlagSet(RequestStateFlags::kCanceled);
|
||||
}
|
||||
|
||||
bool URLRequest::RequestState::Failed() const {
|
||||
return IsFlagSet(RequestStateFlags::kFailed);
|
||||
}
|
||||
|
||||
bool URLRequest::RequestState::Closed() const {
|
||||
return IsFlagSet(RequestStateFlags::kClosed);
|
||||
}
|
||||
|
||||
URLRequest::ResponseState::ResponseState()
|
||||
: StateBase(ResponseStateFlags::kNotStarted) {}
|
||||
|
||||
bool URLRequest::ResponseState::NotStarted() const {
|
||||
return *this == ResponseStateFlags::kNotStarted;
|
||||
}
|
||||
|
||||
bool URLRequest::ResponseState::Started() const {
|
||||
return IsFlagSet(ResponseStateFlags::kStarted);
|
||||
}
|
||||
|
||||
bool URLRequest::ResponseState::Ended() const {
|
||||
return IsFlagSet(ResponseStateFlags::kEnded);
|
||||
}
|
||||
|
||||
bool URLRequest::ResponseState::Failed() const {
|
||||
return IsFlagSet(ResponseStateFlags::kFailed);
|
||||
}
|
||||
|
||||
URLRequest::URLRequest(v8::Isolate* isolate, v8::Local<v8::Object> wrapper) {
|
||||
InitWith(isolate, wrapper);
|
||||
}
|
||||
|
||||
URLRequest::~URLRequest() {
|
||||
// A request has been created in JS, it was not used and then
|
||||
// it got collected, no close event to cleanup, only destructor
|
||||
// is called.
|
||||
if (atom_request_) {
|
||||
atom_request_->Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* URLRequest::New(mate::Arguments* args) {
|
||||
auto isolate = args->isolate();
|
||||
v8::Local<v8::Object> options;
|
||||
args->GetNext(&options);
|
||||
mate::Dictionary dict(isolate, options);
|
||||
std::string method;
|
||||
dict.Get("method", &method);
|
||||
std::string url;
|
||||
dict.Get("url", &url);
|
||||
std::string partition;
|
||||
mate::Handle<api::Session> session;
|
||||
if (dict.Get("session", &session)) {
|
||||
} else if (dict.Get("partition", &partition)) {
|
||||
session = Session::FromPartition(isolate, partition);
|
||||
} else {
|
||||
// Use the default session if not specified.
|
||||
session = Session::FromPartition(isolate, "");
|
||||
}
|
||||
auto browser_context = session->browser_context();
|
||||
auto api_url_request = new URLRequest(args->isolate(), args->GetThis());
|
||||
auto atom_url_request =
|
||||
AtomURLRequest::Create(browser_context, method, url, api_url_request);
|
||||
|
||||
api_url_request->atom_request_ = atom_url_request;
|
||||
|
||||
return api_url_request;
|
||||
}
|
||||
|
||||
// static
|
||||
void URLRequest::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "URLRequest"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
// Request API
|
||||
.MakeDestroyable()
|
||||
.SetMethod("write", &URLRequest::Write)
|
||||
.SetMethod("cancel", &URLRequest::Cancel)
|
||||
.SetMethod("setExtraHeader", &URLRequest::SetExtraHeader)
|
||||
.SetMethod("removeExtraHeader", &URLRequest::RemoveExtraHeader)
|
||||
.SetMethod("setChunkedUpload", &URLRequest::SetChunkedUpload)
|
||||
.SetMethod("_setLoadFlags", &URLRequest::SetLoadFlags)
|
||||
.SetProperty("notStarted", &URLRequest::NotStarted)
|
||||
.SetProperty("finished", &URLRequest::Finished)
|
||||
// Response APi
|
||||
.SetProperty("statusCode", &URLRequest::StatusCode)
|
||||
.SetProperty("statusMessage", &URLRequest::StatusMessage)
|
||||
.SetProperty("rawResponseHeaders", &URLRequest::RawResponseHeaders)
|
||||
.SetProperty("httpVersionMajor", &URLRequest::ResponseHttpVersionMajor)
|
||||
.SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor);
|
||||
}
|
||||
|
||||
bool URLRequest::NotStarted() const {
|
||||
return request_state_.NotStarted();
|
||||
}
|
||||
|
||||
bool URLRequest::Finished() const {
|
||||
return request_state_.Finished();
|
||||
}
|
||||
|
||||
bool URLRequest::Canceled() const {
|
||||
return request_state_.Canceled();
|
||||
}
|
||||
|
||||
bool URLRequest::Write(scoped_refptr<const net::IOBufferWithSize> buffer,
|
||||
bool is_last) {
|
||||
if (request_state_.Canceled() || request_state_.Failed() ||
|
||||
request_state_.Finished() || request_state_.Closed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request_state_.NotStarted()) {
|
||||
request_state_.SetFlag(RequestStateFlags::kStarted);
|
||||
// Pin on first write.
|
||||
Pin();
|
||||
}
|
||||
|
||||
if (is_last) {
|
||||
request_state_.SetFlag(RequestStateFlags::kFinished);
|
||||
EmitRequestEvent(true, "finish");
|
||||
}
|
||||
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
return atom_request_->Write(buffer, is_last);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void URLRequest::Cancel() {
|
||||
if (request_state_.Canceled() || request_state_.Closed()) {
|
||||
// Cancel only once.
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark as canceled.
|
||||
request_state_.SetFlag(RequestStateFlags::kCanceled);
|
||||
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_ && request_state_.Started()) {
|
||||
// Really cancel if it was started.
|
||||
atom_request_->Cancel();
|
||||
}
|
||||
EmitRequestEvent(true, "abort");
|
||||
|
||||
if (response_state_.Started() && !response_state_.Ended()) {
|
||||
EmitResponseEvent(true, "aborted");
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
bool URLRequest::SetExtraHeader(const std::string& name,
|
||||
const std::string& value) {
|
||||
// Request state must be in the initial non started state.
|
||||
if (!request_state_.NotStarted()) {
|
||||
// Cannot change headers after send.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!net::HttpUtil::IsValidHeaderName(name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!net::HttpUtil::IsValidHeaderValue(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
atom_request_->SetExtraHeader(name, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void URLRequest::RemoveExtraHeader(const std::string& name) {
|
||||
// State must be equal to not started.
|
||||
if (!request_state_.NotStarted()) {
|
||||
// Cannot change headers after send.
|
||||
return;
|
||||
}
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
atom_request_->RemoveExtraHeader(name);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequest::SetChunkedUpload(bool is_chunked_upload) {
|
||||
// State must be equal to not started.
|
||||
if (!request_state_.NotStarted()) {
|
||||
// Cannot change headers after send.
|
||||
return;
|
||||
}
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
atom_request_->SetChunkedUpload(is_chunked_upload);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequest::SetLoadFlags(int flags) {
|
||||
// State must be equal to not started.
|
||||
if (!request_state_.NotStarted()) {
|
||||
// Cannot change load flags after start.
|
||||
return;
|
||||
}
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
atom_request_->SetLoadFlags(flags);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequest::OnAuthenticationRequired(
|
||||
scoped_refptr<const net::AuthChallengeInfo> auth_info) {
|
||||
if (request_state_.Canceled() || request_state_.Closed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(atom_request_);
|
||||
if (!atom_request_) {
|
||||
return;
|
||||
}
|
||||
|
||||
Emit("login", auth_info.get(),
|
||||
base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_));
|
||||
}
|
||||
|
||||
void URLRequest::OnResponseStarted(
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers) {
|
||||
if (request_state_.Canceled() || request_state_.Failed() ||
|
||||
request_state_.Closed()) {
|
||||
// Don't emit any event after request cancel.
|
||||
return;
|
||||
}
|
||||
response_headers_ = response_headers;
|
||||
response_state_.SetFlag(ResponseStateFlags::kStarted);
|
||||
Emit("response");
|
||||
}
|
||||
|
||||
void URLRequest::OnResponseData(
|
||||
scoped_refptr<const net::IOBufferWithSize> buffer) {
|
||||
if (request_state_.Canceled() || request_state_.Closed() ||
|
||||
request_state_.Failed() || response_state_.Failed()) {
|
||||
// In case we received an unexpected event from Chromium net,
|
||||
// don't emit any data event after request cancel/error/close.
|
||||
return;
|
||||
}
|
||||
if (!buffer || !buffer->data() || !buffer->size()) {
|
||||
return;
|
||||
}
|
||||
Emit("data", buffer);
|
||||
}
|
||||
|
||||
void URLRequest::OnResponseCompleted() {
|
||||
if (request_state_.Canceled() || request_state_.Closed() ||
|
||||
request_state_.Failed() || response_state_.Failed()) {
|
||||
// In case we received an unexpected event from Chromium net,
|
||||
// don't emit any data event after request cancel/error/close.
|
||||
return;
|
||||
}
|
||||
response_state_.SetFlag(ResponseStateFlags::kEnded);
|
||||
Emit("end");
|
||||
Close();
|
||||
}
|
||||
|
||||
void URLRequest::OnError(const std::string& error, bool isRequestError) {
|
||||
auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error));
|
||||
if (isRequestError) {
|
||||
request_state_.SetFlag(RequestStateFlags::kFailed);
|
||||
EmitRequestEvent(false, "error", error_object);
|
||||
} else {
|
||||
response_state_.SetFlag(ResponseStateFlags::kFailed);
|
||||
EmitResponseEvent(false, "error", error_object);
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
int URLRequest::StatusCode() const {
|
||||
if (response_headers_) {
|
||||
return response_headers_->response_code();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string URLRequest::StatusMessage() const {
|
||||
std::string result;
|
||||
if (response_headers_) {
|
||||
result = response_headers_->GetStatusText();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
net::HttpResponseHeaders* URLRequest::RawResponseHeaders() const {
|
||||
return response_headers_.get();
|
||||
}
|
||||
|
||||
uint32_t URLRequest::ResponseHttpVersionMajor() const {
|
||||
if (response_headers_) {
|
||||
return response_headers_->GetHttpVersion().major_value();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t URLRequest::ResponseHttpVersionMinor() const {
|
||||
if (response_headers_) {
|
||||
return response_headers_->GetHttpVersion().minor_value();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void URLRequest::Close() {
|
||||
if (!request_state_.Closed()) {
|
||||
request_state_.SetFlag(RequestStateFlags::kClosed);
|
||||
if (response_state_.Started()) {
|
||||
// Emit a close event if we really have a response object.
|
||||
EmitResponseEvent(true, "close");
|
||||
}
|
||||
EmitRequestEvent(true, "close");
|
||||
}
|
||||
Unpin();
|
||||
if (atom_request_) {
|
||||
// A request has been created in JS, used and then it ended.
|
||||
// We release unneeded net resources.
|
||||
atom_request_->Terminate();
|
||||
}
|
||||
atom_request_ = nullptr;
|
||||
}
|
||||
|
||||
void URLRequest::Pin() {
|
||||
if (wrapper_.IsEmpty()) {
|
||||
wrapper_.Reset(isolate(), GetWrapper());
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequest::Unpin() {
|
||||
wrapper_.Reset();
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void URLRequest::EmitRequestEvent(Args... args) {
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
mate::CustomEmit(isolate(), GetWrapper(), "_emitRequestEvent", args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void URLRequest::EmitResponseEvent(Args... args) {
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
mate::CustomEmit(isolate(), GetWrapper(), "_emitResponseEvent", args...);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
207
atom/browser/api/atom_api_url_request.h
Normal file
207
atom/browser/api/atom_api_url_request.h
Normal file
@@ -0,0 +1,207 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "native_mate/wrappable_base.h"
|
||||
#include "net/base/auth.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
#include "net/http/http_response_headers.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomURLRequest;
|
||||
|
||||
namespace api {
|
||||
|
||||
//
|
||||
// The URLRequest class implements the V8 binding between the JavaScript API
|
||||
// and Chromium native net library. It is responsible for handling HTTP/HTTPS
|
||||
// requests.
|
||||
//
|
||||
// The current class provides only the binding layer. Two other JavaScript
|
||||
// classes (ClientRequest and IncomingMessage) in the net module provide the
|
||||
// final API, including some state management and arguments validation.
|
||||
//
|
||||
// URLRequest's methods fall into two main categories: command and event
|
||||
// methods. They are always executed on the Browser's UI thread.
|
||||
// Command methods are called directly from JavaScript code via the API defined
|
||||
// in BuildPrototype. A command method is generally implemented by forwarding
|
||||
// the call to a corresponding method on AtomURLRequest which does the
|
||||
// synchronization on the Browser IO thread. The latter then calls into Chromium
|
||||
// net library. On the other hand, net library events originate on the IO
|
||||
// thread in AtomURLRequest and are synchronized back on the UI thread, then
|
||||
// forwarded to a corresponding event method in URLRequest and then to
|
||||
// JavaScript via the EmitRequestEvent/EmitResponseEvent helpers.
|
||||
//
|
||||
// URLRequest lifetime management: we followed the Wrapper/Wrappable pattern
|
||||
// defined in native_mate. However, we augment that pattern with a pin/unpin
|
||||
// mechanism. The main reason is that we want the JS API to provide a similar
|
||||
// lifetime guarantees as the XMLHttpRequest.
|
||||
// https://xhr.spec.whatwg.org/#garbage-collection
|
||||
//
|
||||
// The primary motivation is to not garbage collect a URLInstance as long as the
|
||||
// object is emitting network events. For instance, in the following JS code
|
||||
//
|
||||
// (function() {
|
||||
// let request = new URLRequest(...);
|
||||
// request.on('response', (response)=>{
|
||||
// response.on('data', (data) = > {
|
||||
// console.log(data.toString());
|
||||
// });
|
||||
// });
|
||||
// })();
|
||||
//
|
||||
// we still want data to be logged even if the response/request objects are n
|
||||
// more referenced in JavaScript.
|
||||
//
|
||||
// Binding by simply following the native_mate Wrapper/Wrappable pattern will
|
||||
// delete the URLRequest object when the corresponding JS object is collected.
|
||||
// The v8 handle is a private member in WrappableBase and it is always weak,
|
||||
// there is no way to make it strong without changing native_mate.
|
||||
// The solution we implement consists of maintaining some kind of state that
|
||||
// prevents collection of JS wrappers as long as the request is emitting network
|
||||
// events. At initialization, the object is unpinned. When the request starts,
|
||||
// it is pinned. When no more events would be emitted, the object is unpinned
|
||||
// and lifetime is again managed by the standard native mate Wrapper/Wrappable
|
||||
// pattern.
|
||||
//
|
||||
// pin/unpin: are implemented by constructing/reseting a V8 strong persistent
|
||||
// handle.
|
||||
//
|
||||
// The URLRequest/AtmURLRequest interaction could have been implemented in a
|
||||
// single class. However, it implies that the resulting class lifetime will be
|
||||
// managed by two conflicting mechanisms: JavaScript garbage collection and
|
||||
// Chromium reference counting. Reasoning about lifetime issues become much
|
||||
// more complex.
|
||||
//
|
||||
// We chose to split the implementation into two classes linked via a
|
||||
// reference counted/raw pointers. A URLRequest instance is deleted if it is
|
||||
// unpinned and the corresponding JS wrapper object is garbage collected. On the
|
||||
// other hand, an AtmURLRequest instance lifetime is totally governed by
|
||||
// reference counting.
|
||||
//
|
||||
class URLRequest : public mate::EventEmitter<URLRequest> {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Methods for reporting events into JavaScript.
|
||||
void OnAuthenticationRequired(
|
||||
scoped_refptr<const net::AuthChallengeInfo> auth_info);
|
||||
void OnResponseStarted(
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers);
|
||||
void OnResponseData(scoped_refptr<const net::IOBufferWithSize> data);
|
||||
void OnResponseCompleted();
|
||||
void OnError(const std::string& error, bool isRequestError);
|
||||
|
||||
protected:
|
||||
explicit URLRequest(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
~URLRequest() override;
|
||||
|
||||
private:
|
||||
template <typename Flags>
|
||||
class StateBase {
|
||||
public:
|
||||
void SetFlag(Flags flag);
|
||||
|
||||
protected:
|
||||
explicit StateBase(Flags initialState);
|
||||
bool operator==(Flags flag) const;
|
||||
bool IsFlagSet(Flags flag) const;
|
||||
|
||||
private:
|
||||
Flags state_;
|
||||
};
|
||||
|
||||
enum class RequestStateFlags {
|
||||
kNotStarted = 0x0,
|
||||
kStarted = 0x1,
|
||||
kFinished = 0x2,
|
||||
kCanceled = 0x4,
|
||||
kFailed = 0x8,
|
||||
kClosed = 0x10
|
||||
};
|
||||
|
||||
class RequestState : public StateBase<RequestStateFlags> {
|
||||
public:
|
||||
RequestState();
|
||||
bool NotStarted() const;
|
||||
bool Started() const;
|
||||
bool Finished() const;
|
||||
bool Canceled() const;
|
||||
bool Failed() const;
|
||||
bool Closed() const;
|
||||
};
|
||||
|
||||
enum class ResponseStateFlags {
|
||||
kNotStarted = 0x0,
|
||||
kStarted = 0x1,
|
||||
kEnded = 0x2,
|
||||
kFailed = 0x4
|
||||
};
|
||||
|
||||
class ResponseState : public StateBase<ResponseStateFlags> {
|
||||
public:
|
||||
ResponseState();
|
||||
bool NotStarted() const;
|
||||
bool Started() const;
|
||||
bool Ended() const;
|
||||
bool Canceled() const;
|
||||
bool Failed() const;
|
||||
bool Closed() const;
|
||||
};
|
||||
|
||||
bool NotStarted() const;
|
||||
bool Finished() const;
|
||||
bool Canceled() const;
|
||||
bool Failed() const;
|
||||
bool Write(scoped_refptr<const net::IOBufferWithSize> buffer, bool is_last);
|
||||
void Cancel();
|
||||
bool SetExtraHeader(const std::string& name, const std::string& value);
|
||||
void RemoveExtraHeader(const std::string& name);
|
||||
void SetChunkedUpload(bool is_chunked_upload);
|
||||
void SetLoadFlags(int flags);
|
||||
|
||||
int StatusCode() const;
|
||||
std::string StatusMessage() const;
|
||||
net::HttpResponseHeaders* RawResponseHeaders() const;
|
||||
uint32_t ResponseHttpVersionMajor() const;
|
||||
uint32_t ResponseHttpVersionMinor() const;
|
||||
|
||||
void Close();
|
||||
void Pin();
|
||||
void Unpin();
|
||||
template <typename... Args>
|
||||
void EmitRequestEvent(Args... args);
|
||||
template <typename... Args>
|
||||
void EmitResponseEvent(Args... args);
|
||||
|
||||
scoped_refptr<AtomURLRequest> atom_request_;
|
||||
RequestState request_state_;
|
||||
ResponseState response_state_;
|
||||
|
||||
// Used to implement pin/unpin.
|
||||
v8::Global<v8::Object> wrapper_;
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(URLRequest);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_
|
||||
@@ -35,11 +35,10 @@
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#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/string16_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
@@ -67,7 +66,6 @@
|
||||
#include "content/public/common/context_menu_params.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/http/http_response_headers.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "third_party/WebKit/public/web/WebFindOptions.h"
|
||||
#include "third_party/WebKit/public/web/WebInputEvent.h"
|
||||
@@ -77,6 +75,8 @@
|
||||
#include "ui/aura/window.h"
|
||||
#endif
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct PrintSettings {
|
||||
@@ -133,38 +133,13 @@ struct Converter<WindowOpenDisposition> {
|
||||
case NEW_FOREGROUND_TAB: disposition = "foreground-tab"; break;
|
||||
case NEW_BACKGROUND_TAB: disposition = "background-tab"; break;
|
||||
case NEW_POPUP: case NEW_WINDOW: disposition = "new-window"; break;
|
||||
case SAVE_TO_DISK: disposition = "save-to-disk"; break;
|
||||
default: break;
|
||||
}
|
||||
return mate::ConvertToV8(isolate, disposition);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<net::HttpResponseHeaders*> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
net::HttpResponseHeaders* headers) {
|
||||
base::DictionaryValue response_headers;
|
||||
if (headers) {
|
||||
size_t iter = 0;
|
||||
std::string key;
|
||||
std::string value;
|
||||
while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
|
||||
key = base::ToLowerASCII(key);
|
||||
if (response_headers.HasKey(key)) {
|
||||
base::ListValue* values = nullptr;
|
||||
if (response_headers.GetList(key, &values))
|
||||
values->AppendString(value);
|
||||
} else {
|
||||
std::unique_ptr<base::ListValue> values(new base::ListValue());
|
||||
values->AppendString(value);
|
||||
response_headers.Set(key, std::move(values));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ConvertToV8(isolate, response_headers);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<content::SavePageType> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
@@ -256,17 +231,25 @@ void OnCapturePageDone(base::Callback<void(const gfx::Image&)> callback,
|
||||
} // namespace
|
||||
|
||||
WebContents::WebContents(v8::Isolate* isolate,
|
||||
content::WebContents* web_contents)
|
||||
content::WebContents* web_contents,
|
||||
Type type)
|
||||
: content::WebContentsObserver(web_contents),
|
||||
embedder_(nullptr),
|
||||
type_(REMOTE),
|
||||
type_(type),
|
||||
request_id_(0),
|
||||
background_throttling_(true),
|
||||
enable_devtools_(true) {
|
||||
web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent());
|
||||
|
||||
Init(isolate);
|
||||
AttachAsUserData(web_contents);
|
||||
if (type == REMOTE) {
|
||||
web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent());
|
||||
Init(isolate);
|
||||
AttachAsUserData(web_contents);
|
||||
} else {
|
||||
const mate::Dictionary options = mate::Dictionary::CreateEmpty(isolate);
|
||||
auto session = Session::CreateFrom(isolate, GetBrowserContext());
|
||||
session_.Reset(isolate, session.ToV8());
|
||||
InitWithSessionAndOptions(isolate, web_contents, session, options);
|
||||
}
|
||||
}
|
||||
|
||||
WebContents::WebContents(v8::Isolate* isolate,
|
||||
@@ -334,6 +317,13 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
web_contents = content::WebContents::Create(params);
|
||||
}
|
||||
|
||||
InitWithSessionAndOptions(isolate, web_contents, session, options);
|
||||
}
|
||||
|
||||
void WebContents::InitWithSessionAndOptions(v8::Isolate* isolate,
|
||||
content::WebContents *web_contents,
|
||||
mate::Handle<api::Session> session,
|
||||
const mate::Dictionary& options) {
|
||||
Observe(web_contents);
|
||||
InitWithWebContents(web_contents, session->browser_context());
|
||||
|
||||
@@ -397,13 +387,43 @@ bool WebContents::AddMessageToConsole(content::WebContents* source,
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::OnCreateWindow(const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition) {
|
||||
void WebContents::OnCreateWindow(
|
||||
const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const std::vector<base::string16>& features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body) {
|
||||
if (type_ == BROWSER_WINDOW || type_ == OFF_SCREEN)
|
||||
Emit("-new-window", target_url, frame_name, disposition);
|
||||
Emit("-new-window", target_url, frame_name, disposition, features, body);
|
||||
else
|
||||
Emit("new-window", target_url, frame_name, disposition);
|
||||
Emit("new-window", target_url, frame_name, disposition, features);
|
||||
}
|
||||
|
||||
void WebContents::WebContentsCreated(content::WebContents* source_contents,
|
||||
int opener_render_frame_id,
|
||||
const std::string& frame_name,
|
||||
const GURL& target_url,
|
||||
content::WebContents* new_contents) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto api_web_contents = CreateFrom(isolate(), new_contents, BROWSER_WINDOW);
|
||||
Emit("-web-contents-created", api_web_contents, target_url, frame_name);
|
||||
}
|
||||
|
||||
void WebContents::AddNewContents(content::WebContents* source,
|
||||
content::WebContents* new_contents,
|
||||
WindowOpenDisposition disposition,
|
||||
const gfx::Rect& initial_rect,
|
||||
bool user_gesture,
|
||||
bool* was_blocked) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto api_web_contents = CreateFrom(isolate(), new_contents);
|
||||
if (Emit("-add-new-contents", api_web_contents, disposition, user_gesture,
|
||||
initial_rect.x(), initial_rect.y(), initial_rect.width(),
|
||||
initial_rect.height())) {
|
||||
api_web_contents->DestroyWebContents();
|
||||
}
|
||||
}
|
||||
|
||||
content::WebContents* WebContents::OpenURLFromTab(
|
||||
@@ -421,6 +441,11 @@ content::WebContents* WebContents::OpenURLFromTab(
|
||||
if (Emit("will-navigate", params.url))
|
||||
return nullptr;
|
||||
|
||||
// Don't load the URL if the web contents was marked as destroyed from a
|
||||
// will-navigate event listener
|
||||
if (IsDestroyed())
|
||||
return nullptr;
|
||||
|
||||
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
|
||||
}
|
||||
|
||||
@@ -470,6 +495,17 @@ void WebContents::HandleKeyboardEvent(
|
||||
}
|
||||
}
|
||||
|
||||
bool WebContents::PreHandleKeyboardEvent(
|
||||
content::WebContents* source,
|
||||
const content::NativeWebKeyboardEvent& event,
|
||||
bool* is_keyboard_shortcut) {
|
||||
if (event.type == blink::WebInputEvent::Type::RawKeyDown
|
||||
|| event.type == blink::WebInputEvent::Type::KeyUp)
|
||||
return Emit("before-input-event", event);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void WebContents::EnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin) {
|
||||
auto permission_helper =
|
||||
@@ -527,22 +563,18 @@ void WebContents::FindReply(content::WebContents* web_contents,
|
||||
const gfx::Rect& selection_rect,
|
||||
int active_match_ordinal,
|
||||
bool final_update) {
|
||||
if (!final_update)
|
||||
return;
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
|
||||
mate::Dictionary result = mate::Dictionary::CreateEmpty(isolate());
|
||||
if (number_of_matches == -1) {
|
||||
result.Set("requestId", request_id);
|
||||
result.Set("selectionArea", selection_rect);
|
||||
result.Set("finalUpdate", final_update);
|
||||
result.Set("activeMatchOrdinal", active_match_ordinal);
|
||||
Emit("found-in-page", result);
|
||||
} else if (final_update) {
|
||||
result.Set("requestId", request_id);
|
||||
result.Set("matches", number_of_matches);
|
||||
result.Set("finalUpdate", final_update);
|
||||
Emit("found-in-page", result);
|
||||
}
|
||||
result.Set("requestId", request_id);
|
||||
result.Set("matches", number_of_matches);
|
||||
result.Set("selectionArea", selection_rect);
|
||||
result.Set("activeMatchOrdinal", active_match_ordinal);
|
||||
result.Set("finalUpdate", final_update); // Deprecate after 2.0
|
||||
Emit("found-in-page", result);
|
||||
}
|
||||
|
||||
bool WebContents::CheckMediaAccessPermission(
|
||||
@@ -583,12 +615,20 @@ void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
|
||||
// there are two virtual functions named BeforeUnloadFired.
|
||||
}
|
||||
|
||||
void WebContents::RenderViewCreated(content::RenderViewHost* render_view_host) {
|
||||
const auto impl = content::RenderWidgetHostImpl::FromID(
|
||||
render_view_host->GetProcess()->GetID(),
|
||||
render_view_host->GetRoutingID());
|
||||
if (impl)
|
||||
impl->disable_hidden_ = !background_throttling_;
|
||||
}
|
||||
|
||||
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
|
||||
Emit("render-view-deleted", render_view_host->GetProcess()->GetID());
|
||||
}
|
||||
|
||||
void WebContents::RenderProcessGone(base::TerminationStatus status) {
|
||||
Emit("crashed");
|
||||
Emit("crashed", status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
|
||||
}
|
||||
|
||||
void WebContents::PluginCrashed(const base::FilePath& plugin_path,
|
||||
@@ -608,11 +648,7 @@ void WebContents::MediaStoppedPlaying(const MediaPlayerId& id) {
|
||||
}
|
||||
|
||||
void WebContents::DidChangeThemeColor(SkColor theme_color) {
|
||||
std::string hex_theme_color = base::StringPrintf("#%02X%02X%02X",
|
||||
SkColorGetR(theme_color),
|
||||
SkColorGetG(theme_color),
|
||||
SkColorGetB(theme_color));
|
||||
Emit("did-change-theme-color", hex_theme_color);
|
||||
Emit("did-change-theme-color", atom::ToRGBHex(theme_color));
|
||||
}
|
||||
|
||||
void WebContents::DocumentLoadedInFrame(
|
||||
@@ -803,7 +839,14 @@ void WebContents::NavigationEntryCommitted(
|
||||
details.is_in_page, details.did_replace_entry);
|
||||
}
|
||||
|
||||
int WebContents::GetID() const {
|
||||
int64_t WebContents::GetID() const {
|
||||
int64_t process_id = web_contents()->GetRenderProcessHost()->GetID();
|
||||
int64_t routing_id = web_contents()->GetRoutingID();
|
||||
int64_t rv = (process_id << 32) + routing_id;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int WebContents::GetProcessID() const {
|
||||
return web_contents()->GetRenderProcessHost()->GetID();
|
||||
}
|
||||
|
||||
@@ -840,6 +883,12 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
|
||||
if (options.Get("extraHeaders", &extra_headers))
|
||||
params.extra_headers = extra_headers;
|
||||
|
||||
scoped_refptr<content::ResourceRequestBodyImpl> body;
|
||||
if (options.Get("postData", &body)) {
|
||||
params.post_data = body;
|
||||
params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST;
|
||||
}
|
||||
|
||||
params.transition_type = ui::PAGE_TRANSITION_TYPED;
|
||||
params.should_clear_history_list = true;
|
||||
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
|
||||
@@ -858,11 +907,6 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
|
||||
} else {
|
||||
view->SetBackgroundColor(SK_ColorTRANSPARENT);
|
||||
}
|
||||
|
||||
// For the same reason we can only disable hidden here.
|
||||
const auto host = static_cast<content::RenderWidgetHostImpl*>(
|
||||
view->GetRenderWidgetHost());
|
||||
host->disable_hidden_ = !background_throttling_;
|
||||
}
|
||||
|
||||
void WebContents::DownloadURL(const GURL& url) {
|
||||
@@ -871,7 +915,8 @@ void WebContents::DownloadURL(const GURL& url) {
|
||||
content::BrowserContext::GetDownloadManager(browser_context);
|
||||
|
||||
download_manager->DownloadUrl(
|
||||
content::DownloadUrlParameters::FromWebContents(web_contents(), url));
|
||||
content::DownloadUrlParameters::CreateForWebContentsMainFrame(
|
||||
web_contents(), url));
|
||||
}
|
||||
|
||||
GURL WebContents::GetURL() const {
|
||||
@@ -1177,7 +1222,7 @@ void WebContents::ShowDefinitionForSelection() {
|
||||
}
|
||||
|
||||
void WebContents::CopyImageAt(int x, int y) {
|
||||
const auto host = web_contents()->GetRenderViewHost();
|
||||
const auto host = web_contents()->GetMainFrame();
|
||||
if (host)
|
||||
host->CopyImageAt(x, y);
|
||||
}
|
||||
@@ -1419,6 +1464,15 @@ int WebContents::GetFrameRate() const {
|
||||
return osr_rwhv ? osr_rwhv->GetFrameRate() : 0;
|
||||
}
|
||||
|
||||
void WebContents::Invalidate() {
|
||||
if (!IsOffScreen())
|
||||
return;
|
||||
|
||||
auto* osr_rwhv = static_cast<OffScreenRenderWidgetHostView*>(
|
||||
web_contents()->GetRenderWidgetHostView());
|
||||
if (osr_rwhv)
|
||||
osr_rwhv->Invalidate();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::GetWebPreferences(v8::Isolate* isolate) {
|
||||
WebContentsPreferences* web_preferences =
|
||||
@@ -1447,6 +1501,25 @@ content::WebContents* WebContents::HostWebContents() {
|
||||
return embedder_->web_contents();
|
||||
}
|
||||
|
||||
void WebContents::SetEmbedder(const WebContents* embedder) {
|
||||
if (embedder) {
|
||||
NativeWindow* owner_window = nullptr;
|
||||
auto relay = NativeWindowRelay::FromWebContents(embedder->web_contents());
|
||||
if (relay) {
|
||||
owner_window = relay->window.get();
|
||||
}
|
||||
if (owner_window)
|
||||
SetOwnerWindow(owner_window);
|
||||
|
||||
content::RenderWidgetHostView* rwhv =
|
||||
web_contents()->GetRenderWidgetHostView();
|
||||
if (rwhv) {
|
||||
rwhv->Hide();
|
||||
rwhv->Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::DevToolsWebContents(v8::Isolate* isolate) {
|
||||
if (devtools_web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
@@ -1469,6 +1542,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.MakeDestroyable()
|
||||
.SetMethod("getId", &WebContents::GetID)
|
||||
.SetMethod("getProcessId", &WebContents::GetProcessID)
|
||||
.SetMethod("equal", &WebContents::Equal)
|
||||
.SetMethod("_loadURL", &WebContents::LoadURL)
|
||||
.SetMethod("downloadURL", &WebContents::DownloadURL)
|
||||
@@ -1528,6 +1602,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("isPainting", &WebContents::IsPainting)
|
||||
.SetMethod("setFrameRate", &WebContents::SetFrameRate)
|
||||
.SetMethod("getFrameRate", &WebContents::GetFrameRate)
|
||||
.SetMethod("invalidate", &WebContents::Invalidate)
|
||||
.SetMethod("getType", &WebContents::GetType)
|
||||
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||
@@ -1543,6 +1618,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
&WebContents::ShowDefinitionForSelection)
|
||||
.SetMethod("copyImageAt", &WebContents::CopyImageAt)
|
||||
.SetMethod("capturePage", &WebContents::CapturePage)
|
||||
.SetMethod("setEmbedder", &WebContents::SetEmbedder)
|
||||
.SetProperty("id", &WebContents::ID)
|
||||
.SetProperty("session", &WebContents::Session)
|
||||
.SetProperty("hostWebContents", &WebContents::HostWebContents)
|
||||
@@ -1576,7 +1652,15 @@ mate::Handle<WebContents> WebContents::CreateFrom(
|
||||
return mate::CreateHandle(isolate, static_cast<WebContents*>(existing));
|
||||
|
||||
// Otherwise create a new WebContents wrapper object.
|
||||
return mate::CreateHandle(isolate, new WebContents(isolate, web_contents));
|
||||
return mate::CreateHandle(isolate, new WebContents(isolate, web_contents,
|
||||
REMOTE));
|
||||
}
|
||||
|
||||
mate::Handle<WebContents> WebContents::CreateFrom(
|
||||
v8::Isolate* isolate, content::WebContents* web_contents, Type type) {
|
||||
// Otherwise create a new WebContents wrapper object.
|
||||
return mate::CreateHandle(isolate, new WebContents(isolate, web_contents,
|
||||
type));
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -26,6 +26,10 @@ namespace brightray {
|
||||
class InspectableWebContents;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class ResourceRequestBodyImpl;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
@@ -58,6 +62,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
// Create from an existing WebContents.
|
||||
static mate::Handle<WebContents> CreateFrom(
|
||||
v8::Isolate* isolate, content::WebContents* web_contents);
|
||||
static mate::Handle<WebContents> CreateFrom(
|
||||
v8::Isolate* isolate, content::WebContents* web_contents, Type type);
|
||||
|
||||
// Create a new WebContents.
|
||||
static mate::Handle<WebContents> Create(
|
||||
@@ -66,7 +72,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
int GetID() const;
|
||||
int64_t GetID() const;
|
||||
int GetProcessID() const;
|
||||
Type GetType() const;
|
||||
bool Equal(const WebContents* web_contents) const;
|
||||
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
||||
@@ -102,6 +109,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void SetAudioMuted(bool muted);
|
||||
bool IsAudioMuted();
|
||||
void Print(mate::Arguments* args);
|
||||
void SetEmbedder(const WebContents* embedder);
|
||||
|
||||
// Print current page as PDF.
|
||||
void PrintToPDF(const base::DictionaryValue& setting,
|
||||
@@ -164,6 +172,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
bool IsPainting() const;
|
||||
void SetFrameRate(int frame_rate);
|
||||
int GetFrameRate() const;
|
||||
void Invalidate();
|
||||
|
||||
// Callback triggered on permission response.
|
||||
void OnEnterFullscreenModeForTab(content::WebContents* source,
|
||||
@@ -171,9 +180,12 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
bool allowed);
|
||||
|
||||
// Create window with the given disposition.
|
||||
void OnCreateWindow(const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition);
|
||||
void OnCreateWindow(
|
||||
const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const std::vector<base::string16>& features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body);
|
||||
|
||||
// Returns the web preferences of current WebContents.
|
||||
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);
|
||||
@@ -189,16 +201,34 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
v8::Local<v8::Value> Debugger(v8::Isolate* isolate);
|
||||
|
||||
protected:
|
||||
WebContents(v8::Isolate* isolate, content::WebContents* web_contents);
|
||||
WebContents(v8::Isolate* isolate,
|
||||
content::WebContents* web_contents,
|
||||
Type type);
|
||||
WebContents(v8::Isolate* isolate, const mate::Dictionary& options);
|
||||
~WebContents();
|
||||
|
||||
void InitWithSessionAndOptions(v8::Isolate* isolate,
|
||||
content::WebContents *web_contents,
|
||||
mate::Handle<class Session> session,
|
||||
const mate::Dictionary& options);
|
||||
|
||||
// content::WebContentsDelegate:
|
||||
bool AddMessageToConsole(content::WebContents* source,
|
||||
int32_t level,
|
||||
const base::string16& message,
|
||||
int32_t line_no,
|
||||
const base::string16& source_id) override;
|
||||
void WebContentsCreated(content::WebContents* source_contents,
|
||||
int opener_render_frame_id,
|
||||
const std::string& frame_name,
|
||||
const GURL& target_url,
|
||||
content::WebContents* new_contents) override;
|
||||
void AddNewContents(content::WebContents* source,
|
||||
content::WebContents* new_contents,
|
||||
WindowOpenDisposition disposition,
|
||||
const gfx::Rect& initial_rect,
|
||||
bool user_gesture,
|
||||
bool* was_blocked) override;
|
||||
content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) override;
|
||||
@@ -214,6 +244,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void HandleKeyboardEvent(
|
||||
content::WebContents* source,
|
||||
const content::NativeWebKeyboardEvent& event) override;
|
||||
bool PreHandleKeyboardEvent(content::WebContents* source,
|
||||
const content::NativeWebKeyboardEvent& event,
|
||||
bool* is_keyboard_shortcut) override;
|
||||
void EnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin) override;
|
||||
void ExitFullscreenModeForTab(content::WebContents* source) override;
|
||||
@@ -245,6 +278,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
|
||||
void RenderViewCreated(content::RenderViewHost*) override;
|
||||
void RenderViewDeleted(content::RenderViewHost*) override;
|
||||
void RenderProcessGone(base::TerminationStatus status) override;
|
||||
void DocumentLoadedInFrame(
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
@@ -29,8 +29,11 @@
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "atom/browser/ui/win/taskbar_host.h"
|
||||
#include "ui/base/win/shell.h"
|
||||
#endif
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
namespace mate {
|
||||
|
||||
@@ -71,20 +74,40 @@ v8::Local<v8::Value> ToBuffer(v8::Isolate* isolate, void* val, int size) {
|
||||
|
||||
Window::Window(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options) {
|
||||
// Use options.webPreferences to create WebContents.
|
||||
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
|
||||
options.Get(options::kWebPreferences, &web_preferences);
|
||||
mate::Handle<class WebContents> web_contents;
|
||||
// If no WebContents was passed to the constructor, create it from options.
|
||||
if (!options.Get("webContents", &web_contents)) {
|
||||
// Use options.webPreferences to create 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);
|
||||
// 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);
|
||||
// Creates the WebContents used by BrowserWindow.
|
||||
auto web_contents = WebContents::Create(isolate, web_preferences);
|
||||
v8::Local<v8::Value> transparent;
|
||||
if (options.Get("transparent", &transparent))
|
||||
web_preferences.Set("transparent", transparent);
|
||||
|
||||
// Offscreen windows are always created frameless.
|
||||
bool offscreen;
|
||||
if (web_preferences.Get("offscreen", &offscreen) && offscreen) {
|
||||
auto window_options = const_cast<mate::Dictionary&>(options);
|
||||
window_options.Set(options::kFrame, false);
|
||||
}
|
||||
|
||||
// Creates the WebContents used by BrowserWindow.
|
||||
web_contents = WebContents::Create(isolate, web_preferences);
|
||||
}
|
||||
|
||||
Init(isolate, wrapper, options, web_contents);
|
||||
}
|
||||
|
||||
void Window::Init(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options,
|
||||
mate::Handle<class WebContents> web_contents) {
|
||||
web_contents_.Reset(isolate, web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
|
||||
@@ -229,6 +252,10 @@ void Window::OnWindowScrollTouchEnd() {
|
||||
Emit("scroll-touch-end");
|
||||
}
|
||||
|
||||
void Window::OnWindowScrollTouchEdge() {
|
||||
Emit("scroll-touch-edge");
|
||||
}
|
||||
|
||||
void Window::OnWindowSwipe(const std::string& direction) {
|
||||
Emit("swipe", direction);
|
||||
}
|
||||
@@ -481,8 +508,10 @@ bool Window::IsClosable() {
|
||||
return window_->IsClosable();
|
||||
}
|
||||
|
||||
void Window::SetAlwaysOnTop(bool top) {
|
||||
window_->SetAlwaysOnTop(top);
|
||||
void Window::SetAlwaysOnTop(bool top, mate::Arguments* args) {
|
||||
std::string level = "floating";
|
||||
args->GetNext(&level);
|
||||
window_->SetAlwaysOnTop(top, level);
|
||||
}
|
||||
|
||||
bool Window::IsAlwaysOnTop() {
|
||||
@@ -688,6 +717,25 @@ bool Window::SetThumbnailToolTip(const std::string& tooltip) {
|
||||
return window->taskbar_host().SetThumbnailToolTip(
|
||||
window_->GetAcceleratedWidget(), tooltip);
|
||||
}
|
||||
|
||||
void Window::SetAppDetails(const mate::Dictionary& options) {
|
||||
base::string16 app_id;
|
||||
base::FilePath app_icon_path;
|
||||
int app_icon_index = 0;
|
||||
base::string16 relaunch_command;
|
||||
base::string16 relaunch_display_name;
|
||||
|
||||
options.Get("appId", &app_id);
|
||||
options.Get("appIconPath", &app_icon_path);
|
||||
options.Get("appIconIndex", &app_icon_index);
|
||||
options.Get("relaunchCommand", &relaunch_command);
|
||||
options.Get("relaunchDisplayName", &relaunch_display_name);
|
||||
|
||||
ui::win::SetAppDetailsForWindow(
|
||||
app_id, app_icon_path, app_icon_index,
|
||||
relaunch_command, relaunch_display_name,
|
||||
window_->GetAcceleratedWidget());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
@@ -709,6 +757,17 @@ void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) {
|
||||
window_->SetAspectRatio(aspect_ratio, extra_size);
|
||||
}
|
||||
|
||||
void Window::PreviewFile(const std::string& path, mate::Arguments* args) {
|
||||
std::string display_name;
|
||||
if (!args->GetNext(&display_name))
|
||||
display_name = path;
|
||||
window_->PreviewFile(path, display_name);
|
||||
}
|
||||
|
||||
void Window::CloseFilePreview() {
|
||||
window_->CloseFilePreview();
|
||||
}
|
||||
|
||||
void Window::SetParentWindow(v8::Local<v8::Value> value,
|
||||
mate::Arguments* args) {
|
||||
if (IsModal()) {
|
||||
@@ -759,6 +818,17 @@ bool Window::IsVisibleOnAllWorkspaces() {
|
||||
return window_->IsVisibleOnAllWorkspaces();
|
||||
}
|
||||
|
||||
void Window::SetAutoHideCursor(bool auto_hide) {
|
||||
window_->SetAutoHideCursor(auto_hide);
|
||||
}
|
||||
|
||||
void Window::SetVibrancy(mate::Arguments* args) {
|
||||
std::string type;
|
||||
|
||||
args->GetNext(&type);
|
||||
window_->SetVibrancy(type);
|
||||
}
|
||||
|
||||
int32_t Window::ID() const {
|
||||
return weak_map_id();
|
||||
}
|
||||
@@ -805,6 +875,8 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setFullScreen", &Window::SetFullScreen)
|
||||
.SetMethod("isFullScreen", &Window::IsFullscreen)
|
||||
.SetMethod("setAspectRatio", &Window::SetAspectRatio)
|
||||
.SetMethod("previewFile", &Window::PreviewFile)
|
||||
.SetMethod("closeFilePreview", &Window::CloseFilePreview)
|
||||
#if !defined(OS_WIN)
|
||||
.SetMethod("setParentWindow", &Window::SetParentWindow)
|
||||
#endif
|
||||
@@ -873,6 +945,10 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
&Window::SetVisibleOnAllWorkspaces)
|
||||
.SetMethod("isVisibleOnAllWorkspaces",
|
||||
&Window::IsVisibleOnAllWorkspaces)
|
||||
#if defined(OS_MACOSX)
|
||||
.SetMethod("setAutoHideCursor", &Window::SetAutoHideCursor)
|
||||
#endif
|
||||
.SetMethod("setVibrancy", &Window::SetVibrancy)
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("hookWindowMessage", &Window::HookWindowMessage)
|
||||
.SetMethod("isWindowMessageHooked", &Window::IsWindowMessageHooked)
|
||||
@@ -880,6 +956,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("unhookAllWindowMessages", &Window::UnhookAllWindowMessages)
|
||||
.SetMethod("setThumbnailClip", &Window::SetThumbnailClip)
|
||||
.SetMethod("setThumbnailToolTip", &Window::SetThumbnailToolTip)
|
||||
.SetMethod("setAppDetails", &Window::SetAppDetails)
|
||||
#endif
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
.SetMethod("setIcon", &Window::SetIcon)
|
||||
|
||||
@@ -74,6 +74,7 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void OnWindowMoved() override;
|
||||
void OnWindowScrollTouchBegin() override;
|
||||
void OnWindowScrollTouchEnd() override;
|
||||
void OnWindowScrollTouchEdge() override;
|
||||
void OnWindowSwipe(const std::string& direction) override;
|
||||
void OnWindowEnterFullScreen() override;
|
||||
void OnWindowLeaveFullScreen() override;
|
||||
@@ -88,6 +89,10 @@ class Window : public mate::TrackableObject<Window>,
|
||||
#endif
|
||||
|
||||
private:
|
||||
void Init(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options,
|
||||
mate::Handle<class WebContents> web_contents);
|
||||
// APIs for NativeWindow.
|
||||
void Close();
|
||||
void Focus();
|
||||
@@ -131,7 +136,7 @@ class Window : public mate::TrackableObject<Window>,
|
||||
bool IsFullScreenable();
|
||||
void SetClosable(bool closable);
|
||||
bool IsClosable();
|
||||
void SetAlwaysOnTop(bool top);
|
||||
void SetAlwaysOnTop(bool top, mate::Arguments* args);
|
||||
bool IsAlwaysOnTop();
|
||||
void Center();
|
||||
void SetPosition(int x, int y, mate::Arguments* args);
|
||||
@@ -165,6 +170,8 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void SetMenuBarVisibility(bool visible);
|
||||
bool IsMenuBarVisible();
|
||||
void SetAspectRatio(double aspect_ratio, mate::Arguments* args);
|
||||
void PreviewFile(const std::string& path, mate::Arguments* args);
|
||||
void CloseFilePreview();
|
||||
void SetParentWindow(v8::Local<v8::Value> value, mate::Arguments* args);
|
||||
v8::Local<v8::Value> GetParentWindow() const;
|
||||
std::vector<v8::Local<v8::Object>> GetChildWindows() const;
|
||||
@@ -181,6 +188,7 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void UnhookAllWindowMessages();
|
||||
bool SetThumbnailClip(const gfx::Rect& region);
|
||||
bool SetThumbnailToolTip(const std::string& tooltip);
|
||||
void SetAppDetails(const mate::Dictionary& options);
|
||||
#endif
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
@@ -190,6 +198,10 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void SetVisibleOnAllWorkspaces(bool visible);
|
||||
bool IsVisibleOnAllWorkspaces();
|
||||
|
||||
void SetAutoHideCursor(bool auto_hide);
|
||||
|
||||
void SetVibrancy(mate::Arguments* args);
|
||||
|
||||
int32_t ID() const;
|
||||
v8::Local<v8::Value> WebContents(v8::Isolate* isolate);
|
||||
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
#include "atom/browser/api/frame_subscriber.h"
|
||||
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/bind.h"
|
||||
#include "content/public/browser/render_widget_host.h"
|
||||
#include "ui/display/display.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -40,6 +43,17 @@ bool FrameSubscriber::ShouldCaptureFrame(
|
||||
if (only_dirty_)
|
||||
rect = dirty_rect;
|
||||
|
||||
gfx::Size view_size = rect.size();
|
||||
gfx::Size bitmap_size = view_size;
|
||||
const gfx::NativeView native_view = view_->GetNativeView();
|
||||
const float scale =
|
||||
display::Screen::GetScreen()->GetDisplayNearestWindow(native_view)
|
||||
.device_scale_factor();
|
||||
if (scale > 1.0f)
|
||||
bitmap_size = gfx::ScaleToCeiledSize(view_size, scale);
|
||||
|
||||
rect = gfx::Rect(rect.origin(), bitmap_size);
|
||||
|
||||
host->CopyFromBackingStore(
|
||||
rect,
|
||||
rect.size(),
|
||||
|
||||
@@ -65,6 +65,12 @@ class TrackableObject : public TrackableObjectBase,
|
||||
Wrappable<T>::GetWrapper()->SetAlignedPointerInInternalField(0, nullptr);
|
||||
}
|
||||
|
||||
bool IsDestroyed() {
|
||||
v8::Local<v8::Object> wrapper = Wrappable<T>::GetWrapper();
|
||||
return wrapper->InternalFieldCount() == 0 ||
|
||||
wrapper->GetAlignedPointerFromInternalField(0) == nullptr;
|
||||
}
|
||||
|
||||
// Finds out the TrackableObject from its ID in weak map.
|
||||
static T* FromWeakMapID(v8::Isolate* isolate, int32_t id) {
|
||||
if (!weak_map_)
|
||||
|
||||
@@ -4,27 +4,66 @@
|
||||
|
||||
#include "atom/browser/atom_access_token_store.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/common/google_api_key.h"
|
||||
#include "base/environment.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/geolocation_provider.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
namespace internal {
|
||||
|
||||
// Notice that we just combined the api key with the url together here, because
|
||||
// if we use the standard {url: key} format Chromium would override our key with
|
||||
// the predefined one in common.gypi of libchromiumcontent, which is empty.
|
||||
const char* kGeolocationProviderURL =
|
||||
"https://www.googleapis.com/geolocation/v1/geolocate?key="
|
||||
GOOGLEAPIS_API_KEY;
|
||||
// Loads access tokens and other necessary data on the UI thread, and
|
||||
// calls back to the originator on the originating thread.
|
||||
class TokenLoadingJob : public base::RefCountedThreadSafe<TokenLoadingJob> {
|
||||
public:
|
||||
explicit TokenLoadingJob(
|
||||
const content::AccessTokenStore::LoadAccessTokensCallback& callback)
|
||||
: callback_(callback), request_context_getter_(nullptr) {}
|
||||
|
||||
} // namespace
|
||||
void Run(AtomBrowserContext* browser_context) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
request_context_getter_ = browser_context->GetRequestContext();
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (!env->GetVar("GOOGLE_API_KEY", &api_key_))
|
||||
api_key_ = GOOGLEAPIS_API_KEY;
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&TokenLoadingJob::RespondOnIOThread, this));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<TokenLoadingJob>;
|
||||
|
||||
~TokenLoadingJob() {}
|
||||
|
||||
void RespondOnIOThread() {
|
||||
// Equivalent to access_token_map[kGeolocationProviderURL].
|
||||
// Somehow base::string16 is causing compilation errors when used in a pair
|
||||
// of std::map on Linux, this can work around it.
|
||||
content::AccessTokenStore::AccessTokenMap access_token_map;
|
||||
std::pair<GURL, base::string16> token_pair;
|
||||
token_pair.first = GURL(GOOGLEAPIS_ENDPOINT + api_key_);
|
||||
access_token_map.insert(token_pair);
|
||||
|
||||
callback_.Run(access_token_map, request_context_getter_);
|
||||
}
|
||||
|
||||
content::AccessTokenStore::LoadAccessTokensCallback callback_;
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
std::string api_key_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
AtomAccessTokenStore::AtomAccessTokenStore() {
|
||||
browser_context_ = AtomBrowserContext::From("", false);
|
||||
content::GeolocationProvider::GetInstance()->UserDidOptIntoLocationServices();
|
||||
}
|
||||
|
||||
@@ -33,35 +72,20 @@ AtomAccessTokenStore::~AtomAccessTokenStore() {
|
||||
|
||||
void AtomAccessTokenStore::LoadAccessTokens(
|
||||
const LoadAccessTokensCallback& callback) {
|
||||
content::BrowserThread::PostTaskAndReply(
|
||||
content::BrowserThread::UI,
|
||||
FROM_HERE,
|
||||
base::Bind(&AtomAccessTokenStore::GetRequestContextOnUIThread, this),
|
||||
base::Bind(&AtomAccessTokenStore::RespondOnOriginatingThread,
|
||||
this, callback));
|
||||
scoped_refptr<internal::TokenLoadingJob> job(
|
||||
new internal::TokenLoadingJob(callback));
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&AtomAccessTokenStore::RunTokenLoadingJob,
|
||||
this, base::RetainedRef(job)));
|
||||
}
|
||||
|
||||
void AtomAccessTokenStore::RunTokenLoadingJob(
|
||||
scoped_refptr<internal::TokenLoadingJob> job) {
|
||||
job->Run(browser_context_.get());
|
||||
}
|
||||
|
||||
void AtomAccessTokenStore::SaveAccessToken(const GURL& server_url,
|
||||
const base::string16& access_token) {
|
||||
}
|
||||
|
||||
void AtomAccessTokenStore::GetRequestContextOnUIThread() {
|
||||
auto browser_context = AtomBrowserContext::From("", false);
|
||||
request_context_getter_ = browser_context->GetRequestContext();
|
||||
}
|
||||
|
||||
void AtomAccessTokenStore::RespondOnOriginatingThread(
|
||||
const LoadAccessTokensCallback& callback) {
|
||||
// Equivelent to access_token_map[kGeolocationProviderURL].
|
||||
// Somehow base::string16 is causing compilation errors when used in a pair
|
||||
// of std::map on Linux, this can work around it.
|
||||
AccessTokenMap access_token_map;
|
||||
std::pair<GURL, base::string16> token_pair;
|
||||
token_pair.first = GURL(kGeolocationProviderURL);
|
||||
access_token_map.insert(token_pair);
|
||||
|
||||
callback.Run(access_token_map, request_context_getter_.get());
|
||||
request_context_getter_ = nullptr;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserContext;
|
||||
|
||||
namespace internal {
|
||||
class TokenLoadingJob;
|
||||
}
|
||||
|
||||
class AtomAccessTokenStore : public content::AccessTokenStore {
|
||||
public:
|
||||
AtomAccessTokenStore();
|
||||
@@ -21,11 +27,9 @@ class AtomAccessTokenStore : public content::AccessTokenStore {
|
||||
const base::string16& access_token) override;
|
||||
|
||||
private:
|
||||
void GetRequestContextOnUIThread();
|
||||
void RespondOnOriginatingThread(const LoadAccessTokensCallback& callback);
|
||||
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
|
||||
void RunTokenLoadingJob(scoped_refptr<internal::TokenLoadingJob> job);
|
||||
|
||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomAccessTokenStore);
|
||||
};
|
||||
|
||||
|
||||
138
atom/browser/atom_blob_reader.cc
Normal file
138
atom/browser/atom_blob_reader.cc
Normal file
@@ -0,0 +1,138 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/atom_blob_reader.h"
|
||||
|
||||
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "storage/browser/blob/blob_data_handle.h"
|
||||
#include "storage/browser/blob/blob_reader.h"
|
||||
#include "storage/browser/blob/blob_storage_context.h"
|
||||
#include "storage/browser/fileapi/file_system_context.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
void FreeNodeBufferData(char* data, void* hint) {
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
void RunCallbackInUI(
|
||||
const AtomBlobReader::CompletionCallback& callback,
|
||||
char* blob_data,
|
||||
int size) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
if (blob_data) {
|
||||
v8::Local<v8::Value> buffer = node::Buffer::New(isolate,
|
||||
blob_data, static_cast<size_t>(size), &FreeNodeBufferData, nullptr)
|
||||
.ToLocalChecked();
|
||||
callback.Run(buffer);
|
||||
} else {
|
||||
callback.Run(v8::Null(isolate));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomBlobReader::AtomBlobReader(
|
||||
content::ChromeBlobStorageContext* blob_context,
|
||||
storage::FileSystemContext* file_system_context)
|
||||
: blob_context_(blob_context),
|
||||
file_system_context_(file_system_context) {
|
||||
}
|
||||
|
||||
AtomBlobReader::~AtomBlobReader() {
|
||||
}
|
||||
|
||||
void AtomBlobReader::StartReading(
|
||||
const std::string& uuid,
|
||||
const AtomBlobReader::CompletionCallback& completion_callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
auto blob_data_handle =
|
||||
blob_context_->context()->GetBlobDataFromUUID(uuid);
|
||||
auto callback = base::Bind(&RunCallbackInUI,
|
||||
completion_callback);
|
||||
if (!blob_data_handle) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(callback, nullptr, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
auto blob_reader = blob_data_handle->CreateReader(
|
||||
file_system_context_.get(),
|
||||
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get());
|
||||
BlobReadHelper* blob_read_helper =
|
||||
new BlobReadHelper(std::move(blob_reader), callback);
|
||||
blob_read_helper->Read();
|
||||
}
|
||||
|
||||
AtomBlobReader::BlobReadHelper::BlobReadHelper(
|
||||
std::unique_ptr<storage::BlobReader> blob_reader,
|
||||
const BlobReadHelper::CompletionCallback& callback)
|
||||
: blob_reader_(std::move(blob_reader)),
|
||||
completion_callback_(callback) {
|
||||
}
|
||||
|
||||
AtomBlobReader::BlobReadHelper::~BlobReadHelper() {
|
||||
}
|
||||
|
||||
void AtomBlobReader::BlobReadHelper::Read() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
storage::BlobReader::Status size_status = blob_reader_->CalculateSize(
|
||||
base::Bind(&AtomBlobReader::BlobReadHelper::DidCalculateSize,
|
||||
base::Unretained(this)));
|
||||
if (size_status != storage::BlobReader::Status::IO_PENDING)
|
||||
DidCalculateSize(net::OK);
|
||||
}
|
||||
|
||||
void AtomBlobReader::BlobReadHelper::DidCalculateSize(int result) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
if (result != net::OK) {
|
||||
DidReadBlobData(nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t total_size = blob_reader_->total_size();
|
||||
int bytes_read = 0;
|
||||
scoped_refptr<net::IOBuffer> blob_data =
|
||||
new net::IOBuffer(static_cast<size_t>(total_size));
|
||||
auto callback = base::Bind(&AtomBlobReader::BlobReadHelper::DidReadBlobData,
|
||||
base::Unretained(this),
|
||||
base::RetainedRef(blob_data));
|
||||
storage::BlobReader::Status read_status = blob_reader_->Read(
|
||||
blob_data.get(),
|
||||
total_size,
|
||||
&bytes_read,
|
||||
callback);
|
||||
if (read_status != storage::BlobReader::Status::IO_PENDING)
|
||||
callback.Run(bytes_read);
|
||||
}
|
||||
|
||||
void AtomBlobReader::BlobReadHelper::DidReadBlobData(
|
||||
const scoped_refptr<net::IOBuffer>& blob_data,
|
||||
int size) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
char* data = new char[size];
|
||||
memcpy(data, blob_data->data(), size);
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(completion_callback_, data, size));
|
||||
delete this;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
80
atom/browser/atom_blob_reader.h
Normal file
80
atom/browser/atom_blob_reader.h
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_ATOM_BLOB_READER_H_
|
||||
#define ATOM_BROWSER_ATOM_BLOB_READER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/callback.h"
|
||||
|
||||
namespace content {
|
||||
class ChromeBlobStorageContext;
|
||||
}
|
||||
|
||||
namespace net {
|
||||
class IOBuffer;
|
||||
}
|
||||
|
||||
namespace storage {
|
||||
class BlobDataHandle;
|
||||
class BlobReader;
|
||||
class FileSystemContext;
|
||||
}
|
||||
|
||||
namespace v8 {
|
||||
template <class T>
|
||||
class Local;
|
||||
class Value;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
// A class to keep track of the blob context. All methods,
|
||||
// except Ctor are expected to be called on IO thread.
|
||||
class AtomBlobReader {
|
||||
public:
|
||||
using CompletionCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
|
||||
AtomBlobReader(content::ChromeBlobStorageContext* blob_context,
|
||||
storage::FileSystemContext* file_system_context);
|
||||
~AtomBlobReader();
|
||||
|
||||
void StartReading(
|
||||
const std::string& uuid,
|
||||
const AtomBlobReader::CompletionCallback& callback);
|
||||
|
||||
private:
|
||||
// A self-destroyed helper class to read the blob data.
|
||||
// Must be accessed on IO thread.
|
||||
class BlobReadHelper {
|
||||
public:
|
||||
using CompletionCallback = base::Callback<void(char*, int)>;
|
||||
|
||||
BlobReadHelper(std::unique_ptr<storage::BlobReader> blob_reader,
|
||||
const BlobReadHelper::CompletionCallback& callback);
|
||||
~BlobReadHelper();
|
||||
|
||||
void Read();
|
||||
|
||||
private:
|
||||
void DidCalculateSize(int result);
|
||||
void DidReadBlobData(const scoped_refptr<net::IOBuffer>& blob_data,
|
||||
int bytes_read);
|
||||
|
||||
std::unique_ptr<storage::BlobReader> blob_reader_;
|
||||
BlobReadHelper::CompletionCallback completion_callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BlobReadHelper);
|
||||
};
|
||||
|
||||
scoped_refptr<content::ChromeBlobStorageContext> blob_context_;
|
||||
scoped_refptr<storage::FileSystemContext> file_system_context_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBlobReader);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_ATOM_BLOB_READER_H_
|
||||
@@ -30,13 +30,16 @@
|
||||
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
|
||||
#include "chrome/browser/renderer_host/pepper/widevine_cdm_message_filter.h"
|
||||
#include "chrome/browser/speech/tts_message_filter.h"
|
||||
#include "content/common/resource_request_body_impl.h"
|
||||
#include "content/public/browser/browser_ppapi_host.h"
|
||||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
#include "content/public/browser/geolocation_delegate.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/resource_dispatcher_host.h"
|
||||
#include "content/public/browser/site_instance.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/common/url_constants.h"
|
||||
#include "content/public/common/web_preferences.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
#include "ppapi/host/ppapi_host.h"
|
||||
@@ -53,6 +56,19 @@ bool g_suppress_renderer_process_restart = false;
|
||||
// Custom schemes to be registered to handle service worker.
|
||||
std::string g_custom_service_worker_schemes = "";
|
||||
|
||||
// A provider of Geolocation services to override AccessTokenStore.
|
||||
class AtomGeolocationDelegate : public content::GeolocationDelegate {
|
||||
public:
|
||||
AtomGeolocationDelegate() = default;
|
||||
|
||||
content::AccessTokenStore* CreateAccessTokenStore() final {
|
||||
return new AtomAccessTokenStore();
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomGeolocationDelegate);
|
||||
};
|
||||
|
||||
void Noop(scoped_refptr<content::SiteInstance>) {
|
||||
}
|
||||
|
||||
@@ -85,6 +101,44 @@ content::WebContents* AtomBrowserClient::GetWebContentsFromProcessID(
|
||||
return WebContentsPreferences::GetWebContentsFromProcessID(process_id);
|
||||
}
|
||||
|
||||
bool AtomBrowserClient::ShouldCreateNewSiteInstance(
|
||||
content::BrowserContext* browser_context,
|
||||
content::SiteInstance* current_instance,
|
||||
const GURL& url) {
|
||||
|
||||
if (url.SchemeIs(url::kJavaScriptScheme))
|
||||
// "javacript:" scheme should always use same SiteInstance
|
||||
return false;
|
||||
|
||||
if (!IsRendererSandboxed(current_instance->GetProcess()->GetID()))
|
||||
// non-sandboxed renderers should always create a new SiteInstance
|
||||
return true;
|
||||
|
||||
// Create new a SiteInstance if navigating to a different site.
|
||||
auto src_url = current_instance->GetSiteURL();
|
||||
return
|
||||
!content::SiteInstance::IsSameWebSite(browser_context, src_url, url) &&
|
||||
// `IsSameWebSite` doesn't seem to work for some URIs such as `file:`,
|
||||
// handle these scenarios by comparing only the site as defined by
|
||||
// `GetSiteForURL`.
|
||||
content::SiteInstance::GetSiteForURL(browser_context, url) != src_url;
|
||||
}
|
||||
|
||||
void AtomBrowserClient::AddSandboxedRendererId(int process_id) {
|
||||
base::AutoLock auto_lock(sandboxed_renderers_lock_);
|
||||
sandboxed_renderers_.insert(process_id);
|
||||
}
|
||||
|
||||
void AtomBrowserClient::RemoveSandboxedRendererId(int process_id) {
|
||||
base::AutoLock auto_lock(sandboxed_renderers_lock_);
|
||||
sandboxed_renderers_.erase(process_id);
|
||||
}
|
||||
|
||||
bool AtomBrowserClient::IsRendererSandboxed(int process_id) {
|
||||
base::AutoLock auto_lock(sandboxed_renderers_lock_);
|
||||
return sandboxed_renderers_.count(process_id);
|
||||
}
|
||||
|
||||
void AtomBrowserClient::RenderProcessWillLaunch(
|
||||
content::RenderProcessHost* host) {
|
||||
int process_id = host->GetID();
|
||||
@@ -92,6 +146,13 @@ void AtomBrowserClient::RenderProcessWillLaunch(
|
||||
host->AddFilter(new TtsMessageFilter(process_id, host->GetBrowserContext()));
|
||||
host->AddFilter(
|
||||
new WidevineCdmMessageFilter(process_id, host->GetBrowserContext()));
|
||||
|
||||
content::WebContents* web_contents = GetWebContentsFromProcessID(process_id);
|
||||
if (WebContentsPreferences::IsSandboxed(web_contents)) {
|
||||
AddSandboxedRendererId(host->GetID());
|
||||
// ensure the sandboxed renderer id is removed later
|
||||
host->AddObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
content::SpeechRecognitionManagerDelegate*
|
||||
@@ -99,8 +160,9 @@ content::SpeechRecognitionManagerDelegate*
|
||||
return new AtomSpeechRecognitionManagerDelegate;
|
||||
}
|
||||
|
||||
content::AccessTokenStore* AtomBrowserClient::CreateAccessTokenStore() {
|
||||
return new AtomAccessTokenStore;
|
||||
content::GeolocationDelegate*
|
||||
AtomBrowserClient::CreateGeolocationDelegate() {
|
||||
return new AtomGeolocationDelegate();
|
||||
}
|
||||
|
||||
void AtomBrowserClient::OverrideWebkitPrefs(
|
||||
@@ -140,8 +202,7 @@ void AtomBrowserClient::OverrideSiteInstanceForNavigation(
|
||||
return;
|
||||
}
|
||||
|
||||
// Restart renderer process for all navigations except "javacript:" scheme.
|
||||
if (url.SchemeIs(url::kJavaScriptScheme))
|
||||
if (!ShouldCreateNewSiteInstance(browser_context, current_instance, url))
|
||||
return;
|
||||
|
||||
scoped_refptr<content::SiteInstance> site_instance =
|
||||
@@ -173,6 +234,8 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||
// Copy following switches to child process.
|
||||
static const char* const kCommonSwitchNames[] = {
|
||||
switches::kStandardSchemes,
|
||||
switches::kEnableSandbox,
|
||||
switches::kSecureSchemes
|
||||
};
|
||||
command_line->CopySwitchesFrom(
|
||||
*base::CommandLine::ForCurrentProcess(),
|
||||
@@ -257,6 +320,8 @@ bool AtomBrowserClient::CanCreateWindow(
|
||||
const content::Referrer& referrer,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::WebWindowFeatures& features,
|
||||
const std::vector<base::string16>& additional_features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||
bool user_gesture,
|
||||
bool opener_suppressed,
|
||||
content::ResourceContext* context,
|
||||
@@ -266,6 +331,11 @@ bool AtomBrowserClient::CanCreateWindow(
|
||||
bool* no_javascript_access) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
|
||||
if (IsRendererSandboxed(render_process_id)) {
|
||||
*no_javascript_access = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (delegate_) {
|
||||
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&api::App::OnCreateWindow,
|
||||
@@ -273,6 +343,8 @@ bool AtomBrowserClient::CanCreateWindow(
|
||||
target_url,
|
||||
frame_name,
|
||||
disposition,
|
||||
additional_features,
|
||||
body,
|
||||
render_process_id,
|
||||
opener_render_frame_id));
|
||||
}
|
||||
@@ -287,6 +359,7 @@ void AtomBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
|
||||
additional_schemes->insert(additional_schemes->end(),
|
||||
schemes_list.begin(),
|
||||
schemes_list.end());
|
||||
additional_schemes->push_back(content::kChromeDevToolsScheme);
|
||||
}
|
||||
|
||||
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
|
||||
@@ -323,6 +396,7 @@ void AtomBrowserClient::RenderProcessHostDestroyed(
|
||||
break;
|
||||
}
|
||||
}
|
||||
RemoveSandboxedRendererId(process_id);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define ATOM_BROWSER_ATOM_BROWSER_CLIENT_H_
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -49,7 +50,7 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||
void RenderProcessWillLaunch(content::RenderProcessHost* host) override;
|
||||
content::SpeechRecognitionManagerDelegate*
|
||||
CreateSpeechRecognitionManagerDelegate() override;
|
||||
content::AccessTokenStore* CreateAccessTokenStore() override;
|
||||
content::GeolocationDelegate* CreateGeolocationDelegate() override;
|
||||
void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
|
||||
content::WebPreferences* prefs) override;
|
||||
std::string GetApplicationLocale() override;
|
||||
@@ -78,22 +79,25 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
void ResourceDispatcherHostCreated() override;
|
||||
bool CanCreateWindow(const GURL& opener_url,
|
||||
const GURL& opener_top_level_frame_url,
|
||||
const GURL& source_origin,
|
||||
WindowContainerType container_type,
|
||||
const std::string& frame_name,
|
||||
const GURL& target_url,
|
||||
const content::Referrer& referrer,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::WebWindowFeatures& features,
|
||||
bool user_gesture,
|
||||
bool opener_suppressed,
|
||||
content::ResourceContext* context,
|
||||
int render_process_id,
|
||||
int opener_render_view_id,
|
||||
int opener_render_frame_id,
|
||||
bool* no_javascript_access) override;
|
||||
bool CanCreateWindow(
|
||||
const GURL& opener_url,
|
||||
const GURL& opener_top_level_frame_url,
|
||||
const GURL& source_origin,
|
||||
WindowContainerType container_type,
|
||||
const std::string& frame_name,
|
||||
const GURL& target_url,
|
||||
const content::Referrer& referrer,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::WebWindowFeatures& features,
|
||||
const std::vector<base::string16>& additional_features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||
bool user_gesture,
|
||||
bool opener_suppressed,
|
||||
content::ResourceContext* context,
|
||||
int render_process_id,
|
||||
int opener_render_view_id,
|
||||
int opener_render_frame_id,
|
||||
bool* no_javascript_access) override;
|
||||
void GetAdditionalAllowedSchemesForFileSystem(
|
||||
std::vector<std::string>* schemes) override;
|
||||
|
||||
@@ -108,8 +112,19 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
|
||||
|
||||
private:
|
||||
bool ShouldCreateNewSiteInstance(content::BrowserContext* browser_context,
|
||||
content::SiteInstance* current_instance,
|
||||
const GURL& dest_url);
|
||||
// Add/remove a process id to `sandboxed_renderers_`.
|
||||
void AddSandboxedRendererId(int process_id);
|
||||
void RemoveSandboxedRendererId(int process_id);
|
||||
bool IsRendererSandboxed(int process_id);
|
||||
|
||||
// pending_render_process => current_render_process.
|
||||
std::map<int, int> pending_processes_;
|
||||
// Set that contains the process ids of all sandboxed renderers
|
||||
std::set<int> sandboxed_renderers_;
|
||||
base::Lock sandboxed_renderers_lock_;
|
||||
|
||||
std::unique_ptr<AtomResourceDispatcherHostDelegate>
|
||||
resource_dispatcher_host_delegate_;
|
||||
|
||||
@@ -5,12 +5,15 @@
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_protocol.h"
|
||||
#include "atom/browser/atom_blob_reader.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/atom_download_manager_delegate.h"
|
||||
#include "atom/browser/atom_permission_manager.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/net/about_protocol_handler.h"
|
||||
#include "atom/browser/net/asar/asar_protocol_handler.h"
|
||||
#include "atom/browser/net/atom_cert_verifier.h"
|
||||
#include "atom/browser/net/atom_ct_delegate.h"
|
||||
#include "atom/browser/net/atom_network_delegate.h"
|
||||
#include "atom/browser/net/atom_ssl_config_service.h"
|
||||
#include "atom/browser/net/atom_url_request_job_factory.h"
|
||||
@@ -30,7 +33,9 @@
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
#include "components/prefs/pref_registry_simple.h"
|
||||
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
#include "content/public/common/url_constants.h"
|
||||
#include "content/public/common/user_agent.h"
|
||||
#include "net/ftp/ftp_network_layer.h"
|
||||
@@ -64,11 +69,13 @@ std::string RemoveWhitespace(const std::string& str) {
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomBrowserContext::AtomBrowserContext(
|
||||
const std::string& partition, bool in_memory,
|
||||
const base::DictionaryValue& options)
|
||||
AtomBrowserContext::AtomBrowserContext(const std::string& partition,
|
||||
bool in_memory,
|
||||
const base::DictionaryValue& options)
|
||||
: brightray::BrowserContext(partition, in_memory),
|
||||
network_delegate_(new AtomNetworkDelegate) {
|
||||
ct_delegate_(new AtomCTDelegate),
|
||||
network_delegate_(new AtomNetworkDelegate),
|
||||
cookie_delegate_(new AtomCookieDelegate) {
|
||||
// Construct user agent string.
|
||||
Browser* browser = Browser::Get();
|
||||
std::string name = RemoveWhitespace(browser->GetName());
|
||||
@@ -104,6 +111,10 @@ net::NetworkDelegate* AtomBrowserContext::CreateNetworkDelegate() {
|
||||
return network_delegate_;
|
||||
}
|
||||
|
||||
net::CookieMonsterDelegate* AtomBrowserContext::CreateCookieDelegate() {
|
||||
return cookie_delegate();
|
||||
}
|
||||
|
||||
std::string AtomBrowserContext::GetUserAgent() {
|
||||
return user_agent_;
|
||||
}
|
||||
@@ -120,6 +131,8 @@ AtomBrowserContext::CreateURLRequestJobFactory(
|
||||
}
|
||||
protocol_handlers->clear();
|
||||
|
||||
job_factory->SetProtocolHandler(url::kAboutScheme,
|
||||
base::WrapUnique(new AboutProtocolHandler));
|
||||
job_factory->SetProtocolHandler(
|
||||
url::kDataScheme, base::WrapUnique(new net::DataProtocolHandler));
|
||||
job_factory->SetProtocolHandler(
|
||||
@@ -182,7 +195,7 @@ content::PermissionManager* AtomBrowserContext::GetPermissionManager() {
|
||||
}
|
||||
|
||||
std::unique_ptr<net::CertVerifier> AtomBrowserContext::CreateCertVerifier() {
|
||||
return base::WrapUnique(new AtomCertVerifier);
|
||||
return base::WrapUnique(new AtomCertVerifier(ct_delegate_.get()));
|
||||
}
|
||||
|
||||
net::SSLConfigService* AtomBrowserContext::CreateSSLConfigService() {
|
||||
@@ -197,6 +210,11 @@ std::vector<std::string> AtomBrowserContext::GetCookieableSchemes() {
|
||||
return default_schemes;
|
||||
}
|
||||
|
||||
net::TransportSecurityState::RequireCTDelegate*
|
||||
AtomBrowserContext::GetRequireCTDelegate() {
|
||||
return ct_delegate_.get();
|
||||
}
|
||||
|
||||
void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
|
||||
pref_registry->RegisterFilePathPref(prefs::kSelectFileLastDirectory,
|
||||
base::FilePath());
|
||||
@@ -207,6 +225,19 @@ void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
|
||||
pref_registry->RegisterDictionaryPref(prefs::kDevToolsFileSystemPaths);
|
||||
}
|
||||
|
||||
AtomBlobReader* AtomBrowserContext::GetBlobReader() {
|
||||
if (!blob_reader_.get()) {
|
||||
content::ChromeBlobStorageContext* blob_context =
|
||||
content::ChromeBlobStorageContext::GetFor(this);
|
||||
storage::FileSystemContext* file_system_context =
|
||||
content::BrowserContext::GetStoragePartition(
|
||||
this, nullptr)->GetFileSystemContext();
|
||||
blob_reader_.reset(new AtomBlobReader(blob_context,
|
||||
file_system_context));
|
||||
}
|
||||
return blob_reader_.get();
|
||||
}
|
||||
|
||||
// static
|
||||
scoped_refptr<AtomBrowserContext> AtomBrowserContext::From(
|
||||
const std::string& partition, bool in_memory,
|
||||
|
||||
@@ -8,10 +8,14 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/net/atom_cookie_delegate.h"
|
||||
#include "brightray/browser/browser_context.h"
|
||||
#include "net/cookies/cookie_monster.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBlobReader;
|
||||
class AtomCTDelegate;
|
||||
class AtomDownloadManagerDelegate;
|
||||
class AtomNetworkDelegate;
|
||||
class AtomPermissionManager;
|
||||
@@ -30,6 +34,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
|
||||
// brightray::URLRequestContextGetter::Delegate:
|
||||
net::NetworkDelegate* CreateNetworkDelegate() override;
|
||||
net::CookieMonsterDelegate* CreateCookieDelegate() override;
|
||||
std::string GetUserAgent() override;
|
||||
std::unique_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory(
|
||||
content::ProtocolHandlerMap* protocol_handlers) override;
|
||||
@@ -38,6 +43,8 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
std::unique_ptr<net::CertVerifier> CreateCertVerifier() override;
|
||||
net::SSLConfigService* CreateSSLConfigService() override;
|
||||
std::vector<std::string> GetCookieableSchemes() override;
|
||||
net::TransportSecurityState::RequireCTDelegate* GetRequireCTDelegate()
|
||||
override;
|
||||
|
||||
// content::BrowserContext:
|
||||
content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
|
||||
@@ -47,7 +54,11 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
// brightray::BrowserContext:
|
||||
void RegisterPrefs(PrefRegistrySimple* pref_registry) override;
|
||||
|
||||
AtomBlobReader* GetBlobReader();
|
||||
AtomNetworkDelegate* network_delegate() const { return network_delegate_; }
|
||||
AtomCookieDelegate* cookie_delegate() const {
|
||||
return cookie_delegate_.get();
|
||||
}
|
||||
|
||||
protected:
|
||||
AtomBrowserContext(const std::string& partition, bool in_memory,
|
||||
@@ -58,11 +69,14 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
std::unique_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
|
||||
std::unique_ptr<WebViewManager> guest_manager_;
|
||||
std::unique_ptr<AtomPermissionManager> permission_manager_;
|
||||
std::unique_ptr<AtomBlobReader> blob_reader_;
|
||||
std::unique_ptr<AtomCTDelegate> ct_delegate_;
|
||||
std::string user_agent_;
|
||||
bool use_cache_;
|
||||
|
||||
// Managed by brightray::BrowserContext.
|
||||
AtomNetworkDelegate* network_delegate_;
|
||||
scoped_refptr<AtomCookieDelegate> cookie_delegate_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext);
|
||||
};
|
||||
|
||||
@@ -117,7 +117,7 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
|
||||
if (node_debugger_->IsRunning())
|
||||
env->AssignToContext(v8::Debug::GetDebugContext());
|
||||
|
||||
// Add atom-shell extended APIs.
|
||||
// Add Electron extended APIs.
|
||||
atom_bindings_->BindTo(js_env_->isolate(), env->process_object());
|
||||
|
||||
// Load everything.
|
||||
|
||||
@@ -60,7 +60,7 @@ void AtomDownloadManagerDelegate::CreateDownloadPath(
|
||||
std::string(),
|
||||
suggested_filename,
|
||||
mime_type,
|
||||
std::string());
|
||||
"download");
|
||||
|
||||
if (!base::PathExists(default_download_path))
|
||||
base::CreateDirectory(default_download_path);
|
||||
|
||||
@@ -5,20 +5,49 @@
|
||||
#include "atom/browser/atom_javascript_dialog_manager.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/ui/message_box.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "ui/gfx/image/image_skia.h"
|
||||
|
||||
using content::JavaScriptMessageType;
|
||||
|
||||
namespace atom {
|
||||
|
||||
void AtomJavaScriptDialogManager::RunJavaScriptDialog(
|
||||
content::WebContents* web_contents,
|
||||
const GURL& origin_url,
|
||||
content::JavaScriptMessageType javascript_message_type,
|
||||
JavaScriptMessageType message_type,
|
||||
const base::string16& message_text,
|
||||
const base::string16& default_prompt_text,
|
||||
const DialogClosedCallback& callback,
|
||||
bool* did_suppress_message) {
|
||||
callback.Run(false, base::string16());
|
||||
|
||||
if (message_type != JavaScriptMessageType::JAVASCRIPT_MESSAGE_TYPE_ALERT &&
|
||||
message_type != JavaScriptMessageType::JAVASCRIPT_MESSAGE_TYPE_CONFIRM) {
|
||||
callback.Run(false, base::string16());
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> buttons = {"OK"};
|
||||
if (message_type == JavaScriptMessageType::JAVASCRIPT_MESSAGE_TYPE_CONFIRM) {
|
||||
buttons.push_back("Cancel");
|
||||
}
|
||||
|
||||
atom::ShowMessageBox(NativeWindow::FromWebContents(web_contents),
|
||||
atom::MessageBoxType::MESSAGE_BOX_TYPE_NONE,
|
||||
buttons,
|
||||
-1,
|
||||
0,
|
||||
atom::MessageBoxOptions::MESSAGE_BOX_NONE,
|
||||
"",
|
||||
base::UTF16ToUTF8(message_text),
|
||||
"",
|
||||
gfx::ImageSkia(),
|
||||
base::Bind(&OnMessageBoxCallback, callback));
|
||||
}
|
||||
|
||||
void AtomJavaScriptDialogManager::RunBeforeUnloadDialog(
|
||||
@@ -29,4 +58,10 @@ void AtomJavaScriptDialogManager::RunBeforeUnloadDialog(
|
||||
callback.Run(false, base::ASCIIToUTF16("This should not be displayed"));
|
||||
}
|
||||
|
||||
// static
|
||||
void AtomJavaScriptDialogManager::OnMessageBoxCallback(
|
||||
const DialogClosedCallback& callback, int code) {
|
||||
callback.Run(code == 0, base::string16());
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -29,6 +29,10 @@ class AtomJavaScriptDialogManager : public content::JavaScriptDialogManager {
|
||||
void CancelActiveAndPendingDialogs(
|
||||
content::WebContents* web_contents) override {}
|
||||
void ResetDialogState(content::WebContents* web_contents) override {};
|
||||
|
||||
private:
|
||||
static void OnMessageBoxCallback(const DialogClosedCallback& callback,
|
||||
int code);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -10,8 +10,17 @@
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "net/base/escape.h"
|
||||
#include "net/ssl/client_cert_store.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
#include "net/ssl/client_cert_store_nss.h"
|
||||
#elif defined(OS_WIN)
|
||||
#include "net/ssl/client_cert_store_win.h"
|
||||
#elif defined(OS_MACOSX)
|
||||
#include "net/ssl/client_cert_store_mac.h"
|
||||
#endif
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
@@ -59,7 +68,8 @@ bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol(
|
||||
const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
|
||||
bool is_main_frame,
|
||||
ui::PageTransition transition,
|
||||
bool has_user_gesture) {
|
||||
bool has_user_gesture,
|
||||
content::ResourceContext* resource_context) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&HandleExternalProtocolInUI,
|
||||
url,
|
||||
@@ -75,4 +85,19 @@ AtomResourceDispatcherHostDelegate::CreateLoginDelegate(
|
||||
return new LoginHandler(auth_info, request);
|
||||
}
|
||||
|
||||
std::unique_ptr<net::ClientCertStore>
|
||||
AtomResourceDispatcherHostDelegate::CreateClientCertStore(
|
||||
content::ResourceContext* resource_context) {
|
||||
#if defined(USE_NSS_CERTS)
|
||||
return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(
|
||||
net::ClientCertStoreNSS::PasswordDelegateFactory()));
|
||||
#elif defined(OS_WIN)
|
||||
return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
|
||||
#elif defined(OS_MACOSX)
|
||||
return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
|
||||
#elif defined(USE_OPENSSL)
|
||||
return std::unique_ptr<net::ClientCertStore>();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -21,10 +21,13 @@ class AtomResourceDispatcherHostDelegate
|
||||
const content::ResourceRequestInfo::WebContentsGetter&,
|
||||
bool is_main_frame,
|
||||
ui::PageTransition transition,
|
||||
bool has_user_gesture) override;
|
||||
bool has_user_gesture,
|
||||
content::ResourceContext* resource_context) override;
|
||||
content::ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
|
||||
net::AuthChallengeInfo* auth_info,
|
||||
net::URLRequest* request) override;
|
||||
std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
|
||||
content::ResourceContext* resource_context) override;
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -27,7 +27,7 @@ bool BridgeTaskRunner::PostDelayedTask(
|
||||
base::TimeDelta delay) {
|
||||
auto message_loop = base::MessageLoop::current();
|
||||
if (!message_loop) {
|
||||
tasks_.push_back(base::MakeTuple(from_here, task, delay));
|
||||
tasks_.push_back(std::make_tuple(from_here, task, delay));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ bool BridgeTaskRunner::PostNonNestableDelayedTask(
|
||||
base::TimeDelta delay) {
|
||||
auto message_loop = base::MessageLoop::current();
|
||||
if (!message_loop) {
|
||||
non_nestable_tasks_.push_back(base::MakeTuple(from_here, task, delay));
|
||||
non_nestable_tasks_.push_back(std::make_tuple(from_here, task, delay));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_
|
||||
#define ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "base/single_thread_task_runner.h"
|
||||
@@ -33,7 +34,7 @@ class BridgeTaskRunner : public base::SingleThreadTaskRunner {
|
||||
base::TimeDelta delay) override;
|
||||
|
||||
private:
|
||||
using TaskPair = base::Tuple<
|
||||
using TaskPair = std::tuple<
|
||||
tracked_objects::Location, base::Closure, base::TimeDelta>;
|
||||
std::vector<TaskPair> tasks_;
|
||||
std::vector<TaskPair> non_nestable_tasks_;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "base/macros.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "base/values.h"
|
||||
#include "native_mate/arguments.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -21,7 +22,6 @@
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
class FilePath;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class Browser : public WindowListObserver {
|
||||
// Overrides the application version.
|
||||
void SetVersion(const std::string& version);
|
||||
|
||||
// Returns the application's name, default is just Atom-Shell.
|
||||
// Returns the application's name, default is just Electron.
|
||||
std::string GetName() const;
|
||||
|
||||
// Overrides the application name.
|
||||
@@ -146,6 +146,9 @@ class Browser : public WindowListObserver {
|
||||
|
||||
// Set docks' icon.
|
||||
void DockSetIcon(const gfx::Image& image);
|
||||
|
||||
void ShowAboutPanel();
|
||||
void SetAboutPanelOptions(const base::DictionaryValue& options);
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -245,6 +248,10 @@ class Browser : public WindowListObserver {
|
||||
base::string16 app_user_model_id_;
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
base::DictionaryValue about_panel_options_;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Browser);
|
||||
};
|
||||
|
||||
|
||||
@@ -253,4 +253,36 @@ void Browser::DockSetIcon(const gfx::Image& image) {
|
||||
setApplicationIconImage:image.AsNSImage()];
|
||||
}
|
||||
|
||||
void Browser::ShowAboutPanel() {
|
||||
NSDictionary* options = DictionaryValueToNSDictionary(about_panel_options_);
|
||||
|
||||
// Credits must be a NSAttributedString instead of NSString
|
||||
id credits = options[@"Credits"];
|
||||
if (credits != nil) {
|
||||
NSMutableDictionary* mutable_options = [options mutableCopy];
|
||||
mutable_options[@"Credits"] = [[[NSAttributedString alloc]
|
||||
initWithString:(NSString*)credits] autorelease];
|
||||
options = [NSDictionary dictionaryWithDictionary:mutable_options];
|
||||
}
|
||||
|
||||
[[AtomApplication sharedApplication]
|
||||
orderFrontStandardAboutPanelWithOptions:options];
|
||||
}
|
||||
|
||||
void Browser::SetAboutPanelOptions(const base::DictionaryValue& options) {
|
||||
about_panel_options_.Clear();
|
||||
|
||||
// Upper case option keys for orderFrontStandardAboutPanelWithOptions format
|
||||
for (base::DictionaryValue::Iterator iter(options);
|
||||
!iter.IsAtEnd();
|
||||
iter.Advance()) {
|
||||
std::string key = iter.key();
|
||||
std::string value;
|
||||
if (!key.empty() && iter.value().GetAsString(&value)) {
|
||||
key[0] = base::ToUpperASCII(key[0]);
|
||||
about_panel_options_.SetString(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -252,11 +252,11 @@ content::ColorChooser* CommonWebContentsDelegate::OpenColorChooser(
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::RunFileChooser(
|
||||
content::WebContents* guest,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const content::FileChooserParams& params) {
|
||||
if (!web_dialog_helper_)
|
||||
web_dialog_helper_.reset(new WebDialogHelper(owner_window()));
|
||||
web_dialog_helper_->RunFileChooser(guest, params);
|
||||
web_dialog_helper_->RunFileChooser(render_frame_host, params);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::EnumerateDirectory(content::WebContents* guest,
|
||||
|
||||
@@ -71,7 +71,7 @@ class CommonWebContentsDelegate
|
||||
content::WebContents* web_contents,
|
||||
SkColor color,
|
||||
const std::vector<content::ColorSuggestion>& suggestions) override;
|
||||
void RunFileChooser(content::WebContents* web_contents,
|
||||
void RunFileChooser(content::RenderFrameHost* render_frame_host,
|
||||
const content::FileChooserParams& params) override;
|
||||
void EnumerateDirectory(content::WebContents* web_contents,
|
||||
int request_id,
|
||||
|
||||
@@ -87,4 +87,8 @@
|
||||
atom::Browser::Get()->OnAccessibilitySupportChanged();
|
||||
}
|
||||
|
||||
- (void)orderFrontStandardAboutPanel:(id)sender {
|
||||
atom::Browser::Get()->ShowAboutPanel();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "base/values.h"
|
||||
|
||||
@interface NSWindow (SierraSDK)
|
||||
@property(class) BOOL allowsAutomaticWindowTabbing;
|
||||
@end
|
||||
|
||||
@implementation AtomApplicationDelegate
|
||||
|
||||
- (void)setApplicationDockMenu:(atom::AtomMenuModel*)model {
|
||||
@@ -21,6 +25,10 @@
|
||||
// Don't add the "Enter Full Screen" menu item automatically.
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
|
||||
|
||||
// Don't add the "Show Tab Bar" menu item.
|
||||
if ([NSWindow respondsToSelector:@selector(allowsAutomaticWindowTabbing)])
|
||||
NSWindow.allowsAutomaticWindowTabbing = NO;
|
||||
|
||||
atom::Browser::Get()->WillFinishLaunching();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,15 @@ class DictionaryValue;
|
||||
|
||||
namespace atom {
|
||||
|
||||
NSArray* ListValueToNSArray(const base::ListValue& value);
|
||||
|
||||
std::unique_ptr<base::ListValue> NSArrayToListValue(NSArray* arr);
|
||||
|
||||
NSDictionary* DictionaryValueToNSDictionary(const base::DictionaryValue& value);
|
||||
|
||||
std::unique_ptr<base::DictionaryValue> NSDictionaryToDictionaryValue(
|
||||
NSDictionary* dict);
|
||||
|
||||
std::unique_ptr<base::ListValue> NSArrayToListValue(NSArray* arr);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_MAC_DICT_UTIL_H_
|
||||
|
||||
@@ -10,6 +10,18 @@
|
||||
|
||||
namespace atom {
|
||||
|
||||
NSArray* ListValueToNSArray(const base::ListValue& value) {
|
||||
std::string json;
|
||||
if (!base::JSONWriter::Write(value, &json))
|
||||
return nil;
|
||||
NSData* jsonData = [NSData dataWithBytes:json.c_str() length:json.length()];
|
||||
id obj =
|
||||
[NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
|
||||
if (![obj isKindOfClass:[NSArray class]])
|
||||
return nil;
|
||||
return obj;
|
||||
}
|
||||
|
||||
std::unique_ptr<base::ListValue> NSArrayToListValue(NSArray* arr) {
|
||||
if (!arr)
|
||||
return nullptr;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/skia/include/core/SkRegion.h"
|
||||
#include "ui/gfx/codec/png_codec.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
@@ -332,6 +333,12 @@ void NativeWindow::SetParentWindow(NativeWindow* parent) {
|
||||
parent_ = parent;
|
||||
}
|
||||
|
||||
void NativeWindow::SetAutoHideCursor(bool auto_hide) {
|
||||
}
|
||||
|
||||
void NativeWindow::SetVibrancy(const std::string& filename) {
|
||||
}
|
||||
|
||||
void NativeWindow::FocusOnWebView() {
|
||||
web_contents()->GetRenderViewHost()->GetWidget()->Focus();
|
||||
}
|
||||
@@ -373,6 +380,13 @@ void NativeWindow::SetAspectRatio(double aspect_ratio,
|
||||
aspect_ratio_extraSize_ = extra_size;
|
||||
}
|
||||
|
||||
void NativeWindow::PreviewFile(const std::string& path,
|
||||
const std::string& display_name) {
|
||||
}
|
||||
|
||||
void NativeWindow::CloseFilePreview() {
|
||||
}
|
||||
|
||||
void NativeWindow::RequestToClosePage() {
|
||||
bool prevent_default = false;
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver,
|
||||
@@ -390,6 +404,10 @@ void NativeWindow::RequestToClosePage() {
|
||||
if (window_unresposive_closure_.IsCancelled())
|
||||
ScheduleUnresponsiveEvent(5000);
|
||||
|
||||
if (!web_contents())
|
||||
// Already closed by renderer
|
||||
return;
|
||||
|
||||
if (web_contents()->NeedToFireBeforeUnload())
|
||||
web_contents()->DispatchBeforeUnload();
|
||||
else
|
||||
@@ -503,6 +521,11 @@ void NativeWindow::NotifyWindowScrollTouchEnd() {
|
||||
OnWindowScrollTouchEnd());
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowScrollTouchEdge() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_,
|
||||
OnWindowScrollTouchEdge());
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowSwipe(const std::string& direction) {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_,
|
||||
OnWindowSwipe(direction));
|
||||
|
||||
@@ -118,7 +118,8 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual bool IsFullScreenable() = 0;
|
||||
virtual void SetClosable(bool closable) = 0;
|
||||
virtual bool IsClosable() = 0;
|
||||
virtual void SetAlwaysOnTop(bool top) = 0;
|
||||
virtual void SetAlwaysOnTop(bool top,
|
||||
const std::string& level = "floating") = 0;
|
||||
virtual bool IsAlwaysOnTop() = 0;
|
||||
virtual void Center() = 0;
|
||||
virtual void SetTitle(const std::string& title) = 0;
|
||||
@@ -160,6 +161,11 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual void SetVisibleOnAllWorkspaces(bool visible) = 0;
|
||||
virtual bool IsVisibleOnAllWorkspaces() = 0;
|
||||
|
||||
virtual void SetAutoHideCursor(bool auto_hide);
|
||||
|
||||
// Vibrancy API
|
||||
virtual void SetVibrancy(const std::string& type);
|
||||
|
||||
// Webview APIs.
|
||||
virtual void FocusOnWebView();
|
||||
virtual void BlurWebView();
|
||||
@@ -176,6 +182,11 @@ class NativeWindow : public base::SupportsUserData,
|
||||
gfx::Size GetAspectRatioExtraSize();
|
||||
virtual void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size);
|
||||
|
||||
// File preview APIs.
|
||||
virtual void PreviewFile(const std::string& path,
|
||||
const std::string& display_name);
|
||||
virtual void CloseFilePreview();
|
||||
|
||||
base::WeakPtr<NativeWindow> GetWeakPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
@@ -207,6 +218,7 @@ class NativeWindow : public base::SupportsUserData,
|
||||
void NotifyWindowMoved();
|
||||
void NotifyWindowScrollTouchBegin();
|
||||
void NotifyWindowScrollTouchEnd();
|
||||
void NotifyWindowScrollTouchEdge();
|
||||
void NotifyWindowSwipe(const std::string& direction);
|
||||
void NotifyWindowEnterFullScreen();
|
||||
void NotifyWindowLeaveFullScreen();
|
||||
|
||||
@@ -55,6 +55,9 @@ class NativeWindowMac : public NativeWindow,
|
||||
void SetMovable(bool movable) override;
|
||||
void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size)
|
||||
override;
|
||||
void PreviewFile(const std::string& path, const std::string& display_name)
|
||||
override;
|
||||
void CloseFilePreview() override;
|
||||
bool IsMovable() override;
|
||||
void SetMinimizable(bool minimizable) override;
|
||||
bool IsMinimizable() override;
|
||||
@@ -64,7 +67,7 @@ class NativeWindowMac : public NativeWindow,
|
||||
bool IsFullScreenable() override;
|
||||
void SetClosable(bool closable) override;
|
||||
bool IsClosable() override;
|
||||
void SetAlwaysOnTop(bool top) override;
|
||||
void SetAlwaysOnTop(bool top, const std::string& level) override;
|
||||
bool IsAlwaysOnTop() override;
|
||||
void Center() override;
|
||||
void SetTitle(const std::string& title) override;
|
||||
@@ -88,9 +91,14 @@ class NativeWindowMac : public NativeWindow,
|
||||
void SetProgressBar(double progress, const ProgressState state) override;
|
||||
void SetOverlayIcon(const gfx::Image& overlay,
|
||||
const std::string& description) override;
|
||||
|
||||
void SetVisibleOnAllWorkspaces(bool visible) override;
|
||||
bool IsVisibleOnAllWorkspaces() override;
|
||||
|
||||
void SetAutoHideCursor(bool auto_hide) override;
|
||||
|
||||
void SetVibrancy(const std::string& type) override;
|
||||
|
||||
// content::RenderWidgetHost::InputEventObserver:
|
||||
void OnInputEvent(const blink::WebInputEvent& event) override;
|
||||
|
||||
@@ -114,6 +122,8 @@ class NativeWindowMac : public NativeWindow,
|
||||
};
|
||||
TitleBarStyle title_bar_style() const { return title_bar_style_; }
|
||||
|
||||
bool zoom_to_page_width() const { return zoom_to_page_width_; }
|
||||
|
||||
protected:
|
||||
// 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.
|
||||
@@ -152,6 +162,10 @@ class NativeWindowMac : public NativeWindow,
|
||||
|
||||
bool is_kiosk_;
|
||||
|
||||
bool was_fullscreen_;
|
||||
|
||||
bool zoom_to_page_width_;
|
||||
|
||||
NSInteger attention_request_id_; // identifier from requestUserAttention
|
||||
|
||||
// The presentation options before entering kiosk mode.
|
||||
@@ -160,9 +174,6 @@ class NativeWindowMac : public NativeWindow,
|
||||
// The "titleBarStyle" option.
|
||||
TitleBarStyle title_bar_style_;
|
||||
|
||||
// Whether user has scrolled the page to edge.
|
||||
bool is_edge_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NativeWindowMac);
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "atom/browser/native_window_mac.h"
|
||||
|
||||
#include <Quartz/Quartz.h>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/window_list.h"
|
||||
@@ -22,6 +23,7 @@
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "skia/ext/skia_utils_mac.h"
|
||||
#include "third_party/skia/include/core/SkRegion.h"
|
||||
#include "ui/gfx/skia_util.h"
|
||||
|
||||
namespace {
|
||||
@@ -100,6 +102,41 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Called when the user clicks the zoom button or selects it from the Window
|
||||
// menu to determine the "standard size" of the window.
|
||||
- (NSRect)windowWillUseStandardFrame:(NSWindow*)window
|
||||
defaultFrame:(NSRect)frame {
|
||||
if (!shell_->zoom_to_page_width())
|
||||
return frame;
|
||||
|
||||
// If the shift key is down, maximize.
|
||||
if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask)
|
||||
return frame;
|
||||
|
||||
content::WebContents* web_contents = shell_->web_contents();
|
||||
if (!web_contents)
|
||||
return frame;
|
||||
|
||||
CGFloat page_width = static_cast<CGFloat>(
|
||||
web_contents->GetPreferredSize().width());
|
||||
NSRect window_frame = [window frame];
|
||||
|
||||
// Never shrink from the current size on zoom.
|
||||
CGFloat zoomed_width = std::max(page_width, NSWidth(window_frame));
|
||||
|
||||
// |frame| determines our maximum extents. We need to set the origin of the
|
||||
// frame -- and only move it left if necessary.
|
||||
if (window_frame.origin.x + zoomed_width > NSMaxX(frame))
|
||||
frame.origin.x = NSMaxX(frame) - zoomed_width;
|
||||
else
|
||||
frame.origin.x = window_frame.origin.x;
|
||||
|
||||
// Set the width. Don't touch y or height.
|
||||
frame.size.width = zoomed_width;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeMain:(NSNotification*)notification {
|
||||
content::WebContents* web_contents = shell_->web_contents();
|
||||
if (!web_contents)
|
||||
@@ -276,7 +313,29 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||
|
||||
@end
|
||||
|
||||
@interface AtomNSWindow : EventDispatchingWindow {
|
||||
@interface AtomPreviewItem : NSObject <QLPreviewItem>
|
||||
|
||||
@property (nonatomic, retain) NSURL* previewItemURL;
|
||||
@property (nonatomic, retain) NSString* previewItemTitle;
|
||||
|
||||
- (id)initWithURL:(NSURL*)url title:(NSString*)title;
|
||||
|
||||
@end
|
||||
|
||||
@implementation AtomPreviewItem
|
||||
|
||||
- (id)initWithURL:(NSURL*)url title:(NSString*)title {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.previewItemURL = url;
|
||||
self.previewItemTitle = title;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface AtomNSWindow : EventDispatchingWindow<QLPreviewPanelDataSource, QLPreviewPanelDelegate> {
|
||||
@private
|
||||
atom::NativeWindowMac* shell_;
|
||||
bool enable_larger_than_screen_;
|
||||
@@ -286,6 +345,8 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||
@property BOOL disableAutoHideCursor;
|
||||
@property BOOL disableKeyOrMainWindow;
|
||||
@property NSPoint windowButtonsOffset;
|
||||
@property (nonatomic, retain) AtomPreviewItem* quickLookItem;
|
||||
@property (nonatomic, retain) NSView* vibrantView;
|
||||
|
||||
- (void)setShell:(atom::NativeWindowMac*)shell;
|
||||
- (void)setEnableLargerThanScreen:(bool)enable;
|
||||
@@ -443,6 +504,36 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||
return [[self contentView] superview];
|
||||
}
|
||||
|
||||
// Quicklook methods
|
||||
|
||||
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel*)panel {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)beginPreviewPanelControl:(QLPreviewPanel*)panel {
|
||||
panel.delegate = self;
|
||||
panel.dataSource = self;
|
||||
}
|
||||
|
||||
- (void)endPreviewPanelControl:(QLPreviewPanel*)panel {
|
||||
panel.delegate = nil;
|
||||
panel.dataSource = nil;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel*)panel {
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel*)panel previewItemAtIndex:(NSInteger)index {
|
||||
return [self quickLookItem];
|
||||
}
|
||||
|
||||
- (void)previewFileAtPath:(NSString*)path withName:(NSString*) fileName {
|
||||
NSURL* url = [[[NSURL alloc] initFileURLWithPath:path] autorelease];
|
||||
[self setQuickLookItem:[[[AtomPreviewItem alloc] initWithURL:url title:fileName] autorelease]];
|
||||
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface ControlRegionView : NSView
|
||||
@@ -528,14 +619,15 @@ NativeWindowMac::NativeWindowMac(
|
||||
NativeWindow* parent)
|
||||
: NativeWindow(web_contents, options, parent),
|
||||
is_kiosk_(false),
|
||||
was_fullscreen_(false),
|
||||
zoom_to_page_width_(false),
|
||||
attention_request_id_(0),
|
||||
title_bar_style_(NORMAL),
|
||||
is_edge_(false) {
|
||||
title_bar_style_(NORMAL) {
|
||||
int width = 800, height = 600;
|
||||
options.Get(options::kWidth, &width);
|
||||
options.Get(options::kHeight, &height);
|
||||
|
||||
NSRect main_screen_rect = [[[NSScreen screens] objectAtIndex:0] frame];
|
||||
NSRect main_screen_rect = [[[NSScreen screens] firstObject] frame];
|
||||
NSRect cocoa_bounds = NSMakeRect(
|
||||
round((NSWidth(main_screen_rect) - width) / 2) ,
|
||||
round((NSHeight(main_screen_rect) - height) / 2),
|
||||
@@ -651,6 +743,8 @@ NativeWindowMac::NativeWindowMac(
|
||||
if (!has_frame() || !use_content_size)
|
||||
SetSize(gfx::Size(width, height));
|
||||
|
||||
options.Get(options::kZoomToPageWidth, &zoom_to_page_width_);
|
||||
|
||||
// Enable the NSView to accept first mouse event.
|
||||
bool acceptsFirstMouse = false;
|
||||
options.Get(options::kAcceptFirstMouse, &acceptsFirstMouse);
|
||||
@@ -675,22 +769,25 @@ NativeWindowMac::NativeWindowMac(
|
||||
if (!web_contents)
|
||||
return event;
|
||||
|
||||
if (!began && is_edge_ && (([event phase] == NSEventPhaseMayBegin) ||
|
||||
if (!began && (([event phase] == NSEventPhaseMayBegin) ||
|
||||
([event phase] == NSEventPhaseBegan))) {
|
||||
this->NotifyWindowScrollTouchBegin();
|
||||
began = YES;
|
||||
is_edge_ = false;
|
||||
} else if (began && (([event phase] == NSEventPhaseEnded) ||
|
||||
([event phase] == NSEventPhaseCancelled))) {
|
||||
this->NotifyWindowScrollTouchEnd();
|
||||
began = NO;
|
||||
is_edge_ = false;
|
||||
}
|
||||
return event;
|
||||
}];
|
||||
|
||||
InstallView();
|
||||
|
||||
std::string type;
|
||||
if (options.Get(options::kVibrancyType, &type)) {
|
||||
SetVibrancy(type);
|
||||
}
|
||||
|
||||
// Set maximizable state last to ensure zoom button does not get reset
|
||||
// by calls to other APIs.
|
||||
SetMaximizable(maximizable);
|
||||
@@ -742,8 +839,9 @@ bool NativeWindowMac::IsFocused() {
|
||||
|
||||
void NativeWindowMac::Show() {
|
||||
if (is_modal() && parent()) {
|
||||
[parent()->GetNativeWindow() beginSheet:window_
|
||||
completionHandler:^(NSModalResponse) {}];
|
||||
if ([window_ sheetParent] == nil)
|
||||
[parent()->GetNativeWindow() beginSheet:window_
|
||||
completionHandler:^(NSModalResponse) {}];
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -840,7 +938,7 @@ void NativeWindowMac::SetBounds(const gfx::Rect& bounds, bool animate) {
|
||||
|
||||
NSRect cocoa_bounds = NSMakeRect(bounds.x(), 0, size.width(), size.height());
|
||||
// Flip coordinates based on the primary screen.
|
||||
NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
|
||||
NSScreen* screen = [[NSScreen screens] firstObject];
|
||||
cocoa_bounds.origin.y =
|
||||
NSHeight([screen frame]) - size.height() - bounds.y();
|
||||
|
||||
@@ -850,7 +948,7 @@ void NativeWindowMac::SetBounds(const gfx::Rect& bounds, bool animate) {
|
||||
gfx::Rect NativeWindowMac::GetBounds() {
|
||||
NSRect frame = [window_ frame];
|
||||
gfx::Rect bounds(frame.origin.x, 0, NSWidth(frame), NSHeight(frame));
|
||||
NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
|
||||
NSScreen* screen = [[NSScreen screens] firstObject];
|
||||
bounds.set_y(NSHeight([screen frame]) - NSMaxY(frame));
|
||||
return bounds;
|
||||
}
|
||||
@@ -900,6 +998,19 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio,
|
||||
[window_ setResizeIncrements:NSMakeSize(1.0, 1.0)];
|
||||
}
|
||||
|
||||
void NativeWindowMac::PreviewFile(const std::string& path,
|
||||
const std::string& display_name) {
|
||||
NSString* path_ns = [NSString stringWithUTF8String:path.c_str()];
|
||||
NSString* name_ns = [NSString stringWithUTF8String:display_name.c_str()];
|
||||
[window_ previewFileAtPath:path_ns withName:name_ns];
|
||||
}
|
||||
|
||||
void NativeWindowMac::CloseFilePreview() {
|
||||
if ([QLPreviewPanel sharedPreviewPanelExists]) {
|
||||
[[QLPreviewPanel sharedPreviewPanel] close];
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetMovable(bool movable) {
|
||||
[window_ setMovable:movable];
|
||||
}
|
||||
@@ -945,12 +1056,33 @@ bool NativeWindowMac::IsClosable() {
|
||||
return [window_ styleMask] & NSClosableWindowMask;
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetAlwaysOnTop(bool top) {
|
||||
[window_ setLevel:(top ? NSFloatingWindowLevel : NSNormalWindowLevel)];
|
||||
void NativeWindowMac::SetAlwaysOnTop(bool top, const std::string& level) {
|
||||
int windowLevel = NSNormalWindowLevel;
|
||||
if (top) {
|
||||
if (level == "floating") {
|
||||
windowLevel = NSFloatingWindowLevel;
|
||||
} else if (level == "torn-off-menu") {
|
||||
windowLevel = NSTornOffMenuWindowLevel;
|
||||
} else if (level == "modal-panel") {
|
||||
windowLevel = NSModalPanelWindowLevel;
|
||||
} else if (level == "main-menu") {
|
||||
windowLevel = NSMainMenuWindowLevel;
|
||||
} else if (level == "status") {
|
||||
windowLevel = NSStatusWindowLevel;
|
||||
} else if (level == "pop-up-menu") {
|
||||
windowLevel = NSPopUpMenuWindowLevel;
|
||||
} else if (level == "screen-saver") {
|
||||
windowLevel = NSScreenSaverWindowLevel;
|
||||
} else if (level == "dock") {
|
||||
// Deprecated by macOS, but kept for backwards compatibility
|
||||
windowLevel = NSDockWindowLevel;
|
||||
}
|
||||
}
|
||||
[window_ setLevel:windowLevel];
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsAlwaysOnTop() {
|
||||
return [window_ level] == NSFloatingWindowLevel;
|
||||
return [window_ level] != NSNormalWindowLevel;
|
||||
}
|
||||
|
||||
void NativeWindowMac::Center() {
|
||||
@@ -995,10 +1127,11 @@ void NativeWindowMac::SetKiosk(bool kiosk) {
|
||||
NSApplicationPresentationDisableHideApplication;
|
||||
[NSApp setPresentationOptions:options];
|
||||
is_kiosk_ = true;
|
||||
SetFullScreen(true);
|
||||
was_fullscreen_ = IsFullscreen();
|
||||
if (!was_fullscreen_) SetFullScreen(true);
|
||||
} else if (!kiosk && is_kiosk_) {
|
||||
is_kiosk_ = false;
|
||||
SetFullScreen(false);
|
||||
if (!was_fullscreen_) SetFullScreen(false);
|
||||
[NSApp setPresentationOptions:kiosk_options_];
|
||||
}
|
||||
}
|
||||
@@ -1009,8 +1142,8 @@ bool NativeWindowMac::IsKiosk() {
|
||||
|
||||
void NativeWindowMac::SetBackgroundColor(const std::string& color_name) {
|
||||
SkColor color = ParseHexColor(color_name);
|
||||
base::ScopedCFTypeRef<CGColorRef> cgcolor =
|
||||
skia::CGColorCreateFromSkColor(color);
|
||||
base::ScopedCFTypeRef<CGColorRef> cgcolor(
|
||||
skia::CGColorCreateFromSkColor(color));
|
||||
[[[window_ contentView] layer] setBackgroundColor:cgcolor];
|
||||
|
||||
const auto view = web_contents()->GetRenderWidgetHostView();
|
||||
@@ -1125,12 +1258,83 @@ bool NativeWindowMac::IsVisibleOnAllWorkspaces() {
|
||||
return collectionBehavior & NSWindowCollectionBehaviorCanJoinAllSpaces;
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetAutoHideCursor(bool auto_hide) {
|
||||
[window_ setDisableAutoHideCursor:!auto_hide];
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetVibrancy(const std::string& type) {
|
||||
if (!base::mac::IsOSYosemiteOrLater()) return;
|
||||
|
||||
NSView* vibrant_view = [window_ vibrantView];
|
||||
|
||||
if (type.empty()) {
|
||||
if (vibrant_view == nil) return;
|
||||
|
||||
[vibrant_view removeFromSuperview];
|
||||
[window_ setVibrantView:nil];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
NSVisualEffectView* effect_view = (NSVisualEffectView*)vibrant_view;
|
||||
if (effect_view == nil) {
|
||||
effect_view = [[[NSVisualEffectView alloc]
|
||||
initWithFrame: [[window_ contentView] bounds]] autorelease];
|
||||
[window_ setVibrantView:(NSView*)effect_view];
|
||||
|
||||
[effect_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[effect_view setBlendingMode:NSVisualEffectBlendingModeBehindWindow];
|
||||
[effect_view setState:NSVisualEffectStateActive];
|
||||
[[window_ contentView] addSubview:effect_view
|
||||
positioned:NSWindowBelow
|
||||
relativeTo:nil];
|
||||
}
|
||||
|
||||
NSVisualEffectMaterial vibrancyType = NSVisualEffectMaterialLight;
|
||||
|
||||
if (type == "appearance-based") {
|
||||
vibrancyType = NSVisualEffectMaterialAppearanceBased;
|
||||
} else if (type == "light") {
|
||||
vibrancyType = NSVisualEffectMaterialLight;
|
||||
} else if (type == "dark") {
|
||||
vibrancyType = NSVisualEffectMaterialDark;
|
||||
} else if (type == "titlebar") {
|
||||
vibrancyType = NSVisualEffectMaterialTitlebar;
|
||||
}
|
||||
|
||||
if (base::mac::IsOSElCapitanOrLater()) {
|
||||
// TODO(kevinsawicki): Use NSVisualEffectMaterial* constants directly once
|
||||
// they are available in the minimum SDK version
|
||||
if (type == "selection") {
|
||||
// NSVisualEffectMaterialSelection
|
||||
vibrancyType = (NSVisualEffectMaterial) 4;
|
||||
} else if (type == "menu") {
|
||||
// NSVisualEffectMaterialMenu
|
||||
vibrancyType = (NSVisualEffectMaterial) 5;
|
||||
} else if (type == "popover") {
|
||||
// NSVisualEffectMaterialPopover
|
||||
vibrancyType = (NSVisualEffectMaterial) 6;
|
||||
} else if (type == "sidebar") {
|
||||
// NSVisualEffectMaterialSidebar
|
||||
vibrancyType = (NSVisualEffectMaterial) 7;
|
||||
} else if (type == "medium-light") {
|
||||
// NSVisualEffectMaterialMediumLight
|
||||
vibrancyType = (NSVisualEffectMaterial) 8;
|
||||
} else if (type == "ultra-dark") {
|
||||
// NSVisualEffectMaterialUltraDark
|
||||
vibrancyType = (NSVisualEffectMaterial) 9;
|
||||
}
|
||||
}
|
||||
|
||||
[effect_view setMaterial:vibrancyType];
|
||||
}
|
||||
|
||||
void NativeWindowMac::OnInputEvent(const blink::WebInputEvent& event) {
|
||||
switch (event.type) {
|
||||
case blink::WebInputEvent::GestureScrollBegin:
|
||||
case blink::WebInputEvent::GestureScrollUpdate:
|
||||
case blink::WebInputEvent::GestureScrollEnd:
|
||||
is_edge_ = true;
|
||||
this->NotifyWindowScrollTouchEdge();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1200,10 +1404,10 @@ void NativeWindowMac::ShowWindowButton(NSWindowButton button) {
|
||||
}
|
||||
|
||||
void NativeWindowMac::InstallView() {
|
||||
// Make sure the bottom corner is rounded: http://crbug.com/396264.
|
||||
// Make sure the bottom corner is rounded for non-modal windows: http://crbug.com/396264.
|
||||
// But do not enable it on OS X 10.9 for transparent window, otherwise a
|
||||
// semi-transparent frame would show.
|
||||
if (!(transparent() && base::mac::IsOSMavericks()))
|
||||
if (!(transparent() && base::mac::IsOSMavericks()) && !is_modal())
|
||||
[[window_ contentView] setWantsLayer:YES];
|
||||
|
||||
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
|
||||
|
||||
@@ -64,6 +64,7 @@ class NativeWindowObserver {
|
||||
virtual void OnWindowMoved() {}
|
||||
virtual void OnWindowScrollTouchBegin() {}
|
||||
virtual void OnWindowScrollTouchEnd() {}
|
||||
virtual void OnWindowScrollTouchEdge() {}
|
||||
virtual void OnWindowSwipe(const std::string& direction) {}
|
||||
virtual void OnWindowEnterFullScreen() {}
|
||||
virtual void OnWindowLeaveFullScreen() {}
|
||||
|
||||
@@ -426,7 +426,7 @@ bool NativeWindowViews::IsEnabled() {
|
||||
void NativeWindowViews::Maximize() {
|
||||
#if defined(OS_WIN)
|
||||
// For window without WS_THICKFRAME style, we can not call Maximize().
|
||||
if (!thick_frame_) {
|
||||
if (!(::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME)) {
|
||||
restore_bounds_ = GetBounds();
|
||||
auto display =
|
||||
display::Screen::GetScreen()->GetDisplayNearestPoint(GetPosition());
|
||||
@@ -444,7 +444,7 @@ void NativeWindowViews::Maximize() {
|
||||
|
||||
void NativeWindowViews::Unmaximize() {
|
||||
#if defined(OS_WIN)
|
||||
if (!thick_frame_) {
|
||||
if (!(::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME)) {
|
||||
SetBounds(restore_bounds_, false);
|
||||
return;
|
||||
}
|
||||
@@ -488,6 +488,7 @@ void NativeWindowViews::SetFullScreen(bool fullscreen) {
|
||||
}
|
||||
|
||||
// For window without WS_THICKFRAME style, we can not call SetFullscreen().
|
||||
// This path will be used for transparent windows as well.
|
||||
if (!thick_frame_) {
|
||||
if (fullscreen) {
|
||||
restore_bounds_ = GetBounds();
|
||||
@@ -572,7 +573,7 @@ void NativeWindowViews::SetContentSizeConstraints(
|
||||
|
||||
void NativeWindowViews::SetResizable(bool resizable) {
|
||||
#if defined(OS_WIN)
|
||||
if (thick_frame_)
|
||||
if (has_frame())
|
||||
FlipWindowStyle(GetAcceleratedWidget(), resizable, WS_THICKFRAME);
|
||||
#elif defined(USE_X11)
|
||||
if (resizable != resizable_) {
|
||||
@@ -595,11 +596,10 @@ void NativeWindowViews::SetResizable(bool resizable) {
|
||||
|
||||
bool NativeWindowViews::IsResizable() {
|
||||
#if defined(OS_WIN)
|
||||
if (thick_frame_) {
|
||||
if (has_frame())
|
||||
return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME;
|
||||
} else {
|
||||
else
|
||||
return CanResize();
|
||||
}
|
||||
#else
|
||||
return CanResize();
|
||||
#endif
|
||||
@@ -682,7 +682,7 @@ bool NativeWindowViews::IsClosable() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetAlwaysOnTop(bool top) {
|
||||
void NativeWindowViews::SetAlwaysOnTop(bool top, const std::string& level) {
|
||||
window_->SetAlwaysOnTop(top);
|
||||
}
|
||||
|
||||
@@ -846,7 +846,7 @@ void NativeWindowViews::SetMenu(AtomMenuModel* menu_model) {
|
||||
|
||||
if (!menu_bar_) {
|
||||
gfx::Size content_size = GetContentSize();
|
||||
menu_bar_.reset(new MenuBar);
|
||||
menu_bar_.reset(new MenuBar(this));
|
||||
menu_bar_->set_owned_by_client();
|
||||
|
||||
if (!menu_bar_autohide_) {
|
||||
|
||||
@@ -86,7 +86,7 @@ class NativeWindowViews : public NativeWindow,
|
||||
bool IsFullScreenable() override;
|
||||
void SetClosable(bool closable) override;
|
||||
bool IsClosable() override;
|
||||
void SetAlwaysOnTop(bool top) override;
|
||||
void SetAlwaysOnTop(bool top, const std::string& level) override;
|
||||
bool IsAlwaysOnTop() override;
|
||||
void Center() override;
|
||||
void SetTitle(const std::string& title) override;
|
||||
@@ -216,6 +216,7 @@ class NativeWindowViews : public NativeWindow,
|
||||
// size of the window while in the normal state (not maximized, minimized or
|
||||
// fullscreen), so we restore it correctly.
|
||||
gfx::Rect last_normal_bounds_;
|
||||
gfx::Rect last_normal_bounds_before_move_;
|
||||
|
||||
// last_normal_bounds_ may or may not require update on WM_MOVE. When a
|
||||
// window is maximized, it is moved (WM_MOVE) to maximum size first and then
|
||||
|
||||
@@ -125,9 +125,12 @@ bool NativeWindowViews::PreHandleMSG(
|
||||
return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param));
|
||||
return false;
|
||||
case WM_SIZE: {
|
||||
consecutive_moves_ = false;
|
||||
// Handle window state change.
|
||||
HandleSizeEvent(w_param, l_param);
|
||||
|
||||
consecutive_moves_ = false;
|
||||
last_normal_bounds_before_move_ = last_normal_bounds_;
|
||||
|
||||
return false;
|
||||
}
|
||||
case WM_MOVING: {
|
||||
@@ -155,6 +158,9 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
|
||||
switch (w_param) {
|
||||
case SIZE_MAXIMIZED:
|
||||
last_window_state_ = ui::SHOW_STATE_MAXIMIZED;
|
||||
if (consecutive_moves_) {
|
||||
last_normal_bounds_ = last_normal_bounds_before_move_;
|
||||
}
|
||||
NotifyWindowMaximize();
|
||||
break;
|
||||
case SIZE_MINIMIZED:
|
||||
@@ -165,14 +171,14 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
|
||||
if (last_window_state_ == ui::SHOW_STATE_NORMAL) {
|
||||
// Window was resized so we save it's new size.
|
||||
last_normal_bounds_ = GetBounds();
|
||||
last_normal_bounds_before_move_ = last_normal_bounds_;
|
||||
} else {
|
||||
switch (last_window_state_) {
|
||||
case ui::SHOW_STATE_MAXIMIZED:
|
||||
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
||||
|
||||
// When the window is restored we resize it to the previous known
|
||||
// normal size.
|
||||
SetBounds(last_normal_bounds_, false);
|
||||
// Don't force out last known bounds onto the window as Windows
|
||||
// actually gets these correct
|
||||
|
||||
NotifyWindowUnmaximize();
|
||||
break;
|
||||
|
||||
25
atom/browser/net/about_protocol_handler.cc
Normal file
25
atom/browser/net/about_protocol_handler.cc
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/net/about_protocol_handler.h"
|
||||
|
||||
#include "atom/browser/net/url_request_about_job.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
AboutProtocolHandler::AboutProtocolHandler() {}
|
||||
|
||||
AboutProtocolHandler::~AboutProtocolHandler() {}
|
||||
|
||||
net::URLRequestJob* AboutProtocolHandler::MaybeCreateJob(
|
||||
net::URLRequest* request,
|
||||
net::NetworkDelegate* network_delegate) const {
|
||||
return new URLRequestAboutJob(request, network_delegate);
|
||||
}
|
||||
|
||||
bool AboutProtocolHandler::IsSafeRedirectTarget(const GURL& location) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
29
atom/browser/net/about_protocol_handler.h
Normal file
29
atom/browser/net/about_protocol_handler.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_NET_ABOUT_PROTOCOL_HANDLER_H_
|
||||
#define ATOM_BROWSER_NET_ABOUT_PROTOCOL_HANDLER_H_
|
||||
|
||||
#include "net/url_request/url_request_job_factory.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AboutProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
|
||||
public:
|
||||
AboutProtocolHandler();
|
||||
~AboutProtocolHandler() override;
|
||||
|
||||
// net::URLRequestJobFactory::ProtocolHandler:
|
||||
net::URLRequestJob* MaybeCreateJob(
|
||||
net::URLRequest* request,
|
||||
net::NetworkDelegate* network_delegate) const override;
|
||||
bool IsSafeRedirectTarget(const GURL& location) const override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AboutProtocolHandler);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_NET_ABOUT_PROTOCOL_HANDLER_H_
|
||||
@@ -5,9 +5,11 @@
|
||||
#include "atom/browser/net/atom_cert_verifier.h"
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/net/atom_ct_delegate.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "net/cert/cert_verify_result.h"
|
||||
#include "net/cert/crl_set.h"
|
||||
#include "net/cert/x509_certificate.h"
|
||||
|
||||
@@ -28,22 +30,18 @@ void OnResult(
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomCertVerifier::AtomCertVerifier()
|
||||
: default_cert_verifier_(net::CertVerifier::CreateDefault()) {
|
||||
}
|
||||
AtomCertVerifier::AtomCertVerifier(AtomCTDelegate* ct_delegate)
|
||||
: default_cert_verifier_(net::CertVerifier::CreateDefault()),
|
||||
ct_delegate_(ct_delegate) {}
|
||||
|
||||
AtomCertVerifier::~AtomCertVerifier() {
|
||||
}
|
||||
AtomCertVerifier::~AtomCertVerifier() {}
|
||||
|
||||
void AtomCertVerifier::SetVerifyProc(const VerifyProc& proc) {
|
||||
verify_proc_ = proc;
|
||||
}
|
||||
|
||||
int AtomCertVerifier::Verify(
|
||||
net::X509Certificate* cert,
|
||||
const std::string& hostname,
|
||||
const std::string& ocsp_response,
|
||||
int flags,
|
||||
const RequestParams& params,
|
||||
net::CRLSet* crl_set,
|
||||
net::CertVerifyResult* verify_result,
|
||||
const net::CompletionCallback& callback,
|
||||
@@ -51,14 +49,19 @@ int AtomCertVerifier::Verify(
|
||||
const net::BoundNetLog& net_log) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
if (verify_proc_.is_null())
|
||||
if (verify_proc_.is_null()) {
|
||||
ct_delegate_->ClearCTExcludedHostsList();
|
||||
return default_cert_verifier_->Verify(
|
||||
cert, hostname, ocsp_response, flags, crl_set, verify_result, callback,
|
||||
out_req, net_log);
|
||||
params, crl_set, verify_result, callback, out_req, net_log);
|
||||
}
|
||||
|
||||
verify_result->Reset();
|
||||
verify_result->verified_cert = params.certificate();
|
||||
ct_delegate_->AddCTExcludedHost(params.hostname());
|
||||
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(verify_proc_, hostname, make_scoped_refptr(cert),
|
||||
base::Bind(verify_proc_, params.hostname(), params.certificate(),
|
||||
base::Bind(OnResult, verify_result, callback)));
|
||||
return net::ERR_IO_PENDING;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomCTDelegate;
|
||||
|
||||
class AtomCertVerifier : public net::CertVerifier {
|
||||
public:
|
||||
AtomCertVerifier();
|
||||
explicit AtomCertVerifier(AtomCTDelegate* ct_delegate);
|
||||
virtual ~AtomCertVerifier();
|
||||
|
||||
using VerifyProc =
|
||||
@@ -26,10 +28,7 @@ class AtomCertVerifier : public net::CertVerifier {
|
||||
|
||||
protected:
|
||||
// net::CertVerifier:
|
||||
int Verify(net::X509Certificate* cert,
|
||||
const std::string& hostname,
|
||||
const std::string& ocsp_response,
|
||||
int flags,
|
||||
int Verify(const RequestParams& params,
|
||||
net::CRLSet* crl_set,
|
||||
net::CertVerifyResult* verify_result,
|
||||
const net::CompletionCallback& callback,
|
||||
@@ -40,6 +39,7 @@ class AtomCertVerifier : public net::CertVerifier {
|
||||
private:
|
||||
VerifyProc verify_proc_;
|
||||
std::unique_ptr<net::CertVerifier> default_cert_verifier_;
|
||||
AtomCTDelegate* ct_delegate_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier);
|
||||
};
|
||||
|
||||
41
atom/browser/net/atom_cookie_delegate.cc
Normal file
41
atom/browser/net/atom_cookie_delegate.cc
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/net/atom_cookie_delegate.h"
|
||||
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomCookieDelegate::AtomCookieDelegate() {
|
||||
}
|
||||
|
||||
AtomCookieDelegate::~AtomCookieDelegate() {
|
||||
}
|
||||
|
||||
void AtomCookieDelegate::AddObserver(Observer* observer) {
|
||||
observers_.AddObserver(observer);
|
||||
}
|
||||
|
||||
void AtomCookieDelegate::RemoveObserver(Observer* observer) {
|
||||
observers_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
void AtomCookieDelegate::NotifyObservers(
|
||||
const net::CanonicalCookie& cookie, bool removed, ChangeCause cause) {
|
||||
FOR_EACH_OBSERVER(Observer,
|
||||
observers_,
|
||||
OnCookieChanged(cookie, removed, cause));
|
||||
}
|
||||
|
||||
void AtomCookieDelegate::OnCookieChanged(
|
||||
const net::CanonicalCookie& cookie, bool removed, ChangeCause cause) {
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::UI,
|
||||
FROM_HERE,
|
||||
base::Bind(&AtomCookieDelegate::NotifyObservers,
|
||||
this, cookie, removed, cause));
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
48
atom/browser/net/atom_cookie_delegate.h
Normal file
48
atom/browser/net/atom_cookie_delegate.h
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_NET_ATOM_COOKIE_DELEGATE_H_
|
||||
#define ATOM_BROWSER_NET_ATOM_COOKIE_DELEGATE_H_
|
||||
|
||||
#include "base/observer_list.h"
|
||||
#include "net/cookies/cookie_monster.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomCookieDelegate : public net::CookieMonsterDelegate {
|
||||
public:
|
||||
AtomCookieDelegate();
|
||||
~AtomCookieDelegate() override;
|
||||
|
||||
class Observer {
|
||||
public:
|
||||
virtual void OnCookieChanged(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
ChangeCause cause) {}
|
||||
protected:
|
||||
virtual ~Observer() {}
|
||||
};
|
||||
|
||||
void AddObserver(Observer* observer);
|
||||
void RemoveObserver(Observer* observer);
|
||||
|
||||
// net::CookieMonsterDelegate:
|
||||
void OnCookieChanged(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
ChangeCause cause) override;
|
||||
|
||||
|
||||
private:
|
||||
base::ObserverList<Observer> observers_;
|
||||
|
||||
void NotifyObservers(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
ChangeCause cause);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomCookieDelegate);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_NET_ATOM_COOKIE_DELEGATE_H_
|
||||
34
atom/browser/net/atom_ct_delegate.cc
Normal file
34
atom/browser/net/atom_ct_delegate.cc
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/net/atom_ct_delegate.h"
|
||||
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomCTDelegate::AtomCTDelegate() {}
|
||||
|
||||
AtomCTDelegate::~AtomCTDelegate() {}
|
||||
|
||||
void AtomCTDelegate::AddCTExcludedHost(const std::string& host) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
ct_excluded_hosts_.insert(host);
|
||||
}
|
||||
|
||||
void AtomCTDelegate::ClearCTExcludedHostsList() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
ct_excluded_hosts_.clear();
|
||||
}
|
||||
|
||||
AtomCTDelegate::CTRequirementLevel AtomCTDelegate::IsCTRequiredForHost(
|
||||
const std::string& host) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (!ct_excluded_hosts_.empty() &&
|
||||
(ct_excluded_hosts_.find(host) != ct_excluded_hosts_.end()))
|
||||
return CTRequirementLevel::NOT_REQUIRED;
|
||||
return CTRequirementLevel::DEFAULT;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
33
atom/browser/net/atom_ct_delegate.h
Normal file
33
atom/browser/net/atom_ct_delegate.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_NET_ATOM_CT_DELEGATE_H_
|
||||
#define ATOM_BROWSER_NET_ATOM_CT_DELEGATE_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "net/http/transport_security_state.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomCTDelegate : public net::TransportSecurityState::RequireCTDelegate {
|
||||
public:
|
||||
AtomCTDelegate();
|
||||
~AtomCTDelegate() override;
|
||||
|
||||
void AddCTExcludedHost(const std::string& host);
|
||||
void ClearCTExcludedHostsList();
|
||||
|
||||
// net::TransportSecurityState::RequireCTDelegate:
|
||||
CTRequirementLevel IsCTRequiredForHost(const std::string& host) override;
|
||||
|
||||
private:
|
||||
std::set<std::string> ct_excluded_hosts_;
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomCTDelegate);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_NET_ATOM_CT_DELEGATE_H_
|
||||
@@ -239,7 +239,7 @@ int AtomNetworkDelegate::OnBeforeURLRequest(
|
||||
return HandleResponseEvent(kOnBeforeRequest, request, callback, new_url);
|
||||
}
|
||||
|
||||
int AtomNetworkDelegate::OnBeforeSendHeaders(
|
||||
int AtomNetworkDelegate::OnBeforeStartTransaction(
|
||||
net::URLRequest* request,
|
||||
const net::CompletionCallback& callback,
|
||||
net::HttpRequestHeaders* headers) {
|
||||
@@ -254,18 +254,18 @@ int AtomNetworkDelegate::OnBeforeSendHeaders(
|
||||
DevToolsNetworkTransaction::kDevToolsEmulateNetworkConditionsClientId,
|
||||
client_id);
|
||||
if (!ContainsKey(response_listeners_, kOnBeforeSendHeaders))
|
||||
return brightray::NetworkDelegate::OnBeforeSendHeaders(
|
||||
return brightray::NetworkDelegate::OnBeforeStartTransaction(
|
||||
request, callback, headers);
|
||||
|
||||
return HandleResponseEvent(
|
||||
kOnBeforeSendHeaders, request, callback, headers, *headers);
|
||||
}
|
||||
|
||||
void AtomNetworkDelegate::OnSendHeaders(
|
||||
void AtomNetworkDelegate::OnStartTransaction(
|
||||
net::URLRequest* request,
|
||||
const net::HttpRequestHeaders& headers) {
|
||||
if (!ContainsKey(simple_listeners_, kOnSendHeaders)) {
|
||||
brightray::NetworkDelegate::OnSendHeaders(request, headers);
|
||||
brightray::NetworkDelegate::OnStartTransaction(request, headers);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,11 +77,11 @@ class AtomNetworkDelegate : public brightray::NetworkDelegate {
|
||||
int OnBeforeURLRequest(net::URLRequest* request,
|
||||
const net::CompletionCallback& callback,
|
||||
GURL* new_url) override;
|
||||
int OnBeforeSendHeaders(net::URLRequest* request,
|
||||
const net::CompletionCallback& callback,
|
||||
net::HttpRequestHeaders* headers) override;
|
||||
void OnSendHeaders(net::URLRequest* request,
|
||||
const net::HttpRequestHeaders& headers) override;
|
||||
int OnBeforeStartTransaction(net::URLRequest* request,
|
||||
const net::CompletionCallback& callback,
|
||||
net::HttpRequestHeaders* headers) override;
|
||||
void OnStartTransaction(net::URLRequest* request,
|
||||
const net::HttpRequestHeaders& headers) override;
|
||||
int OnHeadersReceived(
|
||||
net::URLRequest* request,
|
||||
const net::CompletionCallback& callback,
|
||||
|
||||
441
atom/browser/net/atom_url_request.cc
Normal file
441
atom/browser/net/atom_url_request.cc
Normal file
@@ -0,0 +1,441 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/net/atom_url_request.h"
|
||||
#include <string>
|
||||
#include "atom/browser/api/atom_api_url_request.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "base/callback.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "net/base/elements_upload_data_stream.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
#include "net/base/load_flags.h"
|
||||
#include "net/base/upload_bytes_element_reader.h"
|
||||
|
||||
namespace {
|
||||
const int kBufferSize = 4096;
|
||||
} // namespace
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace internal {
|
||||
|
||||
class UploadOwnedIOBufferElementReader : public net::UploadBytesElementReader {
|
||||
public:
|
||||
explicit UploadOwnedIOBufferElementReader(
|
||||
scoped_refptr<const net::IOBufferWithSize> buffer)
|
||||
: net::UploadBytesElementReader(buffer->data(), buffer->size()),
|
||||
buffer_(buffer) {}
|
||||
|
||||
~UploadOwnedIOBufferElementReader() override {}
|
||||
|
||||
static UploadOwnedIOBufferElementReader* CreateWithBuffer(
|
||||
scoped_refptr<const net::IOBufferWithSize> buffer) {
|
||||
return new UploadOwnedIOBufferElementReader(std::move(buffer));
|
||||
}
|
||||
|
||||
private:
|
||||
scoped_refptr<const net::IOBuffer> buffer_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(UploadOwnedIOBufferElementReader);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
AtomURLRequest::AtomURLRequest(api::URLRequest* delegate)
|
||||
: delegate_(delegate),
|
||||
is_chunked_upload_(false),
|
||||
response_read_buffer_(new net::IOBuffer(kBufferSize)) {}
|
||||
|
||||
AtomURLRequest::~AtomURLRequest() {
|
||||
DCHECK(!request_context_getter_);
|
||||
DCHECK(!request_);
|
||||
}
|
||||
|
||||
scoped_refptr<AtomURLRequest> AtomURLRequest::Create(
|
||||
AtomBrowserContext* browser_context,
|
||||
const std::string& method,
|
||||
const std::string& url,
|
||||
api::URLRequest* delegate) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
DCHECK(browser_context);
|
||||
DCHECK(!url.empty());
|
||||
DCHECK(delegate);
|
||||
if (!browser_context || url.empty() || !delegate) {
|
||||
return nullptr;
|
||||
}
|
||||
auto request_context_getter = browser_context->url_request_context_getter();
|
||||
DCHECK(request_context_getter);
|
||||
if (!request_context_getter) {
|
||||
return nullptr;
|
||||
}
|
||||
scoped_refptr<AtomURLRequest> atom_url_request(new AtomURLRequest(delegate));
|
||||
if (content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::DoInitialize, atom_url_request,
|
||||
request_context_getter, method, url))) {
|
||||
return atom_url_request;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AtomURLRequest::Terminate() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
delegate_ = nullptr;
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::DoTerminate, this));
|
||||
}
|
||||
|
||||
void AtomURLRequest::DoInitialize(
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& method,
|
||||
const std::string& url) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
DCHECK(request_context_getter);
|
||||
|
||||
request_context_getter_ = request_context_getter;
|
||||
request_context_getter_->AddObserver(this);
|
||||
auto context = request_context_getter_->GetURLRequestContext();
|
||||
if (!context) {
|
||||
// Called after shutdown.
|
||||
DoCancelWithError("Cannot start a request after shutdown.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(context);
|
||||
request_ = context->CreateRequest(
|
||||
GURL(url), net::RequestPriority::DEFAULT_PRIORITY, this);
|
||||
if (!request_) {
|
||||
DoCancelWithError("Failed to create a net::URLRequest.", true);
|
||||
return;
|
||||
}
|
||||
request_->set_method(method);
|
||||
// Do not send cookies from the cookie store.
|
||||
DoSetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES);
|
||||
}
|
||||
|
||||
void AtomURLRequest::DoTerminate() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
request_.reset();
|
||||
if (request_context_getter_) {
|
||||
request_context_getter_->RemoveObserver(this);
|
||||
request_context_getter_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool AtomURLRequest::Write(scoped_refptr<const net::IOBufferWithSize> buffer,
|
||||
bool is_last) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
return content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::DoWriteBuffer, this, buffer, is_last));
|
||||
}
|
||||
|
||||
void AtomURLRequest::SetChunkedUpload(bool is_chunked_upload) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
// The method can be called only before switching to multi-threaded mode,
|
||||
// i.e. before the first call to write.
|
||||
// So it is safe to change the object in the UI thread.
|
||||
is_chunked_upload_ = is_chunked_upload;
|
||||
}
|
||||
|
||||
void AtomURLRequest::Cancel() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::DoCancel, this));
|
||||
}
|
||||
|
||||
void AtomURLRequest::SetExtraHeader(const std::string& name,
|
||||
const std::string& value) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::DoSetExtraHeader, this, name, value));
|
||||
}
|
||||
|
||||
void AtomURLRequest::RemoveExtraHeader(const std::string& name) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::DoRemoveExtraHeader, this, name));
|
||||
}
|
||||
|
||||
void AtomURLRequest::PassLoginInformation(
|
||||
const base::string16& username,
|
||||
const base::string16& password) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
if (username.empty() || password.empty()) {
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::DoCancelAuth, this));
|
||||
} else {
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::DoSetAuth, this, username, password));
|
||||
}
|
||||
}
|
||||
|
||||
void AtomURLRequest::SetLoadFlags(int flags) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::DoSetLoadFlags, this, flags));
|
||||
}
|
||||
|
||||
void AtomURLRequest::DoWriteBuffer(
|
||||
scoped_refptr<const net::IOBufferWithSize> buffer,
|
||||
bool is_last) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (!request_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_chunked_upload_) {
|
||||
// Chunked encoding case.
|
||||
|
||||
bool first_call = false;
|
||||
if (!chunked_stream_writer_) {
|
||||
std::unique_ptr<net::ChunkedUploadDataStream> chunked_stream(
|
||||
new net::ChunkedUploadDataStream(0));
|
||||
chunked_stream_writer_ = chunked_stream->CreateWriter();
|
||||
request_->set_upload(std::move(chunked_stream));
|
||||
first_call = true;
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
// Non-empty buffer.
|
||||
chunked_stream_writer_->AppendData(buffer->data(), buffer->size(),
|
||||
is_last);
|
||||
else if (is_last)
|
||||
// Empty buffer and last chunk, i.e. request.end().
|
||||
chunked_stream_writer_->AppendData(nullptr, 0, true);
|
||||
|
||||
if (first_call) {
|
||||
request_->Start();
|
||||
}
|
||||
} else {
|
||||
if (buffer) {
|
||||
// Handling potential empty buffers.
|
||||
using internal::UploadOwnedIOBufferElementReader;
|
||||
auto element_reader =
|
||||
UploadOwnedIOBufferElementReader::CreateWithBuffer(std::move(buffer));
|
||||
upload_element_readers_.push_back(
|
||||
std::unique_ptr<net::UploadElementReader>(element_reader));
|
||||
}
|
||||
|
||||
if (is_last) {
|
||||
auto elements_upload_data_stream = new net::ElementsUploadDataStream(
|
||||
std::move(upload_element_readers_), 0);
|
||||
request_->set_upload(
|
||||
std::unique_ptr<net::UploadDataStream>(elements_upload_data_stream));
|
||||
request_->Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AtomURLRequest::DoCancel() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (request_) {
|
||||
request_->Cancel();
|
||||
}
|
||||
DoTerminate();
|
||||
}
|
||||
|
||||
void AtomURLRequest::DoSetExtraHeader(const std::string& name,
|
||||
const std::string& value) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (!request_) {
|
||||
return;
|
||||
}
|
||||
request_->SetExtraRequestHeaderByName(name, value, true);
|
||||
}
|
||||
|
||||
void AtomURLRequest::DoRemoveExtraHeader(const std::string& name) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (!request_) {
|
||||
return;
|
||||
}
|
||||
request_->RemoveRequestHeaderByName(name);
|
||||
}
|
||||
|
||||
void AtomURLRequest::DoSetAuth(const base::string16& username,
|
||||
const base::string16& password) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (!request_) {
|
||||
return;
|
||||
}
|
||||
request_->SetAuth(net::AuthCredentials(username, password));
|
||||
}
|
||||
|
||||
void AtomURLRequest::DoCancelAuth() const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (!request_) {
|
||||
return;
|
||||
}
|
||||
request_->CancelAuth();
|
||||
}
|
||||
|
||||
void AtomURLRequest::DoCancelWithError(const std::string& error,
|
||||
bool isRequestError) {
|
||||
DoCancel();
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::InformDelegateErrorOccured, this, error,
|
||||
isRequestError));
|
||||
}
|
||||
|
||||
void AtomURLRequest::DoSetLoadFlags(int flags) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (!request_) {
|
||||
return;
|
||||
}
|
||||
request_->SetLoadFlags(request_->load_flags() | flags);
|
||||
}
|
||||
|
||||
void AtomURLRequest::OnAuthRequired(net::URLRequest* request,
|
||||
net::AuthChallengeInfo* auth_info) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::InformDelegateAuthenticationRequired, this,
|
||||
scoped_refptr<net::AuthChallengeInfo>(auth_info)));
|
||||
}
|
||||
|
||||
void AtomURLRequest::OnResponseStarted(net::URLRequest* request) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (!request_) {
|
||||
return;
|
||||
}
|
||||
DCHECK_EQ(request, request_.get());
|
||||
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers =
|
||||
request->response_headers();
|
||||
const auto& status = request_->status();
|
||||
if (status.is_success()) {
|
||||
// Success or pending trigger a Read.
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this,
|
||||
response_headers));
|
||||
ReadResponse();
|
||||
} else if (status.status() == net::URLRequestStatus::Status::FAILED) {
|
||||
// Report error on Start.
|
||||
DoCancelWithError(net::ErrorToString(status.ToNetError()), true);
|
||||
}
|
||||
// We don't report an error is the request is canceled.
|
||||
}
|
||||
|
||||
void AtomURLRequest::ReadResponse() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
|
||||
int bytes_read = -1;
|
||||
if (request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)) {
|
||||
OnReadCompleted(request_.get(), bytes_read);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (!request_) {
|
||||
return;
|
||||
}
|
||||
DCHECK_EQ(request, request_.get());
|
||||
|
||||
const auto status = request_->status();
|
||||
|
||||
bool response_error = false;
|
||||
bool data_ended = false;
|
||||
bool data_transfer_error = false;
|
||||
do {
|
||||
if (!status.is_success()) {
|
||||
response_error = true;
|
||||
break;
|
||||
}
|
||||
if (bytes_read == 0) {
|
||||
data_ended = true;
|
||||
break;
|
||||
}
|
||||
if (bytes_read < 0 || !CopyAndPostBuffer(bytes_read)) {
|
||||
data_transfer_error = true;
|
||||
break;
|
||||
}
|
||||
} while (
|
||||
request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read));
|
||||
if (response_error) {
|
||||
DoCancelWithError(net::ErrorToString(status.ToNetError()), false);
|
||||
} else if (data_ended) {
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::InformDelegateResponseCompleted, this));
|
||||
DoTerminate();
|
||||
} else if (data_transfer_error) {
|
||||
// We abort the request on corrupted data transfer.
|
||||
DoCancelWithError("Failed to transfer data from IO to UI thread.", false);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomURLRequest::OnContextShuttingDown() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
DoCancel();
|
||||
}
|
||||
|
||||
bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
|
||||
// data is only a wrapper for the asynchronous response_read_buffer_.
|
||||
// Make a deep copy of payload and transfer ownership to the UI thread.
|
||||
auto buffer_copy = new net::IOBufferWithSize(bytes_read);
|
||||
memcpy(buffer_copy->data(), response_read_buffer_->data(), bytes_read);
|
||||
|
||||
return content::BrowserThread::PostTask(
|
||||
content::BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&AtomURLRequest::InformDelegateResponseData, this,
|
||||
buffer_copy));
|
||||
}
|
||||
|
||||
void AtomURLRequest::InformDelegateAuthenticationRequired(
|
||||
scoped_refptr<net::AuthChallengeInfo> auth_info) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
if (delegate_)
|
||||
delegate_->OnAuthenticationRequired(auth_info);
|
||||
}
|
||||
|
||||
void AtomURLRequest::InformDelegateResponseStarted(
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
if (delegate_)
|
||||
delegate_->OnResponseStarted(response_headers);
|
||||
}
|
||||
|
||||
void AtomURLRequest::InformDelegateResponseData(
|
||||
scoped_refptr<net::IOBufferWithSize> data) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
// Transfer ownership of the data buffer, data will be released
|
||||
// by the delegate's OnResponseData.
|
||||
if (delegate_)
|
||||
delegate_->OnResponseData(data);
|
||||
}
|
||||
|
||||
void AtomURLRequest::InformDelegateResponseCompleted() const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnResponseCompleted();
|
||||
}
|
||||
|
||||
void AtomURLRequest::InformDelegateErrorOccured(const std::string& error,
|
||||
bool isRequestError) const {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnError(error, isRequestError);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
106
atom/browser/net/atom_url_request.h
Normal file
106
atom/browser/net/atom_url_request.h
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_NET_ATOM_URL_REQUEST_H_
|
||||
#define ATOM_BROWSER_NET_ATOM_URL_REQUEST_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "atom/browser/api/atom_api_url_request.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "net/base/auth.h"
|
||||
#include "net/base/chunked_upload_data_stream.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
#include "net/base/upload_element_reader.h"
|
||||
#include "net/http/http_response_headers.h"
|
||||
#include "net/url_request/url_request.h"
|
||||
#include "net/url_request/url_request_context_getter_observer.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomURLRequest : public base::RefCountedThreadSafe<AtomURLRequest>,
|
||||
public net::URLRequest::Delegate,
|
||||
public net::URLRequestContextGetterObserver {
|
||||
public:
|
||||
static scoped_refptr<AtomURLRequest> Create(
|
||||
AtomBrowserContext* browser_context,
|
||||
const std::string& method,
|
||||
const std::string& url,
|
||||
api::URLRequest* delegate);
|
||||
void Terminate();
|
||||
|
||||
bool Write(scoped_refptr<const net::IOBufferWithSize> buffer, bool is_last);
|
||||
void SetChunkedUpload(bool is_chunked_upload);
|
||||
void Cancel();
|
||||
void SetExtraHeader(const std::string& name, const std::string& value) const;
|
||||
void RemoveExtraHeader(const std::string& name) const;
|
||||
void PassLoginInformation(const base::string16& username,
|
||||
const base::string16& password) const;
|
||||
void SetLoadFlags(int flags) const;
|
||||
|
||||
protected:
|
||||
// Overrides of net::URLRequest::Delegate
|
||||
void OnAuthRequired(net::URLRequest* request,
|
||||
net::AuthChallengeInfo* auth_info) override;
|
||||
void OnResponseStarted(net::URLRequest* request) override;
|
||||
void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
|
||||
|
||||
// Overrides of net::URLRequestContextGetterObserver
|
||||
void OnContextShuttingDown() override;
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<AtomURLRequest>;
|
||||
|
||||
explicit AtomURLRequest(api::URLRequest* delegate);
|
||||
~AtomURLRequest() override;
|
||||
|
||||
void DoInitialize(scoped_refptr<net::URLRequestContextGetter>,
|
||||
const std::string& method,
|
||||
const std::string& url);
|
||||
void DoTerminate();
|
||||
void DoWriteBuffer(scoped_refptr<const net::IOBufferWithSize> buffer,
|
||||
bool is_last);
|
||||
void DoCancel();
|
||||
void DoSetExtraHeader(const std::string& name,
|
||||
const std::string& value) const;
|
||||
void DoRemoveExtraHeader(const std::string& name) const;
|
||||
void DoSetAuth(const base::string16& username,
|
||||
const base::string16& password) const;
|
||||
void DoCancelAuth() const;
|
||||
void DoCancelWithError(const std::string& error, bool isRequestError);
|
||||
void DoSetLoadFlags(int flags) const;
|
||||
|
||||
void ReadResponse();
|
||||
bool CopyAndPostBuffer(int bytes_read);
|
||||
|
||||
void InformDelegateAuthenticationRequired(
|
||||
scoped_refptr<net::AuthChallengeInfo> auth_info) const;
|
||||
void InformDelegateResponseStarted(
|
||||
scoped_refptr<net::HttpResponseHeaders>) const;
|
||||
void InformDelegateResponseData(
|
||||
scoped_refptr<net::IOBufferWithSize> data) const;
|
||||
void InformDelegateResponseCompleted() const;
|
||||
void InformDelegateErrorOccured(const std::string& error,
|
||||
bool isRequestError) const;
|
||||
|
||||
api::URLRequest* delegate_;
|
||||
std::unique_ptr<net::URLRequest> request_;
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
|
||||
|
||||
bool is_chunked_upload_;
|
||||
std::unique_ptr<net::ChunkedUploadDataStream> chunked_stream_;
|
||||
std::unique_ptr<net::ChunkedUploadDataStream::Writer> chunked_stream_writer_;
|
||||
std::vector<std::unique_ptr<net::UploadElementReader>>
|
||||
upload_element_readers_;
|
||||
scoped_refptr<net::IOBuffer> response_read_buffer_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomURLRequest);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_NET_ATOM_URL_REQUEST_H_
|
||||
37
atom/browser/net/url_request_about_job.cc
Normal file
37
atom/browser/net/url_request_about_job.cc
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/net/url_request_about_job.h"
|
||||
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
URLRequestAboutJob::URLRequestAboutJob(net::URLRequest* request,
|
||||
net::NetworkDelegate* network_delegate)
|
||||
: net::URLRequestJob(request, network_delegate), weak_ptr_factory_(this) {}
|
||||
|
||||
void URLRequestAboutJob::Start() {
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, base::Bind(&URLRequestAboutJob::StartAsync,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
void URLRequestAboutJob::Kill() {
|
||||
weak_ptr_factory_.InvalidateWeakPtrs();
|
||||
URLRequestJob::Kill();
|
||||
}
|
||||
|
||||
bool URLRequestAboutJob::GetMimeType(std::string* mime_type) const {
|
||||
*mime_type = "text/html";
|
||||
return true;
|
||||
}
|
||||
|
||||
URLRequestAboutJob::~URLRequestAboutJob() {}
|
||||
|
||||
void URLRequestAboutJob::StartAsync() {
|
||||
NotifyHeadersComplete();
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
35
atom/browser/net/url_request_about_job.h
Normal file
35
atom/browser/net/url_request_about_job.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_NET_URL_REQUEST_ABOUT_JOB_H_
|
||||
#define ATOM_BROWSER_NET_URL_REQUEST_ABOUT_JOB_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "net/url_request/url_request_job.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class URLRequestAboutJob : public net::URLRequestJob {
|
||||
public:
|
||||
URLRequestAboutJob(net::URLRequest*, net::NetworkDelegate*);
|
||||
|
||||
// URLRequestJob:
|
||||
void Start() override;
|
||||
void Kill() override;
|
||||
bool GetMimeType(std::string* mime_type) const override;
|
||||
|
||||
private:
|
||||
~URLRequestAboutJob() override;
|
||||
void StartAsync();
|
||||
|
||||
base::WeakPtrFactory<URLRequestAboutJob> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(URLRequestAboutJob);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_NET_URL_REQUEST_ABOUT_JOB_H_
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_session.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
@@ -89,15 +91,23 @@ void URLRequestFetchJob::BeforeStartInUI(
|
||||
return;
|
||||
|
||||
// When |session| is set to |null| we use a new request context for fetch job.
|
||||
// TODO(zcbenz): Handle the case when it is not null.
|
||||
v8::Local<v8::Value> session;
|
||||
if (options.Get("session", &session) && session->IsNull()) {
|
||||
// We have to create the URLRequestContextGetter on UI thread.
|
||||
url_request_context_getter_ = new brightray::URLRequestContextGetter(
|
||||
this, nullptr, nullptr, base::FilePath(), true,
|
||||
BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO),
|
||||
BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE),
|
||||
nullptr, content::URLRequestInterceptorScopedVector());
|
||||
v8::Local<v8::Value> val;
|
||||
if (options.Get("session", &val)) {
|
||||
if (val->IsNull()) {
|
||||
// We have to create the URLRequestContextGetter on UI thread.
|
||||
url_request_context_getter_ = new brightray::URLRequestContextGetter(
|
||||
this, nullptr, nullptr, base::FilePath(), true,
|
||||
BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO),
|
||||
BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE),
|
||||
nullptr, content::URLRequestInterceptorScopedVector());
|
||||
} else {
|
||||
mate::Handle<api::Session> session;
|
||||
if (mate::ConvertFromV8(isolate, val, &session) && !session.IsEmpty()) {
|
||||
AtomBrowserContext* browser_context = session->browser_context();
|
||||
url_request_context_getter_ =
|
||||
browser_context->url_request_context_getter();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,21 +247,21 @@ int URLRequestFetchJob::GetResponseCode() const {
|
||||
}
|
||||
|
||||
void URLRequestFetchJob::OnURLFetchComplete(const net::URLFetcher* source) {
|
||||
if (!response_info_) {
|
||||
// Since we notify header completion only after first write there will be
|
||||
// no response object constructed for http respones with no content 204.
|
||||
// We notify header completion here.
|
||||
HeadersCompleted();
|
||||
return;
|
||||
}
|
||||
|
||||
ClearPendingBuffer();
|
||||
ClearWriteBuffer();
|
||||
|
||||
if (fetcher_->GetStatus().is_success())
|
||||
if (fetcher_->GetStatus().is_success()) {
|
||||
if (!response_info_) {
|
||||
// Since we notify header completion only after first write there will be
|
||||
// no response object constructed for http respones with no content 204.
|
||||
// We notify header completion here.
|
||||
HeadersCompleted();
|
||||
return;
|
||||
}
|
||||
ReadRawDataComplete(0);
|
||||
else
|
||||
} else {
|
||||
NotifyStartError(fetcher_->GetStatus());
|
||||
}
|
||||
}
|
||||
|
||||
int URLRequestFetchJob::BufferCopy(net::IOBuffer* source, int num_bytes,
|
||||
|
||||
@@ -71,8 +71,9 @@ class AtomCopyFrameGenerator {
|
||||
content::BrowserThread::PostDelayedTask(content::BrowserThread::UI,
|
||||
FROM_HERE,
|
||||
base::Bind(&AtomCopyFrameGenerator::InternalGenerateCopyFrame,
|
||||
weak_ptr_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(
|
||||
frame_rate_threshold_ms_ - frame_rate_delta));
|
||||
weak_ptr_factory_.GetWeakPtr()),
|
||||
base::TimeDelta::FromMilliseconds(
|
||||
frame_rate_threshold_ms_ - frame_rate_delta));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -103,9 +104,7 @@ class AtomCopyFrameGenerator {
|
||||
damage_rect));
|
||||
|
||||
request->set_area(gfx::Rect(view_->GetPhysicalBackingSize()));
|
||||
|
||||
view_->DelegatedFrameHostGetLayer()->RequestCopyOfOutput(
|
||||
std::move(request));
|
||||
view_->GetRootLayer()->RequestCopyOfOutput(std::move(request));
|
||||
}
|
||||
|
||||
void CopyFromCompositingSurfaceHasResult(
|
||||
@@ -302,10 +301,9 @@ class AtomBeginFrameTimer : public cc::DelayBasedTimeSourceClient {
|
||||
AtomBeginFrameTimer(int frame_rate_threshold_ms,
|
||||
const base::Closure& callback)
|
||||
: callback_(callback) {
|
||||
time_source_ = cc::DelayBasedTimeSource::Create(
|
||||
base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms),
|
||||
time_source_.reset(new cc::DelayBasedTimeSource(
|
||||
content::BrowserThread::GetMessageLoopProxyForThread(
|
||||
content::BrowserThread::UI).get());
|
||||
content::BrowserThread::UI).get()));
|
||||
time_source_->SetClient(this);
|
||||
}
|
||||
|
||||
@@ -351,12 +349,17 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
is_showing_(!render_widget_host_->is_hidden()),
|
||||
size_(native_window->GetSize()),
|
||||
painting_(true),
|
||||
root_layer_(new ui::Layer(ui::LAYER_SOLID_COLOR)),
|
||||
#if !defined(OS_MACOSX)
|
||||
delegated_frame_host_(new content::DelegatedFrameHost(this)),
|
||||
#endif
|
||||
weak_ptr_factory_(this) {
|
||||
DCHECK(render_widget_host_);
|
||||
render_widget_host_->SetView(this);
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
CreatePlatformWidget();
|
||||
#else
|
||||
@@ -364,17 +367,29 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
new ui::Compositor(content::GetContextFactory(),
|
||||
base::ThreadTaskRunnerHandle::Get()));
|
||||
compositor_->SetAcceleratedWidget(native_window_->GetAcceleratedWidget());
|
||||
#endif
|
||||
compositor_->SetDelegate(this);
|
||||
compositor_->SetRootLayer(root_layer_.get());
|
||||
#endif
|
||||
GetCompositor()->SetDelegate(this);
|
||||
|
||||
native_window_->AddObserver(this);
|
||||
|
||||
ResizeRootLayer();
|
||||
}
|
||||
|
||||
OffScreenRenderWidgetHostView::~OffScreenRenderWidgetHostView() {
|
||||
if (native_window_)
|
||||
native_window_->RemoveObserver(this);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
if (is_showing_)
|
||||
browser_compositor_->SetRenderWidgetHostIsHidden(true);
|
||||
#else
|
||||
// Marking the DelegatedFrameHost as removed from the window hierarchy is
|
||||
// necessary to remove all connections to its old ui::Compositor.
|
||||
if (is_showing_)
|
||||
delegated_frame_host_->WasHidden();
|
||||
delegated_frame_host_->ResetCompositor();
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
DestroyPlatformWidget();
|
||||
@@ -429,11 +444,10 @@ content::RenderWidgetHost* OffScreenRenderWidgetHostView::GetRenderWidgetHost()
|
||||
void OffScreenRenderWidgetHostView::SetSize(const gfx::Size& size) {
|
||||
size_ = size;
|
||||
|
||||
const gfx::Size& size_in_pixels =
|
||||
gfx::ConvertSizeToPixel(scale_factor_, size);
|
||||
|
||||
root_layer_->SetBounds(gfx::Rect(size));
|
||||
compositor_->SetScaleAndSize(scale_factor_, size_in_pixels);
|
||||
ResizeRootLayer();
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->WasResized();
|
||||
GetDelegatedFrameHost()->WasResized();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetBounds(const gfx::Rect& new_bounds) {
|
||||
@@ -464,7 +478,7 @@ bool OffScreenRenderWidgetHostView::HasFocus() const {
|
||||
}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::IsSurfaceAvailableForCopy() const {
|
||||
return delegated_frame_host_->CanCopyToBitmap();
|
||||
return GetDelegatedFrameHost()->CanCopyToBitmap();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::Show() {
|
||||
@@ -472,10 +486,16 @@ void OffScreenRenderWidgetHostView::Show() {
|
||||
return;
|
||||
|
||||
is_showing_ = true;
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->WasShown(ui::LatencyInfo());
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->SetRenderWidgetHostIsHidden(false);
|
||||
#else
|
||||
delegated_frame_host_->SetCompositor(compositor_.get());
|
||||
delegated_frame_host_->WasShown(ui::LatencyInfo());
|
||||
#endif
|
||||
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->WasShown(ui::LatencyInfo());
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::Hide() {
|
||||
@@ -484,8 +504,14 @@ void OffScreenRenderWidgetHostView::Hide() {
|
||||
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->WasHidden();
|
||||
delegated_frame_host_->WasHidden();
|
||||
delegated_frame_host_->ResetCompositor();
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->SetRenderWidgetHostIsHidden(true);
|
||||
#else
|
||||
GetDelegatedFrameHost()->WasHidden();
|
||||
GetDelegatedFrameHost()->ResetCompositor();
|
||||
#endif
|
||||
|
||||
is_showing_ = false;
|
||||
}
|
||||
|
||||
@@ -522,52 +548,63 @@ bool OffScreenRenderWidgetHostView::LockMouse() {
|
||||
void OffScreenRenderWidgetHostView::UnlockMouse() {
|
||||
}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::GetScreenColorProfile(std::vector<char>*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnSwapCompositorFrame(
|
||||
uint32_t output_surface_id,
|
||||
std::unique_ptr<cc::CompositorFrame> frame) {
|
||||
cc::CompositorFrame frame) {
|
||||
TRACE_EVENT0("electron",
|
||||
"OffScreenRenderWidgetHostView::OnSwapCompositorFrame");
|
||||
|
||||
if (frame->metadata.root_scroll_offset != last_scroll_offset_) {
|
||||
last_scroll_offset_ = frame->metadata.root_scroll_offset;
|
||||
if (frame.metadata.root_scroll_offset != last_scroll_offset_) {
|
||||
last_scroll_offset_ = frame.metadata.root_scroll_offset;
|
||||
}
|
||||
|
||||
if (frame->delegated_frame_data) {
|
||||
if (frame.delegated_frame_data) {
|
||||
if (software_output_device_) {
|
||||
if (!begin_frame_timer_.get()) {
|
||||
software_output_device_->SetActive(painting_);
|
||||
}
|
||||
|
||||
// The compositor will draw directly to the SoftwareOutputDevice which
|
||||
// then calls OnPaint.
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->SwapCompositorFrame(output_surface_id,
|
||||
std::move(frame));
|
||||
#else
|
||||
delegated_frame_host_->SwapDelegatedFrame(output_surface_id,
|
||||
std::move(frame));
|
||||
#endif
|
||||
} else {
|
||||
if (!copy_frame_generator_.get()) {
|
||||
copy_frame_generator_.reset(
|
||||
new AtomCopyFrameGenerator(frame_rate_threshold_ms_, this));
|
||||
}
|
||||
|
||||
// Determine the damage rectangle for the current frame. This is the same
|
||||
// calculation that SwapDelegatedFrame uses.
|
||||
cc::RenderPass* root_pass =
|
||||
frame->delegated_frame_data->render_pass_list.back().get();
|
||||
frame.delegated_frame_data->render_pass_list.back().get();
|
||||
gfx::Size frame_size = root_pass->output_rect.size();
|
||||
gfx::Rect damage_rect =
|
||||
gfx::ToEnclosingRect(gfx::RectF(root_pass->damage_rect));
|
||||
damage_rect.Intersect(gfx::Rect(frame_size));
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->SwapCompositorFrame(output_surface_id,
|
||||
std::move(frame));
|
||||
#else
|
||||
delegated_frame_host_->SwapDelegatedFrame(output_surface_id,
|
||||
std::move(frame));
|
||||
#endif
|
||||
|
||||
if (painting_)
|
||||
copy_frame_generator_->GenerateCopyFrame(true, damage_rect);
|
||||
// Request a copy of the last compositor frame which will eventually call
|
||||
// OnPaint asynchronously.
|
||||
copy_frame_generator_->GenerateCopyFrame(true, damage_rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ClearCompositorFrame() {
|
||||
delegated_frame_host_->ClearDelegatedFrame();
|
||||
GetDelegatedFrameHost()->ClearDelegatedFrame();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::InitAsPopup(
|
||||
@@ -612,7 +649,7 @@ void OffScreenRenderWidgetHostView::CopyFromCompositingSurface(
|
||||
const gfx::Size& dst_size,
|
||||
const content::ReadbackRequestCallback& callback,
|
||||
const SkColorType preferred_color_type) {
|
||||
delegated_frame_host_->CopyFromCompositingSurface(
|
||||
GetDelegatedFrameHost()->CopyFromCompositingSurface(
|
||||
src_subrect, dst_size, callback, preferred_color_type);
|
||||
}
|
||||
|
||||
@@ -620,21 +657,21 @@ void OffScreenRenderWidgetHostView::CopyFromCompositingSurfaceToVideoFrame(
|
||||
const gfx::Rect& src_subrect,
|
||||
const scoped_refptr<media::VideoFrame>& target,
|
||||
const base::Callback<void(const gfx::Rect&, bool)>& callback) {
|
||||
delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
|
||||
GetDelegatedFrameHost()->CopyFromCompositingSurfaceToVideoFrame(
|
||||
src_subrect, target, callback);
|
||||
}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::CanCopyToVideoFrame() const {
|
||||
return delegated_frame_host_->CanCopyToVideoFrame();
|
||||
return GetDelegatedFrameHost()->CanCopyToVideoFrame();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::BeginFrameSubscription(
|
||||
std::unique_ptr<content::RenderWidgetHostViewFrameSubscriber> subscriber) {
|
||||
delegated_frame_host_->BeginFrameSubscription(std::move(subscriber));
|
||||
GetDelegatedFrameHost()->BeginFrameSubscription(std::move(subscriber));
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::EndFrameSubscription() {
|
||||
delegated_frame_host_->EndFrameSubscription();
|
||||
GetDelegatedFrameHost()->EndFrameSubscription();
|
||||
}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::HasAcceleratedSurface(const gfx::Size &) {
|
||||
@@ -749,7 +786,7 @@ void OffScreenRenderWidgetHostView::SetBeginFrameSource(
|
||||
std::unique_ptr<cc::SoftwareOutputDevice>
|
||||
OffScreenRenderWidgetHostView::CreateSoftwareOutputDevice(
|
||||
ui::Compositor* compositor) {
|
||||
DCHECK_EQ(compositor_.get(), compositor);
|
||||
DCHECK_EQ(GetCompositor(), compositor);
|
||||
DCHECK(!copy_frame_generator_);
|
||||
DCHECK(!software_output_device_);
|
||||
|
||||
@@ -763,7 +800,11 @@ std::unique_ptr<cc::SoftwareOutputDevice>
|
||||
bool OffScreenRenderWidgetHostView::InstallTransparency() {
|
||||
if (transparent_) {
|
||||
SetBackgroundColor(SkColor());
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->SetHasTransparentBackground(true);
|
||||
#else
|
||||
compositor_->SetHostHasTransparentBackground(true);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -816,13 +857,28 @@ int OffScreenRenderWidgetHostView::GetFrameRate() const {
|
||||
return frame_rate_;
|
||||
}
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
ui::Compositor* OffScreenRenderWidgetHostView::GetCompositor() const {
|
||||
return compositor_.get();
|
||||
}
|
||||
|
||||
ui::Layer* OffScreenRenderWidgetHostView::GetRootLayer() const {
|
||||
return root_layer_.get();
|
||||
}
|
||||
|
||||
content::DelegatedFrameHost*
|
||||
OffScreenRenderWidgetHostView::GetDelegatedFrameHost() const {
|
||||
return delegated_frame_host_.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetupFrameRate(bool force) {
|
||||
if (!force && frame_rate_threshold_ms_ != 0)
|
||||
return;
|
||||
|
||||
frame_rate_threshold_ms_ = 1000 / frame_rate_;
|
||||
|
||||
compositor_->vsync_manager()->SetAuthoritativeVSyncInterval(
|
||||
GetCompositor()->vsync_manager()->SetAuthoritativeVSyncInterval(
|
||||
base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms_));
|
||||
|
||||
if (copy_frame_generator_.get()) {
|
||||
@@ -840,6 +896,16 @@ void OffScreenRenderWidgetHostView::SetupFrameRate(bool force) {
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::Invalidate() {
|
||||
const gfx::Rect& bounds_in_pixels = GetViewBounds();
|
||||
|
||||
if (software_output_device_) {
|
||||
software_output_device_->OnPaint(bounds_in_pixels);
|
||||
} else if (copy_frame_generator_.get()) {
|
||||
copy_frame_generator_->GenerateCopyFrame(true, bounds_in_pixels);
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ResizeRootLayer() {
|
||||
SetupFrameRate(false);
|
||||
|
||||
@@ -848,14 +914,25 @@ void OffScreenRenderWidgetHostView::ResizeRootLayer() {
|
||||
|
||||
gfx::Size size = GetViewBounds().size();
|
||||
|
||||
if (!scaleFactorDidChange && size == root_layer_->bounds().size())
|
||||
if (!scaleFactorDidChange && size == GetRootLayer()->bounds().size())
|
||||
return;
|
||||
|
||||
const gfx::Size& size_in_pixels =
|
||||
gfx::ConvertSizeToPixel(scale_factor_, size);
|
||||
|
||||
root_layer_->SetBounds(gfx::Rect(size));
|
||||
compositor_->SetScaleAndSize(scale_factor_, size_in_pixels);
|
||||
GetRootLayer()->SetBounds(gfx::Rect(size));
|
||||
GetCompositor()->SetScaleAndSize(scale_factor_, size_in_pixels);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnWindowResize() {
|
||||
// In offscreen mode call RenderWidgetHostView's SetSize explicitly
|
||||
auto size = native_window_->GetSize();
|
||||
SetSize(size);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnWindowClosed() {
|
||||
native_window_->RemoveObserver(this);
|
||||
native_window_ = nullptr;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#endif
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/native_window_observer.h"
|
||||
#include "atom/browser/osr/osr_output_device.h"
|
||||
#include "base/process/kill.h"
|
||||
#include "base/threading/thread.h"
|
||||
@@ -36,7 +37,6 @@
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "content/browser/renderer_host/browser_compositor_view_mac.h"
|
||||
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
@@ -54,13 +54,15 @@ namespace atom {
|
||||
class AtomCopyFrameGenerator;
|
||||
class AtomBeginFrameTimer;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
class MacHelper;
|
||||
#endif
|
||||
|
||||
class OffScreenRenderWidgetHostView
|
||||
: public content::RenderWidgetHostViewBase,
|
||||
#if defined(OS_MACOSX)
|
||||
public ui::AcceleratedWidgetMacNSView,
|
||||
#endif
|
||||
public ui::CompositorDelegate,
|
||||
public content::DelegatedFrameHostClient {
|
||||
public content::DelegatedFrameHostClient,
|
||||
public NativeWindowObserver {
|
||||
public:
|
||||
OffScreenRenderWidgetHostView(bool transparent,
|
||||
const OnPaintCallback& callback,
|
||||
@@ -90,7 +92,6 @@ class OffScreenRenderWidgetHostView
|
||||
void SetBackgroundColor(SkColor color) override;
|
||||
bool LockMouse(void) override;
|
||||
void UnlockMouse(void) override;
|
||||
bool GetScreenColorProfile(std::vector<char>*) override;
|
||||
#if defined(OS_MACOSX)
|
||||
ui::AcceleratedWidgetMac* GetAcceleratedWidgetMac() const override;
|
||||
void SetActive(bool active) override;
|
||||
@@ -102,7 +103,7 @@ class OffScreenRenderWidgetHostView
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
// content::RenderWidgetHostViewBase:
|
||||
void OnSwapCompositorFrame(uint32_t, std::unique_ptr<cc::CompositorFrame>)
|
||||
void OnSwapCompositorFrame(uint32_t, cc::CompositorFrame)
|
||||
override;
|
||||
void ClearCompositorFrame(void) override;
|
||||
void InitAsPopup(content::RenderWidgetHostView *rwhv, const gfx::Rect& rect)
|
||||
@@ -173,13 +174,9 @@ class OffScreenRenderWidgetHostView
|
||||
bool IsAutoResizeEnabled() const;
|
||||
void OnSetNeedsBeginFrames(bool enabled);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// ui::AcceleratedWidgetMacNSView:
|
||||
NSView* AcceleratedWidgetGetNSView() const override;
|
||||
void AcceleratedWidgetGetVSyncParameters(
|
||||
base::TimeTicks* timebase, base::TimeDelta* interval) const override;
|
||||
void AcceleratedWidgetSwapCompleted() override;
|
||||
#endif // defined(OS_MACOSX)
|
||||
// NativeWindowObserver:
|
||||
void OnWindowResize() override;
|
||||
void OnWindowClosed() override;
|
||||
|
||||
void OnBeginFrameTimerTick();
|
||||
void SendBeginFrame(base::TimeTicks frame_time,
|
||||
@@ -198,9 +195,15 @@ class OffScreenRenderWidgetHostView
|
||||
void SetFrameRate(int frame_rate);
|
||||
int GetFrameRate() const;
|
||||
|
||||
ui::Compositor* compositor() const { return compositor_.get(); }
|
||||
ui::Compositor* GetCompositor() const;
|
||||
ui::Layer* GetRootLayer() const;
|
||||
content::DelegatedFrameHost* GetDelegatedFrameHost() const;
|
||||
|
||||
void Invalidate();
|
||||
|
||||
content::RenderWidgetHostImpl* render_widget_host() const
|
||||
{ return render_widget_host_; }
|
||||
NativeWindow* window() const { return native_window_; }
|
||||
|
||||
private:
|
||||
void SetupFrameRate(bool force);
|
||||
@@ -233,10 +236,13 @@ class OffScreenRenderWidgetHostView
|
||||
std::unique_ptr<AtomBeginFrameTimer> begin_frame_timer_;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
NSWindow* window_;
|
||||
CALayer* background_layer_;
|
||||
std::unique_ptr<content::BrowserCompositorMac> browser_compositor_;
|
||||
|
||||
// Can not be managed by smart pointer because its header can not be included
|
||||
// in the file that has the destructor.
|
||||
MacHelper* mac_helper_;
|
||||
|
||||
// Selected text on the renderer.
|
||||
std::string selected_text_;
|
||||
#endif
|
||||
|
||||
@@ -7,48 +7,115 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/common/view_messages.h"
|
||||
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class MacHelper :
|
||||
public content::BrowserCompositorMacClient,
|
||||
public ui::AcceleratedWidgetMacNSView {
|
||||
public:
|
||||
explicit MacHelper(OffScreenRenderWidgetHostView* view) : view_(view) {}
|
||||
virtual ~MacHelper() {}
|
||||
|
||||
// content::BrowserCompositorMacClient:
|
||||
NSView* BrowserCompositorMacGetNSView() const override {
|
||||
// Intentionally return nil so that
|
||||
// BrowserCompositorMac::DelegatedFrameHostDesiredSizeInDIP uses the layer
|
||||
// size instead of the NSView size.
|
||||
return nil;
|
||||
}
|
||||
|
||||
SkColor BrowserCompositorMacGetGutterColor(SkColor color) const override {
|
||||
// When making an element on the page fullscreen the element's background
|
||||
// may not match the page's, so use black as the gutter color to avoid
|
||||
// flashes of brighter colors during the transition.
|
||||
if (view_->render_widget_host()->delegate() &&
|
||||
view_->render_widget_host()->delegate()->IsFullscreenForCurrentTab()) {
|
||||
return SK_ColorBLACK;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
void BrowserCompositorMacSendCompositorSwapAck(
|
||||
int output_surface_id,
|
||||
const cc::CompositorFrameAck& ack) override {
|
||||
view_->render_widget_host()->Send(new ViewMsg_SwapCompositorFrameAck(
|
||||
view_->render_widget_host()->GetRoutingID(), output_surface_id, ack));
|
||||
}
|
||||
|
||||
void BrowserCompositorMacSendReclaimCompositorResources(
|
||||
int output_surface_id,
|
||||
const cc::CompositorFrameAck& ack) override {
|
||||
view_->render_widget_host()->Send(new ViewMsg_ReclaimCompositorResources(
|
||||
view_->render_widget_host()->GetRoutingID(), output_surface_id, ack));
|
||||
}
|
||||
|
||||
void BrowserCompositorMacOnLostCompositorResources() override {
|
||||
view_->render_widget_host()->ScheduleComposite();
|
||||
}
|
||||
|
||||
void BrowserCompositorMacUpdateVSyncParameters(
|
||||
const base::TimeTicks& timebase,
|
||||
const base::TimeDelta& interval) override {
|
||||
view_->render_widget_host()->UpdateVSyncParameters(timebase, interval);
|
||||
}
|
||||
|
||||
void BrowserCompositorMacSendBeginFrame(
|
||||
const cc::BeginFrameArgs& args) override {
|
||||
view_->render_widget_host()->Send(
|
||||
new ViewMsg_BeginFrame(view_->render_widget_host()->GetRoutingID(),
|
||||
args));
|
||||
}
|
||||
// ui::AcceleratedWidgetMacNSView:
|
||||
NSView* AcceleratedWidgetGetNSView() const override {
|
||||
return [view_->window()->GetNativeWindow() contentView];
|
||||
}
|
||||
|
||||
void AcceleratedWidgetGetVSyncParameters(
|
||||
base::TimeTicks* timebase, base::TimeDelta* interval) const override {
|
||||
*timebase = base::TimeTicks();
|
||||
*interval = base::TimeDelta();
|
||||
}
|
||||
|
||||
void AcceleratedWidgetSwapCompleted() override {
|
||||
}
|
||||
|
||||
private:
|
||||
OffScreenRenderWidgetHostView* view_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MacHelper);
|
||||
};
|
||||
|
||||
ui::AcceleratedWidgetMac*
|
||||
atom::OffScreenRenderWidgetHostView::GetAcceleratedWidgetMac() const {
|
||||
OffScreenRenderWidgetHostView::GetAcceleratedWidgetMac() const {
|
||||
if (browser_compositor_)
|
||||
return browser_compositor_->accelerated_widget_mac();
|
||||
return browser_compositor_->GetAcceleratedWidgetMac();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NSView* atom::OffScreenRenderWidgetHostView::AcceleratedWidgetGetNSView() const {
|
||||
return [native_window_->GetNativeWindow() contentView];
|
||||
void OffScreenRenderWidgetHostView::SetActive(bool active) {
|
||||
}
|
||||
|
||||
void atom::OffScreenRenderWidgetHostView::AcceleratedWidgetGetVSyncParameters(
|
||||
base::TimeTicks* timebase, base::TimeDelta* interval) const {
|
||||
*timebase = base::TimeTicks();
|
||||
*interval = base::TimeDelta();
|
||||
void OffScreenRenderWidgetHostView::ShowDefinitionForSelection() {
|
||||
}
|
||||
|
||||
void atom::OffScreenRenderWidgetHostView::AcceleratedWidgetSwapCompleted() {
|
||||
}
|
||||
|
||||
void atom::OffScreenRenderWidgetHostView::SetActive(bool active) {
|
||||
}
|
||||
|
||||
void atom::OffScreenRenderWidgetHostView::ShowDefinitionForSelection() {
|
||||
}
|
||||
|
||||
bool atom::OffScreenRenderWidgetHostView::SupportsSpeech() const {
|
||||
bool OffScreenRenderWidgetHostView::SupportsSpeech() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void atom::OffScreenRenderWidgetHostView::SpeakSelection() {
|
||||
void OffScreenRenderWidgetHostView::SpeakSelection() {
|
||||
}
|
||||
|
||||
bool atom::OffScreenRenderWidgetHostView::IsSpeaking() const {
|
||||
bool OffScreenRenderWidgetHostView::IsSpeaking() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void atom::OffScreenRenderWidgetHostView::StopSpeaking() {
|
||||
void OffScreenRenderWidgetHostView::StopSpeaking() {
|
||||
}
|
||||
|
||||
void atom::OffScreenRenderWidgetHostView::SelectionChanged(
|
||||
void OffScreenRenderWidgetHostView::SelectionChanged(
|
||||
const base::string16& text,
|
||||
size_t offset,
|
||||
const gfx::Range& range) {
|
||||
@@ -69,24 +136,28 @@ void atom::OffScreenRenderWidgetHostView::SelectionChanged(
|
||||
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
|
||||
}
|
||||
|
||||
void atom::OffScreenRenderWidgetHostView::CreatePlatformWidget() {
|
||||
browser_compositor_ = content::BrowserCompositorMac::Create();
|
||||
|
||||
compositor_.reset(browser_compositor_->compositor());
|
||||
compositor_->SetRootLayer(root_layer_.get());
|
||||
browser_compositor_->accelerated_widget_mac()->SetNSView(this);
|
||||
browser_compositor_->compositor()->SetVisible(true);
|
||||
|
||||
compositor_->SetLocksWillTimeOut(true);
|
||||
browser_compositor_->Unsuspend();
|
||||
void OffScreenRenderWidgetHostView::CreatePlatformWidget() {
|
||||
mac_helper_ = new MacHelper(this);
|
||||
browser_compositor_.reset(new content::BrowserCompositorMac(
|
||||
mac_helper_, mac_helper_, render_widget_host_->is_hidden(), true));
|
||||
}
|
||||
|
||||
void atom::OffScreenRenderWidgetHostView::DestroyPlatformWidget() {
|
||||
ui::Compositor* compositor = compositor_.release();
|
||||
ALLOW_UNUSED_LOCAL(compositor);
|
||||
|
||||
browser_compositor_->accelerated_widget_mac()->ResetNSView();
|
||||
browser_compositor_->compositor()->SetVisible(false);
|
||||
browser_compositor_->compositor()->SetScaleAndSize(1.0, gfx::Size(0, 0));
|
||||
browser_compositor_->compositor()->SetRootLayer(NULL);
|
||||
void OffScreenRenderWidgetHostView::DestroyPlatformWidget() {
|
||||
browser_compositor_.reset();
|
||||
delete mac_helper_;
|
||||
}
|
||||
|
||||
ui::Compositor* OffScreenRenderWidgetHostView::GetCompositor() const {
|
||||
return browser_compositor_->GetCompositor();
|
||||
}
|
||||
|
||||
ui::Layer* OffScreenRenderWidgetHostView::GetRootLayer() const {
|
||||
return browser_compositor_->GetRootLayer();
|
||||
}
|
||||
|
||||
content::DelegatedFrameHost*
|
||||
OffScreenRenderWidgetHostView::GetDelegatedFrameHost() const {
|
||||
return browser_compositor_->GetDelegatedFrameHost();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "atom/browser/osr/osr_web_contents_view.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface OffScreenView : NSView
|
||||
@end
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>electron.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.3.15</string>
|
||||
<string>1.4.15</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.3.15</string>
|
||||
<string>1.4.15</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@@ -56,8 +56,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,3,15,0
|
||||
PRODUCTVERSION 1,3,15,0
|
||||
FILEVERSION 1,4,15,0
|
||||
PRODUCTVERSION 1,4,15,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -74,12 +74,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "1.3.15"
|
||||
VALUE "FileVersion", "1.4.15"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "1.3.15"
|
||||
VALUE "ProductVersion", "1.4.15"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -90,11 +90,12 @@ bool TriggerAcceleratorTableCommand(AcceleratorTable* table,
|
||||
const ui::Accelerator& accelerator) {
|
||||
if (ContainsKey(*table, accelerator)) {
|
||||
const accelerator_util::MenuItem& item = (*table)[accelerator];
|
||||
item.model->ActivatedAt(item.position);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
if (item.model->IsEnabledAt(item.position)) {
|
||||
item.model->ActivatedAt(item.position);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace accelerator_util
|
||||
|
||||
@@ -37,8 +37,8 @@ typedef base::Callback<void(int code)> MessageBoxCallback;
|
||||
int ShowMessageBox(NativeWindow* parent_window,
|
||||
MessageBoxType type,
|
||||
const std::vector<std::string>& buttons,
|
||||
int cancel_id,
|
||||
int default_id,
|
||||
int cancel_id,
|
||||
int options,
|
||||
const std::string& title,
|
||||
const std::string& message,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "atom/browser/ui/message_box.h"
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window_observer.h"
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "base/callback.h"
|
||||
@@ -25,7 +26,7 @@ namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
class GtkMessageBox {
|
||||
class GtkMessageBox : public NativeWindowObserver {
|
||||
public:
|
||||
GtkMessageBox(NativeWindow* parent_window,
|
||||
MessageBoxType type,
|
||||
@@ -77,6 +78,7 @@ class GtkMessageBox {
|
||||
|
||||
// Parent window.
|
||||
if (parent_) {
|
||||
parent_->AddObserver(this);
|
||||
parent_->SetEnabled(false);
|
||||
libgtk2ui::SetGtkTransientForAura(dialog_, parent_->GetNativeWindow());
|
||||
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
|
||||
@@ -85,8 +87,10 @@ class GtkMessageBox {
|
||||
|
||||
~GtkMessageBox() {
|
||||
gtk_widget_destroy(dialog_);
|
||||
if (parent_)
|
||||
if (parent_) {
|
||||
parent_->RemoveObserver(this);
|
||||
parent_->SetEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
GtkMessageType GetMessageType(MessageBoxType type) {
|
||||
@@ -144,6 +148,11 @@ class GtkMessageBox {
|
||||
Show();
|
||||
}
|
||||
|
||||
void OnWindowClosed() override {
|
||||
parent_->RemoveObserver(this);
|
||||
parent_ = nullptr;
|
||||
}
|
||||
|
||||
CHROMEGTK_CALLBACK_1(GtkMessageBox, void, OnResponseDialog, int);
|
||||
|
||||
private:
|
||||
|
||||
@@ -297,7 +297,6 @@ const CGFloat kVerticalTitleMargin = 2;
|
||||
|
||||
if (NSPointInRect([sender draggingLocation], self.frame)) {
|
||||
trayIcon_->NotifyDrop();
|
||||
[self handleDrop:sender];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,6 +324,7 @@ const CGFloat kVerticalTitleMargin = 2;
|
||||
}
|
||||
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
|
||||
[self handleDrop:sender];
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,9 +47,10 @@ void GetMenuBarColor(SkColor* enabled, SkColor* disabled, SkColor* highlight,
|
||||
|
||||
} // namespace
|
||||
|
||||
MenuBar::MenuBar()
|
||||
MenuBar::MenuBar(NativeWindow* window)
|
||||
: background_color_(kDefaultColor),
|
||||
menu_model_(NULL) {
|
||||
menu_model_(NULL),
|
||||
window_(window) {
|
||||
UpdateMenuBarColor();
|
||||
SetLayoutManager(new views::BoxLayout(
|
||||
views::BoxLayout::kHorizontal, 0, 0, 0));
|
||||
@@ -63,7 +64,9 @@ void MenuBar::SetMenu(AtomMenuModel* model) {
|
||||
RemoveAllChildViews(true);
|
||||
|
||||
for (int i = 0; i < model->GetItemCount(); ++i) {
|
||||
SubmenuButton* button = new SubmenuButton(this, model->GetLabelAt(i), this);
|
||||
SubmenuButton* button = new SubmenuButton(model->GetLabelAt(i),
|
||||
this,
|
||||
background_color_);
|
||||
button->set_tag(i);
|
||||
|
||||
#if defined(USE_X11)
|
||||
@@ -131,9 +134,6 @@ const char* MenuBar::GetClassName() const {
|
||||
return kViewClassName;
|
||||
}
|
||||
|
||||
void MenuBar::ButtonPressed(views::Button* sender, const ui::Event& event) {
|
||||
}
|
||||
|
||||
void MenuBar::OnMenuButtonClicked(views::MenuButton* source,
|
||||
const gfx::Point& point,
|
||||
const ui::Event* event) {
|
||||
@@ -143,6 +143,9 @@ void MenuBar::OnMenuButtonClicked(views::MenuButton* source,
|
||||
if (!menu_model_)
|
||||
return;
|
||||
|
||||
if (!window_->IsFocused())
|
||||
window_->Focus(true);
|
||||
|
||||
int id = source->tag();
|
||||
AtomMenuModel::ItemType type = menu_model_->GetTypeAt(id);
|
||||
if (type != AtomMenuModel::TYPE_SUBMENU) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user