Compare commits
382
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9edf1b7bea | ||
|
|
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 | ||
|
|
3163b3af18 | ||
|
|
1fb9257ed8 | ||
|
|
72d0b86709 | ||
|
|
2215d8467e | ||
|
|
a0461e3775 | ||
|
|
4490f61f58 | ||
|
|
1fe9c19305 | ||
|
|
5afcb4a092 | ||
|
|
8689ac6304 | ||
|
|
014fdd0521 | ||
|
|
2c626f6046 | ||
|
|
4dac05e0e0 | ||
|
|
cfdfbcf059 | ||
|
|
6f7dd6fd98 | ||
|
|
22a75217e1 | ||
|
|
a970411caf | ||
|
|
e8be661944 | ||
|
|
5ab5ce9c4f | ||
|
|
205e69e2bb | ||
|
|
c337c1496b | ||
|
|
7f6f1c664d | ||
|
|
9acd98298c | ||
|
|
ce71c0fe3f | ||
|
|
42cf1ad419 | ||
|
|
6272d48e86 | ||
|
|
27e7b312a5 | ||
|
|
0a0830ba8b | ||
|
|
c921ad59d5 | ||
|
|
349346d0b7 | ||
|
|
e983389355 | ||
|
|
2b7197465d | ||
|
|
5c583e905e | ||
|
|
1ee35eafa0 | ||
|
|
b5ece9f771 | ||
|
|
08da125d9c | ||
|
|
ca35efb84e | ||
|
|
e7e63565ee | ||
|
|
6f707bde95 | ||
|
|
aa0fd3d68c | ||
|
|
1bf0734a72 | ||
|
|
b1eb04d3f0 | ||
|
|
616b39413d | ||
|
|
cd1f724135 | ||
|
|
3d671e4275 | ||
|
|
56da7e2747 | ||
|
|
0dd3424f77 | ||
|
|
4e31a42b28 |
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
|
||||
Clobber for NSS update
|
||||
@@ -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;
|
||||
|
||||
@@ -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*
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
|
||||
|
||||
@@ -21,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',
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -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
|
||||
=============== ==================================== =================
|
||||
@@ -18,14 +18,14 @@ built tree::
|
||||
|
||||
mach build
|
||||
|
||||
Then, simply generate the Android Eclipse build backend::
|
||||
Then, simply generate the 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``).
|
||||
printed.
|
||||
|
||||
To use the generated Android Eclipse project files, you'll need to
|
||||
To use the generated 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/>`_
|
||||
@@ -43,7 +43,7 @@ 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
|
||||
Eclipse project files. You can do this by running ``mach build
|
||||
&& mach build-backend -b CppEclipse`` from the
|
||||
command line.
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ integrated development environment (IDE)
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
androideclipse
|
||||
cppeclipse
|
||||
visualstudio
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
+4
-40
@@ -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,43 +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',
|
||||
'Darwin': 'mac' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' else 'ios',
|
||||
'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' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' else 'ios',
|
||||
'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
-10
@@ -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,13 @@ 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 +189,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);
|
||||
}
|
||||
@@ -2,5 +2,13 @@
|
||||
* 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/. */
|
||||
|
||||
pref("toolkit.defaultChromeURI", "chrome://simple/content/simple.xul");
|
||||
pref("general.useragent.extra.simple", "SimpleApp/0.1");
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# 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/.
|
||||
|
||||
# i386/x86-64 Universal Build mozconfig
|
||||
|
||||
# As used here, arguments in $MOZ_BUILD_PROJECTS are suitable as arguments
|
||||
# to gcc's -arch parameter.
|
||||
mk_add_options MOZ_BUILD_PROJECTS="x86_64 i386"
|
||||
|
||||
. $topsrcdir/build/macosx/universal/mozconfig.common
|
||||
@@ -0,0 +1,55 @@
|
||||
# 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/.
|
||||
|
||||
mk_add_options MOZ_UNIFY_BDATE=1
|
||||
|
||||
DARWIN_VERSION=10
|
||||
ac_add_app_options i386 --target=i386-apple-darwin$DARWIN_VERSION
|
||||
ac_add_app_options x86_64 --target=x86_64-apple-darwin$DARWIN_VERSION
|
||||
ac_add_app_options i386 --with-unify-dist=../x86_64/dist
|
||||
ac_add_app_options x86_64 --with-unify-dist=../i386/dist
|
||||
|
||||
if ! test `uname -s` = Linux; then
|
||||
# Cross-universal builds already do the equivalent of this by setting -isysroot directly
|
||||
ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.7.sdk
|
||||
fi
|
||||
|
||||
. $topsrcdir/build/macosx/mozconfig.common
|
||||
|
||||
# $MOZ_BUILD_APP is only defined when sourced by configure. That's not a
|
||||
# problem, because the variables it affects only need to be set for
|
||||
# configure.
|
||||
if test -n "$MOZ_BUILD_APP" ; then
|
||||
if test "$MOZ_BUILD_APP" = "i386" -o "$MOZ_BUILD_APP" = "x86_64"; then
|
||||
TARGET_CPU=$MOZ_BUILD_APP
|
||||
|
||||
# $HOST_CXX is presently unused. $HOST_CC will only be used during a cross
|
||||
# compile.
|
||||
HOST_CC=$CC
|
||||
HOST_CXX=$CXX
|
||||
|
||||
NATIVE_CPU=`$topsrcdir/build/autoconf/config.guess | cut -f1 -d-`
|
||||
|
||||
# It's not strictly necessary to specify -arch during native builds, but it
|
||||
# makes the merged about:buildconfig easier to follow, and it reduces
|
||||
# conditionalized differences between builds.
|
||||
CC="$CC -arch $TARGET_CPU"
|
||||
CXX="$CXX -arch $TARGET_CPU"
|
||||
|
||||
# These must be set for cross builds, and don't hurt straight builds.
|
||||
RANLIB="${TOOLCHAIN_PREFIX}ranlib"
|
||||
AR="${TOOLCHAIN_PREFIX}ar"
|
||||
AS=$CC
|
||||
LD=ld
|
||||
STRIP="${TOOLCHAIN_PREFIX}strip"
|
||||
OTOOL="${TOOLCHAIN_PREFIX}otool"
|
||||
|
||||
# Each per-CPU build should be entirely oblivious to the fact that a
|
||||
# universal binary will be produced. The exception is packager.mk, which
|
||||
# needs to know to look for universal bits when building the .dmg.
|
||||
UNIVERSAL_BINARY=1
|
||||
|
||||
export CC CXX HOST_CC HOST_CXX RANLIB AR AS LD STRIP OTOOL
|
||||
fi
|
||||
fi
|
||||
Executable
+1525
File diff suppressed because it is too large.
Load diff
@@ -1,451 +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/.
|
||||
|
||||
import datetime
|
||||
import mozcrash
|
||||
import threading
|
||||
import os
|
||||
import posixpath
|
||||
import Queue
|
||||
import re
|
||||
import shutil
|
||||
import signal
|
||||
import tempfile
|
||||
import time
|
||||
import traceback
|
||||
import zipfile
|
||||
|
||||
from automation import Automation
|
||||
from mozlog import get_default_logger
|
||||
from mozprocess import ProcessHandlerMixin
|
||||
|
||||
|
||||
class StdOutProc(ProcessHandlerMixin):
|
||||
"""Process handler for b2g which puts all output in a Queue.
|
||||
"""
|
||||
|
||||
def __init__(self, cmd, queue, **kwargs):
|
||||
self.queue = queue
|
||||
kwargs.setdefault('processOutputLine', []).append(self.handle_output)
|
||||
ProcessHandlerMixin.__init__(self, cmd, **kwargs)
|
||||
|
||||
def handle_output(self, line):
|
||||
self.queue.put_nowait(line)
|
||||
|
||||
|
||||
class B2GRemoteAutomation(Automation):
|
||||
_devicemanager = None
|
||||
|
||||
def __init__(self, deviceManager, appName='', remoteLog=None,
|
||||
marionette=None):
|
||||
self._devicemanager = deviceManager
|
||||
self._appName = appName
|
||||
self._remoteProfile = None
|
||||
self._remoteLog = remoteLog
|
||||
self.marionette = marionette
|
||||
self._is_emulator = False
|
||||
self.test_script = None
|
||||
self.test_script_args = None
|
||||
|
||||
# Default our product to b2g
|
||||
self._product = "b2g"
|
||||
self.lastTestSeen = "b2gautomation.py"
|
||||
# Default log finish to mochitest standard
|
||||
self.logFinish = 'INFO SimpleTest FINISHED'
|
||||
Automation.__init__(self)
|
||||
|
||||
def setEmulator(self, is_emulator):
|
||||
self._is_emulator = is_emulator
|
||||
|
||||
def setDeviceManager(self, deviceManager):
|
||||
self._devicemanager = deviceManager
|
||||
|
||||
def setAppName(self, appName):
|
||||
self._appName = appName
|
||||
|
||||
def setRemoteProfile(self, remoteProfile):
|
||||
self._remoteProfile = remoteProfile
|
||||
|
||||
def setProduct(self, product):
|
||||
self._product = product
|
||||
|
||||
def setRemoteLog(self, logfile):
|
||||
self._remoteLog = logfile
|
||||
|
||||
def getExtensionIDFromRDF(self, rdfSource):
|
||||
"""
|
||||
Retrieves the extension id from an install.rdf file (or string).
|
||||
"""
|
||||
from xml.dom.minidom import parse, parseString, Node
|
||||
|
||||
if isinstance(rdfSource, file):
|
||||
document = parse(rdfSource)
|
||||
else:
|
||||
document = parseString(rdfSource)
|
||||
|
||||
# Find the <em:id> element. There can be multiple <em:id> tags
|
||||
# within <em:targetApplication> tags, so we have to check this way.
|
||||
for rdfChild in document.documentElement.childNodes:
|
||||
if rdfChild.nodeType == Node.ELEMENT_NODE and rdfChild.tagName == "Description":
|
||||
for descChild in rdfChild.childNodes:
|
||||
if descChild.nodeType == Node.ELEMENT_NODE and descChild.tagName == "em:id":
|
||||
return descChild.childNodes[0].data
|
||||
return None
|
||||
|
||||
def installExtension(self, extensionSource, profileDir, extensionID=None):
|
||||
# Bug 827504 - installing special-powers extension separately causes problems in B2G
|
||||
if extensionID != "special-powers@mozilla.org":
|
||||
if not os.path.isdir(profileDir):
|
||||
self.log.info("INFO | automation.py | Cannot install extension, invalid profileDir at: %s", profileDir)
|
||||
return
|
||||
|
||||
installRDFFilename = "install.rdf"
|
||||
|
||||
extensionsRootDir = os.path.join(profileDir, "extensions", "staged")
|
||||
if not os.path.isdir(extensionsRootDir):
|
||||
os.makedirs(extensionsRootDir)
|
||||
|
||||
if os.path.isfile(extensionSource):
|
||||
reader = zipfile.ZipFile(extensionSource, "r")
|
||||
|
||||
for filename in reader.namelist():
|
||||
# Sanity check the zip file.
|
||||
if os.path.isabs(filename):
|
||||
self.log.info("INFO | automation.py | Cannot install extension, bad files in xpi")
|
||||
return
|
||||
|
||||
# We may need to dig the extensionID out of the zip file...
|
||||
if extensionID is None and filename == installRDFFilename:
|
||||
extensionID = self.getExtensionIDFromRDF(reader.read(filename))
|
||||
|
||||
# We must know the extensionID now.
|
||||
if extensionID is None:
|
||||
self.log.info("INFO | automation.py | Cannot install extension, missing extensionID")
|
||||
return
|
||||
|
||||
# Make the extension directory.
|
||||
extensionDir = os.path.join(extensionsRootDir, extensionID)
|
||||
os.mkdir(extensionDir)
|
||||
|
||||
# Extract all files.
|
||||
reader.extractall(extensionDir)
|
||||
|
||||
elif os.path.isdir(extensionSource):
|
||||
if extensionID is None:
|
||||
filename = os.path.join(extensionSource, installRDFFilename)
|
||||
if os.path.isfile(filename):
|
||||
with open(filename, "r") as installRDF:
|
||||
extensionID = self.getExtensionIDFromRDF(installRDF)
|
||||
|
||||
if extensionID is None:
|
||||
self.log.info("INFO | automation.py | Cannot install extension, missing extensionID")
|
||||
return
|
||||
|
||||
# Copy extension tree into its own directory.
|
||||
# "destination directory must not already exist".
|
||||
shutil.copytree(extensionSource, os.path.join(extensionsRootDir, extensionID))
|
||||
|
||||
else:
|
||||
self.log.info("INFO | automation.py | Cannot install extension, invalid extensionSource at: %s", extensionSource)
|
||||
|
||||
# Set up what we need for the remote environment
|
||||
def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False):
|
||||
# Because we are running remote, we don't want to mimic the local env
|
||||
# so no copying of os.environ
|
||||
if env is None:
|
||||
env = {}
|
||||
|
||||
# We always hide the results table in B2G; it's much slower if we don't.
|
||||
env['MOZ_HIDE_RESULTS_TABLE'] = '1'
|
||||
return env
|
||||
|
||||
def waitForNet(self):
|
||||
active = False
|
||||
time_out = 0
|
||||
while not active and time_out < 40:
|
||||
data = self._devicemanager._runCmd(['shell', '/system/bin/netcfg']).stdout.readlines()
|
||||
data.pop(0)
|
||||
for line in data:
|
||||
if (re.search(r'UP\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3}', line)):
|
||||
active = True
|
||||
break
|
||||
time_out += 1
|
||||
time.sleep(1)
|
||||
return active
|
||||
|
||||
def checkForCrashes(self, directory, symbolsPath):
|
||||
crashed = False
|
||||
remote_dump_dir = self._remoteProfile + '/minidumps'
|
||||
print "checking for crashes in '%s'" % remote_dump_dir
|
||||
if self._devicemanager.dirExists(remote_dump_dir):
|
||||
local_dump_dir = tempfile.mkdtemp()
|
||||
self._devicemanager.getDirectory(remote_dump_dir, local_dump_dir)
|
||||
try:
|
||||
logger = get_default_logger()
|
||||
if logger is not None:
|
||||
crashed = mozcrash.log_crashes(logger, local_dump_dir, symbolsPath, test=self.lastTestSeen)
|
||||
else:
|
||||
crashed = mozcrash.check_for_crashes(local_dump_dir, symbolsPath, test_name=self.lastTestSeen)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
shutil.rmtree(local_dump_dir)
|
||||
self._devicemanager.removeDir(remote_dump_dir)
|
||||
return crashed
|
||||
|
||||
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
|
||||
# if remote profile is specified, use that instead
|
||||
if (self._remoteProfile):
|
||||
profileDir = self._remoteProfile
|
||||
|
||||
cmd, args = Automation.buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs)
|
||||
|
||||
return app, args
|
||||
|
||||
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime,
|
||||
debuggerInfo, symbolsPath, outputHandler=None):
|
||||
""" Wait for tests to finish (as evidenced by a signature string
|
||||
in logcat), or for a given amount of time to elapse with no
|
||||
output.
|
||||
"""
|
||||
timeout = timeout or 120
|
||||
while True:
|
||||
lines = proc.getStdoutLines(timeout)
|
||||
if lines:
|
||||
currentlog = '\n'.join(lines)
|
||||
|
||||
if outputHandler:
|
||||
for line in lines:
|
||||
outputHandler(line)
|
||||
else:
|
||||
print(currentlog)
|
||||
|
||||
# Match the test filepath from the last TEST-START line found in the new
|
||||
# log content. These lines are in the form:
|
||||
# ... INFO TEST-START | /filepath/we/wish/to/capture.html\n
|
||||
testStartFilenames = re.findall(r"TEST-START \| ([^\s]*)", currentlog)
|
||||
if testStartFilenames:
|
||||
self.lastTestSeen = testStartFilenames[-1]
|
||||
if (outputHandler and outputHandler.suite_finished) or (
|
||||
hasattr(self, 'logFinish') and self.logFinish in currentlog):
|
||||
return 0
|
||||
else:
|
||||
self.log.info("TEST-UNEXPECTED-FAIL | %s | application timed "
|
||||
"out after %d seconds with no output",
|
||||
self.lastTestSeen, int(timeout))
|
||||
self._devicemanager.killProcess('/system/b2g/b2g', sig=signal.SIGABRT)
|
||||
|
||||
timeout = 10 # seconds
|
||||
starttime = datetime.datetime.utcnow()
|
||||
while datetime.datetime.utcnow() - starttime < datetime.timedelta(seconds=timeout):
|
||||
if not self._devicemanager.processExist('/system/b2g/b2g'):
|
||||
break
|
||||
time.sleep(1)
|
||||
else:
|
||||
print "timed out after %d seconds waiting for b2g process to exit" % timeout
|
||||
return 1
|
||||
|
||||
self.checkForCrashes(None, symbolsPath)
|
||||
return 1
|
||||
|
||||
def getDeviceStatus(self, serial=None):
|
||||
# Get the current status of the device. If we know the device
|
||||
# serial number, we look for that, otherwise we use the (presumably
|
||||
# only) device shown in 'adb devices'.
|
||||
serial = serial or self._devicemanager._deviceSerial
|
||||
status = 'unknown'
|
||||
|
||||
for line in self._devicemanager._runCmd(['devices']).stdout.readlines():
|
||||
result = re.match('(.*?)\t(.*)', line)
|
||||
if result:
|
||||
thisSerial = result.group(1)
|
||||
if not serial or thisSerial == serial:
|
||||
serial = thisSerial
|
||||
status = result.group(2)
|
||||
|
||||
return (serial, status)
|
||||
|
||||
def restartB2G(self):
|
||||
# TODO hangs in subprocess.Popen without this delay
|
||||
time.sleep(5)
|
||||
self._devicemanager._checkCmd(['shell', 'stop', 'b2g'])
|
||||
# Wait for a bit to make sure B2G has completely shut down.
|
||||
time.sleep(10)
|
||||
self._devicemanager._checkCmd(['shell', 'start', 'b2g'])
|
||||
if self._is_emulator:
|
||||
self.marionette.emulator.wait_for_port(self.marionette.port)
|
||||
|
||||
def rebootDevice(self):
|
||||
# find device's current status and serial number
|
||||
serial, status = self.getDeviceStatus()
|
||||
|
||||
# reboot!
|
||||
self._devicemanager._runCmd(['shell', '/system/bin/reboot'])
|
||||
|
||||
# The above command can return while adb still thinks the device is
|
||||
# connected, so wait a little bit for it to disconnect from adb.
|
||||
time.sleep(10)
|
||||
|
||||
# wait for device to come back to previous status
|
||||
print 'waiting for device to come back online after reboot'
|
||||
start = time.time()
|
||||
rserial, rstatus = self.getDeviceStatus(serial)
|
||||
while rstatus != 'device':
|
||||
if time.time() - start > 120:
|
||||
# device hasn't come back online in 2 minutes, something's wrong
|
||||
raise Exception("Device %s (status: %s) not back online after reboot" % (serial, rstatus))
|
||||
time.sleep(5)
|
||||
rserial, rstatus = self.getDeviceStatus(serial)
|
||||
print 'device:', serial, 'status:', rstatus
|
||||
|
||||
def Process(self, cmd, stdout=None, stderr=None, env=None, cwd=None):
|
||||
# On a desktop or fennec run, the Process method invokes a gecko
|
||||
# process in which to the tests. For B2G, we simply
|
||||
# reboot the device (which was configured with a test profile
|
||||
# already), wait for B2G to start up, and then navigate to the
|
||||
# test url using Marionette. There doesn't seem to be any way
|
||||
# to pass env variables into the B2G process, but this doesn't
|
||||
# seem to matter.
|
||||
|
||||
# reboot device so it starts up with the mochitest profile
|
||||
# XXX: We could potentially use 'stop b2g' + 'start b2g' to achieve
|
||||
# a similar effect; will see which is more stable while attempting
|
||||
# to bring up the continuous integration.
|
||||
if not self._is_emulator:
|
||||
self.rebootDevice()
|
||||
time.sleep(5)
|
||||
#wait for wlan to come up
|
||||
if not self.waitForNet():
|
||||
raise Exception("network did not come up, please configure the network" +
|
||||
" prior to running before running the automation framework")
|
||||
|
||||
# stop b2g
|
||||
self._devicemanager._runCmd(['shell', 'stop', 'b2g'])
|
||||
time.sleep(5)
|
||||
|
||||
# For some reason user.js in the profile doesn't get picked up.
|
||||
# Manually copy it over to prefs.js. See bug 1009730 for more details.
|
||||
self._devicemanager.moveTree(posixpath.join(self._remoteProfile, 'user.js'),
|
||||
posixpath.join(self._remoteProfile, 'prefs.js'))
|
||||
|
||||
# relaunch b2g inside b2g instance
|
||||
instance = self.B2GInstance(self._devicemanager, env=env)
|
||||
|
||||
time.sleep(5)
|
||||
|
||||
# Set up port forwarding again for Marionette, since any that
|
||||
# existed previously got wiped out by the reboot.
|
||||
if not self._is_emulator:
|
||||
self._devicemanager._checkCmd(['forward',
|
||||
'tcp:%s' % self.marionette.port,
|
||||
'tcp:%s' % self.marionette.port])
|
||||
|
||||
if self._is_emulator:
|
||||
self.marionette.emulator.wait_for_port(self.marionette.port)
|
||||
else:
|
||||
time.sleep(5)
|
||||
|
||||
# start a marionette session
|
||||
session = self.marionette.start_session()
|
||||
if 'b2g' not in session:
|
||||
raise Exception("bad session value %s returned by start_session" % session)
|
||||
|
||||
with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
|
||||
self.marionette.execute_script("""
|
||||
let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Services.prefs.setBoolPref(SECURITY_PREF, true);
|
||||
|
||||
if (!testUtils.hasOwnProperty("specialPowersObserver")) {
|
||||
let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Components.interfaces.mozIJSSubScriptLoader);
|
||||
loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm",
|
||||
testUtils);
|
||||
testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
|
||||
testUtils.specialPowersObserver.init();
|
||||
}
|
||||
""")
|
||||
|
||||
# run the script that starts the tests
|
||||
if self.test_script:
|
||||
if os.path.isfile(self.test_script):
|
||||
script = open(self.test_script, 'r')
|
||||
self.marionette.execute_script(script.read(), script_args=self.test_script_args)
|
||||
script.close()
|
||||
elif isinstance(self.test_script, basestring):
|
||||
self.marionette.execute_script(self.test_script, script_args=self.test_script_args)
|
||||
else:
|
||||
# assumes the tests are started on startup automatically
|
||||
pass
|
||||
|
||||
return instance
|
||||
|
||||
# be careful here as this inner class doesn't have access to outer class members
|
||||
class B2GInstance(object):
|
||||
"""Represents a B2G instance running on a device, and exposes
|
||||
some process-like methods/properties that are expected by the
|
||||
automation.
|
||||
"""
|
||||
|
||||
def __init__(self, dm, env=None):
|
||||
self.dm = dm
|
||||
self.env = env or {}
|
||||
self.stdout_proc = None
|
||||
self.queue = Queue.Queue()
|
||||
|
||||
# Launch b2g in a separate thread, and dump all output lines
|
||||
# into a queue. The lines in this queue are
|
||||
# retrieved and returned by accessing the stdout property of
|
||||
# this class.
|
||||
cmd = [self.dm._adbPath]
|
||||
if self.dm._deviceSerial:
|
||||
cmd.extend(['-s', self.dm._deviceSerial])
|
||||
cmd.append('shell')
|
||||
for k, v in self.env.iteritems():
|
||||
cmd.append("%s=%s" % (k, v))
|
||||
cmd.append('/system/bin/b2g.sh')
|
||||
proc = threading.Thread(target=self._save_stdout_proc, args=(cmd, self.queue))
|
||||
proc.daemon = True
|
||||
proc.start()
|
||||
|
||||
def _save_stdout_proc(self, cmd, queue):
|
||||
self.stdout_proc = StdOutProc(cmd, queue)
|
||||
self.stdout_proc.run()
|
||||
if hasattr(self.stdout_proc, 'processOutput'):
|
||||
self.stdout_proc.processOutput()
|
||||
self.stdout_proc.wait()
|
||||
self.stdout_proc = None
|
||||
|
||||
@property
|
||||
def pid(self):
|
||||
# a dummy value to make the automation happy
|
||||
return 0
|
||||
|
||||
def getStdoutLines(self, timeout):
|
||||
# Return any lines in the queue used by the
|
||||
# b2g process handler.
|
||||
lines = []
|
||||
# get all of the lines that are currently available
|
||||
while True:
|
||||
try:
|
||||
lines.append(self.queue.get_nowait())
|
||||
except Queue.Empty:
|
||||
break
|
||||
|
||||
# wait 'timeout' for any additional lines
|
||||
if not lines:
|
||||
try:
|
||||
lines.append(self.queue.get(True, timeout))
|
||||
except Queue.Empty:
|
||||
pass
|
||||
return lines
|
||||
|
||||
def wait(self, timeout=None):
|
||||
# this should never happen
|
||||
raise Exception("'wait' called on B2GInstance")
|
||||
|
||||
def kill(self):
|
||||
# this should never happen
|
||||
raise Exception("'kill' called on B2GInstance")
|
||||
|
||||
@@ -1,401 +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/.
|
||||
|
||||
import datetime
|
||||
import glob
|
||||
import time
|
||||
import re
|
||||
import os
|
||||
import posixpath
|
||||
import tempfile
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from automation import Automation
|
||||
from mozdevice import DMError, DeviceManager
|
||||
from mozlog import get_default_logger
|
||||
import mozcrash
|
||||
|
||||
# signatures for logcat messages that we don't care about much
|
||||
fennecLogcatFilters = [ "The character encoding of the HTML document was not declared",
|
||||
"Use of Mutation Events is deprecated. Use MutationObserver instead.",
|
||||
"Unexpected value from nativeGetEnabledTags: 0" ]
|
||||
|
||||
class RemoteAutomation(Automation):
|
||||
_devicemanager = None
|
||||
|
||||
# Part of a hack for Robocop: "am COMMAND" is handled specially if COMMAND
|
||||
# is in this set. See usages below.
|
||||
_specialAmCommands = ('instrument', 'start')
|
||||
|
||||
def __init__(self, deviceManager, appName = '', remoteLog = None,
|
||||
processArgs=None):
|
||||
self._devicemanager = deviceManager
|
||||
self._appName = appName
|
||||
self._remoteProfile = None
|
||||
self._remoteLog = remoteLog
|
||||
self._processArgs = processArgs or {};
|
||||
|
||||
# Default our product to fennec
|
||||
self._product = "fennec"
|
||||
self.lastTestSeen = "remoteautomation.py"
|
||||
Automation.__init__(self)
|
||||
|
||||
def setDeviceManager(self, deviceManager):
|
||||
self._devicemanager = deviceManager
|
||||
|
||||
def setAppName(self, appName):
|
||||
self._appName = appName
|
||||
|
||||
def setRemoteProfile(self, remoteProfile):
|
||||
self._remoteProfile = remoteProfile
|
||||
|
||||
def setProduct(self, product):
|
||||
self._product = product
|
||||
|
||||
def setRemoteLog(self, logfile):
|
||||
self._remoteLog = logfile
|
||||
|
||||
# Set up what we need for the remote environment
|
||||
def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, dmdPath=None, lsanPath=None):
|
||||
# Because we are running remote, we don't want to mimic the local env
|
||||
# so no copying of os.environ
|
||||
if env is None:
|
||||
env = {}
|
||||
|
||||
if dmdPath:
|
||||
env['MOZ_REPLACE_MALLOC_LIB'] = os.path.join(dmdPath, 'libdmd.so')
|
||||
|
||||
# Except for the mochitest results table hiding option, which isn't
|
||||
# passed to runtestsremote.py as an actual option, but through the
|
||||
# MOZ_HIDE_RESULTS_TABLE environment variable.
|
||||
if 'MOZ_HIDE_RESULTS_TABLE' in os.environ:
|
||||
env['MOZ_HIDE_RESULTS_TABLE'] = os.environ['MOZ_HIDE_RESULTS_TABLE']
|
||||
|
||||
env['MOZ_CRASHREPORTER_DISABLE'] = '1'
|
||||
|
||||
# Crash on non-local network connections by default.
|
||||
# MOZ_DISABLE_NONLOCAL_CONNECTIONS can be set to "0" to temporarily
|
||||
# enable non-local connections for the purposes of local testing.
|
||||
# Don't override the user's choice here. See bug 1049688.
|
||||
env.setdefault('MOZ_DISABLE_NONLOCAL_CONNECTIONS', '1')
|
||||
|
||||
# Send an env var noting that we are in automation. Passing any
|
||||
# value except the empty string will declare the value to exist.
|
||||
#
|
||||
# This may be used to disabled network connections during testing, e.g.
|
||||
# Switchboard & telemetry uploads.
|
||||
env.setdefault('MOZ_IN_AUTOMATION', '1')
|
||||
|
||||
# Set WebRTC logging in case it is not set yet.
|
||||
# On Android, environment variables cannot contain ',' so the
|
||||
# standard WebRTC setting for NSPR_LOG_MODULES is not available.
|
||||
# env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5')
|
||||
env.setdefault('R_LOG_LEVEL', '6')
|
||||
env.setdefault('R_LOG_DESTINATION', 'stderr')
|
||||
env.setdefault('R_LOG_VERBOSE', '1')
|
||||
|
||||
return env
|
||||
|
||||
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath, outputHandler=None):
|
||||
""" Wait for tests to finish.
|
||||
If maxTime seconds elapse or no output is detected for timeout
|
||||
seconds, kill the process and fail the test.
|
||||
"""
|
||||
# maxTime is used to override the default timeout, we should honor that
|
||||
status = proc.wait(timeout = maxTime, noOutputTimeout = timeout)
|
||||
self.lastTestSeen = proc.getLastTestSeen
|
||||
|
||||
topActivity = self._devicemanager.getTopActivity()
|
||||
if topActivity == proc.procName:
|
||||
proc.kill(True)
|
||||
if status == 1:
|
||||
if maxTime:
|
||||
print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
|
||||
"allowed maximum time of %s seconds" % (self.lastTestSeen, maxTime)
|
||||
else:
|
||||
print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
|
||||
"allowed maximum time" % (self.lastTestSeen)
|
||||
if status == 2:
|
||||
print "TEST-UNEXPECTED-FAIL | %s | application timed out after %d seconds with no output" \
|
||||
% (self.lastTestSeen, int(timeout))
|
||||
|
||||
return status
|
||||
|
||||
def deleteANRs(self):
|
||||
# empty ANR traces.txt file; usually need root permissions
|
||||
# we make it empty and writable so we can test the ANR reporter later
|
||||
traces = "/data/anr/traces.txt"
|
||||
try:
|
||||
self._devicemanager.shellCheckOutput(['echo', '', '>', traces], root=True,
|
||||
timeout=DeviceManager.short_timeout)
|
||||
self._devicemanager.shellCheckOutput(['chmod', '666', traces], root=True,
|
||||
timeout=DeviceManager.short_timeout)
|
||||
except DMError:
|
||||
print "Error deleting %s" % traces
|
||||
pass
|
||||
|
||||
def checkForANRs(self):
|
||||
traces = "/data/anr/traces.txt"
|
||||
if self._devicemanager.fileExists(traces):
|
||||
try:
|
||||
t = self._devicemanager.pullFile(traces)
|
||||
if t:
|
||||
stripped = t.strip()
|
||||
if len(stripped) > 0:
|
||||
print "Contents of %s:" % traces
|
||||
print t
|
||||
# Once reported, delete traces
|
||||
self.deleteANRs()
|
||||
except DMError:
|
||||
print "Error pulling %s" % traces
|
||||
except IOError:
|
||||
print "Error pulling %s" % traces
|
||||
else:
|
||||
print "%s not found" % traces
|
||||
|
||||
def deleteTombstones(self):
|
||||
# delete any existing tombstone files from device
|
||||
remoteDir = "/data/tombstones"
|
||||
try:
|
||||
self._devicemanager.shellCheckOutput(['rm', '-r', remoteDir], root=True,
|
||||
timeout=DeviceManager.short_timeout)
|
||||
except DMError:
|
||||
# This may just indicate that the tombstone directory is missing
|
||||
pass
|
||||
|
||||
def checkForTombstones(self):
|
||||
# pull any tombstones from device and move to MOZ_UPLOAD_DIR
|
||||
remoteDir = "/data/tombstones"
|
||||
blobberUploadDir = os.environ.get('MOZ_UPLOAD_DIR', None)
|
||||
if blobberUploadDir:
|
||||
if not os.path.exists(blobberUploadDir):
|
||||
os.mkdir(blobberUploadDir)
|
||||
if self._devicemanager.dirExists(remoteDir):
|
||||
# copy tombstone files from device to local blobber upload directory
|
||||
try:
|
||||
self._devicemanager.shellCheckOutput(['chmod', '777', remoteDir], root=True,
|
||||
timeout=DeviceManager.short_timeout)
|
||||
self._devicemanager.shellCheckOutput(['chmod', '666', os.path.join(remoteDir, '*')], root=True,
|
||||
timeout=DeviceManager.short_timeout)
|
||||
self._devicemanager.getDirectory(remoteDir, blobberUploadDir, False)
|
||||
except DMError:
|
||||
# This may just indicate that no tombstone files are present
|
||||
pass
|
||||
self.deleteTombstones()
|
||||
# add a .txt file extension to each tombstone file name, so
|
||||
# that blobber will upload it
|
||||
for f in glob.glob(os.path.join(blobberUploadDir, "tombstone_??")):
|
||||
# add a unique integer to the file name, in case there are
|
||||
# multiple tombstones generated with the same name, for
|
||||
# instance, after multiple robocop tests
|
||||
for i in xrange(1, sys.maxint):
|
||||
newname = "%s.%d.txt" % (f, i)
|
||||
if not os.path.exists(newname):
|
||||
os.rename(f, newname)
|
||||
break
|
||||
else:
|
||||
print "%s does not exist; tombstone check skipped" % remoteDir
|
||||
else:
|
||||
print "MOZ_UPLOAD_DIR not defined; tombstone check skipped"
|
||||
|
||||
def checkForCrashes(self, directory, symbolsPath):
|
||||
self.checkForANRs()
|
||||
self.checkForTombstones()
|
||||
|
||||
logcat = self._devicemanager.getLogcat(filterOutRegexps=fennecLogcatFilters)
|
||||
|
||||
javaException = mozcrash.check_for_java_exception(logcat, test_name=self.lastTestSeen)
|
||||
if javaException:
|
||||
return True
|
||||
|
||||
# No crash reporting means we can't say anything.
|
||||
return False
|
||||
|
||||
|
||||
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
|
||||
# If remote profile is specified, use that instead
|
||||
if (self._remoteProfile):
|
||||
profileDir = self._remoteProfile
|
||||
|
||||
# Hack for robocop, if app & testURL == None and extraArgs contains the rest of the stuff, lets
|
||||
# assume extraArgs is all we need
|
||||
if app == "am" and extraArgs[0] in RemoteAutomation._specialAmCommands:
|
||||
return app, extraArgs
|
||||
|
||||
cmd, args = Automation.buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs)
|
||||
# Remove -foreground if it exists, if it doesn't this just returns
|
||||
try:
|
||||
args.remove('-foreground')
|
||||
except:
|
||||
pass
|
||||
#TODO: figure out which platform require NO_EM_RESTART
|
||||
# return app, ['--environ:NO_EM_RESTART=1'] + args
|
||||
return app, args
|
||||
|
||||
def Process(self, cmd, stdout = None, stderr = None, env = None, cwd = None):
|
||||
if stdout == None or stdout == -1 or stdout == subprocess.PIPE:
|
||||
stdout = self._remoteLog
|
||||
|
||||
return self.RProcess(self._devicemanager, cmd, stdout, stderr, env, cwd, self._appName,
|
||||
**self._processArgs)
|
||||
|
||||
# be careful here as this inner class doesn't have access to outer class members
|
||||
class RProcess(object):
|
||||
# device manager process
|
||||
dm = None
|
||||
def __init__(self, dm, cmd, stdout=None, stderr=None, env=None, cwd=None, app=None,
|
||||
messageLogger=None):
|
||||
self.dm = dm
|
||||
self.stdoutlen = 0
|
||||
self.lastTestSeen = "remoteautomation.py"
|
||||
self.proc = dm.launchProcess(cmd, stdout, cwd, env, True)
|
||||
self.messageLogger = messageLogger
|
||||
|
||||
if (self.proc is None):
|
||||
if cmd[0] == 'am':
|
||||
self.proc = stdout
|
||||
else:
|
||||
raise Exception("unable to launch process")
|
||||
self.procName = cmd[0].split('/')[-1]
|
||||
if cmd[0] == 'am' and cmd[1] in RemoteAutomation._specialAmCommands:
|
||||
self.procName = app
|
||||
|
||||
# Setting timeout at 1 hour since on a remote device this takes much longer.
|
||||
# Temporarily increased to 90 minutes because no more chunks can be created.
|
||||
self.timeout = 5400
|
||||
# The benefit of the following sleep is unclear; it was formerly 15 seconds
|
||||
time.sleep(1)
|
||||
|
||||
# Used to buffer log messages until we meet a line break
|
||||
self.logBuffer = ""
|
||||
|
||||
@property
|
||||
def pid(self):
|
||||
pid = self.dm.processExist(self.procName)
|
||||
# HACK: we should probably be more sophisticated about monitoring
|
||||
# running processes for the remote case, but for now we'll assume
|
||||
# that this method can be called when nothing exists and it is not
|
||||
# an error
|
||||
if pid is None:
|
||||
return 0
|
||||
return pid
|
||||
|
||||
def read_stdout(self):
|
||||
"""
|
||||
Fetch the full remote log file using devicemanager, process them and
|
||||
return whether there were any new log entries since the last call.
|
||||
"""
|
||||
if not self.dm.fileExists(self.proc):
|
||||
return False
|
||||
try:
|
||||
newLogContent = self.dm.pullFile(self.proc, self.stdoutlen)
|
||||
except DMError:
|
||||
# we currently don't retry properly in the pullFile
|
||||
# function in dmSUT, so an error here is not necessarily
|
||||
# the end of the world
|
||||
return False
|
||||
if not newLogContent:
|
||||
return False
|
||||
|
||||
self.stdoutlen += len(newLogContent)
|
||||
|
||||
if self.messageLogger is None:
|
||||
testStartFilenames = re.findall(r"TEST-START \| ([^\s]*)", newLogContent)
|
||||
if testStartFilenames:
|
||||
self.lastTestSeen = testStartFilenames[-1]
|
||||
print newLogContent
|
||||
return True
|
||||
|
||||
self.logBuffer += newLogContent
|
||||
lines = self.logBuffer.split('\n')
|
||||
lines = [l for l in lines if l]
|
||||
|
||||
if lines:
|
||||
if self.logBuffer.endswith('\n'):
|
||||
# all lines are complete; no need to buffer
|
||||
self.logBuffer = ""
|
||||
else:
|
||||
# keep the last (unfinished) line in the buffer
|
||||
self.logBuffer = lines[-1]
|
||||
del lines[-1]
|
||||
|
||||
if not lines:
|
||||
return False
|
||||
|
||||
for line in lines:
|
||||
# This passes the line to the logger (to be logged or buffered)
|
||||
parsed_messages = self.messageLogger.write(line)
|
||||
for message in parsed_messages:
|
||||
if isinstance(message, dict) and message.get('action') == 'test_start':
|
||||
self.lastTestSeen = message['test']
|
||||
return True
|
||||
|
||||
@property
|
||||
def getLastTestSeen(self):
|
||||
return self.lastTestSeen
|
||||
|
||||
# Wait for the remote process to end (or for its activity to go to background).
|
||||
# While waiting, periodically retrieve the process output and print it.
|
||||
# If the process is still running after *timeout* seconds, return 1;
|
||||
# If the process is still running but no output is received in *noOutputTimeout*
|
||||
# seconds, return 2;
|
||||
# Else, once the process exits/goes to background, return 0.
|
||||
def wait(self, timeout = None, noOutputTimeout = None):
|
||||
timer = 0
|
||||
noOutputTimer = 0
|
||||
interval = 10
|
||||
if timeout == None:
|
||||
timeout = self.timeout
|
||||
status = 0
|
||||
top = self.procName
|
||||
slowLog = False
|
||||
while (top == self.procName):
|
||||
# Get log updates on each interval, but if it is taking
|
||||
# too long, only do it every 60 seconds
|
||||
if (not slowLog) or (timer % 60 == 0):
|
||||
startRead = datetime.datetime.utcnow()
|
||||
hasOutput = self.read_stdout()
|
||||
if (datetime.datetime.utcnow() - startRead) > datetime.timedelta(seconds=5):
|
||||
slowLog = True
|
||||
if hasOutput:
|
||||
noOutputTimer = 0
|
||||
time.sleep(interval)
|
||||
timer += interval
|
||||
noOutputTimer += interval
|
||||
if (timer > timeout):
|
||||
status = 1
|
||||
break
|
||||
if (noOutputTimeout and noOutputTimer > noOutputTimeout):
|
||||
status = 2
|
||||
break
|
||||
top = self.dm.getTopActivity()
|
||||
# Flush anything added to stdout during the sleep
|
||||
self.read_stdout()
|
||||
return status
|
||||
|
||||
def kill(self, stagedShutdown = False):
|
||||
if stagedShutdown:
|
||||
# Trigger an ANR report with "kill -3" (SIGQUIT)
|
||||
self.dm.killProcess(self.procName, 3)
|
||||
time.sleep(3)
|
||||
# Trigger a breakpad dump with "kill -6" (SIGABRT)
|
||||
self.dm.killProcess(self.procName, 6)
|
||||
# Wait for process to end
|
||||
retries = 0
|
||||
while retries < 3:
|
||||
pid = self.dm.processExist(self.procName)
|
||||
if pid and pid > 0:
|
||||
print "%s still alive after SIGABRT: waiting..." % self.procName
|
||||
time.sleep(5)
|
||||
else:
|
||||
return
|
||||
retries += 1
|
||||
self.dm.killProcess(self.procName, 9)
|
||||
pid = self.dm.processExist(self.procName)
|
||||
if pid and pid > 0:
|
||||
self.dm.killProcess(self.procName)
|
||||
else:
|
||||
self.dm.killProcess(self.procName)
|
||||
@@ -15,7 +15,7 @@ ifndef JS_STANDALONE
|
||||
include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
|
||||
include $(topsrcdir)/toolkit/mozapps/installer/upload-files.mk
|
||||
|
||||
# Clear out DIST_FILES if it was set by upload-files.mk (for Android builds)
|
||||
# Clear out DIST_FILES if it was set
|
||||
DIST_FILES =
|
||||
endif
|
||||
|
||||
|
||||
+1
-7
@@ -3,9 +3,6 @@
|
||||
# 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/.
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Core', 'Build Config')
|
||||
|
||||
# This cannot be named "build" because of bug 922191.
|
||||
SPHINX_TREES['buildsystem'] = 'docs'
|
||||
|
||||
@@ -14,9 +11,6 @@ if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
else:
|
||||
DIRS += ['unix']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||
DIRS += ['annotationProcessors']
|
||||
|
||||
for var in ('GRE_MILESTONE',
|
||||
'MOZ_APP_VERSION',
|
||||
'MOZ_APP_BASENAME',
|
||||
@@ -70,7 +64,7 @@ if CONFIG['MOZ_ASAN'] and CONFIG['CLANG_CL']:
|
||||
|
||||
if CONFIG['MOZ_APP_BASENAME']:
|
||||
FINAL_TARGET_PP_FILES += ['application.ini']
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android' and CONFIG['MOZ_UPDATER']:
|
||||
if CONFIG['MOZ_UPDATER']:
|
||||
FINAL_TARGET_PP_FILES += ['update-settings.ini']
|
||||
|
||||
if CONFIG['MOZ_APP_STATIC_INI']:
|
||||
|
||||
@@ -1,149 +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/.
|
||||
|
||||
|
||||
js_option('--with-android-ndk', nargs=1,
|
||||
help='location where the Android NDK can be found')
|
||||
|
||||
js_option('--with-android-toolchain', nargs=1,
|
||||
help='location of the Android toolchain')
|
||||
|
||||
js_option('--with-android-gnu-compiler-version', nargs=1,
|
||||
help='GNU compiler version to use')
|
||||
|
||||
min_android_version = dependable(lambda: '9')
|
||||
|
||||
js_option('--with-android-version',
|
||||
nargs=1,
|
||||
help='android platform version',
|
||||
default=min_android_version)
|
||||
|
||||
@depends('--with-android-version', min_android_version)
|
||||
@imports(_from='__builtin__', _import='ValueError')
|
||||
def android_version(value, min_version):
|
||||
if not value:
|
||||
# Someone has passed --without-android-version.
|
||||
die('--with-android-version cannot be disabled.')
|
||||
|
||||
try:
|
||||
version = int(value[0])
|
||||
except ValueError:
|
||||
die('--with-android-version expects an integer value')
|
||||
|
||||
if version < int(min_version):
|
||||
die('--with-android-version must be at least %s (got %s)',
|
||||
min_version, value[0])
|
||||
|
||||
return version
|
||||
|
||||
add_old_configure_assignment('android_version', android_version)
|
||||
|
||||
@depends('--with-android-ndk', build_project)
|
||||
def ndk(value, build_project):
|
||||
if build_project == 'mobile/android' and not value:
|
||||
die('You must specify --with-android-ndk=/path/to/ndk when '
|
||||
'building mobile/android')
|
||||
if value:
|
||||
return value[0]
|
||||
|
||||
set_config('ANDROID_NDK', ndk)
|
||||
add_old_configure_assignment('android_ndk', ndk)
|
||||
|
||||
@depends(target, android_version, ndk)
|
||||
@checking('for android platform directory')
|
||||
@imports(_from='os.path', _import='isdir')
|
||||
def android_platform(target, android_version, ndk):
|
||||
if target.os != 'Android':
|
||||
return
|
||||
|
||||
if 'mips' in target.cpu:
|
||||
target_dir_name = 'mips'
|
||||
elif 'aarch64' == target.cpu:
|
||||
target_dir_name = 'arm64'
|
||||
else:
|
||||
target_dir_name = target.cpu
|
||||
|
||||
# Not all Android releases have their own platform release. We use
|
||||
# the next lower platform version in these cases.
|
||||
if android_version in (11, 10):
|
||||
platform_version = 9
|
||||
elif android_version in (20, 22):
|
||||
platform_version = android_version - 1
|
||||
else:
|
||||
platform_version = android_version
|
||||
|
||||
platform_dir = os.path.join(ndk,
|
||||
'platforms',
|
||||
'android-%s' % platform_version,
|
||||
'arch-%s' % target_dir_name)
|
||||
|
||||
if not isdir(platform_dir):
|
||||
die("Android platform directory not found. With the current "
|
||||
"configuration, it should be in %s" % platform_dir)
|
||||
|
||||
return platform_dir
|
||||
|
||||
add_old_configure_assignment('android_platform', android_platform)
|
||||
|
||||
@depends(android_platform)
|
||||
def extra_toolchain_flags(platform_dir):
|
||||
if not platform_dir:
|
||||
return []
|
||||
return ['-idirafter',
|
||||
os.path.join(platform_dir, 'usr', 'include')]
|
||||
|
||||
@depends(target, host, ndk, '--with-android-toolchain',
|
||||
'--with-android-gnu-compiler-version')
|
||||
@checking('for the Android toolchain directory', lambda x: x or 'not found')
|
||||
@imports(_from='os.path', _import='isdir')
|
||||
@imports(_from='mozbuild.shellutil', _import='quote')
|
||||
def android_toolchain(target, host, ndk, toolchain, gnu_compiler_version):
|
||||
if not ndk:
|
||||
return
|
||||
if toolchain:
|
||||
return toolchain[0]
|
||||
else:
|
||||
if target.cpu == 'arm' and target.endianness == 'little':
|
||||
target_base = 'arm-linux-androideabi'
|
||||
elif target.cpu == 'x86':
|
||||
target_base = 'x86'
|
||||
elif target.cpu == 'mips32' and target.endianness == 'little':
|
||||
target_base = 'mipsel-linux-android'
|
||||
elif target.cpu == 'aarch64' and target.endianness == 'little':
|
||||
target_base = 'aarch64-linux-android'
|
||||
else:
|
||||
die('Target cpu is not supported.')
|
||||
|
||||
toolchain_format = '%s/toolchains/%s-%s/prebuilt/%s-%s'
|
||||
|
||||
for version in gnu_compiler_version or ['4.9', '4.8', '4.7']:
|
||||
toolchain = toolchain_format % (ndk, target_base, version,
|
||||
host.kernel.lower(), host.cpu)
|
||||
log.debug('Trying %s' % quote(toolchain))
|
||||
if not isdir(toolchain) and host.cpu == 'x86_64':
|
||||
toolchain = toolchain_format % (ndk, target_base, version,
|
||||
host.kernel.lower(), 'x86')
|
||||
log.debug('Trying %s' % quote(toolchain))
|
||||
if isdir(toolchain):
|
||||
return toolchain
|
||||
else:
|
||||
if gnu_compiler_version:
|
||||
die('Your --with-android-gnu-compiler-version may be wrong')
|
||||
die('You have to specify --with-android-toolchain='
|
||||
'/path/to/ndk/toolchain.')
|
||||
|
||||
set_config('ANDROID_TOOLCHAIN', android_toolchain)
|
||||
|
||||
@depends(target, android_toolchain)
|
||||
def android_toolchain_prefix(target, toolchain):
|
||||
if toolchain:
|
||||
if target.cpu == 'x86':
|
||||
# Ideally, the --target should just have the right x86 variant
|
||||
# in the first place.
|
||||
return '%s/bin/i686-linux-android-' % toolchain
|
||||
return '%s/bin/%s-' % (toolchain, target.toolchain)
|
||||
|
||||
imply_option('--with-toolchain-prefix', android_toolchain_prefix,
|
||||
reason='--with-android-ndk')
|
||||
@@ -42,11 +42,10 @@ def compiler_class(compiler):
|
||||
def checking_fn(fn):
|
||||
return fn
|
||||
|
||||
@depends_when(self, dependable(flags), extra_toolchain_flags, when=when)
|
||||
@depends_when(self, dependable(flags), when=when)
|
||||
@checking_fn
|
||||
def func(compiler, flags, extra_flags):
|
||||
def func(compiler, flags):
|
||||
flags = flags or []
|
||||
flags += extra_flags or []
|
||||
flags.append('-c')
|
||||
|
||||
if try_invoke_compiler(
|
||||
|
||||
@@ -308,10 +308,7 @@ def split_triplet(triplet):
|
||||
# mix of uname and config.guess output, while we now only use the latter,
|
||||
# which presumably has a cleaner and leaner output. Let's refine later.
|
||||
os = os.replace('/', '_')
|
||||
if 'android' in os:
|
||||
canonical_os = 'Android'
|
||||
canonical_kernel = 'Linux'
|
||||
elif os.startswith('linux'):
|
||||
if os.startswith('linux'):
|
||||
canonical_os = 'GNU'
|
||||
canonical_kernel = 'Linux'
|
||||
elif os.startswith('kfreebsd') and os.endswith('-gnu'):
|
||||
@@ -521,6 +518,7 @@ def host_variables(host):
|
||||
HOST_OS_ARCH=os_arch,
|
||||
)
|
||||
|
||||
set_config('HOST_CPU_ARCH', delayed_getattr(host, 'cpu'))
|
||||
set_config('HOST_OS_ARCH', delayed_getattr(host_variables, 'HOST_OS_ARCH'))
|
||||
add_old_configure_assignment('HOST_OS_ARCH',
|
||||
delayed_getattr(host_variables, 'HOST_OS_ARCH'))
|
||||
@@ -549,13 +547,6 @@ def target_is_darwin(target):
|
||||
|
||||
set_define('XP_DARWIN', target_is_darwin)
|
||||
|
||||
@depends(target)
|
||||
def target_is_ios(target):
|
||||
if target.kernel == 'Darwin' and target.os == 'iOS':
|
||||
return True
|
||||
|
||||
set_define('XP_IOS', target_is_ios)
|
||||
|
||||
@depends(target)
|
||||
def target_is_osx(target):
|
||||
if target.kernel == 'Darwin' and target.os == 'OSX':
|
||||
@@ -607,9 +598,7 @@ imply_option('--enable-project', application)
|
||||
|
||||
@depends(check_build_environment, '--help')
|
||||
def default_project(build_env, help):
|
||||
if build_env.topobjdir.endswith('/js/src'):
|
||||
return 'js'
|
||||
return 'application/xulrunner'
|
||||
return 'js'
|
||||
|
||||
option('--enable-project', nargs=1, default=default_project,
|
||||
help='Project to build')
|
||||
@@ -642,9 +631,10 @@ def external_source_dir(value):
|
||||
set_config('EXTERNAL_SOURCE_DIR', external_source_dir)
|
||||
add_old_configure_assignment('EXTERNAL_SOURCE_DIR', external_source_dir)
|
||||
|
||||
@depends('--enable-project', '--with-external-source-dir', check_build_environment, '--help')
|
||||
option('--enable-noncomm-build', default=False, help='Allows non-comm-style builds (deprecated)')
|
||||
@depends('--enable-noncomm-build','--enable-project', '--with-external-source-dir', check_build_environment, '--help')
|
||||
@imports(_from='os.path', _import='exists')
|
||||
def build_project(project, external_source_dir, build_env, help):
|
||||
def build_project(noncomm_build, project, external_source_dir, build_env, help):
|
||||
if not project:
|
||||
die('--enable-project is required.')
|
||||
|
||||
@@ -655,8 +645,13 @@ def build_project(project, external_source_dir, build_env, help):
|
||||
|
||||
build_app = project[0]
|
||||
|
||||
if not external_source_dir and build_app not in ('xulrunner', 'js'):
|
||||
die('Cannot find project %s', build_app)
|
||||
if not external_source_dir and build_app not in ('js'):
|
||||
if noncomm_build:
|
||||
log.info("=====WARNING WARNING WARNING=====")
|
||||
log.info("UNSUPPORTED NONCOMM-BUILD: Application code SHOULD NOT be put inside the platform tree, and doing so may have unforseen consequences if/when platform code is changed.")
|
||||
log.info("=====WARNING WARNING WARNING=====")
|
||||
else:
|
||||
die('Cannot find project %s', build_app)
|
||||
|
||||
build_app_abspath = os.path.join(base_dir, build_app)
|
||||
|
||||
@@ -671,11 +666,7 @@ set_define('MOZ_BUILD_APP', build_project)
|
||||
add_old_configure_assignment('MOZ_BUILD_APP', build_project)
|
||||
|
||||
|
||||
# set RELEASE_OR_BETA and NIGHTLY_BUILD variables depending on the cycle we're in
|
||||
# The logic works like this:
|
||||
# - if we have "a1" in GRE_MILESTONE, we're building Nightly (define NIGHTLY_BUILD)
|
||||
# - otherwise, if we have "a" in GRE_MILESTONE, we're building Nightly or Aurora
|
||||
# - otherwise, we're building Release/Beta (define RELEASE_OR_BETA)
|
||||
# set RELEASE_OR_BETA and NIGHTLY_BUILD variables for compatibility
|
||||
@depends(check_build_environment, '--help')
|
||||
@imports(_from='__builtin__', _import='open')
|
||||
def milestone(build_env, _):
|
||||
@@ -685,12 +676,8 @@ def milestone(build_env, _):
|
||||
with open(milestone_path, 'r') as fh:
|
||||
milestone = fh.read().splitlines()[-1]
|
||||
|
||||
is_nightly = is_release_or_beta = None
|
||||
|
||||
if 'a1' in milestone:
|
||||
is_nightly = True
|
||||
elif 'a' not in milestone:
|
||||
is_release_or_beta = True
|
||||
is_nightly = None
|
||||
is_release_or_beta = True
|
||||
|
||||
return namespace(version=milestone,
|
||||
is_nightly=is_nightly,
|
||||
@@ -809,13 +796,3 @@ def js_option(*args, **kwargs):
|
||||
return value.format(opt.option)
|
||||
|
||||
add_old_configure_arg(js_option)
|
||||
|
||||
|
||||
# Bug 1278542: This function is a workaround to resolve
|
||||
# |android_ndk_include|'s dependency on 'gonkdir.' The
|
||||
# actual implementation is located in b2g/moz.configure.
|
||||
# Remove this function as soon as 'android_ndk_include'
|
||||
# depends on 'target.'
|
||||
@depends('--help')
|
||||
def gonkdir(_):
|
||||
return None
|
||||
@@ -64,14 +64,6 @@ def jemalloc_os_define(jemalloc, target):
|
||||
|
||||
set_define(jemalloc_os_define, '1')
|
||||
|
||||
@depends(jemalloc, target)
|
||||
def jemalloc_os_define_android(jemalloc, target):
|
||||
if jemalloc and target.os == 'Android':
|
||||
return 'MOZ_MEMORY_ANDROID'
|
||||
|
||||
set_define(jemalloc_os_define_android, '1')
|
||||
|
||||
|
||||
option('--enable-replace-malloc',
|
||||
help='Enable ability to dynamically replace the malloc implementation')
|
||||
|
||||
|
||||
@@ -249,17 +249,11 @@ def old_configure_options(*options):
|
||||
'--enable-valgrind',
|
||||
'--enable-verify-mar',
|
||||
'--enable-webrtc',
|
||||
'--enable-xul',
|
||||
'--enable-zipwriter',
|
||||
'--includedir',
|
||||
'--libdir',
|
||||
'--no-create',
|
||||
'--prefix',
|
||||
'--with-android-cxx-stl',
|
||||
'--with-android-distribution-directory',
|
||||
'--with-android-max-sdk',
|
||||
'--with-android-min-sdk',
|
||||
'--with-android-sdk',
|
||||
'--with-app-basename',
|
||||
'--with-app-name',
|
||||
'--with-arch',
|
||||
@@ -312,6 +306,7 @@ def old_configure_options(*options):
|
||||
'--disable-browser-statusbar',
|
||||
'--disable-sync',
|
||||
'--disable-personas',
|
||||
'--enable-phoenix-extensions',
|
||||
|
||||
# Below are configure flags used by Basilisk
|
||||
'--disable-webextensions',
|
||||
|
||||
@@ -61,15 +61,6 @@ set_config('HAVE_YASM', have_yasm)
|
||||
# Until the YASM variable is not necessary in old-configure.
|
||||
add_old_configure_assignment('YASM', have_yasm)
|
||||
|
||||
# Android NDK
|
||||
# ==============================================================
|
||||
|
||||
@depends('--disable-compile-environment', build_project, gonkdir, '--help')
|
||||
def compiling_android(compile_env, build_project, gonkdir, _):
|
||||
return compile_env and (gonkdir or build_project in ('mobile/android', 'js'))
|
||||
|
||||
include('android-ndk.configure', when=compiling_android)
|
||||
|
||||
# MacOS deployment target version
|
||||
# ==============================================================
|
||||
# This needs to happen before any compilation test is done.
|
||||
@@ -165,9 +156,8 @@ def toolchain_prefix(value, target, host, cross_compiling):
|
||||
@depends(toolchain_prefix, target)
|
||||
def first_toolchain_prefix(toolchain_prefix, target):
|
||||
# Pass TOOLCHAIN_PREFIX down to the build system if it was given from the
|
||||
# command line/environment (in which case there's only one value in the tuple),
|
||||
# or when cross-compiling for Android.
|
||||
if toolchain_prefix and (target.os == 'Android' or len(toolchain_prefix) == 1):
|
||||
# command line/environment (in which case there's only one value in the tuple).
|
||||
if toolchain_prefix and (len(toolchain_prefix) == 1):
|
||||
return toolchain_prefix[0]
|
||||
|
||||
set_config('TOOLCHAIN_PREFIX', first_toolchain_prefix)
|
||||
@@ -685,9 +675,9 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
|
||||
# Check the compiler version here instead of in `compiler_version` so
|
||||
# that the `checking` message doesn't pretend the compiler can be used
|
||||
# to then bail out one line later.
|
||||
if info.type == 'gcc' and info.version < '4.9.0':
|
||||
if info.type == 'gcc' and info.version < '7.1.0':
|
||||
raise FatalCheckError(
|
||||
'Only GCC 4.9 or newer is supported (found version %s).'
|
||||
'Only GCC 7.1 or newer is supported (found version %s).'
|
||||
% info.version)
|
||||
|
||||
# If you want to bump the version check here search for
|
||||
@@ -840,10 +830,9 @@ def debug_flags(env_debug_flags, enable_debug_flags, default_debug_flags):
|
||||
set_config('MOZ_DEBUG_FLAGS', debug_flags)
|
||||
add_old_configure_assignment('MOZ_DEBUG_FLAGS', debug_flags)
|
||||
|
||||
# Some standard library headers (notably bionic on Android) declare standard
|
||||
# functions (e.g. getchar()) and also #define macros for those standard
|
||||
# functions. libc++ deals with this by doing something like the following
|
||||
# (explanatory comments added):
|
||||
# Some standard library headers declare standard functions (e.g. getchar()) and
|
||||
# also #define macros for those standard functions. libc++ deals with this by
|
||||
# doing something like the following (explanatory comments added):
|
||||
#
|
||||
# #ifdef FUNC
|
||||
# // Capture the definition of FUNC.
|
||||
@@ -878,7 +867,8 @@ add_old_configure_assignment('MOZ_DEBUG_FLAGS', debug_flags)
|
||||
# effectively does the same thing we are doing here.
|
||||
@depends(c_compiler, target)
|
||||
def libcxx_inline_visibility(c_compiler, target):
|
||||
if c_compiler.type == 'clang' and target.os == 'Android':
|
||||
# FIXME: Vestigial conditional left over from Android, please remove.
|
||||
if False:
|
||||
return ''
|
||||
|
||||
set_define('_LIBCPP_INLINE_VISIBILITY', libcxx_inline_visibility)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
gcc_version=4.8.5
|
||||
gcc_version=7.1.0
|
||||
binutils_version=2.25.1
|
||||
this_path=$(readlink -f $(dirname $0))
|
||||
make_flags='-j12'
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
fun:malloc
|
||||
fun:moz_xmalloc
|
||||
fun:operator new
|
||||
fun:_Z21XRE_CreateStatsObjectv
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ nsChromeProtocolHandler::NewChannel2(nsIURI* aURI,
|
||||
file->Exists(&exists);
|
||||
if (!exists) {
|
||||
nsAutoCString path;
|
||||
file->GetNativePath(path);
|
||||
file->GetPersistentDescriptor(path);
|
||||
printf("Chrome file doesn't exist: %s\n", path.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,9 +108,7 @@ NS_INTERFACE_MAP_BEGIN(nsChromeRegistry)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIChromeRegistry)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXULChromeRegistry)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIToolkitChromeRegistry)
|
||||
#ifdef MOZ_XUL
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXULOverlayProvider)
|
||||
#endif
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChromeRegistry)
|
||||
|
||||
@@ -9,11 +9,7 @@
|
||||
#include "nsIToolkitChromeRegistry.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsIXULOverlayProvider.h"
|
||||
#endif
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsURIHashKey.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
@@ -37,9 +33,7 @@ class nsIURL;
|
||||
{ 0x47049e42, 0x1d87, 0x482a, { 0x98, 0x4d, 0x56, 0xae, 0x18, 0x5e, 0x36, 0x7a } }
|
||||
|
||||
class nsChromeRegistry : public nsIToolkitChromeRegistry,
|
||||
#ifdef MOZ_XUL
|
||||
public nsIXULOverlayProvider,
|
||||
#endif
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
|
||||
@@ -640,7 +640,6 @@ nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI* aBase)
|
||||
return &entry->mArray;
|
||||
}
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
NS_IMETHODIMP
|
||||
nsChromeRegistryChrome::GetStyleOverlays(nsIURI *aChromeURL,
|
||||
nsISimpleEnumerator **aResult)
|
||||
@@ -670,7 +669,6 @@ nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL,
|
||||
|
||||
return NS_NewArrayEnumerator(aResult, *parray);
|
||||
}
|
||||
#endif // MOZ_XUL
|
||||
|
||||
nsIURI*
|
||||
nsChromeRegistry::ManifestProcessingContext::GetManifestURI()
|
||||
|
||||
@@ -41,12 +41,10 @@ class nsChromeRegistryChrome : public nsChromeRegistry
|
||||
NS_IMETHOD Observe(nsISupports *aSubject, const char *aTopic,
|
||||
const char16_t *someData) override;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
NS_IMETHOD GetXULOverlays(nsIURI *aURI,
|
||||
nsISimpleEnumerator **_retval) override;
|
||||
NS_IMETHOD GetStyleOverlays(nsIURI *aURI,
|
||||
nsISimpleEnumerator **_retval) override;
|
||||
#endif
|
||||
|
||||
// If aChild is non-null then it is a new child to notify. If aChild is
|
||||
// null, then we have installed new chrome and we are resetting all of our
|
||||
|
||||
@@ -1,51 +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/.
|
||||
|
||||
# Ensure ANDROID_SDK is defined before including this file.
|
||||
# We use common android defaults for boot class path and java version.
|
||||
ifndef ANDROID_SDK
|
||||
$(error ANDROID_SDK must be defined before including android-common.mk)
|
||||
endif
|
||||
|
||||
# DEBUG_JARSIGNER always debug signs.
|
||||
DEBUG_JARSIGNER=$(PYTHON) $(abspath $(topsrcdir)/mobile/android/debug_sign_tool.py) \
|
||||
--keytool=$(KEYTOOL) \
|
||||
--jarsigner=$(JARSIGNER) \
|
||||
$(NULL)
|
||||
|
||||
# RELEASE_JARSIGNER release signs if possible.
|
||||
ifdef MOZ_SIGN_CMD
|
||||
RELEASE_JARSIGNER := $(MOZ_SIGN_CMD) -f jar
|
||||
else
|
||||
RELEASE_JARSIGNER := $(DEBUG_JARSIGNER)
|
||||
endif
|
||||
|
||||
# $(1) is the full path to input: foo-debug-unsigned-unaligned.apk.
|
||||
# $(2) is the full path to output: foo.apk.
|
||||
# Use this like: $(call RELEASE_SIGN_ANDROID_APK,foo-debug-unsigned-unaligned.apk,foo.apk)
|
||||
#
|
||||
# The |zip -d| there to handle re-signing previously signed APKs. Gradle
|
||||
# produces signed, unaligned APK files, but this expects unsigned, unaligned
|
||||
# APK files. The |zip -d| discards any existing signature, turning a signed,
|
||||
# unaligned APK into an unsigned, unaligned APK. Sadly |zip -q| doesn't
|
||||
# silence a warning about "nothing to do" so we pipe to /dev/null.
|
||||
RELEASE_SIGN_ANDROID_APK = \
|
||||
cp $(1) $(2)-unaligned.apk && \
|
||||
($(ZIP) -d $(2)-unaligned.apk 'META-INF/*' > /dev/null || true) && \
|
||||
$(RELEASE_JARSIGNER) $(2)-unaligned.apk && \
|
||||
$(ZIPALIGN) -f -v 4 $(2)-unaligned.apk $(2) && \
|
||||
$(RM) $(2)-unaligned.apk
|
||||
|
||||
# For Android, we default to 1.7
|
||||
ifndef JAVA_VERSION
|
||||
JAVA_VERSION = 1.7
|
||||
endif
|
||||
|
||||
JAVAC_FLAGS = \
|
||||
-target $(JAVA_VERSION) \
|
||||
-source $(JAVA_VERSION) \
|
||||
-encoding UTF8 \
|
||||
-g:source,lines \
|
||||
-Werror \
|
||||
$(NULL)
|
||||
@@ -550,14 +550,6 @@ ifeq (,$(filter $(OS_TARGET),WINNT Darwin))
|
||||
CHECK_TEXTREL = @$(TOOLCHAIN_PREFIX)readelf -d $(1) | grep TEXTREL > /dev/null && echo 'TEST-UNEXPECTED-FAIL | check_textrel | We do not want text relocations in libraries and programs' || true
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),android)
|
||||
# While this is very unlikely (libc being added by the compiler at the end
|
||||
# of the linker command line), if libmozglue.so ends up after libc.so, all
|
||||
# hell breaks loose, so better safe than sorry, and check it's actually the
|
||||
# case.
|
||||
CHECK_MOZGLUE_ORDER = @$(TOOLCHAIN_PREFIX)readelf -d $(1) | grep NEEDED | awk '{ libs[$$NF] = ++n } END { if (libs["[libmozglue.so]"] && libs["[libc.so]"] < libs["[libmozglue.so]"]) { print "libmozglue.so must be linked before libc.so"; exit 1 } }'
|
||||
endif
|
||||
|
||||
define CHECK_BINARY
|
||||
$(call CHECK_GLIBC,$(1))
|
||||
$(call CHECK_STDCXX,$(1))
|
||||
|
||||
Vendored
+3
-4
@@ -10,9 +10,8 @@ DIRS += ['lgpllibs']
|
||||
if not CONFIG['MOZ_SYSTEM_JPEG']:
|
||||
external_dirs += ['media/libjpeg']
|
||||
|
||||
if CONFIG['MOZ_UPDATER']:
|
||||
if not CONFIG['MOZ_SYSTEM_BZ2']:
|
||||
external_dirs += ['modules/libbz2']
|
||||
if not CONFIG['MOZ_SYSTEM_BZ2']:
|
||||
external_dirs += ['modules/libbz2']
|
||||
|
||||
# There's no "native" brotli or woff2 yet, but probably in the future...
|
||||
external_dirs += ['modules/brotli']
|
||||
@@ -55,7 +54,7 @@ external_dirs += [
|
||||
'media/psshparser'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_LINKER']:
|
||||
if CONFIG['MOZ_UPDATER']:
|
||||
external_dirs += ['modules/xz-embedded']
|
||||
|
||||
DIRS += ['../../' + i for i in external_dirs]
|
||||
Vendored
-469
@@ -1,469 +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/.
|
||||
|
||||
CC_WRAPPER =
|
||||
CXX_WRAPPER =
|
||||
|
||||
default::
|
||||
|
||||
include $(topsrcdir)/config/makefiles/functions.mk
|
||||
|
||||
NSS_LIBS = \
|
||||
nss3 \
|
||||
nssutil3 \
|
||||
smime3 \
|
||||
ssl3 \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
NSS_DLLS = $(LIBRARY_NAME)
|
||||
else
|
||||
NSS_DLLS = $(NSS_LIBS)
|
||||
endif
|
||||
|
||||
NSS_EXTRA_DLLS = \
|
||||
nssckbi \
|
||||
softokn3 \
|
||||
$(NULL)
|
||||
|
||||
ifndef NSS_DISABLE_DBM
|
||||
NSS_EXTRA_DLLS += nssdbm3
|
||||
endif
|
||||
|
||||
SDK_LIBS = crmf
|
||||
|
||||
ifneq (,$(filter WINNT,$(OS_ARCH)))
|
||||
SDK_LIBS += $(NSS_DLLS)
|
||||
endif
|
||||
|
||||
# Default
|
||||
HAVE_FREEBL_LIBS = 1
|
||||
|
||||
# SunOS SPARC
|
||||
|
||||
ifeq ($(OS_ARCH), SunOS)
|
||||
ifneq (86,$(findstring 86,$(OS_TEST)))
|
||||
ifdef HAVE_64BIT_BUILD
|
||||
HAVE_FREEBL_LIBS =
|
||||
HAVE_FREEBL_LIBS_64 = 1
|
||||
else
|
||||
HAVE_FREEBL_LIBS =
|
||||
HAVE_FREEBL_LIBS_32FPU = 1
|
||||
HAVE_FREEBL_LIBS_32INT64 = 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),Linux)
|
||||
HAVE_FREEBL_LIBS =
|
||||
HAVE_FREEBL_LIBS_PRIV = 1
|
||||
FREEBL_LOWHASH_FLAG = FREEBL_LOWHASH=1
|
||||
endif
|
||||
|
||||
ifdef HAVE_FREEBL_LIBS
|
||||
NSS_EXTRA_DLLS += freebl3
|
||||
endif
|
||||
ifdef HAVE_FREEBL_LIBS_PRIV
|
||||
NSS_EXTRA_DLLS += freeblpriv3
|
||||
endif
|
||||
ifdef HAVE_FREEBL_LIBS_32INT32
|
||||
NSS_EXTRA_DLLS += freebl_32int_3
|
||||
endif
|
||||
ifdef HAVE_FREEBL_LIBS_32FPU
|
||||
NSS_EXTRA_DLLS += freebl_32fpu_3
|
||||
endif
|
||||
ifdef HAVE_FREEBL_LIBS_32INT64
|
||||
NSS_EXTRA_DLLS += freebl_32int64_3
|
||||
endif
|
||||
ifdef HAVE_FREEBL_LIBS_64
|
||||
NSS_EXTRA_DLLS += freebl_64int_3
|
||||
NSS_EXTRA_DLLS += freebl_64fpu_3
|
||||
endif
|
||||
|
||||
# For all variables such as DLLFLAGS, that may contain $(DIST)
|
||||
DIST := $(ABS_DIST)
|
||||
# TODO: move this all to configure, but in Python
|
||||
ifndef MOZ_BUILD_NSPR
|
||||
NSPR_INCLUDE_DIR = $(firstword $(filter -I%,$(NSPR_CFLAGS)))
|
||||
ifneq (,$(strip $(NSPR_INCLUDE_DIR)))
|
||||
NSPR_INCLUDE_DIR := $(subst -I,,$(subst -I$(DIST),-I$(ABS_DIST),$(NSPR_INCLUDE_DIR)))
|
||||
else
|
||||
$(error Your NSPR CFLAGS are broken!)
|
||||
endif
|
||||
NSPR_LIB_DIR = $(firstword $(filter -L%,$(NSPR_LIBS)))
|
||||
ifneq (,$(strip $(NSPR_LIB_DIR)))
|
||||
NSPR_LIB_DIR := $(subst -L,,$(subst -L$(DIST),-L$(ABS_DIST),$(NSPR_LIB_DIR)))
|
||||
else
|
||||
$(error Your NSPR LDFLAGS are broken!)
|
||||
endif
|
||||
endif
|
||||
|
||||
# To get debug symbols from NSS
|
||||
export MOZ_DEBUG_SYMBOLS
|
||||
|
||||
DEFAULT_GMAKE_FLAGS =
|
||||
DEFAULT_GMAKE_FLAGS += CC='$(CC)'
|
||||
DEFAULT_GMAKE_FLAGS += MT='$(MT)'
|
||||
DEFAULT_GMAKE_FLAGS += LD='$(LD)'
|
||||
DEFAULT_GMAKE_FLAGS += SOURCE_MD_DIR=$(ABS_DIST)
|
||||
DEFAULT_GMAKE_FLAGS += SOURCE_MDHEADERS_DIR=$(NSPR_INCLUDE_DIR)
|
||||
DEFAULT_GMAKE_FLAGS += DIST=$(ABS_DIST)
|
||||
DEFAULT_GMAKE_FLAGS += NSPR_INCLUDE_DIR=$(NSPR_INCLUDE_DIR)
|
||||
DEFAULT_GMAKE_FLAGS += NSPR_LIB_DIR=$(NSPR_LIB_DIR)
|
||||
DEFAULT_GMAKE_FLAGS += MOZILLA_CLIENT=1
|
||||
DEFAULT_GMAKE_FLAGS += NO_MDUPDATE=1
|
||||
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ECC=1
|
||||
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_TLS_1_3=1
|
||||
ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_1)
|
||||
DEFAULT_GMAKE_FLAGS += OS_DLLFLAGS='-static-libgcc' NSPR31_LIB_PREFIX=lib
|
||||
endif
|
||||
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=mozsqlite3
|
||||
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_DIR=$(ABS_DIST)/../db/sqlite3/src
|
||||
DEFAULT_GMAKE_FLAGS += SQLITE_INCLUDE_DIR=$(ABS_DIST)/include
|
||||
ifdef NSS_DISABLE_DBM
|
||||
DEFAULT_GMAKE_FLAGS += NSS_DISABLE_DBM=1
|
||||
endif
|
||||
# Hack to force NSS build system to use "normal" object directories
|
||||
DEFAULT_GMAKE_FLAGS += topsrcdir='$(topsrcdir)'
|
||||
# topsrcdir can't be expanded here because msys path mangling likes to break
|
||||
# paths in that case.
|
||||
DEFAULT_GMAKE_FLAGS += BUILD='$(MOZ_BUILD_ROOT)/security/$$(subst $$(topsrcdir)/security/,,$$(CURDIR))'
|
||||
DEFAULT_GMAKE_FLAGS += BUILD_TREE='$$(BUILD)' OBJDIR='$$(BUILD)' DEPENDENCIES='$$(BUILD)/.deps' SINGLE_SHLIB_DIR='$$(BUILD)'
|
||||
DEFAULT_GMAKE_FLAGS += SOURCE_XP_DIR=$(ABS_DIST)
|
||||
ifndef MOZ_DEBUG
|
||||
DEFAULT_GMAKE_FLAGS += BUILD_OPT=1 OPT_CODE_SIZE=1
|
||||
endif
|
||||
ifdef GNU_CC
|
||||
DEFAULT_GMAKE_FLAGS += NS_USE_GCC=1
|
||||
else
|
||||
DEFAULT_GMAKE_FLAGS += NS_USE_GCC=
|
||||
endif
|
||||
ifdef USE_N32
|
||||
# It is not really necessary to specify USE_PTHREADS=1. USE_PTHREADS
|
||||
# merely adds _PTH to coreconf's OBJDIR name.
|
||||
DEFAULT_GMAKE_FLAGS += USE_N32=1 USE_PTHREADS=1
|
||||
endif
|
||||
ifdef HAVE_64BIT_BUILD
|
||||
DEFAULT_GMAKE_FLAGS += USE_64=1
|
||||
endif
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
DEFAULT_GMAKE_FLAGS += OS_TARGET=WIN95
|
||||
ifdef MOZ_DEBUG
|
||||
ifndef MOZ_NO_DEBUG_RTL
|
||||
DEFAULT_GMAKE_FLAGS += USE_DEBUG_RTL=1
|
||||
endif
|
||||
endif
|
||||
endif # WINNT
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
# Make nsinstall use absolute symlinks by default when building NSS
|
||||
# for Mozilla on Mac OS X. (Bugzilla bug 193164)
|
||||
ifndef NSDISTMODE
|
||||
DEFAULT_GMAKE_FLAGS += NSDISTMODE=absolute_symlink
|
||||
endif
|
||||
ifdef MACOS_SDK_DIR
|
||||
DEFAULT_GMAKE_FLAGS += MACOS_SDK_DIR=$(MACOS_SDK_DIR)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Turn off TLS compression support because it requires system zlib.
|
||||
# See bug 580679 comment 18.
|
||||
DEFAULT_GMAKE_FLAGS += NSS_SSL_ENABLE_ZLIB=
|
||||
|
||||
# Disable building of the test programs in security/nss/lib/zlib
|
||||
DEFAULT_GMAKE_FLAGS += PROGRAMS=
|
||||
|
||||
# Disable creating .chk files. They will be generated from packager.mk
|
||||
# When bug 681624 lands, we can replace CHECKLOC= with SKIP_SHLIBSIGN=1
|
||||
DEFAULT_GMAKE_FLAGS += CHECKLOC=
|
||||
|
||||
ifdef CROSS_COMPILE
|
||||
|
||||
DEFAULT_GMAKE_FLAGS += \
|
||||
NATIVE_CC='$(HOST_CC)' \
|
||||
CC='$(CC)' \
|
||||
CCC='$(CXX)' \
|
||||
AS='$(AS)' \
|
||||
AR='$(AR) $(AR_FLAGS:$@=$$@)' \
|
||||
RANLIB='$(RANLIB)' \
|
||||
RC='$(RC) $(RCFLAGS)' \
|
||||
OS_ARCH='$(OS_ARCH)' \
|
||||
OS_TEST='$(OS_TEST)' \
|
||||
CPU_ARCH='$(TARGET_CPU)' \
|
||||
$(NULL)
|
||||
|
||||
# Android has pthreads integrated into -lc, so OS_PTHREAD is set to nothing
|
||||
ifeq ($(OS_TARGET), Android)
|
||||
DEFAULT_GMAKE_FLAGS += \
|
||||
OS_RELEASE='2.6' \
|
||||
OS_PTHREAD= \
|
||||
$(NULL)
|
||||
|
||||
DEFAULT_GMAKE_FLAGS += ARCHFLAG='$(filter-out -W%,$(CFLAGS)) -DCHECK_FORK_GETPID $(addprefix -DANDROID_VERSION=,$(ANDROID_VERSION)) -include $(topsrcdir)/security/manager/android_stub.h'
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef WRAP_LDFLAGS
|
||||
NSS_EXTRA_LDFLAGS += $(WRAP_LDFLAGS)
|
||||
endif
|
||||
|
||||
# The SHARED_LIBS part is needed unconditionally on Android. It's not
|
||||
# clear why this is the case, but see bug 1133073 (starting around
|
||||
# comment #8) for context.
|
||||
ifneq (,$(or $(MOZ_GLUE_WRAP_LDFLAGS), $(filter Android, $(OS_TARGET))))
|
||||
NSS_EXTRA_LDFLAGS += $(SHARED_LIBS:$(DEPTH)%=$(MOZ_BUILD_ROOT)%) $(MOZ_GLUE_WRAP_LDFLAGS)
|
||||
endif
|
||||
|
||||
ifneq (,$(NSS_EXTRA_LDFLAGS))
|
||||
DEFAULT_GMAKE_FLAGS += \
|
||||
LDFLAGS='$(LDFLAGS) $(NSS_EXTRA_LDFLAGS)' \
|
||||
DSO_LDOPTS='$(DSO_LDOPTS) $(LDFLAGS) $(NSS_EXTRA_LDFLAGS)' \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
DEFAULT_GMAKE_FLAGS += FREEBL_NO_DEPEND=0 $(FREEBL_LOWHASH_FLAG)
|
||||
DEFAULT_GMAKE_FLAGS += NSS_ALLOW_SSLKEYLOGFILE=1
|
||||
|
||||
ifdef MOZ_NO_WLZDEFS
|
||||
DEFAULT_GMAKE_FLAGS += ZDEFS_FLAG=
|
||||
endif
|
||||
ifdef MOZ_CFLAGS_NSS
|
||||
NSS_XCFLAGS += $(filter-out -W%,$(CFLAGS))
|
||||
DEFAULT_GMAKE_FLAGS += DARWIN_DYLIB_VERSIONS='-compatibility_version 1 -current_version 1 $(LDFLAGS)'
|
||||
endif
|
||||
ifeq (1_1,$(CLANG_CL)_$(MOZ_ASAN))
|
||||
XLDFLAGS := $(OS_LDFLAGS)
|
||||
DEFAULT_GMAKE_FLAGS += XLDFLAGS='$(XLDFLAGS)'
|
||||
endif
|
||||
|
||||
DEFAULT_GMAKE_FLAGS += NSS_NO_PKCS11_BYPASS=1
|
||||
|
||||
# Put NSS headers directly under $(DIST)/include
|
||||
DEFAULT_GMAKE_FLAGS += PUBLIC_EXPORT_DIR='$(ABS_DIST)/include/$$(MODULE)'
|
||||
DEFAULT_GMAKE_FLAGS += SOURCE_XPHEADERS_DIR='$$(SOURCE_XP_DIR)/include/$$(MODULE)'
|
||||
DEFAULT_GMAKE_FLAGS += MODULE_INCLUDES='$$(addprefix -I$$(SOURCE_XP_DIR)/include/,$$(REQUIRES))'
|
||||
|
||||
# Work around NSS's MAKE_OBJDIR being racy. See bug #836220
|
||||
DEFAULT_GMAKE_FLAGS += MAKE_OBJDIR='$$(INSTALL) -D $$(OBJDIR)'
|
||||
|
||||
# Work around NSS adding IMPORT_LIBRARY to TARGETS with no rule for
|
||||
# it, creating race conditions. See bug #836220
|
||||
DEFAULT_GMAKE_FLAGS += TARGETS='$$(LIBRARY) $$(SHARED_LIBRARY) $$(PROGRAM)'
|
||||
|
||||
ifdef MOZ_FOLD_LIBS_FLAGS
|
||||
NSS_XCFLAGS += $(MOZ_FOLD_LIBS_FLAGS)
|
||||
endif
|
||||
|
||||
# Pass on the MSVC target arch from the main build system.
|
||||
# Note this is case- and switch-character sensitive, while
|
||||
# the MSVC option is not.
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
NSS_XCFLAGS += $(filter -arch:%,$(CFLAGS))
|
||||
endif
|
||||
|
||||
# Enable short header experiment. Firefox only.
|
||||
NSS_XCFLAGS += -DNSS_ENABLE_TLS13_SHORT_HEADERS
|
||||
|
||||
# Export accumulated XCFLAGS to modify nss defaults.
|
||||
DEFAULT_GMAKE_FLAGS += XCFLAGS='$(NSS_XCFLAGS)'
|
||||
|
||||
NSS_SRCDIR = $(topsrcdir)
|
||||
|
||||
NSS_DIRS =
|
||||
ifndef MOZ_FOLD_LIBS
|
||||
NSS_DIRS += nss/lib
|
||||
else
|
||||
ifndef NSS_DISABLE_DBM
|
||||
NSS_DIRS += nss/lib/dbm
|
||||
endif
|
||||
endif
|
||||
NSS_DIRS += \
|
||||
nss/cmd/lib \
|
||||
nss/cmd/shlibsign \
|
||||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
NSS_DIRS += \
|
||||
nss/cmd/certutil \
|
||||
nss/cmd/pk12util \
|
||||
nss/cmd/modutil \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifneq (,$(filter %--build-id,$(LDFLAGS)))
|
||||
DEFAULT_GMAKE_ENV = LDFLAGS=-Wl,--build-id
|
||||
endif
|
||||
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
# TODO: The following can be replaced by something simpler when bug 844880
|
||||
# is fixed.
|
||||
# All static libraries required for nss, smime, ssl and nssutil.
|
||||
# The strip is needed to remove potential linefeed characters, since they hang
|
||||
# around in some cases on Windows.
|
||||
NSS_STATIC_LIBS := $(strip $(shell $(MAKE) --no-print-directory -f $(srcdir)/nss.mk DEPTH='$(DEPTH)' topsrcdir='$(topsrcdir)' srcdir='$(srcdir)' echo-variable-libs))
|
||||
# Corresponding build directories
|
||||
NSS_STATIC_DIRS := $(foreach lib,$(NSS_STATIC_LIBS),$(patsubst %/,%,$(dir $(lib))))
|
||||
NSS_DIRS += $(NSS_STATIC_DIRS)
|
||||
|
||||
# TODO: The following can be replaced by something simpler when bug 844884
|
||||
# is fixed.
|
||||
# Remaining nss/lib directories
|
||||
NSS_DIRS += nss/lib/freebl nss/lib/softoken nss/lib/jar nss/lib/crmf nss/lib/ckfw
|
||||
|
||||
DEFAULT_GMAKE_FLAGS += NSS_DISABLE_LIBPKIX=1
|
||||
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
NSS_DIRS += nss/lib/zlib
|
||||
endif
|
||||
endif # MOZ_FOLD_LIBS
|
||||
|
||||
# Filter-out $(LIBRARY_NAME) because it's already handled in config/rules.mk.
|
||||
NSS_DIST_DLL_FILES := $(addprefix $(DIST)/lib/$(DLL_PREFIX),$(addsuffix $(DLL_SUFFIX),$(filter-out $(LIBRARY_NAME),$(NSS_DLLS)) $(NSS_EXTRA_DLLS)))
|
||||
NSS_DIST_DLL_DEST := $(DIST)/bin
|
||||
NSS_DIST_DLL_TARGET := target
|
||||
INSTALL_TARGETS += NSS_DIST_DLL
|
||||
|
||||
ifeq ($(OS_ARCH)_$(1), SunOS_softokn3)
|
||||
# has to use copy mode on Solaris, see #665509
|
||||
$(DIST)/bin/$(DLL_PREFIX)softokn3$(DLL_SUFFIX): INSTALL := $(NSINSTALL) -t
|
||||
endif
|
||||
|
||||
NSS_SDK_LIB_FILES := \
|
||||
$(addprefix $(DIST)/lib/$(LIB_PREFIX),$(addsuffix .$(LIB_SUFFIX),$(SDK_LIBS))) \
|
||||
$(addprefix $(DIST)/bin/$(DLL_PREFIX),$(addsuffix $(DLL_SUFFIX),$(NSS_DLLS))) \
|
||||
$(NULL)
|
||||
NSS_SDK_LIB_DEST := $(DIST)/sdk/lib
|
||||
NSS_SDK_LIB_TARGET := target
|
||||
INSTALL_TARGETS += NSS_SDK_LIB
|
||||
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
# Add all static libraries for nss, smime, ssl and nssutil
|
||||
STATIC_LIBS += $(addprefix $(DEPTH)/security/,$(NSS_STATIC_LIBS))
|
||||
|
||||
IMPORT_LIB_FILES = $(IMPORT_LIBRARY)
|
||||
IMPORT_LIB_DEST ?= $(DIST)/lib
|
||||
IMPORT_LIB_TARGET = target
|
||||
INSTALL_TARGETS += IMPORT_LIB
|
||||
|
||||
endif # MOZ_FOLD_LIBS
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifeq (1,$(ALLOW_COMPILER_WARNINGS))
|
||||
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_WERROR=0
|
||||
endif
|
||||
|
||||
# Can't pass this in DEFAULT_GMAKE_FLAGS because that overrides
|
||||
# definitions in NSS, so just export it into the sub-make's environment.
|
||||
ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_MEMORY))
|
||||
DLLFLAGS := -LIBPATH:$(ABS_DIST)/../mozglue/build -DEFAULTLIB:mozglue
|
||||
export DLLFLAGS
|
||||
endif
|
||||
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
# Force the linker to include everything from the static libraries.
|
||||
EXPAND_LIBS_EXEC += --extract
|
||||
|
||||
$(SHARED_LIBRARY): $(addprefix $(DEPTH)/security/,$(NSS_STATIC_LIBS))
|
||||
|
||||
ifdef IMPORT_LIB_SUFFIX
|
||||
IMPORT_PREFIX = $(LIB_PREFIX)
|
||||
IMPORT_SUFFIX = .$(IMPORT_LIB_SUFFIX)
|
||||
else
|
||||
IMPORT_PREFIX = $(DLL_PREFIX)
|
||||
IMPORT_SUFFIX = $(DLL_SUFFIX)
|
||||
endif
|
||||
|
||||
NSPR_IMPORT_LIBS = $(addprefix $(DIST)/lib/$(IMPORT_PREFIX),$(addsuffix $(IMPORT_SUFFIX),nspr4 plc4 plds4))
|
||||
SQLITE_IMPORT_LIB = $(DIST)/lib/$(IMPORT_PREFIX)mozsqlite3$(IMPORT_SUFFIX)
|
||||
|
||||
# TODO: The following can be replaced by something simpler when bug 844884
|
||||
# is fixed.
|
||||
# Associate target files with the rules that build them.
|
||||
$(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX): libs-nss/lib/crmf
|
||||
$(DIST)/lib/$(DLL_PREFIX)freebl3$(DLL_SUFFIX): libs-nss/lib/freebl
|
||||
$(DIST)/lib/$(DLL_PREFIX)nssckbi$(DLL_SUFFIX): libs-nss/lib/ckfw
|
||||
$(DIST)/lib/$(DLL_PREFIX)softokn3$(DLL_SUFFIX): libs-nss/lib/softoken
|
||||
$(DIST)/lib/$(DLL_PREFIX)nssdbm3$(DLL_SUFFIX): libs-nss/lib/softoken
|
||||
$(foreach lib,$(NSS_STATIC_LIBS),$(eval $(DEPTH)/security/$(lib): libs-$(patsubst %/,%,$(dir $(lib)))))
|
||||
|
||||
# Create fake import libraries for the folded libraries, so that linking
|
||||
# against them works both for the NSS build system (see dependencies below)
|
||||
# and for the rest of the mozilla build system.
|
||||
$(NSPR_IMPORT_LIBS) \
|
||||
$(SQLITE_IMPORT_LIB) \
|
||||
$(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX) \
|
||||
$(DIST)/lib/$(IMPORT_PREFIX)ssl3$(IMPORT_SUFFIX) \
|
||||
$(DIST)/lib/$(IMPORT_PREFIX)smime3$(IMPORT_SUFFIX): $(DIST)/lib/$(IMPORT_PREFIX)nss3$(IMPORT_SUFFIX)
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
cp $< $@
|
||||
else
|
||||
ln -sf $< $@
|
||||
endif
|
||||
|
||||
# Interdependencies between nss sub-directories, and dependencies on NSPR/SQLite
|
||||
libs-nss/lib/ckfw: libs-nss/lib/nss/../base $(NSPR_IMPORT_LIBS)
|
||||
libs-nss/lib/softoken: $(NSPR_IMPORT_LIBS) $(SQLITE_IMPORT_LIB)
|
||||
libs-nss/lib/softoken: libs-nss/lib/freebl
|
||||
ifndef NSS_DISABLE_DBM
|
||||
libs-nss/lib/softoken: libs-nss/lib/dbm
|
||||
endif
|
||||
libs-nss/lib/softoken: $(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX)
|
||||
libs-nss/lib/freebl: $(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX) $(NSPR_IMPORT_LIBS)
|
||||
|
||||
# For each directory where we build static libraries, force the NSS build system
|
||||
# to only build static libraries.
|
||||
$(addprefix libs-,$(NSS_STATIC_DIRS)): DEFAULT_GMAKE_FLAGS += SHARED_LIBRARY= IMPORT_LIBRARY=
|
||||
else
|
||||
$(STATIC_LIBS) $(NSS_DIST_DLL_FILES) $(NSS_SDK_LIB_FILES): libs-nss/lib
|
||||
endif # MOZ_FOLD_LIBS
|
||||
|
||||
ifeq ($(NSINSTALL_PY),$(NSINSTALL))
|
||||
DEFAULT_GMAKE_FLAGS += PYTHON='$(PYTHON)'
|
||||
DEFAULT_GMAKE_FLAGS += NSINSTALL_PY='$(abspath $(topsrcdir)/config/nsinstall.py)'
|
||||
DEFAULT_GMAKE_FLAGS += NSINSTALL='$$(PYTHON) $$(NSINSTALL_PY)'
|
||||
else
|
||||
DEFAULT_GMAKE_FLAGS += NSINSTALL='$(abspath $(NSINSTALL))'
|
||||
endif
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
DEFAULT_GMAKE_FLAGS += INSTALL='$$(NSINSTALL) -t'
|
||||
endif
|
||||
DEFAULT_GMAKE_FLAGS += $(EXTRA_GMAKE_FLAGS)
|
||||
|
||||
$(addprefix libs-,$(NSS_DIRS)): libs-%:
|
||||
# Work around NSS's export rule being racy when recursing for private_export
|
||||
# See bug #836220.
|
||||
$(addprefix export-,$(NSS_DIRS)): EXTRA_GMAKE_FLAGS = PRIVATE_EXPORTS=
|
||||
$(addprefix export-,$(NSS_DIRS)): export-%: private_export-%
|
||||
$(addprefix private_export-,$(NSS_DIRS)): EXTRA_GMAKE_FLAGS =
|
||||
$(addprefix private_export-,$(NSS_DIRS)): private_export-%:
|
||||
|
||||
$(foreach p,libs export private_export,$(addprefix $(p)-,$(NSS_DIRS))):
|
||||
$(DEFAULT_GMAKE_ENV) $(MAKE) -C $(NSS_SRCDIR)/security/$* $(@:-$*=) $(DEFAULT_GMAKE_FLAGS)
|
||||
|
||||
export:: $(addprefix export-,$(NSS_DIRS))
|
||||
|
||||
$(addprefix clean-,$(NSS_DIRS)): clean-%:
|
||||
$(MAKE) -C $(NSS_SRCDIR)/security/$* $(DEFAULT_GMAKE_FLAGS) clean
|
||||
|
||||
clean clobber clobber_all realclean distclean depend:: $(addprefix clean-,$(NSS_DIRS))
|
||||
|
||||
NSS_CMD_TARGETS := $(addprefix libs-,$(filter-out nss/cmd/lib,$(filter nss/cmd/%,$(NSS_DIRS))))
|
||||
target:: $(NSS_CMD_TARGETS)
|
||||
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
$(NSS_CMD_TARGETS): $(addprefix $(DIST)/lib/$(IMPORT_PREFIX),$(addsuffix $(IMPORT_SUFFIX),$(NSS_LIBS)))
|
||||
libs-nss/cmd/modutil: libs-nss/lib/jar
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
libs-nss/cmd/modutil: libs-nss/lib/zlib
|
||||
endif
|
||||
$(NSS_CMD_TARGETS): libs-nss/cmd/lib
|
||||
else
|
||||
$(NSS_CMD_TARGETS): libs-nss/lib libs-nss/cmd/lib
|
||||
endif # MOZ_FOLD_LIBS
|
||||
|
||||
# Work around NSS build system race condition creating certdata.c in
|
||||
# security/nss/lib/ckfw/builtins. See bug #836220.
|
||||
libs-nss/lib$(if $(MOZ_FOLD_LIBS),/ckfw): $(call mkdir_deps,$(DEPTH)/security/nss/lib/ckfw/builtins)
|
||||
|
||||
Vendored
-15
@@ -1,15 +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/.
|
||||
|
||||
Library('crmf')
|
||||
|
||||
USE_LIBS += [
|
||||
# The dependency on nss is not real, but is required to force the
|
||||
# parent directory being built before this one. This has no
|
||||
# practical effect on linkage, since the only thing linking crmf
|
||||
# will need nss anyways.
|
||||
'nss',
|
||||
'static:/security/nss/lib/crmf/crmf',
|
||||
]
|
||||
Vendored
-39
@@ -1,39 +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/.
|
||||
|
||||
DIRS += ['crmf']
|
||||
|
||||
if CONFIG['MOZ_FOLD_LIBS']:
|
||||
GeckoSharedLibrary('nss', linkage=None)
|
||||
# TODO: The library name can be changed when bug 845217 is fixed.
|
||||
SHARED_LIBRARY_NAME = 'nss3'
|
||||
|
||||
SDK_LIBRARY = True
|
||||
|
||||
USE_LIBS += [
|
||||
'nspr4',
|
||||
'plc4',
|
||||
'plds4',
|
||||
]
|
||||
|
||||
OS_LIBS += CONFIG['REALTIME_LIBS']
|
||||
|
||||
SYMBOLS_FILE = 'nss.symbols'
|
||||
else:
|
||||
Library('nss')
|
||||
USE_LIBS += [
|
||||
'/security/nss/lib/nss/nss3',
|
||||
'/security/nss/lib/smime/smime3',
|
||||
'/security/nss/lib/ssl/ssl3',
|
||||
'/security/nss/lib/util/nssutil3',
|
||||
]
|
||||
|
||||
USE_LIBS += ['sqlite']
|
||||
|
||||
# XXX: We should fix these warnings.
|
||||
ALLOW_COMPILER_WARNINGS = True
|
||||
|
||||
if CONFIG['NSS_EXTRA_SYMBOLS_FILE']:
|
||||
DEFINES['NSS_EXTRA_SYMBOLS_FILE'] = CONFIG['NSS_EXTRA_SYMBOLS_FILE']
|
||||
Vendored
-27
@@ -1,27 +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 $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
dirs :=
|
||||
|
||||
define add_dirs
|
||||
SHARED_LIBRARY_DIRS :=
|
||||
include $(topsrcdir)/security/$(1)/config.mk
|
||||
dirs += $$(addprefix $(1)/,$$(SHARED_LIBRARY_DIRS)) $(1)
|
||||
endef
|
||||
$(foreach dir,util nss ssl smime,$(eval $(call add_dirs,nss/lib/$(dir))))
|
||||
|
||||
libs :=
|
||||
define add_lib
|
||||
LIBRARY_NAME :=
|
||||
include $(topsrcdir)/security/$(1)/manifest.mn
|
||||
libs += $$(addprefix $(1)/,$(LIB_PREFIX)$$(LIBRARY_NAME).$(LIB_SUFFIX))
|
||||
endef
|
||||
$(foreach dir,$(dirs),$(eval $(call add_lib,$(dir))))
|
||||
|
||||
echo-variable-%:
|
||||
@echo $($*)
|
||||
@@ -8,9 +8,7 @@
|
||||
#ifndef mozilla_${HEADER}_h
|
||||
#define mozilla_${HEADER}_h
|
||||
|
||||
// For some reason, Apple's GCC refuses to honor -fno-exceptions when
|
||||
// compiling ObjC.
|
||||
#if defined(__EXCEPTIONS) && __EXCEPTIONS && !(__OBJC__ && __GNUC__ && XP_IOS)
|
||||
#if defined(__EXCEPTIONS) && __EXCEPTIONS
|
||||
# error "STL code can only be used with -fno-exceptions"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
# -*- makefile -*-
|
||||
# vim:set ts=8 sw=8 sts=8 noet:
|
||||
#
|
||||
# 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 INCLUDED_JAVA_BUILD_MK #{
|
||||
|
||||
ifdef JAVAFILES #{
|
||||
GENERATED_DIRS += classes
|
||||
|
||||
export:: classes
|
||||
classes: $(call mkdir_deps,classes)
|
||||
endif #} JAVAFILES
|
||||
|
||||
default_bootclasspath_jars := \
|
||||
$(ANDROID_SDK)/android.jar \
|
||||
$(NULL)
|
||||
|
||||
default_classpath_jars := \
|
||||
$(NULL)
|
||||
|
||||
# Turn a possibly empty list of JAR files into a Java classpath, like a.jar:b.jar.
|
||||
# Arg 1: Possibly empty list of JAR files.
|
||||
define classpath_template
|
||||
$(subst $(NULL) ,:,$(strip $(1)))
|
||||
endef
|
||||
|
||||
ifdef ANDROID_APK_NAME #{
|
||||
$(if $(ANDROID_APK_PACKAGE),,$(error Missing ANDROID_APK_PACKAGE with ANDROID_APK_NAME))
|
||||
|
||||
android_res_dirs := $(or $(ANDROID_RES_DIRS),$(srcdir)/res)
|
||||
_ANDROID_RES_FLAG := $(addprefix -S ,$(android_res_dirs))
|
||||
_ANDROID_ASSETS_FLAG := $(if $(ANDROID_ASSETS_DIRS),$(addprefix -A ,$(ANDROID_ASSETS_DIRS)))
|
||||
android_manifest := $(or $(ANDROID_MANIFEST_FILE),AndroidManifest.xml)
|
||||
|
||||
GENERATED_DIRS += classes generated
|
||||
|
||||
generated_r_java := generated/$(subst .,/,$(ANDROID_APK_PACKAGE))/R.java
|
||||
|
||||
classes.dex: $(call mkdir_deps,classes)
|
||||
classes.dex: $(generated_r_java)
|
||||
classes.dex: $(ANDROID_APK_NAME).ap_
|
||||
classes.dex: $(default_classpath_jars) $(ANDROID_CLASSPATH_JARS)
|
||||
classes.dex: $(default_bootclasspath_jars) $(ANDROID_BOOTCLASSPATH_JARS) $(ANDROID_EXTRA_JARS)
|
||||
classes.dex: $(JAVAFILES)
|
||||
$(JAVAC) $(JAVAC_FLAGS) -d classes $(filter %.java,$^) \
|
||||
$(addprefix -bootclasspath ,$(call classpath_template,$(default_bootclasspath_jars) $(ANDROID_BOOTCLASSPATH_JARS))) \
|
||||
$(addprefix -classpath ,$(call classpath_template,$(default_classpath_jars) $(ANDROID_CLASSPATH_JARS) $(ANDROID_EXTRA_JARS)))
|
||||
$(DX) --dex --output=$@ classes $(ANDROID_EXTRA_JARS)
|
||||
|
||||
# R.java and $(ANDROID_APK_NAME).ap_ are both produced by aapt. To
|
||||
# save an aapt invocation, we produce them both at the same time. The
|
||||
# trailing semi-colon defines an empty recipe; defining no recipe at
|
||||
# all causes Make to treat the target differently, in a way that
|
||||
# defeats our dependencies.
|
||||
|
||||
$(generated_r_java): .aapt.deps ;
|
||||
$(ANDROID_APK_NAME).ap_: .aapt.deps ;
|
||||
|
||||
# This uses the fact that Android resource directories list all
|
||||
# resource files one subdirectory below the parent resource directory.
|
||||
android_res_files := $(wildcard $(addsuffix /*,$(wildcard $(addsuffix /*,$(android_res_dirs)))))
|
||||
|
||||
# An extra package like org.example.app generates dependencies like:
|
||||
# generated/org/example/app/R.java: .aapt.deps ;
|
||||
# classes.dex: generated/org/example/app/R.java
|
||||
# GARBAGE: generated/org/example/app/R.java
|
||||
$(foreach extra_package,$(ANDROID_EXTRA_PACKAGES), \
|
||||
$(eval generated/$(subst .,/,$(extra_package))/R.java: .aapt.deps ;) \
|
||||
$(eval classes.dex: generated/$(subst .,/,$(extra_package))/R.java) \
|
||||
$(eval GARBAGE: generated/$(subst .,/,$(extra_package))/R.java) \
|
||||
)
|
||||
|
||||
# aapt flag -m: 'make package directories under location specified by -J'.
|
||||
# The --extra-package list is colon separated.
|
||||
.aapt.deps: $(android_manifest) $(android_res_files) $(wildcard $(ANDROID_ASSETS_DIRS))
|
||||
@$(TOUCH) $@
|
||||
$(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar $(_ANDROID_RES_FLAG) $(_ANDROID_ASSETS_FLAG) \
|
||||
--custom-package $(ANDROID_APK_PACKAGE) \
|
||||
--non-constant-id \
|
||||
--auto-add-overlay \
|
||||
$(if $(ANDROID_EXTRA_PACKAGES),--extra-packages $(subst $(NULL) ,:,$(strip $(ANDROID_EXTRA_PACKAGES)))) \
|
||||
$(if $(ANDROID_EXTRA_RES_DIRS),$(addprefix -S ,$(ANDROID_EXTRA_RES_DIRS))) \
|
||||
-m \
|
||||
-J ${@D}/generated \
|
||||
-F $(ANDROID_APK_NAME).ap_
|
||||
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk: $(ANDROID_APK_NAME).ap_ classes.dex
|
||||
cp $< $@
|
||||
$(ZIP) -0 $@ classes.dex
|
||||
|
||||
$(ANDROID_APK_NAME)-unaligned.apk: $(ANDROID_APK_NAME)-unsigned-unaligned.apk
|
||||
cp $< $@
|
||||
$(DEBUG_JARSIGNER) $@
|
||||
|
||||
$(ANDROID_APK_NAME).apk: $(ANDROID_APK_NAME)-unaligned.apk
|
||||
$(ZIPALIGN) -f 4 $< $@
|
||||
|
||||
GARBAGE += \
|
||||
$(generated_r_java) \
|
||||
classes.dex \
|
||||
$(ANDROID_APK_NAME).ap_ \
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk \
|
||||
$(ANDROID_APK_NAME)-unaligned.apk \
|
||||
$(ANDROID_APK_NAME).apk \
|
||||
$(NULL)
|
||||
|
||||
# Include Android specific java flags, instead of what's in rules.mk.
|
||||
include $(topsrcdir)/config/android-common.mk
|
||||
endif #} ANDROID_APK_NAME
|
||||
|
||||
|
||||
ifdef JAVA_JAR_TARGETS #{
|
||||
# Arg 1: Output target name with .jar suffix, like jars/jarfile.jar.
|
||||
# Intermediate class files are generated in jars/jarfile-classes.
|
||||
# Arg 2: Java sources list. We use VPATH and $^ so sources can be
|
||||
# relative to $(srcdir) or $(CURDIR).
|
||||
# Arg 3: List of extra jars to link against. We do not use VPATH so
|
||||
# jars must be relative to $(CURDIR).
|
||||
# Arg 4: Additional JAVAC_FLAGS.
|
||||
|
||||
# Note: Proguard fails when stale .class files corresponding to
|
||||
# removed inner classes are present in the object directory. These
|
||||
# stale class files get packaged into the .jar file, which then gets
|
||||
# processed by Proguard. To work around this, we always delete any
|
||||
# existing jarfile-classes directory and start fresh.
|
||||
|
||||
define java_jar_template
|
||||
$(1): $(2) $(3) $(default_bootclasspath_jars) $(default_classpath_jars)
|
||||
$$(REPORT_BUILD)
|
||||
@$$(RM) -rf $(1:.jar=)-classes
|
||||
@$$(NSINSTALL) -D $(1:.jar=)-classes
|
||||
@$$(if $$(filter-out .,$$(@D)),$$(NSINSTALL) -D $$(@D))
|
||||
$$(JAVAC) $$(JAVAC_FLAGS)\
|
||||
$(4)\
|
||||
-d $(1:.jar=)-classes\
|
||||
$(addprefix -bootclasspath ,$(call classpath_template,$(default_bootclasspath_jars)))\
|
||||
$(addprefix -classpath ,$(call classpath_template,$(default_classpath_jars) $(3)))\
|
||||
$$(filter %.java,$$^)
|
||||
$$(JAR) cMf $$@ -C $(1:.jar=)-classes .
|
||||
|
||||
GARBAGE += $(1)
|
||||
|
||||
GARBAGE_DIRS += $(1:.jar=)-classes
|
||||
endef
|
||||
|
||||
$(foreach jar,$(JAVA_JAR_TARGETS),\
|
||||
$(if $($(jar)_DEST),,$(error Missing $(jar)_DEST))\
|
||||
$(if $($(jar)_JAVAFILES) $($(jar)_PP_JAVAFILES),,$(error Must provide at least one of $(jar)_JAVAFILES and $(jar)_PP_JAVAFILES))\
|
||||
$(eval $(call java_jar_template,$($(jar)_DEST),$($(jar)_JAVAFILES) $($(jar)_PP_JAVAFILES),$($(jar)_EXTRA_JARS),$($(jar)_JAVAC_FLAGS)))\
|
||||
)
|
||||
endif #} JAVA_JAR_TARGETS
|
||||
|
||||
|
||||
INCLUDED_JAVA_BUILD_MK := 1
|
||||
|
||||
endif #} INCLUDED_JAVA_BUILD_MK
|
||||
@@ -1,4 +1,4 @@
|
||||
# Holds the current milestone.
|
||||
# Holds the current platform (Goanna) milestone.
|
||||
# Should be in the format of
|
||||
#
|
||||
# x.x.x
|
||||
@@ -6,8 +6,6 @@
|
||||
# x.x.x+
|
||||
#
|
||||
# Referenced by milestone.py.
|
||||
# Hopefully I'll be able to automate replacement of *all*
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
4.8.0
|
||||
5.1.0+
|
||||
+1
-8
@@ -144,16 +144,9 @@ ifeq (.,$(DEPTH))
|
||||
js/xpconnect/src/export: dom/bindings/export xpcom/xpidl/export
|
||||
accessible/xpcom/export: xpcom/xpidl/export
|
||||
|
||||
# The widget binding generator code is part of the annotationProcessors.
|
||||
widget/android/bindings/export: build/annotationProcessors/export
|
||||
|
||||
# .xpt generation needs the xpidl lex/yacc files
|
||||
xpcom/xpidl/export: xpcom/idl-parser/xpidl/export
|
||||
|
||||
# The roboextender addon includes a classes.dex containing a test Java addon.
|
||||
# The test addon must be built first.
|
||||
mobile/android/tests/browser/robocop/roboextender/tools: mobile/android/tests/javaaddons/tools
|
||||
|
||||
ifdef ENABLE_CLANG_PLUGIN
|
||||
$(filter-out config/host build/unix/stdc++compat/% build/clang-plugin/%,$(compile_targets)): build/clang-plugin/target build/clang-plugin/tests/target
|
||||
build/clang-plugin/tests/target: build/clang-plugin/target
|
||||
@@ -165,7 +158,7 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),gtk3)
|
||||
toolkit/library/target: widget/gtk/mozgtk/gtk3/target
|
||||
endif
|
||||
ifdef MOZ_LDAP_XPCOM
|
||||
ldap/target: config/external/nss/target mozglue/build/target
|
||||
ldap/target: security/target mozglue/build/target
|
||||
toolkit/library/target: ldap/target
|
||||
endif
|
||||
ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library)
|
||||
|
||||
@@ -1045,13 +1045,6 @@ else
|
||||
normalizepath = $(1)
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
# Java rules
|
||||
###############################################################################
|
||||
ifneq (,$(JAVAFILES)$(ANDROID_RESFILES)$(ANDROID_APKNAME)$(JAVA_JAR_TARGETS))
|
||||
include $(MOZILLA_DIR)/config/makefiles/java-build.mk
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
# Bunch of things that extend the 'export' rule (in order):
|
||||
###############################################################################
|
||||
|
||||
@@ -235,8 +235,8 @@ for ($j = 1; $j < 4; $j++)
|
||||
my $winappversion = "$appver[0],$appver[1],$appver[2],$appver[3]";
|
||||
|
||||
my $copyright = "License: MPL 2.0";
|
||||
my $company = "Moonchild Productions";
|
||||
my $trademarks = "Moonchild";
|
||||
my $company = "UXP Contributors";
|
||||
my $trademarks = "Goanna is (tm) Moonchild Productions";
|
||||
my $productname = "UXP";
|
||||
|
||||
|
||||
|
||||
+11076
-6076
File diff suppressed because it is too large.
Load diff
+218
-39
@@ -123,9 +123,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.33.0"
|
||||
#define SQLITE_VERSION_NUMBER 3033000
|
||||
#define SQLITE_SOURCE_ID "2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f"
|
||||
#define SQLITE_VERSION "3.36.0"
|
||||
#define SQLITE_VERSION_NUMBER 3036000
|
||||
#define SQLITE_SOURCE_ID "2021-06-18 18:36:39 5c9a6c06871cb9fe42814af9c039eb6da5427a6ec28f187af7ebfb62eafa66e5"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -504,6 +504,7 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
|
||||
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
||||
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
||||
#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
@@ -1127,6 +1128,23 @@ struct sqlite3_io_methods {
|
||||
** file to the database file, but before the *-shm file is updated to
|
||||
** record the fact that the pages have been checkpointed.
|
||||
** </ul>
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_EXTERNAL_READER]]
|
||||
** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
|
||||
** whether or not there is a database client in another process with a wal-mode
|
||||
** transaction open on the database or not. It is only available on unix.The
|
||||
** (void*) argument passed with this file-control should be a pointer to a
|
||||
** value of type (int). The integer value is set to 1 if the database is a wal
|
||||
** mode database and there exists at least one client in another process that
|
||||
** currently has an SQL transaction open on the database. It is set to 0 if
|
||||
** the database is not a wal-mode db, or if there is no such connection in any
|
||||
** other process. This opcode cannot be used to detect transactions opened
|
||||
** by clients within the current process, only within other processes.
|
||||
** </ul>
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
|
||||
** Used by the cksmvfs VFS module only.
|
||||
** </ul>
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
|
||||
@@ -1166,6 +1184,8 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_CKPT_DONE 37
|
||||
#define SQLITE_FCNTL_RESERVE_BYTES 38
|
||||
#define SQLITE_FCNTL_CKPT_START 39
|
||||
#define SQLITE_FCNTL_EXTERNAL_READER 40
|
||||
#define SQLITE_FCNTL_CKSM_FILE 41
|
||||
|
||||
/* deprecated names */
|
||||
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
||||
@@ -2114,7 +2134,13 @@ struct sqlite3_mem_methods {
|
||||
** The second parameter is a pointer to an integer into which
|
||||
** is written 0 or 1 to indicate whether triggers are disabled or enabled
|
||||
** following this call. The second parameter may be a NULL pointer, in
|
||||
** which case the trigger setting is not reported back. </dd>
|
||||
** which case the trigger setting is not reported back.
|
||||
**
|
||||
** <p>Originally this option disabled all triggers. ^(However, since
|
||||
** SQLite version 3.35.0, TEMP triggers are still allowed even if
|
||||
** this option is off. So, in other words, this option now only disables
|
||||
** triggers in the main database schema or in the schemas of ATTACH-ed
|
||||
** databases.)^ </dd>
|
||||
**
|
||||
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
|
||||
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
|
||||
@@ -2125,7 +2151,13 @@ struct sqlite3_mem_methods {
|
||||
** The second parameter is a pointer to an integer into which
|
||||
** is written 0 or 1 to indicate whether views are disabled or enabled
|
||||
** following this call. The second parameter may be a NULL pointer, in
|
||||
** which case the view setting is not reported back. </dd>
|
||||
** which case the view setting is not reported back.
|
||||
**
|
||||
** <p>Originally this option disabled all views. ^(However, since
|
||||
** SQLite version 3.35.0, TEMP views are still allowed even if
|
||||
** this option is off. So, in other words, this option now only disables
|
||||
** views in the main database schema or in the schemas of ATTACH-ed
|
||||
** databases.)^ </dd>
|
||||
**
|
||||
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
|
||||
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
|
||||
@@ -3498,6 +3530,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** that uses dot-files in place of posix advisory locking.
|
||||
** <tr><td> file:data.db?mode=readonly <td>
|
||||
** An error. "readonly" is not a valid option for the "mode" parameter.
|
||||
** Use "ro" instead: "file:data.db?mode=ro".
|
||||
** </table>
|
||||
**
|
||||
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
|
||||
@@ -3696,7 +3729,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
|
||||
** If the Y parameter to sqlite3_free_filename(Y) is anything other
|
||||
** than a NULL pointer or a pointer previously acquired from
|
||||
** sqlite3_create_filename(), then bad things such as heap
|
||||
** corruption or segfaults may occur. The value Y should be
|
||||
** corruption or segfaults may occur. The value Y should not be
|
||||
** used again after sqlite3_free_filename(Y) has been called. This means
|
||||
** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y,
|
||||
** then the corresponding [sqlite3_module.xClose() method should also be
|
||||
@@ -4165,6 +4198,15 @@ SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
|
||||
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
|
||||
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
|
||||
** sqlite3_stmt_readonly() returns false for those commands.
|
||||
**
|
||||
** ^This routine returns false if there is any possibility that the
|
||||
** statement might change the database file. ^A false return does
|
||||
** not guarantee that the statement will change the database file.
|
||||
** ^For example, an UPDATE statement might have a WHERE clause that
|
||||
** makes it a no-op, but the sqlite3_stmt_readonly() result would still
|
||||
** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
|
||||
** read-only no-op if the table already exists, but
|
||||
** sqlite3_stmt_readonly() still returns false for such a statement.
|
||||
*/
|
||||
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
||||
|
||||
@@ -4334,18 +4376,22 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** contain embedded NULs. The result of expressions involving strings
|
||||
** with embedded NULs is undefined.
|
||||
**
|
||||
** ^The fifth argument to the BLOB and string binding interfaces
|
||||
** is a destructor used to dispose of the BLOB or
|
||||
** string after SQLite has finished with it. ^The destructor is called
|
||||
** to dispose of the BLOB or string even if the call to the bind API fails,
|
||||
** except the destructor is not called if the third parameter is a NULL
|
||||
** pointer or the fourth parameter is negative.
|
||||
** ^If the fifth argument is
|
||||
** the special value [SQLITE_STATIC], then SQLite assumes that the
|
||||
** information is in static, unmanaged space and does not need to be freed.
|
||||
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
|
||||
** SQLite makes its own private copy of the data immediately, before
|
||||
** the sqlite3_bind_*() routine returns.
|
||||
** ^The fifth argument to the BLOB and string binding interfaces controls
|
||||
** or indicates the lifetime of the object referenced by the third parameter.
|
||||
** These three options exist:
|
||||
** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
|
||||
** with it may be passed. ^It is called to dispose of the BLOB or string even
|
||||
** if the call to the bind API fails, except the destructor is not called if
|
||||
** the third parameter is a NULL pointer or the fourth parameter is negative.
|
||||
** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
|
||||
** the application remains responsible for disposing of the object. ^In this
|
||||
** case, the object and the provided pointer to it must remain valid until
|
||||
** either the prepared statement is finalized or the same SQL parameter is
|
||||
** bound to something else, whichever occurs sooner.
|
||||
** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
|
||||
** object is to be copied prior to the return from sqlite3_bind_*(). ^The
|
||||
** object and pointer to it must remain valid until then. ^SQLite will then
|
||||
** manage the lifetime of its private copy.
|
||||
**
|
||||
** ^The sixth argument to sqlite3_bind_text64() must be one of
|
||||
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
|
||||
@@ -5087,7 +5133,6 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
|
||||
** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
|
||||
** index expressions, or the WHERE clause of partial indexes.
|
||||
**
|
||||
** <span style="background-color:#ffff90;">
|
||||
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
|
||||
** all application-defined SQL functions that do not need to be
|
||||
** used inside of triggers, view, CHECK constraints, or other elements of
|
||||
@@ -5097,7 +5142,6 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
|
||||
** a database file to include invocations of the function with parameters
|
||||
** chosen by the attacker, which the application will then execute when
|
||||
** the database file is opened and read.
|
||||
** </span>
|
||||
**
|
||||
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
|
||||
** function can gain access to this pointer using [sqlite3_user_data()].)^
|
||||
@@ -6186,6 +6230,57 @@ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
|
||||
*/
|
||||
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine the transaction state of a database
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_txn_state(D,S) interface returns the current
|
||||
** [transaction state] of schema S in database connection D. ^If S is NULL,
|
||||
** then the highest transaction state of any schema on database connection D
|
||||
** is returned. Transaction states are (in order of lowest to highest):
|
||||
** <ol>
|
||||
** <li value="0"> SQLITE_TXN_NONE
|
||||
** <li value="1"> SQLITE_TXN_READ
|
||||
** <li value="2"> SQLITE_TXN_WRITE
|
||||
** </ol>
|
||||
** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
|
||||
** a valid schema, then -1 is returned.
|
||||
*/
|
||||
SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
|
||||
** KEYWORDS: {transaction state}
|
||||
**
|
||||
** These constants define the current transaction state of a database file.
|
||||
** ^The [sqlite3_txn_state(D,S)] interface returns one of these
|
||||
** constants in order to describe the transaction state of schema S
|
||||
** in [database connection] D.
|
||||
**
|
||||
** <dl>
|
||||
** [[SQLITE_TXN_NONE]] <dt>SQLITE_TXN_NONE</dt>
|
||||
** <dd>The SQLITE_TXN_NONE state means that no transaction is currently
|
||||
** pending.</dd>
|
||||
**
|
||||
** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt>
|
||||
** <dd>The SQLITE_TXN_READ state means that the database is currently
|
||||
** in a read transaction. Content has been read from the database file
|
||||
** but nothing in the database file has changed. The transaction state
|
||||
** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
|
||||
** no other conflicting concurrent write transactions. The transaction
|
||||
** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
|
||||
** [COMMIT].</dd>
|
||||
**
|
||||
** [[SQLITE_TXN_WRITE]] <dt>SQLITE_TXN_WRITE</dt>
|
||||
** <dd>The SQLITE_TXN_WRITE state means that the database is currently
|
||||
** in a write transaction. Content has been written to the database file
|
||||
** but has not yet committed. The transaction state will change to
|
||||
** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
|
||||
*/
|
||||
#define SQLITE_TXN_NONE 0
|
||||
#define SQLITE_TXN_READ 1
|
||||
#define SQLITE_TXN_WRITE 2
|
||||
|
||||
/*
|
||||
** CAPI3REF: Find the next prepared statement
|
||||
** METHOD: sqlite3
|
||||
@@ -7712,7 +7807,10 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
|
||||
#define SQLITE_TESTCTRL_PRNG_SEED 28
|
||||
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
|
||||
#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
|
||||
#define SQLITE_TESTCTRL_SEEK_COUNT 30
|
||||
#define SQLITE_TESTCTRL_TRACEFLAGS 31
|
||||
#define SQLITE_TESTCTRL_TUNE 32
|
||||
#define SQLITE_TESTCTRL_LAST 32 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Keyword Checking
|
||||
@@ -9192,10 +9290,11 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
|
||||
**
|
||||
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
|
||||
** method of a [virtual table], then it returns true if and only if the
|
||||
** method of a [virtual table], then it might return true if the
|
||||
** column is being fetched as part of an UPDATE operation during which the
|
||||
** column value will not change. Applications might use this to substitute
|
||||
** a return value that is less expensive to compute and that the corresponding
|
||||
** column value will not change. The virtual table implementation can use
|
||||
** this hint as permission to substitute a return value that is less
|
||||
** expensive to compute and that the corresponding
|
||||
** [xUpdate] method understands as a "no-change" value.
|
||||
**
|
||||
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
|
||||
@@ -9204,6 +9303,12 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
|
||||
** In that case, [sqlite3_value_nochange(X)] will return true for the
|
||||
** same column in the [xUpdate] method.
|
||||
**
|
||||
** The sqlite3_vtab_nochange() routine is an optimization. Virtual table
|
||||
** implementations should continue to give a correct answer even if the
|
||||
** sqlite3_vtab_nochange() interface were to always return false. In the
|
||||
** current implementation, the sqlite3_vtab_nochange() interface does always
|
||||
** returns false for the enhanced [UPDATE FROM] statement.
|
||||
*/
|
||||
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
|
||||
|
||||
@@ -9345,6 +9450,7 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flush caches to disk mid-transaction
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^If a write-transaction is open on [database connection] D when the
|
||||
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
|
||||
@@ -9377,6 +9483,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: The pre-update hook.
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^These interfaces are only available if SQLite is compiled using the
|
||||
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
|
||||
@@ -9417,7 +9524,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
|
||||
** seventh parameter is the final rowid value of the row being inserted
|
||||
** or updated. The value of the seventh parameter passed to the callback
|
||||
** function is not defined for operations on WITHOUT ROWID tables, or for
|
||||
** INSERT operations on rowid tables.
|
||||
** DELETE operations on rowid tables.
|
||||
**
|
||||
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
|
||||
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
|
||||
@@ -9455,6 +9562,15 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
|
||||
** triggers; or 2 for changes resulting from triggers called by top-level
|
||||
** triggers; and so forth.
|
||||
**
|
||||
** When the [sqlite3_blob_write()] API is used to update a blob column,
|
||||
** the pre-update hook is invoked with SQLITE_DELETE. This is because the
|
||||
** in this case the new values are not available. In this case, when a
|
||||
** callback made with op==SQLITE_DELETE is actuall a write using the
|
||||
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
|
||||
** the index of the column being written. In other cases, where the
|
||||
** pre-update hook is being invoked for some other reason, including a
|
||||
** regular DELETE, sqlite3_preupdate_blobwrite() returns -1.
|
||||
**
|
||||
** See also: [sqlite3_update_hook()]
|
||||
*/
|
||||
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
|
||||
@@ -9475,10 +9591,12 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
|
||||
SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
|
||||
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
|
||||
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
|
||||
SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** CAPI3REF: Low-level system error code
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^Attempt to return the underlying operating system error code or error
|
||||
** number that caused the most recent I/O error or failure to open a file.
|
||||
@@ -9712,8 +9830,8 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
|
||||
** allocation error occurs.
|
||||
**
|
||||
** This interface is only available if SQLite is compiled with the
|
||||
** [SQLITE_ENABLE_DESERIALIZE] option.
|
||||
** This interface is omitted if SQLite is compiled with the
|
||||
** [SQLITE_OMIT_DESERIALIZE] option.
|
||||
*/
|
||||
SQLITE_API unsigned char *sqlite3_serialize(
|
||||
sqlite3 *db, /* The database connection */
|
||||
@@ -9764,8 +9882,8 @@ SQLITE_API unsigned char *sqlite3_serialize(
|
||||
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
|
||||
** [sqlite3_free()] is invoked on argument P prior to returning.
|
||||
**
|
||||
** This interface is only available if SQLite is compiled with the
|
||||
** [SQLITE_ENABLE_DESERIALIZE] option.
|
||||
** This interface is omitted if SQLite is compiled with the
|
||||
** [SQLITE_OMIT_DESERIALIZE] option.
|
||||
*/
|
||||
SQLITE_API int sqlite3_deserialize(
|
||||
sqlite3 *db, /* The database connection */
|
||||
@@ -10014,6 +10132,38 @@ SQLITE_API int sqlite3session_create(
|
||||
*/
|
||||
SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
|
||||
|
||||
/*
|
||||
** CAPIREF: Conigure a Session Object
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** This method is used to configure a session object after it has been
|
||||
** created. At present the only valid value for the second parameter is
|
||||
** [SQLITE_SESSION_OBJCONFIG_SIZE].
|
||||
**
|
||||
** Arguments for sqlite3session_object_config()
|
||||
**
|
||||
** The following values may passed as the the 4th parameter to
|
||||
** sqlite3session_object_config().
|
||||
**
|
||||
** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
|
||||
** This option is used to set, clear or query the flag that enables
|
||||
** the [sqlite3session_changeset_size()] API. Because it imposes some
|
||||
** computational overhead, this API is disabled by default. Argument
|
||||
** pArg must point to a value of type (int). If the value is initially
|
||||
** 0, then the sqlite3session_changeset_size() API is disabled. If it
|
||||
** is greater than 0, then the same API is enabled. Or, if the initial
|
||||
** value is less than zero, no change is made. In all cases the (int)
|
||||
** variable is set to 1 if the sqlite3session_changeset_size() API is
|
||||
** enabled following the current call, or 0 otherwise.
|
||||
**
|
||||
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
|
||||
** the first table has been attached to the session object.
|
||||
*/
|
||||
SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
|
||||
|
||||
/*
|
||||
*/
|
||||
#define SQLITE_SESSION_OBJCONFIG_SIZE 1
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable A Session Object
|
||||
@@ -10258,6 +10408,22 @@ SQLITE_API int sqlite3session_changeset(
|
||||
void **ppChangeset /* OUT: Buffer containing changeset */
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** By default, this function always returns 0. For it to return
|
||||
** a useful result, the sqlite3_session object must have been configured
|
||||
** to enable this API using sqlite3session_object_config() with the
|
||||
** SQLITE_SESSION_OBJCONFIG_SIZE verb.
|
||||
**
|
||||
** When enabled, this function returns an upper limit, in bytes, for the size
|
||||
** of the changeset that might be produced if sqlite3session_changeset() were
|
||||
** called. The final changeset size might be equal to or smaller than the
|
||||
** size in bytes returned by this function.
|
||||
*/
|
||||
SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Load The Difference Between Tables Into A Session
|
||||
** METHOD: sqlite3_session
|
||||
@@ -10375,6 +10541,14 @@ SQLITE_API int sqlite3session_patchset(
|
||||
*/
|
||||
SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Query for the amount of heap memory used by a session object.
|
||||
**
|
||||
** This API returns the total amount of heap memory in bytes currently
|
||||
** used by the session object passed as the only argument.
|
||||
*/
|
||||
SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Create An Iterator To Traverse A Changeset
|
||||
** CONSTRUCTOR: sqlite3_changeset_iter
|
||||
@@ -10477,18 +10651,23 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
|
||||
** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
|
||||
** is not the case, this function returns [SQLITE_MISUSE].
|
||||
**
|
||||
** If argument pzTab is not NULL, then *pzTab is set to point to a
|
||||
** nul-terminated utf-8 encoded string containing the name of the table
|
||||
** affected by the current change. The buffer remains valid until either
|
||||
** sqlite3changeset_next() is called on the iterator or until the
|
||||
** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
|
||||
** set to the number of columns in the table affected by the change. If
|
||||
** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
|
||||
** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three
|
||||
** outputs are set through these pointers:
|
||||
**
|
||||
** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
|
||||
** depending on the type of change that the iterator currently points to;
|
||||
**
|
||||
** *pnCol is set to the number of columns in the table affected by the change; and
|
||||
**
|
||||
** *pzTab is set to point to a nul-terminated utf-8 encoded string containing
|
||||
** the name of the table affected by the current change. The buffer remains
|
||||
** valid until either sqlite3changeset_next() is called on the iterator
|
||||
** or until the conflict-handler function returns.
|
||||
**
|
||||
** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
|
||||
** is an indirect change, or false (0) otherwise. See the documentation for
|
||||
** [sqlite3session_indirect()] for a description of direct and indirect
|
||||
** changes. Finally, if pOp is not NULL, then *pOp is set to one of
|
||||
** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the
|
||||
** type of change that the iterator currently points to.
|
||||
** changes.
|
||||
**
|
||||
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
|
||||
** SQLite error code is returned. The values of the output variables may not
|
||||
|
||||
@@ -180,13 +180,10 @@ function loadSourceText(source) {
|
||||
[PROMISE]: Task.spawn(function* () {
|
||||
let transportType = gClient.localTransport ? "_LOCAL" : "_REMOTE";
|
||||
let histogramId = "DEVTOOLS_DEBUGGER_DISPLAY_SOURCE" + transportType + "_MS";
|
||||
let histogram = Services.telemetry.getHistogramById(histogramId);
|
||||
let startTime = Date.now();
|
||||
|
||||
const response = yield sourceClient.source();
|
||||
|
||||
histogram.add(Date.now() - startTime);
|
||||
|
||||
// Automatically pretty print if enabled and the test is
|
||||
// detected to be "minified"
|
||||
if (Prefs.autoPrettyPrint &&
|
||||
|
||||
@@ -11474,7 +11474,6 @@ var Debugger =
|
||||
if (telemetry) {
|
||||
var transportType = this._transport.onOutputStreamReady === undefined ? "LOCAL_" : "REMOTE_";
|
||||
var histogramId = "DEVTOOLS_DEBUGGER_RDP_" + transportType + telemetry + "_MS";
|
||||
histogram = Services.telemetry.getHistogramById(histogramId);
|
||||
startTime = +new Date();
|
||||
}
|
||||
var outgoingPacket = {
|
||||
@@ -11513,10 +11512,6 @@ var Debugger =
|
||||
if (thisCallback) {
|
||||
thisCallback(aResponse);
|
||||
}
|
||||
|
||||
if (histogram) {
|
||||
histogram.add(+new Date() - startTime);
|
||||
}
|
||||
}, "DebuggerClient.requester request callback"));
|
||||
}, "DebuggerClient.requester");
|
||||
};
|
||||
|
||||
@@ -23,6 +23,19 @@ function enableSourceMaps() {
|
||||
|
||||
function _resolveSourceMapURL(source) {
|
||||
const { url = "", sourceMapURL = "" } = source;
|
||||
|
||||
const UNSUPPORTED_PROTOCOLS = ["chrome://", "resource://"];
|
||||
if (path.isURL(sourceMapURL) && UNSUPPORTED_PROTOCOLS.some(protocol => sourceMapURL.startsWith(protocol))) {
|
||||
// If it's an internal protocol, don't allow it and return empty.
|
||||
return "";
|
||||
}
|
||||
if (path.isURL(sourceMapURL) && sourceMapURL.startsWith("file://")) {
|
||||
// Only allow file:// source maps from file:// docs
|
||||
if (!url.startsWith("file://")) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
if (path.isURL(sourceMapURL) || url == "") {
|
||||
// If it's already a full URL or the source doesn't have a URL,
|
||||
// don't resolve anything.
|
||||
|
||||
@@ -8,14 +8,7 @@ const {SIDE, BOTTOM, WINDOW} = Toolbox.HostType;
|
||||
|
||||
const URL = "data:text/html;charset=utf8,browser_toolbox_hosts_telemetry.js";
|
||||
|
||||
function getHostHistogram() {
|
||||
return Services.telemetry.getHistogramById("DEVTOOLS_TOOLBOX_HOST");
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
// Reset it to make counting easier
|
||||
getHostHistogram().clear();
|
||||
|
||||
info("Create a test tab and open the toolbox");
|
||||
let tab = yield addTab(URL);
|
||||
let target = TargetFactory.forTab(tab);
|
||||
@@ -27,9 +20,6 @@ add_task(function* () {
|
||||
|
||||
toolbox = target = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
// Cleanup
|
||||
getHostHistogram().clear();
|
||||
});
|
||||
|
||||
function* changeToolboxHost(toolbox) {
|
||||
@@ -43,8 +33,5 @@ function* changeToolboxHost(toolbox) {
|
||||
}
|
||||
|
||||
function checkResults() {
|
||||
let counts = getHostHistogram().snapshot().counts;
|
||||
is(counts[0], 3, "Toolbox HostType bottom has 3 successful entries");
|
||||
is(counts[1], 2, "Toolbox HostType side has 2 successful entries");
|
||||
is(counts[2], 2, "Toolbox HostType window has 2 successful entries");
|
||||
// STUB
|
||||
}
|
||||
@@ -13,18 +13,12 @@ const { makeInfallible, immutableUpdate } = require("devtools/shared/DevToolsUti
|
||||
const { labelDisplays, treeMapDisplays, censusDisplays } = require("./constants");
|
||||
|
||||
exports.countTakeSnapshot = makeInfallible(function () {
|
||||
const histogram = telemetry.getHistogramById("DEVTOOLS_MEMORY_TAKE_SNAPSHOT_COUNT");
|
||||
histogram.add(1);
|
||||
}, "devtools/client/memory/telemetry#countTakeSnapshot");
|
||||
|
||||
exports.countImportSnapshot = makeInfallible(function () {
|
||||
const histogram = telemetry.getHistogramById("DEVTOOLS_MEMORY_IMPORT_SNAPSHOT_COUNT");
|
||||
histogram.add(1);
|
||||
}, "devtools/client/memory/telemetry#countImportSnapshot");
|
||||
|
||||
exports.countExportSnapshot = makeInfallible(function () {
|
||||
const histogram = telemetry.getHistogramById("DEVTOOLS_MEMORY_EXPORT_SNAPSHOT_COUNT");
|
||||
histogram.add(1);
|
||||
}, "devtools/client/memory/telemetry#countExportSnapshot");
|
||||
|
||||
const COARSE_TYPE = "Coarse Type";
|
||||
@@ -43,25 +37,6 @@ const CUSTOM = "Custom";
|
||||
* The display used with the census.
|
||||
*/
|
||||
exports.countCensus = makeInfallible(function ({ filter, diffing, display }) {
|
||||
let histogram = telemetry.getHistogramById("DEVTOOLS_MEMORY_INVERTED_CENSUS");
|
||||
histogram.add(!!display.inverted);
|
||||
|
||||
histogram = telemetry.getHistogramById("DEVTOOLS_MEMORY_FILTER_CENSUS");
|
||||
histogram.add(!!filter);
|
||||
|
||||
histogram = telemetry.getHistogramById("DEVTOOLS_MEMORY_DIFF_CENSUS");
|
||||
histogram.add(!!diffing);
|
||||
|
||||
histogram = telemetry.getKeyedHistogramById("DEVTOOLS_MEMORY_BREAKDOWN_CENSUS_COUNT");
|
||||
if (display === censusDisplays.coarseType) {
|
||||
histogram.add(COARSE_TYPE);
|
||||
} else if (display === censusDisplays.allocationStack) {
|
||||
histogram.add(ALLOCATION_STACK);
|
||||
} else if (display === censusDisplays.invertedAllocationStack) {
|
||||
histogram.add(INVERTED_ALLOCATION_STACK);
|
||||
} else {
|
||||
histogram.add(CUSTOM);
|
||||
}
|
||||
}, "devtools/client/memory/telemetry#countCensus");
|
||||
|
||||
/**
|
||||
@@ -77,15 +52,4 @@ exports.countDiff = makeInfallible(function (opts) {
|
||||
* The display used to label nodes in the dominator tree.
|
||||
*/
|
||||
exports.countDominatorTree = makeInfallible(function ({ display }) {
|
||||
let histogram = telemetry.getHistogramById("DEVTOOLS_MEMORY_DOMINATOR_TREE_COUNT");
|
||||
histogram.add(1);
|
||||
|
||||
histogram = telemetry.getKeyedHistogramById("DEVTOOLS_MEMORY_BREAKDOWN_DOMINATOR_TREE_COUNT");
|
||||
if (display === labelDisplays.coarseType) {
|
||||
histogram.add(COARSE_TYPE);
|
||||
} else if (display === labelDisplays.allocationStack) {
|
||||
histogram.add(ALLOCATION_STACK);
|
||||
} else {
|
||||
histogram.add(CUSTOM);
|
||||
}
|
||||
}, "devtools/client/memory/telemetry#countDominatorTree");
|
||||
@@ -98,11 +98,7 @@ pref("devtools.debugger.auto-pretty-print", false);
|
||||
pref("devtools.debugger.auto-black-box", true);
|
||||
pref("devtools.debugger.workers", false);
|
||||
|
||||
#ifdef RELEASE_OR_BETA
|
||||
pref("devtools.debugger.new-debugger-frontend", false);
|
||||
#else
|
||||
pref("devtools.debugger.new-debugger-frontend", true);
|
||||
#endif
|
||||
|
||||
// The default Debugger UI settings
|
||||
pref("devtools.debugger.ui.panes-workers-and-sources-width", 200);
|
||||
@@ -150,12 +146,8 @@ pref("devtools.performance.ui.show-triggers-for-gc-types",
|
||||
// TODO remove once we have flame charts via bug 1148663
|
||||
pref("devtools.performance.ui.enable-memory-flame", false);
|
||||
|
||||
// Enable experimental options in the UI only in Nightly
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
pref("devtools.performance.ui.experimental", true);
|
||||
#else
|
||||
// Enable experimental options in the UI?
|
||||
pref("devtools.performance.ui.experimental", false);
|
||||
#endif
|
||||
|
||||
// The default cache UI setting
|
||||
pref("devtools.cache.disabled", false);
|
||||
@@ -308,12 +300,8 @@ pref("devtools.webconsole.timestampMessages", false);
|
||||
// to automatically trigger multiline editing (equivalent to shift + enter).
|
||||
pref("devtools.webconsole.autoMultiline", true);
|
||||
|
||||
// Enable the experimental webconsole frontend
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
pref("devtools.webconsole.new-frontend-enabled", true);
|
||||
#else
|
||||
// Enable the experimental webconsole frontend?
|
||||
pref("devtools.webconsole.new-frontend-enabled", false);
|
||||
#endif
|
||||
|
||||
// Enable the experimental support for source maps in console (work in progress)
|
||||
pref("devtools.sourcemap.locations.enabled", false);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
|
||||
* Copyright (C) 2011 Google Inc. All rights reserved.
|
||||
* Copyright (C) 2009 Mozilla Foundation. All rights reserved.
|
||||
* Copyright (C) 2022 Moonchild Productions. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -400,9 +401,15 @@ const CurlUtils = {
|
||||
*/
|
||||
escapeStringWin: function (str) {
|
||||
/*
|
||||
Replace dollar sign because of commands (e.g $(cmd.exe)) in
|
||||
powershell when using double quotes.
|
||||
Useful details http://www.rlmueller.net/PowerShellEscape.htm
|
||||
Replace the backtick character ` with `` in order to escape it.
|
||||
The backtick character is an escape character in PowerShell and
|
||||
can, among other things, be used to disable the effect of some
|
||||
of the other escapes created below.
|
||||
|
||||
Replace dollar sign because of commands in powershell when using
|
||||
double quotes. e.g $(calc.exe).
|
||||
|
||||
Also see http://www.rlmueller.net/PowerShellEscape.htm for details.
|
||||
|
||||
Replace quote by double quote (but not by \") because it is
|
||||
recognized by both cmd.exe and MS Crt arguments parser.
|
||||
@@ -416,13 +423,15 @@ const CurlUtils = {
|
||||
MS Crt arguments parser won't collapse them.
|
||||
|
||||
Replace new line outside of quotes since cmd.exe doesn't let
|
||||
to do it inside.
|
||||
us do it inside.
|
||||
*/
|
||||
return "\"" + str.replace(/\$/g, "`$")
|
||||
.replace(/"/g, "\"\"")
|
||||
.replace(/%/g, "\"%\"")
|
||||
.replace(/\\/g, "\\\\")
|
||||
.replace(/[\r\n]+/g, "\"^$&\"") + "\"";
|
||||
return "\"" +
|
||||
str.replaceAll("`", "``")
|
||||
.replaceAll("$", "`$")
|
||||
.replaceAll('"', '""')
|
||||
.replaceAll("%", '"%"')
|
||||
.replace(/\\/g, "\\\\")
|
||||
.replace(/[\r\n]+/g, "\"^$&\"") + "\"";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ const {
|
||||
const Services = require("Services");
|
||||
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const CSS_GRID_ENABLED_PREF = "layout.css.grid.enabled";
|
||||
|
||||
/**
|
||||
* This module is used to process text for output by developer tools. This means
|
||||
@@ -207,8 +206,7 @@ OutputParser.prototype = {
|
||||
if (options.expectCubicBezier &&
|
||||
BEZIER_KEYWORDS.indexOf(token.text) >= 0) {
|
||||
this._appendCubicBezier(token.text, options);
|
||||
} else if (Services.prefs.getBoolPref(CSS_GRID_ENABLED_PREF) &&
|
||||
options.expectDisplay && token.text === "grid" &&
|
||||
} else if (options.expectDisplay && token.text === "grid" &&
|
||||
text === token.text) {
|
||||
this._appendGrid(token.text, options);
|
||||
} else if (colorOK() &&
|
||||
|
||||
@@ -502,7 +502,7 @@ const Services = {
|
||||
return window.navigator.appVersion;
|
||||
},
|
||||
|
||||
// This is only used by telemetry, which is disabled for the
|
||||
// This was only used by telemetry, which is disabled for the
|
||||
// content case. So, being totally wrong is ok.
|
||||
get is64Bit() {
|
||||
return true;
|
||||
|
||||
@@ -266,15 +266,7 @@ Telemetry.prototype = {
|
||||
* Value to store.
|
||||
*/
|
||||
log: function (histogramId, value) {
|
||||
if (histogramId) {
|
||||
try {
|
||||
let histogram = Services.telemetry.getHistogramById(histogramId);
|
||||
histogram.add(value);
|
||||
} catch (e) {
|
||||
dump("Warning: An attempt was made to write to the " + histogramId +
|
||||
" histogram, which is not defined in Histograms.json\n");
|
||||
}
|
||||
}
|
||||
/* STUB */
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -288,15 +280,7 @@ Telemetry.prototype = {
|
||||
* Value to store.
|
||||
*/
|
||||
logKeyed: function (histogramId, key, value) {
|
||||
if (histogramId) {
|
||||
try {
|
||||
let histogram = Services.telemetry.getKeyedHistogramById(histogramId);
|
||||
histogram.add(key, value);
|
||||
} catch (e) {
|
||||
dump("Warning: An attempt was made to write to the " + histogramId +
|
||||
" histogram, which is not defined in Histograms.json\n");
|
||||
}
|
||||
}
|
||||
/* STUB */
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,6 @@ const {
|
||||
} = require("devtools/shared/layout/utils");
|
||||
const { stringifyGridFragments } = require("devtools/server/actors/utils/css-grid-utils");
|
||||
|
||||
const CSS_GRID_ENABLED_PREF = "layout.css.grid.enabled";
|
||||
const ROWS = "rows";
|
||||
const COLUMNS = "cols";
|
||||
const GRID_LINES_PROPERTIES = {
|
||||
@@ -292,7 +291,7 @@ CssGridHighlighter.prototype = extend(AutoRefreshHighlighter.prototype, {
|
||||
},
|
||||
|
||||
_show() {
|
||||
if (Services.prefs.getBoolPref(CSS_GRID_ENABLED_PREF) && !this.isGrid()) {
|
||||
if (!this.isGrid()) {
|
||||
this.hide();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -13,19 +13,19 @@ import os
|
||||
import sys
|
||||
import string
|
||||
import subprocess
|
||||
|
||||
import mozpack.path as mozpath
|
||||
|
||||
from mozbuild.base import (
|
||||
MozbuildObject,
|
||||
MachCommandBase,
|
||||
)
|
||||
|
||||
from mach.decorators import (
|
||||
CommandProvider,
|
||||
Command,
|
||||
)
|
||||
|
||||
def resolve_path(start, relativePath):
|
||||
"""Helper to resolve a path from a start, and a relative path"""
|
||||
return os.path.normpath(os.path.join(start, relativePath))
|
||||
|
||||
def stringify(obj):
|
||||
"""Helper to stringify to JSON"""
|
||||
return json.dumps(obj, sort_keys=True, indent=2, separators=(',', ': '))
|
||||
@@ -38,6 +38,15 @@ class MachCommands(MachCommandBase):
|
||||
def generate_css_db(self):
|
||||
"""Generate the static css properties database for devtools and write it to file."""
|
||||
|
||||
generated_dir = mozpath.join(self.topsrcdir,
|
||||
'devtools/shared/css/generated')
|
||||
if not os.path.exists(generated_dir):
|
||||
generated_dir = mozpath.join(self.topsrcdir, 'platform',
|
||||
'devtools/shared/css/generated')
|
||||
else:
|
||||
raise Exception('Directory expected at %s does not exist.' % generated_dir)
|
||||
self.generated_dir = generated_dir
|
||||
|
||||
print("Re-generating the css properties database...")
|
||||
db = self.get_properties_db_from_xpcshell()
|
||||
|
||||
@@ -47,13 +56,13 @@ class MachCommands(MachCommandBase):
|
||||
|
||||
def get_properties_db_from_xpcshell(self):
|
||||
"""Generate the static css properties db for devtools from an xpcshell script."""
|
||||
build = MozbuildObject.from_environment()
|
||||
build = MozbuildObject.from_environment(cwd=self.topobjdir)
|
||||
|
||||
# Get the paths
|
||||
script_path = resolve_path(self.topsrcdir,
|
||||
'devtools/shared/css/generated/generate-properties-db.js')
|
||||
gre_path = resolve_path(self.topobjdir, 'dist/bin')
|
||||
browser_path = resolve_path(self.topobjdir, 'dist/bin/browser')
|
||||
script_path = mozpath.join(self.generated_dir,
|
||||
'generate-properties-db.js')
|
||||
gre_path = mozpath.join(self.topobjdir, 'dist/bin')
|
||||
browser_path = mozpath.join(self.topobjdir, 'dist/bin/browser')
|
||||
xpcshell_path = build.get_binary_path(what='xpcshell')
|
||||
print(browser_path)
|
||||
|
||||
@@ -74,10 +83,10 @@ class MachCommands(MachCommandBase):
|
||||
|
||||
def output_template(self, substitutions):
|
||||
"""Output a the properties-db.js from a template."""
|
||||
js_template_path = resolve_path(self.topsrcdir,
|
||||
'devtools/shared/css/generated/properties-db.js.in')
|
||||
destination_path = resolve_path(self.topsrcdir,
|
||||
'devtools/shared/css/generated/properties-db.js')
|
||||
js_template_path = mozpath.join(self.generated_dir,
|
||||
'properties-db.js.in')
|
||||
destination_path = mozpath.join(self.generated_dir,
|
||||
'properties-db.js')
|
||||
|
||||
with open(js_template_path, 'rb') as handle:
|
||||
js_template = handle.read()
|
||||
|
||||
@@ -191,11 +191,13 @@ exports.CSS_PROPERTIES = {
|
||||
"supports": [],
|
||||
"values": [
|
||||
"-moz-gtk-info-bar",
|
||||
"-moz-mac-active-source-list-selection",
|
||||
"-moz-mac-disclosure-button-closed",
|
||||
"-moz-mac-disclosure-button-open",
|
||||
"-moz-mac-fullscreen-button",
|
||||
"-moz-mac-help-button",
|
||||
"-moz-mac-source-list",
|
||||
"-moz-mac-source-list-selection",
|
||||
"-moz-mac-vibrancy-dark",
|
||||
"-moz-mac-vibrancy-light",
|
||||
"-moz-win-borderless-glass",
|
||||
@@ -1236,9 +1238,12 @@ exports.CSS_PROPERTIES = {
|
||||
"tab-size"
|
||||
],
|
||||
"supports": [
|
||||
6,
|
||||
7
|
||||
],
|
||||
"values": [
|
||||
"-moz-calc",
|
||||
"calc",
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
@@ -1746,6 +1751,141 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"-webkit-appearance": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"-moz-appearance"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"-moz-gtk-info-bar",
|
||||
"-moz-mac-active-source-list-selection",
|
||||
"-moz-mac-disclosure-button-closed",
|
||||
"-moz-mac-disclosure-button-open",
|
||||
"-moz-mac-fullscreen-button",
|
||||
"-moz-mac-help-button",
|
||||
"-moz-mac-source-list",
|
||||
"-moz-mac-source-list-selection",
|
||||
"-moz-mac-vibrancy-dark",
|
||||
"-moz-mac-vibrancy-light",
|
||||
"-moz-win-borderless-glass",
|
||||
"-moz-win-browsertabbar-toolbox",
|
||||
"-moz-win-communications-toolbox",
|
||||
"-moz-win-exclude-glass",
|
||||
"-moz-win-glass",
|
||||
"-moz-win-media-toolbox",
|
||||
"-moz-window-button-box",
|
||||
"-moz-window-button-box-maximized",
|
||||
"-moz-window-button-close",
|
||||
"-moz-window-button-maximize",
|
||||
"-moz-window-button-minimize",
|
||||
"-moz-window-button-restore",
|
||||
"-moz-window-frame-bottom",
|
||||
"-moz-window-frame-left",
|
||||
"-moz-window-frame-right",
|
||||
"-moz-window-titlebar",
|
||||
"-moz-window-titlebar-maximized",
|
||||
"button",
|
||||
"button-arrow-down",
|
||||
"button-arrow-next",
|
||||
"button-arrow-previous",
|
||||
"button-arrow-up",
|
||||
"button-bevel",
|
||||
"button-focus",
|
||||
"caret",
|
||||
"checkbox",
|
||||
"checkbox-container",
|
||||
"checkbox-label",
|
||||
"checkmenuitem",
|
||||
"dialog",
|
||||
"dualbutton",
|
||||
"groupbox",
|
||||
"inherit",
|
||||
"initial",
|
||||
"listbox",
|
||||
"listitem",
|
||||
"menuarrow",
|
||||
"menubar",
|
||||
"menucheckbox",
|
||||
"menuimage",
|
||||
"menuitem",
|
||||
"menuitemtext",
|
||||
"menulist",
|
||||
"menulist-button",
|
||||
"menulist-text",
|
||||
"menulist-textfield",
|
||||
"menupopup",
|
||||
"menuradio",
|
||||
"menuseparator",
|
||||
"meterbar",
|
||||
"meterchunk",
|
||||
"none",
|
||||
"number-input",
|
||||
"progressbar",
|
||||
"progressbar-vertical",
|
||||
"progresschunk",
|
||||
"progresschunk-vertical",
|
||||
"radio",
|
||||
"radio-container",
|
||||
"radio-label",
|
||||
"radiomenuitem",
|
||||
"range",
|
||||
"range-thumb",
|
||||
"resizer",
|
||||
"resizerpanel",
|
||||
"scale-horizontal",
|
||||
"scale-vertical",
|
||||
"scalethumb-horizontal",
|
||||
"scalethumb-vertical",
|
||||
"scalethumbend",
|
||||
"scalethumbstart",
|
||||
"scalethumbtick",
|
||||
"scrollbar",
|
||||
"scrollbar-horizontal",
|
||||
"scrollbar-small",
|
||||
"scrollbar-vertical",
|
||||
"scrollbarbutton-down",
|
||||
"scrollbarbutton-left",
|
||||
"scrollbarbutton-right",
|
||||
"scrollbarbutton-up",
|
||||
"scrollbarthumb-horizontal",
|
||||
"scrollbarthumb-vertical",
|
||||
"scrollbartrack-horizontal",
|
||||
"scrollbartrack-vertical",
|
||||
"searchfield",
|
||||
"separator",
|
||||
"spinner",
|
||||
"spinner-downbutton",
|
||||
"spinner-textfield",
|
||||
"spinner-upbutton",
|
||||
"splitter",
|
||||
"statusbar",
|
||||
"statusbarpanel",
|
||||
"tab",
|
||||
"tab-scroll-arrow-back",
|
||||
"tab-scroll-arrow-forward",
|
||||
"tabpanel",
|
||||
"tabpanels",
|
||||
"textfield",
|
||||
"textfield-multiline",
|
||||
"toolbar",
|
||||
"toolbarbutton",
|
||||
"toolbarbutton-dropdown",
|
||||
"toolbargripper",
|
||||
"toolbox",
|
||||
"tooltip",
|
||||
"treeheader",
|
||||
"treeheadercell",
|
||||
"treeheadersortarrow",
|
||||
"treeitem",
|
||||
"treeline",
|
||||
"treetwisty",
|
||||
"treetwistyopen",
|
||||
"treeview",
|
||||
"unset",
|
||||
"window"
|
||||
]
|
||||
},
|
||||
"-webkit-backface-visibility": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@@ -2073,6 +2213,7 @@ exports.CSS_PROPERTIES = {
|
||||
"-moz-min-content",
|
||||
"auto",
|
||||
"calc",
|
||||
"content",
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
@@ -2095,6 +2236,7 @@ exports.CSS_PROPERTIES = {
|
||||
"-moz-min-content",
|
||||
"auto",
|
||||
"calc",
|
||||
"content",
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
@@ -2237,12 +2379,14 @@ exports.CSS_PROPERTIES = {
|
||||
"border-box",
|
||||
"content-box",
|
||||
"exclude",
|
||||
"fill-box",
|
||||
"inherit",
|
||||
"initial",
|
||||
"intersect",
|
||||
"linear-gradient",
|
||||
"luminance",
|
||||
"match-source",
|
||||
"no-clip",
|
||||
"no-repeat",
|
||||
"none",
|
||||
"padding-box",
|
||||
@@ -2254,9 +2398,11 @@ exports.CSS_PROPERTIES = {
|
||||
"repeating-radial-gradient",
|
||||
"round",
|
||||
"space",
|
||||
"stroke-box",
|
||||
"subtract",
|
||||
"unset",
|
||||
"url"
|
||||
"url",
|
||||
"view-box"
|
||||
]
|
||||
},
|
||||
"-webkit-mask-clip": {
|
||||
@@ -2268,10 +2414,14 @@ exports.CSS_PROPERTIES = {
|
||||
"values": [
|
||||
"border-box",
|
||||
"content-box",
|
||||
"fill-box",
|
||||
"inherit",
|
||||
"initial",
|
||||
"no-clip",
|
||||
"padding-box",
|
||||
"unset"
|
||||
"stroke-box",
|
||||
"unset",
|
||||
"view-box"
|
||||
]
|
||||
},
|
||||
"-webkit-mask-composite": {
|
||||
@@ -2327,10 +2477,13 @@ exports.CSS_PROPERTIES = {
|
||||
"values": [
|
||||
"border-box",
|
||||
"content-box",
|
||||
"fill-box",
|
||||
"inherit",
|
||||
"initial",
|
||||
"padding-box",
|
||||
"unset"
|
||||
"stroke-box",
|
||||
"unset",
|
||||
"view-box"
|
||||
]
|
||||
},
|
||||
"-webkit-mask-position": {
|
||||
@@ -2809,6 +2962,7 @@ exports.CSS_PROPERTIES = {
|
||||
"animation-play-state",
|
||||
"animation-timing-function",
|
||||
"-moz-appearance",
|
||||
"aspect-ratio",
|
||||
"backface-visibility",
|
||||
"background-attachment",
|
||||
"background-blend-mode",
|
||||
@@ -2925,16 +3079,15 @@ exports.CSS_PROPERTIES = {
|
||||
"font-variant-ligatures",
|
||||
"font-variant-numeric",
|
||||
"font-variant-position",
|
||||
"font-variation-settings",
|
||||
"font-weight",
|
||||
"-moz-force-broken-image-icon",
|
||||
"grid-auto-columns",
|
||||
"grid-auto-flow",
|
||||
"grid-auto-rows",
|
||||
"grid-column-end",
|
||||
"grid-column-gap",
|
||||
"grid-column-start",
|
||||
"grid-row-end",
|
||||
"grid-row-gap",
|
||||
"grid-row-start",
|
||||
"grid-template-areas",
|
||||
"grid-template-columns",
|
||||
@@ -3029,6 +3182,7 @@ exports.CSS_PROPERTIES = {
|
||||
"quotes",
|
||||
"resize",
|
||||
"right",
|
||||
"row-gap",
|
||||
"ruby-align",
|
||||
"ruby-position",
|
||||
"scroll-behavior",
|
||||
@@ -3141,11 +3295,13 @@ exports.CSS_PROPERTIES = {
|
||||
"-moz-inline-stack",
|
||||
"-moz-left",
|
||||
"-moz-linear-gradient",
|
||||
"-moz-mac-active-source-list-selection",
|
||||
"-moz-mac-disclosure-button-closed",
|
||||
"-moz-mac-disclosure-button-open",
|
||||
"-moz-mac-fullscreen-button",
|
||||
"-moz-mac-help-button",
|
||||
"-moz-mac-source-list",
|
||||
"-moz-mac-source-list-selection",
|
||||
"-moz-mac-vibrancy-dark",
|
||||
"-moz-mac-vibrancy-light",
|
||||
"-moz-max-content",
|
||||
@@ -3192,6 +3348,7 @@ exports.CSS_PROPERTIES = {
|
||||
"alternate",
|
||||
"alternate-reverse",
|
||||
"always",
|
||||
"anywhere",
|
||||
"auto",
|
||||
"avoid",
|
||||
"backwards",
|
||||
@@ -3232,6 +3389,7 @@ exports.CSS_PROPERTIES = {
|
||||
"column-reverse",
|
||||
"condensed",
|
||||
"contain",
|
||||
"content",
|
||||
"content-box",
|
||||
"contents",
|
||||
"cover",
|
||||
@@ -3272,10 +3430,10 @@ exports.CSS_PROPERTIES = {
|
||||
"flex",
|
||||
"flex-end",
|
||||
"flex-start",
|
||||
"flow-root",
|
||||
"forwards",
|
||||
"full-width",
|
||||
"geometricprecision",
|
||||
"grayscale",
|
||||
"grid",
|
||||
"groove",
|
||||
"groupbox",
|
||||
@@ -3283,6 +3441,7 @@ exports.CSS_PROPERTIES = {
|
||||
"hard-light",
|
||||
"hidden",
|
||||
"hide",
|
||||
"high-quality",
|
||||
"horizontal",
|
||||
"horizontal-tb",
|
||||
"hsl",
|
||||
@@ -3355,6 +3514,7 @@ exports.CSS_PROPERTIES = {
|
||||
"mixed",
|
||||
"multiply",
|
||||
"no-change",
|
||||
"no-clip",
|
||||
"no-drag",
|
||||
"no-repeat",
|
||||
"non-scaling-stroke",
|
||||
@@ -3377,6 +3537,7 @@ exports.CSS_PROPERTIES = {
|
||||
"pan-y",
|
||||
"paused",
|
||||
"petite-caps",
|
||||
"pixelated",
|
||||
"pre",
|
||||
"pre-line",
|
||||
"pre-wrap",
|
||||
@@ -3489,6 +3650,7 @@ exports.CSS_PROPERTIES = {
|
||||
"stretch",
|
||||
"stretch-to-fit",
|
||||
"stroke",
|
||||
"stroke-box",
|
||||
"sub",
|
||||
"subtract",
|
||||
"super",
|
||||
@@ -5699,6 +5861,7 @@ exports.CSS_PROPERTIES = {
|
||||
"block",
|
||||
"contents",
|
||||
"flex",
|
||||
"flow-root",
|
||||
"grid",
|
||||
"inherit",
|
||||
"initial",
|
||||
@@ -5841,6 +6004,7 @@ exports.CSS_PROPERTIES = {
|
||||
"-moz-min-content",
|
||||
"auto",
|
||||
"calc",
|
||||
"content",
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
@@ -5863,6 +6027,7 @@ exports.CSS_PROPERTIES = {
|
||||
"-moz-min-content",
|
||||
"auto",
|
||||
"calc",
|
||||
"content",
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
@@ -6314,6 +6479,18 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"font-variation-settings": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
"font-variation-settings"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"font-weight": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
@@ -6328,17 +6505,11 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"grid": {
|
||||
"gap": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"grid-template-areas",
|
||||
"grid-template-rows",
|
||||
"grid-template-columns",
|
||||
"grid-auto-flow",
|
||||
"grid-auto-rows",
|
||||
"grid-auto-columns",
|
||||
"grid-row-gap",
|
||||
"grid-column-gap"
|
||||
"row-gap",
|
||||
"column-gap"
|
||||
],
|
||||
"supports": [
|
||||
6,
|
||||
@@ -6347,6 +6518,27 @@ exports.CSS_PROPERTIES = {
|
||||
"values": [
|
||||
"-moz-calc",
|
||||
"calc",
|
||||
"inherit",
|
||||
"initial",
|
||||
"normal",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"grid": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"grid-template-areas",
|
||||
"grid-template-rows",
|
||||
"grid-template-columns",
|
||||
"grid-auto-flow",
|
||||
"grid-auto-rows",
|
||||
"grid-auto-columns"
|
||||
],
|
||||
"supports": [
|
||||
6,
|
||||
8
|
||||
],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
@@ -6443,7 +6635,7 @@ exports.CSS_PROPERTIES = {
|
||||
"grid-column-gap": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"grid-column-gap"
|
||||
"column-gap"
|
||||
],
|
||||
"supports": [
|
||||
6,
|
||||
@@ -6454,6 +6646,7 @@ exports.CSS_PROPERTIES = {
|
||||
"calc",
|
||||
"inherit",
|
||||
"initial",
|
||||
"normal",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
@@ -6474,8 +6667,8 @@ exports.CSS_PROPERTIES = {
|
||||
"grid-gap": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"grid-row-gap",
|
||||
"grid-column-gap"
|
||||
"row-gap",
|
||||
"column-gap"
|
||||
],
|
||||
"supports": [
|
||||
6,
|
||||
@@ -6486,6 +6679,7 @@ exports.CSS_PROPERTIES = {
|
||||
"calc",
|
||||
"inherit",
|
||||
"initial",
|
||||
"normal",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
@@ -6521,7 +6715,7 @@ exports.CSS_PROPERTIES = {
|
||||
"grid-row-gap": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"grid-row-gap"
|
||||
"row-gap"
|
||||
],
|
||||
"supports": [
|
||||
6,
|
||||
@@ -6532,6 +6726,7 @@ exports.CSS_PROPERTIES = {
|
||||
"calc",
|
||||
"inherit",
|
||||
"initial",
|
||||
"normal",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
@@ -6668,10 +6863,13 @@ exports.CSS_PROPERTIES = {
|
||||
"values": [
|
||||
"-moz-crisp-edges",
|
||||
"auto",
|
||||
"high-quality",
|
||||
"inherit",
|
||||
"initial",
|
||||
"optimizequality",
|
||||
"optimizespeed",
|
||||
"pixelated",
|
||||
"smooth",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
@@ -7207,12 +7405,14 @@ exports.CSS_PROPERTIES = {
|
||||
"border-box",
|
||||
"content-box",
|
||||
"exclude",
|
||||
"fill-box",
|
||||
"inherit",
|
||||
"initial",
|
||||
"intersect",
|
||||
"linear-gradient",
|
||||
"luminance",
|
||||
"match-source",
|
||||
"no-clip",
|
||||
"no-repeat",
|
||||
"none",
|
||||
"padding-box",
|
||||
@@ -7224,9 +7424,11 @@ exports.CSS_PROPERTIES = {
|
||||
"repeating-radial-gradient",
|
||||
"round",
|
||||
"space",
|
||||
"stroke-box",
|
||||
"subtract",
|
||||
"unset",
|
||||
"url"
|
||||
"url",
|
||||
"view-box"
|
||||
]
|
||||
},
|
||||
"mask-clip": {
|
||||
@@ -7238,10 +7440,14 @@ exports.CSS_PROPERTIES = {
|
||||
"values": [
|
||||
"border-box",
|
||||
"content-box",
|
||||
"fill-box",
|
||||
"inherit",
|
||||
"initial",
|
||||
"no-clip",
|
||||
"padding-box",
|
||||
"unset"
|
||||
"stroke-box",
|
||||
"unset",
|
||||
"view-box"
|
||||
]
|
||||
},
|
||||
"mask-composite": {
|
||||
@@ -7312,10 +7518,13 @@ exports.CSS_PROPERTIES = {
|
||||
"values": [
|
||||
"border-box",
|
||||
"content-box",
|
||||
"fill-box",
|
||||
"inherit",
|
||||
"initial",
|
||||
"padding-box",
|
||||
"unset"
|
||||
"stroke-box",
|
||||
"unset",
|
||||
"view-box"
|
||||
]
|
||||
},
|
||||
"mask-position": {
|
||||
@@ -8335,6 +8544,24 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"row-gap": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"row-gap"
|
||||
],
|
||||
"supports": [
|
||||
6,
|
||||
8
|
||||
],
|
||||
"values": [
|
||||
"-moz-calc",
|
||||
"calc",
|
||||
"inherit",
|
||||
"initial",
|
||||
"normal",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"ruby-align": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
@@ -8479,6 +8706,21 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"scrollbar-width": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
"scrollbar-width"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
"thin",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"shape-rendering": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
@@ -8572,6 +8814,8 @@ exports.CSS_PROPERTIES = {
|
||||
8
|
||||
],
|
||||
"values": [
|
||||
"-moz-calc",
|
||||
"calc",
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
|
||||
Loaded 100 of 2307 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user