Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00c5c3e7c2 | ||
|
|
b8cebb4993 | ||
|
|
63875c9e04 | ||
|
|
c927a660ea | ||
|
|
cf8bc4541d | ||
|
|
f4e39fc6f4 | ||
|
|
d10904010a | ||
|
|
22886d3547 | ||
|
|
de87d59cfc | ||
|
|
e67b9b52e3 | ||
|
|
821cba01be | ||
|
|
8d79be38cc | ||
|
|
55c83585d0 | ||
|
|
0ac1b38920 | ||
|
|
2d5b40a675 | ||
|
|
cbfbaf026f | ||
|
|
e17072f3ef | ||
|
|
b2ac2b28e0 | ||
|
|
30a467bf67 | ||
|
|
e1f7b842fe | ||
|
|
42c4708b34 | ||
|
|
7e80662a24 | ||
|
|
982b7bf2a1 | ||
|
|
92452d7614 | ||
|
|
74124f150b | ||
|
|
4078c2dd1e | ||
|
|
6638cc1e6d | ||
|
|
ea31efd98e | ||
|
|
5f1ef110ff | ||
|
|
6d127920f8 | ||
|
|
b1d148fd52 | ||
|
|
51204afc90 | ||
|
|
6d0df6d506 | ||
|
|
860800629b | ||
|
|
ce11609fe9 | ||
|
|
d6f18548a6 | ||
|
|
29c1150eef | ||
|
|
db1c5741cd | ||
|
|
0488d0b40b | ||
|
|
bbc3e455b0 | ||
|
|
aacd52f00f | ||
|
|
0dad0315dd | ||
|
|
d49569ca0d | ||
|
|
d262539fb9 | ||
|
|
3596656ea4 | ||
|
|
10dbd42596 | ||
|
|
b52731f9e0 | ||
|
|
2fc5e3ad7d | ||
|
|
544366e301 | ||
|
|
ef4eb3f926 | ||
|
|
2a57b39dbc | ||
|
|
50bd3acb5b | ||
|
|
8fa66368a0 | ||
|
|
d3f82662f5 | ||
|
|
7a2f786e0c | ||
|
|
a5696dc110 | ||
|
|
eab116cde1 | ||
|
|
a46ea601f7 | ||
|
|
fad8235ad2 | ||
|
|
32c8246e16 | ||
|
|
27bbc35768 | ||
|
|
d60f501490 | ||
|
|
900107da1b | ||
|
|
8a10b7bf8b | ||
|
|
b673400639 | ||
|
|
28e73defa3 | ||
|
|
cfe63a2434 | ||
|
|
0aa19bce59 | ||
|
|
ef4a433814 | ||
|
|
713d6ed1b4 | ||
|
|
515ba7c887 | ||
|
|
562ff3e9ab | ||
|
|
7802bdb5f7 | ||
|
|
b20b9797dc | ||
|
|
824c2f0d40 | ||
|
|
6542ca6bcd | ||
|
|
b395befdbd | ||
|
|
071412ab29 | ||
|
|
b9454f2887 | ||
|
|
3b93fb3645 | ||
|
|
b6185a27f2 | ||
|
|
be2e0f9830 | ||
|
|
62636946ff | ||
|
|
970b041574 | ||
|
|
5487515bca | ||
|
|
5dace0043a | ||
|
|
3f0dc49164 | ||
|
|
81f3903598 | ||
|
|
6957412ab5 | ||
|
|
fa714cba35 | ||
|
|
d73c4c046d | ||
|
|
3d954cb29c | ||
|
|
1aa650b8ac | ||
|
|
e6b3e4ebed | ||
|
|
a7a76f9a29 | ||
|
|
590835c616 | ||
|
|
3bb273771a | ||
|
|
ba7b5589ab | ||
|
|
69a867fd3a | ||
|
|
c6c045a7f7 | ||
|
|
a5421542e5 | ||
|
|
aa3828319a | ||
|
|
bd497f7f83 | ||
|
|
9800079bc2 | ||
|
|
8442b959f8 | ||
|
|
ef89146385 | ||
|
|
286e7ac205 | ||
|
|
f63a7ee3fd | ||
|
|
325a49588a | ||
|
|
00f22ddbe6 | ||
|
|
dcb027a718 | ||
|
|
08c90e00b9 | ||
|
|
9ef5006592 | ||
|
|
61f1adc54d | ||
|
|
68bfe68581 | ||
|
|
1fadb7fa2f | ||
|
|
de383de310 | ||
|
|
c29f3e8dba | ||
|
|
932335ea76 | ||
|
|
ac9e93e5e6 | ||
|
|
2485e982f3 | ||
|
|
ae9de9b891 | ||
|
|
438c04383f | ||
|
|
c830a5f497 | ||
|
|
164800800d | ||
|
|
c4e16d8b64 | ||
|
|
057c632bee | ||
|
|
049feac2c8 | ||
|
|
9221d44207 | ||
|
|
4bf20fc91e | ||
|
|
2a10574d76 | ||
|
|
16b11770a1 | ||
|
|
7277d7c6d7 | ||
|
|
0fe63b74b1 | ||
|
|
07689ab83f | ||
|
|
77e923c146 | ||
|
|
2d4950d2ae | ||
|
|
6056469e41 | ||
|
|
8a92f69986 | ||
|
|
8c1064bc1c | ||
|
|
5654295d83 | ||
|
|
e6baad1f5f | ||
|
|
0051421990 | ||
|
|
58e418aeb0 | ||
|
|
904af3005d | ||
|
|
7e5ab94e0c | ||
|
|
ae8639dc24 | ||
|
|
c56a635ba2 | ||
|
|
f8767c563d | ||
|
|
79e782e53f | ||
|
|
adafcc36fc | ||
|
|
411e6879ee | ||
|
|
9a52ed3bfb | ||
|
|
a08f152454 | ||
|
|
20c80bcbc1 | ||
|
|
016efb9f37 | ||
|
|
dcddfbe7af | ||
|
|
4a1f2294a5 | ||
|
|
f9e0ed9849 | ||
|
|
61cd8ae52b | ||
|
|
76f825276d | ||
|
|
3c7fcec8a0 | ||
|
|
b900a6e486 | ||
|
|
e3fd2e48e0 | ||
|
|
a2cc16a276 | ||
|
|
c6c6ba4e2d | ||
|
|
0f61aed51f | ||
|
|
2c92077deb | ||
|
|
fcc171ddb7 | ||
|
|
bbb68510ee | ||
|
|
d4d80438a3 | ||
|
|
785a7c8198 | ||
|
|
52da5f2644 | ||
|
|
aabe1e7517 | ||
|
|
bc08ae75fe | ||
|
|
26adb1ff41 | ||
|
|
6558fea833 | ||
|
|
4af7884929 | ||
|
|
27347bc827 | ||
|
|
e837b693ba | ||
|
|
334c951f93 | ||
|
|
324f6a0ea3 | ||
|
|
a492c5bdb9 | ||
|
|
5d0bc8e811 | ||
|
|
a90b552eb4 | ||
|
|
165df0f7b5 | ||
|
|
9842b6054c | ||
|
|
b3cacb2c3a | ||
|
|
532cd0ae7a | ||
|
|
5e9342a622 | ||
|
|
f924d979d5 | ||
|
|
2d9b9a9617 | ||
|
|
5652238ba8 | ||
|
|
a164537057 | ||
|
|
2b8f6866cb | ||
|
|
0c99c0ca2e | ||
|
|
ec277eacb8 | ||
|
|
9ad788853f | ||
|
|
79c3747465 | ||
|
|
90307d8552 | ||
|
|
0828fe1232 | ||
|
|
a977ba55eb | ||
|
|
8199a0d551 | ||
|
|
6996115924 | ||
|
|
56ff5a50d4 | ||
|
|
357463d9d7 | ||
|
|
e515299477 | ||
|
|
ad1bd19571 | ||
|
|
d8070a8e0d | ||
|
|
cd7fab2f80 | ||
|
|
9733f9d2e5 | ||
|
|
e65f15fb4c | ||
|
|
9c395967cc | ||
|
|
64e3f4118a | ||
|
|
4abc90ad3e | ||
|
|
43dfe703da | ||
|
|
d53fd09524 | ||
|
|
9551e4c9bc | ||
|
|
193b14528a | ||
|
|
70a9fe579f | ||
|
|
eff26719cd | ||
|
|
14f12a065e | ||
|
|
d7fadcdef9 | ||
|
|
775ce7fc17 | ||
|
|
a2054a3eaf | ||
|
|
c048d762cf | ||
|
|
39fe9559bb | ||
|
|
baa0c0a91e | ||
|
|
7322bc0e9d | ||
|
|
0fad293135 | ||
|
|
612b110946 | ||
|
|
ac6d297268 | ||
|
|
ea3642103f | ||
|
|
e591cf1e1a | ||
|
|
07a26bff17 | ||
|
|
0d8cddaa73 | ||
|
|
a595fa29a3 | ||
|
|
2705986b4a | ||
|
|
8e42fccca6 | ||
|
|
edd7cd7d87 | ||
|
|
23327d7213 | ||
|
|
04d84d20fa | ||
|
|
676305dfeb | ||
|
|
9f0c3479c0 | ||
|
|
33a3173c79 | ||
|
|
e517623574 | ||
|
|
61efa1ee08 | ||
|
|
8a737f3234 | ||
|
|
7e570f010f | ||
|
|
64ea1e09c2 | ||
|
|
84c7d3c2f6 | ||
|
|
5e28396116 | ||
|
|
cd55d0fbe4 | ||
|
|
c772d0ef21 | ||
|
|
46c9f72fc0 | ||
|
|
a160e7772a | ||
|
|
dc5a60fb62 | ||
|
|
1588077e62 | ||
|
|
17970a216b | ||
|
|
be82ca4b1f | ||
|
|
00c51f75fa | ||
|
|
addadda237 | ||
|
|
0efc152b07 | ||
|
|
8618fcbe89 | ||
|
|
20ee1ece01 | ||
|
|
bbe40dab58 | ||
|
|
5e500dc2b4 | ||
|
|
5d6ae8b156 | ||
|
|
99f31e38ba | ||
|
|
51117c2b62 | ||
|
|
991b053042 | ||
|
|
1bf41a59b9 | ||
|
|
86db73b5d1 | ||
|
|
f302cc1391 | ||
|
|
cb0f8292a6 | ||
|
|
4e03bfdec8 | ||
|
|
bdfd859beb | ||
|
|
5338dcd132 | ||
|
|
a9d3c2b52a | ||
|
|
517aec3111 | ||
|
|
930ddd693b | ||
|
|
4cdd532738 | ||
|
|
6f8d063b18 | ||
|
|
b1957eb7c9 | ||
|
|
a5b4a440d6 | ||
|
|
9a84af4d5b | ||
|
|
eecc234b44 | ||
|
|
2366accae5 | ||
|
|
d01ae5cf25 | ||
|
|
92b3def6a8 | ||
|
|
006b8f5c6e | ||
|
|
152974a8fe | ||
|
|
6d480d82a5 | ||
|
|
fa72aef363 | ||
|
|
2ed7526705 | ||
|
|
9ecfdbe358 | ||
|
|
97dcd8009a | ||
|
|
e1fc99d6ef | ||
|
|
0de24cc207 | ||
|
|
28ad4a4b7c | ||
|
|
f41a43acf2 | ||
|
|
1dd2c05377 | ||
|
|
f48c32ebc1 | ||
|
|
b0b90b81f3 | ||
|
|
6f9c302a32 | ||
|
|
a3bee9a6a8 | ||
|
|
26d1ff2bd6 | ||
|
|
825ae7cb05 | ||
|
|
2302734e6f | ||
|
|
40c0791320 | ||
|
|
ab0be54f2d | ||
|
|
6b4ef9af48 | ||
|
|
425677ada7 | ||
|
|
633728842e | ||
|
|
bc2841f9f9 | ||
|
|
d78e03d528 | ||
|
|
bebeb4e26a | ||
|
|
bf110158b9 | ||
|
|
983a87a9d7 | ||
|
|
bf8359c704 | ||
|
|
4e5b100cca | ||
|
|
a874f27b5a | ||
|
|
6b2f1524f8 | ||
|
|
93b170e629 | ||
|
|
33523f5d5e | ||
|
|
1eaadfbc8d | ||
|
|
0102047d68 | ||
|
|
b07c898b06 | ||
|
|
6dd43c3e2f | ||
|
|
b9b1abc871 | ||
|
|
768231cf6a | ||
|
|
c82b759d56 | ||
|
|
9e2a89c71d | ||
|
|
68d1c14bdf | ||
|
|
b73c17b7c6 | ||
|
|
1a31160dde | ||
|
|
e764f258e2 | ||
|
|
3daf711085 | ||
|
|
7fe7026030 | ||
|
|
93407295fc | ||
|
|
db8d2ef672 | ||
|
|
f4f9b0cec7 | ||
|
|
adf51bc0f5 | ||
|
|
378738aaa9 | ||
|
|
c482078b09 | ||
|
|
82f11ad8aa | ||
|
|
72ff18e58e | ||
|
|
a0bdc21cf5 | ||
|
|
42ee994d99 | ||
|
|
f25a45b9e6 | ||
|
|
677085e0c4 | ||
|
|
fbbcbffcc7 | ||
|
|
5d5f72d4bc | ||
|
|
c8b89feae8 | ||
|
|
17b2aa7650 | ||
|
|
6f685140aa | ||
|
|
5aa65d2aea | ||
|
|
712ca7303b | ||
|
|
8c824b8a75 | ||
|
|
7aa445162e | ||
|
|
643e298a55 | ||
|
|
f82c95d1eb | ||
|
|
01747509f6 | ||
|
|
22b8e6b79f | ||
|
|
f9b28d2006 | ||
|
|
185a027640 | ||
|
|
99ec088ecf | ||
|
|
062a5085b1 | ||
|
|
65ed8de1fa | ||
|
|
2e34db5696 | ||
|
|
3a565183f0 | ||
|
|
7ed9c249be | ||
|
|
37c86f2c07 | ||
|
|
8d8da66f94 | ||
|
|
145947d86b | ||
|
|
c2b4aa8cf2 | ||
|
|
129bb5568d | ||
|
|
5b84c3e982 | ||
|
|
3abcec5d8b | ||
|
|
6466bf6f5b | ||
|
|
f4e8585e60 | ||
|
|
cc231f0a26 | ||
|
|
86b17cfb4a | ||
|
|
d2a4597cfc | ||
|
|
43165d9edb | ||
|
|
88624edc98 | ||
|
|
c58e7c72b4 | ||
|
|
8bbfcc4c81 | ||
|
|
f2ad2ba0de | ||
|
|
2af23767e1 | ||
|
|
bb9700d982 | ||
|
|
077b053ba4 | ||
|
|
279ed4a9cf | ||
|
|
5f8057cbed | ||
|
|
95cda916d1 | ||
|
|
08842d77ae | ||
|
|
1191c9e371 | ||
|
|
4ea9a83b75 | ||
|
|
9a2da3012a | ||
|
|
022ed72339 | ||
|
|
f5c363c01d | ||
|
|
41fc1ccf4d | ||
|
|
7abed0e352 | ||
|
|
d430c6398b | ||
|
|
e44c44b749 | ||
|
|
d347a1e0c6 | ||
|
|
39ba93e1d7 | ||
|
|
5cecc096a3 | ||
|
|
8feed35c61 | ||
|
|
7b706516bc | ||
|
|
144b3844da | ||
|
|
eb96f030b9 | ||
|
|
981154dc48 | ||
|
|
a0da6b5b68 | ||
|
|
bd99ce1461 | ||
|
|
bed3776982 | ||
|
|
ef236bef4f | ||
|
|
d90ce1e30a | ||
|
|
bee1a6fe1c | ||
|
|
f9caae6cfd | ||
|
|
e10f9df9df | ||
|
|
7d87b7a270 | ||
|
|
3d43617bc1 | ||
|
|
ac9fdbf123 | ||
|
|
e6101f7fa6 | ||
|
|
52bcfa36bf | ||
|
|
6d9b8e43bf | ||
|
|
ae8cc0e398 | ||
|
|
7d49b154e2 | ||
|
|
d5ae68701b | ||
|
|
330b866f46 | ||
|
|
edcbb85f5e | ||
|
|
c683df5483 | ||
|
|
8862a2ebf7 | ||
|
|
82fa1fbf14 | ||
|
|
faec3f2140 | ||
|
|
ab5f44b61d | ||
|
|
c332210793 | ||
|
|
6709388785 | ||
|
|
2829b9387b | ||
|
|
1e1a1e5c71 | ||
|
|
55d1aa0748 | ||
|
|
9fd02b65e1 | ||
|
|
e6a9d13e64 | ||
|
|
8832bfb62f | ||
|
|
44e35f67b4 | ||
|
|
56d9003017 | ||
|
|
e49b80dba7 | ||
|
|
834ded7d18 | ||
|
|
c617545914 | ||
|
|
ee4e449e04 | ||
|
|
fd51da7587 | ||
|
|
e1a982d677 | ||
|
|
b76d12c2bd | ||
|
|
57dffbd698 | ||
|
|
e0e12932bc | ||
|
|
9a1e152ba3 | ||
|
|
a9046dcd55 | ||
|
|
c265d1cb7c | ||
|
|
d61076d50e | ||
|
|
43bed4dad8 | ||
|
|
3a27ace545 | ||
|
|
d3cc8bc1ae | ||
|
|
4f6406f033 | ||
|
|
ce1c300502 | ||
|
|
6a0d77b68c | ||
|
|
3ceb3ee7ef | ||
|
|
3adf5e5d9c | ||
|
|
b2ad7e8ed9 | ||
|
|
3b48d984b2 | ||
|
|
02afcba614 | ||
|
|
aed6c5eb62 | ||
|
|
429a4cd9d7 | ||
|
|
acf30bc5f4 | ||
|
|
ca38eaca70 | ||
|
|
567ba7ede6 | ||
|
|
79b640795a | ||
|
|
0b75a2a787 | ||
|
|
b8d18bace6 | ||
|
|
ecbe89cd7d | ||
|
|
a7bb296293 | ||
|
|
7da587d0aa | ||
|
|
ac50292859 | ||
|
|
633a742916 | ||
|
|
63b8aaa495 | ||
|
|
4897e3653a | ||
|
|
af32d0b7d1 | ||
|
|
e6c662b5c6 | ||
|
|
6abe7e7914 | ||
|
|
7ab66b1c6a | ||
|
|
df3eed4ef9 | ||
|
|
804d0f6604 | ||
|
|
327f5499ca | ||
|
|
97f911427a | ||
|
|
3b575dfced | ||
|
|
0bc66e3b04 | ||
|
|
6e6b5d8996 | ||
|
|
12635c1c22 | ||
|
|
4c0d99d173 | ||
|
|
8399d85036 | ||
|
|
ef5083db5f | ||
|
|
cff9ef7fb8 | ||
|
|
124a5a8eb7 | ||
|
|
a9376e01cb | ||
|
|
8884db9790 | ||
|
|
28a69cf1e2 | ||
|
|
bdfc1adbd2 | ||
|
|
f990d9a46a | ||
|
|
497e453fe7 | ||
|
|
7dec0edf50 | ||
|
|
97ee3ee428 | ||
|
|
18cfe514ab | ||
|
|
15aafa8a46 | ||
|
|
757a30f720 | ||
|
|
78d1f68932 | ||
|
|
b226f8942d | ||
|
|
f1c2ba75d1 | ||
|
|
f3707e0637 | ||
|
|
ed8d7f1391 | ||
|
|
7e975c2c5b | ||
|
|
4608ae53aa | ||
|
|
121ee9438c | ||
|
|
ba4eba034f | ||
|
|
534de5cc5b | ||
|
|
023a71c6f2 | ||
|
|
c83282fd4d | ||
|
|
d60103257e | ||
|
|
ee86d3eb9c | ||
|
|
d0acadd727 | ||
|
|
9a811901ef | ||
|
|
4a7af0d90f | ||
|
|
0f52679d2e | ||
|
|
e00bc543ad | ||
|
|
1e8c040307 | ||
|
|
7c90c0205c | ||
|
|
a95439db61 | ||
|
|
f5fcb8a32c | ||
|
|
ce0cefe053 | ||
|
|
35e7103093 | ||
|
|
426a9755d9 | ||
|
|
c14bb310ce | ||
|
|
ccee5c781b | ||
|
|
d5934d65de | ||
|
|
39f9ab375b | ||
|
|
28a3cd1028 | ||
|
|
f987138760 | ||
|
|
1803c596dc | ||
|
|
6042fdd44c | ||
|
|
c56023163b | ||
|
|
1caa678592 | ||
|
|
ddaee7c1be | ||
|
|
c030a50228 | ||
|
|
e4c6db86b8 | ||
|
|
a7b63631b0 | ||
|
|
cdff23ad0b | ||
|
|
3635039d2b | ||
|
|
711e049432 | ||
|
|
57c4f24573 | ||
|
|
808f96cc8f | ||
|
|
2a9d0cc5af | ||
|
|
1fa4cfb004 | ||
|
|
44d2b36eff | ||
|
|
bb830b178a | ||
|
|
c6b1b30bb5 | ||
|
|
5f1430b0bd | ||
|
|
b818d43967 | ||
|
|
a21085b86b | ||
|
|
89c3761e5c | ||
|
|
893fc90379 | ||
|
|
41b1b3947c | ||
|
|
c23dab7adc | ||
|
|
cc75c6a6e9 | ||
|
|
ee49838173 | ||
|
|
a725c0fe3d | ||
|
|
5d09ddb574 | ||
|
|
0c2a0f45ec | ||
|
|
4ac28d1d48 | ||
|
|
9d4f14582b | ||
|
|
a5a14974a1 | ||
|
|
9baa17379e | ||
|
|
225b5e5e5a | ||
|
|
741fd8b61c | ||
|
|
fe2ea0ce88 | ||
|
|
fa49002626 | ||
|
|
ca1a84cb93 | ||
|
|
61a3331fe2 | ||
|
|
4932924d67 | ||
|
|
66cd46d9bc | ||
|
|
979c60bc7c | ||
|
|
6203743160 | ||
|
|
738448aa0d | ||
|
|
74989fb284 | ||
|
|
22377b86a3 | ||
|
|
5764d0c28d | ||
|
|
c198ef11b9 | ||
|
|
caf98496b7 | ||
|
|
684000d9a5 | ||
|
|
00f9e24368 | ||
|
|
361743b222 | ||
|
|
ce2938d274 | ||
|
|
6fe78cec8a | ||
|
|
8cc2f6ba9b | ||
|
|
8ea119da4a | ||
|
|
f864b515d9 | ||
|
|
3003f52e1d | ||
|
|
cc934f8264 | ||
|
|
1327910cda | ||
|
|
3b7f2ddd3c | ||
|
|
82b1fdca1f | ||
|
|
1b86eb76fc | ||
|
|
ea0e4de698 | ||
|
|
6e7adbe74d | ||
|
|
a58b35c01b | ||
|
|
5e6305573f |
No files matched your search
@@ -36,11 +36,6 @@ def FlagsForFile(filename):
|
||||
|
||||
flag_list = shlex.split(out.getvalue())
|
||||
|
||||
# This flag is added by Fennec for android build and causes ycmd to fail to parse the file.
|
||||
# Removing this flag is a workaround until ycmd starts to handle this flag properly.
|
||||
# https://github.com/Valloric/YouCompleteMe/issues/1490
|
||||
final_flags = [x for x in flag_list if not x.startswith('-march=armv')]
|
||||
|
||||
return {
|
||||
'flags': final_flags,
|
||||
'do_cache': True
|
||||
|
||||
@@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Clobber for NSS update
|
||||
Issue #1971 - Update to ICU 63 requires clobber
|
||||
+2
-38
@@ -137,16 +137,10 @@ default:: $(BUILD_BACKEND_FILES)
|
||||
endif
|
||||
|
||||
install_manifests := \
|
||||
$(addprefix dist/,branding idl include public private sdk xpi-stage) \
|
||||
$(addprefix dist/,branding bin idl include public private sdk xpi-stage) \
|
||||
_tests \
|
||||
$(NULL)
|
||||
# Skip the dist/bin install manifest when using the hybrid
|
||||
# FasterMake/RecursiveMake backend. This is a hack until bug 1241744 moves
|
||||
# xpidl handling to FasterMake in that case, mechanically making the dist/bin
|
||||
# install manifest non-existent (non-existent manifests being skipped)
|
||||
ifeq (,$(filter FasterMake+RecursiveMake,$(BUILD_BACKENDS)))
|
||||
install_manifests += dist/bin
|
||||
endif
|
||||
|
||||
install_manifest_depends = \
|
||||
CLOBBER \
|
||||
$(configure_dir)/configure \
|
||||
@@ -166,27 +160,6 @@ endif
|
||||
.PHONY: install-manifests
|
||||
install-manifests: $(addprefix install-,$(install_manifests))
|
||||
|
||||
# If we're using the hybrid FasterMake/RecursiveMake backend, we want
|
||||
# to recurse in the faster/ directory in parallel of install manifests.
|
||||
# But dist/idl needs to happen before (cf. dependencies in
|
||||
# config/faster/rules.mk)
|
||||
ifneq (,$(filter FasterMake+RecursiveMake,$(BUILD_BACKENDS)))
|
||||
install-manifests: faster
|
||||
.PHONY: faster
|
||||
faster: install-dist/idl
|
||||
$(MAKE) -C faster FASTER_RECURSIVE_MAKE=1
|
||||
endif
|
||||
|
||||
.PHONY: tup
|
||||
tup:
|
||||
$(call BUILDSTATUS,TIERS make tup)
|
||||
$(call BUILDSTATUS,TIER_START make)
|
||||
$(MAKE) install-manifests buildid.h source-repo.h
|
||||
$(call BUILDSTATUS,TIER_FINISH make)
|
||||
$(call BUILDSTATUS,TIER_START tup)
|
||||
@$(TUP) $(if $(findstring s,$(filter-out --%,$(MAKEFLAGS))),,--verbose)
|
||||
$(call BUILDSTATUS,TIER_FINISH tup)
|
||||
|
||||
# process_install_manifest needs to be invoked with --no-remove when building
|
||||
# js as standalone because automated builds are building nspr separately and
|
||||
# that would remove the resulting files.
|
||||
@@ -198,17 +171,8 @@ endif
|
||||
|
||||
.PHONY: $(addprefix install-,$(subst /,_,$(install_manifests)))
|
||||
$(addprefix install-,$(install_manifests)): install-%: $(install_manifest_depends)
|
||||
ifneq (,$(filter FasterMake+RecursiveMake,$(BUILD_BACKENDS)))
|
||||
@# If we're using the hybrid FasterMake/RecursiveMake backend, we want
|
||||
@# to ensure the FasterMake end doesn't have install manifests for the
|
||||
@# same directory, because that would blow up
|
||||
$(if $(wildcard _build_manifests/install/$(subst /,_,$*)),$(if $(wildcard faster/install_$(subst /,_,$*)*),$(error FasterMake and RecursiveMake ends of the hybrid build system want to handle $*)))
|
||||
endif
|
||||
$(addprefix $(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$*) ,$(wildcard _build_manifests/install/$(subst /,_,$*)))
|
||||
|
||||
# Dummy wrapper rule to allow the faster backend to piggy back
|
||||
$(addprefix install-,$(subst /,_,$(filter dist/%,$(install_manifests)))): install-dist_%: install-dist/% ;
|
||||
|
||||
.PHONY: install-tests
|
||||
install-tests: install-test-files
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ selective cherry-picking of directly-applicable patches, this repository has its
|
||||
own development and holds the base for a maintained platform to be used by XUL
|
||||
applications.
|
||||
|
||||
For a list of active projects making use of the Unified XUL Platform, checkout http://thereisonlyxul.org/.
|
||||
|
||||
## Additional documentation
|
||||
|
||||
Additional documentation relevant to this source code can be found in the `/docs`
|
||||
@@ -23,7 +21,7 @@ You are also always welcome to get in touch with our community on the [Pale Moon
|
||||
|
||||
### A note about trademarks and branding
|
||||
|
||||
Although this repository is licensed under Mozilla Public License v2.0, the
|
||||
Although this repository is primarily licensed under Mozilla Public License v2.0, the
|
||||
trademarks and brands contained herein remain the property of their respective
|
||||
owners. For more details, please see the notifications in the respective directories.
|
||||
|
||||
|
||||
+2
-3
@@ -15,14 +15,14 @@ What should be considered vulnerabilities or security hazards by default:
|
||||
|
||||
Generally not security vulnerabilities:
|
||||
- Null dereferencing crashes;
|
||||
- Malware extensions (but please do report those on the forum in the extensions board!);
|
||||
- Malware extensions (but please do report those on the forum in the add-ons board!);
|
||||
- Denial-of-service (AKA "evil trap sites")
|
||||
- Browser hangs
|
||||
- Issues with non-standard manual configuration (either at build time or by manipulating about:config directly)
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you find an issue in UXP or the applications it builds on that could impact the security or safety of users please **do not**
|
||||
If you find an issue in UXP, or the applications building on it, that could impact the security or safety of users please **do not**
|
||||
make an issue on Gitea about it. Gitea does not support restricted viewability for security sensitive bugs.
|
||||
|
||||
If you want to report a security-sensitive issue then please go to the [forum](https://forum.palemoon.org) and report the issue
|
||||
@@ -33,4 +33,3 @@ except the recipient (not even moderators!).
|
||||
You will be informed via private message if the vulnerability report is accepted or declined, with reasoning.
|
||||
Security updates occur regularly and are given priority over most other development tasks. In general, they can be solved
|
||||
relatively quickly and will be included in the next point release (third digit if not rolled into a more major one).
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
#include "AccIterator.h"
|
||||
|
||||
#include "AccGroupInfo.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "XULTreeAccessible.h"
|
||||
#endif
|
||||
|
||||
#include "mozilla/dom/HTMLLabelElement.h"
|
||||
|
||||
|
||||
@@ -341,8 +341,6 @@ LogRequest(nsIRequest* aRequest)
|
||||
printf("targeted; ");
|
||||
if (loadFlags & nsIChannel::LOAD_CALL_CONTENT_SNIFFERS)
|
||||
printf("call content sniffers; ");
|
||||
if (loadFlags & nsIChannel::LOAD_CLASSIFY_URI)
|
||||
printf("classify uri; ");
|
||||
} else {
|
||||
printf(" no request");
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
@@ -35,10 +35,10 @@ EPlatformDisabledState PlatformDisabledState();
|
||||
void PreInit();
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_ACCESSIBILITY_ATK)
|
||||
#if defined(MOZ_ACCESSIBILITY_ATK) || defined(XP_MACOSX)
|
||||
/**
|
||||
* Is platform accessibility enabled.
|
||||
* Only used on linux with atk.
|
||||
* Only used on linux with atk and MacOS for now.
|
||||
*/
|
||||
bool ShouldA11yBeEnabled();
|
||||
#endif
|
||||
|
||||
@@ -96,6 +96,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
'/accessible/windows/ia2',
|
||||
'/accessible/windows/msaa',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/mac',
|
||||
]
|
||||
else:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/other',
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsDeckFrame.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "XULAlertAccessible.h"
|
||||
#include "XULColorPickerAccessible.h"
|
||||
#include "XULComboboxAccessible.h"
|
||||
@@ -79,7 +78,6 @@
|
||||
#include "XULSliderAccessible.h"
|
||||
#include "XULTabAccessible.h"
|
||||
#include "XULTreeGridAccessibleWrap.h"
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
@@ -1356,7 +1354,6 @@ nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
|
||||
}
|
||||
|
||||
RefPtr<Accessible> accessible;
|
||||
#ifdef MOZ_XUL
|
||||
// XUL controls
|
||||
if (role.EqualsLiteral("xul:alert")) {
|
||||
accessible = new XULAlertAccessible(aContent, aDoc);
|
||||
@@ -1515,7 +1512,6 @@ nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
|
||||
accessible = new XULToolbarButtonAccessible(aContent, aDoc);
|
||||
|
||||
}
|
||||
#endif // MOZ_XUL
|
||||
|
||||
return accessible.forget();
|
||||
}
|
||||
@@ -1739,7 +1735,6 @@ nsAccessibilityService::HasAccessible(nsIDOMNode* aDOMNode)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessibilityService private (DON'T put methods here)
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
already_AddRefed<Accessible>
|
||||
nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
|
||||
DocAccessible* aDoc)
|
||||
@@ -1769,7 +1764,6 @@ nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
|
||||
new XULTreeGridAccessibleWrap(aContent, aDoc, treeFrame);
|
||||
return accessible.forget();
|
||||
}
|
||||
#endif
|
||||
|
||||
nsAccessibilityService*
|
||||
GetOrCreateAccService(uint32_t aNewConsumer)
|
||||
|
||||
@@ -274,13 +274,11 @@ private:
|
||||
CreateAccessibleByFrameType(nsIFrame* aFrame, nsIContent* aContent,
|
||||
Accessible* aContext);
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
/**
|
||||
* Create accessible for XUL tree element.
|
||||
*/
|
||||
already_AddRefed<Accessible>
|
||||
CreateAccessibleForXULTree(nsIContent* aContent, DocAccessible* aDoc);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Reference for accessibility service instance.
|
||||
|
||||
@@ -48,9 +48,7 @@
|
||||
#include "mozilla/dom/DocumentType.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsIXULDocument.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@@ -210,11 +208,9 @@ DocAccessible::NativeRole()
|
||||
return roles::CHROME_WINDOW;
|
||||
|
||||
if (itemType == nsIDocShellTreeItem::typeContent) {
|
||||
#ifdef MOZ_XUL
|
||||
nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocumentNode));
|
||||
if (xulDoc)
|
||||
return roles::APPLICATION;
|
||||
#endif
|
||||
return roles::DOCUMENT;
|
||||
}
|
||||
}
|
||||
@@ -387,13 +383,11 @@ DocAccessible::URL(nsAString& aURL) const
|
||||
void
|
||||
DocAccessible::DocType(nsAString& aType) const
|
||||
{
|
||||
#ifdef MOZ_XUL
|
||||
nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocumentNode));
|
||||
if (xulDoc) {
|
||||
aType.AssignLiteral("window"); // doctype not implemented for XUL at time of writing - causes assertion
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
dom::DocumentType* docType = mDocumentNode->GetDoctype();
|
||||
if (docType)
|
||||
docType->GetPublicId(aType);
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
#include "Relation.h"
|
||||
#include "Role.h"
|
||||
#include "States.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "XULTreeAccessible.h"
|
||||
#endif
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
@@ -43,10 +41,8 @@
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsIXULDocument.h"
|
||||
#include "nsIXULWindow.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@@ -102,7 +98,6 @@ RootAccessible::NativeRole()
|
||||
}
|
||||
|
||||
// RootAccessible protected member
|
||||
#ifdef MOZ_XUL
|
||||
uint32_t
|
||||
RootAccessible::GetChromeFlags()
|
||||
{
|
||||
@@ -122,7 +117,6 @@ RootAccessible::GetChromeFlags()
|
||||
xulWin->GetChromeFlags(&chromeFlags);
|
||||
return chromeFlags;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t
|
||||
RootAccessible::NativeState()
|
||||
@@ -131,7 +125,6 @@ RootAccessible::NativeState()
|
||||
if (state & states::DEFUNCT)
|
||||
return state;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
uint32_t chromeFlags = GetChromeFlags();
|
||||
if (chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE)
|
||||
state |= states::SIZEABLE;
|
||||
@@ -142,7 +135,6 @@ RootAccessible::NativeState()
|
||||
state |= states::MOVEABLE;
|
||||
if (chromeFlags & nsIWebBrowserChrome::CHROME_MODAL)
|
||||
state |= states::MODAL;
|
||||
#endif
|
||||
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm && fm->GetActiveWindow() == mDocumentNode->GetWindow())
|
||||
@@ -292,7 +284,6 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
||||
if (!accessible)
|
||||
return;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
XULTreeAccessible* treeAcc = accessible->AsXULTree();
|
||||
if (treeAcc) {
|
||||
if (eventType.EqualsLiteral("TreeRowCountChanged")) {
|
||||
@@ -305,7 +296,6 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (eventType.EqualsLiteral("RadioStateChange")) {
|
||||
uint64_t state = accessible->State();
|
||||
@@ -341,7 +331,6 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
||||
}
|
||||
|
||||
Accessible* treeItemAcc = nullptr;
|
||||
#ifdef MOZ_XUL
|
||||
// If it's a tree element, need the currently selected item.
|
||||
if (treeAcc) {
|
||||
treeItemAcc = accessible->CurrentItem();
|
||||
@@ -385,29 +374,22 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
||||
nsEventShell::FireEvent(selChangeEvent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (eventType.EqualsLiteral("AlertActive")) {
|
||||
} else if (eventType.EqualsLiteral("AlertActive")) {
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_ALERT, accessible);
|
||||
}
|
||||
else if (eventType.EqualsLiteral("popupshown")) {
|
||||
} else if (eventType.EqualsLiteral("popupshown")) {
|
||||
HandlePopupShownEvent(accessible);
|
||||
}
|
||||
else if (eventType.EqualsLiteral("DOMMenuInactive")) {
|
||||
} else if (eventType.EqualsLiteral("DOMMenuInactive")) {
|
||||
if (accessible->Role() == roles::MENUPOPUP) {
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
|
||||
accessible);
|
||||
}
|
||||
}
|
||||
else if (eventType.EqualsLiteral("DOMMenuItemActive")) {
|
||||
} else if (eventType.EqualsLiteral("DOMMenuItemActive")) {
|
||||
FocusMgr()->ActiveItemChanged(accessible);
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eFocus))
|
||||
logging::ActiveItemChangeCausedBy("DOMMenuItemActive", accessible);
|
||||
#endif
|
||||
}
|
||||
else if (eventType.EqualsLiteral("DOMMenuItemInactive")) {
|
||||
} else if (eventType.EqualsLiteral("DOMMenuItemInactive")) {
|
||||
// Process DOMMenuItemInactive event for autocomplete only because this is
|
||||
// unique widget that may acquire focus from autocomplete popup while popup
|
||||
// stays open and has no active item. In case of XUL tree autocomplete
|
||||
@@ -421,8 +403,7 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
||||
logging::ActiveItemChangeCausedBy("DOMMenuItemInactive", accessible);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (eventType.EqualsLiteral("DOMMenuBarActive")) { // Always from user input
|
||||
} else if (eventType.EqualsLiteral("DOMMenuBarActive")) { // Always from user input
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_START,
|
||||
accessible, eFromUserInput);
|
||||
|
||||
@@ -440,8 +421,7 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
||||
logging::ActiveItemChangeCausedBy("DOMMenuBarActive", accessible);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (eventType.EqualsLiteral("DOMMenuBarInactive")) { // Always from user input
|
||||
} else if (eventType.EqualsLiteral("DOMMenuBarInactive")) { // Always from user input
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_END,
|
||||
accessible, eFromUserInput);
|
||||
|
||||
@@ -450,8 +430,7 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
||||
if (logging::IsEnabled(logging::eFocus))
|
||||
logging::ActiveItemChangeCausedBy("DOMMenuBarInactive", accessible);
|
||||
#endif
|
||||
}
|
||||
else if (accessible->NeedsDOMUIEvent() &&
|
||||
} else if (accessible->NeedsDOMUIEvent() &&
|
||||
eventType.EqualsLiteral("ValueChange")) {
|
||||
uint32_t event = accessible->HasNumericValue()
|
||||
? nsIAccessibleEvent::EVENT_VALUE_CHANGE
|
||||
@@ -650,7 +629,6 @@ RootAccessible::HandlePopupHidingEvent(nsINode* aPopupNode)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
void
|
||||
RootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
|
||||
XULTreeAccessible* aAccessible)
|
||||
@@ -714,7 +692,6 @@ RootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
|
||||
|
||||
aAccessible->TreeViewInvalidated(startRow, endRow, startCol, endCol);
|
||||
}
|
||||
#endif
|
||||
|
||||
ProxyAccessible*
|
||||
RootAccessible::GetPrimaryRemoteTopLevelContentDoc() const
|
||||
|
||||
@@ -70,14 +70,12 @@ protected:
|
||||
*/
|
||||
void HandlePopupHidingEvent(nsINode* aNode);
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
void HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
|
||||
XULTreeAccessible* aAccessible);
|
||||
void HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
|
||||
XULTreeAccessible* aAccessible);
|
||||
void HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
|
||||
XULTreeAccessible* aAccessible);
|
||||
void HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
|
||||
XULTreeAccessible* aAccessible);
|
||||
|
||||
uint32_t GetChromeFlags();
|
||||
#endif
|
||||
uint32_t GetChromeFlags();
|
||||
};
|
||||
|
||||
inline RootAccessible*
|
||||
|
||||
@@ -52,6 +52,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
'/accessible/windows/ia2',
|
||||
'/accessible/windows/msaa',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/mac',
|
||||
]
|
||||
else:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/other',
|
||||
|
||||
@@ -32,6 +32,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
'/accessible/windows/ia2',
|
||||
'/accessible/windows/msaa',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/mac',
|
||||
]
|
||||
else:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/other',
|
||||
|
||||
@@ -19,6 +19,10 @@ else:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/atk',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/mac',
|
||||
]
|
||||
else:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/other',
|
||||
|
||||
@@ -28,6 +28,10 @@ if CONFIG['ACCESSIBILITY']:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/atk',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/mac',
|
||||
]
|
||||
else:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/other',
|
||||
|
||||
@@ -786,7 +786,7 @@ this.UtteranceGenerator = { // jshint ignore:line
|
||||
// This is because we expose the checked information on the node itself.
|
||||
// XXX: this means the checked state is always appended to the end,
|
||||
// regardless of the utterance ordering preference.
|
||||
if ((Utils.AndroidSdkVersion < 16 || Utils.MozBuildApp === 'browser') &&
|
||||
if (Utils.MozBuildApp === 'browser' &&
|
||||
aState.contains(States.CHECKABLE)) {
|
||||
let checked = aState.contains(States.CHECKED);
|
||||
let statetr;
|
||||
|
||||
@@ -39,13 +39,6 @@ var PointerRelay = { // jshint ignore:line
|
||||
delete this._eventsOfInterest;
|
||||
|
||||
switch (Utils.widgetToolkit) {
|
||||
case 'android':
|
||||
this._eventsOfInterest = {
|
||||
'touchstart' : true,
|
||||
'touchmove' : true,
|
||||
'touchend' : true };
|
||||
break;
|
||||
|
||||
default:
|
||||
// Desktop.
|
||||
this._eventsOfInterest = {
|
||||
@@ -110,11 +103,6 @@ var PointerRelay = { // jshint ignore:line
|
||||
target: aEvent.target
|
||||
}];
|
||||
|
||||
if (Utils.widgetToolkit === 'android' &&
|
||||
changedTouches.length === 1 && changedTouches[0].identifier === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (changedTouches.length === 1 &&
|
||||
changedTouches[0].identifier === SYNTH_ID) {
|
||||
return;
|
||||
|
||||
@@ -257,11 +257,8 @@ AndroidPresenter.prototype.pivotChanged =
|
||||
|
||||
let androidEvents = [];
|
||||
|
||||
let isExploreByTouch = (aReason == Ci.nsIAccessiblePivot.REASON_POINT &&
|
||||
Utils.AndroidSdkVersion >= 14);
|
||||
let focusEventType = (Utils.AndroidSdkVersion >= 16) ?
|
||||
this.ANDROID_VIEW_ACCESSIBILITY_FOCUSED :
|
||||
this.ANDROID_VIEW_FOCUSED;
|
||||
let isExploreByTouch = (aReason == Ci.nsIAccessiblePivot.REASON_POINT);
|
||||
let focusEventType = this.ANDROID_VIEW_ACCESSIBILITY_FOCUSED;
|
||||
|
||||
if (isExploreByTouch) {
|
||||
// This isn't really used by TalkBack so this is a half-hearted attempt
|
||||
@@ -270,25 +267,21 @@ AndroidPresenter.prototype.pivotChanged =
|
||||
}
|
||||
|
||||
let brailleOutput = {};
|
||||
if (Utils.AndroidSdkVersion >= 16) {
|
||||
if (!this._braillePresenter) {
|
||||
this._braillePresenter = new BraillePresenter();
|
||||
}
|
||||
brailleOutput = this._braillePresenter.pivotChanged(aContext, aReason).
|
||||
details;
|
||||
if (!this._braillePresenter) {
|
||||
this._braillePresenter = new BraillePresenter();
|
||||
}
|
||||
brailleOutput = this._braillePresenter.pivotChanged(aContext, aReason).
|
||||
details;
|
||||
|
||||
if (aReason === Ci.nsIAccessiblePivot.REASON_TEXT) {
|
||||
if (Utils.AndroidSdkVersion >= 16) {
|
||||
let adjustedText = aContext.textAndAdjustedOffsets;
|
||||
let adjustedText = aContext.textAndAdjustedOffsets;
|
||||
|
||||
androidEvents.push({
|
||||
eventType: this.ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
text: [adjustedText.text],
|
||||
fromIndex: adjustedText.startOffset,
|
||||
toIndex: adjustedText.endOffset
|
||||
});
|
||||
}
|
||||
androidEvents.push({
|
||||
eventType: this.ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
text: [adjustedText.text],
|
||||
fromIndex: adjustedText.startOffset,
|
||||
toIndex: adjustedText.endOffset
|
||||
});
|
||||
} else {
|
||||
let state = Utils.getState(aContext.accessible);
|
||||
androidEvents.push({eventType: (isExploreByTouch) ?
|
||||
@@ -371,7 +364,7 @@ AndroidPresenter.prototype.textSelectionChanged =
|
||||
aOldEnd, aIsFromUserInput) {
|
||||
let androidEvents = [];
|
||||
|
||||
if (Utils.AndroidSdkVersion >= 14 && !aIsFromUserInput) {
|
||||
if (!aIsFromUserInput) {
|
||||
if (!this._braillePresenter) {
|
||||
this._braillePresenter = new BraillePresenter();
|
||||
}
|
||||
@@ -388,7 +381,7 @@ AndroidPresenter.prototype.textSelectionChanged =
|
||||
});
|
||||
}
|
||||
|
||||
if (Utils.AndroidSdkVersion >= 16 && aIsFromUserInput) {
|
||||
if (aIsFromUserInput) {
|
||||
let [from, to] = aOldStart < aStart ?
|
||||
[aOldStart, aStart] : [aStart, aOldStart];
|
||||
androidEvents.push({
|
||||
@@ -407,10 +400,6 @@ AndroidPresenter.prototype.textSelectionChanged =
|
||||
|
||||
AndroidPresenter.prototype.viewportChanged =
|
||||
function AndroidPresenter_viewportChanged(aWindow, aCurrentContext) {
|
||||
if (Utils.AndroidSdkVersion < 14) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let events = [{
|
||||
eventType: this.ANDROID_VIEW_SCROLLED,
|
||||
text: [],
|
||||
@@ -420,7 +409,7 @@ AndroidPresenter.prototype.viewportChanged =
|
||||
maxScrollY: aWindow.scrollMaxY
|
||||
}];
|
||||
|
||||
if (Utils.AndroidSdkVersion >= 16 && aCurrentContext) {
|
||||
if (aCurrentContext) {
|
||||
let currentAcc = aCurrentContext.accessibleForBounds;
|
||||
if (Utils.isAliveAndVisible(currentAcc)) {
|
||||
events.push({
|
||||
@@ -447,8 +436,7 @@ AndroidPresenter.prototype.announce =
|
||||
return {
|
||||
type: this.type,
|
||||
details: [{
|
||||
eventType: (Utils.AndroidSdkVersion >= 16) ?
|
||||
this.ANDROID_ANNOUNCEMENT : this.ANDROID_VIEW_TEXT_CHANGED,
|
||||
eventType: this.ANDROID_ANNOUNCEMENT,
|
||||
text: [localizedAnnouncement],
|
||||
addedCount: localizedAnnouncement.length,
|
||||
removedCount: 0,
|
||||
|
||||
@@ -109,35 +109,13 @@ this.Utils = { // jshint ignore:line
|
||||
return this._ScriptName;
|
||||
},
|
||||
|
||||
get AndroidSdkVersion() {
|
||||
if (!this._AndroidSdkVersion) {
|
||||
if (Services.appinfo.OS == 'Android') {
|
||||
this._AndroidSdkVersion = Services.sysinfo.getPropertyAsInt32(
|
||||
'version');
|
||||
} else {
|
||||
// Most useful in desktop debugging.
|
||||
this._AndroidSdkVersion = 16;
|
||||
}
|
||||
}
|
||||
return this._AndroidSdkVersion;
|
||||
},
|
||||
|
||||
set AndroidSdkVersion(value) {
|
||||
// When we want to mimic another version.
|
||||
this._AndroidSdkVersion = value;
|
||||
},
|
||||
|
||||
get BrowserApp() {
|
||||
if (!this.win) {
|
||||
return null;
|
||||
}
|
||||
switch (this.MozBuildApp) {
|
||||
case 'mobile/android':
|
||||
return this.win.BrowserApp;
|
||||
case 'browser':
|
||||
return this.win.gBrowser;
|
||||
case 'b2g':
|
||||
return this.win.shell;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@@ -147,9 +125,6 @@ this.Utils = { // jshint ignore:line
|
||||
if (!this.BrowserApp) {
|
||||
return null;
|
||||
}
|
||||
if (this.MozBuildApp == 'b2g') {
|
||||
return this.BrowserApp.contentBrowser;
|
||||
}
|
||||
return this.BrowserApp.selectedBrowser;
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_A11Y_ARIAGRIDACCESSIBLEWRAP_H
|
||||
#define MOZILLA_A11Y_ARIAGRIDACCESSIBLEWRAP_H
|
||||
|
||||
#include "ARIAGridAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
typedef class ARIAGridAccessible ARIAGridAccessibleWrap;
|
||||
typedef class ARIAGridCellAccessible ARIAGridCellAccessibleWrap;
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* For documentation of the accessibility architecture,
|
||||
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
|
||||
*/
|
||||
|
||||
#ifndef _AccessibleWrap_H_
|
||||
#define _AccessibleWrap_H_
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
#include "Accessible.h"
|
||||
#include "States.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsTArray.h"
|
||||
|
||||
#if defined(__OBJC__)
|
||||
@class mozAccessible;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
class AccessibleWrap : public Accessible
|
||||
{
|
||||
public: // construction, destruction
|
||||
AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc);
|
||||
virtual ~AccessibleWrap();
|
||||
|
||||
/**
|
||||
* Get the native Obj-C object (mozAccessible).
|
||||
*/
|
||||
virtual void GetNativeInterface(void** aOutAccessible) override;
|
||||
|
||||
/**
|
||||
* The objective-c |Class| type that this accessible's native object
|
||||
* should be instantied with. used on runtime to determine the
|
||||
* right type for this accessible's associated native object.
|
||||
*/
|
||||
virtual Class GetNativeType ();
|
||||
|
||||
virtual void Shutdown () override;
|
||||
|
||||
virtual bool InsertChildAt(uint32_t aIdx, Accessible* aChild) override;
|
||||
virtual bool RemoveChild(Accessible* aAccessible) override;
|
||||
|
||||
virtual nsresult HandleAccEvent(AccEvent* aEvent) override;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Return true if the parent doesn't have children to expose to AT.
|
||||
*/
|
||||
bool AncestorIsFlat();
|
||||
|
||||
/**
|
||||
* Get the native object. Create it if needed.
|
||||
*/
|
||||
#if defined(__OBJC__)
|
||||
mozAccessible* GetNativeObject();
|
||||
#else
|
||||
id GetNativeObject();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Our native object. Private because its creation is done lazily.
|
||||
* Don't access it directly. Ever. Unless you are GetNativeObject() or
|
||||
* Shutdown()
|
||||
*/
|
||||
#if defined(__OBJC__)
|
||||
// if we are in Objective-C, we use the actual Obj-C class.
|
||||
mozAccessible* mNativeObject;
|
||||
#else
|
||||
id mNativeObject;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* We have created our native. This does not mean there is one.
|
||||
* This can never go back to false.
|
||||
* We need it because checking whether we need a native object cost time.
|
||||
*/
|
||||
bool mNativeInited;
|
||||
};
|
||||
|
||||
#if defined(__OBJC__)
|
||||
void FireNativeEvent(mozAccessible* aNativeAcc, uint32_t aEventType);
|
||||
#else
|
||||
void FireNativeEvent(id aNativeAcc, uint32_t aEventType);
|
||||
#endif
|
||||
|
||||
Class GetTypeFromRole(roles::Role aRole);
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,256 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DocAccessible.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
|
||||
#include "Accessible-inl.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "Role.h"
|
||||
|
||||
#import "mozAccessible.h"
|
||||
#import "mozActionElements.h"
|
||||
#import "mozHTMLAccessible.h"
|
||||
#import "mozTableAccessible.h"
|
||||
#import "mozTextAccessible.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
AccessibleWrap::
|
||||
AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
Accessible(aContent, aDoc), mNativeObject(nil),
|
||||
mNativeInited(false)
|
||||
{
|
||||
}
|
||||
|
||||
AccessibleWrap::~AccessibleWrap()
|
||||
{
|
||||
}
|
||||
|
||||
mozAccessible*
|
||||
AccessibleWrap::GetNativeObject()
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (!mNativeInited && !mNativeObject && !IsDefunct() && !AncestorIsFlat()) {
|
||||
uintptr_t accWrap = reinterpret_cast<uintptr_t>(this);
|
||||
mNativeObject = [[GetNativeType() alloc] initWithAccessible:accWrap];
|
||||
}
|
||||
|
||||
mNativeInited = true;
|
||||
|
||||
return mNativeObject;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
void
|
||||
AccessibleWrap::GetNativeInterface(void** aOutInterface)
|
||||
{
|
||||
*aOutInterface = static_cast<void*>(GetNativeObject());
|
||||
}
|
||||
|
||||
// overridden in subclasses to create the right kind of object. by default we create a generic
|
||||
// 'mozAccessible' node.
|
||||
Class
|
||||
AccessibleWrap::GetNativeType ()
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (IsXULTabpanels())
|
||||
return [mozPaneAccessible class];
|
||||
|
||||
if (IsTable())
|
||||
return [mozTableAccessible class];
|
||||
|
||||
if (IsTableRow())
|
||||
return [mozTableRowAccessible class];
|
||||
|
||||
if (IsTableCell())
|
||||
return [mozTableCellAccessible class];
|
||||
|
||||
return GetTypeFromRole(Role());
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
// this method is very important. it is fired when an accessible object "dies". after this point
|
||||
// the object might still be around (because some 3rd party still has a ref to it), but it is
|
||||
// in fact 'dead'.
|
||||
void
|
||||
AccessibleWrap::Shutdown ()
|
||||
{
|
||||
// this ensure we will not try to re-create the native object.
|
||||
mNativeInited = true;
|
||||
|
||||
// we really intend to access the member directly.
|
||||
if (mNativeObject) {
|
||||
[mNativeObject expire];
|
||||
[mNativeObject release];
|
||||
mNativeObject = nil;
|
||||
}
|
||||
|
||||
Accessible::Shutdown();
|
||||
}
|
||||
|
||||
nsresult
|
||||
AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
nsresult rv = Accessible::HandleAccEvent(aEvent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (IPCAccessibilityActive()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t eventType = aEvent->GetEventType();
|
||||
|
||||
// ignore everything but focus-changed, value-changed, caret, selection
|
||||
// and document load complete events for now.
|
||||
if (eventType != nsIAccessibleEvent::EVENT_FOCUS &&
|
||||
eventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
|
||||
eventType != nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE &&
|
||||
eventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
|
||||
eventType != nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED &&
|
||||
eventType != nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE)
|
||||
return NS_OK;
|
||||
|
||||
Accessible* accessible = aEvent->GetAccessible();
|
||||
NS_ENSURE_STATE(accessible);
|
||||
|
||||
mozAccessible *nativeAcc = nil;
|
||||
accessible->GetNativeInterface((void**)&nativeAcc);
|
||||
if (!nativeAcc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
FireNativeEvent(nativeAcc, eventType);
|
||||
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
bool
|
||||
AccessibleWrap::InsertChildAt(uint32_t aIdx, Accessible* aAccessible)
|
||||
{
|
||||
bool inserted = Accessible::InsertChildAt(aIdx, aAccessible);
|
||||
if (inserted && mNativeObject)
|
||||
[mNativeObject appendChild:aAccessible];
|
||||
|
||||
return inserted;
|
||||
}
|
||||
|
||||
bool
|
||||
AccessibleWrap::RemoveChild(Accessible* aAccessible)
|
||||
{
|
||||
bool removed = Accessible::RemoveChild(aAccessible);
|
||||
|
||||
if (removed && mNativeObject)
|
||||
[mNativeObject invalidateChildren];
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccessibleWrap protected
|
||||
|
||||
bool
|
||||
AccessibleWrap::AncestorIsFlat()
|
||||
{
|
||||
// We don't create a native object if we're child of a "flat" accessible;
|
||||
// for example, on OS X buttons shouldn't have any children, because that
|
||||
// makes the OS confused.
|
||||
//
|
||||
// To maintain a scripting environment where the XPCOM accessible hierarchy
|
||||
// look the same on all platforms, we still let the C++ objects be created
|
||||
// though.
|
||||
|
||||
Accessible* parent = Parent();
|
||||
while (parent) {
|
||||
if (nsAccUtils::MustPrune(parent))
|
||||
return true;
|
||||
|
||||
parent = parent->Parent();
|
||||
}
|
||||
// no parent was flat
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
a11y::FireNativeEvent(mozAccessible* aNativeAcc, uint32_t aEventType)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
switch (aEventType) {
|
||||
case nsIAccessibleEvent::EVENT_FOCUS:
|
||||
[aNativeAcc didReceiveFocus];
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
|
||||
case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE:
|
||||
[aNativeAcc valueDidChange];
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
|
||||
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
|
||||
[aNativeAcc selectedTextDidChange];
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
|
||||
[aNativeAcc documentLoadComplete];
|
||||
break;
|
||||
}
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
Class
|
||||
a11y::GetTypeFromRole(roles::Role aRole)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
switch (aRole) {
|
||||
case roles::COMBOBOX:
|
||||
case roles::PUSHBUTTON:
|
||||
case roles::SPLITBUTTON:
|
||||
case roles::TOGGLE_BUTTON:
|
||||
{
|
||||
return [mozButtonAccessible class];
|
||||
}
|
||||
|
||||
case roles::PAGETAB:
|
||||
return [mozButtonAccessible class];
|
||||
|
||||
case roles::CHECKBUTTON:
|
||||
return [mozCheckboxAccessible class];
|
||||
|
||||
case roles::HEADING:
|
||||
return [mozHeadingAccessible class];
|
||||
|
||||
case roles::PAGETABLIST:
|
||||
return [mozTabsAccessible class];
|
||||
|
||||
case roles::ENTRY:
|
||||
case roles::STATICTEXT:
|
||||
case roles::CAPTION:
|
||||
case roles::ACCEL_LABEL:
|
||||
case roles::PASSWORD_TEXT:
|
||||
// normal textfield (static or editable)
|
||||
return [mozTextAccessible class];
|
||||
|
||||
case roles::TEXT_LEAF:
|
||||
return [mozTextLeafAccessible class];
|
||||
|
||||
case roles::LINK:
|
||||
return [mozLinkAccessible class];
|
||||
|
||||
default:
|
||||
return [mozAccessible class];
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim:expandtab:shiftwidth=4:tabstop=4:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_ApplicationAccessibleWrap_h__
|
||||
#define mozilla_a11y_ApplicationAccessibleWrap_h__
|
||||
|
||||
#include "ApplicationAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
typedef ApplicationAccessible ApplicationAccessibleWrap;
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_DocAccessibleWrap_h__
|
||||
#define mozilla_a11y_DocAccessibleWrap_h__
|
||||
|
||||
#include "DocAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
class DocAccessibleWrap : public DocAccessible
|
||||
{
|
||||
public:
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
|
||||
virtual ~DocAccessibleWrap();
|
||||
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DocAccessibleWrap.h"
|
||||
|
||||
#import "mozAccessible.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
DocAccessibleWrap::
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
|
||||
DocAccessible(aDocument, aPresShell)
|
||||
{
|
||||
}
|
||||
|
||||
DocAccessibleWrap::~DocAccessibleWrap()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_HTMLTableAccessibleWrap_h__
|
||||
#define mozilla_a11y_HTMLTableAccessibleWrap_h__
|
||||
|
||||
#include "HTMLTableAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
typedef class HTMLTableAccessible HTMLTableAccessibleWrap;
|
||||
typedef class HTMLTableCellAccessible HTMLTableCellAccessibleWrap;
|
||||
typedef class HTMLTableHeaderCellAccessible HTMLTableHeaderCellAccessibleWrap;
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_HyperTextAccessibleWrap_h__
|
||||
#define mozilla_a11y_HyperTextAccessibleWrap_h__
|
||||
|
||||
#include "HyperTextAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
typedef class HyperTextAccessible HyperTextAccessibleWrap;
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_ImageAccessibleWrap_h__
|
||||
#define mozilla_a11y_ImageAccessibleWrap_h__
|
||||
|
||||
#include "ImageAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
typedef class ImageAccessible ImageAccessibleWrap;
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _MacUtils_H_
|
||||
#define _MacUtils_H_
|
||||
|
||||
@class NSString;
|
||||
class nsString;
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
namespace utils {
|
||||
|
||||
/**
|
||||
* Get a localized string from the string bundle.
|
||||
* Return nil if not found.
|
||||
*/
|
||||
NSString* LocalizedString(const nsString& aString);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import "MacUtils.h"
|
||||
|
||||
#include "Accessible.h"
|
||||
|
||||
#include "nsCocoaUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
namespace utils {
|
||||
|
||||
/**
|
||||
* Get a localized string from the a11y string bundle.
|
||||
* Return nil if not found.
|
||||
*/
|
||||
NSString*
|
||||
LocalizedString(const nsString& aString)
|
||||
{
|
||||
nsString text;
|
||||
|
||||
Accessible::TranslateString(aString, text);
|
||||
|
||||
return text.IsEmpty() ? nil : nsCocoaUtils::ToNSString(text);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "Platform.h"
|
||||
#include "ProxyAccessible.h"
|
||||
#include "DocAccessibleParent.h"
|
||||
#include "mozTableAccessible.h"
|
||||
|
||||
#include "nsAppShell.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
// Mac a11y whitelisting
|
||||
static bool sA11yShouldBeEnabled = false;
|
||||
|
||||
bool
|
||||
ShouldA11yBeEnabled()
|
||||
{
|
||||
EPlatformDisabledState disabledState = PlatformDisabledState();
|
||||
return (disabledState == ePlatformIsForceEnabled) || ((disabledState == ePlatformIsEnabled) && sA11yShouldBeEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
PlatformInit()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PlatformShutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ProxyCreated(ProxyAccessible* aProxy, uint32_t)
|
||||
{
|
||||
// Pass in dummy state for now as retrieving proxy state requires IPC.
|
||||
// Note that we can use ProxyAccessible::IsTable* functions here because they
|
||||
// do not use IPC calls but that might change after bug 1210477.
|
||||
Class type;
|
||||
if (aProxy->IsTable())
|
||||
type = [mozTableAccessible class];
|
||||
else if (aProxy->IsTableRow())
|
||||
type = [mozTableRowAccessible class];
|
||||
else if (aProxy->IsTableCell())
|
||||
type = [mozTableCellAccessible class];
|
||||
else
|
||||
type = GetTypeFromRole(aProxy->Role());
|
||||
|
||||
uintptr_t accWrap = reinterpret_cast<uintptr_t>(aProxy) | IS_PROXY;
|
||||
mozAccessible* mozWrapper = [[type alloc] initWithAccessible:accWrap];
|
||||
aProxy->SetWrapper(reinterpret_cast<uintptr_t>(mozWrapper));
|
||||
|
||||
mozAccessible* nativeParent = nullptr;
|
||||
if (aProxy->IsDoc() && aProxy->AsDoc()->IsTopLevel()) {
|
||||
// If proxy is top level, the parent we need to invalidate the children of
|
||||
// will be a non-remote accessible.
|
||||
Accessible* outerDoc = aProxy->OuterDocOfRemoteBrowser();
|
||||
if (outerDoc) {
|
||||
nativeParent = GetNativeFromGeckoAccessible(outerDoc);
|
||||
}
|
||||
} else {
|
||||
// Non-top level proxies need proxy parents' children invalidated.
|
||||
ProxyAccessible* parent = aProxy->Parent();
|
||||
nativeParent = GetNativeFromProxy(parent);
|
||||
NS_ASSERTION(parent, "a non-top-level proxy is missing a parent?");
|
||||
}
|
||||
|
||||
if (nativeParent) {
|
||||
[nativeParent invalidateChildren];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProxyDestroyed(ProxyAccessible* aProxy)
|
||||
{
|
||||
mozAccessible* nativeParent = nil;
|
||||
if (aProxy->IsDoc() && aProxy->AsDoc()->IsTopLevel()) {
|
||||
// Invalidate native parent in parent process's children on proxy destruction
|
||||
Accessible* outerDoc = aProxy->OuterDocOfRemoteBrowser();
|
||||
if (outerDoc) {
|
||||
nativeParent = GetNativeFromGeckoAccessible(outerDoc);
|
||||
}
|
||||
} else {
|
||||
if (!aProxy->Document()->IsShutdown()) {
|
||||
// Only do if the document has not been shut down, else parent will return
|
||||
// garbage since we don't shut down children from top down.
|
||||
ProxyAccessible* parent = aProxy->Parent();
|
||||
// Invalidate proxy parent's children.
|
||||
if (parent) {
|
||||
nativeParent = GetNativeFromProxy(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mozAccessible* wrapper = GetNativeFromProxy(aProxy);
|
||||
[wrapper expire];
|
||||
[wrapper release];
|
||||
aProxy->SetWrapper(0);
|
||||
|
||||
if (nativeParent) {
|
||||
[nativeParent invalidateChildren];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProxyEvent(ProxyAccessible* aProxy, uint32_t aEventType)
|
||||
{
|
||||
// ignore everything but focus-changed, value-changed, caret and selection
|
||||
// events for now.
|
||||
if (aEventType != nsIAccessibleEvent::EVENT_FOCUS &&
|
||||
aEventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
|
||||
aEventType != nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE &&
|
||||
aEventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
|
||||
aEventType != nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED)
|
||||
return;
|
||||
|
||||
mozAccessible* wrapper = GetNativeFromProxy(aProxy);
|
||||
if (wrapper)
|
||||
FireNativeEvent(wrapper, aEventType);
|
||||
}
|
||||
|
||||
void
|
||||
ProxyStateChangeEvent(ProxyAccessible* aProxy, uint64_t, bool)
|
||||
{
|
||||
// mac doesn't care about state change events
|
||||
}
|
||||
|
||||
void
|
||||
ProxyCaretMoveEvent(ProxyAccessible* aTarget, int32_t aOffset)
|
||||
{
|
||||
mozAccessible* wrapper = GetNativeFromProxy(aTarget);
|
||||
if (wrapper)
|
||||
[wrapper selectedTextDidChange];
|
||||
}
|
||||
|
||||
void
|
||||
ProxyTextChangeEvent(ProxyAccessible*, const nsString&, int32_t, uint32_t,
|
||||
bool, bool)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ProxyShowHideEvent(ProxyAccessible*, ProxyAccessible*, bool, bool)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ProxySelectionEvent(ProxyAccessible*, ProxyAccessible*, uint32_t)
|
||||
{
|
||||
}
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
@interface GeckoNSApplication(a11y)
|
||||
-(void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute;
|
||||
@end
|
||||
|
||||
@implementation GeckoNSApplication(a11y)
|
||||
|
||||
-(void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute
|
||||
{
|
||||
if ([attribute isEqualToString:@"AXEnhancedUserInterface"])
|
||||
mozilla::a11y::sA11yShouldBeEnabled = ([value intValue] == 1);
|
||||
|
||||
return [super accessibilitySetValue:value forAttribute:attribute];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* For documentation of the accessibility architecture,
|
||||
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
|
||||
*/
|
||||
|
||||
#ifndef mozilla_a11y_RootAccessibleWrap_h__
|
||||
#define mozilla_a11y_RootAccessibleWrap_h__
|
||||
|
||||
#include "RootAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
class RootAccessibleWrap : public RootAccessible
|
||||
{
|
||||
public:
|
||||
RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
|
||||
virtual ~RootAccessibleWrap();
|
||||
|
||||
Class GetNativeType ();
|
||||
|
||||
// let's our native accessible get in touch with the
|
||||
// native cocoa view that is our accessible parent.
|
||||
void GetNativeWidget (void **aOutView);
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "RootAccessibleWrap.h"
|
||||
|
||||
#include "mozDocAccessible.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsView.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
RootAccessibleWrap::
|
||||
RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
|
||||
RootAccessible(aDocument, aPresShell)
|
||||
{
|
||||
}
|
||||
|
||||
RootAccessibleWrap::~RootAccessibleWrap()
|
||||
{
|
||||
}
|
||||
|
||||
Class
|
||||
RootAccessibleWrap::GetNativeType()
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
return [mozRootAccessible class];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
void
|
||||
RootAccessibleWrap::GetNativeWidget(void** aOutView)
|
||||
{
|
||||
nsIFrame *frame = GetFrame();
|
||||
if (frame) {
|
||||
nsView *view = frame->GetView();
|
||||
if (view) {
|
||||
nsIWidget *widget = view->GetWidget();
|
||||
if (widget) {
|
||||
*aOutView = (void**)widget->GetNativeData (NS_NATIVE_WIDGET);
|
||||
NS_ASSERTION (*aOutView,
|
||||
"Couldn't get the native NSView parent we need to connect the accessibility hierarchy!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_TextLeafAccessibleWrap_h__
|
||||
#define mozilla_a11y_TextLeafAccessibleWrap_h__
|
||||
|
||||
#include "TextLeafAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
typedef class TextLeafAccessible TextLeafAccessibleWrap;
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_XULListboxAccessibleWrap_h__
|
||||
#define mozilla_a11y_XULListboxAccessibleWrap_h__
|
||||
|
||||
#include "XULListboxAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
typedef class XULListboxAccessible XULListboxAccessibleWrap;
|
||||
typedef class XULListCellAccessible XULListCellAccessibleWrap;
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_XULMenuAccessibleWrap_h__
|
||||
#define mozilla_a11y_XULMenuAccessibleWrap_h__
|
||||
|
||||
#include "XULMenuAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
typedef class XULMenuitemAccessible XULMenuitemAccessibleWrap;
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_XULTreeGridAccessibleWrap_h__
|
||||
#define mozilla_a11y_XULTreeGridAccessibleWrap_h__
|
||||
|
||||
#include "XULTreeGridAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
typedef class XULTreeGridAccessible XULTreeGridAccessibleWrap;
|
||||
typedef class XULTreeGridCellAccessible XULTreeGridCellAccessibleWrap;
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS += [
|
||||
'mozAccessibleProtocol.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.a11y += [
|
||||
'AccessibleWrap.h',
|
||||
'HyperTextAccessibleWrap.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'AccessibleWrap.mm',
|
||||
'DocAccessibleWrap.mm',
|
||||
'MacUtils.mm',
|
||||
'mozAccessible.mm',
|
||||
'mozActionElements.mm',
|
||||
'mozDocAccessible.mm',
|
||||
'mozHTMLAccessible.mm',
|
||||
'mozTableAccessible.mm',
|
||||
'mozTextAccessible.mm',
|
||||
'Platform.mm',
|
||||
'RootAccessibleWrap.mm',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/base',
|
||||
'/accessible/generic',
|
||||
'/accessible/html',
|
||||
'/accessible/ipc',
|
||||
'/accessible/ipc/other',
|
||||
'/accessible/xul',
|
||||
'/layout/generic',
|
||||
'/layout/xul',
|
||||
'/widget',
|
||||
'/widget/cocoa',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
@@ -0,0 +1,181 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AccessibleWrap.h"
|
||||
#include "ProxyAccessible.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "mozAccessibleProtocol.h"
|
||||
|
||||
@class mozRootAccessible;
|
||||
|
||||
/**
|
||||
* All mozAccessibles are either abstract objects (that correspond to XUL
|
||||
* widgets, HTML frames, etc) or are attached to a certain view; for example
|
||||
* a document view. When we hand an object off to an AT, we always want
|
||||
* to give it the represented view, in the latter case.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
inline id <mozAccessible>
|
||||
GetObjectOrRepresentedView(id <mozAccessible> aObject)
|
||||
{
|
||||
return [aObject hasRepresentedView] ? [aObject representedView] : aObject;
|
||||
}
|
||||
|
||||
inline mozAccessible*
|
||||
GetNativeFromGeckoAccessible(Accessible* aAccessible)
|
||||
{
|
||||
mozAccessible* native = nil;
|
||||
aAccessible->GetNativeInterface((void**)&native);
|
||||
return native;
|
||||
}
|
||||
|
||||
inline mozAccessible*
|
||||
GetNativeFromProxy(const ProxyAccessible* aProxy)
|
||||
{
|
||||
return reinterpret_cast<mozAccessible*>(aProxy->GetWrapper());
|
||||
}
|
||||
|
||||
} // a11y
|
||||
} // mozilla
|
||||
|
||||
// This is OR'd with the Accessible owner to indicate the wrap-ee is a proxy.
|
||||
static const uintptr_t IS_PROXY = 1;
|
||||
|
||||
@interface mozAccessible : NSObject <mozAccessible>
|
||||
{
|
||||
/**
|
||||
* Weak reference; it owns us.
|
||||
*/
|
||||
uintptr_t mGeckoAccessible;
|
||||
|
||||
/**
|
||||
* Strong ref to array of children
|
||||
*/
|
||||
NSMutableArray* mChildren;
|
||||
|
||||
/**
|
||||
* Weak reference to the parent
|
||||
*/
|
||||
mozAccessible* mParent;
|
||||
|
||||
/**
|
||||
* The role of our gecko accessible.
|
||||
*/
|
||||
mozilla::a11y::role mRole;
|
||||
}
|
||||
|
||||
// return the Accessible for this mozAccessible if it exists.
|
||||
- (mozilla::a11y::AccessibleWrap*)getGeckoAccessible;
|
||||
|
||||
// return the ProxyAccessible for this mozAccessible if it exists.
|
||||
- (mozilla::a11y::ProxyAccessible*)getProxyAccessible;
|
||||
|
||||
// inits with the gecko owner.
|
||||
- (id)initWithAccessible:(uintptr_t)aGeckoObj;
|
||||
|
||||
// our accessible parent (AXParent)
|
||||
- (id <mozAccessible>)parent;
|
||||
|
||||
// a lazy cache of our accessible children (AXChildren). updated
|
||||
- (NSArray*)children;
|
||||
|
||||
// returns the size of this accessible.
|
||||
- (NSValue*)size;
|
||||
|
||||
// returns the position, in cocoa coordinates.
|
||||
- (NSValue*)position;
|
||||
|
||||
// can be overridden to report another role name.
|
||||
- (NSString*)role;
|
||||
|
||||
// a subrole is a more specialized variant of the role. for example,
|
||||
// the role might be "textfield", while the subrole is "password textfield".
|
||||
- (NSString*)subrole;
|
||||
|
||||
// Return the role description, as there are a few exceptions.
|
||||
- (NSString*)roleDescription;
|
||||
|
||||
// returns the native window we're inside.
|
||||
- (NSWindow*)window;
|
||||
|
||||
// the value of this element.
|
||||
- (id)value;
|
||||
|
||||
// name that is associated with this accessible (for buttons, etc)
|
||||
- (NSString*)title;
|
||||
|
||||
// the accessible description (help text) of this particular instance.
|
||||
- (NSString*)help;
|
||||
|
||||
- (BOOL)isEnabled;
|
||||
|
||||
// information about focus.
|
||||
- (BOOL)isFocused;
|
||||
- (BOOL)canBeFocused;
|
||||
|
||||
// returns NO if for some reason we were unable to focus the element.
|
||||
- (BOOL)focus;
|
||||
|
||||
// notifications sent out to listening accessible providers.
|
||||
- (void)didReceiveFocus;
|
||||
- (void)valueDidChange;
|
||||
- (void)selectedTextDidChange;
|
||||
- (void)documentLoadComplete;
|
||||
|
||||
// internal method to retrieve a child at a given index.
|
||||
- (id)childAt:(uint32_t)i;
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// invalidates and removes all our children from our cached array.
|
||||
- (void)invalidateChildren;
|
||||
|
||||
/**
|
||||
* Append a child if they are already cached.
|
||||
*/
|
||||
- (void)appendChild:(mozilla::a11y::Accessible*)aAccessible;
|
||||
|
||||
// makes ourselves "expired". after this point, we might be around if someone
|
||||
// has retained us (e.g., a third-party), but we really contain no information.
|
||||
- (void)expire;
|
||||
- (BOOL)isExpired;
|
||||
|
||||
#ifdef DEBUG
|
||||
- (void)printHierarchy;
|
||||
- (void)printHierarchyWithLevel:(unsigned)numSpaces;
|
||||
|
||||
- (void)sanityCheckChildren;
|
||||
- (void)sanityCheckChildren:(NSArray*)theChildren;
|
||||
#endif
|
||||
|
||||
// ---- NSAccessibility methods ---- //
|
||||
|
||||
// whether to skip this element when traversing the accessibility
|
||||
// hierarchy.
|
||||
- (BOOL)accessibilityIsIgnored;
|
||||
|
||||
// called by third-parties to determine the deepest child element under the mouse
|
||||
- (id)accessibilityHitTest:(NSPoint)point;
|
||||
|
||||
// returns the deepest unignored focused accessible element
|
||||
- (id)accessibilityFocusedUIElement;
|
||||
|
||||
// a mozAccessible needs to at least provide links to its parent and
|
||||
// children.
|
||||
- (NSArray*)accessibilityAttributeNames;
|
||||
|
||||
// value for the specified attribute
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute;
|
||||
|
||||
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute;
|
||||
- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute;
|
||||
|
||||
@end
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,69 @@
|
||||
/* -*- Mode: Objective-C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "mozView.h"
|
||||
|
||||
/* This protocol's primary use is so widget/cocoa can talk back to us
|
||||
properly.
|
||||
|
||||
ChildView owns the topmost mozRootAccessible, and needs to take care of setting up
|
||||
that parent/child relationship.
|
||||
|
||||
This protocol is thus used to make sure it knows it's talking to us, and not
|
||||
just some random |id|.
|
||||
*/
|
||||
|
||||
@protocol mozAccessible
|
||||
|
||||
// returns whether this accessible is the root accessible. there is one
|
||||
// root accessible per window.
|
||||
- (BOOL)isRoot;
|
||||
|
||||
// some mozAccessibles implement accessibility support in place of another object. for example,
|
||||
// ChildView gets its support from us.
|
||||
//
|
||||
// instead of returning a mozAccessible to the OS when it wants an object, we need to pass the view we represent, so the
|
||||
// OS doesn't get confused and think we return some random object.
|
||||
- (BOOL)hasRepresentedView;
|
||||
- (id)representedView;
|
||||
|
||||
#ifdef DEBUG
|
||||
// debug utility that will print the native accessibility tree, starting
|
||||
// at this node.
|
||||
- (void)printHierarchy;
|
||||
#endif
|
||||
|
||||
/*** general ***/
|
||||
|
||||
// returns the accessible at the specified point.
|
||||
- (id)accessibilityHitTest:(NSPoint)point;
|
||||
|
||||
// whether this element is flagged as ignored.
|
||||
- (BOOL)accessibilityIsIgnored;
|
||||
|
||||
// currently focused UI element (possibly a child accessible)
|
||||
- (id)accessibilityFocusedUIElement;
|
||||
|
||||
/*** attributes ***/
|
||||
|
||||
// all supported attributes
|
||||
- (NSArray*)accessibilityAttributeNames;
|
||||
|
||||
// value for given attribute.
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute;
|
||||
|
||||
// whether a particular attribute can be modified
|
||||
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute;
|
||||
|
||||
/*** actions ***/
|
||||
|
||||
- (NSArray*)accessibilityActionNames;
|
||||
- (NSString*)accessibilityActionDescription:(NSString*)action;
|
||||
- (void)accessibilityPerformAction:(NSString*)action;
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "mozAccessible.h"
|
||||
|
||||
/* Simple subclasses for things like checkboxes, buttons, etc. */
|
||||
|
||||
@interface mozButtonAccessible : mozAccessible
|
||||
{
|
||||
}
|
||||
- (BOOL)hasPopup;
|
||||
- (void)click;
|
||||
- (BOOL)isTab;
|
||||
@end
|
||||
|
||||
@interface mozCheckboxAccessible : mozButtonAccessible
|
||||
// returns one of the constants defined in CheckboxValue
|
||||
- (int)isChecked;
|
||||
@end
|
||||
|
||||
/* Class for tabs - not individual tabs */
|
||||
@interface mozTabsAccessible : mozAccessible
|
||||
{
|
||||
NSMutableArray* mTabs;
|
||||
}
|
||||
-(id)tabs;
|
||||
@end
|
||||
|
||||
/**
|
||||
* Accessible for a PANE
|
||||
*/
|
||||
@interface mozPaneAccessible : mozAccessible
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,340 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import "mozActionElements.h"
|
||||
|
||||
#import "MacUtils.h"
|
||||
#include "Accessible-inl.h"
|
||||
#include "DocAccessible.h"
|
||||
#include "XULTabAccessible.h"
|
||||
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
enum CheckboxValue {
|
||||
// these constants correspond to the values in the OS
|
||||
kUnchecked = 0,
|
||||
kChecked = 1,
|
||||
kMixed = 2
|
||||
};
|
||||
|
||||
@implementation mozButtonAccessible
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
static NSArray *attributes = nil;
|
||||
if (!attributes) {
|
||||
attributes = [[NSArray alloc] initWithObjects:NSAccessibilityParentAttribute, // required
|
||||
NSAccessibilityRoleAttribute, // required
|
||||
NSAccessibilityRoleDescriptionAttribute,
|
||||
NSAccessibilityPositionAttribute, // required
|
||||
NSAccessibilitySizeAttribute, // required
|
||||
NSAccessibilityWindowAttribute, // required
|
||||
NSAccessibilityPositionAttribute, // required
|
||||
NSAccessibilityTopLevelUIElementAttribute, // required
|
||||
NSAccessibilityHelpAttribute,
|
||||
NSAccessibilityEnabledAttribute, // required
|
||||
NSAccessibilityFocusedAttribute, // required
|
||||
NSAccessibilityTitleAttribute, // required
|
||||
NSAccessibilityChildrenAttribute,
|
||||
NSAccessibilityDescriptionAttribute,
|
||||
#if DEBUG
|
||||
@"AXMozDescription",
|
||||
#endif
|
||||
nil];
|
||||
}
|
||||
return attributes;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString *)attribute
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
|
||||
if ([self hasPopup])
|
||||
return [self children];
|
||||
return nil;
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
|
||||
if ([self isTab])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("tab"));
|
||||
|
||||
return NSAccessibilityRoleDescription([self role], nil);
|
||||
}
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsIgnored
|
||||
{
|
||||
return ![self getGeckoAccessible] && ![self getProxyAccessible];
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityActionNames
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([self isEnabled]) {
|
||||
if ([self hasPopup])
|
||||
return [NSArray arrayWithObjects:NSAccessibilityPressAction,
|
||||
NSAccessibilityShowMenuAction,
|
||||
nil];
|
||||
return [NSArray arrayWithObject:NSAccessibilityPressAction];
|
||||
}
|
||||
return nil;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (NSString*)accessibilityActionDescription:(NSString*)action
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([action isEqualToString:NSAccessibilityPressAction]) {
|
||||
if ([self isTab])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("switch"));
|
||||
|
||||
return @"press button"; // XXX: localize this later?
|
||||
}
|
||||
|
||||
if ([self hasPopup]) {
|
||||
if ([action isEqualToString:NSAccessibilityShowMenuAction])
|
||||
return @"show menu";
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (void)accessibilityPerformAction:(NSString*)action
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
if ([self isEnabled] && [action isEqualToString:NSAccessibilityPressAction]) {
|
||||
// TODO: this should bring up the menu, but currently doesn't.
|
||||
// once msaa and atk have merged better, they will implement
|
||||
// the action needed to show the menu.
|
||||
[self click];
|
||||
}
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)click
|
||||
{
|
||||
// both buttons and checkboxes have only one action. we should really stop using arbitrary
|
||||
// arrays with actions, and define constants for these actions.
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
|
||||
accWrap->DoAction(0);
|
||||
else if (ProxyAccessible* proxy = [self getProxyAccessible])
|
||||
proxy->DoAction(0);
|
||||
}
|
||||
|
||||
- (BOOL)isTab
|
||||
{
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
|
||||
return accWrap->Role() == roles::PAGETAB;
|
||||
|
||||
if (ProxyAccessible* proxy = [self getProxyAccessible])
|
||||
return proxy->Role() == roles::PAGETAB;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
- (BOOL)hasPopup
|
||||
{
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
|
||||
return accWrap->NativeState() & states::HASPOPUP;
|
||||
|
||||
if (ProxyAccessible* proxy = [self getProxyAccessible])
|
||||
return proxy->NativeState() & states::HASPOPUP;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation mozCheckboxAccessible
|
||||
|
||||
- (NSString*)accessibilityActionDescription:(NSString*)action
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([action isEqualToString:NSAccessibilityPressAction]) {
|
||||
if ([self isChecked] != kUnchecked)
|
||||
return @"uncheck checkbox"; // XXX: localize this later?
|
||||
|
||||
return @"check checkbox"; // XXX: localize this later?
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (int)isChecked
|
||||
{
|
||||
uint64_t state = 0;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
|
||||
state = accWrap->NativeState();
|
||||
else if (ProxyAccessible* proxy = [self getProxyAccessible])
|
||||
state = proxy->NativeState();
|
||||
|
||||
// check if we're checked or in a mixed state
|
||||
if (state & states::CHECKED) {
|
||||
return (state & states::MIXED) ? kMixed : kChecked;
|
||||
}
|
||||
|
||||
return kUnchecked;
|
||||
}
|
||||
|
||||
- (id)value
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
return [NSNumber numberWithInt:[self isChecked]];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation mozTabsAccessible
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[mTabs release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
// standard attributes that are shared and supported by root accessible (AXMain) elements.
|
||||
static NSMutableArray* attributes = nil;
|
||||
|
||||
if (!attributes) {
|
||||
attributes = [[super accessibilityAttributeNames] mutableCopy];
|
||||
[attributes addObject:NSAccessibilityContentsAttribute];
|
||||
[attributes addObject:NSAccessibilityTabsAttribute];
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString *)attribute
|
||||
{
|
||||
if ([attribute isEqualToString:NSAccessibilityContentsAttribute])
|
||||
return [super children];
|
||||
if ([attribute isEqualToString:NSAccessibilityTabsAttribute])
|
||||
return [self tabs];
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the selected tab (the mozAccessible)
|
||||
*/
|
||||
- (id)value
|
||||
{
|
||||
mozAccessible* nativeAcc = nil;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
if (Accessible* accTab = accWrap->GetSelectedItem(0)) {
|
||||
accTab->GetNativeInterface((void**)&nativeAcc);
|
||||
}
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
if (ProxyAccessible* proxyTab = proxy->GetSelectedItem(0)) {
|
||||
nativeAcc = GetNativeFromProxy(proxyTab);
|
||||
}
|
||||
}
|
||||
|
||||
return nativeAcc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mozAccessibles that are the tabs.
|
||||
*/
|
||||
- (id)tabs
|
||||
{
|
||||
if (mTabs)
|
||||
return mTabs;
|
||||
|
||||
NSArray* children = [self children];
|
||||
NSEnumerator* enumerator = [children objectEnumerator];
|
||||
mTabs = [[NSMutableArray alloc] init];
|
||||
|
||||
id obj;
|
||||
while ((obj = [enumerator nextObject]))
|
||||
if ([obj isTab])
|
||||
[mTabs addObject:obj];
|
||||
|
||||
return mTabs;
|
||||
}
|
||||
|
||||
- (void)invalidateChildren
|
||||
{
|
||||
[super invalidateChildren];
|
||||
|
||||
[mTabs release];
|
||||
mTabs = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation mozPaneAccessible
|
||||
|
||||
- (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute
|
||||
{
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
if (!accWrap && !proxy)
|
||||
return 0;
|
||||
|
||||
// By default this calls -[[mozAccessible children] count].
|
||||
// Since we don't cache mChildren. This is faster.
|
||||
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
|
||||
if (accWrap)
|
||||
return accWrap->ChildCount() ? 1 : 0;
|
||||
|
||||
return proxy->ChildrenCount() ? 1 : 0;
|
||||
}
|
||||
|
||||
return [super accessibilityArrayAttributeCount:attribute];
|
||||
}
|
||||
|
||||
- (NSArray*)children
|
||||
{
|
||||
if (![self getGeckoAccessible])
|
||||
return nil;
|
||||
|
||||
nsDeckFrame* deckFrame = do_QueryFrame([self getGeckoAccessible]->GetFrame());
|
||||
nsIFrame* selectedFrame = deckFrame ? deckFrame->GetSelectedBox() : nullptr;
|
||||
|
||||
Accessible* selectedAcc = nullptr;
|
||||
if (selectedFrame) {
|
||||
nsINode* node = selectedFrame->GetContent();
|
||||
selectedAcc = [self getGeckoAccessible]->Document()->GetAccessible(node);
|
||||
}
|
||||
|
||||
if (selectedAcc) {
|
||||
mozAccessible *curNative = GetNativeFromGeckoAccessible(selectedAcc);
|
||||
if (curNative)
|
||||
return [NSArray arrayWithObjects:GetObjectOrRepresentedView(curNative), nil];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,31 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "mozAccessible.h"
|
||||
|
||||
// our protocol that we implement (so cocoa widgets can talk to us)
|
||||
#import "mozAccessibleProtocol.h"
|
||||
|
||||
/*
|
||||
The root accessible. There is one per window.
|
||||
Created by the RootAccessibleWrap.
|
||||
*/
|
||||
@interface mozRootAccessible : mozAccessible
|
||||
{
|
||||
// the mozView that we're representing.
|
||||
// all outside communication goes through the mozView.
|
||||
// in reality, it's just piping all calls to us, and we're
|
||||
// doing its dirty work!
|
||||
//
|
||||
// whenever someone asks who we are (e.g., a child asking
|
||||
// for its parent, or our parent asking for its child), we'll
|
||||
// respond the mozView. it is absolutely necessary for third-
|
||||
// party tools that we do this!
|
||||
//
|
||||
// /hwaara
|
||||
id <mozView, mozAccessible> mParallelView; // weak ref
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,111 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "RootAccessibleWrap.h"
|
||||
|
||||
#import "mozDocAccessible.h"
|
||||
|
||||
#import "mozView.h"
|
||||
|
||||
// This must be included last:
|
||||
#include "nsObjCExceptions.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
static id <mozAccessible, mozView>
|
||||
getNativeViewFromRootAccessible(Accessible* aAccessible)
|
||||
{
|
||||
RootAccessibleWrap* root =
|
||||
static_cast<RootAccessibleWrap*>(aAccessible->AsRoot());
|
||||
id <mozAccessible, mozView> nativeView = nil;
|
||||
root->GetNativeWidget ((void**)&nativeView);
|
||||
return nativeView;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation mozRootAccessible
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (![self getGeckoAccessible])
|
||||
return [NSArray array];
|
||||
|
||||
// standard attributes that are shared and supported by root accessible (AXMain) elements.
|
||||
static NSMutableArray* attributes = nil;
|
||||
|
||||
if (!attributes) {
|
||||
attributes = [[super accessibilityAttributeNames] mutableCopy];
|
||||
[attributes addObject:NSAccessibilityMainAttribute];
|
||||
[attributes addObject:NSAccessibilityMinimizedAttribute];
|
||||
}
|
||||
|
||||
return attributes;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString *)attribute
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityMainAttribute])
|
||||
return [NSNumber numberWithBool:[[self window] isMainWindow]];
|
||||
if ([attribute isEqualToString:NSAccessibilityMinimizedAttribute])
|
||||
return [NSNumber numberWithBool:[[self window] isMiniaturized]];
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
|
||||
// return the AXParent that our parallell NSView tells us about.
|
||||
- (id)parent
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (!mParallelView)
|
||||
mParallelView = (id<mozView, mozAccessible>)[self representedView];
|
||||
|
||||
if (mParallelView)
|
||||
return [mParallelView accessibilityAttributeValue:NSAccessibilityParentAttribute];
|
||||
|
||||
NSAssert(mParallelView, @"we're a root accessible w/o native view?");
|
||||
return [super parent];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (BOOL)hasRepresentedView
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
// this will return our parallell NSView. see mozDocAccessible.h
|
||||
- (id)representedView
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (mParallelView)
|
||||
return (id)mParallelView;
|
||||
|
||||
mParallelView = getNativeViewFromRootAccessible ([self getGeckoAccessible]);
|
||||
|
||||
NSAssert(mParallelView, @"can't return root accessible's native parallel view.");
|
||||
return mParallelView;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (BOOL)isRoot
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,16 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import "mozAccessible.h"
|
||||
|
||||
@interface mozHeadingAccessible : mozAccessible
|
||||
|
||||
@end
|
||||
|
||||
@interface mozLinkAccessible : mozAccessible
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,141 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import "mozHTMLAccessible.h"
|
||||
|
||||
#import "Accessible-inl.h"
|
||||
#import "HyperTextAccessible.h"
|
||||
|
||||
#import "nsCocoaUtils.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
@implementation mozHeadingAccessible
|
||||
|
||||
- (NSString*)title
|
||||
{
|
||||
nsAutoString title;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
mozilla::ErrorResult rv;
|
||||
// XXX use the flattening API when there are available
|
||||
// see bug 768298
|
||||
accWrap->GetContent()->GetTextContent(title, rv);
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
proxy->Title(title);
|
||||
}
|
||||
|
||||
return nsCocoaUtils::ToNSString(title);
|
||||
}
|
||||
|
||||
- (id)value
|
||||
{
|
||||
uint32_t level = 0;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
level = accWrap->GetLevelInternal();
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
level = proxy->GetLevelInternal();
|
||||
}
|
||||
|
||||
return [NSNumber numberWithInt:level];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface mozLinkAccessible ()
|
||||
-(NSURL*)url;
|
||||
@end
|
||||
|
||||
@implementation mozLinkAccessible
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (![self getGeckoAccessible] && ![self getProxyAccessible])
|
||||
return [NSArray array];
|
||||
|
||||
static NSMutableArray* attributes = nil;
|
||||
|
||||
if (!attributes) {
|
||||
attributes = [[super accessibilityAttributeNames] mutableCopy];
|
||||
[attributes addObject:NSAccessibilityURLAttribute];
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString *)attribute
|
||||
{
|
||||
if ([attribute isEqualToString:NSAccessibilityURLAttribute])
|
||||
return [self url];
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityActionNames
|
||||
{
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (![self getGeckoAccessible] && ![self getProxyAccessible])
|
||||
return [NSArray array];
|
||||
|
||||
static NSArray* actionNames = nil;
|
||||
|
||||
if (!actionNames) {
|
||||
actionNames = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction,
|
||||
nil];
|
||||
}
|
||||
|
||||
return actionNames;
|
||||
}
|
||||
|
||||
- (void)accessibilityPerformAction:(NSString*)action
|
||||
{
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
if (!accWrap && !proxy) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ([action isEqualToString:NSAccessibilityPressAction]) {
|
||||
if (accWrap) {
|
||||
accWrap->DoAction(0);
|
||||
} else if (proxy) {
|
||||
proxy->DoAction(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
[super accessibilityPerformAction:action];
|
||||
|
||||
}
|
||||
|
||||
- (NSString*)customDescription
|
||||
{
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSString*)value
|
||||
{
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSURL*)url
|
||||
{
|
||||
nsAutoString value;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
accWrap->Value(value);
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
proxy->Value(value);
|
||||
}
|
||||
|
||||
NSString* urlString = value.IsEmpty() ? nil : nsCocoaUtils::ToNSString(value);
|
||||
if (!urlString)
|
||||
return nil;
|
||||
|
||||
return [NSURL URLWithString:urlString];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,28 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import "mozAccessible.h"
|
||||
|
||||
@interface mozTablePartAccessible : mozAccessible
|
||||
- (BOOL)isLayoutTablePart;
|
||||
- (NSString*)role;
|
||||
@end
|
||||
|
||||
@interface mozTableAccessible : mozTablePartAccessible
|
||||
- (NSArray*)additionalAccessibilityAttributeNames;
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute;
|
||||
@end
|
||||
|
||||
@interface mozTableRowAccessible : mozTablePartAccessible
|
||||
- (NSArray*)additionalAccessibilityAttributeNames;
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute;
|
||||
@end
|
||||
|
||||
@interface mozTableCellAccessible : mozTablePartAccessible
|
||||
- (NSArray*)additionalAccessibilityAttributeNames;
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute;
|
||||
@end
|
||||
@@ -0,0 +1,281 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import "Accessible-inl.h"
|
||||
#import "mozTableAccessible.h"
|
||||
#import "TableAccessible.h"
|
||||
#import "TableCellAccessible.h"
|
||||
#import "nsCocoaUtils.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
// convert an array of Gecko accessibles to an NSArray of native accessibles
|
||||
static inline NSMutableArray*
|
||||
ConvertToNSArray(nsTArray<Accessible*>& aArray)
|
||||
{
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
|
||||
// iterate through the list, and get each native accessible.
|
||||
size_t totalCount = aArray.Length();
|
||||
for (size_t i = 0; i < totalCount; i++) {
|
||||
Accessible* curAccessible = aArray.ElementAt(i);
|
||||
mozAccessible* curNative = GetNativeFromGeckoAccessible(curAccessible);
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
|
||||
return nativeArray;
|
||||
}
|
||||
|
||||
// convert an array of Gecko proxy accessibles to an NSArray of native accessibles
|
||||
static inline NSMutableArray*
|
||||
ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
||||
{
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
|
||||
// iterate through the list, and get each native accessible.
|
||||
size_t totalCount = aArray.Length();
|
||||
for (size_t i = 0; i < totalCount; i++) {
|
||||
ProxyAccessible* curAccessible = aArray.ElementAt(i);
|
||||
mozAccessible* curNative = GetNativeFromProxy(curAccessible);
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
|
||||
return nativeArray;
|
||||
}
|
||||
|
||||
@implementation mozTablePartAccessible
|
||||
- (BOOL)isLayoutTablePart;
|
||||
{
|
||||
if (Accessible* accWrap = [self getGeckoAccessible]) {
|
||||
while (accWrap) {
|
||||
if (accWrap->IsTable()) {
|
||||
return accWrap->AsTable()->IsProbablyLayoutTable();
|
||||
}
|
||||
accWrap = accWrap->Parent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
while (proxy) {
|
||||
if (proxy->IsTable()) {
|
||||
return proxy->TableIsProbablyForLayout();
|
||||
}
|
||||
proxy = proxy->Parent();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
- (NSString*)role
|
||||
{
|
||||
return [self isLayoutTablePart] ? NSAccessibilityGroupRole : [super role];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation mozTableAccessible
|
||||
- (NSArray*)additionalAccessibilityAttributeNames
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
NSArray* additionalAttributes = [super additionalAccessibilityAttributeNames];
|
||||
if ([self isLayoutTablePart]) {
|
||||
return additionalAttributes;
|
||||
}
|
||||
|
||||
static NSArray* tableAttrs = nil;
|
||||
if (!tableAttrs) {
|
||||
NSMutableArray* tempArray = [NSMutableArray new];
|
||||
[tempArray addObject:NSAccessibilityRowCountAttribute];
|
||||
[tempArray addObject:NSAccessibilityColumnCountAttribute];
|
||||
[tempArray addObject:NSAccessibilityRowsAttribute];
|
||||
tableAttrs = [[NSArray alloc] initWithArray:tempArray];
|
||||
[tempArray release];
|
||||
}
|
||||
|
||||
return [additionalAttributes arrayByAddingObjectsFromArray:tableAttrs];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
TableAccessible* table = accWrap->AsTable();
|
||||
if ([attribute isEqualToString:NSAccessibilityRowCountAttribute])
|
||||
return @(table->RowCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnCountAttribute])
|
||||
return @(table->ColCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityRowsAttribute]) {
|
||||
// Create a new array with the list of table rows.
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
uint32_t totalCount = accWrap->ChildCount();
|
||||
for (uint32_t i = 0; i < totalCount; i++) {
|
||||
if (accWrap->GetChildAt(i)->IsTableRow()) {
|
||||
mozAccessible* curNative =
|
||||
GetNativeFromGeckoAccessible(accWrap->GetChildAt(i));
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
}
|
||||
return nativeArray;
|
||||
}
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
if ([attribute isEqualToString:NSAccessibilityRowCountAttribute])
|
||||
return @(proxy->TableRowCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnCountAttribute])
|
||||
return @(proxy->TableColumnCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityRowsAttribute]) {
|
||||
// Create a new array with the list of table rows.
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
uint32_t totalCount = proxy->ChildrenCount();
|
||||
for (uint32_t i = 0; i < totalCount; i++) {
|
||||
if (proxy->ChildAt(i)->IsTableRow()) {
|
||||
mozAccessible* curNative =
|
||||
GetNativeFromProxy(proxy->ChildAt(i));
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
}
|
||||
return nativeArray;
|
||||
}
|
||||
}
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation mozTableRowAccessible
|
||||
- (NSArray*)additionalAccessibilityAttributeNames
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
NSArray* additionalAttributes = [super additionalAccessibilityAttributeNames];
|
||||
if ([self isLayoutTablePart]) {
|
||||
return additionalAttributes;
|
||||
}
|
||||
|
||||
static NSArray* tableRowAttrs = nil;
|
||||
if (!tableRowAttrs) {
|
||||
NSMutableArray* tempArray = [NSMutableArray new];
|
||||
[tempArray addObject:NSAccessibilityIndexAttribute];
|
||||
tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
|
||||
[tempArray release];
|
||||
}
|
||||
|
||||
return [additionalAttributes arrayByAddingObjectsFromArray:tableRowAttrs];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
if ([attribute isEqualToString:NSAccessibilityIndexAttribute]) {
|
||||
// Count the number of rows before that one to obtain the row index.
|
||||
uint32_t index = 0;
|
||||
Accessible* parent = accWrap->Parent();
|
||||
if (parent) {
|
||||
for (int32_t i = accWrap->IndexInParent() - 1; i >= 0; i--) {
|
||||
if (parent->GetChildAt(i)->IsTableRow()) {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [NSNumber numberWithUnsignedInteger:index];
|
||||
}
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
if ([attribute isEqualToString:NSAccessibilityIndexAttribute]) {
|
||||
// Count the number of rows before that one to obtain the row index.
|
||||
uint32_t index = 0;
|
||||
ProxyAccessible* parent = proxy->Parent();
|
||||
if (parent) {
|
||||
for (int32_t i = proxy->IndexInParent() - 1; i >= 0; i--) {
|
||||
if (parent->ChildAt(i)->IsTableRow()) {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [NSNumber numberWithUnsignedInteger:index];
|
||||
}
|
||||
}
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation mozTableCellAccessible
|
||||
- (NSArray*)additionalAccessibilityAttributeNames
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
NSArray* additionalAttributes = [super additionalAccessibilityAttributeNames];
|
||||
if ([self isLayoutTablePart]) {
|
||||
return additionalAttributes;
|
||||
}
|
||||
|
||||
static NSArray* tableCellAttrs = nil;
|
||||
if (!tableCellAttrs) {
|
||||
NSMutableArray* tempArray = [NSMutableArray new];
|
||||
[tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
|
||||
[tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
|
||||
[tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
|
||||
[tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
|
||||
tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
|
||||
[tempArray release];
|
||||
}
|
||||
|
||||
return [additionalAttributes arrayByAddingObjectsFromArray:tableCellAttrs];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
TableCellAccessible* cell = accWrap->AsTableCell();
|
||||
if ([attribute isEqualToString:NSAccessibilityRowIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(cell->RowIdx(),
|
||||
cell->RowExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(cell->ColIdx(),
|
||||
cell->ColExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
|
||||
AutoTArray<Accessible*, 10> headerCells;
|
||||
cell->RowHeaderCells(&headerCells);
|
||||
return ConvertToNSArray(headerCells);
|
||||
}
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
|
||||
AutoTArray<Accessible*, 10> headerCells;
|
||||
cell->ColHeaderCells(&headerCells);
|
||||
return ConvertToNSArray(headerCells);
|
||||
}
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
if ([attribute isEqualToString:NSAccessibilityRowIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(proxy->RowIdx(),
|
||||
proxy->RowExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(proxy->ColIdx(),
|
||||
proxy->ColExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
|
||||
nsTArray<ProxyAccessible*> headerCells;
|
||||
proxy->RowHeaderCells(&headerCells);
|
||||
return ConvertToNSArray(headerCells);
|
||||
}
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
|
||||
nsTArray<ProxyAccessible*> headerCells;
|
||||
proxy->ColHeaderCells(&headerCells);
|
||||
return ConvertToNSArray(headerCells);
|
||||
}
|
||||
}
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,17 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import "mozAccessible.h"
|
||||
|
||||
#import "HyperTextAccessible.h"
|
||||
|
||||
@interface mozTextAccessible : mozAccessible
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@interface mozTextLeafAccessible : mozAccessible
|
||||
{
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,627 @@
|
||||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Accessible-inl.h"
|
||||
#include "HyperTextAccessible-inl.h"
|
||||
#include "TextLeafAccessible.h"
|
||||
|
||||
#include "nsCocoaUtils.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
|
||||
#import "mozTextAccessible.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
inline bool
|
||||
ToNSRange(id aValue, NSRange* aRange)
|
||||
{
|
||||
NS_PRECONDITION(aRange, "aRange is nil");
|
||||
|
||||
if ([aValue isKindOfClass:[NSValue class]] &&
|
||||
strcmp([(NSValue*)aValue objCType], @encode(NSRange)) == 0) {
|
||||
*aRange = [aValue rangeValue];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline NSString*
|
||||
ToNSString(id aValue)
|
||||
{
|
||||
if ([aValue isKindOfClass:[NSString class]]) {
|
||||
return aValue;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@interface mozTextAccessible ()
|
||||
- (NSString*)subrole;
|
||||
- (NSString*)selectedText;
|
||||
- (NSValue*)selectedTextRange;
|
||||
- (NSValue*)visibleCharacterRange;
|
||||
- (long)textLength;
|
||||
- (BOOL)isReadOnly;
|
||||
- (NSNumber*)caretLineNumber;
|
||||
- (void)setText:(NSString*)newText;
|
||||
- (NSString*)text;
|
||||
- (NSString*)stringFromRange:(NSRange*)range;
|
||||
@end
|
||||
|
||||
@implementation mozTextAccessible
|
||||
|
||||
- (BOOL)accessibilityIsIgnored
|
||||
{
|
||||
return ![self getGeckoAccessible] && ![self getProxyAccessible];
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
static NSMutableArray* supportedAttributes = nil;
|
||||
if (!supportedAttributes) {
|
||||
// text-specific attributes to supplement the standard one
|
||||
supportedAttributes = [[NSMutableArray alloc] initWithObjects:
|
||||
NSAccessibilitySelectedTextAttribute, // required
|
||||
NSAccessibilitySelectedTextRangeAttribute, // required
|
||||
NSAccessibilityNumberOfCharactersAttribute, // required
|
||||
NSAccessibilityVisibleCharacterRangeAttribute, // required
|
||||
NSAccessibilityInsertionPointLineNumberAttribute,
|
||||
@"AXRequired",
|
||||
@"AXInvalid",
|
||||
nil
|
||||
];
|
||||
[supportedAttributes addObjectsFromArray:[super accessibilityAttributeNames]];
|
||||
}
|
||||
return supportedAttributes;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityNumberOfCharactersAttribute])
|
||||
return [NSNumber numberWithInt:[self textLength]];
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute])
|
||||
return [self caretLineNumber];
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute])
|
||||
return [self selectedTextRange];
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute])
|
||||
return [self selectedText];
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
|
||||
return @"";
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
|
||||
// Apple's SpeechSynthesisServer expects AXValue to return an AXStaticText
|
||||
// object's AXSelectedText attribute. See bug 674612 for details.
|
||||
// Also if there is no selected text, we return the full text.
|
||||
// See bug 369710 for details.
|
||||
if ([[self role] isEqualToString:NSAccessibilityStaticTextRole]) {
|
||||
NSString* selectedText = [self selectedText];
|
||||
return (selectedText && [selectedText length]) ? selectedText : [self text];
|
||||
}
|
||||
|
||||
return [self text];
|
||||
}
|
||||
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
if ([attribute isEqualToString:@"AXRequired"]) {
|
||||
return [NSNumber numberWithBool:!!(accWrap->State() & states::REQUIRED)];
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:@"AXInvalid"]) {
|
||||
return [NSNumber numberWithBool:!!(accWrap->State() & states::INVALID)];
|
||||
}
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
if ([attribute isEqualToString:@"AXRequired"]) {
|
||||
return [NSNumber numberWithBool:!!(proxy->State() & states::REQUIRED)];
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:@"AXInvalid"]) {
|
||||
return [NSNumber numberWithBool:!!(proxy->State() & states::INVALID)];
|
||||
}
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute])
|
||||
return [self visibleCharacterRange];
|
||||
|
||||
// let mozAccessible handle all other attributes
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityParameterizedAttributeNames
|
||||
{
|
||||
static NSArray* supportedParametrizedAttributes = nil;
|
||||
// text specific parametrized attributes
|
||||
if (!supportedParametrizedAttributes) {
|
||||
supportedParametrizedAttributes = [[NSArray alloc] initWithObjects:
|
||||
NSAccessibilityStringForRangeParameterizedAttribute,
|
||||
NSAccessibilityLineForIndexParameterizedAttribute,
|
||||
NSAccessibilityRangeForLineParameterizedAttribute,
|
||||
NSAccessibilityAttributedStringForRangeParameterizedAttribute,
|
||||
NSAccessibilityBoundsForRangeParameterizedAttribute,
|
||||
#if DEBUG
|
||||
NSAccessibilityRangeForPositionParameterizedAttribute,
|
||||
NSAccessibilityRangeForIndexParameterizedAttribute,
|
||||
NSAccessibilityRTFForRangeParameterizedAttribute,
|
||||
NSAccessibilityStyleRangeForIndexParameterizedAttribute,
|
||||
#endif
|
||||
nil
|
||||
];
|
||||
}
|
||||
return supportedParametrizedAttributes;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter
|
||||
{
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return nil;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) {
|
||||
NSRange range;
|
||||
if (!ToNSRange(parameter, &range)) {
|
||||
#if DEBUG
|
||||
NSLog(@"%@: range not set", attribute);
|
||||
#endif
|
||||
return @"";
|
||||
}
|
||||
|
||||
return [self stringFromRange:&range];
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityRangeForLineParameterizedAttribute]) {
|
||||
// XXX: actually get the integer value for the line #
|
||||
return [NSValue valueWithRange:NSMakeRange(0, [self textLength])];
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityAttributedStringForRangeParameterizedAttribute]) {
|
||||
NSRange range;
|
||||
if (!ToNSRange(parameter, &range)) {
|
||||
#if DEBUG
|
||||
NSLog(@"%@: range not set", attribute);
|
||||
#endif
|
||||
return @"";
|
||||
}
|
||||
|
||||
return [[[NSAttributedString alloc] initWithString:[self stringFromRange:&range]] autorelease];
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityLineForIndexParameterizedAttribute]) {
|
||||
// XXX: actually return the line #
|
||||
return [NSNumber numberWithInt:0];
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) {
|
||||
NSRange range;
|
||||
if (!ToNSRange(parameter, &range)) {
|
||||
#if DEBUG
|
||||
NSLog(@"%@:no range", attribute);
|
||||
#endif
|
||||
return nil;
|
||||
}
|
||||
|
||||
int32_t start = range.location;
|
||||
int32_t end = start + range.length;
|
||||
DesktopIntRect bounds;
|
||||
if (textAcc) {
|
||||
bounds =
|
||||
DesktopIntRect::FromUnknownRect(textAcc->TextBounds(start, end));
|
||||
} else if (proxy) {
|
||||
bounds =
|
||||
DesktopIntRect::FromUnknownRect(proxy->TextBounds(start, end));
|
||||
}
|
||||
|
||||
return [NSValue valueWithRect:nsCocoaUtils::GeckoRectToCocoaRect(bounds)];
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
NSLog(@"unhandled attribute:%@ forParameter:%@", attribute, parameter);
|
||||
#endif
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
|
||||
return ![self isReadOnly];
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute] ||
|
||||
[attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute] ||
|
||||
[attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute])
|
||||
return YES;
|
||||
|
||||
return [super accessibilityIsAttributeSettable:attribute];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
||||
}
|
||||
|
||||
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
|
||||
[self setText:ToNSString(value)];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
|
||||
NSString* stringValue = ToNSString(value);
|
||||
if (!stringValue)
|
||||
return;
|
||||
|
||||
int32_t start = 0, end = 0;
|
||||
nsString text;
|
||||
if (textAcc) {
|
||||
textAcc->SelectionBoundsAt(0, &start, &end);
|
||||
textAcc->DeleteText(start, end - start);
|
||||
nsCocoaUtils::GetStringForNSString(stringValue, text);
|
||||
textAcc->InsertText(text, start);
|
||||
} else if (proxy) {
|
||||
nsString data;
|
||||
proxy->SelectionBoundsAt(0, data, &start, &end);
|
||||
proxy->DeleteText(start, end - start);
|
||||
nsCocoaUtils::GetStringForNSString(stringValue, text);
|
||||
proxy->InsertText(text, start);
|
||||
}
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
|
||||
NSRange range;
|
||||
if (!ToNSRange(value, &range))
|
||||
return;
|
||||
|
||||
if (textAcc) {
|
||||
textAcc->SetSelectionBoundsAt(0, range.location,
|
||||
range.location + range.length);
|
||||
} else if (proxy) {
|
||||
proxy->SetSelectionBoundsAt(0, range.location,
|
||||
range.location + range.length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
|
||||
NSRange range;
|
||||
if (!ToNSRange(value, &range))
|
||||
return;
|
||||
|
||||
if (textAcc) {
|
||||
textAcc->ScrollSubstringTo(range.location, range.location + range.length,
|
||||
nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE);
|
||||
} else if (proxy) {
|
||||
proxy->ScrollSubstringTo(range.location, range.location + range.length,
|
||||
nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
[super accessibilitySetValue:value forAttribute:attribute];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (NSString*)subrole
|
||||
{
|
||||
if(mRole == roles::PASSWORD_TEXT)
|
||||
return NSAccessibilitySecureTextFieldSubrole;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (BOOL)isReadOnly
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
if ([[self role] isEqualToString:NSAccessibilityStaticTextRole])
|
||||
return YES;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (textAcc)
|
||||
return (accWrap->State() & states::READONLY) == 0;
|
||||
|
||||
if (ProxyAccessible* proxy = [self getProxyAccessible])
|
||||
return (proxy->State() & states::READONLY) == 0;
|
||||
|
||||
return NO;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
||||
}
|
||||
|
||||
- (NSNumber*)caretLineNumber
|
||||
{
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
|
||||
int32_t lineNumber = -1;
|
||||
if (textAcc) {
|
||||
lineNumber = textAcc->CaretLineNumber() - 1;
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
lineNumber = proxy->CaretLineNumber() - 1;
|
||||
}
|
||||
|
||||
return (lineNumber >= 0) ? [NSNumber numberWithInt:lineNumber] : nil;
|
||||
}
|
||||
|
||||
- (void)setText:(NSString*)aNewString
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
|
||||
nsString text;
|
||||
nsCocoaUtils::GetStringForNSString(aNewString, text);
|
||||
if (textAcc) {
|
||||
textAcc->ReplaceText(text);
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
proxy->ReplaceText(text);
|
||||
}
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (NSString*)text
|
||||
{
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return nil;
|
||||
|
||||
// A password text field returns an empty value
|
||||
if (mRole == roles::PASSWORD_TEXT)
|
||||
return @"";
|
||||
|
||||
nsAutoString text;
|
||||
if (textAcc) {
|
||||
textAcc->TextSubstring(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT, text);
|
||||
} else if (proxy) {
|
||||
proxy->TextSubstring(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT, text);
|
||||
}
|
||||
|
||||
return nsCocoaUtils::ToNSString(text);
|
||||
}
|
||||
|
||||
- (long)textLength
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return 0;
|
||||
|
||||
return textAcc ? textAcc->CharacterCount() : proxy->CharacterCount();
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
|
||||
}
|
||||
|
||||
- (long)selectedTextLength
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return 0;
|
||||
|
||||
int32_t start = 0, end = 0;
|
||||
if (textAcc) {
|
||||
textAcc->SelectionBoundsAt(0, &start, &end);
|
||||
} else if (proxy) {
|
||||
nsString data;
|
||||
proxy->SelectionBoundsAt(0, data, &start, &end);
|
||||
}
|
||||
return (end - start);
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
|
||||
}
|
||||
|
||||
- (NSString*)selectedText
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return nil;
|
||||
|
||||
int32_t start = 0, end = 0;
|
||||
nsAutoString selText;
|
||||
if (textAcc) {
|
||||
textAcc->SelectionBoundsAt(0, &start, &end);
|
||||
if (start != end) {
|
||||
textAcc->TextSubstring(start, end, selText);
|
||||
}
|
||||
} else if (proxy) {
|
||||
proxy->SelectionBoundsAt(0, selText, &start, &end);
|
||||
}
|
||||
|
||||
return nsCocoaUtils::ToNSString(selText);
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (NSValue*)selectedTextRange
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
|
||||
int32_t start = 0;
|
||||
int32_t end = 0;
|
||||
int32_t count = 0;
|
||||
if (textAcc) {
|
||||
count = textAcc->SelectionCount();
|
||||
if (count) {
|
||||
textAcc->SelectionBoundsAt(0, &start, &end);
|
||||
return [NSValue valueWithRange:NSMakeRange(start, end - start)];
|
||||
}
|
||||
|
||||
start = textAcc->CaretOffset();
|
||||
return [NSValue valueWithRange:NSMakeRange(start != -1 ? start : 0, 0)];
|
||||
}
|
||||
|
||||
if (proxy) {
|
||||
count = proxy->SelectionCount();
|
||||
if (count) {
|
||||
nsString data;
|
||||
proxy->SelectionBoundsAt(0, data, &start, &end);
|
||||
return [NSValue valueWithRange:NSMakeRange(start, end - start)];
|
||||
}
|
||||
|
||||
start = proxy->CaretOffset();
|
||||
return [NSValue valueWithRange:NSMakeRange(start != -1 ? start : 0, 0)];
|
||||
}
|
||||
|
||||
return [NSValue valueWithRange:NSMakeRange(0, 0)];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (NSValue*)visibleCharacterRange
|
||||
{
|
||||
// XXX this won't work with Textarea and such as we actually don't give
|
||||
// the visible character range.
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return 0;
|
||||
|
||||
return [NSValue valueWithRange:
|
||||
NSMakeRange(0, textAcc ?
|
||||
textAcc->CharacterCount() : proxy->CharacterCount())];
|
||||
}
|
||||
|
||||
- (void)valueDidChange
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
NSAccessibilityPostNotification(GetObjectOrRepresentedView(self),
|
||||
NSAccessibilityValueChangedNotification);
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)selectedTextDidChange
|
||||
{
|
||||
NSAccessibilityPostNotification(GetObjectOrRepresentedView(self),
|
||||
NSAccessibilitySelectedTextChangedNotification);
|
||||
}
|
||||
|
||||
- (NSString*)stringFromRange:(NSRange*)range
|
||||
{
|
||||
NS_PRECONDITION(range, "no range");
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return nil;
|
||||
|
||||
nsAutoString text;
|
||||
if (textAcc) {
|
||||
textAcc->TextSubstring(range->location,
|
||||
range->location + range->length, text);
|
||||
} else if (proxy) {
|
||||
proxy->TextSubstring(range->location,
|
||||
range->location + range->length, text);
|
||||
}
|
||||
|
||||
return nsCocoaUtils::ToNSString(text);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation mozTextLeafAccessible
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
static NSMutableArray* supportedAttributes = nil;
|
||||
if (!supportedAttributes) {
|
||||
supportedAttributes = [[super accessibilityAttributeNames] mutableCopy];
|
||||
[supportedAttributes removeObject:NSAccessibilityChildrenAttribute];
|
||||
}
|
||||
|
||||
return supportedAttributes;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
|
||||
return @"";
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
|
||||
return [self text];
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
|
||||
- (NSString*)text
|
||||
{
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
return nsCocoaUtils::ToNSString(accWrap->AsTextLeaf()->Text());
|
||||
}
|
||||
|
||||
if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
nsString text;
|
||||
proxy->Text(&text);
|
||||
return nsCocoaUtils::ToNSString(text);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (long)textLength
|
||||
{
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
return accWrap->AsTextLeaf()->Text().Length();
|
||||
}
|
||||
|
||||
if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
nsString text;
|
||||
proxy->Text(&text);
|
||||
return text.Length();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -9,6 +9,8 @@ if 'gtk' in toolkit:
|
||||
DIRS += ['atk']
|
||||
elif toolkit == 'windows':
|
||||
DIRS += ['windows']
|
||||
elif toolkit == 'cocoa':
|
||||
DIRS += ['mac']
|
||||
else:
|
||||
DIRS += ['other']
|
||||
|
||||
@@ -19,12 +21,10 @@ DIRS += [ 'aom',
|
||||
'interfaces',
|
||||
'ipc',
|
||||
'jsat',
|
||||
'xpcom'
|
||||
'xpcom',
|
||||
'xul'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_XUL']:
|
||||
DIRS += ['xul']
|
||||
|
||||
TEST_DIRS += ['tests/mochitest']
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
|
||||
@@ -35,19 +35,6 @@ a11y::PlatformInit()
|
||||
|
||||
nsWinUtils::MaybeStartWindowEmulation();
|
||||
ia2AccessibleText::InitTextChangeData();
|
||||
if (BrowserTabsRemoteAutostart()) {
|
||||
mscom::InterceptorLog::Init();
|
||||
UniquePtr<RegisteredProxy> regProxy(
|
||||
mscom::RegisterProxy(L"ia2marshal.dll"));
|
||||
gRegProxy = regProxy.release();
|
||||
UniquePtr<RegisteredProxy> regAccTlb(
|
||||
mscom::RegisterTypelib(L"oleacc.dll",
|
||||
RegistrationFlags::eUseSystemDirectory));
|
||||
gRegAccTlb = regAccTlb.release();
|
||||
UniquePtr<RegisteredProxy> regMiscTlb(
|
||||
mscom::RegisterTypelib(L"Accessible.tlb"));
|
||||
gRegMiscTlb = regMiscTlb.release();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -33,15 +33,11 @@ SOURCES += [
|
||||
'RootAccessibleWrap.cpp',
|
||||
'ServiceProvider.cpp',
|
||||
'TextLeafAccessibleWrap.cpp',
|
||||
'XULListboxAccessibleWrap.cpp',
|
||||
'XULMenuAccessibleWrap.cpp',
|
||||
'XULTreeGridAccessibleWrap.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_XUL']:
|
||||
SOURCES += [
|
||||
'XULListboxAccessibleWrap.cpp',
|
||||
'XULMenuAccessibleWrap.cpp',
|
||||
'XULTreeGridAccessibleWrap.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/base',
|
||||
'/accessible/generic',
|
||||
|
||||
@@ -42,6 +42,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/windows/msaa',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/mac',
|
||||
]
|
||||
else:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/other',
|
||||
|
||||
@@ -37,6 +37,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
'/accessible/windows/ia2',
|
||||
'/accessible/windows/msaa',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/mac',
|
||||
]
|
||||
else:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/other',
|
||||
|
||||
Vendored
-1
@@ -25,7 +25,6 @@ builtin(include, build/autoconf/zlib.m4)dnl
|
||||
builtin(include, build/autoconf/icu.m4)dnl
|
||||
builtin(include, build/autoconf/clang-plugin.m4)dnl
|
||||
builtin(include, build/autoconf/alloc.m4)dnl
|
||||
builtin(include, build/autoconf/ios.m4)dnl
|
||||
builtin(include, build/autoconf/sanitize.m4)dnl
|
||||
|
||||
MOZ_PROG_CHECKMSYS()
|
||||
|
||||
-129
@@ -1,129 +0,0 @@
|
||||
import java.util.regex.Pattern
|
||||
|
||||
allprojects {
|
||||
// Expose the per-object-directory configuration to all projects.
|
||||
ext {
|
||||
mozconfig = gradle.mozconfig
|
||||
topsrcdir = gradle.mozconfig.topsrcdir
|
||||
topobjdir = gradle.mozconfig.topobjdir
|
||||
}
|
||||
|
||||
repositories {
|
||||
if (gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORY) {
|
||||
maven {
|
||||
url gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORY
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildDir "${topobjdir}/gradle/build"
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
if (gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORY) {
|
||||
maven {
|
||||
url gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORY
|
||||
}
|
||||
}
|
||||
// For android-sdk-manager SNAPSHOT releases.
|
||||
maven {
|
||||
url "file://${gradle.mozconfig.topsrcdir}/mobile/android/gradle/m2repo"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.1.3'
|
||||
classpath('com.stanfy.spoon:spoon-gradle-plugin:1.0.4') {
|
||||
// Without these, we get errors linting.
|
||||
exclude module: 'guava'
|
||||
}
|
||||
// Provided in tree.
|
||||
classpath 'com.jakewharton.sdkmanager:gradle-plugin:1.5.0-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
task generateCodeAndResources(type:Exec) {
|
||||
workingDir "${topobjdir}"
|
||||
|
||||
commandLine mozconfig.substs.GMAKE
|
||||
args '-C'
|
||||
args "${topobjdir}/mobile/android/base"
|
||||
args 'gradle-targets'
|
||||
|
||||
// Only show the output if something went wrong.
|
||||
ignoreExitValue = true
|
||||
standardOutput = new ByteArrayOutputStream()
|
||||
errorOutput = standardOutput
|
||||
doLast {
|
||||
if (execResult.exitValue != 0) {
|
||||
throw new GradleException("Process '${commandLine}' finished with non-zero exit value ${execResult.exitValue}:\n\n${standardOutput.toString()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip unit test for all build variants, unless if it was specifically requested by user.
|
||||
// The enabled property for the unit test tasks is reset based on the command line task names just before the task execution.
|
||||
// I bet there is a easier/cleaner way to do this, but this gets the job done for now.
|
||||
Pattern pattern = Pattern.compile('.*test(.+UnitTest)?.*')
|
||||
boolean startTasksIncludeTest = gradle.startParameter.taskNames.any {
|
||||
taskName ->
|
||||
taskName.matches(pattern)
|
||||
}
|
||||
gradle.taskGraph.beforeTask {
|
||||
Task task ->
|
||||
if (task.name.matches(pattern)) {
|
||||
task.enabled = startTasksIncludeTest
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
subprojects {
|
||||
if (!hasProperty('android')) {
|
||||
return
|
||||
}
|
||||
android.applicationVariants.all {
|
||||
preBuild.dependsOn rootProject.generateCodeAndResources
|
||||
}
|
||||
android.libraryVariants.all {
|
||||
preBuild.dependsOn rootProject.generateCodeAndResources
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'idea'
|
||||
|
||||
idea {
|
||||
project {
|
||||
languageLevel = '1.7'
|
||||
}
|
||||
|
||||
module {
|
||||
// Object directories take a huge amount of time for IntelliJ to index.
|
||||
// Exclude them. Convention is that object directories start with obj.
|
||||
// IntelliJ is clever and will not exclude the parts of the object
|
||||
// directory that are referenced, if there are any. In practice,
|
||||
// indexing the entirety of the tree is taking too long, so exclude all
|
||||
// but mobile/.
|
||||
def topsrcdirURI = file(topsrcdir).toURI()
|
||||
excludeDirs += files(file(topsrcdir)
|
||||
.listFiles({it.isDirectory()} as FileFilter)
|
||||
.collect({topsrcdirURI.relativize(it.toURI()).toString()}) // Relative paths.
|
||||
.findAll({!it.equals('mobile/')}))
|
||||
|
||||
// If topobjdir is below topsrcdir, hide only some portions of that tree.
|
||||
def topobjdirURI = file(topobjdir).toURI()
|
||||
if (!topsrcdirURI.relativize(topobjdirURI).isAbsolute()) {
|
||||
excludeDirs -= file(topobjdir)
|
||||
excludeDirs += files(file(topobjdir).listFiles())
|
||||
excludeDirs -= file("${topobjdir}/gradle")
|
||||
}
|
||||
|
||||
if (!mozconfig.substs.MOZ_INSTALL_TRACKING) {
|
||||
excludeDirs += file("${topsrcdir}/mobile/android/thirdparty/com/adjust")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors;
|
||||
|
||||
/**
|
||||
* Object holding annotation data. Used by GeneratableElementIterator.
|
||||
*/
|
||||
public class AnnotationInfo {
|
||||
public enum ExceptionMode {
|
||||
ABORT,
|
||||
NSRESULT,
|
||||
IGNORE;
|
||||
|
||||
String nativeValue() {
|
||||
return "mozilla::jni::ExceptionMode::" + name();
|
||||
}
|
||||
}
|
||||
|
||||
public enum CallingThread {
|
||||
GECKO,
|
||||
UI,
|
||||
ANY;
|
||||
|
||||
String nativeValue() {
|
||||
return "mozilla::jni::CallingThread::" + name();
|
||||
}
|
||||
}
|
||||
|
||||
public enum DispatchTarget {
|
||||
GECKO,
|
||||
PROXY,
|
||||
CURRENT;
|
||||
|
||||
String nativeValue() {
|
||||
return "mozilla::jni::DispatchTarget::" + name();
|
||||
}
|
||||
}
|
||||
|
||||
public final String wrapperName;
|
||||
public final ExceptionMode exceptionMode;
|
||||
public final CallingThread callingThread;
|
||||
public final DispatchTarget dispatchTarget;
|
||||
|
||||
public AnnotationInfo(String wrapperName, ExceptionMode exceptionMode,
|
||||
CallingThread callingThread, DispatchTarget dispatchTarget) {
|
||||
|
||||
this.wrapperName = wrapperName;
|
||||
this.exceptionMode = exceptionMode;
|
||||
this.callingThread = callingThread;
|
||||
this.dispatchTarget = dispatchTarget;
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors;
|
||||
|
||||
import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
|
||||
import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
|
||||
import org.mozilla.gecko.annotationProcessors.classloader.IterableJarLoadingURLClassLoader;
|
||||
import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class AnnotationProcessor {
|
||||
public static final String GENERATED_COMMENT =
|
||||
"// GENERATED CODE\n" +
|
||||
"// Generated by the Java program at /build/annotationProcessors at compile time\n" +
|
||||
"// from annotations on Java methods. To update, change the annotations on the\n" +
|
||||
"// corresponding Java methods and rerun the build. Manually updating this file\n" +
|
||||
"// will cause your build to fail.\n" +
|
||||
"\n";
|
||||
|
||||
private static final StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
|
||||
private static final StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
|
||||
private static final StringBuilder nativesFile = new StringBuilder(GENERATED_COMMENT);
|
||||
|
||||
public static void main(String[] args) {
|
||||
// We expect a list of jars on the commandline. If missing, whinge about it.
|
||||
if (args.length <= 2) {
|
||||
System.err.println("Usage: java AnnotationProcessor outprefix jarfiles ...");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
final String OUTPUT_PREFIX = args[0];
|
||||
final String SOURCE_FILE = OUTPUT_PREFIX + "JNIWrappers.cpp";
|
||||
final String HEADER_FILE = OUTPUT_PREFIX + "JNIWrappers.h";
|
||||
final String NATIVES_FILE = OUTPUT_PREFIX + "JNINatives.h";
|
||||
|
||||
System.out.println("Processing annotations...");
|
||||
|
||||
// We want to produce the same output as last time as often as possible. Ordering of
|
||||
// generated statements, therefore, needs to be consistent.
|
||||
final String[] jars = Arrays.copyOfRange(args, 1, args.length);
|
||||
Arrays.sort(jars);
|
||||
|
||||
// Start the clock!
|
||||
long s = System.currentTimeMillis();
|
||||
|
||||
// Get an iterator over the classes in the jar files given...
|
||||
Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(jars);
|
||||
|
||||
headerFile.append(
|
||||
"#ifndef " + getHeaderGuardName(HEADER_FILE) + "\n" +
|
||||
"#define " + getHeaderGuardName(HEADER_FILE) + "\n" +
|
||||
"\n" +
|
||||
"#include \"mozilla/jni/Refs.h\"\n" +
|
||||
"\n" +
|
||||
"namespace mozilla {\n" +
|
||||
"namespace java {\n" +
|
||||
"\n");
|
||||
|
||||
implementationFile.append(
|
||||
"#include \"" + HEADER_FILE + "\"\n" +
|
||||
"#include \"mozilla/jni/Accessors.h\"\n" +
|
||||
"\n" +
|
||||
"namespace mozilla {\n" +
|
||||
"namespace java {\n" +
|
||||
"\n");
|
||||
|
||||
nativesFile.append(
|
||||
"#ifndef " + getHeaderGuardName(NATIVES_FILE) + "\n" +
|
||||
"#define " + getHeaderGuardName(NATIVES_FILE) + "\n" +
|
||||
"\n" +
|
||||
"#include \"" + HEADER_FILE + "\"\n" +
|
||||
"#include \"mozilla/jni/Natives.h\"\n" +
|
||||
"\n" +
|
||||
"namespace mozilla {\n" +
|
||||
"namespace java {\n" +
|
||||
"\n");
|
||||
|
||||
while (jarClassIterator.hasNext()) {
|
||||
generateClass(jarClassIterator.next());
|
||||
}
|
||||
|
||||
implementationFile.append(
|
||||
"} /* java */\n" +
|
||||
"} /* mozilla */\n");
|
||||
|
||||
headerFile.append(
|
||||
"} /* java */\n" +
|
||||
"} /* mozilla */\n" +
|
||||
"#endif // " + getHeaderGuardName(HEADER_FILE) + "\n");
|
||||
|
||||
nativesFile.append(
|
||||
"} /* java */\n" +
|
||||
"} /* mozilla */\n" +
|
||||
"#endif // " + getHeaderGuardName(NATIVES_FILE) + "\n");
|
||||
|
||||
writeOutputFile(SOURCE_FILE, implementationFile);
|
||||
writeOutputFile(HEADER_FILE, headerFile);
|
||||
writeOutputFile(NATIVES_FILE, nativesFile);
|
||||
|
||||
long e = System.currentTimeMillis();
|
||||
System.out.println("Annotation processing complete in " + (e - s) + "ms");
|
||||
}
|
||||
|
||||
private static void generateClass(final ClassWithOptions annotatedClass) {
|
||||
// Get an iterator over the appropriately generated methods of this class
|
||||
final GeneratableElementIterator methodIterator
|
||||
= new GeneratableElementIterator(annotatedClass);
|
||||
final ClassWithOptions[] innerClasses = methodIterator.getInnerClasses();
|
||||
|
||||
if (!methodIterator.hasNext() && innerClasses.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final CodeGenerator generatorInstance = new CodeGenerator(annotatedClass);
|
||||
generatorInstance.generateClasses(innerClasses);
|
||||
|
||||
// Iterate all annotated members in this class..
|
||||
while (methodIterator.hasNext()) {
|
||||
AnnotatableEntity aElementTuple = methodIterator.next();
|
||||
switch (aElementTuple.mEntityType) {
|
||||
case METHOD:
|
||||
generatorInstance.generateMethod(aElementTuple);
|
||||
break;
|
||||
case NATIVE:
|
||||
generatorInstance.generateNative(aElementTuple);
|
||||
break;
|
||||
case FIELD:
|
||||
generatorInstance.generateField(aElementTuple);
|
||||
break;
|
||||
case CONSTRUCTOR:
|
||||
generatorInstance.generateConstructor(aElementTuple);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
headerFile.append(generatorInstance.getHeaderFileContents());
|
||||
implementationFile.append(generatorInstance.getWrapperFileContents());
|
||||
nativesFile.append(generatorInstance.getNativesFileContents());
|
||||
|
||||
for (ClassWithOptions innerClass : innerClasses) {
|
||||
generateClass(innerClass);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getHeaderGuardName(final String name) {
|
||||
return name.replaceAll("\\W", "_");
|
||||
}
|
||||
|
||||
private static void writeOutputFile(final String name,
|
||||
final StringBuilder content) {
|
||||
FileOutputStream outStream = null;
|
||||
try {
|
||||
outStream = new FileOutputStream(name);
|
||||
outStream.write(content.toString().getBytes());
|
||||
} catch (IOException e) {
|
||||
System.err.println("Unable to write " + name + ". Perhaps a permissions issue?");
|
||||
e.printStackTrace(System.err);
|
||||
} finally {
|
||||
if (outStream != null) {
|
||||
try {
|
||||
outStream.close();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Unable to close outStream due to "+e);
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,627 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors;
|
||||
|
||||
import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
|
||||
import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
|
||||
import org.mozilla.gecko.annotationProcessors.utils.Utils;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class CodeGenerator {
|
||||
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
|
||||
|
||||
// Buffers holding the strings to ultimately be written to the output files.
|
||||
private final StringBuilder cpp = new StringBuilder();
|
||||
private final StringBuilder header = new StringBuilder();
|
||||
private final StringBuilder natives = new StringBuilder();
|
||||
private final StringBuilder nativesInits = new StringBuilder();
|
||||
|
||||
private final Class<?> cls;
|
||||
private final String clsName;
|
||||
private AnnotationInfo.CallingThread callingThread = null;
|
||||
private int numNativesInits;
|
||||
|
||||
private final HashSet<String> takenMethodNames = new HashSet<String>();
|
||||
|
||||
public CodeGenerator(ClassWithOptions annotatedClass) {
|
||||
this.cls = annotatedClass.wrappedClass;
|
||||
this.clsName = annotatedClass.generatedName;
|
||||
|
||||
final String unqualifiedName = Utils.getUnqualifiedName(clsName);
|
||||
header.append(
|
||||
"class " + clsName + " : public mozilla::jni::ObjectBase<" +
|
||||
unqualifiedName + ">\n" +
|
||||
"{\n" +
|
||||
"public:\n" +
|
||||
" static const char name[];\n" +
|
||||
"\n" +
|
||||
" explicit " + unqualifiedName + "(const Context& ctx) : ObjectBase<" +
|
||||
unqualifiedName + ">(ctx) {}\n" +
|
||||
"\n");
|
||||
|
||||
cpp.append(
|
||||
"const char " + clsName + "::name[] =\n" +
|
||||
" \"" + cls.getName().replace('.', '/') + "\";\n" +
|
||||
"\n");
|
||||
|
||||
natives.append(
|
||||
"template<class Impl>\n" +
|
||||
"class " + clsName + "::Natives : " +
|
||||
"public mozilla::jni::NativeImpl<" + unqualifiedName + ", Impl>\n" +
|
||||
"{\n" +
|
||||
"public:\n");
|
||||
}
|
||||
|
||||
private String getTraitsName(String uniqueName, boolean includeScope) {
|
||||
return (includeScope ? clsName + "::" : "") + uniqueName + "_t";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the C++ type name for this class or any class within the chain
|
||||
* of declaring classes, if the target class matches the given type.
|
||||
*
|
||||
* Return null if the given type does not match any class searched.
|
||||
*/
|
||||
private String getMatchingClassType(final Class<?> type) {
|
||||
Class<?> cls = this.cls;
|
||||
String clsName = this.clsName;
|
||||
|
||||
while (cls != null) {
|
||||
if (type.equals(cls)) {
|
||||
return clsName;
|
||||
}
|
||||
cls = cls.getDeclaringClass();
|
||||
clsName = clsName.substring(0, Math.max(0, clsName.lastIndexOf("::")));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getNativeParameterType(Class<?> type, AnnotationInfo info) {
|
||||
final String clsName = getMatchingClassType(type);
|
||||
if (clsName != null) {
|
||||
return Utils.getUnqualifiedName(clsName) + "::Param";
|
||||
}
|
||||
return Utils.getNativeParameterType(type, info);
|
||||
}
|
||||
|
||||
private String getNativeReturnType(Class<?> type, AnnotationInfo info) {
|
||||
final String clsName = getMatchingClassType(type);
|
||||
if (clsName != null) {
|
||||
return Utils.getUnqualifiedName(clsName) + "::LocalRef";
|
||||
}
|
||||
return Utils.getNativeReturnType(type, info);
|
||||
}
|
||||
|
||||
private void generateMember(AnnotationInfo info, Member member,
|
||||
String uniqueName, Class<?> type, Class<?>[] argTypes) {
|
||||
final StringBuilder args = new StringBuilder();
|
||||
for (Class<?> argType : argTypes) {
|
||||
args.append("\n " + getNativeParameterType(argType, info) + ",");
|
||||
}
|
||||
if (args.length() > 0) {
|
||||
args.setLength(args.length() - 1);
|
||||
}
|
||||
|
||||
header.append(
|
||||
" struct " + getTraitsName(uniqueName, /* includeScope */ false) + " {\n" +
|
||||
" typedef " + Utils.getUnqualifiedName(clsName) + " Owner;\n" +
|
||||
" typedef " + getNativeReturnType(type, info) + " ReturnType;\n" +
|
||||
" typedef " + getNativeParameterType(type, info) + " SetterType;\n" +
|
||||
" typedef mozilla::jni::Args<" + args + "> Args;\n" +
|
||||
" static constexpr char name[] = \"" +
|
||||
Utils.getMemberName(member) + "\";\n" +
|
||||
" static constexpr char signature[] =\n" +
|
||||
" \"" + Utils.getSignature(member) + "\";\n" +
|
||||
" static const bool isStatic = " + Utils.isStatic(member) + ";\n" +
|
||||
" static const mozilla::jni::ExceptionMode exceptionMode =\n" +
|
||||
" " + info.exceptionMode.nativeValue() + ";\n" +
|
||||
" static const mozilla::jni::CallingThread callingThread =\n" +
|
||||
" " + info.callingThread.nativeValue() + ";\n" +
|
||||
" static const mozilla::jni::DispatchTarget dispatchTarget =\n" +
|
||||
" " + info.dispatchTarget.nativeValue() + ";\n" +
|
||||
" };\n" +
|
||||
"\n");
|
||||
|
||||
cpp.append(
|
||||
"constexpr char " + getTraitsName(uniqueName, /* includeScope */ true) +
|
||||
"::name[];\n" +
|
||||
"constexpr char " + getTraitsName(uniqueName, /* includeScope */ true) +
|
||||
"::signature[];\n" +
|
||||
"\n");
|
||||
|
||||
if (this.callingThread == null) {
|
||||
this.callingThread = info.callingThread;
|
||||
} else if (this.callingThread != info.callingThread) {
|
||||
// We have a mix of calling threads, so specify "any" for the whole class.
|
||||
this.callingThread = AnnotationInfo.CallingThread.ANY;
|
||||
}
|
||||
}
|
||||
|
||||
private String getUniqueMethodName(String basename) {
|
||||
String newName = basename;
|
||||
int index = 1;
|
||||
|
||||
while (takenMethodNames.contains(newName)) {
|
||||
newName = basename + (++index);
|
||||
}
|
||||
|
||||
takenMethodNames.add(newName);
|
||||
return newName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a method prototype that includes return and argument types,
|
||||
* without specifiers (static, const, etc.).
|
||||
*/
|
||||
private String generatePrototype(String name, Class<?>[] argTypes,
|
||||
Class<?> returnType, AnnotationInfo info,
|
||||
boolean includeScope, boolean includeArgName,
|
||||
boolean isConst) {
|
||||
|
||||
final StringBuilder proto = new StringBuilder();
|
||||
int argIndex = 0;
|
||||
|
||||
proto.append("auto ");
|
||||
|
||||
if (includeScope) {
|
||||
proto.append(clsName).append("::");
|
||||
}
|
||||
|
||||
proto.append(name).append('(');
|
||||
|
||||
for (Class<?> argType : argTypes) {
|
||||
proto.append(getNativeParameterType(argType, info));
|
||||
if (includeArgName) {
|
||||
proto.append(" a").append(argIndex++);
|
||||
}
|
||||
proto.append(", ");
|
||||
}
|
||||
|
||||
if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT &&
|
||||
!returnType.equals(void.class)) {
|
||||
proto.append(getNativeReturnType(returnType, info)).append('*');
|
||||
if (includeArgName) {
|
||||
proto.append(" a").append(argIndex++);
|
||||
}
|
||||
proto.append(", ");
|
||||
}
|
||||
|
||||
if (proto.substring(proto.length() - 2).equals(", ")) {
|
||||
proto.setLength(proto.length() - 2);
|
||||
}
|
||||
|
||||
proto.append(')');
|
||||
|
||||
if (isConst) {
|
||||
proto.append(" const");
|
||||
}
|
||||
|
||||
if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT) {
|
||||
proto.append(" -> nsresult");
|
||||
} else {
|
||||
proto.append(" -> ").append(getNativeReturnType(returnType, info));
|
||||
}
|
||||
return proto.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a method declaration that includes the prototype with specifiers,
|
||||
* but without the method body.
|
||||
*/
|
||||
private String generateDeclaration(String name, Class<?>[] argTypes,
|
||||
Class<?> returnType, AnnotationInfo info,
|
||||
boolean isStatic) {
|
||||
|
||||
return (isStatic ? "static " : "") +
|
||||
generatePrototype(name, argTypes, returnType, info,
|
||||
/* includeScope */ false, /* includeArgName */ false,
|
||||
/* isConst */ !isStatic) + ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a method definition that includes the prototype with specifiers,
|
||||
* and with the method body.
|
||||
*/
|
||||
private String generateDefinition(String accessorName, String name, Class<?>[] argTypes,
|
||||
Class<?> returnType, AnnotationInfo info, boolean isStatic) {
|
||||
|
||||
final StringBuilder def = new StringBuilder(
|
||||
generatePrototype(name, argTypes, returnType, info,
|
||||
/* includeScope */ true, /* includeArgName */ true,
|
||||
/* isConst */ !isStatic));
|
||||
def.append("\n{\n");
|
||||
|
||||
|
||||
// Generate code to handle the return value, if needed.
|
||||
// We initialize rv to NS_OK instead of NS_ERROR_* because loading NS_OK (0) uses
|
||||
// fewer instructions. We are guaranteed to set rv to the correct value later.
|
||||
|
||||
if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT &&
|
||||
returnType.equals(void.class)) {
|
||||
def.append(
|
||||
" nsresult rv = NS_OK;\n" +
|
||||
" ");
|
||||
|
||||
} else if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT) {
|
||||
// Non-void return type
|
||||
final String resultArg = "a" + argTypes.length;
|
||||
def.append(
|
||||
" MOZ_ASSERT(" + resultArg + ");\n" +
|
||||
" nsresult rv = NS_OK;\n" +
|
||||
" *" + resultArg + " = ");
|
||||
|
||||
} else {
|
||||
def.append(
|
||||
" return ");
|
||||
}
|
||||
|
||||
|
||||
// Generate a call, e.g., Method<Traits>::Call(a0, a1, a2);
|
||||
|
||||
def.append(accessorName).append("(")
|
||||
.append(Utils.getUnqualifiedName(clsName) +
|
||||
(isStatic ? "::Context()" : "::mCtx"));
|
||||
|
||||
if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT) {
|
||||
def.append(", &rv");
|
||||
} else {
|
||||
def.append(", nullptr");
|
||||
}
|
||||
|
||||
// Generate the call argument list.
|
||||
for (int argIndex = 0; argIndex < argTypes.length; argIndex++) {
|
||||
def.append(", a").append(argIndex);
|
||||
}
|
||||
|
||||
def.append(");\n");
|
||||
|
||||
|
||||
if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT) {
|
||||
def.append(" return rv;\n");
|
||||
}
|
||||
|
||||
return def.append("}").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the appropriate generated code to the buffers for the method provided.
|
||||
*
|
||||
* @param annotatedMethod The Java method, plus annotation data.
|
||||
*/
|
||||
public void generateMethod(AnnotatableEntity annotatedMethod) {
|
||||
// Unpack the tuple and extract some useful fields from the Method..
|
||||
final Method method = annotatedMethod.getMethod();
|
||||
final AnnotationInfo info = annotatedMethod.mAnnotationInfo;
|
||||
final String uniqueName = getUniqueMethodName(info.wrapperName);
|
||||
final Class<?>[] argTypes = method.getParameterTypes();
|
||||
final Class<?> returnType = method.getReturnType();
|
||||
|
||||
if (method.isSynthetic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (info.dispatchTarget != AnnotationInfo.DispatchTarget.CURRENT) {
|
||||
throw new IllegalStateException("Invalid dispatch target \"" +
|
||||
info.dispatchTarget.name().toLowerCase() +
|
||||
"\" for non-native method " + clsName + "::" + uniqueName);
|
||||
}
|
||||
|
||||
generateMember(info, method, uniqueName, returnType, argTypes);
|
||||
|
||||
final boolean isStatic = Utils.isStatic(method);
|
||||
|
||||
header.append(
|
||||
" " + generateDeclaration(info.wrapperName, argTypes,
|
||||
returnType, info, isStatic) + "\n" +
|
||||
"\n");
|
||||
|
||||
cpp.append(
|
||||
generateDefinition(
|
||||
"mozilla::jni::Method<" +
|
||||
getTraitsName(uniqueName, /* includeScope */ false) + ">::Call",
|
||||
info.wrapperName, argTypes, returnType, info, isStatic) + "\n" +
|
||||
"\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the appropriate generated code to the buffers for the native method provided.
|
||||
*
|
||||
* @param annotatedMethod The Java native method, plus annotation data.
|
||||
*/
|
||||
public void generateNative(AnnotatableEntity annotatedMethod) {
|
||||
// Unpack the tuple and extract some useful fields from the Method..
|
||||
final Method method = annotatedMethod.getMethod();
|
||||
final AnnotationInfo info = annotatedMethod.mAnnotationInfo;
|
||||
final String uniqueName = getUniqueMethodName(info.wrapperName);
|
||||
final Class<?>[] argTypes = method.getParameterTypes();
|
||||
final Class<?> returnType = method.getReturnType();
|
||||
|
||||
// Sanity check
|
||||
if (info.exceptionMode != AnnotationInfo.ExceptionMode.ABORT &&
|
||||
info.exceptionMode != AnnotationInfo.ExceptionMode.IGNORE) {
|
||||
throw new IllegalStateException("Invalid exception mode \"" +
|
||||
info.exceptionMode.name().toLowerCase() +
|
||||
"\" for native method " + clsName + "::" + uniqueName);
|
||||
}
|
||||
if (info.dispatchTarget != AnnotationInfo.DispatchTarget.CURRENT &&
|
||||
returnType != void.class) {
|
||||
throw new IllegalStateException(
|
||||
"Must return void when not dispatching to current thread for native method " +
|
||||
clsName + "::" + uniqueName);
|
||||
}
|
||||
|
||||
generateMember(info, method, uniqueName, returnType, argTypes);
|
||||
|
||||
final String traits = getTraitsName(uniqueName, /* includeScope */ true);
|
||||
|
||||
if (nativesInits.length() > 0) {
|
||||
nativesInits.append(',');
|
||||
}
|
||||
|
||||
nativesInits.append(
|
||||
"\n" +
|
||||
"\n" +
|
||||
" mozilla::jni::MakeNativeMethod<" + traits + ">(\n" +
|
||||
" mozilla::jni::NativeStub<" + traits + ", Impl>\n" +
|
||||
" ::template Wrap<&Impl::" + info.wrapperName + ">)");
|
||||
numNativesInits++;
|
||||
}
|
||||
|
||||
private String getLiteral(Object val, AnnotationInfo info) {
|
||||
final Class<?> type = val.getClass();
|
||||
|
||||
if (type.equals(char.class) || type.equals(Character.class)) {
|
||||
final char c = (char) val;
|
||||
if (c >= 0x20 && c < 0x7F) {
|
||||
return "'" + c + '\'';
|
||||
}
|
||||
return "u'\\u" + Integer.toHexString(0x10000 | (int) c).substring(1) + '\'';
|
||||
|
||||
} else if (type.equals(CharSequence.class) || type.equals(String.class)) {
|
||||
final CharSequence str = (CharSequence) val;
|
||||
final StringBuilder out = new StringBuilder("u\"");
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
final char c = str.charAt(i);
|
||||
if (c >= 0x20 && c < 0x7F) {
|
||||
out.append(c);
|
||||
} else {
|
||||
out.append("\\u").append(Integer.toHexString(0x10000 | (int) c).substring(1));
|
||||
}
|
||||
}
|
||||
return out.append('"').toString();
|
||||
}
|
||||
|
||||
return String.valueOf(val);
|
||||
}
|
||||
|
||||
public void generateField(AnnotatableEntity annotatedField) {
|
||||
final Field field = annotatedField.getField();
|
||||
final AnnotationInfo info = annotatedField.mAnnotationInfo;
|
||||
final String uniqueName = info.wrapperName;
|
||||
final Class<?> type = field.getType();
|
||||
|
||||
// Handles a peculiar case when dealing with enum types. We don't care about this field.
|
||||
// It just gets in the way and stops our code from compiling.
|
||||
if (field.isSynthetic() || field.getName().equals("$VALUES")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (info.dispatchTarget != AnnotationInfo.DispatchTarget.CURRENT) {
|
||||
throw new IllegalStateException("Invalid dispatch target \"" +
|
||||
info.dispatchTarget.name().toLowerCase() +
|
||||
"\" for field " + clsName + "::" + uniqueName);
|
||||
}
|
||||
|
||||
final boolean isStatic = Utils.isStatic(field);
|
||||
final boolean isFinal = Utils.isFinal(field);
|
||||
|
||||
if (isStatic && isFinal && (type.isPrimitive() || type.equals(String.class))) {
|
||||
Object val = null;
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
val = field.get(null);
|
||||
} catch (final IllegalAccessException e) {
|
||||
}
|
||||
|
||||
if (val != null && type.isPrimitive()) {
|
||||
// For static final primitive fields, we can use a "static const" declaration.
|
||||
header.append(
|
||||
" static const " + Utils.getNativeReturnType(type, info) +
|
||||
' ' + info.wrapperName + " = " + getLiteral(val, info) + ";\n" +
|
||||
"\n");
|
||||
return;
|
||||
|
||||
} else if (val != null && type.equals(String.class)) {
|
||||
final String nativeType = "char16_t";
|
||||
|
||||
header.append(
|
||||
" static const " + nativeType + ' ' + info.wrapperName + "[];\n" +
|
||||
"\n");
|
||||
|
||||
cpp.append(
|
||||
"const " + nativeType + ' ' + clsName + "::" + info.wrapperName +
|
||||
"[] = " + getLiteral(val, info) + ";\n" +
|
||||
"\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Fall back to using accessors if we encounter an exception.
|
||||
}
|
||||
|
||||
generateMember(info, field, uniqueName, type, EMPTY_CLASS_ARRAY);
|
||||
|
||||
final Class<?>[] getterArgs = EMPTY_CLASS_ARRAY;
|
||||
|
||||
header.append(
|
||||
" " + generateDeclaration(info.wrapperName, getterArgs,
|
||||
type, info, isStatic) + "\n" +
|
||||
"\n");
|
||||
|
||||
cpp.append(
|
||||
generateDefinition(
|
||||
"mozilla::jni::Field<" +
|
||||
getTraitsName(uniqueName, /* includeScope */ false) + ">::Get",
|
||||
info.wrapperName, getterArgs, type, info, isStatic) + "\n" +
|
||||
"\n");
|
||||
|
||||
if (isFinal) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Class<?>[] setterArgs = new Class<?>[] { type };
|
||||
|
||||
header.append(
|
||||
" " + generateDeclaration(info.wrapperName, setterArgs,
|
||||
void.class, info, isStatic) + "\n" +
|
||||
"\n");
|
||||
|
||||
cpp.append(
|
||||
generateDefinition(
|
||||
"mozilla::jni::Field<" +
|
||||
getTraitsName(uniqueName, /* includeScope */ false) + ">::Set",
|
||||
info.wrapperName, setterArgs, void.class, info, isStatic) + "\n" +
|
||||
"\n");
|
||||
}
|
||||
|
||||
public void generateConstructor(AnnotatableEntity annotatedConstructor) {
|
||||
// Unpack the tuple and extract some useful fields from the Method..
|
||||
final Constructor<?> method = annotatedConstructor.getConstructor();
|
||||
final AnnotationInfo info = annotatedConstructor.mAnnotationInfo;
|
||||
final String wrapperName = "New";
|
||||
final String uniqueName = getUniqueMethodName(wrapperName);
|
||||
final Class<?>[] argTypes = method.getParameterTypes();
|
||||
final Class<?> returnType = cls;
|
||||
|
||||
if (method.isSynthetic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (info.dispatchTarget != AnnotationInfo.DispatchTarget.CURRENT) {
|
||||
throw new IllegalStateException("Invalid dispatch target \"" +
|
||||
info.dispatchTarget.name().toLowerCase() +
|
||||
"\" for constructor " + clsName + "::" + uniqueName);
|
||||
}
|
||||
|
||||
generateMember(info, method, uniqueName, returnType, argTypes);
|
||||
|
||||
header.append(
|
||||
" " + generateDeclaration(wrapperName, argTypes,
|
||||
returnType, info, /* isStatic */ true) + "\n" +
|
||||
"\n");
|
||||
|
||||
cpp.append(
|
||||
generateDefinition(
|
||||
"mozilla::jni::Constructor<" +
|
||||
getTraitsName(uniqueName, /* includeScope */ false) + ">::Call",
|
||||
wrapperName, argTypes, returnType, info, /* isStatic */ true) + "\n" +
|
||||
"\n");
|
||||
}
|
||||
|
||||
public void generateMembers(Member[] members) {
|
||||
for (Member m : members) {
|
||||
if (!Modifier.isPublic(m.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = Utils.getMemberName(m);
|
||||
name = name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
|
||||
// Default for SDK bindings.
|
||||
final AnnotationInfo info = new AnnotationInfo(name,
|
||||
AnnotationInfo.ExceptionMode.NSRESULT,
|
||||
AnnotationInfo.CallingThread.ANY,
|
||||
AnnotationInfo.DispatchTarget.CURRENT);
|
||||
final AnnotatableEntity entity = new AnnotatableEntity(m, info);
|
||||
|
||||
if (m instanceof Constructor) {
|
||||
generateConstructor(entity);
|
||||
} else if (m instanceof Method) {
|
||||
generateMethod(entity);
|
||||
} else if (m instanceof Field) {
|
||||
generateField(entity);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"expected member to be Constructor, Method, or Field");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void generateClasses(final ClassWithOptions[] classes) {
|
||||
if (classes.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final ClassWithOptions cls : classes) {
|
||||
// Extract "Inner" from "Outer::Inner".
|
||||
header.append(
|
||||
" class " + Utils.getUnqualifiedName(cls.generatedName) + ";\n");
|
||||
}
|
||||
header.append('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the finalised bytes to go into the generated wrappers file.
|
||||
*
|
||||
* @return The bytes to be written to the wrappers file.
|
||||
*/
|
||||
public String getWrapperFileContents() {
|
||||
return cpp.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the finalised bytes to go into the generated header file.
|
||||
*
|
||||
* @return The bytes to be written to the header file.
|
||||
*/
|
||||
public String getHeaderFileContents() {
|
||||
if (this.callingThread == null) {
|
||||
this.callingThread = AnnotationInfo.CallingThread.ANY;
|
||||
}
|
||||
|
||||
header.append(
|
||||
" static const mozilla::jni::CallingThread callingThread =\n" +
|
||||
" " + this.callingThread.nativeValue() + ";\n" +
|
||||
"\n");
|
||||
|
||||
if (nativesInits.length() > 0) {
|
||||
header.append(
|
||||
" template<class Impl> class Natives;\n");
|
||||
}
|
||||
header.append(
|
||||
"};\n" +
|
||||
"\n");
|
||||
return header.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the finalised bytes to go into the generated natives header file.
|
||||
*
|
||||
* @return The bytes to be written to the header file.
|
||||
*/
|
||||
public String getNativesFileContents() {
|
||||
if (nativesInits.length() == 0) {
|
||||
return "";
|
||||
}
|
||||
natives.append(
|
||||
" static const JNINativeMethod methods[" + numNativesInits + "];\n" +
|
||||
"};\n" +
|
||||
"\n" +
|
||||
"template<class Impl>\n" +
|
||||
"const JNINativeMethod " + clsName + "::Natives<Impl>::methods[] = {" + nativesInits + '\n' +
|
||||
"};\n" +
|
||||
"\n");
|
||||
return natives.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
# Include Android specific java flags, instead of what's in rules.mk.
|
||||
include $(topsrcdir)/config/android-common.mk
|
||||
|
||||
export:: annotationProcessors.jar
|
||||
@@ -1,258 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors;
|
||||
|
||||
import com.android.tools.lint.checks.ApiLookup;
|
||||
import com.android.tools.lint.LintCliClient;
|
||||
|
||||
import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
|
||||
import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
|
||||
import org.mozilla.gecko.annotationProcessors.classloader.IterableJarLoadingURLClassLoader;
|
||||
import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator;
|
||||
import org.mozilla.gecko.annotationProcessors.utils.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
import java.util.Scanner;
|
||||
import java.util.Vector;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class SDKProcessor {
|
||||
public static final String GENERATED_COMMENT =
|
||||
"// GENERATED CODE\n" +
|
||||
"// Generated by the Java program at /build/annotationProcessors at compile time\n" +
|
||||
"// from annotations on Java methods. To update, change the annotations on the\n" +
|
||||
"// corresponding Javamethods and rerun the build. Manually updating this file\n" +
|
||||
"// will cause your build to fail.\n" +
|
||||
"\n";
|
||||
|
||||
private static ApiLookup sApiLookup;
|
||||
private static int sMaxSdkVersion;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// We expect a list of jars on the commandline. If missing, whinge about it.
|
||||
if (args.length < 5) {
|
||||
System.err.println("Usage: java SDKProcessor sdkjar classlistfile outdir fileprefix max-sdk-version");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
System.out.println("Processing platform bindings...");
|
||||
|
||||
String sdkJar = args[0];
|
||||
Vector classes = getClassList(args[1]);
|
||||
String outdir = args[2];
|
||||
String generatedFilePrefix = args[3];
|
||||
sMaxSdkVersion = Integer.parseInt(args[4]);
|
||||
|
||||
LintCliClient lintClient = new LintCliClient();
|
||||
sApiLookup = ApiLookup.get(lintClient);
|
||||
|
||||
// Start the clock!
|
||||
long s = System.currentTimeMillis();
|
||||
|
||||
// Get an iterator over the classes in the jar files given...
|
||||
// Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
|
||||
|
||||
StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
|
||||
headerFile.append(
|
||||
"#ifndef " + generatedFilePrefix + "_h__\n" +
|
||||
"#define " + generatedFilePrefix + "_h__\n" +
|
||||
"\n" +
|
||||
"#include \"mozilla/jni/Refs.h\"\n" +
|
||||
"\n" +
|
||||
"namespace mozilla {\n" +
|
||||
"namespace java {\n" +
|
||||
"namespace sdk {\n" +
|
||||
"\n");
|
||||
|
||||
StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
|
||||
implementationFile.append(
|
||||
"#include \"" + generatedFilePrefix + ".h\"\n" +
|
||||
"#include \"mozilla/jni/Accessors.h\"\n" +
|
||||
"\n" +
|
||||
"namespace mozilla {\n" +
|
||||
"namespace java {\n" +
|
||||
"namespace sdk {\n" +
|
||||
"\n");
|
||||
|
||||
// Used to track the calls to the various class-specific initialisation functions.
|
||||
ClassLoader loader = null;
|
||||
try {
|
||||
loader = URLClassLoader.newInstance(new URL[] { new URL("file://" + sdkJar) },
|
||||
SDKProcessor.class.getClassLoader());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e.toString());
|
||||
}
|
||||
|
||||
for (Iterator<String> i = classes.iterator(); i.hasNext(); ) {
|
||||
String className = i.next();
|
||||
System.out.println("Looking up: " + className);
|
||||
|
||||
generateClass(Class.forName(className, true, loader),
|
||||
implementationFile,
|
||||
headerFile);
|
||||
}
|
||||
|
||||
implementationFile.append(
|
||||
"} /* sdk */\n" +
|
||||
"} /* java */\n" +
|
||||
"} /* mozilla */\n");
|
||||
|
||||
headerFile.append(
|
||||
"} /* sdk */\n" +
|
||||
"} /* java */\n" +
|
||||
"} /* mozilla */\n" +
|
||||
"#endif\n");
|
||||
|
||||
writeOutputFiles(outdir, generatedFilePrefix, headerFile, implementationFile);
|
||||
long e = System.currentTimeMillis();
|
||||
System.out.println("SDK processing complete in " + (e - s) + "ms");
|
||||
}
|
||||
|
||||
private static int getAPIVersion(Class<?> cls, Member m) {
|
||||
if (m instanceof Method || m instanceof Constructor) {
|
||||
return sApiLookup.getCallVersion(
|
||||
cls.getName().replace('.', '/'),
|
||||
Utils.getMemberName(m),
|
||||
Utils.getSignature(m));
|
||||
} else if (m instanceof Field) {
|
||||
return sApiLookup.getFieldVersion(
|
||||
Utils.getClassDescriptor(m.getDeclaringClass()), m.getName());
|
||||
} else {
|
||||
throw new IllegalArgumentException("expected member to be Method, Constructor, or Field");
|
||||
}
|
||||
}
|
||||
|
||||
private static Member[] sortAndFilterMembers(Class<?> cls, Member[] members) {
|
||||
Arrays.sort(members, new Comparator<Member>() {
|
||||
@Override
|
||||
public int compare(Member a, Member b) {
|
||||
return a.getName().compareTo(b.getName());
|
||||
}
|
||||
});
|
||||
|
||||
ArrayList<Member> list = new ArrayList<>();
|
||||
for (Member m : members) {
|
||||
// Sometimes (e.g. Bundle) has methods that moved to/from a superclass in a later SDK
|
||||
// version, so we check for both classes and see if we can find a minimum SDK version.
|
||||
int version = getAPIVersion(cls, m);
|
||||
final int version2 = getAPIVersion(m.getDeclaringClass(), m);
|
||||
if (version2 > 0 && version2 < version) {
|
||||
version = version2;
|
||||
}
|
||||
if (version > sMaxSdkVersion) {
|
||||
System.out.println("Skipping " + m.getDeclaringClass().getName() + "." + m.getName() +
|
||||
", version " + version + " > " + sMaxSdkVersion);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sometimes (e.g. KeyEvent) a field can appear in both a class and a superclass. In
|
||||
// that case we want to filter out the version that appears in the superclass, or
|
||||
// we'll have bindings with duplicate names.
|
||||
try {
|
||||
if (m instanceof Field && !m.equals(cls.getField(m.getName()))) {
|
||||
// m is a field in a superclass that has been hidden by
|
||||
// a field with the same name in a subclass.
|
||||
System.out.println("Skipping " + m.getName() +
|
||||
" from " + m.getDeclaringClass());
|
||||
continue;
|
||||
}
|
||||
} catch (final NoSuchFieldException e) {
|
||||
}
|
||||
|
||||
list.add(m);
|
||||
}
|
||||
|
||||
return list.toArray(new Member[list.size()]);
|
||||
}
|
||||
|
||||
private static void generateClass(Class<?> clazz,
|
||||
StringBuilder implementationFile,
|
||||
StringBuilder headerFile) {
|
||||
String generatedName = clazz.getSimpleName();
|
||||
|
||||
CodeGenerator generator = new CodeGenerator(new ClassWithOptions(clazz, generatedName));
|
||||
|
||||
generator.generateMembers(sortAndFilterMembers(clazz, clazz.getConstructors()));
|
||||
generator.generateMembers(sortAndFilterMembers(clazz, clazz.getMethods()));
|
||||
generator.generateMembers(sortAndFilterMembers(clazz, clazz.getFields()));
|
||||
|
||||
headerFile.append(generator.getHeaderFileContents());
|
||||
implementationFile.append(generator.getWrapperFileContents());
|
||||
}
|
||||
|
||||
private static Vector<String> getClassList(String path) {
|
||||
Scanner scanner = null;
|
||||
try {
|
||||
scanner = new Scanner(new FileInputStream(path));
|
||||
|
||||
Vector lines = new Vector();
|
||||
while (scanner.hasNextLine()) {
|
||||
lines.add(scanner.nextLine());
|
||||
}
|
||||
return lines;
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.toString());
|
||||
return null;
|
||||
} finally {
|
||||
if (scanner != null) {
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeOutputFiles(String aOutputDir, String aPrefix, StringBuilder aHeaderFile,
|
||||
StringBuilder aImplementationFile) {
|
||||
FileOutputStream implStream = null;
|
||||
try {
|
||||
implStream = new FileOutputStream(new File(aOutputDir, aPrefix + ".cpp"));
|
||||
implStream.write(aImplementationFile.toString().getBytes());
|
||||
} catch (IOException e) {
|
||||
System.err.println("Unable to write " + aOutputDir + ". Perhaps a permissions issue?");
|
||||
e.printStackTrace(System.err);
|
||||
} finally {
|
||||
if (implStream != null) {
|
||||
try {
|
||||
implStream.close();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Unable to close implStream due to "+e);
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileOutputStream headerStream = null;
|
||||
try {
|
||||
headerStream = new FileOutputStream(new File(aOutputDir, aPrefix + ".h"));
|
||||
headerStream.write(aHeaderFile.toString().getBytes());
|
||||
} catch (IOException e) {
|
||||
System.err.println("Unable to write " + aOutputDir + ". Perhaps a permissions issue?");
|
||||
e.printStackTrace(System.err);
|
||||
} finally {
|
||||
if (headerStream != null) {
|
||||
try {
|
||||
headerStream.close();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Unable to close headerStream due to "+e);
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors.classloader;
|
||||
|
||||
import org.mozilla.gecko.annotationProcessors.AnnotationInfo;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* Union type to hold either a method, field, or ctor. Allows us to iterate "The generatable stuff", despite
|
||||
* the fact that such things can be of either flavour.
|
||||
*/
|
||||
public class AnnotatableEntity {
|
||||
public enum ENTITY_TYPE {METHOD, NATIVE, FIELD, CONSTRUCTOR}
|
||||
|
||||
private final Member mMember;
|
||||
public final ENTITY_TYPE mEntityType;
|
||||
|
||||
public final AnnotationInfo mAnnotationInfo;
|
||||
|
||||
public AnnotatableEntity(Member aObject, AnnotationInfo aAnnotationInfo) {
|
||||
mMember = aObject;
|
||||
mAnnotationInfo = aAnnotationInfo;
|
||||
|
||||
if (aObject instanceof Method) {
|
||||
if (Modifier.isNative(aObject.getModifiers())) {
|
||||
mEntityType = ENTITY_TYPE.NATIVE;
|
||||
} else {
|
||||
mEntityType = ENTITY_TYPE.METHOD;
|
||||
}
|
||||
} else if (aObject instanceof Field) {
|
||||
mEntityType = ENTITY_TYPE.FIELD;
|
||||
} else {
|
||||
mEntityType = ENTITY_TYPE.CONSTRUCTOR;
|
||||
}
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
if (mEntityType != ENTITY_TYPE.METHOD && mEntityType != ENTITY_TYPE.NATIVE) {
|
||||
throw new UnsupportedOperationException("Attempt to cast to unsupported member type.");
|
||||
}
|
||||
return (Method) mMember;
|
||||
}
|
||||
public Field getField() {
|
||||
if (mEntityType != ENTITY_TYPE.FIELD) {
|
||||
throw new UnsupportedOperationException("Attempt to cast to unsupported member type.");
|
||||
}
|
||||
return (Field) mMember;
|
||||
}
|
||||
public Constructor<?> getConstructor() {
|
||||
if (mEntityType != ENTITY_TYPE.CONSTRUCTOR) {
|
||||
throw new UnsupportedOperationException("Attempt to cast to unsupported member type.");
|
||||
}
|
||||
return (Constructor<?>) mMember;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors.classloader;
|
||||
|
||||
public class ClassWithOptions {
|
||||
public final Class<?> wrappedClass;
|
||||
public final String generatedName;
|
||||
|
||||
public ClassWithOptions(Class<?> someClass, String name) {
|
||||
wrappedClass = someClass;
|
||||
generatedName = name;
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors.classloader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* A classloader which can be initialised with a list of jar files and which can provide an iterator
|
||||
* over the top level classes in the jar files it was initialised with.
|
||||
* classNames is kept sorted to ensure iteration order is consistent across program invocations.
|
||||
* Otherwise, we'd forever be reporting the outdatedness of the generated code as we permute its
|
||||
* contents.
|
||||
*/
|
||||
public class IterableJarLoadingURLClassLoader extends URLClassLoader {
|
||||
LinkedList<String> classNames = new LinkedList<String>();
|
||||
|
||||
/**
|
||||
* Create an instance and return its iterator. Provides an iterator over the classes in the jar
|
||||
* files provided as arguments.
|
||||
* Inner classes are not supported.
|
||||
*
|
||||
* @param args A list of jar file names an iterator over the classes of which is desired.
|
||||
* @return An iterator over the top level classes in the jar files provided, in arbitrary order.
|
||||
*/
|
||||
public static Iterator<ClassWithOptions> getIteratorOverJars(String[] args) {
|
||||
URL[] urlArray = new URL[args.length];
|
||||
LinkedList<String> aClassNames = new LinkedList<String>();
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
try {
|
||||
urlArray[i] = (new File(args[i])).toURI().toURL();
|
||||
|
||||
Enumeration<JarEntry> entries = new JarFile(args[i]).entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry e = entries.nextElement();
|
||||
String fName = e.getName();
|
||||
if (!fName.endsWith(".class")) {
|
||||
continue;
|
||||
}
|
||||
final String className = fName.substring(0, fName.length() - 6).replace('/', '.');
|
||||
|
||||
aClassNames.add(className);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error loading jar file \"" + args[i] + '"');
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
Collections.sort(aClassNames);
|
||||
return new JarClassIterator(new IterableJarLoadingURLClassLoader(urlArray, aClassNames));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a classloader capable of loading all classes given as URLs in urls. Used by static
|
||||
* method above.
|
||||
*
|
||||
* @param urls URLs for all classes the new instance shall be capable of loading.
|
||||
* @param aClassNames A list of names of the classes this instance shall be capable of loading.
|
||||
*/
|
||||
protected IterableJarLoadingURLClassLoader(URL[] urls, LinkedList<String> aClassNames) {// Array to populate with URLs for each class in the given jars.
|
||||
super(urls);
|
||||
classNames = aClassNames;
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors.classloader;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Class for iterating over an IterableJarLoadingURLClassLoader's classes.
|
||||
*
|
||||
* This class is not thread safe: use it only from a single thread.
|
||||
*/
|
||||
public class JarClassIterator implements Iterator<ClassWithOptions> {
|
||||
private IterableJarLoadingURLClassLoader mTarget;
|
||||
private Iterator<String> mTargetClassListIterator;
|
||||
|
||||
private ClassWithOptions lookAhead;
|
||||
|
||||
public JarClassIterator(IterableJarLoadingURLClassLoader aTarget) {
|
||||
mTarget = aTarget;
|
||||
mTargetClassListIterator = aTarget.classNames.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return fillLookAheadIfPossible();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassWithOptions next() {
|
||||
if (!fillLookAheadIfPossible()) {
|
||||
throw new IllegalStateException("Failed to look ahead in next()!");
|
||||
}
|
||||
ClassWithOptions next = lookAhead;
|
||||
lookAhead = null;
|
||||
return next;
|
||||
}
|
||||
|
||||
private boolean fillLookAheadIfPossible() {
|
||||
if (lookAhead != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mTargetClassListIterator.hasNext()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String className = mTargetClassListIterator.next();
|
||||
try {
|
||||
Class<?> ret = mTarget.loadClass(className);
|
||||
|
||||
// Incremental builds can leave stale classfiles in the jar. Such classfiles will cause
|
||||
// an exception at this point. We can safely ignore these classes - they cannot possibly
|
||||
// ever be loaded as they conflict with their parent class and will be killed by
|
||||
// Proguard later on anyway.
|
||||
final Class<?> enclosingClass;
|
||||
try {
|
||||
enclosingClass = ret.getEnclosingClass();
|
||||
} catch (IncompatibleClassChangeError e) {
|
||||
return fillLookAheadIfPossible();
|
||||
}
|
||||
|
||||
if (enclosingClass != null) {
|
||||
// Anonymous inner class - unsupported.
|
||||
// Or named inner class, which will be processed when we process the outer class.
|
||||
return fillLookAheadIfPossible();
|
||||
}
|
||||
|
||||
lookAhead = new ClassWithOptions(ret, ret.getSimpleName());
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("Unable to enumerate class: " + className + ". Corrupted jar file?");
|
||||
e.printStackTrace();
|
||||
System.exit(2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Removal of classes from iterator not supported.");
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
jar = add_java_jar('annotationProcessors')
|
||||
jar.sources += [
|
||||
'AnnotationInfo.java',
|
||||
'AnnotationProcessor.java',
|
||||
'classloader/AnnotatableEntity.java',
|
||||
'classloader/ClassWithOptions.java',
|
||||
'classloader/IterableJarLoadingURLClassLoader.java',
|
||||
'classloader/JarClassIterator.java',
|
||||
'CodeGenerator.java',
|
||||
'SDKProcessor.java',
|
||||
'utils/AlphabeticAnnotatableEntityComparator.java',
|
||||
'utils/GeneratableElementIterator.java',
|
||||
'utils/Utils.java',
|
||||
]
|
||||
jar.extra_jars += [
|
||||
CONFIG['ANDROID_TOOLS'] + '/lib/lint.jar',
|
||||
CONFIG['ANDROID_TOOLS'] + '/lib/lint-checks.jar',
|
||||
]
|
||||
@@ -1,81 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors.utils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class AlphabeticAnnotatableEntityComparator<T extends Member> implements Comparator<T> {
|
||||
@Override
|
||||
public int compare(T aLhs, T aRhs) {
|
||||
// Constructors, Methods, Fields.
|
||||
boolean lIsConstructor = aLhs instanceof Constructor;
|
||||
boolean rIsConstructor = aRhs instanceof Constructor;
|
||||
boolean lIsMethod = aLhs instanceof Method;
|
||||
boolean rIsField = aRhs instanceof Field;
|
||||
|
||||
if (lIsConstructor) {
|
||||
if (!rIsConstructor) {
|
||||
return -1;
|
||||
}
|
||||
} else if (lIsMethod) {
|
||||
if (rIsConstructor) {
|
||||
return 1;
|
||||
} else if (rIsField) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!rIsField) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify these objects are the same type and cast them.
|
||||
if (aLhs instanceof Method) {
|
||||
return compare((Method) aLhs, (Method) aRhs);
|
||||
} else if (aLhs instanceof Field) {
|
||||
return compare((Field) aLhs, (Field) aRhs);
|
||||
} else {
|
||||
return compare((Constructor) aLhs, (Constructor) aRhs);
|
||||
}
|
||||
}
|
||||
|
||||
// Alas, the type system fails us.
|
||||
private static int compare(Method aLhs, Method aRhs) {
|
||||
// Initially, attempt to differentiate the methods be name alone..
|
||||
String lName = aLhs.getName();
|
||||
String rName = aRhs.getName();
|
||||
|
||||
int ret = lName.compareTo(rName);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// The names were the same, so we need to compare signatures to find their uniqueness..
|
||||
lName = Utils.getSignature(aLhs);
|
||||
rName = Utils.getSignature(aRhs);
|
||||
|
||||
return lName.compareTo(rName);
|
||||
}
|
||||
|
||||
private static int compare(Constructor<?> aLhs, Constructor<?> aRhs) {
|
||||
// The names will be the same, so we need to compare signatures to find their uniqueness..
|
||||
String lName = Utils.getSignature(aLhs);
|
||||
String rName = Utils.getSignature(aRhs);
|
||||
|
||||
return lName.compareTo(rName);
|
||||
}
|
||||
|
||||
private static int compare(Field aLhs, Field aRhs) {
|
||||
// Compare field names..
|
||||
String lName = aLhs.getName();
|
||||
String rName = aRhs.getName();
|
||||
|
||||
return lName.compareTo(rName);
|
||||
}
|
||||
}
|
||||
@@ -1,267 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors.utils;
|
||||
|
||||
import org.mozilla.gecko.annotationProcessors.AnnotationInfo;
|
||||
import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
|
||||
import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Iterator over the methods in a given method list which have the WrappedJNIMethod
|
||||
* annotation. Returns an object containing both the annotation (Which may contain interesting
|
||||
* parameters) and the argument.
|
||||
*/
|
||||
public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
||||
private final ClassWithOptions mClass;
|
||||
private final Member[] mObjects;
|
||||
private AnnotatableEntity mNextReturnValue;
|
||||
private int mElementIndex;
|
||||
private AnnotationInfo mClassInfo;
|
||||
|
||||
private boolean mIterateEveryEntry;
|
||||
private boolean mSkipCurrentEntry;
|
||||
|
||||
public GeneratableElementIterator(ClassWithOptions annotatedClass) {
|
||||
mClass = annotatedClass;
|
||||
|
||||
final Class<?> aClass = annotatedClass.wrappedClass;
|
||||
// Get all the elements of this class as AccessibleObjects.
|
||||
Member[] aMethods = aClass.getDeclaredMethods();
|
||||
Member[] aFields = aClass.getDeclaredFields();
|
||||
Member[] aCtors = aClass.getDeclaredConstructors();
|
||||
|
||||
// Shove them all into one buffer.
|
||||
Member[] objs = new Member[aMethods.length + aFields.length + aCtors.length];
|
||||
|
||||
int offset = 0;
|
||||
System.arraycopy(aMethods, 0, objs, 0, aMethods.length);
|
||||
offset += aMethods.length;
|
||||
System.arraycopy(aFields, 0, objs, offset, aFields.length);
|
||||
offset += aFields.length;
|
||||
System.arraycopy(aCtors, 0, objs, offset, aCtors.length);
|
||||
|
||||
// Sort the elements to ensure determinism.
|
||||
Arrays.sort(objs, new AlphabeticAnnotatableEntityComparator<Member>());
|
||||
mObjects = objs;
|
||||
|
||||
// Check for "Wrap ALL the things" flag.
|
||||
for (Annotation annotation : aClass.getDeclaredAnnotations()) {
|
||||
mClassInfo = buildAnnotationInfo(aClass, annotation);
|
||||
if (mClassInfo != null) {
|
||||
mIterateEveryEntry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mSkipCurrentEntry) {
|
||||
throw new IllegalArgumentException("Cannot skip entire class");
|
||||
}
|
||||
|
||||
findNextValue();
|
||||
}
|
||||
|
||||
private Class<?>[] getFilteredInnerClasses() {
|
||||
// Go through all inner classes and see which ones we want to generate.
|
||||
final Class<?>[] candidates = mClass.wrappedClass.getDeclaredClasses();
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < candidates.length; ++i) {
|
||||
final GeneratableElementIterator testIterator
|
||||
= new GeneratableElementIterator(new ClassWithOptions(candidates[i], null));
|
||||
if (testIterator.hasNext()
|
||||
|| testIterator.getFilteredInnerClasses() != null) {
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
// Clear out ones that don't match.
|
||||
candidates[i] = null;
|
||||
}
|
||||
return count > 0 ? candidates : null;
|
||||
}
|
||||
|
||||
public ClassWithOptions[] getInnerClasses() {
|
||||
final Class<?>[] candidates = getFilteredInnerClasses();
|
||||
if (candidates == null) {
|
||||
return new ClassWithOptions[0];
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (Class<?> candidate : candidates) {
|
||||
if (candidate != null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
final ClassWithOptions[] ret = new ClassWithOptions[count];
|
||||
count = 0;
|
||||
for (Class<?> candidate : candidates) {
|
||||
if (candidate != null) {
|
||||
ret[count++] = new ClassWithOptions(
|
||||
candidate, mClass.generatedName + "::" + candidate.getSimpleName());
|
||||
}
|
||||
}
|
||||
assert ret.length == count;
|
||||
|
||||
Arrays.sort(ret, new Comparator<ClassWithOptions>() {
|
||||
@Override public int compare(ClassWithOptions lhs, ClassWithOptions rhs) {
|
||||
return lhs.generatedName.compareTo(rhs.generatedName);
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static <T extends Enum<T>> T getEnumValue(Class<T> type, String name)
|
||||
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
||||
try {
|
||||
return Enum.valueOf(type, name.toUpperCase());
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
Object[] values = (Object[]) type.getDeclaredMethod("values").invoke(null);
|
||||
StringBuilder names = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (i != 0) {
|
||||
names.append(", ");
|
||||
}
|
||||
names.append(values[i].toString().toLowerCase());
|
||||
}
|
||||
|
||||
System.err.println("***");
|
||||
System.err.println("*** Invalid value \"" + name + "\" for " + type.getSimpleName());
|
||||
System.err.println("*** Specify one of " + names.toString());
|
||||
System.err.println("***");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(6);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private AnnotationInfo buildAnnotationInfo(AnnotatedElement element, Annotation annotation) {
|
||||
Class<? extends Annotation> annotationType = annotation.annotationType();
|
||||
final String annotationTypeName = annotationType.getName();
|
||||
if (!annotationTypeName.equals("org.mozilla.gecko.annotation.WrapForJNI")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String stubName = null;
|
||||
AnnotationInfo.ExceptionMode exceptionMode = null;
|
||||
AnnotationInfo.CallingThread callingThread = null;
|
||||
AnnotationInfo.DispatchTarget dispatchTarget = null;
|
||||
|
||||
try {
|
||||
final Method skipMethod = annotationType.getDeclaredMethod("skip");
|
||||
skipMethod.setAccessible(true);
|
||||
if ((Boolean) skipMethod.invoke(annotation)) {
|
||||
mSkipCurrentEntry = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Determine the explicitly-given name of the stub to generate, if any.
|
||||
final Method stubNameMethod = annotationType.getDeclaredMethod("stubName");
|
||||
stubNameMethod.setAccessible(true);
|
||||
stubName = (String) stubNameMethod.invoke(annotation);
|
||||
|
||||
final Method exceptionModeMethod = annotationType.getDeclaredMethod("exceptionMode");
|
||||
exceptionModeMethod.setAccessible(true);
|
||||
exceptionMode = getEnumValue(
|
||||
AnnotationInfo.ExceptionMode.class,
|
||||
(String) exceptionModeMethod.invoke(annotation));
|
||||
|
||||
final Method calledFromMethod = annotationType.getDeclaredMethod("calledFrom");
|
||||
calledFromMethod.setAccessible(true);
|
||||
callingThread = getEnumValue(
|
||||
AnnotationInfo.CallingThread.class,
|
||||
(String) calledFromMethod.invoke(annotation));
|
||||
|
||||
final Method dispatchToMethod = annotationType.getDeclaredMethod("dispatchTo");
|
||||
dispatchToMethod.setAccessible(true);
|
||||
dispatchTarget = getEnumValue(
|
||||
AnnotationInfo.DispatchTarget.class,
|
||||
(String) dispatchToMethod.invoke(annotation));
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
System.err.println("Unable to find expected field on WrapForJNI annotation. Did the signature change?");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(3);
|
||||
} catch (IllegalAccessException e) {
|
||||
System.err.println("IllegalAccessException reading fields on WrapForJNI annotation. Seems the semantics of Reflection have changed...");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(4);
|
||||
} catch (InvocationTargetException e) {
|
||||
System.err.println("InvocationTargetException reading fields on WrapForJNI annotation. This really shouldn't happen.");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(5);
|
||||
}
|
||||
|
||||
// If the method name was not explicitly given in the annotation generate one...
|
||||
if (stubName.isEmpty()) {
|
||||
stubName = Utils.getNativeName(element);
|
||||
}
|
||||
|
||||
return new AnnotationInfo(stubName, exceptionMode, callingThread, dispatchTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and cache the next appropriately annotated method, plus the annotation parameter, if
|
||||
* one exists. Otherwise cache null, so hasNext returns false.
|
||||
*/
|
||||
private void findNextValue() {
|
||||
while (mElementIndex < mObjects.length) {
|
||||
Member candidateElement = mObjects[mElementIndex];
|
||||
mElementIndex++;
|
||||
for (Annotation annotation : ((AnnotatedElement) candidateElement).getDeclaredAnnotations()) {
|
||||
AnnotationInfo info = buildAnnotationInfo((AnnotatedElement)candidateElement, annotation);
|
||||
if (info != null) {
|
||||
mNextReturnValue = new AnnotatableEntity(candidateElement, info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mSkipCurrentEntry) {
|
||||
mSkipCurrentEntry = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If no annotation found, we might be expected to generate anyway
|
||||
// using default arguments, thanks to the "Generate everything" annotation.
|
||||
if (mIterateEveryEntry) {
|
||||
AnnotationInfo annotationInfo = new AnnotationInfo(
|
||||
Utils.getNativeName(candidateElement),
|
||||
mClassInfo.exceptionMode,
|
||||
mClassInfo.callingThread,
|
||||
mClassInfo.dispatchTarget);
|
||||
mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mNextReturnValue = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return mNextReturnValue != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatableEntity next() {
|
||||
AnnotatableEntity ret = mNextReturnValue;
|
||||
findNextValue();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Removal of methods from GeneratableElementIterator not supported.");
|
||||
}
|
||||
}
|
||||
@@ -1,288 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors.utils;
|
||||
|
||||
import org.mozilla.gecko.annotationProcessors.AnnotationInfo;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* A collection of utility methods used by CodeGenerator. Largely used for translating types.
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
// A collection of lookup tables to simplify the functions to follow...
|
||||
private static final HashMap<String, String> NATIVE_TYPES = new HashMap<String, String>();
|
||||
|
||||
static {
|
||||
NATIVE_TYPES.put("void", "void");
|
||||
NATIVE_TYPES.put("boolean", "bool");
|
||||
NATIVE_TYPES.put("byte", "int8_t");
|
||||
NATIVE_TYPES.put("char", "char16_t");
|
||||
NATIVE_TYPES.put("short", "int16_t");
|
||||
NATIVE_TYPES.put("int", "int32_t");
|
||||
NATIVE_TYPES.put("long", "int64_t");
|
||||
NATIVE_TYPES.put("float", "float");
|
||||
NATIVE_TYPES.put("double", "double");
|
||||
}
|
||||
|
||||
private static final HashMap<String, String> NATIVE_ARRAY_TYPES = new HashMap<String, String>();
|
||||
|
||||
static {
|
||||
NATIVE_ARRAY_TYPES.put("boolean", "mozilla::jni::BooleanArray");
|
||||
NATIVE_ARRAY_TYPES.put("byte", "mozilla::jni::ByteArray");
|
||||
NATIVE_ARRAY_TYPES.put("char", "mozilla::jni::CharArray");
|
||||
NATIVE_ARRAY_TYPES.put("short", "mozilla::jni::ShortArray");
|
||||
NATIVE_ARRAY_TYPES.put("int", "mozilla::jni::IntArray");
|
||||
NATIVE_ARRAY_TYPES.put("long", "mozilla::jni::LongArray");
|
||||
NATIVE_ARRAY_TYPES.put("float", "mozilla::jni::FloatArray");
|
||||
NATIVE_ARRAY_TYPES.put("double", "mozilla::jni::DoubleArray");
|
||||
}
|
||||
|
||||
private static final HashMap<String, String> CLASS_DESCRIPTORS = new HashMap<String, String>();
|
||||
|
||||
static {
|
||||
CLASS_DESCRIPTORS.put("void", "V");
|
||||
CLASS_DESCRIPTORS.put("boolean", "Z");
|
||||
CLASS_DESCRIPTORS.put("byte", "B");
|
||||
CLASS_DESCRIPTORS.put("char", "C");
|
||||
CLASS_DESCRIPTORS.put("short", "S");
|
||||
CLASS_DESCRIPTORS.put("int", "I");
|
||||
CLASS_DESCRIPTORS.put("long", "J");
|
||||
CLASS_DESCRIPTORS.put("float", "F");
|
||||
CLASS_DESCRIPTORS.put("double", "D");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the C++ type corresponding to the provided type parameter.
|
||||
*
|
||||
* @param type Class to determine the corresponding JNI type for.
|
||||
* @return C++ type as a String
|
||||
*/
|
||||
public static String getNativeParameterType(Class<?> type, AnnotationInfo info) {
|
||||
final String name = type.getName().replace('.', '/');
|
||||
|
||||
if (NATIVE_TYPES.containsKey(name)) {
|
||||
return NATIVE_TYPES.get(name);
|
||||
}
|
||||
|
||||
if (type.isArray()) {
|
||||
final String compName = type.getComponentType().getName();
|
||||
if (NATIVE_ARRAY_TYPES.containsKey(compName)) {
|
||||
return NATIVE_ARRAY_TYPES.get(compName) + "::Param";
|
||||
}
|
||||
return "mozilla::jni::ObjectArray::Param";
|
||||
}
|
||||
|
||||
if (type.equals(String.class) || type.equals(CharSequence.class)) {
|
||||
return "mozilla::jni::String::Param";
|
||||
}
|
||||
|
||||
if (type.equals(Class.class)) {
|
||||
// You're doing reflection on Java objects from inside C, returning Class objects
|
||||
// to C, generating the corresponding code using this Java program. Really?!
|
||||
return "mozilla::jni::Class::Param";
|
||||
}
|
||||
|
||||
if (type.equals(Throwable.class)) {
|
||||
return "mozilla::jni::Throwable::Param";
|
||||
}
|
||||
|
||||
if (type.equals(ByteBuffer.class)) {
|
||||
return "mozilla::jni::ByteBuffer::Param";
|
||||
}
|
||||
|
||||
return "mozilla::jni::Object::Param";
|
||||
}
|
||||
|
||||
public static String getNativeReturnType(Class<?> type, AnnotationInfo info) {
|
||||
final String name = type.getName().replace('.', '/');
|
||||
|
||||
if (NATIVE_TYPES.containsKey(name)) {
|
||||
return NATIVE_TYPES.get(name);
|
||||
}
|
||||
|
||||
if (type.isArray()) {
|
||||
final String compName = type.getComponentType().getName();
|
||||
if (NATIVE_ARRAY_TYPES.containsKey(compName)) {
|
||||
return NATIVE_ARRAY_TYPES.get(compName) + "::LocalRef";
|
||||
}
|
||||
return "mozilla::jni::ObjectArray::LocalRef";
|
||||
}
|
||||
|
||||
if (type.equals(String.class)) {
|
||||
return "mozilla::jni::String::LocalRef";
|
||||
}
|
||||
|
||||
if (type.equals(Class.class)) {
|
||||
// You're doing reflection on Java objects from inside C, returning Class objects
|
||||
// to C, generating the corresponding code using this Java program. Really?!
|
||||
return "mozilla::jni::Class::LocalRef";
|
||||
}
|
||||
|
||||
if (type.equals(Throwable.class)) {
|
||||
return "mozilla::jni::Throwable::LocalRef";
|
||||
}
|
||||
|
||||
if (type.equals(ByteBuffer.class)) {
|
||||
return "mozilla::jni::ByteBuffer::LocalRef";
|
||||
}
|
||||
|
||||
return "mozilla::jni::Object::LocalRef";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JNI class descriptor corresponding to the provided type parameter.
|
||||
*
|
||||
* @param type Class to determine the corresponding JNI descriptor for.
|
||||
* @return Class descripor as a String
|
||||
*/
|
||||
public static String getClassDescriptor(Class<?> type) {
|
||||
final String name = type.getName().replace('.', '/');
|
||||
|
||||
if (CLASS_DESCRIPTORS.containsKey(name)) {
|
||||
return CLASS_DESCRIPTORS.get(name);
|
||||
}
|
||||
|
||||
if (type.isArray()) {
|
||||
// Array names are already in class descriptor form.
|
||||
return name;
|
||||
}
|
||||
|
||||
return "L" + name + ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JNI signaure for a member.
|
||||
*
|
||||
* @param member Member to get the signature for.
|
||||
* @return JNI signature as a string
|
||||
*/
|
||||
public static String getSignature(Member member) {
|
||||
return member instanceof Field ? getSignature((Field) member) :
|
||||
member instanceof Method ? getSignature((Method) member) :
|
||||
getSignature((Constructor<?>) member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JNI signaure for a field.
|
||||
*
|
||||
* @param member Field to get the signature for.
|
||||
* @return JNI signature as a string
|
||||
*/
|
||||
public static String getSignature(Field member) {
|
||||
return getClassDescriptor(member.getType());
|
||||
}
|
||||
|
||||
private static String getSignature(Class<?>[] args, Class<?> ret) {
|
||||
final StringBuilder sig = new StringBuilder("(");
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
sig.append(getClassDescriptor(args[i]));
|
||||
}
|
||||
return sig.append(')').append(getClassDescriptor(ret)).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JNI signaure for a method.
|
||||
*
|
||||
* @param member Method to get the signature for.
|
||||
* @return JNI signature as a string
|
||||
*/
|
||||
public static String getSignature(Method member) {
|
||||
return getSignature(member.getParameterTypes(), member.getReturnType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JNI signaure for a constructor.
|
||||
*
|
||||
* @param member Constructor to get the signature for.
|
||||
* @return JNI signature as a string
|
||||
*/
|
||||
public static String getSignature(Constructor<?> member) {
|
||||
return getSignature(member.getParameterTypes(), void.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the C++ name for a member.
|
||||
*
|
||||
* @param member Member to get the name for.
|
||||
* @return JNI name as a string
|
||||
*/
|
||||
public static String getNativeName(Member member) {
|
||||
final String name = getMemberName(member);
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the C++ name for a member.
|
||||
*
|
||||
* @param member Member to get the name for.
|
||||
* @return JNI name as a string
|
||||
*/
|
||||
public static String getNativeName(Class<?> clz) {
|
||||
final String name = clz.getName();
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the C++ name for a member.
|
||||
*
|
||||
* @param member Member to get the name for.
|
||||
* @return JNI name as a string
|
||||
*/
|
||||
public static String getNativeName(AnnotatedElement element) {
|
||||
if (element instanceof Class<?>) {
|
||||
return getNativeName((Class<?>)element);
|
||||
} else if (element instanceof Member) {
|
||||
return getNativeName((Member)element);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JNI name for a member.
|
||||
*
|
||||
* @param member Member to get the name for.
|
||||
* @return JNI name as a string
|
||||
*/
|
||||
public static String getMemberName(Member member) {
|
||||
if (member instanceof Constructor) {
|
||||
return "<init>";
|
||||
}
|
||||
return member.getName();
|
||||
}
|
||||
|
||||
public static String getUnqualifiedName(String name) {
|
||||
return name.substring(name.lastIndexOf(':') + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a member is declared static.
|
||||
*
|
||||
* @param member The Member to check.
|
||||
* @return true if the member is declared static, false otherwise.
|
||||
*/
|
||||
public static boolean isStatic(final Member member) {
|
||||
return Modifier.isStatic(member.getModifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a member is declared final.
|
||||
*
|
||||
* @param member The Member to check.
|
||||
* @return true if the member is declared final, false otherwise.
|
||||
*/
|
||||
public static boolean isFinal(final Member member) {
|
||||
return Modifier.isFinal(member.getModifiers());
|
||||
}
|
||||
}
|
||||
@@ -28,24 +28,12 @@ MOZ_ARG_WITH_STRING(arch,
|
||||
if test -z "$MOZ_ARCH"; then
|
||||
dnl Defaults
|
||||
case "${CPU_ARCH}-${OS_TARGET}" in
|
||||
arm-Android)
|
||||
MOZ_THUMB=yes
|
||||
MOZ_ARCH=armv7-a
|
||||
MOZ_FPU=vfp
|
||||
MOZ_FLOAT_ABI=softfp
|
||||
MOZ_ALIGN=no
|
||||
;;
|
||||
arm-Darwin)
|
||||
MOZ_ARCH=toolchain-default
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test "$MOZ_ARCH" = "armv6" -a "$OS_TARGET" = "Android"; then
|
||||
MOZ_FPU=vfp
|
||||
MOZ_FLOAT_ABI=softfp
|
||||
fi
|
||||
|
||||
MOZ_ARG_WITH_STRING(thumb,
|
||||
[ --with-thumb[[=yes|no|toolchain-default]]]
|
||||
[ Use Thumb instruction set (-mthumb)],
|
||||
|
||||
@@ -16,7 +16,7 @@ dnl set DEVELOPER_OPTIONS early; MOZ_DEFAULT_COMPILER is usually the first non-s
|
||||
DEVELOPER_OPTIONS=,
|
||||
DEVELOPER_OPTIONS=1)
|
||||
|
||||
dnl Default to MSVC for win32 and gcc-4.2 for darwin
|
||||
dnl Default to MSVC for win32
|
||||
dnl ==============================================================
|
||||
if test -z "$CROSS_COMPILE"; then
|
||||
case "$target" in
|
||||
@@ -176,8 +176,8 @@ if test "$GNU_CC"; then
|
||||
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
|
||||
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
|
||||
fi
|
||||
CFLAGS="$CFLAGS -fno-math-errno"
|
||||
CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
|
||||
CFLAGS="$CFLAGS -fno-math-errno -pipe"
|
||||
CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno -pipe"
|
||||
|
||||
if test "$CPU_ARCH" = "x86" -o "$CPU_ARCH" = "x86_64"; then
|
||||
CFLAGS="$CFLAGS -msse2 -mfpmath=sse"
|
||||
@@ -186,7 +186,8 @@ if test "$GNU_CC"; then
|
||||
|
||||
if test -z "$CLANG_CC"; then
|
||||
case "$CC_VERSION" in
|
||||
4.* | 5.*)
|
||||
4.* | 5.* | 6.*)
|
||||
AC_MSG_ERROR([Unsupported GCC version.])
|
||||
;;
|
||||
*)
|
||||
# Lifetime Dead Store Elimination level 2 (default in GCC6+) breaks Gecko.
|
||||
@@ -270,18 +271,9 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$DEVELOPER_OPTIONS"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# bionic in Android < 4.1 doesn't support PIE
|
||||
# On OSX, the linker defaults to building PIE programs when targetting OSX 10.7+,
|
||||
# but not when targetting OSX < 10.7. OSX < 10.7 doesn't support running PIE
|
||||
# programs, so as long as support for OSX 10.6 is kept, we can't build PIE.
|
||||
# Even after dropping 10.6 support, MOZ_PIE would not be useful since it's the
|
||||
# default (and clang says the -pie option is not used).
|
||||
# On other Unix systems, some file managers (Nautilus) can't start PIE programs
|
||||
if test -n "$gonkdir" && test "$ANDROID_VERSION" -ge 16; then
|
||||
MOZ_PIE=1
|
||||
else
|
||||
MOZ_PIE=
|
||||
fi
|
||||
# On some Unix systems, some file managers (e.g. Nautilus) can't start PIE programs
|
||||
# so don't enable it by default.
|
||||
MOZ_PIE=
|
||||
|
||||
MOZ_ARG_ENABLE_BOOL(pie,
|
||||
[ --enable-pie Enable Position Independent Executables],
|
||||
|
||||
Vendored
+2
-6
@@ -114,7 +114,7 @@ esac
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | \
|
||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
|
||||
kopensolaris*-gnu* | \
|
||||
@@ -122,10 +122,6 @@ case $maybe_os in
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
android-linux)
|
||||
os=-linux-android
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
|
||||
;;
|
||||
*)
|
||||
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
|
||||
if [ $basic_machine != $1 ]
|
||||
@@ -1389,7 +1385,7 @@ case $os in
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -mingw32* | -mingw64* | -linux-gnu* \
|
||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
|
||||
@@ -7,11 +7,6 @@ dnl disabling frame pointers in this architecture based on the configure
|
||||
dnl options
|
||||
|
||||
AC_DEFUN([MOZ_SET_FRAMEPTR_FLAGS], [
|
||||
case "$target" in
|
||||
*android*)
|
||||
unwind_tables="-funwind-tables"
|
||||
;;
|
||||
esac
|
||||
if test "$GNU_CC"; then
|
||||
MOZ_ENABLE_FRAME_PTR="-fno-omit-frame-pointer $unwind_tables"
|
||||
MOZ_DISABLE_FRAME_PTR="-fomit-frame-pointer"
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
dnl This Source Code Form is subject to the terms of the Mozilla Public
|
||||
dnl License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
AC_DEFUN([MOZ_IOS_PATH_PROG],
|
||||
[
|
||||
changequote({,})
|
||||
_prog_name=ifelse($2, {}, `echo $1 | tr "[:upper:]" "[:lower:]"`, $2)
|
||||
changequote([,])
|
||||
AC_CACHE_CHECK([for $_prog_name in iOS SDK],
|
||||
ac_cv_ios_path_$1,
|
||||
[
|
||||
_path=`xcrun --sdk $ios_sdk --find $_prog_name 2>/dev/null`
|
||||
_res=$?
|
||||
if test $_res -ne 0; then
|
||||
AC_MSG_ERROR([Could not find '$_prog_name' in the iOS SDK])
|
||||
fi
|
||||
ac_cv_ios_path_$1=$_path
|
||||
])
|
||||
$1="${ac_cv_ios_path_$1}$3"
|
||||
])
|
||||
|
||||
AC_DEFUN([MOZ_IOS_SDK],
|
||||
[
|
||||
|
||||
MOZ_ARG_WITH_STRING(ios-sdk,
|
||||
[ --with-ios-sdk=TYPE
|
||||
Type of iOS SDK to use (iphonesimulator, iphoneos)
|
||||
and optionally version (like iphoneos8.2)],
|
||||
ios_sdk=$withval)
|
||||
|
||||
MOZ_ARG_ENABLE_STRING(ios-target,
|
||||
[ --enable-ios-target=VER (default=8.0)
|
||||
Set the minimum iOS version needed at runtime],
|
||||
[_IOS_TARGET=$enableval])
|
||||
_IOS_TARGET_DEFAULT=8.0
|
||||
|
||||
case "$target" in
|
||||
arm*-apple-darwin*)
|
||||
if test -z "$ios_sdk" -o "$ios_sdk" = "yes"; then
|
||||
ios_sdk=iphoneos
|
||||
fi
|
||||
case "$ios_sdk" in
|
||||
iphoneos*)
|
||||
ios_target_arg="-miphoneos-version-min"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([Only 'iphoneos' SDKs are valid when targeting iOS device, don't know what to do with '$ios_sdk'.])
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*-apple-darwin*)
|
||||
ios_target_arg="-mios-simulator-version-min"
|
||||
case "$ios_sdk" in
|
||||
# Empty SDK is okay, this might be an OS X desktop build.
|
||||
""|iphonesimulator*)
|
||||
;;
|
||||
# Default to iphonesimulator
|
||||
yes)
|
||||
ios_sdk=iphonesimulator
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([Only 'iphonesimulator' SDKs are valid when targeting iOS simulator.])
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
if test -n "$ios_sdk"; then
|
||||
if test -z "$_IOS_TARGET"; then
|
||||
_IOS_TARGET=$_IOS_TARGET_DEFAULT
|
||||
ios_target_arg="${ios_target_arg}=${_IOS_TARGET}"
|
||||
fi
|
||||
# Ensure that xcrun knows where this SDK is.
|
||||
ios_sdk_path=`xcrun --sdk $ios_sdk --show-sdk-path 2>/dev/null`
|
||||
_ret=$?
|
||||
if test $_ret -ne 0; then
|
||||
AC_MSG_ERROR([iOS SDK '$ios_sdk' could not be found.])
|
||||
fi
|
||||
MOZ_IOS=1
|
||||
export HOST_CC=clang
|
||||
export HOST_CXX=clang++
|
||||
# Add isysroot, arch, and ios target arguments
|
||||
case "$target_cpu" in
|
||||
arm*)
|
||||
ARGS="-arch armv7"
|
||||
;;
|
||||
*)
|
||||
# Unfortunately simulator builds need this.
|
||||
export CROSS_COMPILE=1
|
||||
;;
|
||||
esac
|
||||
ARGS=" $ARGS -isysroot $ios_sdk_path $ios_target_arg"
|
||||
# Now find our tools
|
||||
MOZ_IOS_PATH_PROG(CC, clang, $ARGS)
|
||||
MOZ_IOS_PATH_PROG(CXX, clang++, $ARGS)
|
||||
export CPP="$CC -E"
|
||||
export LD="$CXX"
|
||||
MOZ_IOS_PATH_PROG(AR)
|
||||
MOZ_IOS_PATH_PROG(AS, as, $ARGS)
|
||||
MOZ_IOS_PATH_PROG(OTOOL)
|
||||
MOZ_IOS_PATH_PROG(STRIP)
|
||||
export PKG_CONFIG_PATH=${ios_sdk_path}/usr/lib/pkgconfig/
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_IOS)
|
||||
])
|
||||
@@ -138,6 +138,8 @@ if test -n "$NSPR_CFLAGS" -o -n "$NSPR_LIBS"; then
|
||||
,
|
||||
AC_MSG_ERROR([system NSPR does not support PR_UINT64 or including prtypes.h does not provide it]))
|
||||
CFLAGS=$_SAVE_CFLAGS
|
||||
NSPR_INCLUDE_DIR=`echo ${NSPR_CFLAGS} | sed -e 's/.*-I\([^ ]*\).*/\1/'`
|
||||
NSPR_LIB_DIR=`echo ${NSPR_LIBS} | sed -e 's/.*-L\([^ ]*\).*/\1/'`
|
||||
elif test -z "$JS_POSIX_NSPR"; then
|
||||
NSPR_INCLUDE_DIR="${DIST}/include/nspr"
|
||||
NSPR_CFLAGS="-I${NSPR_INCLUDE_DIR}"
|
||||
|
||||
@@ -27,6 +27,9 @@ fi
|
||||
if test "`echo | $AS -o conftest.out -v 2>&1 | grep -c GNU`" != "0"; then
|
||||
GNU_AS=1
|
||||
fi
|
||||
if test "`echo | $AS -o conftest.out -v 2>&1 | grep -c Apple`" != "0"; then
|
||||
GNU_AS=1
|
||||
fi
|
||||
rm -f conftest.out
|
||||
if test "`echo | $LD -v 2>&1 | grep -c GNU`" != "0"; then
|
||||
GNU_LD=1
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Imports
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Sanity check
|
||||
if not len(sys.argv) > 1:
|
||||
print("Incorrect number of arguments")
|
||||
sys.exit(1)
|
||||
|
||||
# Vars
|
||||
listConfigure = sys.argv[1:]
|
||||
listConfig = []
|
||||
strBrandingDirectory = ""
|
||||
listViolations = []
|
||||
|
||||
# Build a list of set configure variables
|
||||
for _value in listConfigure:
|
||||
_splitString = _value.split("=")
|
||||
|
||||
if _splitString[1] == "1":
|
||||
listConfig += [ _splitString[0] ]
|
||||
elif _splitString[0] == "MOZ_BRANDING_DIRECTORY":
|
||||
strBrandingDirectory = _splitString[1]
|
||||
|
||||
# Only applies if using Official Branding or specific branding directories
|
||||
if ('MOZ_OFFICIAL_BRANDING' in listConfig) or (strBrandingDirectory.endswith("branding/official")) or (strBrandingDirectory.endswith("branding/unstable")):
|
||||
# Applies to Pale Moon and Basilisk
|
||||
if ('MC_BASILISK' in listConfig) or ('MC_PALEMOON' in listConfig):
|
||||
listViolations += [
|
||||
'MOZ_SYSTEM_JPEG',
|
||||
'MOZ_SYSTEM_ZLIB',
|
||||
'MOZ_SYSTEM_BZ2',
|
||||
'MOZ_SYSTEM_JEMALLOC'
|
||||
]
|
||||
|
||||
# Applies to Pale Moon Only
|
||||
if 'MC_PALEMOON' in listConfig:
|
||||
listViolations += [
|
||||
'MOZ_EME',
|
||||
'MOZ_WEBRTC'
|
||||
]
|
||||
|
||||
# Iterate through enabled violations and output 1 to DIRECTIVE4 if any are found
|
||||
for _value in listViolations:
|
||||
if _value in listConfig:
|
||||
sys.stdout.write("1")
|
||||
sys.exit(1)
|
||||
|
||||
# Exit outputting nothing to DIRECTIVE4 being empty because there are no violations
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
.. _build_androideclipse:
|
||||
|
||||
========================
|
||||
Android Eclipse Projects
|
||||
========================
|
||||
|
||||
The build system contains alpha support for generating Android Eclipse
|
||||
project files to aid with development.
|
||||
|
||||
To generate Android Eclipse project files, you'll need to have a fully
|
||||
built and packaged tree::
|
||||
|
||||
mach build && mach package
|
||||
|
||||
(This is because Eclipse itself packages an APK containing
|
||||
``omni.ja``, and ``omni.ja`` is only assembled during packaging.)
|
||||
|
||||
Then, simply generate the Android Eclipse build backend::
|
||||
|
||||
mach build-backend -b AndroidEclipse
|
||||
|
||||
If all goes well, the path to the generated projects should be
|
||||
printed (currently, ``$OBJDIR/android_eclipse``).
|
||||
|
||||
To use the generated Android Eclipse project files, you'll need to
|
||||
have a recent version of Eclipse (see `Tested Versions`_) with the
|
||||
`Eclipse ADT plugin
|
||||
<http://developer.android.com/tools/sdk/eclipse-adt.html>`_
|
||||
installed. You can then import all the projects into Eclipse using
|
||||
*File > Import ... > General > Existing Projects into Workspace*.
|
||||
|
||||
Updating Project Files
|
||||
======================
|
||||
|
||||
As you pull and update the source tree, your Android Eclipse files may
|
||||
fall out of sync with the build configuration. The tree should still
|
||||
build fine from within Eclipse, but source files may be missing and in
|
||||
rare circumstances Eclipse's index may not have the proper build
|
||||
configuration.
|
||||
|
||||
To account for this, you'll want to periodically regenerate the
|
||||
Android Eclipse project files. You can do this by running ``mach build
|
||||
&& mach package && mach build-backend -b AndroidEclipse`` from the
|
||||
command line. It's a good idea to refresh and clean build all projects
|
||||
in Eclipse after doing this.
|
||||
|
||||
In future, we'd like to include an Android Eclipse run configuration
|
||||
or build target that integrates updating the project files.
|
||||
|
||||
Currently, regeneration rewrites the original project files. **If
|
||||
you've made any customizations to the projects, they will likely get
|
||||
overwritten.** We would like to improve this user experience in the
|
||||
future.
|
||||
|
||||
Troubleshooting
|
||||
===============
|
||||
|
||||
If Eclipse's builder gets confused, you should always refresh and
|
||||
clean build all projects. If Eclipse's builder is continually
|
||||
confused, you can see a log of what is happening at
|
||||
``$OBJDIR/android_eclipse/build.log``.
|
||||
|
||||
If you run into memory problems executing ``dex``, you should
|
||||
`Increase Eclipse's memory limits <http://stackoverflow.com/a/11093228>`_.
|
||||
|
||||
The produced Android Eclipse project files are unfortunately not
|
||||
portable. Please don't move them around.
|
||||
|
||||
Structure of Android Eclipse projects
|
||||
=====================================
|
||||
|
||||
The Android Eclipse backend generates several projects spanning Fennec
|
||||
itself and its tests. You'll mostly interact with the *Fennec* project
|
||||
itself.
|
||||
|
||||
In future, we'd like to expand this documentation to include some of
|
||||
the technical details of how the Eclipse integration works, and how to
|
||||
add additional Android Eclipse projects using the ``moz.build``
|
||||
system.
|
||||
|
||||
Tested Versions
|
||||
===============
|
||||
|
||||
=============== ==================================== =================
|
||||
OS Version Working as of
|
||||
=============== ==================================== =================
|
||||
Mac OS X Luna (Build id: 20130919-0819) February 2014
|
||||
Mac OS X Kepler (Build id: 20131219-0014) February 2014
|
||||
Mac OS X 10.8.5 Kepler (Build id: 20130919-0819) February 2014
|
||||
=============== ==================================== =================
|
||||
@@ -1,54 +0,0 @@
|
||||
.. _build_cppeclipse:
|
||||
|
||||
=====================
|
||||
Cpp Eclipse Projects
|
||||
=====================
|
||||
|
||||
For additional information on using Eclipse CDT see
|
||||
`the MDN page
|
||||
<https://developer.mozilla.org/en-US/docs/Eclipse_CDT>`_.
|
||||
|
||||
The build system contains alpha support for generating C++ Eclipse
|
||||
project files to aid with development.
|
||||
|
||||
Please report bugs to bugzilla and make them depend on bug 973770.
|
||||
|
||||
To generate a C++ Eclipse project files, you'll need to have a fully
|
||||
built tree::
|
||||
|
||||
mach build
|
||||
|
||||
Then, simply generate the Android Eclipse build backend::
|
||||
|
||||
mach build-backend -b CppEclipse
|
||||
|
||||
If all goes well, the path to the generated workspace should be
|
||||
printed (currently, ``$OBJDIR/android_eclipse``).
|
||||
|
||||
To use the generated Android Eclipse project files, you'll need to
|
||||
have a Eclipse CDT 8.3 (We plan to follow the latest Eclipse release)
|
||||
`Eclipse CDT plugin
|
||||
<https://www.eclipse.org/cdt/>`_
|
||||
installed. You can then import all the projects into Eclipse using
|
||||
*File > Import ... > General > Existing Projects into Workspace*
|
||||
-only- if you have not ran the background indexer.
|
||||
|
||||
Updating Project Files
|
||||
======================
|
||||
|
||||
As you pull and update the source tree, your C++ Eclipse files may
|
||||
fall out of sync with the build configuration. The tree should still
|
||||
build fine from within Eclipse, but source files may be missing and in
|
||||
rare circumstances Eclipse's index may not have the proper build
|
||||
configuration.
|
||||
|
||||
To account for this, you'll want to periodically regenerate the
|
||||
Android Eclipse project files. You can do this by running ``mach build
|
||||
&& mach build-backend -b CppEclipse`` from the
|
||||
command line.
|
||||
|
||||
Currently, regeneration rewrites the original project files. **If
|
||||
you've made any customizations to the projects, they will likely get
|
||||
overwritten.** We would like to improve this user experience in the
|
||||
future.
|
||||
|
||||
@@ -28,15 +28,6 @@ Important Concepts
|
||||
locales
|
||||
rust
|
||||
|
||||
integrated development environment (IDE)
|
||||
========================================
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
androideclipse
|
||||
cppeclipse
|
||||
visualstudio
|
||||
|
||||
mozbuild
|
||||
========
|
||||
|
||||
|
||||
@@ -17,84 +17,5 @@ like a re-packaging post-processing step.
|
||||
There are scripts in-tree in mozharness to orchestrate these re-packaging
|
||||
steps for `Desktop
|
||||
<https://dxr.mozilla.org/mozilla-central/source/testing/mozharness/scripts/desktop_l10n.py>`_
|
||||
and `Android
|
||||
<https://dxr.mozilla.org/mozilla-central/source/testing/mozharness/scripts/mobile_l10n.py>`_
|
||||
but they rely heavily on buildbot information so they are almost impossible to
|
||||
run locally.
|
||||
|
||||
The following instructions are extracted from the `Android script with hg hash
|
||||
494289c7
|
||||
<https://dxr.mozilla.org/mozilla-central/rev/494289c72ba3997183e7b5beaca3e0447ecaf96d/testing/mozharness/scripts/mobile_l10n.py>`_,
|
||||
and may need to be updated and slightly modified for Desktop.
|
||||
|
||||
Step by step instructions for Android
|
||||
-------------------------------------
|
||||
|
||||
This assumes that ``$AB_CD`` is the locale you want to repack with; I tested
|
||||
with "ar" and "en-GB".
|
||||
|
||||
.. warning:: l10n repacks do not work with artifact builds. Repackaging
|
||||
compiles no code so supporting ``--disable-compile-environment`` would not
|
||||
save much, if any, time.
|
||||
|
||||
#. You must have a built and packaged object directory, or a pre-built
|
||||
``en-US`` package.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
./mach build
|
||||
./mach package
|
||||
|
||||
#. Clone ``l10n-central/$AB_CD`` so that it is a sibling to your
|
||||
``mozilla-central`` directory.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ ls -al
|
||||
mozilla-central
|
||||
...
|
||||
$ mkdir -p l10n-central
|
||||
$ hg clone https://hg.mozilla.org/l10n-central/$AB_CD l10n-central/$AB_CD
|
||||
$ ls -al
|
||||
mozilla-central
|
||||
l10n-central/$AB_CD
|
||||
...
|
||||
|
||||
#. Copy your ``mozconfig`` to ``mozconfig.l10n`` and add the following.
|
||||
|
||||
::
|
||||
|
||||
ac_add_options --with-l10n-base=../../l10n-central
|
||||
ac_add_options --disable-tests
|
||||
mk_add_options MOZ_OBJDIR=./objdir-l10n
|
||||
|
||||
#. Configure and prepare the l10n object directory.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
MOZCONFIG=mozconfig.l10n ./mach configure
|
||||
MOZCONFIG=mozconfig.l10n ./mach build -C config export
|
||||
MOZCONFIG=mozconfig.l10n ./mach build buildid.h
|
||||
|
||||
#. Copy your built package and unpack it into the l10n object directory.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cp $OBJDIR/dist/fennec-*en-US*.apk ./objdir-l10n/dist
|
||||
MOZCONFIG=mozconfig.l10n ./mach build -C mobile/android/locales unpack
|
||||
|
||||
#. Run the ``compare-locales`` script to write locale-specific changes into
|
||||
``objdir-l10n/merged``.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
MOZCONFIG=mozconfig.l10n ./mach compare-locales --merge-dir objdir-l10n/merged $AB_CD
|
||||
|
||||
#. Finally, repackage using the locale-specific changes.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
MOZCONFIG=mozconfig.l10n LOCALE_MERGEDIR=`realpath objdir-l10n/merged` ./mach build -C mobile/android/locales installers-$AB_CD
|
||||
|
||||
(Note the absolute path for ``LOCALE_MERGEDIR``.) You should find a
|
||||
re-packaged build at ``objdir-l10n/dist/fennec-*$AB_CD*.apk``.
|
||||
+4
-19
@@ -62,8 +62,7 @@ bits
|
||||
buildapp
|
||||
The path to the XUL application being built.
|
||||
|
||||
For desktop Firefox, this is ``browser``. For Fennec, it's
|
||||
``mobile/android``. For B2G, it's ``b2g``.
|
||||
For desktop Firefox, this is ``browser``.
|
||||
|
||||
crashreporter
|
||||
Whether the crash reporter is enabled for this build.
|
||||
@@ -72,13 +71,6 @@ crashreporter
|
||||
|
||||
Always defined.
|
||||
|
||||
datareporting
|
||||
Whether data reporting (MOZ_DATA_REPORTING) is enabled for this build.
|
||||
|
||||
Values are ``true`` and ``false``.
|
||||
|
||||
Always defined.
|
||||
|
||||
debug
|
||||
Whether this is a debug build.
|
||||
|
||||
@@ -86,13 +78,6 @@ debug
|
||||
|
||||
Always defined.
|
||||
|
||||
healthreport
|
||||
Whether the Health Report feature is enabled.
|
||||
|
||||
Values are ``true`` and ``false``.
|
||||
|
||||
Always defined.
|
||||
|
||||
mozconfig
|
||||
The path of the :ref:`mozconfig file <mozconfig>` used to produce this build.
|
||||
|
||||
@@ -107,9 +92,9 @@ nightly_build
|
||||
|
||||
os
|
||||
The operating system the build is produced for. Values for tier-1
|
||||
supported platforms are ``linux``, ``win``, ``mac``, ``b2g``, and
|
||||
``android``. For other platforms, the value is the lowercase version
|
||||
of the ``OS_TARGET`` variable from ``config.status``.
|
||||
supported platforms are ``linux`` and ``win``. For other platforms,
|
||||
the value is the lowercase version of the ``OS_TARGET`` variable
|
||||
from ``config.status``.
|
||||
|
||||
Always defined.
|
||||
|
||||
|
||||
@@ -5,41 +5,44 @@ Supported Configurations
|
||||
========================
|
||||
|
||||
This page attempts to document supported build configurations.
|
||||
For more up-to-date information please go to http://developer.palemoon.org/
|
||||
|
||||
Windows
|
||||
=======
|
||||
|
||||
We support building on Windows XP and newer operating systems using
|
||||
Visual Studio 2010 and newer.
|
||||
We support building on Windows 7 and newer operating systems using
|
||||
Visual Studio 2015 U3.
|
||||
|
||||
The following are not fully supported by Mozilla (but may work):
|
||||
The following are not fully supported (but may work):
|
||||
|
||||
* Building without the latest *MozillaBuild* Windows development
|
||||
environment
|
||||
* Building with a *MozillaBuild* Windows development
|
||||
environment not mentioned on the developer documentation site.
|
||||
* Building with Mingw or any other non-Visual Studio toolchain.
|
||||
|
||||
OS X
|
||||
====
|
||||
|
||||
We support building on OS X 10.6 and newer with the OS X 10.6 SDK.
|
||||
(This section needs updating)
|
||||
We support building on OS X 10.8 and newer with the OS X 10.8 SDK.
|
||||
|
||||
The tree should build with the following OS X releases and SDK versions:
|
||||
|
||||
* 10.6 Snow Leopard
|
||||
* 10.7 Lion
|
||||
* 10.8 Mountain Lion
|
||||
* 10.9 Mavericks
|
||||
* 10.10 Yosemite
|
||||
* 10.11 El Capitan
|
||||
* 10.12 Sierra
|
||||
* 10.13 High Sierra
|
||||
* 10.14 Mojave
|
||||
* 10.15 Catalina
|
||||
* 11 Big Sur (Including Apple ARM SoC)
|
||||
|
||||
The tree requires building with Clang 3.3 and newer. This corresponds to
|
||||
version of 4.2 of Apple's Clang that ships with Xcode. This corresponds
|
||||
to Xcode 4.6 and newer. Xcode 4.6 only runs on OS X 10.7.4 and newer.
|
||||
So, OS X 10.6 users will need to install a non-Apple toolchain. Running
|
||||
``mach bootstrap`` should install an appropriate toolchain from Homebrew
|
||||
or MacPorts automatically.
|
||||
The tree requires building with Apple's Clang 4.2 that ships with Xcode.
|
||||
This corresponds to Xcode 4.6 and newer. Xcode 4.6 only runs on OS X 10.7.4
|
||||
and newer.
|
||||
|
||||
The tree should build with GCC 4.4 and newer on OS X. However, this
|
||||
The tree should build with GCC 7.1 and newer on OS X. However, this
|
||||
build configuration isn't as widely used (and differs from what Mozilla
|
||||
uses to produce OS X builds), so it's recommended to stick with Clang.
|
||||
uses to produce OS X builds).
|
||||
|
||||
Linux
|
||||
=====
|
||||
@@ -47,9 +50,6 @@ Linux
|
||||
Linux 2.6 and later kernels are supported.
|
||||
|
||||
Most distributions are supported as long as the proper package
|
||||
dependencies are in place. Running ``mach bootstrap`` should install
|
||||
packages for popular Linux distributions. ``configure`` will typically
|
||||
dependencies are in place. ``configure`` will typically
|
||||
detect missing dependencies and inform you how to disable features to
|
||||
work around unsatisfied dependencies.
|
||||
|
||||
Clang 3.3 or GCC 4.4 is required to build the tree.
|
||||
@@ -54,58 +54,3 @@ archive::
|
||||
$ ./mach python build/windows_toolchain.py create-zip vs2015u3
|
||||
|
||||
The produced archive will be the argument to ``create-zip`` + ``.zip``.
|
||||
|
||||
Firefox for Android with Gradle
|
||||
===============================
|
||||
|
||||
To build Firefox for Android with Gradle in automation, archives
|
||||
containing both the Gradle executable and a Maven repository
|
||||
comprising the exact build dependencies are produced and uploaded to
|
||||
an internal Mozilla server. The build automation will download,
|
||||
verify, and extract these archive before building. These archives
|
||||
provide a self-contained Gradle and Maven repository so that machines
|
||||
don't need to fetch additional Maven dependencies at build time.
|
||||
(Gradle and the downloaded Maven dependencies can be both
|
||||
redistributed publicly.)
|
||||
|
||||
Archiving the Gradle executable is straight-forward, but archiving a
|
||||
local Maven repository is not. Therefore a special Task Cluster
|
||||
Docker image and job exist for producing the required archives. The
|
||||
Docker image definition is rooted in
|
||||
``taskcluster/docker/android-gradle-build``. The Task Cluster job
|
||||
definition is in
|
||||
``testing/taskcluster/tasks/builds/android_api_15_gradle_dependencies.yml``.
|
||||
The job runs in a container based on the custom Docker image and
|
||||
spawns a Sonatype Nexus proxying Maven repository process in the
|
||||
background. The job builds Firefox for Android using Gradle and the
|
||||
in-tree Gradle configuration rooted at ``build.gradle``. The spawned
|
||||
proxying Maven repository downloads external dependencies and collects
|
||||
them. After the Gradle build completes, the job archives the Gradle
|
||||
version used to build, and the downloaded Maven repository, and
|
||||
exposes them as Task Cluster artifacts.
|
||||
|
||||
Here is `an example try job fetching these dependencies
|
||||
<https://treeherder.mozilla.org/#/jobs?repo=try&revision=75bc98935147&selectedJob=17793653>`_.
|
||||
The resulting task produced a `Gradle archive
|
||||
<https://queue.taskcluster.net/v1/task/CeYMgAP3Q-KF8h37nMhJjg/runs/0/artifacts/public%2Fbuild%2Fgradle.tar.xz>`_
|
||||
and a `Maven repository archive
|
||||
<https://queue.taskcluster.net/v1/task/CeYMgAP3Q-KF8h37nMhJjg/runs/0/artifacts/public%2Fbuild%2Fjcentral.tar.xz>`_.
|
||||
These archives were then uploaded (manually) to Mozilla automation
|
||||
using tooltool for consumption in Gradle builds.
|
||||
|
||||
To update the version of Gradle in the archive produced, update
|
||||
``gradle/wrapper/gradle-wrapper.properties``. Be sure to also update
|
||||
the SHA256 checksum to prevent poisoning the build machines!
|
||||
|
||||
To update the versions of Gradle dependencies used, update
|
||||
``dependencies`` sections in the in-tree Gradle configuration rooted
|
||||
at ``build.gradle``. Once you are confident your changes build
|
||||
locally, push a fresh try build with an invocation like::
|
||||
|
||||
$ hg push-to-try -m "try: -b o -p android-api-15-gradle-dependencies"
|
||||
|
||||
Then `upload your archives to tooltool
|
||||
<https://wiki.mozilla.org/ReleaseEngineering/Applications/Tooltool#How_To_Upload_To_Tooltool>`_,
|
||||
update the in-tree manifests in
|
||||
``mobile/android/config/tooltool-manifests``, and push a fresh try
|
||||
build.
|
||||
@@ -1,100 +0,0 @@
|
||||
.. _build_visualstudio:
|
||||
|
||||
======================
|
||||
Visual Studio Projects
|
||||
======================
|
||||
|
||||
The build system contains alpha support for generating Visual Studio
|
||||
project files to aid with development.
|
||||
|
||||
To generate Visual Studio project files, you'll need to have a configured tree::
|
||||
|
||||
mach configure
|
||||
|
||||
(If you have built recently, your tree is already configured.)
|
||||
|
||||
Then, simply generate the Visual Studio build backend::
|
||||
|
||||
mach build-backend -b VisualStudio
|
||||
|
||||
If all goes well, the path to the generated Solution (``.sln``) file should be
|
||||
printed. You should be able to open that solution with Visual Studio 2010 or
|
||||
newer.
|
||||
|
||||
Currently, output is hard-coded to the Visual Studio 2010 format. If you open
|
||||
the solution in a newer Visual Studio release, you will be prompted to upgrade
|
||||
projects. Simply click through the wizard to do that.
|
||||
|
||||
Structure of Solution
|
||||
=====================
|
||||
|
||||
The Visual Studio solution consists of hundreds of projects spanning thousands
|
||||
of files. To help with organization, the solution is divided into the following
|
||||
trees/folders:
|
||||
|
||||
Build Targets
|
||||
This folder contains common build targets. The *full* project is used to
|
||||
perform a full build. The *binaries* project is used to build just binaries.
|
||||
The *visual-studio* project can be built to regenerate the Visual Studio
|
||||
project files.
|
||||
|
||||
Performing the *clean* action on any of these targets will clean the
|
||||
*entire* build output.
|
||||
|
||||
Binaries
|
||||
This folder contains common binaries that can be executed from within
|
||||
Visual Studio. If you are building the Firefox desktop application,
|
||||
the *firefox* project will launch firefox.exe. You probably want one of
|
||||
these set to your startup project.
|
||||
|
||||
Libraries
|
||||
This folder contains entries for each static library that is produced as
|
||||
part of the build. These roughly correspond to each directory in the tree
|
||||
containing C/C++. e.g. code from ``dom/base`` will be contained in the
|
||||
``dom_base`` project.
|
||||
|
||||
These projects don't do anything when built. If you build a project here,
|
||||
the *binaries* build target project is built.
|
||||
|
||||
Updating Project Files
|
||||
======================
|
||||
|
||||
As you pull and update the source tree, your Visual Studio files may fall out
|
||||
of sync with the build configuration. The tree should still build fine from
|
||||
within Visual Studio. But source files may be missing and IntelliSense may not
|
||||
have the proper build configuration.
|
||||
|
||||
To account for this, you'll want to periodically regenerate the Visual Studio
|
||||
project files. You can do this within Visual Studio by building the
|
||||
``Build Targets :: visual-studio`` project or by running
|
||||
``mach build-backend -b VisualStudio`` from the command line.
|
||||
|
||||
Currently, regeneration rewrites the original project files. **If you've made
|
||||
any customizations to the solution or projects, they will likely get
|
||||
overwritten.** We would like to improve this user experience in the
|
||||
future.
|
||||
|
||||
Moving Project Files Around
|
||||
===========================
|
||||
|
||||
The produced Visual Studio solution and project files should be portable.
|
||||
If you want to move them to a non-default directory, they should continue
|
||||
to work from wherever they are. If they don't, please file a bug.
|
||||
|
||||
Invoking mach through Visual Studio
|
||||
===================================
|
||||
|
||||
It's possible to build the tree via Visual Studio. There is some light magic
|
||||
involved here.
|
||||
|
||||
Alongside the Visual Studio project files is a batch script named ``mach.bat``.
|
||||
This batch script sets the environment variables present in your *MozillaBuild*
|
||||
development environment at the time of Visual Studio project generation
|
||||
and invokes *mach* inside an msys shell with the arguments specified to the
|
||||
batch script. This script essentially allows you to invoke mach commands
|
||||
inside the MozillaBuild environment without having to load MozillaBuild.
|
||||
|
||||
While projects currently only utilize the ``mach build`` command, the batch
|
||||
script does not limit it's use: any mach command can be invoked. Developers
|
||||
may abuse this fact to add custom projects and commands that invoke other
|
||||
mach commands.
|
||||
+4
-39
@@ -3,7 +3,9 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
gyp_vars = {
|
||||
include('gyp_base.mozbuild')
|
||||
|
||||
gyp_vars.update({
|
||||
'lsan': 0,
|
||||
'asan': 0,
|
||||
'build_with_mozilla': 1,
|
||||
@@ -18,8 +20,6 @@ gyp_vars = {
|
||||
'clang_use_chrome_plugins': 0,
|
||||
'enable_protobuf': 0,
|
||||
'include_tests': 0,
|
||||
'enable_android_opensl': 1,
|
||||
'enable_android_opensl_output': 0,
|
||||
# use_system_lib* still seems to be in use in trunk/build
|
||||
'use_system_libjpeg': 0,
|
||||
'use_system_libvpx': 0,
|
||||
@@ -67,42 +67,7 @@ gyp_vars = {
|
||||
# linker to throw away uneeded bits.
|
||||
'include_isac': 1,
|
||||
'include_pcm16b': 1,
|
||||
}
|
||||
|
||||
os = CONFIG['OS_TARGET']
|
||||
|
||||
if os == 'WINNT':
|
||||
gyp_vars.update(
|
||||
MSVS_VERSION=CONFIG['_MSVS_VERSION'],
|
||||
MSVS_OS_BITS=64 if CONFIG['HAVE_64BIT_BUILD'] else 32,
|
||||
)
|
||||
elif os == 'Android':
|
||||
gyp_vars.update(
|
||||
gtest_target_type='executable',
|
||||
moz_webrtc_mediacodec=1,
|
||||
android_toolchain=CONFIG.get('ANDROID_TOOLCHAIN', ''),
|
||||
)
|
||||
|
||||
flavors = {
|
||||
'WINNT': 'win',
|
||||
'Android': 'android',
|
||||
'Linux': 'linux',
|
||||
'SunOS': 'solaris',
|
||||
'GNU/kFreeBSD': 'freebsd',
|
||||
'DragonFly': 'dragonfly',
|
||||
'FreeBSD': 'freebsd',
|
||||
'NetBSD': 'netbsd',
|
||||
'OpenBSD': 'openbsd',
|
||||
}
|
||||
gyp_vars['OS'] = flavors.get(os)
|
||||
|
||||
arches = {
|
||||
'x86_64': 'x64',
|
||||
'x86': 'ia32',
|
||||
'aarch64': 'arm64',
|
||||
}
|
||||
|
||||
gyp_vars['target_arch'] = arches.get(CONFIG['CPU_ARCH'], CONFIG['CPU_ARCH'])
|
||||
})
|
||||
|
||||
if CONFIG['ARM_ARCH']:
|
||||
if int(CONFIG['ARM_ARCH']) < 7:
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
gyp_vars = {}
|
||||
|
||||
os = CONFIG['OS_TARGET']
|
||||
|
||||
if os == 'WINNT':
|
||||
gyp_vars.update(
|
||||
MSVS_VERSION=CONFIG['_MSVS_VERSION'],
|
||||
MSVS_OS_BITS=64 if CONFIG['HAVE_64BIT_BUILD'] else 32,
|
||||
)
|
||||
|
||||
flavors = {
|
||||
'WINNT': 'win',
|
||||
'Linux': 'linux',
|
||||
'Darwin': 'mac',
|
||||
'SunOS': 'solaris',
|
||||
'GNU/kFreeBSD': 'freebsd',
|
||||
'DragonFly': 'dragonfly',
|
||||
'FreeBSD': 'freebsd',
|
||||
'NetBSD': 'netbsd',
|
||||
'OpenBSD': 'openbsd',
|
||||
}
|
||||
gyp_vars['OS'] = flavors.get(os)
|
||||
|
||||
arches = {
|
||||
'x86_64': 'x64',
|
||||
'x86': 'ia32',
|
||||
'aarch64': 'arm64',
|
||||
}
|
||||
|
||||
gyp_vars['host_arch'] = arches.get(CONFIG['HOST_CPU_ARCH'], CONFIG['HOST_CPU_ARCH'])
|
||||
gyp_vars['target_arch'] = arches.get(CONFIG['CPU_ARCH'], CONFIG['CPU_ARCH'])
|
||||
+14
-11
@@ -35,7 +35,6 @@ Press ENTER/RETURN to continue or CTRL+c to abort.
|
||||
# TODO Bug 794506 Integrate with the in-tree virtualenv configuration.
|
||||
SEARCH_PATHS = [
|
||||
'python/mach',
|
||||
'python/mozboot',
|
||||
'python/mozbuild',
|
||||
'python/mozlint',
|
||||
'python/mozversioncontrol',
|
||||
@@ -65,11 +64,6 @@ SEARCH_PATHS = [
|
||||
'other-licenses/ply',
|
||||
'taskcluster',
|
||||
'testing',
|
||||
'testing/firefox-ui/harness',
|
||||
'testing/marionette/client',
|
||||
'testing/marionette/harness',
|
||||
'testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py',
|
||||
'testing/marionette/puppeteer/firefox',
|
||||
'testing/mozbase/mozcrash',
|
||||
'testing/mozbase/mozdebug',
|
||||
'testing/mozbase/mozdevice',
|
||||
@@ -105,16 +99,12 @@ MACH_MODULES = [
|
||||
'python/mach/mach/commands/commandinfo.py',
|
||||
'python/mach/mach/commands/settings.py',
|
||||
'python/compare-locales/mach_commands.py',
|
||||
'python/mozboot/mozboot/mach_commands.py',
|
||||
'python/mozbuild/mozbuild/mach_commands.py',
|
||||
'python/mozbuild/mozbuild/backend/mach_commands.py',
|
||||
'python/mozbuild/mozbuild/compilation/codecomplete.py',
|
||||
'python/mozbuild/mozbuild/frontend/mach_commands.py',
|
||||
'services/common/tests/mach_commands.py',
|
||||
'taskcluster/mach_commands.py',
|
||||
'testing/firefox-ui/mach_commands.py',
|
||||
'testing/mach_commands.py',
|
||||
'testing/marionette/mach_commands.py',
|
||||
'testing/mochitest/mach_commands.py',
|
||||
'testing/mozharness/mach_commands.py',
|
||||
'testing/talos/mach_commands.py',
|
||||
@@ -198,7 +188,20 @@ def bootstrap(topsrcdir, mozilla_dir=None):
|
||||
# like surprises.
|
||||
sys.path[0:0] = [os.path.join(mozilla_dir, path) for path in SEARCH_PATHS]
|
||||
import mach.main
|
||||
from mozboot.util import get_state_dir
|
||||
|
||||
def get_state_dir():
|
||||
"""Obtain path to a directory to hold state.
|
||||
|
||||
Returns a tuple of the path and a bool indicating whether the
|
||||
value came from an environment variable.
|
||||
"""
|
||||
state_user_dir = os.path.expanduser('~/.mozbuild')
|
||||
state_env_dir = os.environ.get('MOZBUILD_STATE_PATH')
|
||||
|
||||
if state_env_dir:
|
||||
return state_env_dir, True
|
||||
else:
|
||||
return state_user_dir, False
|
||||
|
||||
def telemetry_handler(context, data):
|
||||
# We have not opted-in to telemetry
|
||||
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if ! git remote -v | grep origin | grep -q cctools-port; then
|
||||
echo "must be in a cctools-port checkout"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir build-cctools
|
||||
cd build-cctools
|
||||
|
||||
CFLAGS='-mcpu=generic -mtune=generic' MACOSX_DEPLOYMENT_TARGET=10.7 ../cctools/configure --target=x86_64-apple-darwin11
|
||||
env MACOSX_DEPLOYMENT_TARGET=10.7 make -s -j4
|
||||
|
||||
if test ! -e ld64/src/ld/ld; then
|
||||
echo "ld did not get built"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
gtar jcf cctools.tar.bz2 ld64/src/ld/ld --transform 's#ld64/src/ld#cctools/bin#'
|
||||
|
||||
cd ../
|
||||
|
||||
echo "build from $(git show --pretty=format:%H -s HEAD) complete!"
|
||||
echo "upload the build-cctools/cctools.tar.bz2 file to tooltool"
|
||||
@@ -0,0 +1,47 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MOZ_AUTOMATION_L10N_CHECK=0
|
||||
|
||||
if [ "x$IS_NIGHTLY" = "xyes" ]; then
|
||||
# Some nightlies (eg: Mulet) don't want these set.
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
|
||||
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
|
||||
fi
|
||||
. "$topsrcdir/build/mozconfig.common"
|
||||
|
||||
# ld needs libLTO.so from llvm
|
||||
mk_add_options "export LD_LIBRARY_PATH=$topsrcdir/clang/lib"
|
||||
|
||||
CROSS_CCTOOLS_PATH=$topsrcdir/cctools
|
||||
CROSS_SYSROOT=$topsrcdir/MacOSX10.7.sdk
|
||||
CROSS_PRIVATE_FRAMEWORKS=$CROSS_SYSROOT/System/Library/PrivateFrameworks
|
||||
FLAGS="-target x86_64-apple-darwin10 -mlinker-version=136 -B $CROSS_CCTOOLS_PATH/bin -isysroot $CROSS_SYSROOT"
|
||||
|
||||
export CC="$topsrcdir/clang/bin/clang $FLAGS"
|
||||
export CXX="$topsrcdir/clang/bin/clang++ $FLAGS"
|
||||
export CPP="$topsrcdir/clang/bin/clang $FLAGS -E"
|
||||
export LLVMCONFIG=$topsrcdir/clang/bin/llvm-config
|
||||
export LDFLAGS="-Wl,-syslibroot,$CROSS_SYSROOT -Wl,-dead_strip"
|
||||
export TOOLCHAIN_PREFIX=$CROSS_CCTOOLS_PATH/bin/x86_64-apple-darwin10-
|
||||
export DSYMUTIL=$topsrcdir/clang/bin/llvm-dsymutil
|
||||
export GENISOIMAGE=$topsrcdir/genisoimage/genisoimage
|
||||
export DMG_TOOL=$topsrcdir/dmg/dmg
|
||||
|
||||
export HOST_CC="$topsrcdir/clang/bin/clang"
|
||||
export HOST_CXX="$topsrcdir/clang/bin/clang++"
|
||||
export HOST_CPP="$topsrcdir/clang/bin/clang -E"
|
||||
export HOST_CFLAGS="-g"
|
||||
export HOST_CXXFLAGS="-g"
|
||||
export HOST_LDFLAGS="-g"
|
||||
|
||||
ac_add_options --target=x86_64-apple-darwin
|
||||
ac_add_options --with-macos-private-frameworks=$CROSS_PRIVATE_FRAMEWORKS
|
||||
|
||||
# Enable static analysis checks by default on OSX cross builds.
|
||||
ac_add_options --enable-clang-plugin
|
||||
|
||||
. "$topsrcdir/build/mozconfig.cache"
|
||||
|
||||
export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=/builds/crash-stats-api.token
|
||||
@@ -0,0 +1,46 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
if [ "x$IS_NIGHTLY" = "xyes" ]; then
|
||||
# Some nightlies (eg: Mulet) don't want these set.
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
|
||||
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
|
||||
fi
|
||||
. "$topsrcdir/build/mozconfig.common"
|
||||
|
||||
if [ -d "$topsrcdir/clang" ]; then
|
||||
# mozilla-central based build
|
||||
export CC=$topsrcdir/clang/bin/clang
|
||||
export CXX=$topsrcdir/clang/bin/clang++
|
||||
export LLVMCONFIG=$topsrcdir/clang/bin/llvm-config
|
||||
export DSYMUTIL=$topsrcdir/clang/bin/llvm-dsymutil
|
||||
# Use an updated linker.
|
||||
ldflags="-B$topsrcdir/cctools/bin"
|
||||
elif [ -d "$topsrcdir/../clang" ]; then
|
||||
# comm-central based build
|
||||
export CC=$topsrcdir/../clang/bin/clang
|
||||
export CXX=$topsrcdir/../clang/bin/clang++
|
||||
export LLVMCONFIG=$topsrcdir/../clang/bin/llvm-config
|
||||
export DSYMUTIL=$topsrcdir/../clang/bin/llvm-dsymutil
|
||||
# Use an updated linker.
|
||||
ldflags="-B$topsrcdir/../cctools/bin"
|
||||
fi
|
||||
|
||||
# Ensure the updated linker doesn't generate things our older build tools
|
||||
# don't understand.
|
||||
ldflags="$ldflags -Wl,-no_data_in_code_info"
|
||||
export LDFLAGS="$ldflags"
|
||||
|
||||
# If not set use the system default clang
|
||||
if [ -z "$CC" ]; then
|
||||
export CC=clang
|
||||
fi
|
||||
|
||||
# If not set use the system default clang++
|
||||
if [ -z "$CXX" ]; then
|
||||
export CXX=clang++
|
||||
fi
|
||||
|
||||
export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=/builds/crash-stats-api.token
|
||||
@@ -0,0 +1,5 @@
|
||||
if test `uname -s` = Linux; then
|
||||
. $topsrcdir/build/macosx/cross-mozconfig.common
|
||||
else
|
||||
. $topsrcdir/build/macosx/local-mozconfig.common
|
||||
fi
|
||||
@@ -0,0 +1,20 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
uid_t realuser = getuid();
|
||||
char uidstring[20];
|
||||
snprintf(uidstring, 19, "%i", realuser);
|
||||
uidstring[19] = '\0';
|
||||
|
||||
return execl("/usr/sbin/chown",
|
||||
"/usr/sbin/chown", "-R", "-h", uidstring, argv[1], (char*) 0);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
return execl("/usr/sbin/chown",
|
||||
"/usr/sbin/chown", "-R", "-h", "root:admin", argv[1], (char*) 0);
|
||||
}
|
||||
Loaded 100 of 8707 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user