Compare commits

..
28675 changed files with 1865122 additions and 639415 deletions

No files matched your search

+22
View File
@@ -187,6 +187,28 @@ devtools/client/framework/test/code_ugly*
devtools/server/tests/unit/babel_and_browserify_script_with_source_map.js
devtools/server/tests/unit/setBreakpoint*
# mobile/android/ exclusions
mobile/android/tests/
# Uses `#filter substitution`
mobile/android/b2gdroid/app/b2gdroid.js
mobile/android/app/mobile.js
mobile/android/chrome/content/healthreport-prefs.js
# Uses `#expand`
mobile/android/chrome/content/about.js
# Not much JS to lint and non-standard at that
mobile/android/installer/
mobile/android/locales/
# Non-standard `(catch ex if ...)`
mobile/android/chrome/content/browser.js
mobile/android/components/Snippets.js
# Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression"
mobile/android/modules/HomeProvider.jsm
# services/ exclusions
# Uses `#filter substitution`
+3
View File
@@ -91,6 +91,9 @@ GPATH
# Git clone directory for updating web-platform-tests
testing/web-platform/sync/
# Android Gradle artifacts.
mobile/android/gradle/.gradle
# XCode project cruft
embedding/ios/GoannaEmbed/GoannaEmbed.xcodeproj/project.xcworkspace/xcuserdata
embedding/ios/GoannaEmbed/GoannaEmbed.xcodeproj/xcuserdata
+5
View File
@@ -36,6 +36,11 @@ 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
+1 -1
View File
@@ -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 CSS flow-root implementation
+4 -2
View File
@@ -9,6 +9,8 @@ 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`
@@ -21,7 +23,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 primarily licensed under Mozilla Public License v2.0, the
Although this repository is 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.
@@ -34,4 +36,4 @@ improvement patches upstream to its origin to mutually improve the platform and
a future for XUL.
## Looking for Pale Moon and Basilisk?
As of [`Issue #969`](https://repo.palemoon.org/MoonchildProductions/UXP/issues/969), release versions `28.9.0` and `2020.03.04` respectively, they have been split off into their own dedicated repositories located at [`MoonchildProductions/Pale-Moon`](https://repo.palemoon.org/MoonchildProductions/Pale-Moon) and [`MoonchildProductions/Basilisk`](https://repo.palemoon.org/MoonchildProductions/Basilisk).
As of [`Issue #969`](https://github.com/MoonchildProductions/UXP/issues/969), release versions `28.9.0` and `2020.03.04` respectively, they have been split off into their own dedicated repositories located at [`MoonchildProductions/Pale-Moon`](https://github.com/MoonchildProductions/Pale-Moon) and [`MoonchildProductions/Basilisk`](https://github.com/MoonchildProductions/Basilisk).
+4 -3
View File
@@ -15,15 +15,15 @@ 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 add-ons board!);
- Malware extensions (but please do report those on the forum in the extensions 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 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 find an issue in UXP or the applications it builds on that could impact the security or safety of users please **do not**
make an issue on GitHub about it. GitHub 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
via a **private message** to **Moonchild** (the founder and prime responsible for security issues).
@@ -33,3 +33,4 @@ 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).
+2
View File
@@ -5,7 +5,9 @@
#include "AccIterator.h"
#include "AccGroupInfo.h"
#ifdef MOZ_XUL
#include "XULTreeAccessible.h"
#endif
#include "mozilla/dom/HTMLLabelElement.h"
+2
View File
@@ -341,6 +341,8 @@ 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,6 +13,7 @@
#include "mozilla/dom/TabChild.h"
#include "mozilla/dom/Element.h"
#include "mozilla/Telemetry.h"
using namespace mozilla;
using namespace mozilla::a11y;
@@ -68,6 +68,7 @@
#include "mozilla/Services.h"
#include "nsDeckFrame.h"
#ifdef MOZ_XUL
#include "XULAlertAccessible.h"
#include "XULColorPickerAccessible.h"
#include "XULComboboxAccessible.h"
@@ -78,6 +79,7 @@
#include "XULSliderAccessible.h"
#include "XULTabAccessible.h"
#include "XULTreeGridAccessibleWrap.h"
#endif
#if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
#include "nsNPAPIPluginInstance.h"
@@ -1354,6 +1356,7 @@ nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
}
RefPtr<Accessible> accessible;
#ifdef MOZ_XUL
// XUL controls
if (role.EqualsLiteral("xul:alert")) {
accessible = new XULAlertAccessible(aContent, aDoc);
@@ -1512,6 +1515,7 @@ nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
accessible = new XULToolbarButtonAccessible(aContent, aDoc);
}
#endif // MOZ_XUL
return accessible.forget();
}
@@ -1735,6 +1739,7 @@ nsAccessibilityService::HasAccessible(nsIDOMNode* aDOMNode)
////////////////////////////////////////////////////////////////////////////////
// nsAccessibilityService private (DON'T put methods here)
#ifdef MOZ_XUL
already_AddRefed<Accessible>
nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
DocAccessible* aDoc)
@@ -1764,6 +1769,7 @@ nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
new XULTreeGridAccessibleWrap(aContent, aDoc, treeFrame);
return accessible.forget();
}
#endif
nsAccessibilityService*
GetOrCreateAccService(uint32_t aNewConsumer)
+2
View File
@@ -274,11 +274,13 @@ 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.
+6
View File
@@ -48,7 +48,9 @@
#include "mozilla/dom/DocumentType.h"
#include "mozilla/dom/Element.h"
#ifdef MOZ_XUL
#include "nsIXULDocument.h"
#endif
using namespace mozilla;
using namespace mozilla::a11y;
@@ -208,9 +210,11 @@ 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;
}
}
@@ -383,11 +387,13 @@ 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);
+31 -8
View File
@@ -19,7 +19,9 @@
#include "Relation.h"
#include "Role.h"
#include "States.h"
#ifdef MOZ_XUL
#include "XULTreeAccessible.h"
#endif
#include "mozilla/dom/Element.h"
@@ -41,8 +43,10 @@
#include "nsFocusManager.h"
#include "nsGlobalWindow.h"
#ifdef MOZ_XUL
#include "nsIXULDocument.h"
#include "nsIXULWindow.h"
#endif
using namespace mozilla;
using namespace mozilla::a11y;
@@ -98,6 +102,7 @@ RootAccessible::NativeRole()
}
// RootAccessible protected member
#ifdef MOZ_XUL
uint32_t
RootAccessible::GetChromeFlags()
{
@@ -117,6 +122,7 @@ RootAccessible::GetChromeFlags()
xulWin->GetChromeFlags(&chromeFlags);
return chromeFlags;
}
#endif
uint64_t
RootAccessible::NativeState()
@@ -125,6 +131,7 @@ RootAccessible::NativeState()
if (state & states::DEFUNCT)
return state;
#ifdef MOZ_XUL
uint32_t chromeFlags = GetChromeFlags();
if (chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE)
state |= states::SIZEABLE;
@@ -135,6 +142,7 @@ RootAccessible::NativeState()
state |= states::MOVEABLE;
if (chromeFlags & nsIWebBrowserChrome::CHROME_MODAL)
state |= states::MODAL;
#endif
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm && fm->GetActiveWindow() == mDocumentNode->GetWindow())
@@ -284,6 +292,7 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
if (!accessible)
return;
#ifdef MOZ_XUL
XULTreeAccessible* treeAcc = accessible->AsXULTree();
if (treeAcc) {
if (eventType.EqualsLiteral("TreeRowCountChanged")) {
@@ -296,6 +305,7 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
return;
}
}
#endif
if (eventType.EqualsLiteral("RadioStateChange")) {
uint64_t state = accessible->State();
@@ -331,6 +341,7 @@ 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();
@@ -374,22 +385,29 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
nsEventShell::FireEvent(selChangeEvent);
return;
}
} else if (eventType.EqualsLiteral("AlertActive")) {
}
else
#endif
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
@@ -403,7 +421,8 @@ 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);
@@ -421,7 +440,8 @@ 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);
@@ -430,7 +450,8 @@ 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
@@ -629,6 +650,7 @@ RootAccessible::HandlePopupHidingEvent(nsINode* aPopupNode)
}
}
#ifdef MOZ_XUL
void
RootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
XULTreeAccessible* aAccessible)
@@ -692,6 +714,7 @@ RootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
aAccessible->TreeViewInvalidated(startRow, endRow, startCol, endCol);
}
#endif
ProxyAccessible*
RootAccessible::GetPrimaryRemoteTopLevelContentDoc() const
+7 -5
View File
@@ -70,12 +70,14 @@ protected:
*/
void HandlePopupHidingEvent(nsINode* aNode);
void HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
XULTreeAccessible* aAccessible);
void HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
XULTreeAccessible* aAccessible);
#ifdef MOZ_XUL
void HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
XULTreeAccessible* aAccessible);
void HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
XULTreeAccessible* aAccessible);
uint32_t GetChromeFlags();
uint32_t GetChromeFlags();
#endif
};
inline RootAccessible*
+26 -5
View File
@@ -64,7 +64,9 @@ this.AccessFu = { // jshint ignore:line
if (this._enabled) {
this._disable();
}
if (Utils.win.navigator.mozSettings) {
if (Utils.MozBuildApp === 'mobile/android') {
Services.obs.removeObserver(this, 'Accessibility:Settings');
} else if (Utils.win.navigator.mozSettings) {
Utils.win.navigator.mozSettings.removeObserver(
SCREENREADER_SETTING, this.handleEvent);
}
@@ -583,7 +585,11 @@ var Output = {
get androidBridge() {
delete this.androidBridge;
this.androidBridge = null;
if (Utils.MozBuildApp === 'mobile/android') {
this.androidBridge = Services.androidBridge;
} else {
this.androidBridge = null;
}
return this.androidBridge;
},
@@ -809,6 +815,12 @@ var Input = {
target.blur();
}
}
if (Utils.MozBuildApp == 'mobile/android') {
// Return focus to native Android browser chrome.
Services.androidBridge.handleGeckoMessage(
{ type: 'ToggleChrome:Focus' });
}
break;
case aEvent.DOM_VK_RETURN:
if (this.editState.editing) {
@@ -825,9 +837,18 @@ var Input = {
},
moveToPoint: function moveToPoint(aRule, aX, aY) {
let win = Utils.win;
Utils.winUtils.sendMouseEvent('mousemove',
aX - win.mozInnerScreenX, aY - win.mozInnerScreenY, 0, 0, 0);
// XXX: Bug 1013408 - There is no alignment between the chrome window's
// viewport size and the content viewport size in Android. This makes
// sending mouse events beyond its bounds impossible.
if (Utils.MozBuildApp === 'mobile/android') {
let mm = Utils.getMessageManager(Utils.CurrentBrowser);
mm.sendAsyncMessage('AccessFu:MoveToPoint',
{rule: aRule, x: aX, y: aY, origin: 'top'});
} else {
let win = Utils.win;
Utils.winUtils.sendMouseEvent('mousemove',
aX - win.mozInnerScreenX, aY - win.mozInnerScreenY, 0, 0, 0);
}
},
moveCursor: function moveCursor(aAction, aRule, aInputType, aAdjustRange) {
+3 -1
View File
@@ -76,6 +76,8 @@ const EDGE = 0.1;
const TIMEOUT_MULTIPLIER = 1;
// A single pointer down/up sequence periodically precedes the tripple swipe
// gesture on Android. This delay acounts for that.
const IS_ANDROID = Utils.MozBuildApp === 'mobile/android' &&
Utils.AndroidSdkVersion >= 14;
/**
* A point object containing distance travelled data.
@@ -204,7 +206,7 @@ this.GestureTracker = { // jshint ignore:line
if (aDetail.type !== 'pointerdown') {
return;
}
let GestureConstructor = aGesture || Tap;
let GestureConstructor = aGesture || (IS_ANDROID ? DoubleTap : Tap);
this._create(GestureConstructor);
this._update(aDetail, aTimeStamp);
},
+1 -1
View File
@@ -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.MozBuildApp === 'browser' &&
if ((Utils.AndroidSdkVersion < 16 || Utils.MozBuildApp === 'browser') &&
aState.contains(States.CHECKABLE)) {
let checked = aState.contains(States.CHECKED);
let statetr;
+12
View File
@@ -39,6 +39,13 @@ 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 = {
@@ -103,6 +110,11 @@ 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;
+30 -17
View File
@@ -257,8 +257,11 @@ AndroidPresenter.prototype.pivotChanged =
let androidEvents = [];
let isExploreByTouch = (aReason == Ci.nsIAccessiblePivot.REASON_POINT);
let focusEventType = this.ANDROID_VIEW_ACCESSIBILITY_FOCUSED;
let isExploreByTouch = (aReason == Ci.nsIAccessiblePivot.REASON_POINT &&
Utils.AndroidSdkVersion >= 14);
let focusEventType = (Utils.AndroidSdkVersion >= 16) ?
this.ANDROID_VIEW_ACCESSIBILITY_FOCUSED :
this.ANDROID_VIEW_FOCUSED;
if (isExploreByTouch) {
// This isn't really used by TalkBack so this is a half-hearted attempt
@@ -267,21 +270,25 @@ AndroidPresenter.prototype.pivotChanged =
}
let brailleOutput = {};
if (!this._braillePresenter) {
this._braillePresenter = new BraillePresenter();
if (Utils.AndroidSdkVersion >= 16) {
if (!this._braillePresenter) {
this._braillePresenter = new BraillePresenter();
}
brailleOutput = this._braillePresenter.pivotChanged(aContext, aReason).
details;
}
brailleOutput = this._braillePresenter.pivotChanged(aContext, aReason).
details;
if (aReason === Ci.nsIAccessiblePivot.REASON_TEXT) {
let adjustedText = aContext.textAndAdjustedOffsets;
if (Utils.AndroidSdkVersion >= 16) {
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) ?
@@ -364,7 +371,7 @@ AndroidPresenter.prototype.textSelectionChanged =
aOldEnd, aIsFromUserInput) {
let androidEvents = [];
if (!aIsFromUserInput) {
if (Utils.AndroidSdkVersion >= 14 && !aIsFromUserInput) {
if (!this._braillePresenter) {
this._braillePresenter = new BraillePresenter();
}
@@ -381,7 +388,7 @@ AndroidPresenter.prototype.textSelectionChanged =
});
}
if (aIsFromUserInput) {
if (Utils.AndroidSdkVersion >= 16 && aIsFromUserInput) {
let [from, to] = aOldStart < aStart ?
[aOldStart, aStart] : [aStart, aOldStart];
androidEvents.push({
@@ -400,6 +407,10 @@ 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: [],
@@ -409,7 +420,7 @@ AndroidPresenter.prototype.viewportChanged =
maxScrollY: aWindow.scrollMaxY
}];
if (aCurrentContext) {
if (Utils.AndroidSdkVersion >= 16 && aCurrentContext) {
let currentAcc = aCurrentContext.accessibleForBounds;
if (Utils.isAliveAndVisible(currentAcc)) {
events.push({
@@ -436,7 +447,8 @@ AndroidPresenter.prototype.announce =
return {
type: this.type,
details: [{
eventType: this.ANDROID_ANNOUNCEMENT,
eventType: (Utils.AndroidSdkVersion >= 16) ?
this.ANDROID_ANNOUNCEMENT : this.ANDROID_VIEW_TEXT_CHANGED,
text: [localizedAnnouncement],
addedCount: localizedAnnouncement.length,
removedCount: 0,
@@ -668,6 +680,7 @@ this.Presentation = { // jshint ignore:line
get presenters() {
delete this.presenters;
let presenterMap = {
'mobile/android': [VisualPresenter, AndroidPresenter],
'b2g': [VisualPresenter, B2GPresenter],
'browser': [VisualPresenter, B2GPresenter, AndroidPresenter]
};
+28 -1
View File
@@ -33,7 +33,9 @@ this.Utils = { // jshint ignore:line
_buildAppMap: {
'{3c2e2abc-06d4-11e1-ac3b-374f68613e61}': 'b2g',
'{d1bfe7d9-c01e-4237-998b-7b5f960a4314}': 'graphene',
'{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': 'browser'
'{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': 'browser',
'{aa3c5121-dab2-40e2-81ca-7ea25febc110}': 'mobile/android',
'{a23983c0-fd0e-11dc-95ff-0800200c9a66}': 'mobile/xul'
},
init: function Utils_init(aWindow) {
@@ -109,13 +111,35 @@ 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;
}
@@ -125,6 +149,9 @@ this.Utils = { // jshint ignore:line
if (!this.BrowserApp) {
return null;
}
if (this.MozBuildApp == 'b2g') {
return this.BrowserApp.contentBrowser;
}
return this.BrowserApp.selectedBrowser;
},
+4 -2
View File
@@ -21,10 +21,12 @@ DIRS += [ 'aom',
'interfaces',
'ipc',
'jsat',
'xpcom',
'xul'
'xpcom'
]
if CONFIG['MOZ_XUL']:
DIRS += ['xul']
TEST_DIRS += ['tests/mochitest']
BROWSER_CHROME_MANIFESTS += [
@@ -67,7 +67,7 @@
* Change scrollbar styles from hidden to auto. That makes us to create an
* accessible for scroll area.
*/
function changeScrollStyles(aContainerID, aScrollAreaID)
function changeScrollbarStyles(aContainerID, aScrollAreaID)
{
this.container = getAccessible(aContainerID);
this.scrollAreaNode = getNode(aScrollAreaID);
@@ -77,7 +77,7 @@
new invokerChecker(EVENT_REORDER, this.container)
];
this.invoke = function changeScrollStyles_invoke()
this.invoke = function changeScrollbarStyles_invoke()
{
var accTree =
{ SECTION: [] };
@@ -86,7 +86,7 @@
this.scrollAreaNode.style.overflow = "auto";
}
this.finalCheck = function changeScrollStyles_finalCheck()
this.finalCheck = function changeScrollbarStyles_finalCheck()
{
var accTree =
{ SECTION: [ // container
@@ -95,7 +95,7 @@
testAccessibleTree(this.container, accTree);
}
this.getID = function changeScrollStyles_getID()
this.getID = function changeScrollbarStyles_getID()
{
return "change scrollbar styles " + prettyName(aScrollAreaID);
}
@@ -114,7 +114,7 @@
gQueue = new eventQueue();
gQueue.push(new changeScrollRange("container", "scrollarea"));
gQueue.push(new changeScrollStyles("container2", "scrollarea2"));
gQueue.push(new changeScrollbarStyles("container2", "scrollarea2"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
+13
View File
@@ -35,6 +35,19 @@ 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
+7 -3
View File
@@ -33,11 +33,15 @@ 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',
Vendored
+1
View File
@@ -21,6 +21,7 @@ builtin(include, build/autoconf/frameptr.m4)dnl
builtin(include, build/autoconf/compiler-opts.m4)dnl
builtin(include, build/autoconf/expandlibs.m4)dnl
builtin(include, build/autoconf/arch.m4)dnl
builtin(include, build/autoconf/android.m4)dnl
builtin(include, build/autoconf/zlib.m4)dnl
builtin(include, build/autoconf/icu.m4)dnl
builtin(include, build/autoconf/clang-plugin.m4)dnl
@@ -0,0 +1,54 @@
/* 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;
}
}
@@ -0,0 +1,175 @@
/* 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);
}
}
}
}
}
@@ -0,0 +1,627 @@
/* 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();
}
}
+10
View File
@@ -0,0 +1,10 @@
# 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
@@ -0,0 +1,258 @@
/* 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);
}
}
}
}
}
@@ -0,0 +1,62 @@
/* 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;
}
}
@@ -0,0 +1,15 @@
/* 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;
}
}
@@ -0,0 +1,75 @@
/* 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;
}
}
@@ -0,0 +1,84 @@
/* 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.");
}
}
+23
View File
@@ -0,0 +1,23 @@
# -*- 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',
]
@@ -0,0 +1,81 @@
/* 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);
}
}
@@ -0,0 +1,267 @@
/* 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.");
}
}
+288
View File
@@ -0,0 +1,288 @@
/* 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());
}
}
+376
View File
@@ -0,0 +1,376 @@
dnl This Source Code Form is subject to the terms of the Mozilla Public
dnl License, v. 2.0. If a copy of the MPL was not distributed with this
dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
AC_DEFUN([MOZ_ANDROID_NDK],
[
MOZ_ARG_WITH_STRING(android-cxx-stl,
[ --with-android-cxx-stl=VALUE
use the specified C++ STL (libstdc++, libc++)],
android_cxx_stl=$withval,
android_cxx_stl=libc++)
case "$target" in
*-android*|*-linuxandroid*)
dnl $android_platform will be set for us by Python configure.
CPPFLAGS="-idirafter $android_platform/usr/include $CPPFLAGS"
CFLAGS="-fno-short-enums -fno-exceptions $CFLAGS"
CXXFLAGS="-fno-short-enums -fno-exceptions $CXXFLAGS"
ASFLAGS="-idirafter $android_platform/usr/include -DANDROID $ASFLAGS"
dnl Add --allow-shlib-undefined, because libGLESv2 links to an
dnl undefined symbol (present on the hardware, just not in the
dnl NDK.)
LDFLAGS="-L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform -Wl,--allow-shlib-undefined $LDFLAGS"
dnl Add -llog by default, since we use it all over the place.
LIBS="-llog $LIBS"
ANDROID_PLATFORM="${android_platform}"
AC_DEFINE(ANDROID)
AC_SUBST(ANDROID_PLATFORM)
;;
esac
])
AC_DEFUN([MOZ_ANDROID_CPU_ARCH],
[
if test "$OS_TARGET" = "Android"; then
case "${CPU_ARCH}-${MOZ_ARCH}" in
arm-armv7*)
ANDROID_CPU_ARCH=armeabi-v7a
;;
arm-*)
ANDROID_CPU_ARCH=armeabi
;;
x86-*)
ANDROID_CPU_ARCH=x86
;;
mips32-*) # When target_cpu is mipsel, CPU_ARCH is mips32
ANDROID_CPU_ARCH=mips
;;
aarch64-*)
ANDROID_CPU_ARCH=arm64-v8a
;;
esac
AC_SUBST(ANDROID_CPU_ARCH)
fi
])
AC_DEFUN([MOZ_ANDROID_STLPORT],
[
if test "$OS_TARGET" = "Android"; then
cpu_arch_dir="$ANDROID_CPU_ARCH"
# NDK r12 removed the arm/thumb library split and just made everything
# thumb by default. Attempt to compensate.
if test "$MOZ_THUMB2" = 1 -a -d "$cpu_arch_dir/thumb"; then
cpu_arch_dir="$cpu_arch_dir/thumb"
fi
if test -z "$STLPORT_CPPFLAGS$STLPORT_LIBS"; then
case "$android_cxx_stl" in
libstdc++)
# android-ndk-r8b and later
ndk_base="$android_ndk/sources/cxx-stl/gnu-libstdc++/$android_gnu_compiler_version"
ndk_libs_include="$ndk_base/libs/$ANDROID_CPU_ARCH"
ndk_libs="$ndk_base/libs/$cpu_arch_dir"
ndk_include="$ndk_base/include"
if ! test -e "$ndk_libs/libgnustl_static.a"; then
AC_MSG_ERROR([Couldn't find path to gnu-libstdc++ in the android ndk])
fi
STLPORT_LIBS="-L$ndk_libs -lgnustl_static"
STLPORT_CPPFLAGS="-I$ndk_include -I$ndk_include/backward -I$ndk_libs_include/include"
;;
libc++)
# android-ndk-r8b and later
ndk_base="$android_ndk/sources/cxx-stl"
cxx_base="$ndk_base/llvm-libc++"
cxx_libs="$cxx_base/libs/$cpu_arch_dir"
cxx_include="$cxx_base/libcxx/include"
cxxabi_base="$ndk_base/llvm-libc++abi"
cxxabi_include="$cxxabi_base/libcxxabi/include"
if ! test -e "$cxx_libs/libc++_static.a"; then
AC_MSG_ERROR([Couldn't find path to llvm-libc++ in the android ndk])
fi
STLPORT_LIBS="-L$cxx_libs -lc++_static"
# NDK r12 split the libc++ runtime libraries into pieces.
for lib in c++abi unwind android_support; do
if test -e "$cxx_libs/lib${lib}.a"; then
STLPORT_LIBS="$STLPORT_LIBS -l${lib}"
fi
done
# Add android/support/include/ for prototyping long double math
# functions, locale-specific C library functions, multibyte support,
# etc.
STLPORT_CPPFLAGS="-I$android_ndk/sources/android/support/include -I$cxx_include -I$cxxabi_include"
;;
*)
AC_MSG_ERROR([Bad value for --enable-android-cxx-stl])
;;
esac
fi
CXXFLAGS="$CXXFLAGS $STLPORT_CPPFLAGS"
fi
MOZ_ANDROID_CXX_STL=$android_cxx_stl
AC_SUBST([MOZ_ANDROID_CXX_STL])
AC_SUBST([STLPORT_LIBS])
])
AC_DEFUN([concat],[$1$2$3$4])
dnl Find a component of an AAR.
dnl Arg 1: variable name to expose, like ANDROID_SUPPORT_V4_LIB.
dnl Arg 2: path to component.
dnl Arg 3: if non-empty, expect and require component.
AC_DEFUN([MOZ_ANDROID_AAR_COMPONENT], [
ifelse([$3], ,
[
if test -e "$$1" ; then
AC_MSG_ERROR([Found unexpected exploded $1!])
fi
],
[
AC_MSG_CHECKING([for $1])
$1="$2"
if ! test -e "$$1" ; then
AC_MSG_ERROR([Could not find required exploded $1!])
fi
AC_MSG_RESULT([$$1])
AC_SUBST($1)
])
])
dnl Find an AAR and expose variables representing its exploded components.
dnl AC_SUBSTs ANDROID_NAME_{AAR,AAR_RES,AAR_LIB,AAR_INTERNAL_LIB}.
dnl Arg 1: name, like play-services-base
dnl Arg 2: version, like 7.8.0
dnl Arg 3: extras subdirectory, either android or google
dnl Arg 4: package subdirectory, like com/google/android/gms
dnl Arg 5: if non-empty, expect and require internal_impl JAR.
dnl Arg 6: if non-empty, expect and require assets/ directory.
AC_DEFUN([MOZ_ANDROID_AAR],[
define([local_aar_var_base], translit($1, [-a-z], [_A-Z]))
define([local_aar_var], concat(ANDROID_, local_aar_var_base, _AAR))
local_aar_var="$ANDROID_SDK_ROOT/extras/$3/m2repository/$4/$1/$2/$1-$2.aar"
AC_MSG_CHECKING([for $1 AAR])
if ! test -e "$local_aar_var" ; then
AC_MSG_ERROR([You must download the $1 AAR. Run the Android SDK tool and install the Android and Google Support Repositories under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (Looked for $local_aar_var)])
fi
AC_SUBST(local_aar_var)
AC_MSG_RESULT([$local_aar_var])
if ! $PYTHON -m mozbuild.action.explode_aar --destdir=$MOZ_BUILD_ROOT/dist/exploded-aar $local_aar_var ; then
AC_MSG_ERROR([Could not explode $local_aar_var!])
fi
define([root], $MOZ_BUILD_ROOT/dist/exploded-aar/$1-$2/)
MOZ_ANDROID_AAR_COMPONENT(concat(local_aar_var, _LIB), concat(root, $1-$2-classes.jar), REQUIRED)
MOZ_ANDROID_AAR_COMPONENT(concat(local_aar_var, _RES), concat(root, res), REQUIRED)
MOZ_ANDROID_AAR_COMPONENT(concat(local_aar_var, _INTERNAL_LIB), concat(root, libs/$1-$2-internal_impl-$2.jar), $5)
MOZ_ANDROID_AAR_COMPONENT(concat(local_aar_var, _ASSETS), concat(root, assets), $6)
])
AC_DEFUN([MOZ_ANDROID_GOOGLE_PLAY_SERVICES],
[
if test -n "$MOZ_NATIVE_DEVICES" ; then
AC_SUBST(MOZ_NATIVE_DEVICES)
MOZ_ANDROID_AAR(play-services-base, $ANDROID_GOOGLE_PLAY_SERVICES_VERSION, google, com/google/android/gms)
MOZ_ANDROID_AAR(play-services-basement, $ANDROID_GOOGLE_PLAY_SERVICES_VERSION, google, com/google/android/gms)
MOZ_ANDROID_AAR(play-services-cast, $ANDROID_GOOGLE_PLAY_SERVICES_VERSION, google, com/google/android/gms)
MOZ_ANDROID_AAR(mediarouter-v7, $ANDROID_SUPPORT_LIBRARY_VERSION, android, com/android/support, REQUIRED_INTERNAL_IMPL)
fi
])
AC_DEFUN([MOZ_ANDROID_GOOGLE_CLOUD_MESSAGING],
[
if test -n "$MOZ_ANDROID_GCM" ; then
MOZ_ANDROID_AAR(play-services-base, $ANDROID_GOOGLE_PLAY_SERVICES_VERSION, google, com/google/android/gms)
MOZ_ANDROID_AAR(play-services-basement, $ANDROID_GOOGLE_PLAY_SERVICES_VERSION, google, com/google/android/gms)
MOZ_ANDROID_AAR(play-services-gcm, $ANDROID_GOOGLE_PLAY_SERVICES_VERSION, google, com/google/android/gms)
MOZ_ANDROID_AAR(play-services-measurement, $ANDROID_GOOGLE_PLAY_SERVICES_VERSION, google, com/google/android/gms)
fi
])
AC_DEFUN([MOZ_ANDROID_INSTALL_TRACKING],
[
if test -n "$MOZ_INSTALL_TRACKING"; then
AC_SUBST(MOZ_INSTALL_TRACKING)
MOZ_ANDROID_AAR(play-services-ads, $ANDROID_GOOGLE_PLAY_SERVICES_VERSION, google, com/google/android/gms)
MOZ_ANDROID_AAR(play-services-basement, $ANDROID_GOOGLE_PLAY_SERVICES_VERSION, google, com/google/android/gms)
fi
])
dnl Configure an Android SDK.
dnl Arg 1: target SDK version, like 23.
dnl Arg 2: list of build-tools versions, like "23.0.3 23.0.1".
AC_DEFUN([MOZ_ANDROID_SDK],
[
MOZ_ARG_WITH_STRING(android-sdk,
[ --with-android-sdk=DIR
location where the Android SDK can be found (like ~/.mozbuild/android-sdk-linux)],
android_sdk_root=$withval)
android_sdk_root=${withval%/platforms/android-*}
case "$target" in
*-android*|*-linuxandroid*)
if test -z "$android_sdk_root" ; then
AC_MSG_ERROR([You must specify --with-android-sdk=/path/to/sdk when targeting Android.])
fi
# We were given an old-style
# --with-android-sdk=/path/to/sdk/platforms/android-*. We could warn, but
# we'll get compliance by forcing the issue.
if test -e "$withval"/source.properties ; then
AC_MSG_ERROR([Including platforms/android-* in --with-android-sdk arguments is deprecated. Use --with-android-sdk=$android_sdk_root.])
fi
android_target_sdk=$1
AC_MSG_CHECKING([for Android SDK platform version $android_target_sdk])
android_sdk=$android_sdk_root/platforms/android-$android_target_sdk
if ! test -e "$android_sdk/source.properties" ; then
AC_MSG_ERROR([You must download Android SDK platform version $android_target_sdk. Try |mach bootstrap|. (Looked for $android_sdk)])
fi
AC_MSG_RESULT([$android_sdk])
AC_MSG_CHECKING([for Android build-tools])
android_build_tools_base="$android_sdk_root"/build-tools
android_build_tools_version=""
for version in $2; do
android_build_tools="$android_build_tools_base"/$version
if test -d "$android_build_tools" -a -f "$android_build_tools/aapt"; then
android_build_tools_version=$version
AC_MSG_RESULT([$android_build_tools])
break
fi
done
if test "$android_build_tools_version" = ""; then
version=$(echo $2 | cut -d" " -f1)
AC_MSG_ERROR([You must install the Android build-tools version $version. Try |mach bootstrap|. (Looked for "$android_build_tools_base"/$version)])
fi
MOZ_PATH_PROG(ZIPALIGN, zipalign, :, [$android_build_tools])
MOZ_PATH_PROG(DX, dx, :, [$android_build_tools])
MOZ_PATH_PROG(AAPT, aapt, :, [$android_build_tools])
MOZ_PATH_PROG(AIDL, aidl, :, [$android_build_tools])
if test -z "$ZIPALIGN" -o "$ZIPALIGN" = ":"; then
AC_MSG_ERROR([The program zipalign was not found. Try |mach bootstrap|.])
fi
if test -z "$DX" -o "$DX" = ":"; then
AC_MSG_ERROR([The program dx was not found. Try |mach bootstrap|.])
fi
if test -z "$AAPT" -o "$AAPT" = ":"; then
AC_MSG_ERROR([The program aapt was not found. Try |mach bootstrap|.])
fi
if test -z "$AIDL" -o "$AIDL" = ":"; then
AC_MSG_ERROR([The program aidl was not found. Try |mach bootstrap|.])
fi
android_platform_tools="$android_sdk_root"/platform-tools
AC_MSG_CHECKING([for Android platform-tools])
if test -d "$android_platform_tools" -a -f "$android_platform_tools/adb"; then
AC_MSG_RESULT([$android_platform_tools])
else
AC_MSG_ERROR([You must install the Android platform-tools. Try |mach bootstrap|. (Looked for $android_platform_tools)])
fi
MOZ_PATH_PROG(ADB, adb, :, [$android_platform_tools])
if test -z "$ADB" -o "$ADB" = ":"; then
AC_MSG_ERROR([The program adb was not found. Try |mach bootstrap|.])
fi
android_tools="$android_sdk_root"/tools
AC_MSG_CHECKING([for Android tools])
if test -d "$android_tools" -a -f "$android_tools/emulator"; then
AC_MSG_RESULT([$android_tools])
else
AC_MSG_ERROR([You must install the Android tools. Try |mach bootstrap|. (Looked for $android_tools)])
fi
MOZ_PATH_PROG(EMULATOR, emulator, :, [$android_tools])
if test -z "$EMULATOR" -o "$EMULATOR" = ":"; then
AC_MSG_ERROR([The program emulator was not found. Try |mach bootstrap|.])
fi
ANDROID_TARGET_SDK="${android_target_sdk}"
ANDROID_SDK="${android_sdk}"
ANDROID_SDK_ROOT="${android_sdk_root}"
ANDROID_TOOLS="${android_tools}"
ANDROID_BUILD_TOOLS_VERSION="$android_build_tools_version"
AC_DEFINE_UNQUOTED(ANDROID_TARGET_SDK,$ANDROID_TARGET_SDK)
AC_SUBST(ANDROID_TARGET_SDK)
AC_SUBST(ANDROID_SDK_ROOT)
AC_SUBST(ANDROID_SDK)
AC_SUBST(ANDROID_TOOLS)
AC_SUBST(ANDROID_BUILD_TOOLS_VERSION)
MOZ_ANDROID_AAR(customtabs, $ANDROID_SUPPORT_LIBRARY_VERSION, android, com/android/support)
MOZ_ANDROID_AAR(appcompat-v7, $ANDROID_SUPPORT_LIBRARY_VERSION, android, com/android/support)
MOZ_ANDROID_AAR(support-vector-drawable, $ANDROID_SUPPORT_LIBRARY_VERSION, android, com/android/support)
MOZ_ANDROID_AAR(animated-vector-drawable, $ANDROID_SUPPORT_LIBRARY_VERSION, android, com/android/support)
MOZ_ANDROID_AAR(cardview-v7, $ANDROID_SUPPORT_LIBRARY_VERSION, android, com/android/support)
MOZ_ANDROID_AAR(design, $ANDROID_SUPPORT_LIBRARY_VERSION, android, com/android/support)
MOZ_ANDROID_AAR(recyclerview-v7, $ANDROID_SUPPORT_LIBRARY_VERSION, android, com/android/support)
MOZ_ANDROID_AAR(support-v4, $ANDROID_SUPPORT_LIBRARY_VERSION, android, com/android/support, REQUIRED_INTERNAL_IMPL)
MOZ_ANDROID_AAR(palette-v7, $ANDROID_SUPPORT_LIBRARY_VERSION, android, com/android/support)
ANDROID_SUPPORT_ANNOTATIONS_JAR="$ANDROID_SDK_ROOT/extras/android/m2repository/com/android/support/support-annotations/$ANDROID_SUPPORT_LIBRARY_VERSION/support-annotations-$ANDROID_SUPPORT_LIBRARY_VERSION.jar"
AC_MSG_CHECKING([for support-annotations JAR])
if ! test -e $ANDROID_SUPPORT_ANNOTATIONS_JAR ; then
AC_MSG_ERROR([You must download the support-annotations lib. Run the Android SDK tool and install the Android Support Repository under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_SUPPORT_ANNOTATIONS_JAR)])
fi
AC_MSG_RESULT([$ANDROID_SUPPORT_ANNOTATIONS_JAR])
AC_SUBST(ANDROID_SUPPORT_ANNOTATIONS_JAR)
ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB=$ANDROID_SUPPORT_ANNOTATIONS_JAR
AC_SUBST(ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB)
;;
esac
MOZ_ARG_WITH_STRING(android-min-sdk,
[ --with-android-min-sdk=[VER] Impose a minimum Firefox for Android SDK version],
[ MOZ_ANDROID_MIN_SDK_VERSION=$withval ])
MOZ_ARG_WITH_STRING(android-max-sdk,
[ --with-android-max-sdk=[VER] Impose a maximum Firefox for Android SDK version],
[ MOZ_ANDROID_MAX_SDK_VERSION=$withval ])
if test -n "$MOZ_ANDROID_MIN_SDK_VERSION"; then
if test -n "$MOZ_ANDROID_MAX_SDK_VERSION"; then
if test $MOZ_ANDROID_MAX_SDK_VERSION -lt $MOZ_ANDROID_MIN_SDK_VERSION ; then
AC_MSG_ERROR([--with-android-max-sdk must be at least the value of --with-android-min-sdk.])
fi
fi
if test $MOZ_ANDROID_MIN_SDK_VERSION -gt $ANDROID_TARGET_SDK ; then
AC_MSG_ERROR([--with-android-min-sdk is expected to be less than $ANDROID_TARGET_SDK])
fi
AC_DEFINE_UNQUOTED(MOZ_ANDROID_MIN_SDK_VERSION, $MOZ_ANDROID_MIN_SDK_VERSION)
AC_SUBST(MOZ_ANDROID_MIN_SDK_VERSION)
fi
if test -n "$MOZ_ANDROID_MAX_SDK_VERSION"; then
AC_DEFINE_UNQUOTED(MOZ_ANDROID_MAX_SDK_VERSION, $MOZ_ANDROID_MAX_SDK_VERSION)
AC_SUBST(MOZ_ANDROID_MAX_SDK_VERSION)
fi
])
+12
View File
@@ -28,12 +28,24 @@ 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 -8
View File
@@ -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
dnl Default to MSVC for win32 and gcc-4.2 for darwin
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 -pipe"
CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno -pipe"
CFLAGS="$CFLAGS -fno-math-errno"
CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
if test "$CPU_ARCH" = "x86" -o "$CPU_ARCH" = "x86_64"; then
CFLAGS="$CFLAGS -msse2 -mfpmath=sse"
@@ -186,8 +186,7 @@ if test "$GNU_CC"; then
if test -z "$CLANG_CC"; then
case "$CC_VERSION" in
4.* | 5.* | 6.*)
AC_MSG_ERROR([Unsupported GCC version.])
4.* | 5.*)
;;
*)
# Lifetime Dead Store Elimination level 2 (default in GCC6+) breaks Gecko.
@@ -271,9 +270,18 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$DEVELOPER_OPTIONS"; then
fi
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=
# 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
MOZ_ARG_ENABLE_BOOL(pie,
[ --enable-pie Enable Position Independent Executables],
+6 -2
View File
@@ -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-dietlibc | linux-newlib* | \
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
kopensolaris*-gnu* | \
@@ -122,6 +122,10 @@ 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 ]
@@ -1385,7 +1389,7 @@ case $os in
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+5
View File
@@ -7,6 +7,11 @@ 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"
-2
View File
@@ -138,8 +138,6 @@ 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}"
+90
View File
@@ -0,0 +1,90 @@
.. _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
=============== ==================================== =================
+4 -4
View File
@@ -18,14 +18,14 @@ built tree::
mach build
Then, simply generate the Eclipse build backend::
Then, simply generate the Android Eclipse build backend::
mach build-backend -b CppEclipse
If all goes well, the path to the generated workspace should be
printed.
printed (currently, ``$OBJDIR/android_eclipse``).
To use the generated Eclipse project files, you'll need to
To use the generated Android Eclipse project files, you'll need to
have a Eclipse CDT 8.3 (We plan to follow the latest Eclipse release)
`Eclipse CDT plugin
<https://www.eclipse.org/cdt/>`_
@@ -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
Eclipse project files. You can do this by running ``mach build
Android Eclipse project files. You can do this by running ``mach build
&& mach build-backend -b CppEclipse`` from the
command line.
+1
View File
@@ -33,6 +33,7 @@ integrated development environment (IDE)
.. toctree::
:maxdepth: 1
androideclipse
cppeclipse
visualstudio
+79
View File
@@ -17,5 +17,84 @@ 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``.
+19 -4
View File
@@ -62,7 +62,8 @@ bits
buildapp
The path to the XUL application being built.
For desktop Firefox, this is ``browser``.
For desktop Firefox, this is ``browser``. For Fennec, it's
``mobile/android``. For B2G, it's ``b2g``.
crashreporter
Whether the crash reporter is enabled for this build.
@@ -71,6 +72,13 @@ 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.
@@ -78,6 +86,13 @@ 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.
@@ -92,9 +107,9 @@ nightly_build
os
The operating system the build is produced for. Values for tier-1
supported platforms are ``linux`` and ``win``. For other platforms,
the value is the lowercase version of the ``OS_TARGET`` variable
from ``config.status``.
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``.
Always defined.
+55
View File
@@ -54,3 +54,58 @@ 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.
-5
View File
@@ -63,11 +63,6 @@ def GeckoBinary(linkage='dependent', msvcrt='dynamic', mozglue=None):
LDFLAGS += ['-rdynamic']
if CONFIG['MOZ_MEMORY']:
USE_LIBS += ['memory']
if CONFIG['OS_ARCH'] == 'FreeBSD':
# Make sure this function is linked in, so that it is
# executed at executable load (it has the 'constructor'
# flag).
LDFLAGS += ['-u', 'jemalloc_FreeBSD_init']
elif mozglue == 'library':
LIBRARY_DEFINES['MOZ_HAS_MOZGLUE'] = True
if not CONFIG['MOZ_GLUE_IN_PROGRAM']:
+40 -4
View File
@@ -3,9 +3,7 @@
# 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('gyp_base.mozbuild')
gyp_vars.update({
gyp_vars = {
'lsan': 0,
'asan': 0,
'build_with_mozilla': 1,
@@ -20,6 +18,8 @@ gyp_vars.update({
'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,7 +67,43 @@ gyp_vars.update({
# 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:
-36
View File
@@ -1,36 +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/.
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 -14
View File
@@ -35,6 +35,7 @@ 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',
@@ -64,6 +65,11 @@ 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',
@@ -84,6 +90,9 @@ SEARCH_PATHS = [
'testing/mozbase/manifestparser',
'testing/taskcluster',
'testing/tools/autotry',
'testing/web-platform',
'testing/web-platform/harness',
'testing/web-platform/tests/tools/wptserve',
'testing/xpcshell',
'xpcom/idl-parser',
]
@@ -99,16 +108,20 @@ 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',
'testing/web-platform/mach_commands.py',
'testing/xpcshell/mach_commands.py',
'tools/docs/mach_commands.py',
'tools/lint/mach_commands.py',
@@ -189,20 +202,7 @@ 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
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
from mozboot.util import get_state_dir
def telemetry_handler(context, data):
# We have not opted-in to telemetry
+451
View File
@@ -0,0 +1,451 @@
# 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")
+401
View File
@@ -0,0 +1,401 @@
# 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)
+1 -1
View File
@@ -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
# Clear out DIST_FILES if it was set by upload-files.mk (for Android builds)
DIST_FILES =
endif
+7 -1
View File
@@ -3,6 +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/.
with Files('**'):
BUG_COMPONENT = ('Core', 'Build Config')
# This cannot be named "build" because of bug 922191.
SPHINX_TREES['buildsystem'] = 'docs'
@@ -11,6 +14,9 @@ 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',
@@ -64,7 +70,7 @@ if CONFIG['MOZ_ASAN'] and CONFIG['CLANG_CL']:
if CONFIG['MOZ_APP_BASENAME']:
FINAL_TARGET_PP_FILES += ['application.ini']
if CONFIG['MOZ_UPDATER']:
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android' and CONFIG['MOZ_UPDATER']:
FINAL_TARGET_PP_FILES += ['update-settings.ini']
if CONFIG['MOZ_APP_STATIC_INI']:
+149
View File
@@ -0,0 +1,149 @@
# -*- 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')
+3 -2
View File
@@ -42,10 +42,11 @@ def compiler_class(compiler):
def checking_fn(fn):
return fn
@depends_when(self, dependable(flags), when=when)
@depends_when(self, dependable(flags), extra_toolchain_flags, when=when)
@checking_fn
def func(compiler, flags):
def func(compiler, flags, extra_flags):
flags = flags or []
flags += extra_flags or []
flags.append('-c')
if try_invoke_compiler(
+39 -16
View File
@@ -308,7 +308,10 @@ 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 os.startswith('linux'):
if 'android' in os:
canonical_os = 'Android'
canonical_kernel = 'Linux'
elif os.startswith('linux'):
canonical_os = 'GNU'
canonical_kernel = 'Linux'
elif os.startswith('kfreebsd') and os.endswith('-gnu'):
@@ -518,7 +521,6 @@ 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'))
@@ -547,6 +549,13 @@ 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':
@@ -598,7 +607,9 @@ imply_option('--enable-project', application)
@depends(check_build_environment, '--help')
def default_project(build_env, help):
return 'js'
if build_env.topobjdir.endswith('/js/src'):
return 'js'
return 'application/xulrunner'
option('--enable-project', nargs=1, default=default_project,
help='Project to build')
@@ -631,10 +642,9 @@ def external_source_dir(value):
set_config('EXTERNAL_SOURCE_DIR', external_source_dir)
add_old_configure_assignment('EXTERNAL_SOURCE_DIR', external_source_dir)
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')
@depends('--enable-project', '--with-external-source-dir', check_build_environment, '--help')
@imports(_from='os.path', _import='exists')
def build_project(noncomm_build, project, external_source_dir, build_env, help):
def build_project(project, external_source_dir, build_env, help):
if not project:
die('--enable-project is required.')
@@ -645,13 +655,8 @@ def build_project(noncomm_build, project, external_source_dir, build_env, help):
build_app = project[0]
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)
if not external_source_dir and build_app not in ('xulrunner', 'js'):
die('Cannot find project %s', build_app)
build_app_abspath = os.path.join(base_dir, build_app)
@@ -666,7 +671,11 @@ set_define('MOZ_BUILD_APP', build_project)
add_old_configure_assignment('MOZ_BUILD_APP', build_project)
# set RELEASE_OR_BETA and NIGHTLY_BUILD variables for compatibility
# 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)
@depends(check_build_environment, '--help')
@imports(_from='__builtin__', _import='open')
def milestone(build_env, _):
@@ -676,8 +685,12 @@ def milestone(build_env, _):
with open(milestone_path, 'r') as fh:
milestone = fh.read().splitlines()[-1]
is_nightly = None
is_release_or_beta = True
is_nightly = is_release_or_beta = None
if 'a1' in milestone:
is_nightly = True
elif 'a' not in milestone:
is_release_or_beta = True
return namespace(version=milestone,
is_nightly=is_nightly,
@@ -796,3 +809,13 @@ 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
+4
View File
@@ -36,6 +36,10 @@ def keyfile(desc, help=None, callback=lambda x: x):
def simple_keyfile(desc):
value = keyfile(desc)
set_config('MOZ_%s_KEY' % desc.upper().replace(' ', '_'), value)
# Only really required for MOZ_ADJUST_SDK_KEY currently still used in
# old-configure.
add_old_configure_assignment('MOZ_%s_KEY' % desc.upper().replace(' ', '_'),
value)
@template
+8
View File
@@ -64,6 +64,14 @@ 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')
+7 -4
View File
@@ -161,8 +161,6 @@ def old_configure_options(*options):
'--enable-b2g-camera',
'--enable-b2g-ril',
'--enable-bundled-fonts',
'--enable-chrome-compression',
'--enable-chrome-format',
'--enable-clang-plugin',
'--enable-content-sandbox',
'--enable-cookies',
@@ -200,6 +198,7 @@ def old_configure_options(*options):
'--enable-logrefcnt',
'--enable-maintenance-service',
'--enable-memory-sanitizer',
'--enable-mobile-optimize',
'--enable-mozril-geoloc',
'--enable-necko-wifi',
'--enable-negotiateauth',
@@ -225,7 +224,6 @@ def old_configure_options(*options):
'--enable-safe-browsing',
'--enable-sandbox',
'--enable-security-sqlstore',
'--enable-shared-media',
'--enable-signmar',
'--enable-simulator',
'--enable-small-chunk-size',
@@ -249,16 +247,21 @@ 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',
'--with-branding',
'--with-chrome-name',
'--with-crashreporter-enable-percent',
'--with-cross-lib',
'--with-debug-label',
+19 -9
View File
@@ -61,6 +61,15 @@ 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.
@@ -156,8 +165,9 @@ 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).
if toolchain_prefix and (len(toolchain_prefix) == 1):
# 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):
return toolchain_prefix[0]
set_config('TOOLCHAIN_PREFIX', first_toolchain_prefix)
@@ -675,9 +685,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 < '7.1.0':
if info.type == 'gcc' and info.version < '4.9.0':
raise FatalCheckError(
'Only GCC 7.1 or newer is supported (found version %s).'
'Only GCC 4.9 or newer is supported (found version %s).'
% info.version)
# If you want to bump the version check here search for
@@ -830,9 +840,10 @@ 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 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 (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):
#
# #ifdef FUNC
# // Capture the definition of FUNC.
@@ -867,8 +878,7 @@ 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):
# FIXME: Vestigial conditional left over from Android, please remove.
if False:
if c_compiler.type == 'clang' and target.os == 'Android':
return ''
set_define('_LIBCPP_INLINE_VISIBILITY', libcxx_inline_visibility)
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/bash
gcc_version=7.1.0
gcc_version=4.8.5
binutils_version=2.25.1
this_path=$(readlink -f $(dirname $0))
make_flags='-j12'
+1
View File
@@ -40,6 +40,7 @@
fun:malloc
fun:moz_xmalloc
fun:operator new
fun:_Z21XRE_CreateStatsObjectv
...
}
+1 -1
View File
@@ -160,7 +160,7 @@ nsChromeProtocolHandler::NewChannel2(nsIURI* aURI,
file->Exists(&exists);
if (!exists) {
nsAutoCString path;
file->GetPersistentDescriptor(path);
file->GetNativePath(path);
printf("Chrome file doesn't exist: %s\n", path.get());
}
}
+2
View File
@@ -108,7 +108,9 @@ 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)
+6
View File
@@ -9,7 +9,11 @@
#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"
@@ -33,7 +37,9 @@ 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
{
+2
View File
@@ -640,6 +640,7 @@ nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI* aBase)
return &entry->mArray;
}
#ifdef MOZ_XUL
NS_IMETHODIMP
nsChromeRegistryChrome::GetStyleOverlays(nsIURI *aChromeURL,
nsISimpleEnumerator **aResult)
@@ -669,6 +670,7 @@ nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL,
return NS_NewArrayEnumerator(aResult, *parray);
}
#endif // MOZ_XUL
nsIURI*
nsChromeRegistry::ManifestProcessingContext::GetManifestURI()
+2
View File
@@ -41,10 +41,12 @@ 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
+51
View File
@@ -0,0 +1,51 @@
# 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)
-3
View File
@@ -79,7 +79,6 @@ included_inclnames_to_ignore = set([
'prtypes.h', # NSPR
'selfhosted.out.h', # generated in $OBJDIR
'shellmoduleloader.out.h', # generated in $OBJDIR
'unicode/plurrule.h', # ICU
'unicode/timezone.h', # ICU
'unicode/ucal.h', # ICU
'unicode/uclean.h', # ICU
@@ -87,11 +86,9 @@ included_inclnames_to_ignore = set([
'unicode/udat.h', # ICU
'unicode/udatpg.h', # ICU
'unicode/uenum.h', # ICU
'unicode/uniset.h', # ICU
'unicode/unorm.h', # ICU
'unicode/unum.h', # ICU
'unicode/unumsys.h', # ICU
'unicode/upluralrules.h', # ICU
'unicode/ustring.h', # ICU
'unicode/utypes.h', # ICU
'vtune/VTuneWrapper.h' # VTune
+9 -1
View File
@@ -216,7 +216,7 @@ endif # NO_PROFILE_GUIDED_OPTIMIZE
MAKE_JARS_FLAGS = \
-t $(topsrcdir) \
-f $(MOZ_CHROME_FILE_FORMAT) \
-f $(MOZ_JAR_MAKER_FILE_FORMAT) \
$(NULL)
ifdef USE_EXTENSION_MANIFEST
@@ -550,6 +550,14 @@ 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))
Binary file not shown.
+4 -3
View File
@@ -10,8 +10,9 @@ DIRS += ['lgpllibs']
if not CONFIG['MOZ_SYSTEM_JPEG']:
external_dirs += ['media/libjpeg']
if not CONFIG['MOZ_SYSTEM_BZ2']:
external_dirs += ['modules/libbz2']
if CONFIG['MOZ_UPDATER']:
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']
@@ -54,7 +55,7 @@ external_dirs += [
'media/psshparser'
]
if CONFIG['MOZ_UPDATER']:
if CONFIG['MOZ_LINKER']:
external_dirs += ['modules/xz-embedded']
DIRS += ['../../' + i for i in external_dirs]
+469
View File
@@ -0,0 +1,469 @@
#
# 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)
+15
View File
@@ -0,0 +1,15 @@
# -*- 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',
]
+39
View File
@@ -0,0 +1,39 @@
# -*- 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']
+27
View File
@@ -0,0 +1,27 @@
# 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 $($*)
File renamed without changes.
+3 -9
View File
@@ -8,7 +8,9 @@
#ifndef mozilla_${HEADER}_h
#define mozilla_${HEADER}_h
#if defined(__EXCEPTIONS) && __EXCEPTIONS
// For some reason, Apple's GCC refuses to honor -fno-exceptions when
// compiling ObjC.
#if defined(__EXCEPTIONS) && __EXCEPTIONS && !(__OBJC__ && __GNUC__ && XP_IOS)
# error "STL code can only be used with -fno-exceptions"
#endif
@@ -30,14 +32,6 @@
# define moz_dont_include_mozalloc_for_cstdlib
#endif
#ifndef moz_dont_include_mozalloc_for_type_traits
# define moz_dont_include_mozalloc_for_type_traits
#endif
#ifndef moz_dont_include_mozalloc_for_limits
# define moz_dont_include_mozalloc_for_limits
#endif
// Include mozalloc after the STL header and all other headers it includes
// have been preprocessed.
#if !defined(MOZ_INCLUDE_MOZALLOC_H) && \
+159
View File
@@ -0,0 +1,159 @@
# -*- 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
+4 -2
View File
@@ -1,4 +1,4 @@
# Holds the current platform (Goanna) milestone.
# Holds the current milestone.
# Should be in the format of
#
# x.x.x
@@ -6,6 +6,8 @@
# 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.
#--------------------------------------------------------
5.1.0+
4.6.0
-3
View File
@@ -28,9 +28,6 @@ if CONFIG['HOST_OS_ARCH'] != 'WINNT':
# while the program here is in C.
HostProgram('nsinstall_real', c_only=True)
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
DEFINES['GKMEDIAS_SHARED_LIBRARY'] = True
PYTHON_UNIT_TESTS += [
'tests/test_mozbuild_reading.py',
'tests/unit-expandlibs.py',
+8 -1
View File
@@ -144,9 +144,16 @@ 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
@@ -158,7 +165,7 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),gtk3)
toolkit/library/target: widget/gtk/mozgtk/gtk3/target
endif
ifdef MOZ_LDAP_XPCOM
ldap/target: security/target mozglue/build/target
ldap/target: config/external/nss/target mozglue/build/target
toolkit/library/target: ldap/target
endif
ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library)
+7
View File
@@ -1045,6 +1045,13 @@ 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):
###############################################################################
+218 -16
View File
@@ -164,6 +164,13 @@ all.h
alloca.h
alloc.h
alsa/asoundlib.h
#ifdef ANDROID
android/ashmem.h
android/log.h
android/looper.h
android/native_window.h
android_audio/AudioSystem.h
#endif
ansi_parms.h
a.out.h
app/Cursor.h
@@ -193,6 +200,14 @@ atlimpl.cpp
atlwin.cpp
ATSTypes.h
ATSUnicode.h
#ifdef ANDROID
audio_effects/effect_aec.h
audio_effects/effect_ns.h
AudioParameter.h
AudioSystem.h
AudioTrack.h
avc_utils.h
#endif
Balloons.h
base/pblock.h
base/PCR_Base.h
@@ -203,6 +218,18 @@ Beep.h
be/kernel/image.h
be/kernel/OS.h
bfd.h
#ifdef ANDROID
binder/Binder.h
binder/BinderService.h
binder/IBinder.h
binder/IInterface.h
binder/IMemory.h
binder/IPCThreadState.h
binder/IPermissionController.h
binder/IServiceManager.h
binder/Parcel.h
binder/ProcessState.h
#endif
Bitmap.h
bitset
blapi.h
@@ -281,6 +308,10 @@ dfb_types.h
directfb_strings.h
directfb_keyboard.h
callconv.h
#ifdef ANDROID
camera/Camera.h
camera/CameraParameters.h
#endif
Carbon/Carbon.h
CarbonEvents.h
Carbon.h
@@ -304,6 +335,9 @@ Clipboard.h
cmplrs/stsupport.h
Cocoa/Cocoa.h
CodeFragments.h
#ifdef ANDROID
ColorConverter.h
#endif
comdef.h
commctrl.h
COMMCTRL.H
@@ -332,6 +366,15 @@ ctype.h
curl/curl.h
curl/easy.h
curses.h
#ifdef ANDROID
cutils/android_reboot.h
cutils/atomic.h
cutils/compiler.h
cutils/log.h
cutils/native_handle.h
cutils/properties.h
cutils/sockets.h
#endif
cxxabi.h
DateTimeUtils.h
dbus/dbus.h
@@ -386,6 +429,19 @@ fontconfig/fontconfig.h
fontconfig/fcfreetype.h
Font.h
Fonts.h
#ifdef ANDROID
foundation/ABase.h
foundation/ABitReader.h
foundation/ABuffer.h
foundation/ADebug.h
foundation/AHandler.h
foundation/AHandlerReflector.h
foundation/ALooper.h
foundation/AMessage.h
foundation/AString.h
foundation/base64.h
foundation/hexdump.h
#endif
fp.h
fpieee.h
frame/log.h
@@ -449,8 +505,34 @@ gssapi.h
gtk/gtk.h
gtk/gtkx.h
gtk/gtkunixprint.h
#ifdef ANDROID
gui/BufferQueue.h
gui/ConsumerBase.h
gui/GraphicBufferAlloc.h
gui/IConsumerListener.h
gui/IGraphicBufferAlloc.h
gui/IGraphicBufferProducer.h
gui/ISurfaceComposer.h
gui/ISurfaceComposerClient.h
gui/ISurfaceTexture.h
gui/Surface.h
gui/SurfaceComposerClient.h
gui/SurfaceTextureClient.h
hardware/audio.h
hardware/gralloc.h
hardware/hardware.h
hardware/hwcomposer.h
hardware/lights.h
hardware/power.h
hardware_legacy/power.h
hardware_legacy/uevent.h
hardware_legacy/vibrator.h
#endif
HIToolbox/HIToolbox.h
hlink.h
#ifdef ANDROID
HTTPBase.h
#endif
ia64/sys/inline.h
Icons.h
iconv.h
@@ -542,6 +624,10 @@ libgnomeui/gnome-icon-theme.h
libgnomeui/gnome-ui-init.h
limits.h
link.h
#ifdef ANDROID
linux/android_alarm.h
linux/ashmem.h
#endif
linux/ioprio.h
linux/kernel.h
linux/limits.h
@@ -627,6 +713,53 @@ mapix.h
Math64.h
math.h
mbstring.h
#ifdef ANDROID
android/native_window.h
android/native_window_jni.h
media/AudioEffect.h
media/AudioSystem.h
media/ICrypto.h
media/IOMX.h
media/MediaProfiles.h
media/MediaRecorderBase.h
media/openmax/OMX_Audio.h
media/stagefright/AACWriter.h
media/stagefright/AMRWriter.h
media/stagefright/AudioSource.h
media/stagefright/DataSource.h
media/stagefright/foundation/ABase.h
media/stagefright/foundation/ABitReader.h
media/stagefright/foundation/ABuffer.h
media/stagefright/foundation/ADebug.h
media/stagefright/foundation/AHandler.h
media/stagefright/foundation/AHandlerReflector.h
media/stagefright/foundation/ALooper.h
media/stagefright/foundation/AMessage.h
media/stagefright/foundation/AString.h
media/stagefright/foundation/base64.h
media/stagefright/foundation/hexdump.h
media/stagefright/MediaBuffer.h
media/stagefright/MediaBufferGroup.h
media/stagefright/MediaCodec.h
media/stagefright/MediaCodecList.h
media/stagefright/MediaCodecSource.h
media/stagefright/MediaDefs.h
media/stagefright/MediaErrors.h
media/stagefright/MediaExtractor.h
media/stagefright/MediaSource.h
media/stagefright/MediaWriter.h
media/stagefright/MetaData.h
media/stagefright/MPEG2TSWriter.h
media/stagefright/MPEG4Writer.h
media/stagefright/OMXClient.h
media/stagefright/OMXCodec.h
media/stagefright/openmax/OMX_Core.h
media/stagefright/openmax/OMX_Index.h
media/stagefright/openmax/OMX_IVCommon.h
media/stagefright/openmax/OMX_Types.h
media/stagefright/openmax/OMX_Video.h
media/stagefright/Utils.h
#endif
mem.h
memory.h
Memory.h
@@ -666,6 +799,10 @@ Objsafe.h
ojiapitests.h
ole2.h
oleidl.h
#ifdef ANDROID
OMX.h
OMX_Component.h
#endif
OpenGL/OpenGL.h
OpenTptInternet.h
OpenTransport.h
@@ -711,6 +848,10 @@ PP_Resources.h
PP_Types.h
Printing.h
Print/PMPrintingDialogExtensions.h
#ifdef ANDROID
private/android_filesystem_config.h
private/qucomextra_p.h
#endif
Processes.h
process.h
Process.h
@@ -777,6 +918,43 @@ Sound.h
soundcard.h
sqlite3.h
sstream
#ifdef ANDROID
stagefright/AACWriter.h
stagefright/AMRWriter.h
stagefright/AudioSource.h
stagefright/DataSource.h
stagefright/foundation/ABase.h
stagefright/foundation/ABitReader.h
stagefright/foundation/ABuffer.h
stagefright/foundation/ADebug.h
stagefright/foundation/AHandler.h
stagefright/foundation/AHandlerReflector.h
stagefright/foundation/ALooper.h
stagefright/foundation/AMessage.h
stagefright/foundation/AString.h
stagefright/foundation/base64.h
stagefright/foundation/hexdump.h
stagefright/MediaBuffer.h
stagefright/MediaBufferGroup.h
stagefright/MediaCodec.h
stagefright/MediaDefs.h
stagefright/MediaErrors.h
stagefright/MediaExtractor.h
stagefright/MediaSource.h
stagefright/MediaWriter.h
stagefright/MetaData.h
stagefright/MPEG2TSWriter.h
stagefright/MPEG4Writer.h
stagefright/OMXCodec.h
stagefright/OMXClient.h
stagefright/openmax/OMX_Component.h
stagefright/openmax/OMX_Core.h
stagefright/openmax/OMX_Index.h
stagefright/openmax/OMX_IVCommon.h
stagefright/openmax/OMX_Types.h
stagefright/openmax/OMX_Video.h
stagefright/Utils.h
#endif
StandardFile.h
starlet.h
stat.h
@@ -804,6 +982,9 @@ SupportDefs.h
support/String.h
support/SupportDefs.h
support/TLS.h
#ifdef ANDROID
suspend/autosuspend.h
#endif
svrcore.h
symconst.h
sym.h
@@ -891,6 +1072,12 @@ sys/unistd.h
sys/utsname.h
sys/vfs.h
sys/wait.h
#ifdef ANDROID
sysutils/NetlinkEvent.h
system/audio.h
system/graphics.h
system/window.h
#endif
tables.h
TArray.h
TArrayIterator.h
@@ -933,6 +1120,15 @@ UEventMgr.h
UException.h
UExtractFromAEDesc.h
UGWorld.h
#ifdef ANDROID
ui/ANativeObjectBase.h
ui/egl/android_natives.h
ui/Fence.h
ui/FramebufferNativeWindow.h
ui/GraphicBuffer.h
ui/Rect.h
ui/Region.h
#endif
UKeyFilters.h
ulocks.h
ulserrno.h
@@ -954,6 +1150,28 @@ UReanimator.h
URegions.h
URegistrar.h
UResourceMgr.h
#ifdef ANDROID
utils/BitSet.h
utils/CallStack.h
utils/Errors.h
utils/FileMap.h
utils/KeyedVector.h
utils/List.h
utils/Log.h
utils/Looper.h
utils/PropertyMap.h
utils/RefBase.h
utils/String16.h
utils/String8.h
utils/threads.h
utils/TextOutput.h
utils/Timers.h
utils/Trace.h
utils/TypeHelpers.h
utils/Unicode.h
utils/Vector.h
utils/VectorImpl.h
#endif
urlhist.h
urlmon.h
UScrap.h
@@ -1070,22 +1288,6 @@ QtSparql/qsparqlresult.h
#if MOZ_TREE_PIXMAN!=1
pixman.h
#endif
#ifdef GKMEDIAS_SHARED_LIBRARY
vpx/vpx_codec.h
vpx/vpx_decoder.h
vpx/vpx_encoder.h
vpx/vp8cx.h
vpx/vp8dx.h
vpx_mem/vpx_mem.h
vorbis/codec.h
theora/theoradec.h
tremor/ivorbiscodec.h
speex/speex_resampler.h
ogg/ogg.h
ogg/os_types.h
nestegg/nestegg.h
cubeb/cubeb.h
#endif
gst/gst.h
gst/app/gstappsink.h
gst/app/gstappsrc.h
+1 -1
View File
@@ -22,7 +22,7 @@ REF_MANIFEST = $(if $(USE_EXTENSION_MANIFEST),chrome.manifest,test.manifest)
check-%::
if test -d $(FINAL_TARGET); then rm -rf $(FINAL_TARGET); fi;
$(MAKE) realchrome MOZ_CHROME_FILE_FORMAT=$*
$(MAKE) realchrome MOZ_JAR_MAKER_FILE_FORMAT=$*
@echo 'Comparing manifests...'
@if ! sort $(MY_MANIFEST) | diff --text -U 0 $(srcdir)/../$(REF_MANIFEST).$* - ; then \
echo 'TEST-UNEXPECTED-FAIL | config/tests/$(REF_MANIFEST).$* | differing content in manifest!' ; \
+2 -2
View File
@@ -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 = "UXP Contributors";
my $trademarks = "Goanna is (tm) Moonchild Productions";
my $company = "Moonchild Productions";
my $trademarks = "Moonchild";
my $productname = "UXP";
+6064 -11064
View File
File diff suppressed because it is too large. Load diff
+39 -218
View File
@@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.36.0"
#define SQLITE_VERSION_NUMBER 3036000
#define SQLITE_SOURCE_ID "2021-06-18 18:36:39 5c9a6c06871cb9fe42814af9c039eb6da5427a6ec28f187af7ebfb62eafa66e5"
#define SQLITE_VERSION "3.33.0"
#define SQLITE_VERSION_NUMBER 3033000
#define SQLITE_SOURCE_ID "2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -504,7 +504,6 @@ 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))
@@ -1128,23 +1127,6 @@ 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
@@ -1184,8 +1166,6 @@ 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
@@ -2134,13 +2114,7 @@ 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.
**
** <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>
** which case the trigger setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
@@ -2151,13 +2125,7 @@ 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.
**
** <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>
** which case the view setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
@@ -3530,7 +3498,6 @@ 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
@@ -3729,7 +3696,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 not be
** corruption or segfaults may occur. The value Y should 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
@@ -4198,15 +4165,6 @@ 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);
@@ -4376,22 +4334,18 @@ 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 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 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 sixth argument to sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
@@ -5133,6 +5087,7 @@ 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
@@ -5142,6 +5097,7 @@ 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()].)^
@@ -6230,57 +6186,6 @@ 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
@@ -7807,10 +7712,7 @@ 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_SEEK_COUNT 30
#define SQLITE_TESTCTRL_TRACEFLAGS 31
#define SQLITE_TESTCTRL_TUNE 32
#define SQLITE_TESTCTRL_LAST 32 /* Largest TESTCTRL */
#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -9290,11 +9192,10 @@ 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 might return true if the
** method of a [virtual table], then it returns true if and only if the
** column is being fetched as part of an UPDATE operation during which the
** 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
** column value will not change. Applications might use this 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
@@ -9303,12 +9204,6 @@ 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*);
@@ -9450,7 +9345,6 @@ 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
@@ -9483,7 +9377,6 @@ 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.
@@ -9524,7 +9417,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
** DELETE operations on rowid tables.
** INSERT operations on rowid tables.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
@@ -9562,15 +9455,6 @@ 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)
@@ -9591,12 +9475,10 @@ 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.
@@ -9830,8 +9712,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 omitted if SQLite is compiled with the
** [SQLITE_OMIT_DESERIALIZE] option.
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_DESERIALIZE] option.
*/
SQLITE_API unsigned char *sqlite3_serialize(
sqlite3 *db, /* The database connection */
@@ -9882,8 +9764,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 omitted if SQLite is compiled with the
** [SQLITE_OMIT_DESERIALIZE] option.
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_DESERIALIZE] option.
*/
SQLITE_API int sqlite3_deserialize(
sqlite3 *db, /* The database connection */
@@ -10132,38 +10014,6 @@ 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
@@ -10408,22 +10258,6 @@ 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
@@ -10541,14 +10375,6 @@ 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
@@ -10651,23 +10477,18 @@ 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].
**
** 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
** 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
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
** changes.
** 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.
**
** 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,10 +180,13 @@ 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 &&
+5
View File
@@ -11474,6 +11474,7 @@ 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 = {
@@ -11512,6 +11513,10 @@ var Debugger =
if (thisCallback) {
thisCallback(aResponse);
}
if (histogram) {
histogram.add(+new Date() - startTime);
}
}, "DebuggerClient.requester request callback"));
}, "DebuggerClient.requester");
};
@@ -23,19 +23,6 @@ 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,7 +8,14 @@ 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);
@@ -20,6 +27,9 @@ add_task(function* () {
toolbox = target = null;
gBrowser.removeCurrentTab();
// Cleanup
getHostHistogram().clear();
});
function* changeToolboxHost(toolbox) {
@@ -33,5 +43,8 @@ function* changeToolboxHost(toolbox) {
}
function checkResults() {
// STUB
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");
}
@@ -29,7 +29,7 @@ function* testTopLeft(inspector, view) {
elementRulesNb: 4,
firstLineRulesNb: 2,
firstLetterRulesNb: 1,
selectionRulesNb: 1,
selectionRulesNb: 0,
afterRulesNb: 1,
beforeRulesNb: 2
}
@@ -166,7 +166,7 @@ function* testParagraph(inspector, view) {
elementRulesNb: 3,
firstLineRulesNb: 1,
firstLetterRulesNb: 1,
selectionRulesNb: 2,
selectionRulesNb: 1,
beforeRulesNb: 0,
afterRulesNb: 0
});
@@ -216,7 +216,7 @@ function* assertPseudoElementRulesNumbers(selector, inspector, view, ruleNbs) {
firstLetterRules: elementStyle.rules.filter(rule =>
rule.pseudoElement === ":first-letter"),
selectionRules: elementStyle.rules.filter(rule =>
rule.pseudoElement === ":selection"),
rule.pseudoElement === ":-moz-selection"),
beforeRules: elementStyle.rules.filter(rule =>
rule.pseudoElement === ":before"),
afterRules: elementStyle.rules.filter(rule =>
+36
View File
@@ -13,12 +13,18 @@ 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";
@@ -37,6 +43,25 @@ 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");
/**
@@ -52,4 +77,15 @@ 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");
+14 -2
View File
@@ -98,7 +98,11 @@ 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);
@@ -146,8 +150,12 @@ 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?
// Enable experimental options in the UI only in Nightly
#if defined(NIGHTLY_BUILD)
pref("devtools.performance.ui.experimental", true);
#else
pref("devtools.performance.ui.experimental", false);
#endif
// The default cache UI setting
pref("devtools.cache.disabled", false);
@@ -300,8 +308,12 @@ pref("devtools.webconsole.timestampMessages", false);
// to automatically trigger multiline editing (equivalent to shift + enter).
pref("devtools.webconsole.autoMultiline", true);
// Enable the experimental webconsole frontend?
// Enable the experimental webconsole frontend
#if defined(NIGHTLY_BUILD)
pref("devtools.webconsole.new-frontend-enabled", true);
#else
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);
Loaded 100 of 28675 files, more files were not shown because too many files have changed in this diff. Show more