mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
619 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec0a8a1321 | ||
|
|
ad8e727ba2 | ||
|
|
46c69cc3e5 | ||
|
|
69140af083 | ||
|
|
ca6f688013 | ||
|
|
3d4318e15e | ||
|
|
367a61d234 | ||
|
|
d4bfeff6ad | ||
|
|
a2a4970f5f | ||
|
|
0e131f760b | ||
|
|
bdd2f91913 | ||
|
|
eb7ed5b456 | ||
|
|
74b76102a8 | ||
|
|
add9c38023 | ||
|
|
791f988aba | ||
|
|
5d7cfa1b3a | ||
|
|
9e880f8d8f | ||
|
|
b4ec7c5aaf | ||
|
|
9a2e2b365d | ||
|
|
01d2765e4b | ||
|
|
12f46ab533 | ||
|
|
9fe326ebeb | ||
|
|
021ee20400 | ||
|
|
b78bb84424 | ||
|
|
77fa02e93e | ||
|
|
3ca4678705 | ||
|
|
55acdcb1ad | ||
|
|
3503b62ff2 | ||
|
|
0f9f8e62fc | ||
|
|
651009a1dc | ||
|
|
64640afc20 | ||
|
|
24518d13d5 | ||
|
|
0ecf077590 | ||
|
|
9eb7c3ac2d | ||
|
|
8385a73d69 | ||
|
|
c1fba9b4a5 | ||
|
|
f9300e0912 | ||
|
|
5d9e4fc8fd | ||
|
|
8d61531f4e | ||
|
|
63c065299a | ||
|
|
6082b83a65 | ||
|
|
e2345163a1 | ||
|
|
af971a46bd | ||
|
|
ef4014e14b | ||
|
|
ca40ea8e2f | ||
|
|
1045bbc861 | ||
|
|
f2c7943d42 | ||
|
|
83c514001e | ||
|
|
0fb68e8130 | ||
|
|
e5e4749eb3 | ||
|
|
d5f81357b6 | ||
|
|
8c3116851d | ||
|
|
8b65d37861 | ||
|
|
4fdf6ceb51 | ||
|
|
21f7316a18 | ||
|
|
fd2bc76bc9 | ||
|
|
79112288b8 | ||
|
|
93f58925aa | ||
|
|
464134a31a | ||
|
|
17483147eb | ||
|
|
a0dcfc57b2 | ||
|
|
d848c1344d | ||
|
|
305d98abc5 | ||
|
|
ee0f0f6cfc | ||
|
|
fa95d32475 | ||
|
|
8734395358 | ||
|
|
7f1cb9f90a | ||
|
|
a987715222 | ||
|
|
1b18a4dfad | ||
|
|
db0732b35b | ||
|
|
442c79abe0 | ||
|
|
82bb790530 | ||
|
|
11af4b63ac | ||
|
|
c18fa63db6 | ||
|
|
44ee74a9b1 | ||
|
|
21cd4c1431 | ||
|
|
70bdfedabf | ||
|
|
6dcc752f67 | ||
|
|
fd9eadd1fa | ||
|
|
6c3a1040aa | ||
|
|
cc912fb7fe | ||
|
|
0fb0808c7b | ||
|
|
fc7f4ae24b | ||
|
|
7923e19553 | ||
|
|
397fbeae28 | ||
|
|
457147365a | ||
|
|
9f30e5f526 | ||
|
|
690f859a78 | ||
|
|
9c44f6ac9f | ||
|
|
56520159f7 | ||
|
|
775c90b733 | ||
|
|
bb102717b4 | ||
|
|
c0528c5049 | ||
|
|
5de1b20935 | ||
|
|
7884a2319c | ||
|
|
6f944ad49b | ||
|
|
94e5018a47 | ||
|
|
4a64d1d946 | ||
|
|
004d3ced53 | ||
|
|
109d8352e1 | ||
|
|
01f0643142 | ||
|
|
a0638fe801 | ||
|
|
ecefd3540b | ||
|
|
06cc133959 | ||
|
|
da57a3101f | ||
|
|
fc422e5d55 | ||
|
|
10731de9d6 | ||
|
|
c73d1ce6c7 | ||
|
|
83481a369a | ||
|
|
1879392c7b | ||
|
|
39695cdb85 | ||
|
|
0861d5d44b | ||
|
|
62604708d1 | ||
|
|
e3fab8b5b3 | ||
|
|
497732fb6f | ||
|
|
fe2d9ee0f6 | ||
|
|
5d26bc08ee | ||
|
|
5ca5c4fb92 | ||
|
|
576257470b | ||
|
|
269f70c12a | ||
|
|
9e90ea8734 | ||
|
|
9b1fa04988 | ||
|
|
d621755f13 | ||
|
|
e3ec705c80 | ||
|
|
b0e5039951 | ||
|
|
22e6f15795 | ||
|
|
1520ebfe1f | ||
|
|
142702866d | ||
|
|
334c28d128 | ||
|
|
057c77341a | ||
|
|
706deae1b0 | ||
|
|
f8f8db7e88 | ||
|
|
6c01cec8d2 | ||
|
|
d8062ab9e1 | ||
|
|
748b1387d2 | ||
|
|
d3a79010ea | ||
|
|
6c8a9cb072 | ||
|
|
7165aa5467 | ||
|
|
8bfa3cba63 | ||
|
|
f2fa0e96eb | ||
|
|
d0d71efb0b | ||
|
|
486f16fffa | ||
|
|
e499bb14de | ||
|
|
4521db459b | ||
|
|
de41890196 | ||
|
|
a6b7dd22e8 | ||
|
|
f06f8ae73b | ||
|
|
9cbdde2eba | ||
|
|
f07fea1936 | ||
|
|
7c65d05b02 | ||
|
|
619a397ec9 | ||
|
|
889d7c1e02 | ||
|
|
4cccce6bfe | ||
|
|
4a91972037 | ||
|
|
42515c6f41 | ||
|
|
eccb5e7590 | ||
|
|
008af00044 | ||
|
|
325feca864 | ||
|
|
5ef9c7e1a1 | ||
|
|
22168bc6d8 | ||
|
|
62d64e7528 | ||
|
|
477103191f | ||
|
|
57bf0cb615 | ||
|
|
01a3bf5881 | ||
|
|
a69c9600ce | ||
|
|
a567d7a0b6 | ||
|
|
7807d878d2 | ||
|
|
a69121fc24 | ||
|
|
be600fda55 | ||
|
|
35fc8885de | ||
|
|
717e0f9821 | ||
|
|
997ac91fe0 | ||
|
|
4391e81dfe | ||
|
|
d0ee30101d | ||
|
|
dd38131704 | ||
|
|
40b861bc9c | ||
|
|
5ec74451ef | ||
|
|
87b9b0bc31 | ||
|
|
76b7cd0908 | ||
|
|
c626ee6e92 | ||
|
|
94b6b92e4c | ||
|
|
6cf6cb9a79 | ||
|
|
7bb9595b81 | ||
|
|
f716d47e54 | ||
|
|
353cdd967a | ||
|
|
32bff05208 | ||
|
|
b8d50f3a3a | ||
|
|
7b2980434c | ||
|
|
ff0e15bf58 | ||
|
|
1e918480b4 | ||
|
|
573892c112 | ||
|
|
86f523d3c1 | ||
|
|
42863e4700 | ||
|
|
9e7de78231 | ||
|
|
c550546ff1 | ||
|
|
5a599cb6ff | ||
|
|
84ce441fb6 | ||
|
|
d7bac5a10b | ||
|
|
ec90d03d74 | ||
|
|
ee0d48dc5a | ||
|
|
15394b9a3b | ||
|
|
5aa7cf7a30 | ||
|
|
7dc7ee1c41 | ||
|
|
96d35ec29e | ||
|
|
91796e7095 | ||
|
|
75b0d0cd6c | ||
|
|
6b875110ed | ||
|
|
1348e18a81 | ||
|
|
c700c58793 | ||
|
|
a46cb8cebb | ||
|
|
01ed2c4222 | ||
|
|
d28789b509 | ||
|
|
2be6bdcf4a | ||
|
|
5604655d54 | ||
|
|
93639a080c | ||
|
|
e30dd943db | ||
|
|
a386bb4edf | ||
|
|
ce8eb4a32c | ||
|
|
e73c655d65 | ||
|
|
e3c64d7971 | ||
|
|
9fd5a64cd8 | ||
|
|
ec7ea3005d | ||
|
|
3f881e8617 | ||
|
|
25a2f28501 | ||
|
|
cb13d8bdc7 | ||
|
|
11ee2c47d0 | ||
|
|
7b75b29265 | ||
|
|
b9c274929b | ||
|
|
842ec3d11b | ||
|
|
244e184b7e | ||
|
|
a3a9bbb979 | ||
|
|
57c910faef | ||
|
|
90064eeddd | ||
|
|
08f5c32306 | ||
|
|
69cc3ab5ef | ||
|
|
5269380b6d | ||
|
|
d8f77e5134 | ||
|
|
ceef06b344 | ||
|
|
a3e9ff67b0 | ||
|
|
ae776b523c | ||
|
|
10b1ea7244 | ||
|
|
6615787775 | ||
|
|
cf6008a05e | ||
|
|
f1787d747a | ||
|
|
eced01eb9d | ||
|
|
357c7af3c0 | ||
|
|
817363b955 | ||
|
|
311a5456ec | ||
|
|
3cf34fe40f | ||
|
|
2a3a65f67c | ||
|
|
c9ee6b4caf | ||
|
|
b72a5884f2 | ||
|
|
97857aa152 | ||
|
|
fe2219a635 | ||
|
|
c99ec368b3 | ||
|
|
9652ed6508 | ||
|
|
dc59b4fa06 | ||
|
|
a1ccfdf777 | ||
|
|
40d93ce55a | ||
|
|
377e7ee3a7 | ||
|
|
8a8b11cf10 | ||
|
|
e656d8428c | ||
|
|
238d4add99 | ||
|
|
3bf73bc455 | ||
|
|
9134b9cf43 | ||
|
|
dd7036035a | ||
|
|
6bae0bada0 | ||
|
|
f140f35910 | ||
|
|
a5dc911a05 | ||
|
|
5d8f1dd404 | ||
|
|
409b0b54e0 | ||
|
|
c006c4efa4 | ||
|
|
3ad5d17612 | ||
|
|
4d28fbf561 | ||
|
|
1533d97e16 | ||
|
|
ca8943c4ba | ||
|
|
8534ff4526 | ||
|
|
c346fcb326 | ||
|
|
9e7b67802c | ||
|
|
9d366e6c5c | ||
|
|
d2e52fb6bb | ||
|
|
baacc939f6 | ||
|
|
3bd16a5ecd | ||
|
|
7c3d3e4a87 | ||
|
|
e388163d33 | ||
|
|
654626305c | ||
|
|
989799633d | ||
|
|
bf01112acd | ||
|
|
af5262630a | ||
|
|
a1cd806955 | ||
|
|
ff67fae9ef | ||
|
|
b80aab3cf2 | ||
|
|
750d3e979c | ||
|
|
c3664463ab | ||
|
|
c6395c2197 | ||
|
|
39bd10d1ef | ||
|
|
9eca0f82de | ||
|
|
4b8472d3b4 | ||
|
|
aae2d82c28 | ||
|
|
6cfe43a644 | ||
|
|
2ac2392a6b | ||
|
|
7c287d565d | ||
|
|
31775aa049 | ||
|
|
9ca85a7859 | ||
|
|
b861a174ca | ||
|
|
92f7899c60 | ||
|
|
572199068b | ||
|
|
32a66fa94e | ||
|
|
60522e0d68 | ||
|
|
708526baec | ||
|
|
ae2f754d10 | ||
|
|
143453b603 | ||
|
|
d4cbf7cadb | ||
|
|
3ee854d9a3 | ||
|
|
442b0d5df3 | ||
|
|
c8954ff32c | ||
|
|
6321a3898c | ||
|
|
70af2e0bee | ||
|
|
626c7d1090 | ||
|
|
1497e7e2ac | ||
|
|
69769f9319 | ||
|
|
f807a8f1e7 | ||
|
|
b2af370249 | ||
|
|
c29a2e4992 | ||
|
|
279fd0a461 | ||
|
|
1a35d6bda6 | ||
|
|
5593717d78 | ||
|
|
6abc4fb255 | ||
|
|
e9712e2998 | ||
|
|
ce49bba2fc | ||
|
|
5089929be8 | ||
|
|
590be75fa9 | ||
|
|
0046970805 | ||
|
|
9dc6cfc1e9 | ||
|
|
749a1a3e9a | ||
|
|
93bbc0bca9 | ||
|
|
9d51da505e | ||
|
|
e48f5ea1aa | ||
|
|
e5496d9ac0 | ||
|
|
c2b2a2072f | ||
|
|
446235c8cd | ||
|
|
530b040ade | ||
|
|
375ac3e6ec | ||
|
|
a200718944 | ||
|
|
ba02e19fae | ||
|
|
8e1979a6a5 | ||
|
|
e5386cf8ea | ||
|
|
e597229750 | ||
|
|
8b3ed9067e | ||
|
|
40d4c65866 | ||
|
|
1ca6534dcd | ||
|
|
830bb54d6a | ||
|
|
785eb9657b | ||
|
|
21bd578935 | ||
|
|
1e0facc103 | ||
|
|
db3e27ceaa | ||
|
|
b521e45ef8 | ||
|
|
ad6e67fdfa | ||
|
|
564b74b19c | ||
|
|
62b1034c6b | ||
|
|
4412a89270 | ||
|
|
d4aa2308cd | ||
|
|
8912b404a9 | ||
|
|
d7ec0b99fd | ||
|
|
87e02f2858 | ||
|
|
66f7f2e6f2 | ||
|
|
13722e26cd | ||
|
|
e365cb6b1c | ||
|
|
46b2b91a27 | ||
|
|
24bbe5dabf | ||
|
|
3717f5b7f2 | ||
|
|
10bc0c20b1 | ||
|
|
0a4fb2ec4f | ||
|
|
8cc1046992 | ||
|
|
3669113ad2 | ||
|
|
aad1f5082f | ||
|
|
f56d715104 | ||
|
|
cd12dbd47e | ||
|
|
5830532a45 | ||
|
|
4537d88a58 | ||
|
|
342e0c6cf7 | ||
|
|
512f89910d | ||
|
|
e2bd1abce6 | ||
|
|
5eb0bedbbc | ||
|
|
2454dccde0 | ||
|
|
0b1a3f3ef3 | ||
|
|
fafb28e41a | ||
|
|
ba25bed45b | ||
|
|
3773f81fd5 | ||
|
|
f2bdca31b3 | ||
|
|
9c235509a6 | ||
|
|
b1afe538ee | ||
|
|
0b97d58a6f | ||
|
|
880dce950d | ||
|
|
39975378bb | ||
|
|
96771c7098 | ||
|
|
0e92a3e333 | ||
|
|
dd871812b7 | ||
|
|
81d423c547 | ||
|
|
943fe2c22d | ||
|
|
38e948f55b | ||
|
|
3e4ad4c696 | ||
|
|
0bc8e7b787 | ||
|
|
a8d56df41e | ||
|
|
41e1555cf4 | ||
|
|
dcbd8316df | ||
|
|
1a1b45e088 | ||
|
|
b980650b6e | ||
|
|
b9da81ee6a | ||
|
|
b797804fd9 | ||
|
|
0577e911b3 | ||
|
|
619c77f409 | ||
|
|
6c5c202a99 | ||
|
|
090c817ac9 | ||
|
|
f91a7e6d04 | ||
|
|
5d6ac2296b | ||
|
|
26dea993df | ||
|
|
eb8ac2b5d8 | ||
|
|
44528ce60e | ||
|
|
e72e09719a | ||
|
|
6f9d822472 | ||
|
|
67026cccc8 | ||
|
|
30c714a27f | ||
|
|
05031a38e5 | ||
|
|
ae8ffae59e | ||
|
|
587a9f1c5b | ||
|
|
bd264aa1ba | ||
|
|
9557ce523a | ||
|
|
f1e5a99881 | ||
|
|
03ba9533fb | ||
|
|
8f59c0b642 | ||
|
|
da5bac42f3 | ||
|
|
150b540e72 | ||
|
|
5189147021 | ||
|
|
d180d3b168 | ||
|
|
3f546e6bab | ||
|
|
c65ccb6857 | ||
|
|
e3504b2b24 | ||
|
|
53b9d61831 | ||
|
|
2c3751e287 | ||
|
|
4a81300100 | ||
|
|
73af4c017d | ||
|
|
2734d67a38 | ||
|
|
c81de98d22 | ||
|
|
599e9b90bb | ||
|
|
c1d7ad9631 | ||
|
|
ee0dc0d926 | ||
|
|
4254eb279f | ||
|
|
262b66b93a | ||
|
|
45491ca7ab | ||
|
|
1db843244d | ||
|
|
992aada90f | ||
|
|
c01d2fbbcd | ||
|
|
f75458f78d | ||
|
|
d6daea12af | ||
|
|
28e5258a96 | ||
|
|
f6d6a2a4c3 | ||
|
|
c56b78f0fa | ||
|
|
27b77a06ed | ||
|
|
357dea506a | ||
|
|
c2dcccf7c7 | ||
|
|
28764b0f77 | ||
|
|
66a1405d2b | ||
|
|
b3eb6dc32b | ||
|
|
3af2540fad | ||
|
|
2f41641139 | ||
|
|
131cd9cff6 | ||
|
|
bd20104e5a | ||
|
|
2e5a539f57 | ||
|
|
159b6ca611 | ||
|
|
3914ff2ac5 | ||
|
|
f12ccac17e | ||
|
|
f8d40a88fb | ||
|
|
e78db6ae07 | ||
|
|
e71d2bd8e7 | ||
|
|
ba7ddd66a1 | ||
|
|
f5f3278ffa | ||
|
|
bfa33de792 | ||
|
|
ae3ff4e1e3 | ||
|
|
0fa0aedd86 | ||
|
|
e6265ec405 | ||
|
|
6bce5b560b | ||
|
|
009b27f5f1 | ||
|
|
7d07f10c25 | ||
|
|
d830badc57 | ||
|
|
dbcd0a4235 | ||
|
|
47d103af72 | ||
|
|
91c75d73dd | ||
|
|
2ead38b03f | ||
|
|
dd2ed559cf | ||
|
|
ab726ec1f5 | ||
|
|
2c47532702 | ||
|
|
95133af0ee | ||
|
|
17cc43152d | ||
|
|
0cb20c48f6 | ||
|
|
4e7f56846f | ||
|
|
4062ca5f68 | ||
|
|
e043ea9c20 | ||
|
|
10b53f7f73 | ||
|
|
7acd3c1973 | ||
|
|
889c982918 | ||
|
|
c70513f7ce | ||
|
|
691d8dd9ab | ||
|
|
316210d6c4 | ||
|
|
dddb598818 | ||
|
|
50bfe9e335 | ||
|
|
a03df3ac5a | ||
|
|
05d0f17447 | ||
|
|
f31848563f | ||
|
|
d9c3830df7 | ||
|
|
cb4558e75b | ||
|
|
be73388918 | ||
|
|
6a2bd80a9a | ||
|
|
52916f70ed | ||
|
|
a5234224a6 | ||
|
|
c6269bf77a | ||
|
|
0e4ae6f864 | ||
|
|
96bb9b2757 | ||
|
|
e0a57a0a47 | ||
|
|
8cf1bc8457 | ||
|
|
eb3769f98e | ||
|
|
afff32dc8d | ||
|
|
ddee9f3e75 | ||
|
|
3dd3fd9200 | ||
|
|
625ee387f3 | ||
|
|
c59c0bd5b3 | ||
|
|
ebedb60684 | ||
|
|
9ecc4bcb7d | ||
|
|
b205bd381e | ||
|
|
af52eda0eb | ||
|
|
aed487ef40 | ||
|
|
50c7985ee2 | ||
|
|
00136a221f | ||
|
|
a6b86e924a | ||
|
|
ed01698444 | ||
|
|
6459531bef | ||
|
|
49b15bd4f3 | ||
|
|
c67268a74f | ||
|
|
2c79e9fd41 | ||
|
|
29c865f0e1 | ||
|
|
e0542945ce | ||
|
|
842ba6aea6 | ||
|
|
009e228218 | ||
|
|
d93b6c1cae | ||
|
|
2206279846 | ||
|
|
1e5b7af490 | ||
|
|
cb62afca23 | ||
|
|
254cdc0e6c | ||
|
|
2c6210cf9c | ||
|
|
3d4f0dfc44 | ||
|
|
874367e2c5 | ||
|
|
22652860a2 | ||
|
|
87db1e8802 | ||
|
|
8b6f3dc0aa | ||
|
|
9c46be9d47 | ||
|
|
9ee063ca14 | ||
|
|
eab88ea09c | ||
|
|
cfc5ecb05d | ||
|
|
8757da6c47 | ||
|
|
39e3506add | ||
|
|
0f2ef3feb2 | ||
|
|
82d801ab9e | ||
|
|
955ae78e33 | ||
|
|
8d40714f78 | ||
|
|
2c3ed90ff3 | ||
|
|
b1fc18f405 | ||
|
|
e8a04981bb | ||
|
|
a2cc936a3b | ||
|
|
e6e09a8a7c | ||
|
|
50736296a7 | ||
|
|
b759999272 | ||
|
|
a5969fd076 | ||
|
|
91150839be | ||
|
|
83aa9df1ee | ||
|
|
a38d34d368 | ||
|
|
e8461b6f90 | ||
|
|
33a19f9071 | ||
|
|
58081ca9e9 | ||
|
|
8ee91bce44 | ||
|
|
dbc1855b42 | ||
|
|
dd28a2ef14 | ||
|
|
609961a1de | ||
|
|
852d982057 | ||
|
|
6277a65bb7 | ||
|
|
26f7f2ab21 | ||
|
|
aa03fddb62 | ||
|
|
bbf2cbb6f6 | ||
|
|
221eff7fec | ||
|
|
c2073a3c45 | ||
|
|
d02ced87b8 | ||
|
|
f74d7d71e6 | ||
|
|
e4c01f3187 | ||
|
|
a1f17069ec | ||
|
|
71f46c0287 | ||
|
|
a34a16653e | ||
|
|
f96c76584f | ||
|
|
586b407103 | ||
|
|
715a88026e | ||
|
|
3001ef7980 | ||
|
|
0a4144e67a | ||
|
|
71fa87e4ed | ||
|
|
4e781eb042 | ||
|
|
5f1897713c | ||
|
|
38b519ceb5 | ||
|
|
71f74f4042 | ||
|
|
c282d4c0ff | ||
|
|
00de81771c | ||
|
|
bc909ddf5e | ||
|
|
840095b444 | ||
|
|
f4783772c5 | ||
|
|
ba9c47eb7e | ||
|
|
76416d5e47 | ||
|
|
864c8df639 | ||
|
|
81ed608b9c | ||
|
|
d2288815f8 | ||
|
|
2c7ccffe1a | ||
|
|
a67767dbea | ||
|
|
703ced32db | ||
|
|
90392e9231 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,4 +17,3 @@ node_modules/
|
||||
*.pyc
|
||||
debug.log
|
||||
npm-debug.log
|
||||
atom/common/chrome_version.h
|
||||
|
||||
@@ -29,7 +29,8 @@ possible with your report. If you can, please include:
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
* Follow the CoffeeScript, JavaScript, C++ and Python [coding style defined in docs](/docs/development/coding-style.md).
|
||||
* Write documentation in [Markdown](https://daringfireball.net/projects/markdown).
|
||||
* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages-styleguide).
|
||||
See the [Documentation Styleguide](/docs/styleguide.md).
|
||||
* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages).
|
||||
|
||||
## Styleguides
|
||||
|
||||
|
||||
17
README-ko.md
17
README-ko.md
@@ -6,13 +6,15 @@
|
||||
|
||||
### [Electron](https://github.com/atom/electron/) 한국어 참조문서
|
||||
|
||||
:zap: *이전까지 Atom Shell로 알려져 있었습니다* :zap:
|
||||
:zap: *프레임워크 이름이 Atom Shell에서 Electron으로 변경되었습니다* :zap:
|
||||
|
||||
Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. 이 프레임워크는 [io.js](http://iojs.org) 와
|
||||
[Chromium](http://www.chromium.org)을 기반으로 만들어 졌으며 [Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다.
|
||||
|
||||
Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서 [@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요.
|
||||
|
||||
이 프로젝트는 기여자 규약 1.2를 준수합니다. 이 프로젝트에 참여할 때 코드를 유지해야 합니다. 받아들일 수 없는 행동은 atom@github.com로 보고 하십시오.
|
||||
|
||||
## 다운로드
|
||||
|
||||
Linux, Windows, Mac용으로 미리 빌드된 Electron 바이너리와 디버그 심볼이 준비되어 있습니다. [releases](https://github.com/atom/electron/releases) 페이지에서 받아 볼 수 있습니다.
|
||||
@@ -36,14 +38,21 @@ npm install electron-prebuilt --save-dev
|
||||
[Docs](https://github.com/atom/electron/tree/master/docs/README.md)에 개발 가이드와 API 레퍼런스가 있습니다.
|
||||
Electron을 빌드 하는 방법과 프로젝트에 기여하는 방법도 문서에 포함되어 있으니 참고하시기 바랍니다.
|
||||
|
||||
## 참조 문서(번역)
|
||||
## 참조 문서 (번역)
|
||||
|
||||
- [한국어](https://github.com/atom/electron/tree/master/docs-translations/ko)
|
||||
- [브라질 포르투칼어](https://github.com/atom/electron/tree/master/docs-translations/pt-BR)
|
||||
- [한국어](https://github.com/atom/electron/tree/master/docs-translations/ko-KR)
|
||||
- [일본어](https://github.com/atom/electron/tree/master/docs-translations/jp)
|
||||
- [스페인어](https://github.com/atom/electron/tree/master/docs-translations/es)
|
||||
- [중국어 간체](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
|
||||
- [중국어 번체](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||
|
||||
## 커뮤니티
|
||||
|
||||
[Atom 포럼내의 `electron` 카테고리](http://discuss.atom.io/category/electron)와 Freenode `#atom-shell` 채팅 채널에서 활발하게 토론이 이어지고 있습니다.
|
||||
다음 링크를 통해 커뮤니티에 질문을 올리거나 토론을 나누실 수 있습니다:
|
||||
|
||||
- Atom 포럼의 [`electron`](http://discuss.atom.io/category/electron) 카테고리
|
||||
- Freenode 채팅의 `#atom-shell` 채널
|
||||
- Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널
|
||||
|
||||
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트엔 커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 한번 참고해 보시기 바랍니다.
|
||||
|
||||
21
README.md
21
README.md
@@ -4,7 +4,7 @@
|
||||
[](https://david-dm.org/atom/electron#info=devDependencies)
|
||||
[](http://atom-slack.herokuapp.com/)
|
||||
|
||||
:zap: *formerly known as Atom Shell* :zap:
|
||||
:zap: *Formerly known as Atom Shell* :zap:
|
||||
|
||||
The Electron framework lets you write cross-platform desktop applications
|
||||
using JavaScript, HTML and CSS. It is based on [io.js](http://iojs.org) and
|
||||
@@ -15,7 +15,8 @@ Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
|
||||
announcements.
|
||||
|
||||
This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable behavior to atom@github.com.
|
||||
By participating, you are expected to uphold this code. Please report
|
||||
unacceptable behavior to atom@github.com.
|
||||
|
||||
## Downloads
|
||||
|
||||
@@ -45,13 +46,21 @@ contains documents describing how to build and contribute to Electron.
|
||||
|
||||
## Documentation Translations
|
||||
|
||||
- [Korean](https://github.com/atom/electron/tree/master/docs-translations/ko)
|
||||
- [Brazilian Portuguese](https://github.com/atom/electron/tree/master/docs-translations/pt-BR)
|
||||
- [Korean](https://github.com/atom/electron/tree/master/docs-translations/ko-KR)
|
||||
- [Japanese](https://github.com/atom/electron/tree/master/docs-translations/jp)
|
||||
- [Spanish](https://github.com/atom/electron/tree/master/docs-translations/es)
|
||||
- [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
|
||||
- [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||
|
||||
## Community
|
||||
|
||||
There is an [`electron` category on the Atom forums](http://discuss.atom.io/category/electron)
|
||||
as well as an `#atom-shell` channel on Freenode.
|
||||
You can ask questions and interact with the community in the following
|
||||
locations:
|
||||
- [`electron`](http://discuss.atom.io/category/electron) category on the Atom
|
||||
forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
||||
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron) for a community maintained list of useful example apps, tools and resources.
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
for a community maintained list of useful example apps, tools and resources.
|
||||
|
||||
2
atom.gyp
2
atom.gyp
@@ -4,7 +4,7 @@
|
||||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '0.31.0',
|
||||
'version%': '0.33.5',
|
||||
},
|
||||
'includes': [
|
||||
'filenames.gypi',
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/atom_version.h"
|
||||
#include "atom/common/chrome_version.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
@@ -14,6 +15,7 @@
|
||||
#include "base/strings/string_util.h"
|
||||
#include "content/public/common/content_constants.h"
|
||||
#include "content/public/common/pepper_plugin_info.h"
|
||||
#include "content/public/common/user_agent.h"
|
||||
#include "ppapi/shared_impl/ppapi_permissions.h"
|
||||
|
||||
namespace atom {
|
||||
@@ -72,6 +74,12 @@ std::string AtomContentClient::GetProduct() const {
|
||||
return "Chrome/" CHROME_VERSION_STRING;
|
||||
}
|
||||
|
||||
std::string AtomContentClient::GetUserAgent() const {
|
||||
return content::BuildUserAgentFromProduct(
|
||||
"Chrome/" CHROME_VERSION_STRING " "
|
||||
ATOM_PRODUCT_NAME "/" ATOM_VERSION_STRING);
|
||||
}
|
||||
|
||||
void AtomContentClient::AddAdditionalSchemes(
|
||||
std::vector<std::string>* standard_schemes,
|
||||
std::vector<std::string>* savable_schemes) {
|
||||
|
||||
@@ -20,6 +20,7 @@ class AtomContentClient : public brightray::ContentClient {
|
||||
protected:
|
||||
// content::ContentClient:
|
||||
std::string GetProduct() const override;
|
||||
std::string GetUserAgent() const override;
|
||||
void AddAdditionalSchemes(
|
||||
std::vector<std::string>* standard_schemes,
|
||||
std::vector<std::string>* savable_schemes) override;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "atom/app/node_main.h"
|
||||
#include "atom/common/atom_command_line.h"
|
||||
#include "base/at_exit.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -134,6 +135,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
if (env->GetVar("ATOM_SHELL_INTERNAL_RUN_AS_NODE", &node_indicator) &&
|
||||
node_indicator == "1") {
|
||||
// Now that argv conversion is done, we can finally start.
|
||||
base::AtExitManager atexit_manager;
|
||||
base::i18n::InitializeICU();
|
||||
return atom::NodeMain(argc, argv);
|
||||
} else if (env->GetVar("ATOM_SHELL_INTERNAL_CRASH_SERVICE",
|
||||
@@ -165,6 +167,7 @@ int main(int argc, const char* argv[]) {
|
||||
char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
|
||||
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
|
||||
base::i18n::InitializeICU();
|
||||
base::AtExitManager atexit_manager;
|
||||
return atom::NodeMain(argc, const_cast<char**>(argv));
|
||||
}
|
||||
|
||||
|
||||
@@ -27,10 +27,10 @@ AtomMainDelegate::~AtomMainDelegate() {
|
||||
}
|
||||
|
||||
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
// Disable logging out to debug.log on Windows
|
||||
logging::LoggingSettings settings;
|
||||
#if defined(OS_WIN)
|
||||
#if defined(DEBUG)
|
||||
// Print logging to debug.log on Windows
|
||||
settings.logging_dest = logging::LOG_TO_ALL;
|
||||
settings.log_file = L"debug.log";
|
||||
settings.lock_log = logging::LOCK_LOG_FILE;
|
||||
@@ -38,7 +38,15 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
#else
|
||||
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
#endif // defined(DEBUG)
|
||||
#endif // defined(OS_WIN)
|
||||
#else // defined(OS_WIN)
|
||||
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
#endif // !defined(OS_WIN)
|
||||
|
||||
// Only enable logging when --enable-logging is specified.
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
if (!command_line->HasSwitch(switches::kEnableLogging))
|
||||
settings.logging_dest = logging::LOG_NONE;
|
||||
|
||||
logging::InitLogging(settings);
|
||||
|
||||
// Logging with pid and timestamp.
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
#include "atom/app/node_main.h"
|
||||
|
||||
#include "atom/app/uv_task_runner.h"
|
||||
#include "atom/browser/javascript_environment.h"
|
||||
#include "atom/browser/node_debugger.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "gin/array_buffer.h"
|
||||
#include "gin/public/isolate_holder.h"
|
||||
#include "gin/v8_initializer.h"
|
||||
@@ -24,14 +26,20 @@ int NodeMain(int argc, char *argv[]) {
|
||||
|
||||
int exit_code = 1;
|
||||
{
|
||||
// Feed gin::PerIsolateData with a task runner.
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
scoped_refptr<UvTaskRunner> uv_task_runner(new UvTaskRunner(loop));
|
||||
base::ThreadTaskRunnerHandle handle(uv_task_runner);
|
||||
|
||||
gin::V8Initializer::LoadV8Snapshot();
|
||||
gin::V8Initializer::LoadV8Natives();
|
||||
gin::IsolateHolder::Initialize(
|
||||
gin::IsolateHolder::kNonStrictMode,
|
||||
gin::ArrayBufferAllocator::SharedInstance());
|
||||
|
||||
JavascriptEnvironment gin_env;
|
||||
node::Environment* env = node::CreateEnvironment(
|
||||
gin_env.isolate(), uv_default_loop(), gin_env.context(), argc, argv,
|
||||
gin_env.isolate(), loop, gin_env.context(), argc, argv,
|
||||
exec_argc, exec_argv);
|
||||
|
||||
// Start our custom debugger implementation.
|
||||
|
||||
55
atom/app/uv_task_runner.cc
Normal file
55
atom/app/uv_task_runner.cc
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/app/uv_task_runner.h"
|
||||
|
||||
#include "base/stl_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
UvTaskRunner::UvTaskRunner(uv_loop_t* loop) : loop_(loop) {
|
||||
}
|
||||
|
||||
UvTaskRunner::~UvTaskRunner() {
|
||||
for (auto& iter : tasks_) {
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(iter.first));
|
||||
delete iter.first;
|
||||
}
|
||||
}
|
||||
|
||||
bool UvTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
uv_timer_t* timer = new uv_timer_t;
|
||||
timer->data = this;
|
||||
uv_timer_init(loop_, timer);
|
||||
uv_timer_start(timer, UvTaskRunner::OnTimeout, delay.InMilliseconds(), 0);
|
||||
tasks_[timer] = task;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UvTaskRunner::RunsTasksOnCurrentThread() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UvTaskRunner::PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
return PostDelayedTask(from_here, task, delay);;
|
||||
}
|
||||
|
||||
// static
|
||||
void UvTaskRunner::OnTimeout(uv_timer_t* timer) {
|
||||
UvTaskRunner* self = static_cast<UvTaskRunner*>(timer->data);
|
||||
if (!ContainsKey(self->tasks_, timer))
|
||||
return;
|
||||
|
||||
self->tasks_[timer].Run();
|
||||
self->tasks_.erase(timer);
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(timer));
|
||||
delete timer;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
44
atom/app/uv_task_runner.h
Normal file
44
atom/app/uv_task_runner.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_APP_UV_TASK_RUNNER_H_
|
||||
#define ATOM_APP_UV_TASK_RUNNER_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "vendor/node/deps/uv/include/uv.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// TaskRunner implementation that posts tasks into libuv's default loop.
|
||||
class UvTaskRunner : public base::SingleThreadTaskRunner {
|
||||
public:
|
||||
explicit UvTaskRunner(uv_loop_t* loop);
|
||||
~UvTaskRunner() override;
|
||||
|
||||
// base::SingleThreadTaskRunner:
|
||||
bool PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) override;
|
||||
bool RunsTasksOnCurrentThread() const override;
|
||||
bool PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) override;
|
||||
|
||||
private:
|
||||
static void OnTimeout(uv_timer_t* timer);
|
||||
|
||||
uv_loop_t* loop_;
|
||||
|
||||
std::map<uv_timer_t*, base::Closure> tasks_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(UvTaskRunner);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_APP_UV_TASK_RUNNER_H_
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#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/command_line.h"
|
||||
#include "base/environment.h"
|
||||
#include "base/files/file_path.h"
|
||||
@@ -29,13 +30,12 @@
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#endif
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using atom::Browser;
|
||||
|
||||
namespace mate {
|
||||
@@ -168,8 +168,8 @@ void App::OnOpenURL(const std::string& url) {
|
||||
Emit("open-url", url);
|
||||
}
|
||||
|
||||
void App::OnActivateWithNoOpenWindows() {
|
||||
Emit("activate-with-no-open-windows");
|
||||
void App::OnActivate(bool has_visible_windows) {
|
||||
Emit("activate", has_visible_windows);
|
||||
}
|
||||
|
||||
void App::OnWillFinishLaunching() {
|
||||
@@ -249,6 +249,10 @@ void App::SetAppUserModelId(const std::string& app_id) {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string App::GetLocale() {
|
||||
return l10n_util::GetApplicationLocale("");
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> App::DefaultSession(v8::Isolate* isolate) {
|
||||
if (default_session_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
@@ -279,6 +283,7 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
|
||||
.SetMethod("getPath", &App::GetPath)
|
||||
.SetMethod("setDesktopName", &App::SetDesktopName)
|
||||
.SetMethod("setAppUserModelId", &App::SetAppUserModelId)
|
||||
.SetMethod("getLocale", &App::GetLocale)
|
||||
.SetProperty("defaultSession", &App::DefaultSession);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class App : public mate::EventEmitter,
|
||||
void OnQuit() override;
|
||||
void OnOpenFile(bool* prevent_default, const std::string& file_path) override;
|
||||
void OnOpenURL(const std::string& url) override;
|
||||
void OnActivateWithNoOpenWindows() override;
|
||||
void OnActivate(bool has_visible_windows) override;
|
||||
void OnWillFinishLaunching() override;
|
||||
void OnFinishLaunching() override;
|
||||
void OnSelectCertificate(
|
||||
@@ -65,6 +65,7 @@ class App : public mate::EventEmitter,
|
||||
|
||||
void SetDesktopName(const std::string& desktop_name);
|
||||
void SetAppUserModelId(const std::string& app_id);
|
||||
std::string GetLocale();
|
||||
v8::Local<v8::Value> DefaultSession(v8::Isolate* isolate);
|
||||
|
||||
v8::Global<v8::Value> default_session_;
|
||||
|
||||
@@ -7,11 +7,10 @@
|
||||
#include "base/time/time.h"
|
||||
#include "atom/browser/auto_updater.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
@@ -7,39 +7,30 @@
|
||||
|
||||
#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 {
|
||||
|
||||
template<>
|
||||
struct Converter<base::trace_event::CategoryFilter> {
|
||||
struct Converter<base::trace_event::TraceConfig> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
base::trace_event::CategoryFilter* out) {
|
||||
std::string filter;
|
||||
if (!ConvertFromV8(isolate, val, &filter))
|
||||
return false;
|
||||
*out = base::trace_event::CategoryFilter(filter);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<base::trace_event::TraceOptions> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
base::trace_event::TraceOptions* out) {
|
||||
std::string options;
|
||||
base::trace_event::TraceConfig* out) {
|
||||
Dictionary options;
|
||||
if (!ConvertFromV8(isolate, val, &options))
|
||||
return false;
|
||||
return out->SetFromString(options);
|
||||
std::string category_filter, trace_options;
|
||||
if (!options.Get("categoryFilter", &category_filter) ||
|
||||
!options.Get("traceOptions", &trace_options))
|
||||
return false;
|
||||
*out = base::trace_event::TraceConfig(category_filter, trace_options);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using atom::api::Cookies;
|
||||
using content::BrowserThread;
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ class Cookies : public mate::Wrappable {
|
||||
// Must be called on IO thread.
|
||||
net::CookieStore* GetCookieStore();
|
||||
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Cookies);
|
||||
};
|
||||
|
||||
201
atom/browser/api/atom_api_download_item.cc
Normal file
201
atom/browser/api/atom_api_download_item.cc
Normal file
@@ -0,0 +1,201 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_download_item.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#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/memory/linked_ptr.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "net/base/filename_util.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<content::DownloadItem::DownloadState> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
content::DownloadItem::DownloadState state) {
|
||||
std::string download_state;
|
||||
switch (state) {
|
||||
case content::DownloadItem::COMPLETE:
|
||||
download_state = "completed";
|
||||
break;
|
||||
case content::DownloadItem::CANCELLED:
|
||||
download_state = "cancelled";
|
||||
break;
|
||||
case content::DownloadItem::INTERRUPTED:
|
||||
download_state = "interrupted";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ConvertToV8(isolate, download_state);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
// The wrapDownloadItem funtion which is implemented in JavaScript
|
||||
using WrapDownloadItemCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
WrapDownloadItemCallback g_wrap_download_item;
|
||||
|
||||
char kDownloadItemSavePathKey[] = "DownloadItemSavePathKey";
|
||||
|
||||
std::map<uint32, linked_ptr<v8::Global<v8::Value>>> g_download_item_objects;
|
||||
} // namespace
|
||||
|
||||
DownloadItem::SavePathData::SavePathData(const base::FilePath& path) :
|
||||
path_(path) {
|
||||
}
|
||||
|
||||
const base::FilePath& DownloadItem::SavePathData::path() {
|
||||
return path_;
|
||||
}
|
||||
|
||||
DownloadItem::DownloadItem(content::DownloadItem* download_item) :
|
||||
download_item_(download_item) {
|
||||
download_item_->AddObserver(this);
|
||||
}
|
||||
|
||||
DownloadItem::~DownloadItem() {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void DownloadItem::Destroy() {
|
||||
if (download_item_) {
|
||||
download_item_->RemoveObserver(this);
|
||||
auto iter = g_download_item_objects.find(download_item_->GetId());
|
||||
if (iter != g_download_item_objects.end())
|
||||
g_download_item_objects.erase(iter);
|
||||
download_item_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool DownloadItem::IsDestroyed() const {
|
||||
return download_item_ == nullptr;
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
|
||||
download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated");
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
int64 DownloadItem::GetReceivedBytes() {
|
||||
return download_item_->GetReceivedBytes();
|
||||
}
|
||||
|
||||
int64 DownloadItem::GetTotalBytes() {
|
||||
return download_item_->GetTotalBytes();
|
||||
}
|
||||
|
||||
const GURL& DownloadItem::GetUrl() {
|
||||
return download_item_->GetURL();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetMimeType() {
|
||||
return download_item_->GetMimeType();
|
||||
}
|
||||
|
||||
bool DownloadItem::HasUserGesture() {
|
||||
return download_item_->HasUserGesture();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetFilename() {
|
||||
return base::UTF16ToUTF8(net::GenerateFileName(GetUrl(),
|
||||
GetContentDisposition(),
|
||||
std::string(),
|
||||
download_item_->GetSuggestedFilename(),
|
||||
GetMimeType(),
|
||||
std::string()).LossyDisplayName());
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetContentDisposition() {
|
||||
return download_item_->GetContentDisposition();
|
||||
}
|
||||
|
||||
void DownloadItem::SetSavePath(const base::FilePath& path) {
|
||||
download_item_->SetUserData(UserDataKey(), new SavePathData(path));
|
||||
}
|
||||
|
||||
void DownloadItem::Pause() {
|
||||
download_item_->Pause();
|
||||
}
|
||||
|
||||
void DownloadItem::Resume() {
|
||||
download_item_->Resume();
|
||||
}
|
||||
|
||||
void DownloadItem::Cancel() {
|
||||
download_item_->Cancel(true);
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("pause", &DownloadItem::Pause)
|
||||
.SetMethod("resume", &DownloadItem::Resume)
|
||||
.SetMethod("cancel", &DownloadItem::Cancel)
|
||||
.SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes)
|
||||
.SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes)
|
||||
.SetMethod("getUrl", &DownloadItem::GetUrl)
|
||||
.SetMethod("getMimeType", &DownloadItem::GetMimeType)
|
||||
.SetMethod("hasUserGesture", &DownloadItem::HasUserGesture)
|
||||
.SetMethod("getFilename", &DownloadItem::GetFilename)
|
||||
.SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition)
|
||||
.SetMethod("setSavePath", &DownloadItem::SetSavePath);
|
||||
}
|
||||
|
||||
void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) {
|
||||
g_wrap_download_item = callback;
|
||||
}
|
||||
|
||||
void ClearWrapDownloadItem() {
|
||||
g_wrap_download_item.Reset();
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<DownloadItem> DownloadItem::Create(
|
||||
v8::Isolate* isolate, content::DownloadItem* item) {
|
||||
auto handle = mate::CreateHandle(isolate, new DownloadItem(item));
|
||||
g_wrap_download_item.Run(handle.ToV8());
|
||||
g_download_item_objects[item->GetId()] = make_linked_ptr(
|
||||
new v8::Global<v8::Value>(isolate, handle.ToV8()));
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
void* DownloadItem::UserDataKey() {
|
||||
return &kDownloadItemSavePathKey;
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("_setWrapDownloadItem", &atom::api::SetWrapDownloadItem);
|
||||
dict.SetMethod("_clearWrapDownloadItem", &atom::api::ClearWrapDownloadItem);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_download_item, Initialize);
|
||||
72
atom/browser/api/atom_api_download_item.h
Normal file
72
atom/browser/api/atom_api_download_item.h
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "content/public/browser/download_item.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class DownloadItem : public mate::EventEmitter,
|
||||
public content::DownloadItem::Observer {
|
||||
public:
|
||||
class SavePathData : public base::SupportsUserData::Data {
|
||||
public:
|
||||
explicit SavePathData(const base::FilePath& path);
|
||||
const base::FilePath& path();
|
||||
private:
|
||||
base::FilePath path_;
|
||||
};
|
||||
|
||||
static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
|
||||
content::DownloadItem* item);
|
||||
static void* UserDataKey();
|
||||
|
||||
protected:
|
||||
explicit DownloadItem(content::DownloadItem* download_item);
|
||||
~DownloadItem();
|
||||
|
||||
// Override content::DownloadItem::Observer methods
|
||||
void OnDownloadUpdated(content::DownloadItem* download) override;
|
||||
void OnDownloadDestroyed(content::DownloadItem* download) override;
|
||||
|
||||
void Pause();
|
||||
void Resume();
|
||||
void Cancel();
|
||||
int64 GetReceivedBytes();
|
||||
int64 GetTotalBytes();
|
||||
std::string GetMimeType();
|
||||
bool HasUserGesture();
|
||||
std::string GetFilename();
|
||||
std::string GetContentDisposition();
|
||||
const GURL& GetUrl();
|
||||
void SetSavePath(const base::FilePath& path);
|
||||
|
||||
private:
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
bool IsDestroyed() const override;
|
||||
|
||||
void Destroy();
|
||||
|
||||
content::DownloadItem* download_item_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DownloadItem);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
|
||||
@@ -107,6 +107,10 @@ void Menu::SetSublabel(int index, const base::string16& sublabel) {
|
||||
model_->SetSublabel(index, sublabel);
|
||||
}
|
||||
|
||||
void Menu::SetRole(int index, const base::string16& role) {
|
||||
model_->SetRole(index, role);
|
||||
}
|
||||
|
||||
void Menu::Clear() {
|
||||
model_->Clear();
|
||||
}
|
||||
@@ -154,6 +158,7 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("insertSubMenu", &Menu::InsertSubMenuAt)
|
||||
.SetMethod("setIcon", &Menu::SetIcon)
|
||||
.SetMethod("setSublabel", &Menu::SetSublabel)
|
||||
.SetMethod("setRole", &Menu::SetRole)
|
||||
.SetMethod("clear", &Menu::Clear)
|
||||
.SetMethod("getIndexOfCommandId", &Menu::GetIndexOfCommandId)
|
||||
.SetMethod("getItemCount", &Menu::GetItemCount)
|
||||
|
||||
@@ -73,6 +73,7 @@ class Menu : public mate::Wrappable,
|
||||
Menu* menu);
|
||||
void SetIcon(int index, const gfx::Image& image);
|
||||
void SetSublabel(int index, const base::string16& sublabel);
|
||||
void SetRole(int index, const base::string16& role);
|
||||
void Clear();
|
||||
int GetIndexOfCommandId(int command_id);
|
||||
int GetItemCount() const;
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
#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 {
|
||||
@@ -41,9 +40,9 @@ void PowerMonitor::OnResume() {
|
||||
// static
|
||||
v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
node::ThrowError(
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate,
|
||||
"Cannot initialize \"power-monitor\" module before app is ready");
|
||||
"Cannot initialize \"power-monitor\" module before app is ready")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "content/public/browser/power_save_blocker.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
|
||||
@@ -12,9 +12,8 @@
|
||||
#include "atom/browser/net/url_request_fetch_job.h"
|
||||
#include "atom/browser/net/url_request_string_job.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class Protocol : public mate::Wrappable {
|
||||
public:
|
||||
CustomProtocolHandler(
|
||||
v8::Isolate* isolate,
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context,
|
||||
net::URLRequestContextGetter* request_context,
|
||||
const Handler& handler)
|
||||
: isolate_(isolate),
|
||||
request_context_(request_context),
|
||||
@@ -83,7 +83,7 @@ class Protocol : public mate::Wrappable {
|
||||
|
||||
private:
|
||||
v8::Isolate* isolate_;
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_;
|
||||
net::URLRequestContextGetter* request_context_;
|
||||
Protocol::Handler handler_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler);
|
||||
@@ -172,7 +172,7 @@ class Protocol : public mate::Wrappable {
|
||||
// Convert error code to string.
|
||||
std::string ErrorCodeToString(ProtocolError error);
|
||||
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
|
||||
// Map that stores the original protocols of schemes.
|
||||
using OriginalProtocolsMap = base::ScopedPtrHashMap<
|
||||
|
||||
@@ -113,14 +113,16 @@ mate::ObjectTemplateBuilder Screen::GetObjectTemplateBuilder(
|
||||
// static
|
||||
v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
node::ThrowError(isolate,
|
||||
"Cannot initialize \"screen\" module before app is ready");
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate,
|
||||
"Cannot initialize \"screen\" module before app is ready")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
gfx::Screen* screen = gfx::Screen::GetNativeScreen();
|
||||
if (!screen) {
|
||||
node::ThrowError(isolate, "Failed to get screen information");
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate, "Failed to get screen information")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,19 @@
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/atom_api_cookies.h"
|
||||
#include "atom/browser/api/atom_api_download_item.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/prefs/pref_service.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "brightray/browser/net/devtools_network_conditions.h"
|
||||
#include "brightray/browser/net/devtools_network_controller.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
@@ -28,8 +33,6 @@
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
using content::StoragePartition;
|
||||
|
||||
@@ -109,6 +112,10 @@ namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
// The wrapSession funtion which is implemented in JavaScript
|
||||
using WrapSessionCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
WrapSessionCallback g_wrap_session;
|
||||
|
||||
class ResolveProxyHelper {
|
||||
public:
|
||||
ResolveProxyHelper(AtomBrowserContext* browser_context,
|
||||
@@ -215,13 +222,41 @@ void SetProxyInIO(net::URLRequestContextGetter* getter,
|
||||
Session::Session(AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context) {
|
||||
AttachAsUserData(browser_context);
|
||||
|
||||
// Observe DownloadManger to get download notifications.
|
||||
content::BrowserContext::GetDownloadManager(browser_context)->
|
||||
AddObserver(this);
|
||||
}
|
||||
|
||||
Session::~Session() {
|
||||
content::BrowserContext::GetDownloadManager(browser_context())->
|
||||
RemoveObserver(this);
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||
content::DownloadItem* item) {
|
||||
auto web_contents = item->GetWebContents();
|
||||
bool prevent_default = Emit(
|
||||
"will-download",
|
||||
DownloadItem::Create(isolate(), item),
|
||||
api::WebContents::CreateFrom(isolate(), web_contents));
|
||||
if (prevent_default) {
|
||||
item->Cancel(true);
|
||||
item->Remove();
|
||||
}
|
||||
}
|
||||
|
||||
bool Session::IsDestroyed() const {
|
||||
return !browser_context_;
|
||||
}
|
||||
|
||||
void Session::Destroy() {
|
||||
browser_context_ = nullptr;
|
||||
}
|
||||
|
||||
void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
|
||||
new ResolveProxyHelper(browser_context_, url, callback);
|
||||
new ResolveProxyHelper(browser_context(), url, callback);
|
||||
}
|
||||
|
||||
void Session::ClearCache(const net::CompletionCallback& callback) {
|
||||
@@ -242,7 +277,7 @@ void Session::ClearStorageData(mate::Arguments* args) {
|
||||
}
|
||||
|
||||
auto storage_partition =
|
||||
content::BrowserContext::GetStoragePartition(browser_context_, nullptr);
|
||||
content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
|
||||
storage_partition->ClearData(
|
||||
options.storage_types, options.quota_types, options.origin,
|
||||
content::StoragePartition::OriginMatcherFunction(),
|
||||
@@ -261,9 +296,46 @@ void Session::SetDownloadPath(const base::FilePath& path) {
|
||||
prefs::kDownloadDefaultDirectory, path);
|
||||
}
|
||||
|
||||
void Session::EnableNetworkEmulation(const mate::Dictionary& options) {
|
||||
scoped_ptr<brightray::DevToolsNetworkConditions> conditions;
|
||||
bool offline = false;
|
||||
double latency, download_throughput, upload_throughput;
|
||||
if (options.Get("offline", &offline) && offline) {
|
||||
conditions.reset(new brightray::DevToolsNetworkConditions(offline));
|
||||
} else {
|
||||
options.Get("latency", &latency);
|
||||
options.Get("downloadThroughput", &download_throughput);
|
||||
options.Get("uploadThroughput", &upload_throughput);
|
||||
conditions.reset(
|
||||
new brightray::DevToolsNetworkConditions(false,
|
||||
latency,
|
||||
download_throughput,
|
||||
upload_throughput));
|
||||
}
|
||||
auto controller = browser_context_->GetDevToolsNetworkController();
|
||||
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&brightray::DevToolsNetworkController::SetNetworkState,
|
||||
base::Unretained(controller),
|
||||
std::string(),
|
||||
base::Passed(&conditions)));
|
||||
}
|
||||
|
||||
void Session::DisableNetworkEmulation() {
|
||||
scoped_ptr<brightray::DevToolsNetworkConditions> conditions(
|
||||
new brightray::DevToolsNetworkConditions(false));
|
||||
auto controller = browser_context_->GetDevToolsNetworkController();
|
||||
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&brightray::DevToolsNetworkController::SetNetworkState,
|
||||
base::Unretained(controller),
|
||||
std::string(),
|
||||
base::Passed(&conditions)));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
|
||||
if (cookies_.IsEmpty()) {
|
||||
auto handle = atom::api::Cookies::Create(isolate, browser_context_);
|
||||
auto handle = atom::api::Cookies::Create(isolate, browser_context());
|
||||
cookies_.Reset(isolate, handle.ToV8());
|
||||
}
|
||||
return v8::Local<v8::Value>::New(isolate, cookies_);
|
||||
@@ -277,20 +349,54 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder(
|
||||
.SetMethod("clearStorageData", &Session::ClearStorageData)
|
||||
.SetMethod("setProxy", &Session::SetProxy)
|
||||
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
|
||||
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
|
||||
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
|
||||
.SetProperty("cookies", &Session::Cookies);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Session> Session::CreateFrom(
|
||||
v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context) {
|
||||
auto existing = TrackableObject::FromWrappedClass(isolate, browser_context);
|
||||
if (existing)
|
||||
return mate::CreateHandle(isolate, static_cast<Session*>(existing));
|
||||
|
||||
return mate::CreateHandle(isolate, new Session(browser_context));
|
||||
auto handle = mate::CreateHandle(isolate, new Session(browser_context));
|
||||
g_wrap_session.Run(handle.ToV8());
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Session> Session::FromPartition(
|
||||
v8::Isolate* isolate, const std::string& partition, bool in_memory) {
|
||||
auto browser_context = brightray::BrowserContext::From(partition, in_memory);
|
||||
return CreateFrom(isolate,
|
||||
static_cast<AtomBrowserContext*>(browser_context.get()));
|
||||
}
|
||||
|
||||
void SetWrapSession(const WrapSessionCallback& callback) {
|
||||
g_wrap_session = callback;
|
||||
}
|
||||
|
||||
void ClearWrapSession() {
|
||||
g_wrap_session.Reset();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("fromPartition", &atom::api::Session::FromPartition);
|
||||
dict.SetMethod("_setWrapSession", &atom::api::SetWrapSession);
|
||||
dict.SetMethod("_clearWrapSession", &atom::api::ClearWrapSession);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_session, Initialize)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
|
||||
@@ -19,6 +20,7 @@ class FilePath;
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
@@ -27,7 +29,8 @@ class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class Session: public mate::TrackableObject<Session> {
|
||||
class Session: public mate::TrackableObject<Session>,
|
||||
public content::DownloadManager::Observer {
|
||||
public:
|
||||
using ResolveProxyCallback = base::Callback<void(std::string)>;
|
||||
|
||||
@@ -35,27 +38,42 @@ class Session: public mate::TrackableObject<Session> {
|
||||
static mate::Handle<Session> CreateFrom(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
|
||||
AtomBrowserContext* browser_context() const { return browser_context_; }
|
||||
// Gets the Session of |partition| and |in_memory|.
|
||||
static mate::Handle<Session> FromPartition(
|
||||
v8::Isolate* isolate, const std::string& partition, bool in_memory);
|
||||
|
||||
AtomBrowserContext* browser_context() const { return browser_context_.get(); }
|
||||
|
||||
protected:
|
||||
explicit Session(AtomBrowserContext* browser_context);
|
||||
~Session();
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
// content::DownloadManager::Observer:
|
||||
void OnDownloadCreated(content::DownloadManager* manager,
|
||||
content::DownloadItem* item) override;
|
||||
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
bool IsDestroyed() const override;
|
||||
|
||||
private:
|
||||
// mate::TrackableObject:
|
||||
void Destroy() override;
|
||||
|
||||
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
|
||||
void ClearCache(const net::CompletionCallback& callback);
|
||||
void ClearStorageData(mate::Arguments* args);
|
||||
void SetProxy(const std::string& proxy, const base::Closure& callback);
|
||||
void SetDownloadPath(const base::FilePath& path);
|
||||
void EnableNetworkEmulation(const mate::Dictionary& options);
|
||||
void DisableNetworkEmulation();
|
||||
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
||||
|
||||
// Cached object for cookies API.
|
||||
v8::Global<v8::Value> cookies_;
|
||||
|
||||
AtomBrowserContext* browser_context_; // weak ref
|
||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Session);
|
||||
};
|
||||
|
||||
@@ -12,13 +12,12 @@
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/events/event_constants.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
@@ -35,7 +34,8 @@ Tray::~Tray() {
|
||||
// static
|
||||
mate::Wrappable* Tray::New(v8::Isolate* isolate, const gfx::Image& image) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
node::ThrowError(isolate, "Cannot create Tray before app is ready");
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate, "Cannot create Tray before app is ready")));
|
||||
return nullptr;
|
||||
}
|
||||
return new Tray(image);
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
#include <set>
|
||||
|
||||
#include "atom/browser/api/atom_api_session.h"
|
||||
#include "atom/browser/api/atom_api_window.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
#include "atom/browser/web_view_guest_delegate.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
#include "atom/common/native_mate_converters/blink_converter.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"
|
||||
@@ -24,15 +27,19 @@
|
||||
#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"
|
||||
#include "chrome/browser/printing/print_view_manager_basic.h"
|
||||
#include "chrome/browser/printing/print_preview_message_handler.h"
|
||||
#include "content/common/view_messages.h"
|
||||
#include "content/public/browser/favicon_status.h"
|
||||
#include "content/public/browser/native_web_keyboard_event.h"
|
||||
#include "content/public/browser/navigation_details.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
#include "content/public/browser/plugin_service.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "content/public/browser/resource_request_details.h"
|
||||
#include "content/public/browser/service_worker_context.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
@@ -43,6 +50,7 @@
|
||||
#include "net/http/http_response_headers.h"
|
||||
#include "net/url_request/static_http_user_agent_settings.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "third_party/WebKit/public/web/WebInputEvent.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
@@ -114,6 +122,33 @@ struct Converter<WindowOpenDisposition> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<net::HttpResponseHeaders*> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
net::HttpResponseHeaders* headers) {
|
||||
base::DictionaryValue response_headers;
|
||||
if (headers) {
|
||||
void* iter = nullptr;
|
||||
std::string key;
|
||||
std::string value;
|
||||
while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
|
||||
key = base::StringToLowerASCII(key);
|
||||
value = base::StringToLowerASCII(value);
|
||||
if (response_headers.HasKey(key)) {
|
||||
base::ListValue* values = nullptr;
|
||||
if (response_headers.GetList(key, &values))
|
||||
values->AppendString(value);
|
||||
} else {
|
||||
scoped_ptr<base::ListValue> values(new base::ListValue());
|
||||
values->AppendString(value);
|
||||
response_headers.Set(key, values.Pass());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ConvertToV8(isolate, response_headers);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
|
||||
@@ -125,7 +160,7 @@ namespace {
|
||||
|
||||
v8::Persistent<v8::ObjectTemplate> template_;
|
||||
|
||||
// The wrapWebContents funtion which is implemented in JavaScript
|
||||
// The wrapWebContents function which is implemented in JavaScript
|
||||
using WrapWebContentsCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
WrapWebContentsCallback g_wrap_web_contents;
|
||||
|
||||
@@ -153,23 +188,41 @@ WebContents::WebContents(content::WebContents* web_contents)
|
||||
web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent());
|
||||
}
|
||||
|
||||
WebContents::WebContents(const mate::Dictionary& options) {
|
||||
WebContents::WebContents(v8::Isolate* isolate,
|
||||
const mate::Dictionary& options) {
|
||||
// Whether it is a guest WebContents.
|
||||
bool is_guest = false;
|
||||
options.Get("isGuest", &is_guest);
|
||||
|
||||
type_ = is_guest ? WEB_VIEW : BROWSER_WINDOW;
|
||||
|
||||
auto browser_context = AtomBrowserMainParts::Get()->browser_context();
|
||||
// Obtain the session.
|
||||
std::string partition;
|
||||
mate::Handle<api::Session> session;
|
||||
if (options.Get("session", &session)) {
|
||||
} else if (options.Get("partition", &partition) && !partition.empty()) {
|
||||
bool in_memory = true;
|
||||
if (base::StartsWith(partition, "persist:", base::CompareCase::SENSITIVE)) {
|
||||
in_memory = false;
|
||||
partition = partition.substr(8);
|
||||
}
|
||||
session = Session::FromPartition(isolate, partition, in_memory);
|
||||
} else {
|
||||
// Use the default session if not specified.
|
||||
session = Session::FromPartition(isolate, "", false);
|
||||
}
|
||||
session_.Reset(isolate, session.ToV8());
|
||||
|
||||
content::WebContents* web_contents;
|
||||
if (is_guest) {
|
||||
content::SiteInstance* site_instance = content::SiteInstance::CreateForURL(
|
||||
browser_context, GURL("chrome-guest://fake-host"));
|
||||
content::WebContents::CreateParams params(browser_context, site_instance);
|
||||
session->browser_context(), GURL("chrome-guest://fake-host"));
|
||||
content::WebContents::CreateParams params(
|
||||
session->browser_context(), site_instance);
|
||||
guest_delegate_.reset(new WebViewGuestDelegate);
|
||||
params.guest_delegate = guest_delegate_.get();
|
||||
web_contents = content::WebContents::Create(params);
|
||||
} else {
|
||||
content::WebContents::CreateParams params(browser_context);
|
||||
content::WebContents::CreateParams params(session->browser_context());
|
||||
web_contents = content::WebContents::Create(params);
|
||||
}
|
||||
|
||||
@@ -177,6 +230,13 @@ WebContents::WebContents(const mate::Dictionary& options) {
|
||||
AttachAsUserData(web_contents);
|
||||
InitWithWebContents(web_contents);
|
||||
|
||||
managed_web_contents()->GetView()->SetDelegate(this);
|
||||
|
||||
// Save the preferences in C++.
|
||||
base::DictionaryValue web_preferences;
|
||||
mate::ConvertFromV8(isolate, options.GetHandle(), &web_preferences);
|
||||
new WebContentsPreferences(web_contents, &web_preferences);
|
||||
|
||||
web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent());
|
||||
|
||||
if (is_guest) {
|
||||
@@ -217,7 +277,7 @@ bool WebContents::ShouldCreateWebContents(
|
||||
int route_id,
|
||||
int main_frame_route_id,
|
||||
WindowContainerType window_container_type,
|
||||
const base::string16& frame_name,
|
||||
const std::string& frame_name,
|
||||
const GURL& target_url,
|
||||
const std::string& partition_id,
|
||||
content::SessionStorageNamespace* session_storage_namespace) {
|
||||
@@ -362,15 +422,17 @@ void WebContents::DidFailProvisionalLoad(
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& validated_url,
|
||||
int error_code,
|
||||
const base::string16& error_description) {
|
||||
Emit("did-fail-load", error_code, error_description);
|
||||
const base::string16& error_description,
|
||||
bool was_ignored_by_handler) {
|
||||
Emit("did-fail-load", error_code, error_description, validated_url);
|
||||
}
|
||||
|
||||
void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
|
||||
const GURL& validated_url,
|
||||
int error_code,
|
||||
const base::string16& error_description) {
|
||||
Emit("did-fail-load", error_code, error_description);
|
||||
const base::string16& error_description,
|
||||
bool was_ignored_by_handler) {
|
||||
Emit("did-fail-load", error_code, error_description, validated_url);
|
||||
}
|
||||
|
||||
void WebContents::DidStartLoading() {
|
||||
@@ -383,30 +445,6 @@ void WebContents::DidStopLoading() {
|
||||
|
||||
void WebContents::DidGetResourceResponseStart(
|
||||
const content::ResourceRequestDetails& details) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
base::DictionaryValue response_headers;
|
||||
|
||||
net::HttpResponseHeaders* headers = details.headers.get();
|
||||
if (!headers)
|
||||
return;
|
||||
void* iter = nullptr;
|
||||
std::string key;
|
||||
std::string value;
|
||||
while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
|
||||
key = base::StringToLowerASCII(key);
|
||||
value = base::StringToLowerASCII(value);
|
||||
if (response_headers.HasKey(key)) {
|
||||
base::ListValue* values = nullptr;
|
||||
if (response_headers.GetList(key, &values))
|
||||
values->AppendString(value);
|
||||
} else {
|
||||
scoped_ptr<base::ListValue> values(new base::ListValue());
|
||||
values->AppendString(value);
|
||||
response_headers.Set(key, values.Pass());
|
||||
}
|
||||
}
|
||||
|
||||
Emit("did-get-response-details",
|
||||
details.socket_address.IsEmpty(),
|
||||
details.url,
|
||||
@@ -414,7 +452,7 @@ void WebContents::DidGetResourceResponseStart(
|
||||
details.http_response_code,
|
||||
details.method,
|
||||
details.referrer,
|
||||
response_headers);
|
||||
details.headers.get());
|
||||
}
|
||||
|
||||
void WebContents::DidGetRedirectForResourceRequest(
|
||||
@@ -423,7 +461,11 @@ void WebContents::DidGetRedirectForResourceRequest(
|
||||
Emit("did-get-redirect-request",
|
||||
details.url,
|
||||
details.new_url,
|
||||
(details.resource_type == content::RESOURCE_TYPE_MAIN_FRAME));
|
||||
(details.resource_type == content::RESOURCE_TYPE_MAIN_FRAME),
|
||||
details.http_response_code,
|
||||
details.method,
|
||||
details.referrer,
|
||||
details.headers.get());
|
||||
}
|
||||
|
||||
void WebContents::DidNavigateMainFrame(
|
||||
@@ -453,6 +495,33 @@ void WebContents::DidUpdateFaviconURL(
|
||||
Emit("page-favicon-updated", unique_urls);
|
||||
}
|
||||
|
||||
void WebContents::DevToolsFocused() {
|
||||
Emit("devtools-focused");
|
||||
}
|
||||
|
||||
void WebContents::DevToolsOpened() {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto handle = WebContents::CreateFrom(
|
||||
isolate(), managed_web_contents()->GetDevToolsWebContents());
|
||||
devtools_web_contents_.Reset(isolate(), handle.ToV8());
|
||||
|
||||
// Inherit owner window in devtools.
|
||||
if (owner_window())
|
||||
handle->SetOwnerWindow(managed_web_contents()->GetDevToolsWebContents(),
|
||||
owner_window());
|
||||
|
||||
Emit("devtools-opened");
|
||||
}
|
||||
|
||||
void WebContents::DevToolsClosed() {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
devtools_web_contents_.Reset();
|
||||
|
||||
Emit("devtools-closed");
|
||||
}
|
||||
|
||||
bool WebContents::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(WebContents, message)
|
||||
@@ -479,6 +548,7 @@ void WebContents::NavigationEntryCommitted(
|
||||
}
|
||||
|
||||
void WebContents::Destroy() {
|
||||
session_.Reset();
|
||||
if (type_ == WEB_VIEW && managed_web_contents()) {
|
||||
// When force destroying the "destroyed" event is not emitted.
|
||||
WebContentsDestroyed();
|
||||
@@ -520,6 +590,10 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
|
||||
web_contents()->GetController().LoadURLWithParams(params);
|
||||
}
|
||||
|
||||
GURL WebContents::GetURL() const {
|
||||
return web_contents()->GetURL();
|
||||
}
|
||||
|
||||
base::string16 WebContents::GetTitle() const {
|
||||
return web_contents()->GetTitle();
|
||||
}
|
||||
@@ -609,6 +683,21 @@ bool WebContents::IsDevToolsOpened() {
|
||||
return managed_web_contents()->IsDevToolsViewShowing();
|
||||
}
|
||||
|
||||
void WebContents::EnableDeviceEmulation(
|
||||
const blink::WebDeviceEmulationParams& params) {
|
||||
if (type_ == REMOTE)
|
||||
return;
|
||||
|
||||
Send(new ViewMsg_EnableDeviceEmulation(routing_id(), params));
|
||||
}
|
||||
|
||||
void WebContents::DisableDeviceEmulation() {
|
||||
if (type_ == REMOTE)
|
||||
return;
|
||||
|
||||
Send(new ViewMsg_DisableDeviceEmulation(routing_id()));
|
||||
}
|
||||
|
||||
void WebContents::ToggleDevTools() {
|
||||
if (IsDevToolsOpened())
|
||||
CloseDevTools();
|
||||
@@ -640,14 +729,6 @@ void WebContents::InspectServiceWorker() {
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
|
||||
if (session_.IsEmpty()) {
|
||||
auto handle = Session::CreateFrom(isolate, GetBrowserContext());
|
||||
session_.Reset(isolate, handle.ToV8());
|
||||
}
|
||||
return v8::Local<v8::Value>::New(isolate, session_);
|
||||
}
|
||||
|
||||
void WebContents::HasServiceWorker(
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
auto context = GetServiceWorkerContext(web_contents());
|
||||
@@ -694,17 +775,19 @@ void WebContents::PrintToPDF(const base::DictionaryValue& setting,
|
||||
PrintToPDF(setting, callback);
|
||||
}
|
||||
|
||||
void WebContents::AddWorkSpace(const base::FilePath& path) {
|
||||
void WebContents::AddWorkSpace(mate::Arguments* args,
|
||||
const base::FilePath& path) {
|
||||
if (path.empty()) {
|
||||
node::ThrowError(isolate(), "path cannot be empty");
|
||||
args->ThrowError("path cannot be empty");
|
||||
return;
|
||||
}
|
||||
DevToolsAddFileSystem(path);
|
||||
}
|
||||
|
||||
void WebContents::RemoveWorkSpace(const base::FilePath& path) {
|
||||
void WebContents::RemoveWorkSpace(mate::Arguments* args,
|
||||
const base::FilePath& path) {
|
||||
if (path.empty()) {
|
||||
node::ThrowError(isolate(), "path cannot be empty");
|
||||
args->ThrowError("path cannot be empty");
|
||||
return;
|
||||
}
|
||||
DevToolsRemoveFileSystem(path);
|
||||
@@ -767,6 +850,56 @@ bool WebContents::SendIPCMessage(const base::string16& channel,
|
||||
return Send(new AtomViewMsg_Message(routing_id(), channel, args));
|
||||
}
|
||||
|
||||
void WebContents::SendInputEvent(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> input_event) {
|
||||
const auto view = web_contents()->GetRenderWidgetHostView();
|
||||
if (!view)
|
||||
return;
|
||||
const auto host = view->GetRenderWidgetHost();
|
||||
if (!host)
|
||||
return;
|
||||
|
||||
int type = mate::GetWebInputEventType(isolate, input_event);
|
||||
if (blink::WebInputEvent::isMouseEventType(type)) {
|
||||
blink::WebMouseEvent mouse_event;
|
||||
if (mate::ConvertFromV8(isolate, input_event, &mouse_event)) {
|
||||
host->ForwardMouseEvent(mouse_event);
|
||||
return;
|
||||
}
|
||||
} else if (blink::WebInputEvent::isKeyboardEventType(type)) {
|
||||
content::NativeWebKeyboardEvent keyboard_event;;
|
||||
if (mate::ConvertFromV8(isolate, input_event, &keyboard_event)) {
|
||||
host->ForwardKeyboardEvent(keyboard_event);
|
||||
return;
|
||||
}
|
||||
} else if (type == blink::WebInputEvent::MouseWheel) {
|
||||
blink::WebMouseWheelEvent mouse_wheel_event;
|
||||
if (mate::ConvertFromV8(isolate, input_event, &mouse_wheel_event)) {
|
||||
host->ForwardWheelEvent(mouse_wheel_event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate, "Invalid event object")));
|
||||
}
|
||||
|
||||
void WebContents::BeginFrameSubscription(
|
||||
const FrameSubscriber::FrameCaptureCallback& callback) {
|
||||
const auto view = web_contents()->GetRenderWidgetHostView();
|
||||
if (view) {
|
||||
scoped_ptr<FrameSubscriber> frame_subscriber(new FrameSubscriber(
|
||||
isolate(), view->GetVisibleViewportSize(), callback));
|
||||
view->BeginFrameSubscription(frame_subscriber.Pass());
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::EndFrameSubscription() {
|
||||
const auto view = web_contents()->GetRenderWidgetHostView();
|
||||
if (view)
|
||||
view->EndFrameSubscription();
|
||||
}
|
||||
|
||||
void WebContents::SetSize(const SetSizeParams& params) {
|
||||
if (guest_delegate_)
|
||||
guest_delegate_->SetSize(params);
|
||||
@@ -781,6 +914,30 @@ bool WebContents::IsGuest() const {
|
||||
return type_ == WEB_VIEW;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::GetWebPreferences(v8::Isolate* isolate) {
|
||||
WebContentsPreferences* web_preferences =
|
||||
WebContentsPreferences::FromWebContents(web_contents());
|
||||
return mate::ConvertToV8(isolate, *web_preferences->web_preferences());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::GetOwnerBrowserWindow() {
|
||||
if (owner_window())
|
||||
return Window::From(isolate(), owner_window());
|
||||
else
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
|
||||
return v8::Local<v8::Value>::New(isolate, session_);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::DevToolsWebContents(v8::Isolate* isolate) {
|
||||
if (devtools_web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
else
|
||||
return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
if (template_.IsEmpty())
|
||||
@@ -790,6 +947,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
.SetMethod("getId", &WebContents::GetID)
|
||||
.SetMethod("equal", &WebContents::Equal)
|
||||
.SetMethod("_loadUrl", &WebContents::LoadURL)
|
||||
.SetMethod("_getUrl", &WebContents::GetURL)
|
||||
.SetMethod("getTitle", &WebContents::GetTitle)
|
||||
.SetMethod("isLoading", &WebContents::IsLoading)
|
||||
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
|
||||
@@ -806,6 +964,10 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
.SetMethod("openDevTools", &WebContents::OpenDevTools)
|
||||
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
|
||||
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
|
||||
.SetMethod("enableDeviceEmulation",
|
||||
&WebContents::EnableDeviceEmulation)
|
||||
.SetMethod("disableDeviceEmulation",
|
||||
&WebContents::DisableDeviceEmulation)
|
||||
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
|
||||
.SetMethod("inspectElement", &WebContents::InspectElement)
|
||||
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
|
||||
@@ -824,9 +986,15 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
.SetMethod("focus", &WebContents::Focus)
|
||||
.SetMethod("tabTraverse", &WebContents::TabTraverse)
|
||||
.SetMethod("_send", &WebContents::SendIPCMessage, true)
|
||||
.SetMethod("sendInputEvent", &WebContents::SendInputEvent)
|
||||
.SetMethod("beginFrameSubscription",
|
||||
&WebContents::BeginFrameSubscription)
|
||||
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
|
||||
.SetMethod("setSize", &WebContents::SetSize)
|
||||
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
|
||||
.SetMethod("isGuest", &WebContents::IsGuest)
|
||||
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
|
||||
.SetMethod("unregisterServiceWorker",
|
||||
&WebContents::UnregisterServiceWorker)
|
||||
@@ -835,7 +1003,9 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
.SetMethod("_printToPDF", &WebContents::PrintToPDF)
|
||||
.SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
|
||||
.SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
|
||||
.SetProperty("session", &WebContents::Session)
|
||||
.SetProperty("session", &WebContents::Session, true)
|
||||
.SetProperty("devToolsWebContents",
|
||||
&WebContents::DevToolsWebContents, true)
|
||||
.Build());
|
||||
|
||||
return mate::ObjectTemplateBuilder(
|
||||
@@ -880,7 +1050,7 @@ mate::Handle<WebContents> WebContents::CreateFrom(
|
||||
// static
|
||||
mate::Handle<WebContents> WebContents::Create(
|
||||
v8::Isolate* isolate, const mate::Dictionary& options) {
|
||||
auto handle = mate::CreateHandle(isolate, new WebContents(options));
|
||||
auto handle = mate::CreateHandle(isolate, new WebContents(isolate, options));
|
||||
g_wrap_web_contents.Run(handle.ToV8());
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -8,13 +8,18 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/frame_subscriber.h"
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/common_web_contents_delegate.h"
|
||||
#include "content/public/common/favicon_url.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/common/favicon_url.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
namespace blink {
|
||||
struct WebDeviceEmulationParams;
|
||||
}
|
||||
|
||||
namespace brightray {
|
||||
class InspectableWebContents;
|
||||
}
|
||||
@@ -48,11 +53,14 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
static mate::Handle<WebContents> Create(
|
||||
v8::Isolate* isolate, const mate::Dictionary& options);
|
||||
|
||||
void Destroy();
|
||||
// mate::TrackableObject:
|
||||
void Destroy() override;
|
||||
|
||||
bool IsAlive() const;
|
||||
int GetID() const;
|
||||
bool Equal(const WebContents* web_contents) const;
|
||||
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
||||
GURL GetURL() const;
|
||||
base::string16 GetTitle() const;
|
||||
bool IsLoading() const;
|
||||
bool IsWaitingForResponse() const;
|
||||
@@ -71,9 +79,10 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void CloseDevTools();
|
||||
bool IsDevToolsOpened();
|
||||
void ToggleDevTools();
|
||||
void EnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
|
||||
void DisableDeviceEmulation();
|
||||
void InspectElement(int x, int y);
|
||||
void InspectServiceWorker();
|
||||
v8::Local<v8::Value> Session(v8::Isolate* isolate);
|
||||
void HasServiceWorker(const base::Callback<void(bool)>&);
|
||||
void UnregisterServiceWorker(const base::Callback<void(bool)>&);
|
||||
void SetAudioMuted(bool muted);
|
||||
@@ -85,8 +94,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
const PrintToPDFCallback& callback);
|
||||
|
||||
// DevTools workspace api.
|
||||
void AddWorkSpace(const base::FilePath& path);
|
||||
void RemoveWorkSpace(const base::FilePath& path);
|
||||
void AddWorkSpace(mate::Arguments* args, const base::FilePath& path);
|
||||
void RemoveWorkSpace(mate::Arguments* args, const base::FilePath& path);
|
||||
|
||||
// Editing commands.
|
||||
void Undo();
|
||||
@@ -105,18 +114,36 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void Focus();
|
||||
void TabTraverse(bool reverse);
|
||||
|
||||
// Sending messages to browser.
|
||||
// Send messages to browser.
|
||||
bool SendIPCMessage(const base::string16& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Send WebInputEvent to the page.
|
||||
void SendInputEvent(v8::Isolate* isolate, v8::Local<v8::Value> input_event);
|
||||
|
||||
// Subscribe to the frame updates.
|
||||
void BeginFrameSubscription(
|
||||
const FrameSubscriber::FrameCaptureCallback& callback);
|
||||
void EndFrameSubscription();
|
||||
|
||||
// Methods for creating <webview>.
|
||||
void SetSize(const SetSizeParams& params);
|
||||
void SetAllowTransparency(bool allow);
|
||||
bool IsGuest() const;
|
||||
|
||||
// Returns the web preferences of current WebContents.
|
||||
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);
|
||||
|
||||
// Returns the owner window.
|
||||
v8::Local<v8::Value> GetOwnerBrowserWindow();
|
||||
|
||||
// Properties.
|
||||
v8::Local<v8::Value> Session(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
||||
|
||||
protected:
|
||||
explicit WebContents(content::WebContents* web_contents);
|
||||
explicit WebContents(const mate::Dictionary& options);
|
||||
WebContents(v8::Isolate* isolate, const mate::Dictionary& options);
|
||||
~WebContents();
|
||||
|
||||
// mate::Wrappable:
|
||||
@@ -135,7 +162,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
int route_id,
|
||||
int main_frame_route_id,
|
||||
WindowContainerType window_container_type,
|
||||
const base::string16& frame_name,
|
||||
const std::string& frame_name,
|
||||
const GURL& target_url,
|
||||
const std::string& partition_id,
|
||||
content::SessionStorageNamespace* session_storage_namespace) override;
|
||||
@@ -170,11 +197,13 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void DidFailLoad(content::RenderFrameHost* render_frame_host,
|
||||
const GURL& validated_url,
|
||||
int error_code,
|
||||
const base::string16& error_description) override;
|
||||
const base::string16& error_description,
|
||||
bool was_ignored_by_handler) override;
|
||||
void DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host,
|
||||
const GURL& validated_url,
|
||||
int error_code,
|
||||
const base::string16& error_description) override;
|
||||
const base::string16& error_description,
|
||||
bool was_ignored_by_handler) override;
|
||||
void DidStartLoading() override;
|
||||
void DidStopLoading() override;
|
||||
void DidGetResourceResponseStart(
|
||||
@@ -195,6 +224,11 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void PluginCrashed(const base::FilePath& plugin_path,
|
||||
base::ProcessId plugin_pid) override;
|
||||
|
||||
// brightray::InspectableWebContentsViewDelegate:
|
||||
void DevToolsFocused() override;
|
||||
void DevToolsOpened() override;
|
||||
void DevToolsClosed() override;
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
BROWSER_WINDOW, // Used by BrowserWindow.
|
||||
@@ -214,6 +248,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
IPC::Message* message);
|
||||
|
||||
v8::Global<v8::Value> session_;
|
||||
v8::Global<v8::Value> devtools_web_contents_;
|
||||
|
||||
scoped_ptr<WebViewGuestDelegate> guest_delegate_;
|
||||
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "net/base/filename_util.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
using atom::WebContentsPreferences;
|
||||
|
||||
namespace mate {
|
||||
|
||||
@@ -25,28 +26,6 @@ struct Converter<content::WebContents*> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<atom::WebViewManager::WebViewInfo> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
atom::WebViewManager::WebViewInfo* out) {
|
||||
Dictionary options;
|
||||
if (!ConvertFromV8(isolate, val, &options))
|
||||
return false;
|
||||
|
||||
GURL preload_url;
|
||||
if (!options.Get("preloadUrl", &preload_url))
|
||||
return false;
|
||||
|
||||
if (!preload_url.is_empty() &&
|
||||
!net::FileURLToFilePath(preload_url, &(out->preload_script)))
|
||||
return false;
|
||||
|
||||
return options.Get("nodeIntegration", &(out->node_integration)) &&
|
||||
options.Get("plugins", &(out->plugins)) &&
|
||||
options.Get("disableWebSecurity", &(out->disable_web_security));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace {
|
||||
@@ -65,14 +44,13 @@ void AddGuest(int guest_instance_id,
|
||||
int element_instance_id,
|
||||
content::WebContents* embedder,
|
||||
content::WebContents* guest_web_contents,
|
||||
atom::WebViewManager::WebViewInfo info) {
|
||||
const base::DictionaryValue& options) {
|
||||
auto manager = GetWebViewManager(embedder);
|
||||
if (manager) {
|
||||
info.guest_instance_id = guest_instance_id;
|
||||
info.embedder = embedder;
|
||||
if (manager)
|
||||
manager->AddGuest(guest_instance_id, element_instance_id, embedder,
|
||||
guest_web_contents, info);
|
||||
}
|
||||
guest_web_contents);
|
||||
|
||||
WebContentsPreferences::FromWebContents(guest_web_contents)->Merge(options);
|
||||
}
|
||||
|
||||
void RemoveGuest(content::WebContents* embedder, int guest_instance_id) {
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#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 "content/public/browser/render_process_host.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
@@ -23,8 +25,6 @@
|
||||
#include "atom/browser/ui/win/taskbar_host.h"
|
||||
#endif
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
namespace mate {
|
||||
|
||||
@@ -64,18 +64,35 @@ void OnCapturePageDone(
|
||||
|
||||
|
||||
Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
|
||||
// Use options['web-preferences'] to create WebContents.
|
||||
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
|
||||
options.Get(switches::kWebPreferences, &web_preferences);
|
||||
|
||||
// Be compatible with old options which are now in web_preferences.
|
||||
v8::Local<v8::Value> value;
|
||||
if (options.Get(switches::kNodeIntegration, &value))
|
||||
web_preferences.Set(switches::kNodeIntegration, value);
|
||||
if (options.Get(switches::kPreloadScript, &value))
|
||||
web_preferences.Set(switches::kPreloadScript, value);
|
||||
if (options.Get(switches::kZoomFactor, &value))
|
||||
web_preferences.Set(switches::kZoomFactor, value);
|
||||
|
||||
// Creates the WebContents used by BrowserWindow.
|
||||
mate::Dictionary web_contents_options(isolate, v8::Object::New(isolate));
|
||||
auto web_contents = WebContents::Create(isolate, web_contents_options);
|
||||
auto web_contents = WebContents::Create(isolate, web_preferences);
|
||||
web_contents_.Reset(isolate, web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
|
||||
// Keep a copy of the options for later use.
|
||||
mate::Dictionary(isolate, web_contents->GetWrapper(isolate)).Set(
|
||||
"browserWindowOptions", options);
|
||||
|
||||
// Creates BrowserWindow.
|
||||
window_.reset(NativeWindow::Create(web_contents->managed_web_contents(),
|
||||
options));
|
||||
web_contents->SetOwnerWindow(window_.get());
|
||||
window_->InitFromOptions(options);
|
||||
window_->AddObserver(this);
|
||||
AttachAsUserData(window_.get());
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
@@ -103,6 +120,9 @@ void Window::OnWindowClosed() {
|
||||
window_->RemoveObserver(this);
|
||||
|
||||
Emit("closed");
|
||||
|
||||
// Clean up the resources after window has been closed.
|
||||
base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release());
|
||||
}
|
||||
|
||||
void Window::OnWindowBlur() {
|
||||
@@ -165,28 +185,6 @@ void Window::OnRendererResponsive() {
|
||||
Emit("responsive");
|
||||
}
|
||||
|
||||
void Window::OnDevToolsFocus() {
|
||||
Emit("devtools-focused");
|
||||
}
|
||||
|
||||
void Window::OnDevToolsOpened() {
|
||||
Emit("devtools-opened");
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto handle = WebContents::CreateFrom(
|
||||
isolate(), api_web_contents_->GetDevToolsWebContents());
|
||||
devtools_web_contents_.Reset(isolate(), handle.ToV8());
|
||||
}
|
||||
|
||||
void Window::OnDevToolsClosed() {
|
||||
Emit("devtools-closed");
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
devtools_web_contents_.Reset();
|
||||
}
|
||||
|
||||
void Window::OnExecuteWindowsCommand(const std::string& command_name) {
|
||||
Emit("app-command", command_name);
|
||||
}
|
||||
@@ -195,8 +193,8 @@ void Window::OnExecuteWindowsCommand(const std::string& command_name) {
|
||||
mate::Wrappable* Window::New(v8::Isolate* isolate,
|
||||
const mate::Dictionary& options) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
node::ThrowError(isolate,
|
||||
"Cannot create BrowserWindow before app is ready");
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate, "Cannot create BrowserWindow before app is ready")));
|
||||
return nullptr;
|
||||
}
|
||||
return new Window(isolate, options);
|
||||
@@ -207,7 +205,8 @@ bool Window::IsDestroyed() const {
|
||||
}
|
||||
|
||||
void Window::Destroy() {
|
||||
window_->CloseContents(nullptr);
|
||||
if (window_)
|
||||
window_->CloseContents(nullptr);
|
||||
}
|
||||
|
||||
void Window::Close() {
|
||||
@@ -398,6 +397,10 @@ bool Window::IsWebViewFocused() {
|
||||
return window_->IsWebViewFocused();
|
||||
}
|
||||
|
||||
bool Window::IsDevToolsFocused() {
|
||||
return window_->IsDevToolsFocused();
|
||||
}
|
||||
|
||||
void Window::SetRepresentedFilename(const std::string& filename) {
|
||||
window_->SetRepresentedFilename(filename);
|
||||
}
|
||||
@@ -516,13 +519,6 @@ v8::Local<v8::Value> Window::WebContents(v8::Isolate* isolate) {
|
||||
return v8::Local<v8::Value>::New(isolate, web_contents_);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Window::DevToolsWebContents(v8::Isolate* isolate) {
|
||||
if (devtools_web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
else
|
||||
return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
|
||||
}
|
||||
|
||||
// static
|
||||
void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype) {
|
||||
@@ -575,6 +571,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("focusOnWebView", &Window::FocusOnWebView)
|
||||
.SetMethod("blurWebView", &Window::BlurWebView)
|
||||
.SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
|
||||
.SetMethod("isDevToolsFocused", &Window::IsDevToolsFocused)
|
||||
.SetMethod("capturePage", &Window::CapturePage)
|
||||
.SetMethod("setProgressBar", &Window::SetProgressBar)
|
||||
.SetMethod("setOverlayIcon", &Window::SetOverlayIcon)
|
||||
@@ -593,8 +590,17 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
&Window::ShowDefinitionForSelection)
|
||||
#endif
|
||||
.SetProperty("id", &Window::ID, true)
|
||||
.SetProperty("webContents", &Window::WebContents, true)
|
||||
.SetProperty("devToolsWebContents", &Window::DevToolsWebContents, true);
|
||||
.SetProperty("webContents", &Window::WebContents, true);
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> Window::From(v8::Isolate* isolate,
|
||||
NativeWindow* native_window) {
|
||||
auto existing = TrackableObject::FromWrappedClass(isolate, native_window);
|
||||
if (existing)
|
||||
return existing->GetWrapper(isolate);
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -43,6 +43,10 @@ class Window : public mate::TrackableObject<Window>,
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
// Returns the BrowserWindow object from |native_window|.
|
||||
static v8::Local<v8::Value> From(v8::Isolate* isolate,
|
||||
NativeWindow* native_window);
|
||||
|
||||
NativeWindow* window() const { return window_.get(); }
|
||||
|
||||
protected:
|
||||
@@ -69,17 +73,16 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void OnWindowLeaveHtmlFullScreen() override;
|
||||
void OnRendererUnresponsive() override;
|
||||
void OnRendererResponsive() override;
|
||||
void OnDevToolsFocus() override;
|
||||
void OnDevToolsOpened() override;
|
||||
void OnDevToolsClosed() override;
|
||||
void OnExecuteWindowsCommand(const std::string& command_name) override;
|
||||
|
||||
// mate::Wrappable:
|
||||
bool IsDestroyed() const override;
|
||||
|
||||
private:
|
||||
// mate::TrackableObject:
|
||||
void Destroy() override;
|
||||
|
||||
// APIs for NativeWindow.
|
||||
void Destroy();
|
||||
void Close();
|
||||
bool IsClosed();
|
||||
void Focus();
|
||||
@@ -122,6 +125,7 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void FocusOnWebView();
|
||||
void BlurWebView();
|
||||
bool IsWebViewFocused();
|
||||
bool IsDevToolsFocused();
|
||||
void SetRepresentedFilename(const std::string& filename);
|
||||
std::string GetRepresentedFilename();
|
||||
void SetDocumentEdited(bool edited);
|
||||
@@ -147,10 +151,8 @@ class Window : public mate::TrackableObject<Window>,
|
||||
|
||||
int32_t ID() const;
|
||||
v8::Local<v8::Value> WebContents(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
v8::Global<v8::Value> devtools_web_contents_;
|
||||
v8::Global<v8::Value> menu_;
|
||||
|
||||
api::WebContents* api_web_contents_;
|
||||
|
||||
66
atom/browser/api/frame_subscriber.cc
Normal file
66
atom/browser/api/frame_subscriber.cc
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/frame_subscriber.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/bind.h"
|
||||
#include "media/base/video_frame.h"
|
||||
#include "media/base/yuv_convert.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
FrameSubscriber::FrameSubscriber(v8::Isolate* isolate,
|
||||
const gfx::Size& size,
|
||||
const FrameCaptureCallback& callback)
|
||||
: isolate_(isolate), size_(size), callback_(callback) {
|
||||
}
|
||||
|
||||
bool FrameSubscriber::ShouldCaptureFrame(
|
||||
const gfx::Rect& damage_rect,
|
||||
base::TimeTicks present_time,
|
||||
scoped_refptr<media::VideoFrame>* storage,
|
||||
DeliverFrameCallback* callback) {
|
||||
*storage = media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_,
|
||||
gfx::Rect(size_), size_,
|
||||
base::TimeDelta());
|
||||
*callback = base::Bind(&FrameSubscriber::OnFrameDelivered,
|
||||
base::Unretained(this),
|
||||
*storage);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FrameSubscriber::OnFrameDelivered(
|
||||
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool result) {
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
gfx::Rect rect = frame->visible_rect();
|
||||
size_t rgb_arr_size = rect.width() * rect.height() * 4;
|
||||
v8::MaybeLocal<v8::Object> buffer = node::Buffer::New(isolate_, rgb_arr_size);
|
||||
if (buffer.IsEmpty())
|
||||
return;
|
||||
|
||||
// Convert a frame of YUV to 32 bit ARGB.
|
||||
media::ConvertYUVToRGB32(frame->data(media::VideoFrame::kYPlane),
|
||||
frame->data(media::VideoFrame::kUPlane),
|
||||
frame->data(media::VideoFrame::kVPlane),
|
||||
reinterpret_cast<uint8*>(
|
||||
node::Buffer::Data(buffer.ToLocalChecked())),
|
||||
rect.width(), rect.height(),
|
||||
frame->stride(media::VideoFrame::kYPlane),
|
||||
frame->stride(media::VideoFrame::kUVPlane),
|
||||
rect.width() * 4,
|
||||
media::YV12);
|
||||
|
||||
v8::Locker locker(isolate_);
|
||||
v8::HandleScope handle_scope(isolate_);
|
||||
callback_.Run(buffer.ToLocalChecked());
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
45
atom/browser/api/frame_subscriber.h
Normal file
45
atom/browser/api/frame_subscriber.h
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_
|
||||
#define ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
|
||||
public:
|
||||
using FrameCaptureCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
|
||||
FrameSubscriber(v8::Isolate* isolate,
|
||||
const gfx::Size& size,
|
||||
const FrameCaptureCallback& callback);
|
||||
|
||||
bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
|
||||
base::TimeTicks present_time,
|
||||
scoped_refptr<media::VideoFrame>* storage,
|
||||
DeliverFrameCallback* callback) override;
|
||||
|
||||
private:
|
||||
void OnFrameDelivered(
|
||||
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool);
|
||||
|
||||
v8::Isolate* isolate_;
|
||||
gfx::Size size_;
|
||||
FrameCaptureCallback callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FrameSubscriber);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_
|
||||
@@ -1,10 +1,25 @@
|
||||
EventEmitter = require('events').EventEmitter
|
||||
|
||||
bindings = process.atomBinding 'app'
|
||||
sessionBindings = process.atomBinding 'session'
|
||||
downloadItemBindings = process.atomBinding 'download_item'
|
||||
|
||||
app = bindings.app
|
||||
app.__proto__ = EventEmitter.prototype
|
||||
|
||||
wrapSession = (session) ->
|
||||
# session is an Event Emitter.
|
||||
session.__proto__ = EventEmitter.prototype
|
||||
|
||||
wrapDownloadItem = (download_item) ->
|
||||
# download_item is an Event Emitter.
|
||||
download_item.__proto__ = EventEmitter.prototype
|
||||
# Be compatible with old APIs.
|
||||
download_item.url = download_item.getUrl()
|
||||
download_item.filename = download_item.getFilename()
|
||||
download_item.mimeType = download_item.getMimeType()
|
||||
download_item.hasUserGesture = download_item.hasUserGesture()
|
||||
|
||||
app.setApplicationMenu = (menu) ->
|
||||
require('menu').setApplicationMenu menu
|
||||
|
||||
@@ -40,6 +55,14 @@ app.getHomeDir = -> @getPath 'home'
|
||||
app.getDataPath = -> @getPath 'userData'
|
||||
app.setDataPath = (path) -> @setPath 'userData', path
|
||||
app.resolveProxy = -> @defaultSession.resolveProxy.apply @defaultSession, arguments
|
||||
app.on 'activate', (event, hasVisibleWindows) -> @emit 'activate-with-no-open-windows' if not hasVisibleWindows
|
||||
|
||||
# Session wrapper.
|
||||
sessionBindings._setWrapSession wrapSession
|
||||
process.once 'exit', sessionBindings._clearWrapSession
|
||||
|
||||
downloadItemBindings._setWrapDownloadItem wrapDownloadItem
|
||||
process.once 'exit', downloadItemBindings._clearWrapDownloadItem
|
||||
|
||||
# Only one App object pemitted.
|
||||
module.exports = app
|
||||
|
||||
@@ -45,6 +45,18 @@ BrowserWindow::_init = ->
|
||||
@on 'focus', (event) =>
|
||||
app.emit 'browser-window-focus', event, this
|
||||
|
||||
# Notify the creation of the window.
|
||||
app.emit 'browser-window-created', {}, this
|
||||
|
||||
# Be compatible with old APIs.
|
||||
@webContents.on 'devtools-focused', => @emit 'devtools-focused'
|
||||
@webContents.on 'devtools-opened', => @emit 'devtools-opened'
|
||||
@webContents.on 'devtools-closed', => @emit 'devtools-closed'
|
||||
Object.defineProperty this, 'devToolsWebContents',
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
get: -> @webContents.devToolsWebContents
|
||||
|
||||
BrowserWindow.getFocusedWindow = ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
return window for window in windows when window.isFocused()
|
||||
@@ -62,6 +74,12 @@ BrowserWindow::loadUrl = -> @webContents.loadUrl.apply @webContents, arguments
|
||||
BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
|
||||
|
||||
# Be compatible with old API.
|
||||
BrowserWindow::undo = -> @webContents.undo()
|
||||
BrowserWindow::redo = -> @webContents.redo()
|
||||
BrowserWindow::cut = -> @webContents.cut()
|
||||
BrowserWindow::copy = -> @webContents.copy()
|
||||
BrowserWindow::paste = -> @webContents.paste()
|
||||
BrowserWindow::selectAll = -> @webContents.selectAll()
|
||||
BrowserWindow::restart = -> @webContents.reload()
|
||||
BrowserWindow::getUrl = -> @webContents.getUrl()
|
||||
BrowserWindow::reload = -> @webContents.reload.apply @webContents, arguments
|
||||
|
||||
@@ -3,18 +3,30 @@ v8Util = process.atomBinding 'v8_util'
|
||||
|
||||
nextCommandId = 0
|
||||
|
||||
# Maps role to methods of webContents
|
||||
rolesMap =
|
||||
undo: 'undo'
|
||||
redo: 'redo'
|
||||
cut: 'cut'
|
||||
copy: 'copy'
|
||||
paste: 'paste'
|
||||
selectall: 'selectAll'
|
||||
minimize: 'minimize'
|
||||
close: 'close'
|
||||
|
||||
class MenuItem
|
||||
@types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
|
||||
|
||||
constructor: (options) ->
|
||||
Menu = require 'menu'
|
||||
|
||||
{click, @selector, @type, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options
|
||||
{click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options
|
||||
|
||||
@type = 'submenu' if not @type? and @submenu?
|
||||
throw new Error('Invalid submenu') if @type is 'submenu' and @submenu?.constructor isnt Menu
|
||||
|
||||
@overrideReadOnlyProperty 'type', 'normal'
|
||||
@overrideReadOnlyProperty 'role'
|
||||
@overrideReadOnlyProperty 'accelerator'
|
||||
@overrideReadOnlyProperty 'icon'
|
||||
@overrideReadOnlyProperty 'submenu'
|
||||
@@ -27,12 +39,14 @@ class MenuItem
|
||||
throw new Error("Unknown menu type #{@type}") if MenuItem.types.indexOf(@type) is -1
|
||||
|
||||
@commandId = ++nextCommandId
|
||||
@click = =>
|
||||
@click = (focusedWindow) =>
|
||||
# Manually flip the checked flags when clicked.
|
||||
@checked = !@checked if @type in ['checkbox', 'radio']
|
||||
|
||||
if typeof click is 'function'
|
||||
click this, BrowserWindow.getFocusedWindow()
|
||||
if @role and rolesMap[@role] and process.platform isnt 'darwin'
|
||||
focusedWindow?[rolesMap[@role]]()
|
||||
else if typeof click is 'function'
|
||||
click this, focusedWindow
|
||||
else if typeof @selector is 'string'
|
||||
Menu.sendActionToFirstResponder @selector
|
||||
|
||||
|
||||
@@ -67,7 +67,8 @@ Menu::_init = ->
|
||||
isCommandIdVisible: (commandId) => @commandsMap[commandId]?.visible
|
||||
getAcceleratorForCommandId: (commandId) => @commandsMap[commandId]?.accelerator
|
||||
getIconForCommandId: (commandId) => @commandsMap[commandId]?.icon
|
||||
executeCommand: (commandId) => @commandsMap[commandId]?.click()
|
||||
executeCommand: (commandId) =>
|
||||
@commandsMap[commandId]?.click BrowserWindow.getFocusedWindow()
|
||||
menuWillShow: =>
|
||||
# Make sure radio groups have at least one menu item seleted.
|
||||
for id, group of @groupsMap
|
||||
@@ -78,7 +79,11 @@ Menu::_init = ->
|
||||
v8Util.setHiddenValue group[0], 'checked', true unless checked
|
||||
|
||||
Menu::popup = (window, x, y) ->
|
||||
throw new TypeError('Invalid window') unless window?.constructor is BrowserWindow
|
||||
unless window?.constructor is BrowserWindow
|
||||
# Shift.
|
||||
y = x
|
||||
x = window
|
||||
window = BrowserWindow.getFocusedWindow()
|
||||
if x? and y?
|
||||
@_popupAt(window, x, y)
|
||||
else
|
||||
@@ -115,6 +120,7 @@ Menu::insert = (pos, item) ->
|
||||
|
||||
@setSublabel pos, item.sublabel if item.sublabel?
|
||||
@setIcon pos, item.icon if item.icon?
|
||||
@setRole pos, item.role if item.role?
|
||||
|
||||
# Make menu accessable to items.
|
||||
item.overrideReadOnlyProperty 'menu', this
|
||||
|
||||
@@ -16,6 +16,11 @@ class NavigationController
|
||||
constructor: (@webContents) ->
|
||||
@clearHistory()
|
||||
|
||||
# webContents may have already navigated to a page.
|
||||
if @webContents._getUrl()
|
||||
@currentIndex++
|
||||
@history.push @webContents._getUrl()
|
||||
|
||||
@webContents.on 'navigation-entry-commited', (event, url, inPage, replaceEntry) =>
|
||||
if @inPageIndex > -1 and not inPage
|
||||
# Navigated to a new page, clear in-page mark.
|
||||
|
||||
@@ -44,10 +44,8 @@ wrapWebContents = (webContents) ->
|
||||
|
||||
# Make sure webContents.executeJavaScript would run the code only when the
|
||||
# web contents has been loaded.
|
||||
webContents.loaded = false
|
||||
webContents.once 'did-finish-load', -> @loaded = true
|
||||
webContents.executeJavaScript = (code, hasUserGesture=false) ->
|
||||
if @loaded
|
||||
if @getUrl() and not @isLoading()
|
||||
@_executeJavaScript code, hasUserGesture
|
||||
else
|
||||
webContents.once 'did-finish-load', @_executeJavaScript.bind(this, code, hasUserGesture)
|
||||
|
||||
@@ -29,7 +29,9 @@ class IDUserData : public base::SupportsUserData::Data {
|
||||
} // namespace
|
||||
|
||||
TrackableObjectBase::TrackableObjectBase()
|
||||
: weak_map_id_(0), wrapped_(nullptr) {
|
||||
: weak_map_id_(0), wrapped_(nullptr), weak_factory_(this) {
|
||||
RegisterDestructionCallback(
|
||||
base::Bind(&TrackableObjectBase::Destroy, weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
TrackableObjectBase::~TrackableObjectBase() {
|
||||
@@ -61,8 +63,9 @@ int32_t TrackableObjectBase::GetIDFromWrappedClass(base::SupportsUserData* w) {
|
||||
}
|
||||
|
||||
// static
|
||||
void TrackableObjectBase::RegisterDestructionCallback(void (*c)()) {
|
||||
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(base::Bind(c));
|
||||
void TrackableObjectBase::RegisterDestructionCallback(
|
||||
const base::Closure& closure) {
|
||||
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(closure);
|
||||
}
|
||||
|
||||
} // namespace mate
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/common/id_weak_map.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
|
||||
namespace base {
|
||||
class SupportsUserData;
|
||||
@@ -28,6 +30,9 @@ class TrackableObjectBase : public mate::EventEmitter {
|
||||
// Wrap TrackableObject into a class that SupportsUserData.
|
||||
void AttachAsUserData(base::SupportsUserData* wrapped);
|
||||
|
||||
// Subclasses should implement this to destroy their native types.
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
protected:
|
||||
~TrackableObjectBase() override;
|
||||
|
||||
@@ -39,12 +44,14 @@ class TrackableObjectBase : public mate::EventEmitter {
|
||||
|
||||
// Register a callback that should be destroyed before JavaScript environment
|
||||
// gets destroyed.
|
||||
static void RegisterDestructionCallback(void (*callback)());
|
||||
static void RegisterDestructionCallback(const base::Closure& closure);
|
||||
|
||||
int32_t weak_map_id_;
|
||||
base::SupportsUserData* wrapped_;
|
||||
|
||||
private:
|
||||
base::WeakPtrFactory<TrackableObjectBase> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TrackableObjectBase);
|
||||
};
|
||||
|
||||
@@ -85,7 +92,8 @@ class TrackableObject : public TrackableObjectBase {
|
||||
}
|
||||
|
||||
TrackableObject() {
|
||||
RegisterDestructionCallback(&TrackableObject<T>::ReleaseAllWeakReferences);
|
||||
RegisterDestructionCallback(
|
||||
base::Bind(&TrackableObject<T>::ReleaseAllWeakReferences));
|
||||
}
|
||||
|
||||
// Removes this instance from the weak map.
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/atom_quota_permission_context.h"
|
||||
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
|
||||
#include "atom/browser/atom_speech_recognition_manager_delegate.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
@@ -30,6 +31,7 @@
|
||||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/resource_dispatcher_host.h"
|
||||
#include "content/public/browser/site_instance.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/common/web_preferences.h"
|
||||
@@ -37,6 +39,7 @@
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
#include "ppapi/host/ppapi_host.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -53,33 +56,6 @@ bool g_suppress_renderer_process_restart = false;
|
||||
// Custom schemes to be registered to standard.
|
||||
std::string g_custom_schemes = "";
|
||||
|
||||
// Find out the owner of the child process according to |process_id|.
|
||||
enum ProcessOwner {
|
||||
OWNER_NATIVE_WINDOW,
|
||||
OWNER_GUEST_WEB_CONTENTS,
|
||||
OWNER_NONE, // it might be devtools though.
|
||||
};
|
||||
|
||||
ProcessOwner GetProcessOwner(int process_id,
|
||||
NativeWindow** window,
|
||||
WebViewManager::WebViewInfo* info) {
|
||||
content::WebContents* web_contents = content::WebContents::FromRenderViewHost(
|
||||
content::RenderViewHost::FromID(process_id, kDefaultRoutingID));
|
||||
if (!web_contents)
|
||||
return OWNER_NONE;
|
||||
|
||||
// First search for NativeWindow.
|
||||
*window = NativeWindow::FromWebContents(web_contents);
|
||||
if (*window)
|
||||
return OWNER_NATIVE_WINDOW;
|
||||
|
||||
// Then search for guest WebContents.
|
||||
if (WebViewManager::GetInfoForWebContents(web_contents, info))
|
||||
return OWNER_GUEST_WEB_CONTENTS;
|
||||
|
||||
return OWNER_NONE;
|
||||
}
|
||||
|
||||
scoped_refptr<net::X509Certificate> ImportCertFromFile(
|
||||
const base::FilePath& path) {
|
||||
if (path.empty())
|
||||
@@ -155,15 +131,7 @@ void AtomBrowserClient::OverrideWebkitPrefs(
|
||||
|
||||
// Custom preferences of guest page.
|
||||
auto web_contents = content::WebContents::FromRenderViewHost(host);
|
||||
WebViewManager::WebViewInfo info;
|
||||
if (WebViewManager::GetInfoForWebContents(web_contents, &info)) {
|
||||
prefs->web_security_enabled = !info.disable_web_security;
|
||||
return;
|
||||
}
|
||||
|
||||
NativeWindow* window = NativeWindow::FromWebContents(web_contents);
|
||||
if (window)
|
||||
window->OverrideWebkitPrefs(prefs);
|
||||
WebContentsPreferences::OverrideWebkitPrefs(web_contents, prefs);
|
||||
}
|
||||
|
||||
std::string AtomBrowserClient::GetApplicationLocale() {
|
||||
@@ -219,23 +187,14 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||
if (ContainsKey(pending_processes_, process_id))
|
||||
process_id = pending_processes_[process_id];
|
||||
|
||||
NativeWindow* window;
|
||||
WebViewManager::WebViewInfo info;
|
||||
ProcessOwner owner = GetProcessOwner(process_id, &window, &info);
|
||||
// Get the WebContents of the render process.
|
||||
content::WebContents* web_contents = content::WebContents::FromRenderViewHost(
|
||||
content::RenderViewHost::FromID(process_id, kDefaultRoutingID));
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
if (owner == OWNER_NATIVE_WINDOW) {
|
||||
window->AppendExtraCommandLineSwitches(command_line);
|
||||
} else if (owner == OWNER_GUEST_WEB_CONTENTS) {
|
||||
command_line->AppendSwitchASCII(
|
||||
switches::kGuestInstanceID, base::IntToString(info.guest_instance_id));
|
||||
command_line->AppendSwitchASCII(
|
||||
switches::kNodeIntegration, info.node_integration ? "true" : "false");
|
||||
if (info.plugins)
|
||||
command_line->AppendSwitch(switches::kEnablePlugins);
|
||||
if (!info.preload_script.empty())
|
||||
command_line->AppendSwitchPath(
|
||||
switches::kPreloadScript, info.preload_script);
|
||||
}
|
||||
WebContentsPreferences::AppendExtraCommandLineSwitches(
|
||||
web_contents, command_line);
|
||||
}
|
||||
|
||||
void AtomBrowserClient::DidCreatePpapiPlugin(
|
||||
@@ -269,6 +228,13 @@ void AtomBrowserClient::SelectClientCertificate(
|
||||
delegate.Pass());
|
||||
}
|
||||
|
||||
void AtomBrowserClient::ResourceDispatcherHostCreated() {
|
||||
resource_dispatcher_host_delegate_.reset(
|
||||
new AtomResourceDispatcherHostDelegate);
|
||||
content::ResourceDispatcherHost::Get()->SetDelegate(
|
||||
resource_dispatcher_host_delegate_.get());
|
||||
}
|
||||
|
||||
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
|
||||
const content::MainFunctionParams&) {
|
||||
v8::V8::Initialize(); // Init V8 before creating main parts.
|
||||
|
||||
@@ -23,6 +23,8 @@ class SSLCertRequestInfo;
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomResourceDispatcherHostDelegate;
|
||||
|
||||
class AtomBrowserClient : public brightray::BrowserClient,
|
||||
public content::RenderProcessHostObserver {
|
||||
public:
|
||||
@@ -56,6 +58,7 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
void ResourceDispatcherHostCreated() override;
|
||||
|
||||
// brightray::BrowserClient:
|
||||
brightray::BrowserMainParts* OverrideCreateBrowserMainParts(
|
||||
@@ -68,6 +71,9 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||
// pending_render_process => current_render_process.
|
||||
std::map<int, int> pending_processes_;
|
||||
|
||||
scoped_ptr<AtomResourceDispatcherHostDelegate>
|
||||
resource_dispatcher_host_delegate_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient);
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/atom_download_manager_delegate.h"
|
||||
#include "atom/browser/atom_ssl_config_service.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/net/atom_url_request_job_factory.h"
|
||||
#include "atom/browser/net/asar/asar_protocol_handler.h"
|
||||
@@ -56,8 +57,10 @@ std::string RemoveWhitespace(const std::string& str) {
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomBrowserContext::AtomBrowserContext()
|
||||
: job_factory_(new AtomURLRequestJobFactory) {
|
||||
AtomBrowserContext::AtomBrowserContext(const std::string& partition,
|
||||
bool in_memory)
|
||||
: brightray::BrowserContext(partition, in_memory),
|
||||
job_factory_(new AtomURLRequestJobFactory) {
|
||||
}
|
||||
|
||||
AtomBrowserContext::~AtomBrowserContext() {
|
||||
@@ -150,10 +153,14 @@ AtomBrowserContext::GetDownloadManagerDelegate() {
|
||||
|
||||
content::BrowserPluginGuestManager* AtomBrowserContext::GetGuestManager() {
|
||||
if (!guest_manager_)
|
||||
guest_manager_.reset(new WebViewManager(this));
|
||||
guest_manager_.reset(new WebViewManager);
|
||||
return guest_manager_.get();
|
||||
}
|
||||
|
||||
net::SSLConfigService* AtomBrowserContext::CreateSSLConfigService() {
|
||||
return new AtomSSLConfigService;
|
||||
}
|
||||
|
||||
void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
|
||||
pref_registry->RegisterFilePathPref(prefs::kSelectFileLastDirectory,
|
||||
base::FilePath());
|
||||
@@ -162,3 +169,13 @@ void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace brightray {
|
||||
|
||||
// static
|
||||
scoped_refptr<BrowserContext> BrowserContext::Create(
|
||||
const std::string& partition, bool in_memory) {
|
||||
return make_scoped_refptr(new atom::AtomBrowserContext(partition, in_memory));
|
||||
}
|
||||
|
||||
} // namespace brightray
|
||||
|
||||
@@ -17,8 +17,8 @@ class WebViewManager;
|
||||
|
||||
class AtomBrowserContext : public brightray::BrowserContext {
|
||||
public:
|
||||
AtomBrowserContext();
|
||||
virtual ~AtomBrowserContext();
|
||||
AtomBrowserContext(const std::string& partition, bool in_memory);
|
||||
~AtomBrowserContext() override;
|
||||
|
||||
// brightray::URLRequestContextGetter::Delegate:
|
||||
std::string GetUserAgent() override;
|
||||
@@ -27,6 +27,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
content::URLRequestInterceptorScopedVector* interceptors) override;
|
||||
net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory(
|
||||
const base::FilePath& base_path) override;
|
||||
net::SSLConfigService* CreateSSLConfigService() override;
|
||||
|
||||
// content::BrowserContext:
|
||||
content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
|
||||
@@ -41,7 +42,8 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
scoped_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
|
||||
scoped_ptr<WebViewManager> guest_manager_;
|
||||
|
||||
AtomURLRequestJobFactory* job_factory_; // Weak reference.
|
||||
// Managed by brightray::BrowserContext.
|
||||
AtomURLRequestJobFactory* job_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext);
|
||||
};
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/bridge_task_runner.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/javascript_environment.h"
|
||||
#include "atom/browser/node_debugger.h"
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "v8/include/v8-debug.h"
|
||||
|
||||
@@ -20,8 +23,6 @@
|
||||
#include "chrome/browser/ui/libgtk2ui/gtk2_util.h"
|
||||
#endif
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// static
|
||||
@@ -38,8 +39,6 @@ AtomBrowserMainParts::AtomBrowserMainParts()
|
||||
}
|
||||
|
||||
AtomBrowserMainParts::~AtomBrowserMainParts() {
|
||||
for (const auto& callback : destruction_callbacks_)
|
||||
callback.Run();
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -53,20 +52,27 @@ void AtomBrowserMainParts::RegisterDestructionCallback(
|
||||
destruction_callbacks_.push_back(callback);
|
||||
}
|
||||
|
||||
brightray::BrowserContext* AtomBrowserMainParts::CreateBrowserContext() {
|
||||
return new AtomBrowserContext();
|
||||
void AtomBrowserMainParts::PreEarlyInitialization() {
|
||||
brightray::BrowserMainParts::PreEarlyInitialization();
|
||||
#if defined(OS_POSIX)
|
||||
HandleSIGCHLD();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::PostEarlyInitialization() {
|
||||
brightray::BrowserMainParts::PostEarlyInitialization();
|
||||
|
||||
#if defined(USE_X11)
|
||||
SetDPIFromGSettings();
|
||||
#endif
|
||||
{
|
||||
// Temporary set the bridge_task_runner_ as current thread's task runner,
|
||||
// so we can fool gin::PerIsolateData to use it as its task runner, instead
|
||||
// of getting current message loop's task runner, which is null for now.
|
||||
bridge_task_runner_ = new BridgeTaskRunner;
|
||||
base::ThreadTaskRunnerHandle handle(bridge_task_runner_);
|
||||
|
||||
// The ProxyResolverV8 has setup a complete V8 environment, in order to avoid
|
||||
// conflicts we only initialize our V8 environment after that.
|
||||
js_env_.reset(new JavascriptEnvironment);
|
||||
// The ProxyResolverV8 has setup a complete V8 environment, in order to
|
||||
// avoid conflicts we only initialize our V8 environment after that.
|
||||
js_env_.reset(new JavascriptEnvironment);
|
||||
}
|
||||
|
||||
node_bindings_->Initialize();
|
||||
|
||||
@@ -113,4 +119,21 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::PostMainMessageLoopStart() {
|
||||
brightray::BrowserMainParts::PostMainMessageLoopStart();
|
||||
#if defined(OS_POSIX)
|
||||
HandleShutdownSignals();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::PostMainMessageLoopRun() {
|
||||
brightray::BrowserMainParts::PostMainMessageLoopRun();
|
||||
|
||||
// Make sure destruction callbacks are called before message loop is
|
||||
// destroyed, otherwise some objects that need to be deleted on IO thread
|
||||
// won't be freed.
|
||||
for (const auto& callback : destruction_callbacks_)
|
||||
callback.Run();
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
#define ATOM_BROWSER_ATOM_BROWSER_MAIN_PARTS_H_
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "brightray/browser/browser_main_parts.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
|
||||
class BrowserProcess;
|
||||
|
||||
@@ -20,6 +22,7 @@ class Browser;
|
||||
class JavascriptEnvironment;
|
||||
class NodeBindings;
|
||||
class NodeDebugger;
|
||||
class BridgeTaskRunner;
|
||||
|
||||
class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
||||
public:
|
||||
@@ -35,25 +38,31 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
||||
Browser* browser() { return browser_.get(); }
|
||||
|
||||
protected:
|
||||
// Implementations of brightray::BrowserMainParts.
|
||||
brightray::BrowserContext* CreateBrowserContext() override;
|
||||
|
||||
// Implementations of content::BrowserMainParts.
|
||||
// content::BrowserMainParts:
|
||||
void PreEarlyInitialization() override;
|
||||
void PostEarlyInitialization() override;
|
||||
void PreMainMessageLoopRun() override;
|
||||
void PostMainMessageLoopStart() override;
|
||||
void PostMainMessageLoopRun() override;
|
||||
#if defined(OS_MACOSX)
|
||||
void PreMainMessageLoopStart() override;
|
||||
void PostDestroyThreads() override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if defined(USE_X11)
|
||||
void SetDPIFromGSettings();
|
||||
#if defined(OS_POSIX)
|
||||
// Set signal handlers.
|
||||
void HandleSIGCHLD();
|
||||
void HandleShutdownSignals();
|
||||
#endif
|
||||
|
||||
// A fake BrowserProcess object that used to feed the source code from chrome.
|
||||
scoped_ptr<BrowserProcess> fake_browser_process_;
|
||||
|
||||
// The gin::PerIsolateData requires a task runner to create, so we feed it
|
||||
// with a task runner that will post all work to main loop.
|
||||
scoped_refptr<BridgeTaskRunner> bridge_task_runner_;
|
||||
|
||||
scoped_ptr<Browser> browser_;
|
||||
scoped_ptr<JavascriptEnvironment> js_env_;
|
||||
scoped_ptr<NodeBindings> node_bindings_;
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// 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/atom_browser_main_parts.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "ui/gfx/switches.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const char* kInterfaceSchema = "org.gnome.desktop.interface";
|
||||
const char* kScaleFactor = "scaling-factor";
|
||||
|
||||
bool SchemaExists(const char* schema_name) {
|
||||
const gchar* const* schemas = g_settings_list_schemas();
|
||||
while (*schemas) {
|
||||
if (strcmp(schema_name, static_cast<const char*>(*schemas)) == 0)
|
||||
return true;
|
||||
schemas++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyExists(GSettings* client, const char* key) {
|
||||
gchar** keys = g_settings_list_keys(client);
|
||||
if (!keys)
|
||||
return false;
|
||||
|
||||
gchar** iter = keys;
|
||||
while (*iter) {
|
||||
if (strcmp(*iter, key) == 0)
|
||||
break;
|
||||
iter++;
|
||||
}
|
||||
|
||||
bool exists = *iter != NULL;
|
||||
g_strfreev(keys);
|
||||
return exists;
|
||||
}
|
||||
|
||||
void GetDPIFromGSettings(guint* scale_factor) {
|
||||
GSettings* client = nullptr;
|
||||
if (!SchemaExists(kInterfaceSchema) ||
|
||||
!(client = g_settings_new(kInterfaceSchema))) {
|
||||
VLOG(1) << "Cannot create gsettings client.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (KeyExists(client, kScaleFactor))
|
||||
*scale_factor = g_settings_get_uint(client, kScaleFactor);
|
||||
|
||||
g_object_unref(client);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void AtomBrowserMainParts::SetDPIFromGSettings() {
|
||||
guint scale_factor = 1;
|
||||
GetDPIFromGSettings(&scale_factor);
|
||||
if (scale_factor == 0)
|
||||
scale_factor = 1;
|
||||
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
switches::kForceDeviceScaleFactor, base::UintToString(scale_factor));
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
225
atom/browser/atom_browser_main_parts_posix.cc
Normal file
225
atom/browser/atom_browser_main_parts_posix.cc
Normal file
@@ -0,0 +1,225 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Most code came from: chrome/browser/chrome_browser_main_posix.cc.
|
||||
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "base/posix/eintr_wrapper.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// See comment in |PreEarlyInitialization()|, where sigaction is called.
|
||||
void SIGCHLDHandler(int signal) {
|
||||
}
|
||||
|
||||
// The OSX fork() implementation can crash in the child process before
|
||||
// fork() returns. In that case, the shutdown pipe will still be
|
||||
// shared with the parent process. To prevent child crashes from
|
||||
// causing parent shutdowns, |g_pipe_pid| is the pid for the process
|
||||
// which registered |g_shutdown_pipe_write_fd|.
|
||||
// See <http://crbug.com/175341>.
|
||||
pid_t g_pipe_pid = -1;
|
||||
int g_shutdown_pipe_write_fd = -1;
|
||||
int g_shutdown_pipe_read_fd = -1;
|
||||
|
||||
// Common code between SIG{HUP, INT, TERM}Handler.
|
||||
void GracefulShutdownHandler(int signal) {
|
||||
// Reinstall the default handler. We had one shot at graceful shutdown.
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof(action));
|
||||
action.sa_handler = SIG_DFL;
|
||||
RAW_CHECK(sigaction(signal, &action, NULL) == 0);
|
||||
|
||||
RAW_CHECK(g_pipe_pid == getpid());
|
||||
RAW_CHECK(g_shutdown_pipe_write_fd != -1);
|
||||
RAW_CHECK(g_shutdown_pipe_read_fd != -1);
|
||||
size_t bytes_written = 0;
|
||||
do {
|
||||
int rv = HANDLE_EINTR(
|
||||
write(g_shutdown_pipe_write_fd,
|
||||
reinterpret_cast<const char*>(&signal) + bytes_written,
|
||||
sizeof(signal) - bytes_written));
|
||||
RAW_CHECK(rv >= 0);
|
||||
bytes_written += rv;
|
||||
} while (bytes_written < sizeof(signal));
|
||||
}
|
||||
|
||||
// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
|
||||
void SIGHUPHandler(int signal) {
|
||||
RAW_CHECK(signal == SIGHUP);
|
||||
GracefulShutdownHandler(signal);
|
||||
}
|
||||
|
||||
// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
|
||||
void SIGINTHandler(int signal) {
|
||||
RAW_CHECK(signal == SIGINT);
|
||||
GracefulShutdownHandler(signal);
|
||||
}
|
||||
|
||||
// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
|
||||
void SIGTERMHandler(int signal) {
|
||||
RAW_CHECK(signal == SIGTERM);
|
||||
GracefulShutdownHandler(signal);
|
||||
}
|
||||
|
||||
class ShutdownDetector : public base::PlatformThread::Delegate {
|
||||
public:
|
||||
explicit ShutdownDetector(int shutdown_fd);
|
||||
|
||||
void ThreadMain() override;
|
||||
|
||||
private:
|
||||
const int shutdown_fd_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
|
||||
};
|
||||
|
||||
ShutdownDetector::ShutdownDetector(int shutdown_fd)
|
||||
: shutdown_fd_(shutdown_fd) {
|
||||
CHECK_NE(shutdown_fd_, -1);
|
||||
}
|
||||
|
||||
// These functions are used to help us diagnose crash dumps that happen
|
||||
// during the shutdown process.
|
||||
NOINLINE void ShutdownFDReadError() {
|
||||
// Ensure function isn't optimized away.
|
||||
asm("");
|
||||
sleep(UINT_MAX);
|
||||
}
|
||||
|
||||
NOINLINE void ShutdownFDClosedError() {
|
||||
// Ensure function isn't optimized away.
|
||||
asm("");
|
||||
sleep(UINT_MAX);
|
||||
}
|
||||
|
||||
NOINLINE void ExitPosted() {
|
||||
// Ensure function isn't optimized away.
|
||||
asm("");
|
||||
sleep(UINT_MAX);
|
||||
}
|
||||
|
||||
void ShutdownDetector::ThreadMain() {
|
||||
base::PlatformThread::SetName("CrShutdownDetector");
|
||||
|
||||
int signal;
|
||||
size_t bytes_read = 0;
|
||||
ssize_t ret;
|
||||
do {
|
||||
ret = HANDLE_EINTR(
|
||||
read(shutdown_fd_,
|
||||
reinterpret_cast<char*>(&signal) + bytes_read,
|
||||
sizeof(signal) - bytes_read));
|
||||
if (ret < 0) {
|
||||
NOTREACHED() << "Unexpected error: " << strerror(errno);
|
||||
ShutdownFDReadError();
|
||||
break;
|
||||
} else if (ret == 0) {
|
||||
NOTREACHED() << "Unexpected closure of shutdown pipe.";
|
||||
ShutdownFDClosedError();
|
||||
break;
|
||||
}
|
||||
bytes_read += ret;
|
||||
} while (bytes_read < sizeof(signal));
|
||||
VLOG(1) << "Handling shutdown for signal " << signal << ".";
|
||||
base::Closure task =
|
||||
base::Bind(&Browser::Quit, base::Unretained(Browser::Get()));
|
||||
|
||||
if (!BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task)) {
|
||||
// Without a UI thread to post the exit task to, there aren't many
|
||||
// options. Raise the signal again. The default handler will pick it up
|
||||
// and cause an ungraceful exit.
|
||||
RAW_LOG(WARNING, "No UI thread, exiting ungracefully.");
|
||||
kill(getpid(), signal);
|
||||
|
||||
// The signal may be handled on another thread. Give that a chance to
|
||||
// happen.
|
||||
sleep(3);
|
||||
|
||||
// We really should be dead by now. For whatever reason, we're not. Exit
|
||||
// immediately, with the exit status set to the signal number with bit 8
|
||||
// set. On the systems that we care about, this exit status is what is
|
||||
// normally used to indicate an exit by this signal's default handler.
|
||||
// This mechanism isn't a de jure standard, but even in the worst case, it
|
||||
// should at least result in an immediate exit.
|
||||
RAW_LOG(WARNING, "Still here, exiting really ungracefully.");
|
||||
_exit(signal | (1 << 7));
|
||||
}
|
||||
ExitPosted();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void AtomBrowserMainParts::HandleSIGCHLD() {
|
||||
// We need to accept SIGCHLD, even though our handler is a no-op because
|
||||
// otherwise we cannot wait on children. (According to POSIX 2001.)
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof(action));
|
||||
action.sa_handler = SIGCHLDHandler;
|
||||
CHECK_EQ(sigaction(SIGCHLD, &action, NULL), 0);
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::HandleShutdownSignals() {
|
||||
int pipefd[2];
|
||||
int ret = pipe(pipefd);
|
||||
if (ret < 0) {
|
||||
PLOG(DFATAL) << "Failed to create pipe";
|
||||
} else {
|
||||
g_pipe_pid = getpid();
|
||||
g_shutdown_pipe_read_fd = pipefd[0];
|
||||
g_shutdown_pipe_write_fd = pipefd[1];
|
||||
#if !defined(ADDRESS_SANITIZER) && !defined(KEEP_SHADOW_STACKS)
|
||||
const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2;
|
||||
#else
|
||||
// ASan instrumentation and -finstrument-functions (used for keeping the
|
||||
// shadow stacks) bloat the stack frames, so we need to increase the stack
|
||||
// size to avoid hitting the guard page.
|
||||
const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4;
|
||||
#endif
|
||||
// TODO(viettrungluu,willchan): crbug.com/29675 - This currently leaks, so
|
||||
// if you change this, you'll probably need to change the suppression.
|
||||
if (!base::PlatformThread::CreateNonJoinable(
|
||||
kShutdownDetectorThreadStackSize,
|
||||
new ShutdownDetector(g_shutdown_pipe_read_fd))) {
|
||||
LOG(DFATAL) << "Failed to create shutdown detector task.";
|
||||
}
|
||||
}
|
||||
// Setup signal handlers for shutdown AFTER shutdown pipe is setup because
|
||||
// it may be called right away after handler is set.
|
||||
|
||||
// If adding to this list of signal handlers, note the new signal probably
|
||||
// needs to be reset in child processes. See
|
||||
// base/process_util_posix.cc:LaunchProcess.
|
||||
|
||||
// We need to handle SIGTERM, because that is how many POSIX-based distros ask
|
||||
// processes to quit gracefully at shutdown time.
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof(action));
|
||||
action.sa_handler = SIGTERMHandler;
|
||||
CHECK_EQ(sigaction(SIGTERM, &action, NULL), 0);
|
||||
// Also handle SIGINT - when the user terminates the browser via Ctrl+C. If
|
||||
// the browser process is being debugged, GDB will catch the SIGINT first.
|
||||
action.sa_handler = SIGINTHandler;
|
||||
CHECK_EQ(sigaction(SIGINT, &action, NULL), 0);
|
||||
// And SIGHUP, for when the terminal disappears. On shutdown, many Linux
|
||||
// distros send SIGHUP, SIGTERM, and then SIGKILL.
|
||||
action.sa_handler = SIGHUPHandler;
|
||||
CHECK_EQ(sigaction(SIGHUP, &action, NULL), 0);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_download_item.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/ui/file_dialog.h"
|
||||
@@ -73,18 +74,19 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
|
||||
if (relay)
|
||||
window = relay->window.get();
|
||||
|
||||
file_dialog::Filters filters;
|
||||
base::FilePath path;
|
||||
if (!file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path,
|
||||
filters, &path)) {
|
||||
return;
|
||||
if (file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path,
|
||||
file_dialog::Filters(), &path)) {
|
||||
// Remember the last selected download directory.
|
||||
AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
|
||||
download_manager_->GetBrowserContext());
|
||||
browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
|
||||
path.DirName());
|
||||
}
|
||||
|
||||
// Remeber the last selected download directory.
|
||||
AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
|
||||
download_manager_->GetBrowserContext());
|
||||
browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
|
||||
path.DirName());
|
||||
// Running the DownloadTargetCallback with an empty FilePath signals that the
|
||||
// download should be cancelled.
|
||||
// If user cancels the file save dialog, run the callback with empty FilePath.
|
||||
callback.Run(path,
|
||||
content::DownloadItem::TARGET_DISPOSITION_PROMPT,
|
||||
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path);
|
||||
@@ -100,6 +102,25 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget(
|
||||
const content::DownloadTargetCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
if (!download->GetForcedFilePath().empty()) {
|
||||
callback.Run(download->GetForcedFilePath(),
|
||||
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
|
||||
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||
download->GetForcedFilePath());
|
||||
return true;
|
||||
}
|
||||
base::SupportsUserData::Data* save_path = download->GetUserData(
|
||||
atom::api::DownloadItem::UserDataKey());
|
||||
if (save_path) {
|
||||
const base::FilePath& default_download_path =
|
||||
static_cast<api::DownloadItem::SavePathData*>(save_path)->path();
|
||||
callback.Run(default_download_path,
|
||||
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
|
||||
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||
default_download_path);
|
||||
return true;
|
||||
}
|
||||
|
||||
AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
|
||||
download_manager_->GetBrowserContext());
|
||||
base::FilePath default_download_path = browser_context->prefs()->GetFilePath(
|
||||
@@ -110,14 +131,6 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget(
|
||||
default_download_path = path.Append(FILE_PATH_LITERAL("Downloads"));
|
||||
}
|
||||
|
||||
if (!download->GetForcedFilePath().empty()) {
|
||||
callback.Run(download->GetForcedFilePath(),
|
||||
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
|
||||
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||
download->GetForcedFilePath());
|
||||
return true;
|
||||
}
|
||||
|
||||
CreateDownloadPathCallback download_path_callback =
|
||||
base::Bind(&AtomDownloadManagerDelegate::OnDownloadPathGenerated,
|
||||
weak_ptr_factory_.GetWeakPtr(),
|
||||
|
||||
32
atom/browser/atom_resource_dispatcher_host_delegate.cc
Normal file
32
atom/browser/atom_resource_dispatcher_host_delegate.cc
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
|
||||
|
||||
#include "atom/common/platform_util.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "net/base/escape.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() {
|
||||
}
|
||||
|
||||
bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol(
|
||||
const GURL& url,
|
||||
int render_process_id,
|
||||
int render_view_id,
|
||||
bool is_main_frame,
|
||||
ui::PageTransition transition,
|
||||
bool has_user_gesture) {
|
||||
GURL escaped_url(net::EscapeExternalHandlerValue(url.spec()));
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(base::IgnoreResult(platform_util::OpenExternal), escaped_url));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
28
atom/browser/atom_resource_dispatcher_host_delegate.h
Normal file
28
atom/browser/atom_resource_dispatcher_host_delegate.h
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
||||
#define ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
||||
|
||||
#include "content/public/browser/resource_dispatcher_host_delegate.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomResourceDispatcherHostDelegate
|
||||
: public content::ResourceDispatcherHostDelegate {
|
||||
public:
|
||||
AtomResourceDispatcherHostDelegate();
|
||||
|
||||
// content::ResourceDispatcherHostDelegate:
|
||||
bool HandleExternalProtocol(const GURL& url,
|
||||
int render_process_id,
|
||||
int render_view_id,
|
||||
bool is_main_frame,
|
||||
ui::PageTransition transition,
|
||||
bool has_user_gesture) override;
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
||||
47
atom/browser/atom_ssl_config_service.cc
Normal file
47
atom/browser/atom_ssl_config_service.cc
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/atom_ssl_config_service.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "net/socket/ssl_client_socket.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
uint16 GetSSLProtocolVersion(const std::string& version_string) {
|
||||
uint16 version = 0; // Invalid
|
||||
if (version_string == "tls1")
|
||||
version = net::SSL_PROTOCOL_VERSION_TLS1;
|
||||
else if (version_string == "tls1.1")
|
||||
version = net::SSL_PROTOCOL_VERSION_TLS1_1;
|
||||
else if (version_string == "tls1.2")
|
||||
version = net::SSL_PROTOCOL_VERSION_TLS1_2;
|
||||
return version;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomSSLConfigService::AtomSSLConfigService() {
|
||||
auto cmd_line = base::CommandLine::ForCurrentProcess();
|
||||
if (cmd_line->HasSwitch(switches::kSSLVersionFallbackMin)) {
|
||||
auto version_string =
|
||||
cmd_line->GetSwitchValueASCII(switches::kSSLVersionFallbackMin);
|
||||
config_.version_fallback_min = GetSSLProtocolVersion(version_string);
|
||||
}
|
||||
}
|
||||
|
||||
AtomSSLConfigService::~AtomSSLConfigService() {
|
||||
}
|
||||
|
||||
void AtomSSLConfigService::GetSSLConfig(net::SSLConfig* config) {
|
||||
*config = config_;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
28
atom/browser/atom_ssl_config_service.h
Normal file
28
atom/browser/atom_ssl_config_service.h
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_
|
||||
#define ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_
|
||||
|
||||
#include "net/ssl/ssl_config_service.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomSSLConfigService : public net::SSLConfigService {
|
||||
public:
|
||||
AtomSSLConfigService();
|
||||
~AtomSSLConfigService() override;
|
||||
|
||||
// net::SSLConfigService:
|
||||
void GetSSLConfig(net::SSLConfig* config) override;
|
||||
|
||||
private:
|
||||
net::SSLConfig config_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomSSLConfigService);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_
|
||||
42
atom/browser/bridge_task_runner.cc
Normal file
42
atom/browser/bridge_task_runner.cc
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/bridge_task_runner.h"
|
||||
|
||||
#include "base/message_loop/message_loop.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
bool BridgeTaskRunner::PostDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
auto message_loop = base::MessageLoop::current();
|
||||
if (!message_loop)
|
||||
return false;
|
||||
|
||||
return message_loop->task_runner()->PostDelayedTask(from_here, task, delay);
|
||||
}
|
||||
|
||||
bool BridgeTaskRunner::RunsTasksOnCurrentThread() const {
|
||||
auto message_loop = base::MessageLoop::current();
|
||||
if (!message_loop)
|
||||
return false;
|
||||
|
||||
return message_loop->task_runner()->RunsTasksOnCurrentThread();
|
||||
}
|
||||
|
||||
bool BridgeTaskRunner::PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
auto message_loop = base::MessageLoop::current();
|
||||
if (!message_loop)
|
||||
return false;
|
||||
|
||||
return message_loop->task_runner()->PostNonNestableDelayedTask(
|
||||
from_here, task, delay);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
35
atom/browser/bridge_task_runner.h
Normal file
35
atom/browser/bridge_task_runner.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_
|
||||
#define ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_
|
||||
|
||||
#include "base/single_thread_task_runner.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Post all tasks to the current message loop's task runner if available,
|
||||
// otherwise fail silently.
|
||||
class BridgeTaskRunner : public base::SingleThreadTaskRunner {
|
||||
public:
|
||||
BridgeTaskRunner() {}
|
||||
~BridgeTaskRunner() override {}
|
||||
|
||||
// base::SingleThreadTaskRunner:
|
||||
bool PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) override;
|
||||
bool RunsTasksOnCurrentThread() const override;
|
||||
bool PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(BridgeTaskRunner);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_
|
||||
@@ -16,7 +16,8 @@ namespace atom {
|
||||
|
||||
Browser::Browser()
|
||||
: is_quiting_(false),
|
||||
is_ready_(false) {
|
||||
is_ready_(false),
|
||||
is_shutdown_(false) {
|
||||
WindowList::AddObserver(this);
|
||||
}
|
||||
|
||||
@@ -30,6 +31,9 @@ Browser* Browser::Get() {
|
||||
}
|
||||
|
||||
void Browser::Quit() {
|
||||
if (is_quiting_)
|
||||
return;
|
||||
|
||||
is_quiting_ = HandleBeforeQuit();
|
||||
if (!is_quiting_)
|
||||
return;
|
||||
@@ -42,9 +46,13 @@ void Browser::Quit() {
|
||||
}
|
||||
|
||||
void Browser::Shutdown() {
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnQuit());
|
||||
if (is_shutdown_)
|
||||
return;
|
||||
|
||||
is_shutdown_ = true;
|
||||
is_quiting_ = true;
|
||||
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnQuit());
|
||||
base::MessageLoop::current()->PostTask(
|
||||
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
|
||||
}
|
||||
@@ -94,8 +102,10 @@ void Browser::OpenURL(const std::string& url) {
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnOpenURL(url));
|
||||
}
|
||||
|
||||
void Browser::ActivateWithNoOpenWindows() {
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnActivateWithNoOpenWindows());
|
||||
void Browser::Activate(bool has_visible_windows) {
|
||||
FOR_EACH_OBSERVER(BrowserObserver,
|
||||
observers_,
|
||||
OnActivate(has_visible_windows));
|
||||
}
|
||||
|
||||
void Browser::WillFinishLaunching() {
|
||||
@@ -119,6 +129,9 @@ void Browser::ClientCertificateSelector(
|
||||
}
|
||||
|
||||
void Browser::NotifyAndShutdown() {
|
||||
if (is_shutdown_)
|
||||
return;
|
||||
|
||||
bool prevent_default = false;
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWillQuit(&prevent_default));
|
||||
|
||||
|
||||
@@ -108,8 +108,9 @@ class Browser : public WindowListObserver {
|
||||
// Tell the application to open a url.
|
||||
void OpenURL(const std::string& url);
|
||||
|
||||
// Tell the application that application is activated with no open windows.
|
||||
void ActivateWithNoOpenWindows();
|
||||
// Tell the application that application is activated with visible/invisible
|
||||
// windows.
|
||||
void Activate(bool has_visible_windows);
|
||||
|
||||
// Tell the application the loading has been done.
|
||||
void WillFinishLaunching();
|
||||
@@ -153,11 +154,14 @@ class Browser : public WindowListObserver {
|
||||
void OnWindowAllClosed() override;
|
||||
|
||||
// Observers of the browser.
|
||||
ObserverList<BrowserObserver> observers_;
|
||||
base::ObserverList<BrowserObserver> observers_;
|
||||
|
||||
// Whether "ready" event has been emitted.
|
||||
bool is_ready_;
|
||||
|
||||
// The browse is being shutdown.
|
||||
bool is_shutdown_;
|
||||
|
||||
std::string version_override_;
|
||||
std::string name_override_;
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@ class BrowserObserver {
|
||||
// Browser is used to open a url.
|
||||
virtual void OnOpenURL(const std::string& url) {}
|
||||
|
||||
// The browser is activated with no open windows (usually by clicking on the
|
||||
// dock icon).
|
||||
virtual void OnActivateWithNoOpenWindows() {}
|
||||
// The browser is activated with visible/invisible windows (usually by
|
||||
// clicking on the dock icon).
|
||||
virtual void OnActivate(bool has_visible_windows) {}
|
||||
|
||||
// The browser has finished loading.
|
||||
virtual void OnWillFinishLaunching() {}
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "storage/browser/fileapi/isolated_context.h"
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "atom/browser/browser.h"
|
||||
#endif
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
@@ -128,7 +136,11 @@ void CommonWebContentsDelegate::InitWithWebContents(
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::SetOwnerWindow(NativeWindow* owner_window) {
|
||||
content::WebContents* web_contents = GetWebContents();
|
||||
SetOwnerWindow(GetWebContents(), owner_window);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::SetOwnerWindow(
|
||||
content::WebContents* web_contents, NativeWindow* owner_window) {
|
||||
owner_window_ = owner_window->GetWeakPtr();
|
||||
NativeWindowRelay* relay = new NativeWindowRelay(owner_window_);
|
||||
web_contents->SetUserData(relay->key, relay);
|
||||
@@ -355,6 +367,23 @@ void CommonWebContentsDelegate::OnDevToolsAppendToFile(
|
||||
"DevToolsAPI.appendedToURL", &url_value, nullptr, nullptr);
|
||||
}
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
gfx::ImageSkia CommonWebContentsDelegate::GetDevToolsWindowIcon() {
|
||||
if (!owner_window())
|
||||
return gfx::ImageSkia();
|
||||
return static_cast<views::WidgetDelegate*>(static_cast<NativeWindowViews*>(
|
||||
owner_window()))->GetWindowAppIcon();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
void CommonWebContentsDelegate::GetDevToolsWindowWMClass(
|
||||
std::string* name, std::string* class_name) {
|
||||
*class_name = Browser::Get()->GetName();
|
||||
*name = base::StringToLowerASCII(*class_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
||||
// Window is already in fullscreen mode, save the state.
|
||||
if (enter_fullscreen && owner_window_->IsFullscreen()) {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "brightray/browser/default_web_contents_delegate.h"
|
||||
#include "brightray/browser/inspectable_web_contents_impl.h"
|
||||
#include "brightray/browser/inspectable_web_contents_delegate.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view_delegate.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -21,7 +22,8 @@ class WebDialogHelper;
|
||||
|
||||
class CommonWebContentsDelegate
|
||||
: public brightray::DefaultWebContentsDelegate,
|
||||
public brightray::InspectableWebContentsDelegate {
|
||||
public brightray::InspectableWebContentsDelegate,
|
||||
public brightray::InspectableWebContentsViewDelegate {
|
||||
public:
|
||||
CommonWebContentsDelegate();
|
||||
virtual ~CommonWebContentsDelegate();
|
||||
@@ -32,6 +34,8 @@ class CommonWebContentsDelegate
|
||||
|
||||
// Set the window as owner window.
|
||||
void SetOwnerWindow(NativeWindow* owner_window);
|
||||
void SetOwnerWindow(content::WebContents* web_contents,
|
||||
NativeWindow* owner_window);
|
||||
|
||||
// Destroy the managed InspectableWebContents object.
|
||||
void DestroyWebContents();
|
||||
@@ -86,6 +90,15 @@ class CommonWebContentsDelegate
|
||||
void DevToolsRemoveFileSystem(
|
||||
const base::FilePath& file_system_path) override;
|
||||
|
||||
// brightray::InspectableWebContentsViewDelegate:
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
gfx::ImageSkia GetDevToolsWindowIcon() override;
|
||||
#endif
|
||||
#if defined(USE_X11)
|
||||
void GetDevToolsWindowWMClass(
|
||||
std::string* name, std::string* class_name) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Callback for when DevToolsSaveToFile has completed.
|
||||
void OnDevToolsSaveToFile(const std::string& url);
|
||||
|
||||
@@ -13,8 +13,8 @@ app.on('window-all-closed', function() {
|
||||
|
||||
// Parse command line options.
|
||||
var argv = process.argv.slice(1);
|
||||
var option = { file: null, help: null, version: null, webdriver: null };
|
||||
for (var i in argv) {
|
||||
var option = { file: null, help: null, version: null, webdriver: null, modules: [] };
|
||||
for (var i = 0; i < argv.length; i++) {
|
||||
if (argv[i] == '--version' || argv[i] == '-v') {
|
||||
option.version = true;
|
||||
break;
|
||||
@@ -23,6 +23,9 @@ for (var i in argv) {
|
||||
break;
|
||||
} else if (argv[i] == '--test-type=webdriver') {
|
||||
option.webdriver = true;
|
||||
} else if (argv[i] == '--require' || argv[i] == '-r') {
|
||||
option.modules.push(argv[++i]);
|
||||
continue;
|
||||
} else if (argv[i][0] == '-') {
|
||||
continue;
|
||||
} else {
|
||||
@@ -36,244 +39,186 @@ app.once('ready', function() {
|
||||
if (Menu.getApplicationMenu())
|
||||
return;
|
||||
|
||||
var template;
|
||||
var template = [
|
||||
{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Undo',
|
||||
accelerator: 'CmdOrCtrl+Z',
|
||||
role: 'undo'
|
||||
},
|
||||
{
|
||||
label: 'Redo',
|
||||
accelerator: 'Shift+CmdOrCtrl+Z',
|
||||
role: 'redo'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Cut',
|
||||
accelerator: 'CmdOrCtrl+X',
|
||||
role: 'cut'
|
||||
},
|
||||
{
|
||||
label: 'Copy',
|
||||
accelerator: 'CmdOrCtrl+C',
|
||||
role: 'copy'
|
||||
},
|
||||
{
|
||||
label: 'Paste',
|
||||
accelerator: 'CmdOrCtrl+V',
|
||||
role: 'paste'
|
||||
},
|
||||
{
|
||||
label: 'Select All',
|
||||
accelerator: 'CmdOrCtrl+A',
|
||||
role: 'selectall'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
click: function(item, focusedWindow) {
|
||||
if (focusedWindow)
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Full Screen',
|
||||
accelerator: (function() {
|
||||
if (process.platform == 'darwin')
|
||||
return 'Ctrl+Command+F';
|
||||
else
|
||||
return 'F11';
|
||||
})(),
|
||||
click: function(item, focusedWindow) {
|
||||
if (focusedWindow)
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: (function() {
|
||||
if (process.platform == 'darwin')
|
||||
return 'Alt+Command+I';
|
||||
else
|
||||
return 'Ctrl+Shift+I';
|
||||
})(),
|
||||
click: function(item, focusedWindow) {
|
||||
if (focusedWindow)
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Window',
|
||||
role: 'window',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Minimize',
|
||||
accelerator: 'CmdOrCtrl+M',
|
||||
role: 'minimize'
|
||||
},
|
||||
{
|
||||
label: 'Close',
|
||||
accelerator: 'CmdOrCtrl+W',
|
||||
role: 'close'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
||||
},
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
|
||||
},
|
||||
{
|
||||
label: 'Search Issues',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
|
||||
}
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
if (process.platform == 'darwin') {
|
||||
template = [
|
||||
template.unshift({
|
||||
label: 'Electron',
|
||||
submenu: [
|
||||
{
|
||||
label: 'About Electron',
|
||||
role: 'about'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Services',
|
||||
role: 'services',
|
||||
submenu: []
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Hide Electron',
|
||||
accelerator: 'Command+H',
|
||||
role: 'hide'
|
||||
},
|
||||
{
|
||||
label: 'Hide Others',
|
||||
accelerator: 'Command+Shift+H',
|
||||
role: 'hideothers:'
|
||||
},
|
||||
{
|
||||
label: 'Show All',
|
||||
role: 'unhide:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Command+Q',
|
||||
click: function() { app.quit(); }
|
||||
},
|
||||
]
|
||||
});
|
||||
template[3].submenu.push(
|
||||
{
|
||||
label: 'Electron',
|
||||
submenu: [
|
||||
{
|
||||
label: 'About Electron',
|
||||
selector: 'orderFrontStandardAboutPanel:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Services',
|
||||
submenu: []
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Hide Electron',
|
||||
accelerator: 'Command+H',
|
||||
selector: 'hide:'
|
||||
},
|
||||
{
|
||||
label: 'Hide Others',
|
||||
accelerator: 'Command+Shift+H',
|
||||
selector: 'hideOtherApplications:'
|
||||
},
|
||||
{
|
||||
label: 'Show All',
|
||||
selector: 'unhideAllApplications:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Command+Q',
|
||||
click: function() { app.quit(); }
|
||||
},
|
||||
]
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Undo',
|
||||
accelerator: 'Command+Z',
|
||||
selector: 'undo:'
|
||||
},
|
||||
{
|
||||
label: 'Redo',
|
||||
accelerator: 'Shift+Command+Z',
|
||||
selector: 'redo:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Cut',
|
||||
accelerator: 'Command+X',
|
||||
selector: 'cut:'
|
||||
},
|
||||
{
|
||||
label: 'Copy',
|
||||
accelerator: 'Command+C',
|
||||
selector: 'copy:'
|
||||
},
|
||||
{
|
||||
label: 'Paste',
|
||||
accelerator: 'Command+V',
|
||||
selector: 'paste:'
|
||||
},
|
||||
{
|
||||
label: 'Select All',
|
||||
accelerator: 'Command+A',
|
||||
selector: 'selectAll:'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'Command+R',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Full Screen',
|
||||
accelerator: 'Ctrl+Command+F',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: 'Alt+Command+I',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Window',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Minimize',
|
||||
accelerator: 'Command+M',
|
||||
selector: 'performMiniaturize:'
|
||||
},
|
||||
{
|
||||
label: 'Close',
|
||||
accelerator: 'Command+W',
|
||||
selector: 'performClose:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Bring All to Front',
|
||||
selector: 'arrangeInFront:'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
||||
},
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
|
||||
},
|
||||
{
|
||||
label: 'Search Issues',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
|
||||
}
|
||||
]
|
||||
label: 'Bring All to Front',
|
||||
role: 'front'
|
||||
}
|
||||
];
|
||||
} else {
|
||||
template = [
|
||||
{
|
||||
label: '&File',
|
||||
submenu: [
|
||||
{
|
||||
label: '&Open',
|
||||
accelerator: 'Ctrl+O',
|
||||
},
|
||||
{
|
||||
label: '&Close',
|
||||
accelerator: 'Ctrl+W',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.close();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '&View',
|
||||
submenu: [
|
||||
{
|
||||
label: '&Reload',
|
||||
accelerator: 'Ctrl+R',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle &Full Screen',
|
||||
accelerator: 'F11',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle &Developer Tools',
|
||||
accelerator: 'Shift+Ctrl+I',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
||||
},
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
|
||||
},
|
||||
{
|
||||
label: 'Search Issues',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
);
|
||||
}
|
||||
|
||||
var menu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(menu);
|
||||
});
|
||||
|
||||
if (option.modules.length > 0) {
|
||||
require('module')._preloadModules(option.modules);
|
||||
}
|
||||
|
||||
// Start the specified app if there is one specified in command line, otherwise
|
||||
// start the default app.
|
||||
if (option.file && !option.webdriver) {
|
||||
@@ -315,6 +260,7 @@ if (option.file && !option.webdriver) {
|
||||
helpMessage += "A path to an Electron application may be specified. The path must be to \n";
|
||||
helpMessage += "an index.js file or to a folder containing a package.json or index.js file.\n\n";
|
||||
helpMessage += "Options:\n";
|
||||
helpMessage += " -r, --require Module to preload (option can be repeated)";
|
||||
helpMessage += " -h, --help Print this usage message.\n";
|
||||
helpMessage += " -v, --version Print the version.";
|
||||
console.log(helpMessage);
|
||||
|
||||
@@ -32,6 +32,7 @@ getExtensionInfoFromPath = (srcDirectory) ->
|
||||
startPage: page
|
||||
name: manifest.name
|
||||
srcDirectory: srcDirectory
|
||||
exposeExperimentalAPIs: true
|
||||
extensionInfoMap[manifest.name]
|
||||
|
||||
# The loaded extensions cache and its persistent path.
|
||||
|
||||
@@ -43,7 +43,7 @@ createGuest = (embedder, params) ->
|
||||
webViewManager ?= process.atomBinding 'web_view_manager'
|
||||
|
||||
id = getNextInstanceId embedder
|
||||
guest = webContents.create {isGuest: true, embedder}
|
||||
guest = webContents.create {isGuest: true, partition: params.partition, embedder}
|
||||
guestInstances[id] = {guest, embedder}
|
||||
|
||||
# Destroy guest when the embedder is gone or navigated.
|
||||
@@ -84,6 +84,8 @@ createGuest = (embedder, params) ->
|
||||
if params.allowtransparency?
|
||||
@setAllowTransparency params.allowtransparency
|
||||
|
||||
guest.allowPopups = params.allowpopups
|
||||
|
||||
# Dispatch events to embedder.
|
||||
for event in supportedWebViewEvents
|
||||
do (event) ->
|
||||
@@ -115,11 +117,13 @@ attachGuest = (embedder, elementInstanceId, guestInstanceId, params) ->
|
||||
return unless guestInstances[oldGuestInstanceId]?
|
||||
destroyGuest embedder, oldGuestInstanceId
|
||||
|
||||
webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest,
|
||||
nodeIntegration: params.nodeintegration
|
||||
plugins: params.plugins
|
||||
disableWebSecurity: params.disablewebsecurity
|
||||
preloadUrl: params.preload ? ''
|
||||
webPreferences =
|
||||
'guest-instance-id': guestInstanceId
|
||||
'node-integration': params.nodeintegration ? false
|
||||
'plugins': params.plugins
|
||||
'web-security': !params.disablewebsecurity
|
||||
webPreferences['preload-url'] = params.preload if params.preload
|
||||
webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest, webPreferences
|
||||
|
||||
guest.attachParams = params
|
||||
embedderElementsMap[key] = guestInstanceId
|
||||
|
||||
@@ -4,6 +4,17 @@ BrowserWindow = require 'browser-window'
|
||||
|
||||
frameToGuest = {}
|
||||
|
||||
# Merge |options| with the |embedder|'s window's options.
|
||||
mergeBrowserWindowOptions = (embedder, options) ->
|
||||
if embedder.browserWindowOptions?
|
||||
# Inherit the original options if it is a BrowserWindow.
|
||||
options.__proto__ = embedder.browserWindowOptions
|
||||
else
|
||||
# Or only inherit web-preferences if it is a webview.
|
||||
options['web-preferences'] ?= {}
|
||||
options['web-preferences'].__proto__ = embedder.getWebPreferences()
|
||||
options
|
||||
|
||||
# Create a new guest created by |embedder| with |options|.
|
||||
createGuest = (embedder, url, frameName, options) ->
|
||||
guest = frameToGuest[frameName]
|
||||
@@ -40,11 +51,12 @@ createGuest = (embedder, url, frameName, options) ->
|
||||
# Routed window.open messages.
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, args...) ->
|
||||
[url, frameName, options] = args
|
||||
event.sender.emit 'new-window', event, url, frameName, 'new-window'
|
||||
if event.sender.isGuest() or event.defaultPrevented
|
||||
options = mergeBrowserWindowOptions event.sender, options
|
||||
event.sender.emit 'new-window', event, url, frameName, 'new-window', options
|
||||
if (event.sender.isGuest() and not event.sender.allowPopups) or event.defaultPrevented
|
||||
event.returnValue = null
|
||||
else
|
||||
event.returnValue = createGuest event.sender, args...
|
||||
event.returnValue = createGuest event.sender, url, frameName, options
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', (event, guestId) ->
|
||||
BrowserWindow.fromId(guestId)?.destroy()
|
||||
@@ -57,13 +69,19 @@ ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, me
|
||||
if guestContents?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*'
|
||||
guestContents.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', message, targetOrigin
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, message, targetOrigin) ->
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, guestId, message, targetOrigin, sourceOrigin) ->
|
||||
embedder = v8Util.getHiddenValue event.sender, 'embedder'
|
||||
if embedder?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*'
|
||||
embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', message, targetOrigin
|
||||
embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, sourceOrigin
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) ->
|
||||
BrowserWindow.fromId(guestId)?.webContents?[method] args...
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_IS_GUEST_WINDOW', (event) ->
|
||||
event.returnValue = v8Util.getHiddenValue(event.sender, 'embedder') isnt undefined
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_GET_GUEST_ID', (event) ->
|
||||
embedder = v8Util.getHiddenValue event.sender, 'embedder'
|
||||
if embedder?
|
||||
guest = BrowserWindow.fromWebContents event.sender
|
||||
if guest?
|
||||
event.returnValue = guest.id
|
||||
return
|
||||
event.returnValue = null
|
||||
|
||||
@@ -7,14 +7,17 @@ Module = require 'module'
|
||||
# we need to restore it here.
|
||||
process.argv.splice 1, 1
|
||||
|
||||
# Clear search paths.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths')
|
||||
|
||||
# Import common settings.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
|
||||
|
||||
# Add browser/api/lib to module search paths, which contains javascript part of
|
||||
# Electron's built-in libraries.
|
||||
globalPaths = Module.globalPaths
|
||||
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
|
||||
|
||||
# Import common settings.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
|
||||
|
||||
if process.platform is 'win32'
|
||||
# Redirect node's console to use our own implementations, since node can not
|
||||
# handle console output when running as GUI program.
|
||||
@@ -64,7 +67,9 @@ for packagePath in searchPaths
|
||||
catch e
|
||||
continue
|
||||
|
||||
throw new Error("Unable to find a valid app") unless packageJson?
|
||||
unless packageJson?
|
||||
process.nextTick -> process.exit 1
|
||||
throw new Error("Unable to find a valid app")
|
||||
|
||||
# Set application's version.
|
||||
app.setVersion packageJson.version if packageJson.version?
|
||||
|
||||
@@ -106,16 +106,9 @@ ipc.on 'ATOM_BROWSER_GLOBAL', (event, name) ->
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event, guestInstanceId) ->
|
||||
ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event) ->
|
||||
try
|
||||
BrowserWindow = require 'browser-window'
|
||||
if guestInstanceId?
|
||||
guestViewManager = require './guest-view-manager'
|
||||
window = BrowserWindow.fromWebContents guestViewManager.getEmbedder(guestInstanceId)
|
||||
else
|
||||
window = BrowserWindow.fromWebContents event.sender
|
||||
window = BrowserWindow.fromDevToolsWebContents event.sender unless window?
|
||||
event.returnValue = valueToMeta event.sender, window
|
||||
event.returnValue = valueToMeta event.sender, event.sender.getOwnerBrowserWindow()
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
|
||||
@@ -52,12 +52,8 @@
|
||||
- (BOOL)applicationShouldHandleReopen:(NSApplication*)theApplication
|
||||
hasVisibleWindows:(BOOL)flag {
|
||||
atom::Browser* browser = atom::Browser::Get();
|
||||
if (flag) {
|
||||
return YES;
|
||||
} else {
|
||||
browser->ActivateWithNoOpenWindows();
|
||||
return NO;
|
||||
}
|
||||
browser->Activate(static_cast<bool>(flag));
|
||||
return flag;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,12 +15,10 @@
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "base/prefs/pref_service.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
@@ -31,8 +29,6 @@
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "content/public/common/renderer_preferences.h"
|
||||
#include "content/public/common/web_preferences.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/gfx/codec/png_codec.h"
|
||||
@@ -43,31 +39,12 @@
|
||||
#include "ui/gfx/screen.h"
|
||||
#include "ui/gl/gpu_switching_manager.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/gfx/switches.h"
|
||||
#endif
|
||||
|
||||
using content::NavigationEntry;
|
||||
using content::RenderWidgetHostView;
|
||||
using content::RenderWidgetHost;
|
||||
|
||||
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay);
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// Array of available web runtime features.
|
||||
const char* kWebRuntimeFeatures[] = {
|
||||
switches::kExperimentalFeatures,
|
||||
switches::kExperimentalCanvasFeatures,
|
||||
switches::kSubpixelFontScaling,
|
||||
switches::kOverlayScrollbars,
|
||||
switches::kOverlayFullscreenVideo,
|
||||
switches::kSharedWorker,
|
||||
switches::kPageVisibility,
|
||||
};
|
||||
|
||||
// Convert draggable regions in raw format to SkRegion format. Caller is
|
||||
// responsible for deleting the returned SkRegion instance.
|
||||
scoped_ptr<SkRegion> DraggableRegionsToSkRegion(
|
||||
@@ -91,21 +68,17 @@ NativeWindow::NativeWindow(
|
||||
const mate::Dictionary& options)
|
||||
: content::WebContentsObserver(inspectable_web_contents->GetWebContents()),
|
||||
has_frame_(true),
|
||||
force_using_draggable_region_(false),
|
||||
transparent_(false),
|
||||
enable_larger_than_screen_(false),
|
||||
is_closed_(false),
|
||||
node_integration_(true),
|
||||
has_dialog_attached_(false),
|
||||
zoom_factor_(1.0),
|
||||
aspect_ratio_(0.0),
|
||||
inspectable_web_contents_(inspectable_web_contents),
|
||||
weak_factory_(this) {
|
||||
inspectable_web_contents->GetView()->SetDelegate(this);
|
||||
|
||||
options.Get(switches::kFrame, &has_frame_);
|
||||
options.Get(switches::kTransparent, &transparent_);
|
||||
options.Get(switches::kEnableLargerThanScreen, &enable_larger_than_screen_);
|
||||
options.Get(switches::kNodeIntegration, &node_integration_);
|
||||
|
||||
// Tell the content module to initialize renderer widget with transparent
|
||||
// mode.
|
||||
@@ -114,25 +87,6 @@ NativeWindow::NativeWindow(
|
||||
// Read icon before window is created.
|
||||
options.Get(switches::kIcon, &icon_);
|
||||
|
||||
// The "preload" option must be absolute path.
|
||||
if (options.Get(switches::kPreloadScript, &preload_script_) &&
|
||||
!preload_script_.IsAbsolute()) {
|
||||
LOG(ERROR) << "Path of \"preload\" script must be absolute.";
|
||||
preload_script_.clear();
|
||||
}
|
||||
|
||||
// Be compatible with old API of "node-integration" option.
|
||||
std::string old_string_token;
|
||||
if (options.Get(switches::kNodeIntegration, &old_string_token) &&
|
||||
old_string_token != "disable")
|
||||
node_integration_ = true;
|
||||
|
||||
// Read the web preferences.
|
||||
options.Get(switches::kWebPreferences, &web_preferences_);
|
||||
|
||||
// Read the zoom factor before any navigation.
|
||||
options.Get(switches::kZoomFactor, &zoom_factor_);
|
||||
|
||||
WindowList::AddWindow(this);
|
||||
}
|
||||
|
||||
@@ -241,38 +195,6 @@ bool NativeWindow::IsDocumentEdited() {
|
||||
void NativeWindow::SetMenu(ui::MenuModel* menu) {
|
||||
}
|
||||
|
||||
void NativeWindow::ShowDefinitionForSelection() {
|
||||
NOTIMPLEMENTED();
|
||||
}
|
||||
|
||||
void NativeWindow::SetAutoHideMenuBar(bool auto_hide) {
|
||||
}
|
||||
|
||||
bool NativeWindow::IsMenuBarAutoHide() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void NativeWindow::SetMenuBarVisibility(bool visible) {
|
||||
}
|
||||
|
||||
bool NativeWindow::IsMenuBarVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
double NativeWindow::GetAspectRatio() {
|
||||
return aspect_ratio_;
|
||||
}
|
||||
|
||||
gfx::Size NativeWindow::GetAspectRatioExtraSize() {
|
||||
return aspect_ratio_extraSize_;
|
||||
}
|
||||
|
||||
void NativeWindow::SetAspectRatio(double aspect_ratio,
|
||||
const gfx::Size& extra_size) {
|
||||
aspect_ratio_ = aspect_ratio;
|
||||
aspect_ratio_extraSize_ = extra_size;
|
||||
}
|
||||
|
||||
bool NativeWindow::HasModalDialog() {
|
||||
return has_dialog_attached_;
|
||||
}
|
||||
@@ -290,6 +212,10 @@ bool NativeWindow::IsWebViewFocused() {
|
||||
return host_view && host_view->HasFocus();
|
||||
}
|
||||
|
||||
bool NativeWindow::IsDevToolsFocused() {
|
||||
return inspectable_web_contents_->GetView()->IsDevToolsViewFocused();
|
||||
}
|
||||
|
||||
void NativeWindow::CapturePage(const gfx::Rect& rect,
|
||||
const CapturePageCallback& callback) {
|
||||
const auto view = web_contents()->GetRenderWidgetHostView();
|
||||
@@ -323,6 +249,38 @@ void NativeWindow::CapturePage(const gfx::Rect& rect,
|
||||
kBGRA_8888_SkColorType);
|
||||
}
|
||||
|
||||
void NativeWindow::ShowDefinitionForSelection() {
|
||||
NOTIMPLEMENTED();
|
||||
}
|
||||
|
||||
void NativeWindow::SetAutoHideMenuBar(bool auto_hide) {
|
||||
}
|
||||
|
||||
bool NativeWindow::IsMenuBarAutoHide() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void NativeWindow::SetMenuBarVisibility(bool visible) {
|
||||
}
|
||||
|
||||
bool NativeWindow::IsMenuBarVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
double NativeWindow::GetAspectRatio() {
|
||||
return aspect_ratio_;
|
||||
}
|
||||
|
||||
gfx::Size NativeWindow::GetAspectRatioExtraSize() {
|
||||
return aspect_ratio_extraSize_;
|
||||
}
|
||||
|
||||
void NativeWindow::SetAspectRatio(double aspect_ratio,
|
||||
const gfx::Size& extra_size) {
|
||||
aspect_ratio_ = aspect_ratio;
|
||||
aspect_ratio_extraSize_ = extra_size;
|
||||
}
|
||||
|
||||
void NativeWindow::RequestToClosePage() {
|
||||
bool prevent_default = false;
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver,
|
||||
@@ -381,81 +339,6 @@ void NativeWindow::RendererResponsive(content::WebContents* source) {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive());
|
||||
}
|
||||
|
||||
void NativeWindow::AppendExtraCommandLineSwitches(
|
||||
base::CommandLine* command_line) {
|
||||
// Append --node-integration to renderer process.
|
||||
command_line->AppendSwitchASCII(switches::kNodeIntegration,
|
||||
node_integration_ ? "true" : "false");
|
||||
|
||||
// Append --preload.
|
||||
if (!preload_script_.empty())
|
||||
command_line->AppendSwitchPath(switches::kPreloadScript, preload_script_);
|
||||
|
||||
// Append --zoom-factor.
|
||||
if (zoom_factor_ != 1.0)
|
||||
command_line->AppendSwitchASCII(switches::kZoomFactor,
|
||||
base::DoubleToString(zoom_factor_));
|
||||
|
||||
if (web_preferences_.IsEmpty())
|
||||
return;
|
||||
|
||||
bool b;
|
||||
#if defined(OS_WIN)
|
||||
// Check if DirectWrite is disabled.
|
||||
if (web_preferences_.Get(switches::kDirectWrite, &b) && !b)
|
||||
command_line->AppendSwitch(::switches::kDisableDirectWrite);
|
||||
#endif
|
||||
|
||||
// Check if plugins are enabled.
|
||||
if (web_preferences_.Get("plugins", &b) && b)
|
||||
command_line->AppendSwitch(switches::kEnablePlugins);
|
||||
|
||||
// This set of options are not availabe in WebPreferences, so we have to pass
|
||||
// them via command line and enable them in renderer procss.
|
||||
for (size_t i = 0; i < arraysize(kWebRuntimeFeatures); ++i) {
|
||||
const char* feature = kWebRuntimeFeatures[i];
|
||||
if (web_preferences_.Get(feature, &b))
|
||||
command_line->AppendSwitchASCII(feature, b ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindow::OverrideWebkitPrefs(content::WebPreferences* prefs) {
|
||||
if (web_preferences_.IsEmpty())
|
||||
return;
|
||||
|
||||
bool b;
|
||||
std::vector<base::FilePath> list;
|
||||
if (web_preferences_.Get("javascript", &b))
|
||||
prefs->javascript_enabled = b;
|
||||
if (web_preferences_.Get("images", &b))
|
||||
prefs->images_enabled = b;
|
||||
if (web_preferences_.Get("java", &b))
|
||||
prefs->java_enabled = b;
|
||||
if (web_preferences_.Get("text-areas-are-resizable", &b))
|
||||
prefs->text_areas_are_resizable = b;
|
||||
if (web_preferences_.Get("webgl", &b))
|
||||
prefs->experimental_webgl_enabled = b;
|
||||
if (web_preferences_.Get("webaudio", &b))
|
||||
prefs->webaudio_enabled = b;
|
||||
if (web_preferences_.Get("web-security", &b)) {
|
||||
prefs->web_security_enabled = b;
|
||||
prefs->allow_displaying_insecure_content = !b;
|
||||
prefs->allow_running_insecure_content = !b;
|
||||
}
|
||||
if (web_preferences_.Get("allow-displaying-insecure-content", &b))
|
||||
prefs->allow_displaying_insecure_content = b;
|
||||
if (web_preferences_.Get("allow-running-insecure-content", &b))
|
||||
prefs->allow_running_insecure_content = b;
|
||||
if (web_preferences_.Get("extra-plugin-dirs", &list)) {
|
||||
if (content::PluginService::GetInstance()->NPAPIPluginsSupported()) {
|
||||
for (size_t i = 0; i < list.size(); ++i)
|
||||
content::PluginService::GetInstance()->AddExtraPluginDir(list[i]);
|
||||
} else {
|
||||
LOG(WARNING) << "NPAPI plugins not supported on this platform";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowClosed() {
|
||||
if (is_closed_)
|
||||
return;
|
||||
@@ -528,18 +411,6 @@ void NativeWindow::NotifyWindowExecuteWindowsCommand(
|
||||
OnExecuteWindowsCommand(command));
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsFocused() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus());
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsOpened() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened());
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsClosed() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed());
|
||||
}
|
||||
|
||||
void NativeWindow::RenderViewCreated(
|
||||
content::RenderViewHost* render_view_host) {
|
||||
if (!transparent_)
|
||||
@@ -584,7 +455,7 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
|
||||
void NativeWindow::UpdateDraggableRegions(
|
||||
const std::vector<DraggableRegion>& regions) {
|
||||
// Draggable region is not supported for non-frameless window.
|
||||
if (has_frame_)
|
||||
if (has_frame_ && !force_using_draggable_region_)
|
||||
return;
|
||||
draggable_region_ = DraggableRegionsToSkRegion(regions);
|
||||
}
|
||||
|
||||
@@ -15,27 +15,21 @@
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view_delegate.h"
|
||||
#include "base/supports_user_data.h"
|
||||
#include "content/public/browser/readback_types.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
#include "native_mate/persistent_dictionary.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
#include "ui/gfx/image/image_skia.h"
|
||||
|
||||
class SkRegion;
|
||||
|
||||
namespace base {
|
||||
class CommandLine;
|
||||
}
|
||||
|
||||
namespace brightray {
|
||||
class InspectableWebContents;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
struct NativeWebKeyboardEvent;
|
||||
struct WebPreferences;
|
||||
}
|
||||
|
||||
namespace gfx {
|
||||
@@ -56,8 +50,8 @@ namespace atom {
|
||||
|
||||
struct DraggableRegion;
|
||||
|
||||
class NativeWindow : public content::WebContentsObserver,
|
||||
public brightray::InspectableWebContentsViewDelegate {
|
||||
class NativeWindow : public base::SupportsUserData,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
using CapturePageCallback = base::Callback<void(const SkBitmap& bitmap)>;
|
||||
|
||||
@@ -154,6 +148,7 @@ class NativeWindow : public content::WebContentsObserver,
|
||||
virtual void FocusOnWebView();
|
||||
virtual void BlurWebView();
|
||||
virtual bool IsWebViewFocused();
|
||||
virtual bool IsDevToolsFocused();
|
||||
|
||||
// Captures the page with |rect|, |callback| would be called when capturing is
|
||||
// done.
|
||||
@@ -189,10 +184,6 @@ class NativeWindow : public content::WebContentsObserver,
|
||||
content::WebContents*,
|
||||
const content::NativeWebKeyboardEvent& event) {}
|
||||
|
||||
// Called when renderer process is going to be started.
|
||||
void AppendExtraCommandLineSwitches(base::CommandLine* command_line);
|
||||
void OverrideWebkitPrefs(content::WebPreferences* prefs);
|
||||
|
||||
// Public API used by platform-dependent delegates and observers to send UI
|
||||
// related notifications.
|
||||
void NotifyWindowClosed();
|
||||
@@ -228,6 +219,13 @@ class NativeWindow : public content::WebContentsObserver,
|
||||
bool enable_larger_than_screen() const { return enable_larger_than_screen_; }
|
||||
gfx::ImageSkia icon() const { return icon_; }
|
||||
|
||||
bool force_using_draggable_region() const {
|
||||
return force_using_draggable_region_;
|
||||
}
|
||||
void set_force_using_draggable_region(bool force) {
|
||||
force_using_draggable_region_ = true;
|
||||
}
|
||||
|
||||
void set_has_dialog_attached(bool has_dialog_attached) {
|
||||
has_dialog_attached_ = has_dialog_attached;
|
||||
}
|
||||
@@ -236,11 +234,6 @@ class NativeWindow : public content::WebContentsObserver,
|
||||
NativeWindow(brightray::InspectableWebContents* inspectable_web_contents,
|
||||
const mate::Dictionary& options);
|
||||
|
||||
// brightray::InspectableWebContentsViewDelegate:
|
||||
void DevToolsFocused() override;
|
||||
void DevToolsOpened() override;
|
||||
void DevToolsClosed() override;
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
|
||||
void BeforeUnloadDialogCancelled() override;
|
||||
@@ -266,6 +259,9 @@ class NativeWindow : public content::WebContentsObserver,
|
||||
// Whether window has standard frame.
|
||||
bool has_frame_;
|
||||
|
||||
// Force the window to be aware of draggable regions.
|
||||
bool force_using_draggable_region_;
|
||||
|
||||
// Whether window is transparent.
|
||||
bool transparent_;
|
||||
|
||||
@@ -282,9 +278,6 @@ class NativeWindow : public content::WebContentsObserver,
|
||||
// The windows has been closed.
|
||||
bool is_closed_;
|
||||
|
||||
// Whether node integration is enabled.
|
||||
bool node_integration_;
|
||||
|
||||
// There is a dialog that has been attached to window.
|
||||
bool has_dialog_attached_;
|
||||
|
||||
@@ -292,15 +285,6 @@ class NativeWindow : public content::WebContentsObserver,
|
||||
// it should be cancelled when we can prove that the window is responsive.
|
||||
base::CancelableClosure window_unresposive_closure_;
|
||||
|
||||
// Web preferences.
|
||||
mate::PersistentDictionary web_preferences_;
|
||||
|
||||
// The script to load before page's JavaScript starts to run.
|
||||
base::FilePath preload_script_;
|
||||
|
||||
// Page's default zoom factor.
|
||||
double zoom_factor_;
|
||||
|
||||
// Used to maintain the aspect ratio of a view which is inside of the
|
||||
// content view.
|
||||
double aspect_ratio_;
|
||||
@@ -310,14 +294,13 @@ class NativeWindow : public content::WebContentsObserver,
|
||||
brightray::InspectableWebContents* inspectable_web_contents_;
|
||||
|
||||
// Observers of this window.
|
||||
ObserverList<NativeWindowObserver> observers_;
|
||||
base::ObserverList<NativeWindowObserver> observers_;
|
||||
|
||||
base::WeakPtrFactory<NativeWindow> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NativeWindow);
|
||||
};
|
||||
|
||||
|
||||
// This class provides a hook to get a NativeWindow from a WebContents.
|
||||
class NativeWindowRelay :
|
||||
public content::WebContentsUserData<NativeWindowRelay> {
|
||||
|
||||
@@ -351,11 +351,20 @@ NativeWindowMac::NativeWindowMac(
|
||||
bool useStandardWindow = true;
|
||||
options.Get(switches::kStandardWindow, &useStandardWindow);
|
||||
|
||||
// New title bar styles are available in Yosemite or newer
|
||||
std::string titleBarStyle;
|
||||
if (base::mac::IsOSYosemiteOrLater())
|
||||
options.Get(switches::kTitleBarStyle, &titleBarStyle);
|
||||
|
||||
NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask |
|
||||
NSMiniaturizableWindowMask | NSResizableWindowMask;
|
||||
if (!useStandardWindow || transparent() || !has_frame()) {
|
||||
styleMask |= NSTexturedBackgroundWindowMask;
|
||||
}
|
||||
if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) {
|
||||
styleMask |= NSFullSizeContentViewWindowMask;
|
||||
styleMask |= NSUnifiedTitleAndToolbarWindowMask;
|
||||
}
|
||||
|
||||
window_.reset([[AtomNSWindow alloc]
|
||||
initWithContentRect:cocoa_bounds
|
||||
@@ -382,6 +391,20 @@ NativeWindowMac::NativeWindowMac(
|
||||
// We will manage window's lifetime ourselves.
|
||||
[window_ setReleasedWhenClosed:NO];
|
||||
|
||||
// Hide the title bar.
|
||||
if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) {
|
||||
[window_ setTitlebarAppearsTransparent:YES];
|
||||
[window_ setTitleVisibility:NSWindowTitleHidden];
|
||||
if (titleBarStyle == "hidden-inset") {
|
||||
base::scoped_nsobject<NSToolbar> toolbar(
|
||||
[[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]);
|
||||
[toolbar setShowsBaselineSeparator:NO];
|
||||
[window_ setToolbar:toolbar];
|
||||
}
|
||||
// We should be aware of draggable regions when using hidden titlebar.
|
||||
set_force_using_draggable_region(true);
|
||||
}
|
||||
|
||||
// On OS X the initial window size doesn't include window frame.
|
||||
bool use_content_size = false;
|
||||
options.Get(switches::kUseContentSize, &use_content_size);
|
||||
@@ -411,6 +434,11 @@ NativeWindowMac::NativeWindowMac(
|
||||
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
|
||||
InstallView();
|
||||
|
||||
// Install the DraggableRegionView if it is forced to use draggable regions
|
||||
// for normal window.
|
||||
if (has_frame() && force_using_draggable_region())
|
||||
InstallDraggableRegionView();
|
||||
}
|
||||
|
||||
NativeWindowMac::~NativeWindowMac() {
|
||||
|
||||
@@ -55,11 +55,6 @@ class NativeWindowObserver {
|
||||
virtual void OnWindowEnterHtmlFullScreen() {}
|
||||
virtual void OnWindowLeaveHtmlFullScreen() {}
|
||||
|
||||
// Redirect devtools events.
|
||||
virtual void OnDevToolsFocus() {}
|
||||
virtual void OnDevToolsOpened() {}
|
||||
virtual void OnDevToolsClosed() {}
|
||||
|
||||
// Called when renderer is hung.
|
||||
virtual void OnRendererUnresponsive() {}
|
||||
|
||||
|
||||
@@ -169,9 +169,6 @@ NativeWindowViews::NativeWindowViews(
|
||||
menu_bar_autohide_(false),
|
||||
menu_bar_visible_(false),
|
||||
menu_bar_alt_pressed_(false),
|
||||
#if defined(OS_WIN)
|
||||
is_minimized_(false),
|
||||
#endif
|
||||
keyboard_event_handler_(new views::UnhandledKeyboardEventHandler),
|
||||
use_content_size_(false),
|
||||
resizable_(true) {
|
||||
@@ -228,6 +225,9 @@ NativeWindowViews::NativeWindowViews(
|
||||
|
||||
window_->Init(params);
|
||||
|
||||
bool fullscreen = false;
|
||||
options.Get(switches::kFullscreen, &fullscreen);
|
||||
|
||||
#if defined(USE_X11)
|
||||
// Start monitoring window states.
|
||||
window_state_watcher_.reset(new WindowStateWatcher(this));
|
||||
@@ -253,8 +253,7 @@ NativeWindowViews::NativeWindowViews(
|
||||
}
|
||||
|
||||
// Before the window is mapped, there is no SHOW_FULLSCREEN_STATE.
|
||||
bool fullscreen = false;
|
||||
if (options.Get(switches::kFullscreen, & fullscreen) && fullscreen) {
|
||||
if (fullscreen) {
|
||||
state_atom_list.push_back(GetAtom("_NET_WM_STATE_FULLSCREEN"));
|
||||
}
|
||||
|
||||
@@ -278,6 +277,12 @@ NativeWindowViews::NativeWindowViews(
|
||||
bounds = ContentBoundsToWindowBounds(bounds);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Save initial window state.
|
||||
if (fullscreen)
|
||||
last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
|
||||
else
|
||||
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
||||
|
||||
if (!has_frame()) {
|
||||
// Set Window style so that we get a minimize and maximize animation when
|
||||
// frameless.
|
||||
@@ -346,7 +351,7 @@ void NativeWindowViews::ShowInactive() {
|
||||
}
|
||||
|
||||
void NativeWindowViews::Hide() {
|
||||
window_->Hide();
|
||||
web_contents()->WasHidden();
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsVisible() {
|
||||
@@ -388,11 +393,16 @@ bool NativeWindowViews::IsMinimized() {
|
||||
void NativeWindowViews::SetFullScreen(bool fullscreen) {
|
||||
#if defined(OS_WIN)
|
||||
// There is no native fullscreen state on Windows.
|
||||
window_->SetFullscreen(fullscreen);
|
||||
if (fullscreen)
|
||||
if (fullscreen) {
|
||||
last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
|
||||
NotifyWindowEnterFullScreen();
|
||||
else
|
||||
} else {
|
||||
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
||||
NotifyWindowLeaveFullScreen();
|
||||
}
|
||||
// We set the new value after notifying, so we can handle the size event
|
||||
// correctly.
|
||||
window_->SetFullscreen(fullscreen);
|
||||
#else
|
||||
if (IsVisible())
|
||||
window_->SetFullscreen(fullscreen);
|
||||
@@ -804,48 +814,63 @@ void NativeWindowViews::OnWidgetMove() {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
bool NativeWindowViews::ExecuteWindowsCommand(int command_id) {
|
||||
// Windows uses the 4 lower order bits of |command_id| for type-specific
|
||||
// information so we must exclude this when comparing.
|
||||
static const int sc_mask = 0xFFF0;
|
||||
if ((command_id & sc_mask) == SC_MINIMIZE) {
|
||||
NotifyWindowMinimize();
|
||||
is_minimized_ = true;
|
||||
} else if ((command_id & sc_mask) == SC_RESTORE) {
|
||||
if (is_minimized_)
|
||||
NotifyWindowRestore();
|
||||
else
|
||||
NotifyWindowUnmaximize();
|
||||
is_minimized_ = false;
|
||||
} else if ((command_id & sc_mask) == SC_MAXIMIZE) {
|
||||
NotifyWindowMaximize();
|
||||
} else {
|
||||
std::string command = AppCommandToString(command_id);
|
||||
NotifyWindowExecuteWindowsCommand(command);
|
||||
}
|
||||
std::string command = AppCommandToString(command_id);
|
||||
NotifyWindowExecuteWindowsCommand(command);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
gfx::ImageSkia NativeWindowViews::GetDevToolsWindowIcon() {
|
||||
return GetWindowAppIcon();
|
||||
}
|
||||
|
||||
#if defined(USE_X11)
|
||||
void NativeWindowViews::GetDevToolsWindowWMClass(
|
||||
std::string* name, std::string* class_name) {
|
||||
*class_name = Browser::Get()->GetName();
|
||||
*name = base::StringToLowerASCII(*class_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
bool NativeWindowViews::PreHandleMSG(
|
||||
UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) {
|
||||
// Handle thumbar button click message.
|
||||
if (message == WM_COMMAND && HIWORD(w_param) == THBN_CLICKED)
|
||||
return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param));
|
||||
else
|
||||
return false;
|
||||
switch (message) {
|
||||
case WM_COMMAND:
|
||||
// Handle thumbar button click message.
|
||||
if (HIWORD(w_param) == THBN_CLICKED)
|
||||
return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param));
|
||||
return false;
|
||||
case WM_SIZE:
|
||||
// Handle window state change.
|
||||
HandleSizeEvent(w_param, l_param);
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
|
||||
// Here we handle the WM_SIZE event in order to figure out what is the current
|
||||
// window state and notify the user accordingly.
|
||||
switch (w_param) {
|
||||
case SIZE_MAXIMIZED:
|
||||
last_window_state_ = ui::SHOW_STATE_MAXIMIZED;
|
||||
NotifyWindowMaximize();
|
||||
break;
|
||||
case SIZE_MINIMIZED:
|
||||
last_window_state_ = ui::SHOW_STATE_MINIMIZED;
|
||||
NotifyWindowMinimize();
|
||||
break;
|
||||
case SIZE_RESTORED:
|
||||
if (last_window_state_ == ui::SHOW_STATE_NORMAL)
|
||||
return;
|
||||
|
||||
switch (last_window_state_) {
|
||||
case ui::SHOW_STATE_MAXIMIZED:
|
||||
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
||||
NotifyWindowUnmaximize();
|
||||
break;
|
||||
case ui::SHOW_STATE_MINIMIZED:
|
||||
if (IsFullscreen()) {
|
||||
last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
|
||||
NotifyWindowEnterFullScreen();
|
||||
} else {
|
||||
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
||||
NotifyWindowRestore();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -880,9 +905,6 @@ void NativeWindowViews::HandleKeyboardEvent(
|
||||
// When a single Alt is pressed:
|
||||
menu_bar_alt_pressed_ = true;
|
||||
} else if (event.type == blink::WebInputEvent::KeyUp && IsAltKey(event) &&
|
||||
#if defined(USE_X11)
|
||||
event.modifiers == 0 &&
|
||||
#endif
|
||||
menu_bar_alt_pressed_) {
|
||||
// When a single Alt is released right after a Alt is pressed:
|
||||
menu_bar_alt_pressed_ = false;
|
||||
|
||||
@@ -131,17 +131,12 @@ class NativeWindowViews : public NativeWindow,
|
||||
bool ExecuteWindowsCommand(int command_id) override;
|
||||
#endif
|
||||
|
||||
// brightray::InspectableWebContentsViewDelegate:
|
||||
gfx::ImageSkia GetDevToolsWindowIcon() override;
|
||||
#if defined(USE_X11)
|
||||
void GetDevToolsWindowWMClass(
|
||||
std::string* name, std::string* class_name) override;
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// MessageHandlerDelegate:
|
||||
bool PreHandleMSG(
|
||||
UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) override;
|
||||
|
||||
void HandleSizeEvent(WPARAM w_param, LPARAM l_param);
|
||||
#endif
|
||||
|
||||
// NativeWindow:
|
||||
@@ -178,9 +173,9 @@ class NativeWindowViews : public NativeWindow,
|
||||
#elif defined(OS_WIN)
|
||||
// Weak ref.
|
||||
AtomDesktopWindowTreeHostWin* atom_desktop_window_tree_host_win_;
|
||||
// Records window was whether restored from minimized state or maximized
|
||||
// state.
|
||||
bool is_minimized_;
|
||||
|
||||
ui::WindowShowState last_window_state_;
|
||||
|
||||
// In charge of running taskbar related APIs.
|
||||
TaskbarHost taskbar_host_;
|
||||
#endif
|
||||
|
||||
@@ -172,7 +172,7 @@ bool URLRequestAsarJob::IsRedirectResponse(GURL* location,
|
||||
#if defined(OS_WIN)
|
||||
// Follow a Windows shortcut.
|
||||
// We just resolve .lnk file, ignore others.
|
||||
if (!LowerCaseEqualsASCII(file_path_.Extension(), ".lnk"))
|
||||
if (!base::LowerCaseEqualsASCII(file_path_.Extension(), ".lnk"))
|
||||
return false;
|
||||
|
||||
base::FilePath new_path = file_path_;
|
||||
@@ -193,7 +193,7 @@ bool URLRequestAsarJob::IsRedirectResponse(GURL* location,
|
||||
|
||||
net::Filter* URLRequestAsarJob::SetupFilter() const {
|
||||
// Bug 9936 - .svgz files needs to be decompressed.
|
||||
return LowerCaseEqualsASCII(file_path_.Extension(), ".svgz")
|
||||
return base::LowerCaseEqualsASCII(file_path_.Extension(), ".svgz")
|
||||
? net::Filter::GZipFactory() : NULL;
|
||||
}
|
||||
|
||||
@@ -265,8 +265,7 @@ void URLRequestAsarJob::DidOpen(int result) {
|
||||
}
|
||||
|
||||
if (type_ == TYPE_ASAR) {
|
||||
int rv = stream_->Seek(base::File::FROM_BEGIN,
|
||||
file_info_.offset,
|
||||
int rv = stream_->Seek(file_info_.offset,
|
||||
base::Bind(&URLRequestAsarJob::DidSeek,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
if (rv != net::ERR_IO_PENDING) {
|
||||
@@ -285,8 +284,7 @@ void URLRequestAsarJob::DidOpen(int result) {
|
||||
byte_range_.first_byte_position() + 1;
|
||||
|
||||
if (remaining_bytes_ > 0 && byte_range_.first_byte_position() != 0) {
|
||||
int rv = stream_->Seek(base::File::FROM_BEGIN,
|
||||
byte_range_.first_byte_position(),
|
||||
int rv = stream_->Seek(byte_range_.first_byte_position(),
|
||||
base::Bind(&URLRequestAsarJob::DidSeek,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
if (rv != net::ERR_IO_PENDING) {
|
||||
|
||||
@@ -46,7 +46,7 @@ class JsAsker : public RequestJob {
|
||||
// Called by |CustomProtocolHandler| to store handler related information.
|
||||
void SetHandlerInfo(
|
||||
v8::Isolate* isolate,
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
|
||||
net::URLRequestContextGetter* request_context_getter,
|
||||
const JavaScriptHandler& handler) {
|
||||
isolate_ = isolate;
|
||||
request_context_getter_ = request_context_getter;
|
||||
@@ -57,7 +57,7 @@ class JsAsker : public RequestJob {
|
||||
virtual void StartAsync(scoped_ptr<base::Value> options) = 0;
|
||||
|
||||
net::URLRequestContextGetter* request_context_getter() const {
|
||||
return request_context_getter_.get();
|
||||
return request_context_getter_;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -89,7 +89,7 @@ class JsAsker : public RequestJob {
|
||||
}
|
||||
|
||||
v8::Isolate* isolate_;
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
JavaScriptHandler handler_;
|
||||
|
||||
base::WeakPtrFactory<JsAsker> weak_factory_;
|
||||
|
||||
@@ -6,13 +6,15 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "net/base/net_errors.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
URLRequestBufferJob::URLRequestBufferJob(
|
||||
net::URLRequest* request, net::NetworkDelegate* network_delegate)
|
||||
: JsAsker<net::URLRequestSimpleJob>(request, network_delegate) {
|
||||
: JsAsker<net::URLRequestSimpleJob>(request, network_delegate),
|
||||
status_code_(net::HTTP_NOT_IMPLEMENTED) {
|
||||
}
|
||||
|
||||
void URLRequestBufferJob::StartAsync(scoped_ptr<base::Value> options) {
|
||||
@@ -36,9 +38,28 @@ void URLRequestBufferJob::StartAsync(scoped_ptr<base::Value> options) {
|
||||
data_ = new base::RefCountedBytes(
|
||||
reinterpret_cast<const unsigned char*>(binary->GetBuffer()),
|
||||
binary->GetSize());
|
||||
status_code_ = net::HTTP_OK;
|
||||
net::URLRequestSimpleJob::Start();
|
||||
}
|
||||
|
||||
void URLRequestBufferJob::GetResponseInfo(net::HttpResponseInfo* info) {
|
||||
std::string status("HTTP/1.1 ");
|
||||
status.append(base::IntToString(status_code_));
|
||||
status.append(" ");
|
||||
status.append(net::GetHttpReasonPhrase(status_code_));
|
||||
status.append("\0\0", 2);
|
||||
net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
|
||||
|
||||
if (!mime_type_.empty()) {
|
||||
std::string content_type_header(net::HttpRequestHeaders::kContentType);
|
||||
content_type_header.append(": ");
|
||||
content_type_header.append(mime_type_);
|
||||
headers->AddHeader(content_type_header);
|
||||
}
|
||||
|
||||
info->headers = headers;
|
||||
}
|
||||
|
||||
int URLRequestBufferJob::GetRefCountedData(
|
||||
std::string* mime_type,
|
||||
std::string* charset,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "atom/browser/net/js_asker.h"
|
||||
#include "base/memory/ref_counted_memory.h"
|
||||
#include "net/http/http_status_code.h"
|
||||
#include "net/url_request/url_request_simple_job.h"
|
||||
|
||||
namespace atom {
|
||||
@@ -20,6 +21,9 @@ class URLRequestBufferJob : public JsAsker<net::URLRequestSimpleJob> {
|
||||
// JsAsker:
|
||||
void StartAsync(scoped_ptr<base::Value> options) override;
|
||||
|
||||
// URLRequestJob:
|
||||
void GetResponseInfo(net::HttpResponseInfo* info) override;
|
||||
|
||||
// URLRequestSimpleJob:
|
||||
int GetRefCountedData(std::string* mime_type,
|
||||
std::string* charset,
|
||||
@@ -30,6 +34,7 @@ class URLRequestBufferJob : public JsAsker<net::URLRequestSimpleJob> {
|
||||
std::string mime_type_;
|
||||
std::string charset_;
|
||||
scoped_refptr<base::RefCountedBytes> data_;
|
||||
net::HttpStatusCode status_code_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(URLRequestBufferJob);
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace {
|
||||
|
||||
// Convert string to RequestType.
|
||||
net::URLFetcher::RequestType GetRequestType(const std::string& raw) {
|
||||
std::string method = StringToUpperASCII(raw);
|
||||
std::string method = base::StringToUpperASCII(raw);
|
||||
if (method.empty() || method == "GET")
|
||||
return net::URLFetcher::GET;
|
||||
else if (method == "POST")
|
||||
|
||||
@@ -28,6 +28,20 @@ void URLRequestStringJob::StartAsync(scoped_ptr<base::Value> options) {
|
||||
net::URLRequestSimpleJob::Start();
|
||||
}
|
||||
|
||||
void URLRequestStringJob::GetResponseInfo(net::HttpResponseInfo* info) {
|
||||
std::string status("HTTP/1.1 200 OK");
|
||||
net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
|
||||
|
||||
if (!mime_type_.empty()) {
|
||||
std::string content_type_header(net::HttpRequestHeaders::kContentType);
|
||||
content_type_header.append(": ");
|
||||
content_type_header.append(mime_type_);
|
||||
headers->AddHeader(content_type_header);
|
||||
}
|
||||
|
||||
info->headers = headers;
|
||||
}
|
||||
|
||||
int URLRequestStringJob::GetData(
|
||||
std::string* mime_type,
|
||||
std::string* charset,
|
||||
|
||||
@@ -19,6 +19,9 @@ class URLRequestStringJob : public JsAsker<net::URLRequestSimpleJob> {
|
||||
// JsAsker:
|
||||
void StartAsync(scoped_ptr<base::Value> options) override;
|
||||
|
||||
// URLRequestJob:
|
||||
void GetResponseInfo(net::HttpResponseInfo* info) override;
|
||||
|
||||
// URLRequestSimpleJob:
|
||||
int GetData(std::string* mime_type,
|
||||
std::string* charset,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>atom.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.31.0</string>
|
||||
<string>0.33.5</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.8.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
|
||||
@@ -56,8 +56,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,31,0,0
|
||||
PRODUCTVERSION 0,31,0,0
|
||||
FILEVERSION 0,33,5,0
|
||||
PRODUCTVERSION 0,33,5,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -74,12 +74,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "0.31.0"
|
||||
VALUE "FileVersion", "0.33.5"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "0.31.0"
|
||||
VALUE "ProductVersion", "0.33.5"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/keyboad_util.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_split.h"
|
||||
@@ -17,74 +18,6 @@
|
||||
|
||||
namespace accelerator_util {
|
||||
|
||||
namespace {
|
||||
|
||||
// Return key code of the char.
|
||||
ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted) {
|
||||
*shifted = false;
|
||||
switch (c) {
|
||||
case 8: case 0x7F: return ui::VKEY_BACK;
|
||||
case 9: return ui::VKEY_TAB;
|
||||
case 0xD: case 3: return ui::VKEY_RETURN;
|
||||
case 0x1B: return ui::VKEY_ESCAPE;
|
||||
case ' ': return ui::VKEY_SPACE;
|
||||
|
||||
case 'a': return ui::VKEY_A;
|
||||
case 'b': return ui::VKEY_B;
|
||||
case 'c': return ui::VKEY_C;
|
||||
case 'd': return ui::VKEY_D;
|
||||
case 'e': return ui::VKEY_E;
|
||||
case 'f': return ui::VKEY_F;
|
||||
case 'g': return ui::VKEY_G;
|
||||
case 'h': return ui::VKEY_H;
|
||||
case 'i': return ui::VKEY_I;
|
||||
case 'j': return ui::VKEY_J;
|
||||
case 'k': return ui::VKEY_K;
|
||||
case 'l': return ui::VKEY_L;
|
||||
case 'm': return ui::VKEY_M;
|
||||
case 'n': return ui::VKEY_N;
|
||||
case 'o': return ui::VKEY_O;
|
||||
case 'p': return ui::VKEY_P;
|
||||
case 'q': return ui::VKEY_Q;
|
||||
case 'r': return ui::VKEY_R;
|
||||
case 's': return ui::VKEY_S;
|
||||
case 't': return ui::VKEY_T;
|
||||
case 'u': return ui::VKEY_U;
|
||||
case 'v': return ui::VKEY_V;
|
||||
case 'w': return ui::VKEY_W;
|
||||
case 'x': return ui::VKEY_X;
|
||||
case 'y': return ui::VKEY_Y;
|
||||
case 'z': return ui::VKEY_Z;
|
||||
|
||||
case ')': *shifted = true; case '0': return ui::VKEY_0;
|
||||
case '!': *shifted = true; case '1': return ui::VKEY_1;
|
||||
case '@': *shifted = true; case '2': return ui::VKEY_2;
|
||||
case '#': *shifted = true; case '3': return ui::VKEY_3;
|
||||
case '$': *shifted = true; case '4': return ui::VKEY_4;
|
||||
case '%': *shifted = true; case '5': return ui::VKEY_5;
|
||||
case '^': *shifted = true; case '6': return ui::VKEY_6;
|
||||
case '&': *shifted = true; case '7': return ui::VKEY_7;
|
||||
case '*': *shifted = true; case '8': return ui::VKEY_8;
|
||||
case '(': *shifted = true; case '9': return ui::VKEY_9;
|
||||
|
||||
case ':': *shifted = true; case ';': return ui::VKEY_OEM_1;
|
||||
case '+': *shifted = true; case '=': return ui::VKEY_OEM_PLUS;
|
||||
case '<': *shifted = true; case ',': return ui::VKEY_OEM_COMMA;
|
||||
case '_': *shifted = true; case '-': return ui::VKEY_OEM_MINUS;
|
||||
case '>': *shifted = true; case '.': return ui::VKEY_OEM_PERIOD;
|
||||
case '?': *shifted = true; case '/': return ui::VKEY_OEM_2;
|
||||
case '~': *shifted = true; case '`': return ui::VKEY_OEM_3;
|
||||
case '{': *shifted = true; case '[': return ui::VKEY_OEM_4;
|
||||
case '|': *shifted = true; case '\\': return ui::VKEY_OEM_5;
|
||||
case '}': *shifted = true; case ']': return ui::VKEY_OEM_6;
|
||||
case '"': *shifted = true; case '\'': return ui::VKEY_OEM_7;
|
||||
|
||||
default: return ui::VKEY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool StringToAccelerator(const std::string& description,
|
||||
ui::Accelerator* accelerator) {
|
||||
if (!base::IsStringASCII(description)) {
|
||||
@@ -104,7 +37,7 @@ bool StringToAccelerator(const std::string& description,
|
||||
// to be correct and usually only uses few special tokens.
|
||||
if (tokens[i].size() == 1) {
|
||||
bool shifted = false;
|
||||
key = KeyboardCodeFromCharCode(tokens[i][0], &shifted);
|
||||
key = atom::KeyboardCodeFromCharCode(tokens[i][0], &shifted);
|
||||
if (shifted)
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
} else if (tokens[i] == "ctrl" || tokens[i] == "control") {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "atom/browser/ui/atom_menu_model.h"
|
||||
|
||||
#include "base/stl_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomMenuModel::AtomMenuModel(Delegate* delegate)
|
||||
@@ -14,6 +16,17 @@ AtomMenuModel::AtomMenuModel(Delegate* delegate)
|
||||
AtomMenuModel::~AtomMenuModel() {
|
||||
}
|
||||
|
||||
void AtomMenuModel::SetRole(int index, const base::string16& role) {
|
||||
roles_[index] = role;
|
||||
}
|
||||
|
||||
base::string16 AtomMenuModel::GetRoleAt(int index) {
|
||||
if (ContainsKey(roles_, index))
|
||||
return roles_[index];
|
||||
else
|
||||
return base::string16();
|
||||
}
|
||||
|
||||
void AtomMenuModel::MenuClosed() {
|
||||
ui::SimpleMenuModel::MenuClosed();
|
||||
FOR_EACH_OBSERVER(Observer, observers_, MenuClosed());
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef ATOM_BROWSER_UI_ATOM_MENU_MODEL_H_
|
||||
#define ATOM_BROWSER_UI_ATOM_MENU_MODEL_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "base/observer_list.h"
|
||||
#include "ui/base/models/simple_menu_model.h"
|
||||
|
||||
@@ -31,13 +33,17 @@ class AtomMenuModel : public ui::SimpleMenuModel {
|
||||
void AddObserver(Observer* obs) { observers_.AddObserver(obs); }
|
||||
void RemoveObserver(Observer* obs) { observers_.RemoveObserver(obs); }
|
||||
|
||||
void SetRole(int index, const base::string16& role);
|
||||
base::string16 GetRoleAt(int index);
|
||||
|
||||
// ui::SimpleMenuModel:
|
||||
void MenuClosed() override;
|
||||
|
||||
private:
|
||||
Delegate* delegate_; // weak ref.
|
||||
|
||||
ObserverList<Observer> observers_;
|
||||
std::map<int, base::string16> roles_;
|
||||
base::ObserverList<Observer> observers_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomMenuModel);
|
||||
};
|
||||
|
||||
@@ -59,17 +59,4 @@ class MenuModel;
|
||||
|
||||
@end
|
||||
|
||||
// Exposed only for unit testing, do not call directly.
|
||||
@interface AtomMenuController (PrivateExposedForTesting)
|
||||
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item;
|
||||
@end
|
||||
|
||||
// Protected methods that subclassers can override.
|
||||
@interface AtomMenuController (Protected)
|
||||
- (void)addItemToMenu:(NSMenu*)menu
|
||||
atIndex:(NSInteger)index
|
||||
fromModel:(ui::MenuModel*)model;
|
||||
- (NSMenu*)menuFromModel:(ui::MenuModel*)model;
|
||||
@end
|
||||
|
||||
#endif // ATOM_BROWSER_UI_COCOA_ATOM_MENU_CONTROLLER_H_
|
||||
|
||||
@@ -8,16 +8,36 @@
|
||||
#include "atom/browser/ui/atom_menu_model.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "ui/base/accelerators/accelerator.h"
|
||||
#include "ui/base/accelerators/platform_accelerator_cocoa.h"
|
||||
#include "ui/base/l10n/l10n_util_mac.h"
|
||||
#include "ui/events/cocoa/cocoa_event_utils.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
@interface AtomMenuController (Private)
|
||||
- (void)addSeparatorToMenu:(NSMenu*)menu
|
||||
atIndex:(int)index;
|
||||
@end
|
||||
namespace {
|
||||
|
||||
struct Role {
|
||||
SEL selector;
|
||||
const char* role;
|
||||
};
|
||||
Role kRolesMap[] = {
|
||||
{ @selector(orderFrontStandardAboutPanel:), "about" },
|
||||
{ @selector(hide:), "hide" },
|
||||
{ @selector(hideOtherApplications:), "hideothers" },
|
||||
{ @selector(unhideAllApplications:), "unhide" },
|
||||
{ @selector(arrangeInFront:), "front" },
|
||||
{ @selector(undo:), "undo" },
|
||||
{ @selector(redo:), "redo" },
|
||||
{ @selector(cut:), "cut" },
|
||||
{ @selector(copy:), "copy" },
|
||||
{ @selector(paste:), "paste" },
|
||||
{ @selector(selectAll:), "selectall" },
|
||||
{ @selector(performMiniaturize:), "minimize" },
|
||||
{ @selector(performClose:), "close" },
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@implementation AtomMenuController
|
||||
|
||||
@@ -101,7 +121,9 @@
|
||||
// associated with the entry in the model identified by |modelIndex|.
|
||||
- (void)addItemToMenu:(NSMenu*)menu
|
||||
atIndex:(NSInteger)index
|
||||
fromModel:(ui::MenuModel*)model {
|
||||
fromModel:(ui::MenuModel*)ui_model {
|
||||
atom::AtomMenuModel* model = static_cast<atom::AtomMenuModel*>(ui_model);
|
||||
|
||||
base::string16 label16 = model->GetLabelAt(index);
|
||||
NSString* label = l10n_util::FixUpWindowsStyleLabel(label16);
|
||||
base::scoped_nsobject<NSMenuItem> item(
|
||||
@@ -124,13 +146,13 @@
|
||||
[submenu setTitle:[item title]];
|
||||
[item setSubmenu:submenu];
|
||||
|
||||
// Hack to set window and help menu.
|
||||
if ([[item title] isEqualToString:@"Window"] && [submenu numberOfItems] > 0)
|
||||
// Set submenu's role.
|
||||
base::string16 role = model->GetRoleAt(index);
|
||||
if (role == base::ASCIIToUTF16("window"))
|
||||
[NSApp setWindowsMenu:submenu];
|
||||
else if ([[item title] isEqualToString:@"Help"])
|
||||
else if (role == base::ASCIIToUTF16("help"))
|
||||
[NSApp setHelpMenu:submenu];
|
||||
if ([[item title] isEqualToString:@"Services"] &&
|
||||
[submenu numberOfItems] == 0)
|
||||
if (role == base::ASCIIToUTF16("services"))
|
||||
[NSApp setServicesMenu:submenu];
|
||||
} else {
|
||||
// The MenuModel works on indexes so we can't just set the command id as the
|
||||
@@ -139,7 +161,6 @@
|
||||
// model. Setting the target to |self| allows this class to participate
|
||||
// in validation of the menu items.
|
||||
[item setTag:index];
|
||||
[item setTarget:self];
|
||||
NSValue* modelObject = [NSValue valueWithPointer:model];
|
||||
[item setRepresentedObject:modelObject]; // Retains |modelObject|.
|
||||
ui::Accelerator accelerator;
|
||||
@@ -153,6 +174,19 @@
|
||||
platformAccelerator->modifier_mask()];
|
||||
}
|
||||
}
|
||||
|
||||
// Set menu item's role.
|
||||
base::string16 role = model->GetRoleAt(index);
|
||||
if (role.empty()) {
|
||||
[item setTarget:self];
|
||||
} else {
|
||||
for (const Role& pair : kRolesMap) {
|
||||
if (role == base::ASCIIToUTF16(pair.role)) {
|
||||
[item setAction:pair.selector];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[menu insertItem:item atIndex:index];
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ gboolean FileFilterCaseInsensitive(const GtkFileFilterInfo* file_info,
|
||||
// Makes .* file extension matches all file types.
|
||||
if (*file_extension == ".*")
|
||||
return true;
|
||||
return EndsWith(file_info->filename, *file_extension, false);
|
||||
return base::EndsWith(file_info->filename, *file_extension, false);
|
||||
}
|
||||
|
||||
// Deletes |data| when gtk_file_filter_add_custom() is done with it.
|
||||
|
||||
@@ -79,6 +79,9 @@ class FileDialog {
|
||||
if (!title.empty())
|
||||
GetPtr()->SetTitle(base::UTF8ToUTF16(title).c_str());
|
||||
|
||||
if (!filterspec.empty())
|
||||
GetPtr()->SetDefaultExtension(filterspec.front().pszSpec);
|
||||
|
||||
SetDefaultFolder(default_path);
|
||||
}
|
||||
|
||||
@@ -252,7 +255,7 @@ bool ShowSaveDialog(atom::NativeWindow* parent_window,
|
||||
|
||||
bool matched = false;
|
||||
for (size_t i = 0; i < filter.second.size(); ++i) {
|
||||
if (EndsWith(file_name, filter.second[i], false)) {
|
||||
if (base::EndsWith(file_name, filter.second[i], false)) {
|
||||
matched = true;
|
||||
break;;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ class TrayIcon {
|
||||
TrayIcon();
|
||||
|
||||
private:
|
||||
ObserverList<TrayIconObserver> observers_;
|
||||
base::ObserverList<TrayIconObserver> observers_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TrayIcon);
|
||||
};
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
|
||||
#include "atom/browser/ui/win/notify_icon.h"
|
||||
|
||||
#include <shobjidl.h>
|
||||
|
||||
#include "atom/browser/ui/win/notify_icon_host.h"
|
||||
#include "base/md5.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/win/windows_version.h"
|
||||
@@ -28,31 +25,7 @@ NotifyIcon::NotifyIcon(NotifyIconHost* host,
|
||||
icon_id_(id),
|
||||
window_(window),
|
||||
message_id_(message),
|
||||
menu_model_(NULL),
|
||||
has_tray_app_id_hash_(false) {
|
||||
// NB: If we have an App Model ID, we should propagate that to the tray.
|
||||
// Doing this prevents duplicate items from showing up in the notification
|
||||
// preferences (i.e. "Always Show / Show notifications only / etc")
|
||||
PWSTR explicit_app_id;
|
||||
if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&explicit_app_id))) {
|
||||
// GUIDs and MD5 hashes are the same length. So convenient!
|
||||
base::MD5Sum(explicit_app_id,
|
||||
sizeof(wchar_t) * wcslen(explicit_app_id),
|
||||
reinterpret_cast<base::MD5Digest*>(&tray_app_id_hash_));
|
||||
|
||||
// Set the GUID to version 4 as described in RFC 4122, section 4.4.
|
||||
// The format of GUID version 4 must be like
|
||||
// xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, where y is one of [8, 9, A, B].
|
||||
tray_app_id_hash_.Data3 &= 0x0fff;
|
||||
tray_app_id_hash_.Data3 |= 0x4000;
|
||||
|
||||
// Set y to one of [8, 9, A, B].
|
||||
tray_app_id_hash_.Data4[0] = 1;
|
||||
|
||||
has_tray_app_id_hash_ = true;
|
||||
CoTaskMemFree(explicit_app_id);
|
||||
}
|
||||
|
||||
menu_model_(NULL) {
|
||||
NOTIFYICONDATA icon_data;
|
||||
InitIconData(&icon_data);
|
||||
icon_data.uFlags |= NIF_MESSAGE;
|
||||
@@ -81,10 +54,6 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos,
|
||||
icon_id.uID = icon_id_;
|
||||
icon_id.hWnd = window_;
|
||||
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
|
||||
if (has_tray_app_id_hash_)
|
||||
memcpy(reinterpret_cast<void*>(&icon_id.guidItem),
|
||||
&tray_app_id_hash_,
|
||||
sizeof(GUID));
|
||||
|
||||
RECT rect = { 0 };
|
||||
Shell_NotifyIconGetRect(&icon_id, &rect);
|
||||
@@ -202,13 +171,6 @@ void NotifyIcon::InitIconData(NOTIFYICONDATA* icon_data) {
|
||||
icon_data->cbSize = sizeof(NOTIFYICONDATA);
|
||||
icon_data->hWnd = window_;
|
||||
icon_data->uID = icon_id_;
|
||||
|
||||
if (has_tray_app_id_hash_) {
|
||||
icon_data->uFlags |= NIF_GUID;
|
||||
memcpy(reinterpret_cast<void*>(&icon_data->guidItem),
|
||||
&tray_app_id_hash_,
|
||||
sizeof(GUID));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -79,10 +79,6 @@ class NotifyIcon : public TrayIcon {
|
||||
// The context menu.
|
||||
ui::SimpleMenuModel* menu_model_;
|
||||
|
||||
// A hash of the app model ID
|
||||
GUID tray_app_id_hash_;
|
||||
bool has_tray_app_id_hash_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NotifyIcon);
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "base/environment.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "dbus/bus.h"
|
||||
#include "dbus/object_proxy.h"
|
||||
@@ -41,7 +42,7 @@ void SetWindowType(::Window xwindow, const std::string& type) {
|
||||
XDisplay* xdisplay = gfx::GetXDisplay();
|
||||
std::string type_prefix = "_NET_WM_WINDOW_TYPE_";
|
||||
::Atom window_type = XInternAtom(
|
||||
xdisplay, (type_prefix + StringToUpperASCII(type)).c_str(), False);
|
||||
xdisplay, (type_prefix + base::StringToUpperASCII(type)).c_str(), False);
|
||||
XChangeProperty(xdisplay, xwindow,
|
||||
XInternAtom(xdisplay, "_NET_WM_WINDOW_TYPE", False),
|
||||
XA_ATOM,
|
||||
@@ -50,6 +51,10 @@ void SetWindowType(::Window xwindow, const std::string& type) {
|
||||
}
|
||||
|
||||
bool ShouldUseGlobalMenuBar() {
|
||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (env->HasVar("ELECTRON_FORCE_WINDOW_MENU_BAR"))
|
||||
return false;
|
||||
|
||||
dbus::Bus::Options options;
|
||||
scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
|
||||
|
||||
|
||||
157
atom/browser/web_contents_preferences.cc
Normal file
157
atom/browser/web_contents_preferences.cc
Normal file
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "content/public/common/web_preferences.h"
|
||||
#include "net/base/filename_util.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/gfx/switches.h"
|
||||
#endif
|
||||
|
||||
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::WebContentsPreferences);
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// Array of available web runtime features.
|
||||
const char* kWebRuntimeFeatures[] = {
|
||||
switches::kExperimentalFeatures,
|
||||
switches::kExperimentalCanvasFeatures,
|
||||
switches::kSubpixelFontScaling,
|
||||
switches::kOverlayScrollbars,
|
||||
switches::kOverlayFullscreenVideo,
|
||||
switches::kSharedWorker,
|
||||
switches::kPageVisibility,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
WebContentsPreferences::WebContentsPreferences(
|
||||
content::WebContents* web_contents,
|
||||
base::DictionaryValue* web_preferences) {
|
||||
web_preferences_.Swap(web_preferences);
|
||||
web_contents->SetUserData(UserDataKey(), this);
|
||||
|
||||
// The "isGuest" is not a preferences field.
|
||||
web_preferences_.Remove("isGuest", nullptr);
|
||||
}
|
||||
|
||||
WebContentsPreferences::~WebContentsPreferences() {
|
||||
}
|
||||
|
||||
void WebContentsPreferences::Merge(const base::DictionaryValue& extend) {
|
||||
web_preferences_.MergeDictionary(&extend);
|
||||
}
|
||||
|
||||
// static
|
||||
void WebContentsPreferences::AppendExtraCommandLineSwitches(
|
||||
content::WebContents* web_contents, base::CommandLine* command_line) {
|
||||
WebContentsPreferences* self = FromWebContents(web_contents);
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
base::DictionaryValue& web_preferences = self->web_preferences_;
|
||||
|
||||
bool b;
|
||||
#if defined(OS_WIN)
|
||||
// Check if DirectWrite is disabled.
|
||||
if (web_preferences.GetBoolean(switches::kDirectWrite, &b) && !b)
|
||||
command_line->AppendSwitch(::switches::kDisableDirectWrite);
|
||||
#endif
|
||||
|
||||
// Check if plugins are enabled.
|
||||
if (web_preferences.GetBoolean("plugins", &b) && b)
|
||||
command_line->AppendSwitch(switches::kEnablePlugins);
|
||||
|
||||
// This set of options are not availabe in WebPreferences, so we have to pass
|
||||
// them via command line and enable them in renderer procss.
|
||||
for (size_t i = 0; i < arraysize(kWebRuntimeFeatures); ++i) {
|
||||
const char* feature = kWebRuntimeFeatures[i];
|
||||
if (web_preferences.GetBoolean(feature, &b))
|
||||
command_line->AppendSwitchASCII(feature, b ? "true" : "false");
|
||||
}
|
||||
|
||||
// Check if we have node integration specified.
|
||||
bool node_integration = true;
|
||||
web_preferences.GetBoolean(switches::kNodeIntegration, &node_integration);
|
||||
// Be compatible with old API of "node-integration" option.
|
||||
std::string old_token;
|
||||
if (web_preferences.GetString(switches::kNodeIntegration, &old_token) &&
|
||||
old_token != "disable")
|
||||
node_integration = true;
|
||||
command_line->AppendSwitchASCII(switches::kNodeIntegration,
|
||||
node_integration ? "true" : "false");
|
||||
|
||||
// The preload script.
|
||||
base::FilePath::StringType preload;
|
||||
if (web_preferences.GetString(switches::kPreloadScript, &preload)) {
|
||||
if (base::FilePath(preload).IsAbsolute())
|
||||
command_line->AppendSwitchNative(switches::kPreloadScript, preload);
|
||||
else
|
||||
LOG(ERROR) << "preload script must have absolute path.";
|
||||
} else if (web_preferences.GetString(switches::kPreloadUrl, &preload)) {
|
||||
// Translate to file path if there is "preload-url" option.
|
||||
base::FilePath preload_path;
|
||||
if (net::FileURLToFilePath(GURL(preload), &preload_path))
|
||||
command_line->AppendSwitchPath(switches::kPreloadScript, preload_path);
|
||||
else
|
||||
LOG(ERROR) << "preload url must be file:// protocol.";
|
||||
}
|
||||
|
||||
// The zoom factor.
|
||||
double zoom_factor = 1.0;
|
||||
if (web_preferences.GetDouble(switches::kZoomFactor, &zoom_factor) &&
|
||||
zoom_factor != 1.0)
|
||||
command_line->AppendSwitchASCII(switches::kZoomFactor,
|
||||
base::DoubleToString(zoom_factor));
|
||||
|
||||
// --guest-instance-id, which is used to identify guest WebContents.
|
||||
int guest_instance_id;
|
||||
if (web_preferences.GetInteger(switches::kGuestInstanceID,
|
||||
&guest_instance_id))
|
||||
command_line->AppendSwitchASCII(switches::kGuestInstanceID,
|
||||
base::IntToString(guest_instance_id));
|
||||
}
|
||||
|
||||
// static
|
||||
void WebContentsPreferences::OverrideWebkitPrefs(
|
||||
content::WebContents* web_contents, content::WebPreferences* prefs) {
|
||||
WebContentsPreferences* self = FromWebContents(web_contents);
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
bool b;
|
||||
if (self->web_preferences_.GetBoolean("javascript", &b))
|
||||
prefs->javascript_enabled = b;
|
||||
if (self->web_preferences_.GetBoolean("images", &b))
|
||||
prefs->images_enabled = b;
|
||||
if (self->web_preferences_.GetBoolean("java", &b))
|
||||
prefs->java_enabled = b;
|
||||
if (self->web_preferences_.GetBoolean("text-areas-are-resizable", &b))
|
||||
prefs->text_areas_are_resizable = b;
|
||||
if (self->web_preferences_.GetBoolean("webgl", &b))
|
||||
prefs->experimental_webgl_enabled = b;
|
||||
if (self->web_preferences_.GetBoolean("webaudio", &b))
|
||||
prefs->webaudio_enabled = b;
|
||||
if (self->web_preferences_.GetBoolean("web-security", &b)) {
|
||||
prefs->web_security_enabled = b;
|
||||
prefs->allow_displaying_insecure_content = !b;
|
||||
prefs->allow_running_insecure_content = !b;
|
||||
}
|
||||
if (self->web_preferences_.GetBoolean("allow-displaying-insecure-content",
|
||||
&b))
|
||||
prefs->allow_displaying_insecure_content = b;
|
||||
if (self->web_preferences_.GetBoolean("allow-running-insecure-content", &b))
|
||||
prefs->allow_running_insecure_content = b;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
53
atom/browser/web_contents_preferences.h
Normal file
53
atom/browser/web_contents_preferences.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_WEB_CONTENTS_PREFERENCES_H_
|
||||
#define ATOM_BROWSER_WEB_CONTENTS_PREFERENCES_H_
|
||||
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
|
||||
namespace base {
|
||||
class CommandLine;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
struct WebPreferences;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Stores and applies the preferences of WebContents.
|
||||
class WebContentsPreferences
|
||||
: public content::WebContentsUserData<WebContentsPreferences> {
|
||||
public:
|
||||
// Append command paramters according to |web_contents|'s preferences.
|
||||
static void AppendExtraCommandLineSwitches(
|
||||
content::WebContents* web_contents, base::CommandLine* command_line);
|
||||
|
||||
// Modify the WebPreferences according to |web_contents|'s preferences.
|
||||
static void OverrideWebkitPrefs(
|
||||
content::WebContents* web_contents, content::WebPreferences* prefs);
|
||||
|
||||
WebContentsPreferences(content::WebContents* web_contents,
|
||||
base::DictionaryValue* web_preferences);
|
||||
~WebContentsPreferences() override;
|
||||
|
||||
// $.extend(|web_preferences_|, |new_web_preferences|).
|
||||
void Merge(const base::DictionaryValue& new_web_preferences);
|
||||
|
||||
// Returns the web preferences.
|
||||
base::DictionaryValue* web_preferences() { return &web_preferences_; }
|
||||
|
||||
private:
|
||||
friend class content::WebContentsUserData<WebContentsPreferences>;
|
||||
|
||||
base::DictionaryValue web_preferences_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebContentsPreferences);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_WEB_CONTENTS_PREFERENCES_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user