зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
e4c3394a35
|
@ -41,16 +41,17 @@
|
|||
// gSyncUI handles updating the tools menu
|
||||
let gSyncUI = {
|
||||
_obs: ["weave:service:sync:start",
|
||||
"weave:service:sync:finish",
|
||||
"weave:service:sync:error",
|
||||
"weave:service:sync:delayed",
|
||||
"weave:service:quota:remaining",
|
||||
"weave:service:setup-complete",
|
||||
"weave:service:login:start",
|
||||
"weave:service:login:finish",
|
||||
"weave:service:login:error",
|
||||
"weave:service:logout:finish",
|
||||
"weave:service:start-over"],
|
||||
"weave:service:start-over",
|
||||
"weave:ui:login:error",
|
||||
"weave:ui:sync:error",
|
||||
"weave:ui:sync:finish",
|
||||
"weave:ui:clear-error"],
|
||||
|
||||
_unloaded: false,
|
||||
|
||||
|
@ -189,14 +190,6 @@ let gSyncUI = {
|
|||
button.setAttribute("status", "active");
|
||||
},
|
||||
|
||||
onSyncFinish: function SUI_onSyncFinish() {
|
||||
this._onSyncEnd(true);
|
||||
},
|
||||
|
||||
onSyncError: function SUI_onSyncError() {
|
||||
this._onSyncEnd(false);
|
||||
},
|
||||
|
||||
onSyncDelay: function SUI_onSyncDelay() {
|
||||
// basically, we want to just inform users that stuff is going to take a while
|
||||
let title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title");
|
||||
|
@ -215,9 +208,7 @@ let gSyncUI = {
|
|||
onLoginFinish: function SUI_onLoginFinish() {
|
||||
// Clear out any login failure notifications
|
||||
let title = this._stringBundle.GetStringFromName("error.login.title");
|
||||
Weave.Notifications.removeAll(title);
|
||||
|
||||
this.updateUI();
|
||||
this.clearError(title);
|
||||
},
|
||||
|
||||
onLoginError: function SUI_onLoginError() {
|
||||
|
@ -225,15 +216,26 @@ let gSyncUI = {
|
|||
Weave.Notifications.removeAll();
|
||||
|
||||
// if we haven't set up the client, don't show errors
|
||||
if (this._needsSetup() || Weave.Service.shouldIgnoreError()) {
|
||||
if (this._needsSetup()) {
|
||||
this.updateUI();
|
||||
return;
|
||||
}
|
||||
|
||||
let title = this._stringBundle.GetStringFromName("error.login.title");
|
||||
let reason = Weave.Utils.getErrorString(Weave.Status.login);
|
||||
let description =
|
||||
this._stringBundle.formatStringFromName("error.login.description", [reason], 1);
|
||||
|
||||
let description;
|
||||
if (Weave.Status.sync == Weave.PROLONGED_SYNC_FAILURE) {
|
||||
// Convert to days
|
||||
let lastSync =
|
||||
Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400;
|
||||
description =
|
||||
this._stringBundle.formatStringFromName("error.sync.prolonged_failure", [lastSync], 1);
|
||||
} else {
|
||||
let reason = Weave.Utils.getErrorString(Weave.Status.login);
|
||||
description =
|
||||
this._stringBundle.formatStringFromName("error.sync.description", [reason], 1);
|
||||
}
|
||||
|
||||
let buttons = [];
|
||||
buttons.push(new Weave.NotificationButton(
|
||||
this._stringBundle.GetStringFromName("error.login.prefs.label"),
|
||||
|
@ -252,8 +254,7 @@ let gSyncUI = {
|
|||
},
|
||||
|
||||
onStartOver: function SUI_onStartOver() {
|
||||
Weave.Notifications.removeAll();
|
||||
this.updateUI();
|
||||
this.clearError();
|
||||
},
|
||||
|
||||
onQuotaNotice: function onQuotaNotice(subject, data) {
|
||||
|
@ -278,7 +279,7 @@ let gSyncUI = {
|
|||
|
||||
// Commands
|
||||
doSync: function SUI_doSync() {
|
||||
setTimeout(function() Weave.Service.sync(), 0);
|
||||
setTimeout(function() Weave.ErrorHandler.syncAndReportErrors(), 0);
|
||||
},
|
||||
|
||||
handleToolbarButton: function SUI_handleStatusbarButton() {
|
||||
|
@ -342,79 +343,93 @@ let gSyncUI = {
|
|||
syncButton.setAttribute("tooltiptext", lastSyncLabel);
|
||||
},
|
||||
|
||||
_onSyncEnd: function SUI__onSyncEnd(success) {
|
||||
clearError: function SUI_clearError(errorString) {
|
||||
Weave.Notifications.removeAll(errorString);
|
||||
this.updateUI();
|
||||
},
|
||||
|
||||
onSyncFinish: function SUI_onSyncFinish() {
|
||||
let title = this._stringBundle.GetStringFromName("error.sync.title");
|
||||
if (!success) {
|
||||
if (Weave.Status.login != Weave.LOGIN_SUCCEEDED) {
|
||||
this.onLoginError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore network related errors unless we haven't been able to
|
||||
// sync for a while.
|
||||
if (Weave.Service.shouldIgnoreError()) {
|
||||
this.updateUI();
|
||||
return;
|
||||
}
|
||||
// Clear out sync failures on a successful sync
|
||||
this.clearError(title);
|
||||
|
||||
if (this._wasDelayed && Weave.Status.sync != Weave.NO_SYNC_NODE_FOUND) {
|
||||
title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title");
|
||||
this.clearError(title);
|
||||
this._wasDelayed = false;
|
||||
}
|
||||
},
|
||||
|
||||
onSyncError: function SUI_onSyncError() {
|
||||
let title = this._stringBundle.GetStringFromName("error.sync.title");
|
||||
|
||||
if (Weave.Status.login != Weave.LOGIN_SUCCEEDED) {
|
||||
this.onLoginError();
|
||||
return;
|
||||
}
|
||||
|
||||
let description;
|
||||
if (Weave.Status.sync == Weave.PROLONGED_SYNC_FAILURE) {
|
||||
// Convert to days
|
||||
let lastSync =
|
||||
Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400;
|
||||
description =
|
||||
this._stringBundle.formatStringFromName("error.sync.prolonged_failure", [lastSync], 1);
|
||||
} else {
|
||||
let error = Weave.Utils.getErrorString(Weave.Status.sync);
|
||||
let description =
|
||||
description =
|
||||
this._stringBundle.formatStringFromName("error.sync.description", [error], 1);
|
||||
}
|
||||
let priority = Weave.Notifications.PRIORITY_WARNING;
|
||||
let buttons = [];
|
||||
|
||||
let priority = Weave.Notifications.PRIORITY_WARNING;
|
||||
let buttons = [];
|
||||
// Check if the client is outdated in some way
|
||||
let outdated = Weave.Status.sync == Weave.VERSION_OUT_OF_DATE;
|
||||
for (let [engine, reason] in Iterator(Weave.Status.engines))
|
||||
outdated = outdated || reason == Weave.VERSION_OUT_OF_DATE;
|
||||
|
||||
// Check if the client is outdated in some way
|
||||
let outdated = Weave.Status.sync == Weave.VERSION_OUT_OF_DATE;
|
||||
for (let [engine, reason] in Iterator(Weave.Status.engines))
|
||||
outdated = outdated || reason == Weave.VERSION_OUT_OF_DATE;
|
||||
|
||||
if (outdated) {
|
||||
description = this._stringBundle.GetStringFromName(
|
||||
"error.sync.needUpdate.description");
|
||||
buttons.push(new Weave.NotificationButton(
|
||||
this._stringBundle.GetStringFromName("error.sync.needUpdate.label"),
|
||||
this._stringBundle.GetStringFromName("error.sync.needUpdate.accesskey"),
|
||||
function() { window.openUILinkIn("https://services.mozilla.com/update/", "tab"); return true; }
|
||||
));
|
||||
}
|
||||
else if (Weave.Status.sync == Weave.OVER_QUOTA) {
|
||||
description = this._stringBundle.GetStringFromName(
|
||||
"error.sync.quota.description");
|
||||
buttons.push(new Weave.NotificationButton(
|
||||
this._stringBundle.GetStringFromName(
|
||||
"error.sync.viewQuotaButton.label"),
|
||||
this._stringBundle.GetStringFromName(
|
||||
"error.sync.viewQuotaButton.accesskey"),
|
||||
function() { gSyncUI.openQuotaDialog(); return true; } )
|
||||
);
|
||||
}
|
||||
else if (Weave.Status.enforceBackoff) {
|
||||
priority = Weave.Notifications.PRIORITY_INFO;
|
||||
buttons.push(new Weave.NotificationButton(
|
||||
this._stringBundle.GetStringFromName("error.sync.serverStatusButton.label"),
|
||||
this._stringBundle.GetStringFromName("error.sync.serverStatusButton.accesskey"),
|
||||
function() { gSyncUI.openServerStatus(); return true; }
|
||||
));
|
||||
}
|
||||
else {
|
||||
priority = Weave.Notifications.PRIORITY_INFO;
|
||||
buttons.push(new Weave.NotificationButton(
|
||||
this._stringBundle.GetStringFromName("error.sync.tryAgainButton.label"),
|
||||
this._stringBundle.GetStringFromName("error.sync.tryAgainButton.accesskey"),
|
||||
function() { gSyncUI.doSync(); return true; }
|
||||
));
|
||||
}
|
||||
|
||||
let notification =
|
||||
new Weave.Notification(title, description, null, priority, buttons);
|
||||
Weave.Notifications.replaceTitle(notification);
|
||||
if (outdated) {
|
||||
description = this._stringBundle.GetStringFromName(
|
||||
"error.sync.needUpdate.description");
|
||||
buttons.push(new Weave.NotificationButton(
|
||||
this._stringBundle.GetStringFromName("error.sync.needUpdate.label"),
|
||||
this._stringBundle.GetStringFromName("error.sync.needUpdate.accesskey"),
|
||||
function() { window.openUILinkIn("https://services.mozilla.com/update/", "tab"); return true; }
|
||||
));
|
||||
}
|
||||
else if (Weave.Status.sync == Weave.OVER_QUOTA) {
|
||||
description = this._stringBundle.GetStringFromName(
|
||||
"error.sync.quota.description");
|
||||
buttons.push(new Weave.NotificationButton(
|
||||
this._stringBundle.GetStringFromName(
|
||||
"error.sync.viewQuotaButton.label"),
|
||||
this._stringBundle.GetStringFromName(
|
||||
"error.sync.viewQuotaButton.accesskey"),
|
||||
function() { gSyncUI.openQuotaDialog(); return true; } )
|
||||
);
|
||||
}
|
||||
else if (Weave.Status.enforceBackoff) {
|
||||
priority = Weave.Notifications.PRIORITY_INFO;
|
||||
buttons.push(new Weave.NotificationButton(
|
||||
this._stringBundle.GetStringFromName("error.sync.serverStatusButton.label"),
|
||||
this._stringBundle.GetStringFromName("error.sync.serverStatusButton.accesskey"),
|
||||
function() { gSyncUI.openServerStatus(); return true; }
|
||||
));
|
||||
}
|
||||
else {
|
||||
// Clear out sync failures on a successful sync
|
||||
Weave.Notifications.removeAll(title);
|
||||
priority = Weave.Notifications.PRIORITY_INFO;
|
||||
buttons.push(new Weave.NotificationButton(
|
||||
this._stringBundle.GetStringFromName("error.sync.tryAgainButton.label"),
|
||||
this._stringBundle.GetStringFromName("error.sync.tryAgainButton.accesskey"),
|
||||
function() { gSyncUI.doSync(); return true; }
|
||||
));
|
||||
}
|
||||
|
||||
let notification =
|
||||
new Weave.Notification(title, description, null, priority, buttons);
|
||||
Weave.Notifications.replaceTitle(notification);
|
||||
|
||||
if (this._wasDelayed && Weave.Status.sync != Weave.NO_SYNC_NODE_FOUND) {
|
||||
title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title");
|
||||
Weave.Notifications.removeAll(title);
|
||||
|
@ -434,10 +449,10 @@ let gSyncUI = {
|
|||
case "weave:service:sync:start":
|
||||
this.onActivityStart();
|
||||
break;
|
||||
case "weave:service:sync:finish":
|
||||
case "weave:ui:sync:finish":
|
||||
this.onSyncFinish();
|
||||
break;
|
||||
case "weave:service:sync:error":
|
||||
case "weave:ui:sync:error":
|
||||
this.onSyncError();
|
||||
break;
|
||||
case "weave:service:sync:delayed":
|
||||
|
@ -455,7 +470,7 @@ let gSyncUI = {
|
|||
case "weave:service:login:finish":
|
||||
this.onLoginFinish();
|
||||
break;
|
||||
case "weave:service:login:error":
|
||||
case "weave:ui:login:error":
|
||||
this.onLoginError();
|
||||
break;
|
||||
case "weave:service:logout:finish":
|
||||
|
@ -470,6 +485,9 @@ let gSyncUI = {
|
|||
case "weave:notification:added":
|
||||
this.initNotifications();
|
||||
break;
|
||||
case "weave:ui:clear-error":
|
||||
this.clearError();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
<menuseparator/>
|
||||
<menuitem label="&changePassword2.label;"
|
||||
oncommand="gSyncUtils.changePassword();"/>
|
||||
<menuitem label="&mySyncKey.label;"
|
||||
<menuitem label="&myRecoveryKey.label;"
|
||||
oncommand="gSyncUtils.resetPassphrase();"/>
|
||||
<menuseparator/>
|
||||
<menuitem label="&resetSync2.label;"
|
||||
|
|
|
@ -1272,6 +1272,22 @@ xpicleanup@BIN_SUFFIX@
|
|||
components/nsPostUpdateWin.js
|
||||
js3250.dll
|
||||
plugins/npnul32.dll
|
||||
#if _MSC_VER != 1400
|
||||
@BINPATH@/Microsoft.VC80.CRT.manifest
|
||||
@BINPATH@/msvcm80.dll
|
||||
@BINPATH@/msvcp80.dll
|
||||
@BINPATH@/msvcr80.dll
|
||||
#endif
|
||||
#if _MSC_VER != 1500
|
||||
@BINPATH@/Microsoft.VC90.CRT.manifest
|
||||
@BINPATH@/msvcm90.dll
|
||||
@BINPATH@/msvcp90.dll
|
||||
@BINPATH@/msvcr90.dll
|
||||
#endif
|
||||
#if _MSC_VER != 1600
|
||||
@BINPATH@/msvcp100.dll
|
||||
@BINPATH@/msvcr100.dll
|
||||
#endif
|
||||
mozcrt19.dll
|
||||
mozcpp19.dll
|
||||
#endif
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
<!ENTITY manageAccount.label "Manage Account">
|
||||
<!ENTITY manageAccount.accesskey "A">
|
||||
<!ENTITY viewQuota.label "View Quota">
|
||||
<!ENTITY changePassword2.label "Change Password…">
|
||||
<!ENTITY mySyncKey.label "My Sync Key">
|
||||
<!ENTITY resetSync2.label "Reset Sync…">
|
||||
<!ENTITY changePassword2.label "Change Password…">
|
||||
<!ENTITY myRecoveryKey.label "My Recovery Key">
|
||||
<!ENTITY resetSync2.label "Reset Sync…">
|
||||
|
||||
<!ENTITY addDevice.label "Add a Device">
|
||||
|
||||
|
|
111
build/hcc
111
build/hcc
|
@ -1,111 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Fix brain-damaged compilers that don't understand -o and -c together
|
||||
#
|
||||
CC=`echo $1 | sed -e "s|'||g" -e 's|"||g'`
|
||||
shift
|
||||
DASH_C=0
|
||||
DASH_O=0
|
||||
DUMMY="XxxXxxX"
|
||||
GET_OBJECT=0
|
||||
OBJ="${DUMMY}"
|
||||
OBJECT="${DUMMY}"
|
||||
|
||||
for i in $*
|
||||
do
|
||||
[ "${CHECK_O}" = yes ] && {
|
||||
case $i in
|
||||
./*/*.o) OBJECT="$i"
|
||||
OPTS="${OPTS} -o"
|
||||
DASH_O=1
|
||||
;;
|
||||
./*.o) OBJECT="`basename $i`"
|
||||
i=""
|
||||
DASH_O=1
|
||||
;;
|
||||
*.o) if [ $i = `basename $i` ]
|
||||
then
|
||||
OBJECT="$i"
|
||||
i=""
|
||||
else
|
||||
OPTS="${OPTS} -o"
|
||||
fi
|
||||
DASH_O=1
|
||||
;;
|
||||
*) OPTS="${OPTS} -o $i"
|
||||
DASH_O=1
|
||||
i=""
|
||||
;;
|
||||
esac
|
||||
CHECK_O=no
|
||||
}
|
||||
case $i in
|
||||
-c) DASH_C=1
|
||||
OPTS="${OPTS} -c"
|
||||
;;
|
||||
-o) CHECK_O=yes
|
||||
;;
|
||||
*.c) C_SRC=$i
|
||||
OPTS="${OPTS} $i"
|
||||
# cc always creates the .o from the .c name
|
||||
OBJ=`basename $C_SRC .c`.o
|
||||
;;
|
||||
*.s) S_SRC=$i
|
||||
OPTS="${OPTS} $i"
|
||||
# or the .o from the .s name
|
||||
OBJ=`basename $S_SRC .s`.o
|
||||
;;
|
||||
*.o) OBJECT=$i
|
||||
OPTS="${OPTS} $i"
|
||||
;;
|
||||
*) OPTS="${OPTS} $i"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
${CC} ${OPTS} || exit $?
|
||||
|
||||
# if there was no -c and -o we're done
|
||||
[ $DASH_C = 1 -a $DASH_O = 1 ] || exit 0
|
||||
|
||||
# if $OBJ and $OBJECT are the same we're done
|
||||
[ $OBJ = $OBJECT ] && exit 0
|
||||
|
||||
[ -f $OBJ ] && mv -f $OBJ $OBJECT
|
145
build/hcpp
145
build/hcpp
|
@ -1,145 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Wrapper for brain-damaged compilers that don't understand -o and -c together.
|
||||
#
|
||||
CXX=`echo $1 | sed -e "s|'||g" -e 's|"||g'`
|
||||
shift
|
||||
DUMMY="XxxXxxX"
|
||||
DASH_C=0
|
||||
DASH_O=0
|
||||
GET_OBJECT=0
|
||||
C_SRC="${DUMMY}"
|
||||
CC_SRC="${DUMMY}"
|
||||
CPP_SRC="${DUMMY}"
|
||||
S_SRC="${DUMMY}"
|
||||
OBJECT="${DUMMY}"
|
||||
NEW_i="${DUMMY}"
|
||||
PLATFORM=`uname -s`
|
||||
|
||||
for i in $*
|
||||
do
|
||||
[ ${GET_OBJECT} -eq 1 ] && {
|
||||
case $i in
|
||||
./*/*.o) OBJECT="$i"
|
||||
OPTS="${OPTS} -o"
|
||||
DASH_O=1
|
||||
;;
|
||||
./*.o) OBJECT="`basename $i`"
|
||||
i=""
|
||||
DASH_O=1
|
||||
;;
|
||||
*.o) if [ $i = `basename $i` ]
|
||||
then
|
||||
i=""
|
||||
else
|
||||
OPTS="${OPTS} -o"
|
||||
DASH_O=1
|
||||
fi
|
||||
;;
|
||||
*) OPTS="${OPTS} -o $i"
|
||||
DASH_O=1
|
||||
i=""
|
||||
;;
|
||||
esac
|
||||
GET_OBJECT=0
|
||||
}
|
||||
case $i in
|
||||
-c)
|
||||
DASH_C=1
|
||||
OPTS="${OPTS} -c"
|
||||
;;
|
||||
-o)
|
||||
GET_OBJECT=1
|
||||
;;
|
||||
*.c)
|
||||
C_SRC="$i"
|
||||
OPTS="${OPTS} $i"
|
||||
# cc always creates the .o from the .c name
|
||||
OBJ=`basename ${C_SRC} .c`.o
|
||||
;;
|
||||
+.*)
|
||||
OPTS="${OPTS} $i"
|
||||
;;
|
||||
*.cpp)
|
||||
CPP_SRC="$i"
|
||||
if [ "${PLATFORM}" = "SCO_SV" ]; then
|
||||
OPTS="${OPTS} +.cpp $i"
|
||||
else
|
||||
OPTS="${OPTS} $i"
|
||||
fi
|
||||
# cc always creates the .o from the .cpp name
|
||||
OBJ=`basename ${CPP_SRC} .cpp`.o
|
||||
;;
|
||||
*.cc)
|
||||
CC_SRC="$i"
|
||||
OPTS="${OPTS} $i"
|
||||
# cc always creates the .o from the .cc name
|
||||
OBJ=`basename ${CC_SRC} .cc`.o
|
||||
;;
|
||||
*.s)
|
||||
S_SRC="$i"
|
||||
OPTS="${OPTS} $i"
|
||||
# cc always creates the .o from the .s name
|
||||
OBJ=`basename ${S_SRC} .s`.o
|
||||
;;
|
||||
*.o) OBJECT=$i
|
||||
OPTS="${OPTS} $i"
|
||||
;;
|
||||
*) OPTS="${OPTS} $i"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
${CXX} ${OPTS} || exit $?
|
||||
rm -f ${NEW_i}
|
||||
|
||||
# LAME!!!
|
||||
if [ -f -O ]; then
|
||||
mv -f -- -O ${OBJECT}
|
||||
fi
|
||||
|
||||
# if there was no -c and -o we're done
|
||||
[ ${DASH_C} -eq 1 -a ${DASH_O} -eq 1 ] || exit 0
|
||||
|
||||
# if $OBJ and $OBJECT are the same we're done
|
||||
[ $OBJ = $OBJECT ] && exit 0
|
||||
|
||||
[ -f $OBJ ] && mv -f $OBJ $OBJECT
|
||||
|
|
@ -47,6 +47,7 @@ INTERNAL_TOOLS = 1
|
|||
|
||||
HOST_PROGRAM = elfhack
|
||||
NO_DIST_INSTALL = 1
|
||||
NO_PROFILE_GUIDED_OPTIMIZE = 1
|
||||
|
||||
VPATH += $(topsrcdir)/build
|
||||
|
||||
|
@ -71,12 +72,20 @@ endif
|
|||
CSRCS := \
|
||||
inject/$(CPU).c \
|
||||
inject/$(CPU)-noinit.c \
|
||||
test.c \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(CSRCS:.c=.$(OBJ_SUFFIX))
|
||||
ifndef CROSS_COMPILE
|
||||
CSRCS += dummy.c
|
||||
endif
|
||||
|
||||
WRAP_MALLOC_CFLAGS=
|
||||
WRAP_MALLOC_LIB=
|
||||
WRAP_LDFLAGS=
|
||||
|
||||
# need this to suppress errors due to /usr/include/linux/byteorder/swab.h
|
||||
# on mozilla buildbots
|
||||
OS_CXXFLAGS := $(filter-out -pedantic,$(OS_CXXFLAGS))
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
test$(DLL_SUFFIX): test.$(OBJ_SUFFIX) elfhack $(CSRCS:.c=.$(OBJ_SUFFIX))
|
||||
$(MKSHLIB) $(LDFLAGS) $<
|
||||
|
@ -94,8 +103,6 @@ test$(DLL_SUFFIX): test.$(OBJ_SUFFIX) elfhack $(CSRCS:.c=.$(OBJ_SUFFIX))
|
|||
|
||||
.PRECIOUS: test$(DLL_SUFFIX)
|
||||
|
||||
CSRCS += test.c
|
||||
|
||||
GARBAGE += test$(DLL_SUFFIX) test$(DLL_SUFFIX).bak
|
||||
|
||||
libs:: test$(DLL_SUFFIX)
|
||||
|
@ -108,8 +115,6 @@ libs:: dummy
|
|||
# Will either crash or return exit code 1 if elfhack is broken
|
||||
LD_LIBRARY_PATH=$(CURDIR) $(CURDIR)/dummy
|
||||
|
||||
CSRCS += dummy.c
|
||||
|
||||
GARBAGE += dummy
|
||||
endif
|
||||
|
||||
|
@ -121,12 +126,6 @@ inject/%.c: inject.c | inject
|
|||
|
||||
GARBAGE_DIRS += inject
|
||||
|
||||
# need this to suppress errors due to /usr/include/linux/byteorder/swab.h
|
||||
# on mozilla buildbots
|
||||
OS_CXXFLAGS := $(filter-out -pedantic,$(OS_CXXFLAGS))
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
inject/%.$(OBJ_SUFFIX): DEFINES += -DBITS=$(if $(HAVE_64BIT_OS),64,32)
|
||||
inject/%.$(OBJ_SUFFIX): CFLAGS := -O2 -fno-stack-protector $(filter -m% -I%,$(CFLAGS))
|
||||
inject/$(CPU)-noinit.$(OBJ_SUFFIX): DEFINES += -DNOINIT
|
||||
|
|
|
@ -350,7 +350,10 @@ _MSC_VER = @_MSC_VER@
|
|||
|
||||
DLL_PREFIX = @DLL_PREFIX@
|
||||
LIB_PREFIX = @LIB_PREFIX@
|
||||
OBJ_SUFFIX = @OBJ_SUFFIX@
|
||||
# We do magic with OBJ_SUFFIX in config.mk, the following ensures we don't
|
||||
# manually use it before config.mk inclusion
|
||||
OBJ_SUFFIX = $(error config/config.mk needs to be included before using OBJ_SUFFIX)
|
||||
_OBJ_SUFFIX = @OBJ_SUFFIX@
|
||||
LIB_SUFFIX = @LIB_SUFFIX@
|
||||
DLL_SUFFIX = @DLL_SUFFIX@
|
||||
BIN_SUFFIX = @BIN_SUFFIX@
|
||||
|
@ -502,8 +505,7 @@ LIBICONV = @LIBICONV@
|
|||
# to normal behavior. Makefile's that create shared libraries out of
|
||||
# archives use these flags to force in all of the .o files in the
|
||||
# archives into the shared library.
|
||||
WRAP_MALLOC_LIB = @WRAP_MALLOC_LIB@
|
||||
WRAP_MALLOC_CFLAGS = @WRAP_MALLOC_CFLAGS@
|
||||
WRAP_LDFLAGS = @WRAP_LDFLAGS@
|
||||
DSO_CFLAGS = @DSO_CFLAGS@
|
||||
DSO_PIC_CFLAGS = @DSO_PIC_CFLAGS@
|
||||
MKSHLIB = @MKSHLIB@
|
||||
|
|
|
@ -790,3 +790,21 @@ EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) --uselist -- $(MKSHLIB)
|
|||
ifdef STDCXX_COMPAT
|
||||
CHECK_STDCXX = objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null && echo "TEST-UNEXPECTED-FAIL | | We don't want these libstdc++ symbols to be used:" && objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && exit 1 || exit 0
|
||||
endif
|
||||
|
||||
# autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
|
||||
# this file
|
||||
OBJ_SUFFIX := $(_OBJ_SUFFIX)
|
||||
|
||||
# PGO builds with GCC build objects with instrumentation in a first pass,
|
||||
# then objects optimized, without instrumentation, in a second pass. If
|
||||
# we overwrite the ojects from the first pass with those from the second,
|
||||
# we end up not getting instrumentation data for better optimization on
|
||||
# incremental builds. As a consequence, we use a different object suffix
|
||||
# for the first pass.
|
||||
ifndef NO_PROFILE_GUIDED_OPTIMIZE
|
||||
ifdef MOZ_PROFILE_GENERATE
|
||||
ifdef GNU_CC
|
||||
OBJ_SUFFIX := i_o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -93,7 +93,7 @@ class ExpandArgsMore(ExpandArgs):
|
|||
subprocess.call(ar_extract + [os.path.abspath(arg)], cwd=tmp)
|
||||
objs = []
|
||||
for root, dirs, files in os.walk(tmp):
|
||||
objs += [relativize(os.path.join(root, f)) for f in files if os.path.splitext(f)[1] == conf.OBJ_SUFFIX]
|
||||
objs += [relativize(os.path.join(root, f)) for f in files if os.path.splitext(f)[1] in [conf.OBJ_SUFFIX, '.i_o']]
|
||||
newlist += objs
|
||||
else:
|
||||
newlist += [arg]
|
||||
|
|
|
@ -46,7 +46,7 @@ from expandlibs import LibDescriptor
|
|||
def generate(args):
|
||||
desc = LibDescriptor()
|
||||
for arg in args:
|
||||
if os.path.splitext(arg)[1] == conf.OBJ_SUFFIX:
|
||||
if os.path.splitext(arg)[1] in [conf.OBJ_SUFFIX, '.i_o']:
|
||||
desc['OBJS'].append(os.path.abspath(arg))
|
||||
elif os.path.splitext(arg)[1] == conf.LIB_SUFFIX and \
|
||||
(os.path.exists(arg) or os.path.exists(arg + conf.LIBS_DESC_SUFFIX)):
|
||||
|
|
|
@ -423,7 +423,7 @@ endif
|
|||
ALL_TRASH = \
|
||||
$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
|
||||
$(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \
|
||||
$(OBJS:.$(OBJ_SUFFIX)=.i) \
|
||||
$(OBJS:.$(OBJ_SUFFIX)=.i) $(OBJS:.$(OBJ_SUFFIX)=.i_o) \
|
||||
$(HOST_PROGOBJS) $(HOST_OBJS) $(IMPORT_LIBRARY) $(DEF_FILE)\
|
||||
$(EXE_DEF_FILE) so_locations _gen _stubs $(wildcard *.res) $(wildcard *.RES) \
|
||||
$(wildcard *.pdb) $(CODFILE) $(MAPFILE) $(IMPORT_LIBRARY) \
|
||||
|
@ -821,13 +821,22 @@ ifdef MOZ_PROFILE_GENERATE
|
|||
# Clean up profiling data during PROFILE_GENERATE phase
|
||||
export::
|
||||
ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_)
|
||||
-$(RM) *.pgd
|
||||
$(foreach pgd,$(wildcard *.pgd),pgomgr -clear $(pgd);)
|
||||
else
|
||||
ifdef GNU_CC
|
||||
-$(RM) *.gcda
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
|
||||
ifdef GNU_CC
|
||||
# Force rebuilding libraries and programs in both passes because each
|
||||
# pass uses different object files.
|
||||
$(PROGRAM) $(SHARED_LIBRARY) $(LIBRARY): FORCE
|
||||
endif
|
||||
endif
|
||||
|
||||
endif # NO_PROFILE_GUIDED_OPTIMIZE
|
||||
|
||||
##############################################
|
||||
|
@ -888,10 +897,10 @@ ifdef MOZ_PROFILE_GENERATE
|
|||
endif
|
||||
else # !WINNT || GNU_CC
|
||||
ifeq ($(CPP_PROG_LINK),1)
|
||||
$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(WRAP_MALLOC_CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(WRAP_MALLOC_LIB) $(EXE_DEF_FILE)
|
||||
$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
|
||||
@$(call CHECK_STDCXX,$@)
|
||||
else # ! CPP_PROG_LINK
|
||||
$(EXPAND_CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
|
||||
$(EXPAND_CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
|
||||
endif # CPP_PROG_LINK
|
||||
endif # WINNT && !GNU_CC
|
||||
|
||||
|
@ -946,10 +955,10 @@ ifdef MSMANIFEST_TOOL
|
|||
endif # MSVC with manifest tool
|
||||
else
|
||||
ifeq ($(CPP_PROG_LINK),1)
|
||||
$(EXPAND_CCC) $(WRAP_MALLOC_CFLAGS) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(BIN_FLAGS)
|
||||
$(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS)
|
||||
@$(call CHECK_STDCXX,$@)
|
||||
else
|
||||
$(EXPAND_CC) $(WRAP_MALLOC_CFLAGS) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(BIN_FLAGS)
|
||||
$(EXPAND_CC) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS)
|
||||
endif # CPP_PROG_LINK
|
||||
endif # WINNT && !GNU_CC
|
||||
|
||||
|
@ -1060,10 +1069,10 @@ ifdef DTRACE_LIB_DEPENDENT
|
|||
ifndef XP_MACOSX
|
||||
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
|
||||
endif
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
|
||||
@$(RM) $(DTRACE_PROBE_OBJ)
|
||||
else # ! DTRACE_LIB_DEPENDENT
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
|
||||
endif # DTRACE_LIB_DEPENDENT
|
||||
@$(call CHECK_STDCXX,$@)
|
||||
|
||||
|
@ -1340,6 +1349,9 @@ $(topsrcdir)/configure: $(topsrcdir)/configure.in
|
|||
(cd $(topsrcdir) && $(AUTOCONF)) && (cd $(DEPTH) && ./config.status --recheck)
|
||||
endif
|
||||
|
||||
$(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in
|
||||
cd $(DEPTH) && CONFIG_HEADERS= CONFIG_FILES=config/autoconf.mk ./config.status
|
||||
|
||||
###############################################################################
|
||||
# Bunch of things that extend the 'export' rule (in order):
|
||||
###############################################################################
|
||||
|
|
130
configure.in
130
configure.in
|
@ -945,18 +945,6 @@ EOF
|
|||
;;
|
||||
esac
|
||||
|
||||
dnl Test breaks icc on OS/2 && MSVC
|
||||
if test "$CC" != "icc" -a -z "$_WIN32_MSVC"; then
|
||||
AC_PROG_CC_C_O
|
||||
if grep "NO_MINUS_C_MINUS_O 1" ./confdefs.h >/dev/null; then
|
||||
USING_HCC=1
|
||||
_OLDCC=$CC
|
||||
_OLDCXX=$CXX
|
||||
CC="${srcdir}/build/hcc '$CC'"
|
||||
CXX="${srcdir}/build/hcpp '$CXX'"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CXXCPP
|
||||
|
||||
|
@ -2095,22 +2083,31 @@ case "$target" in
|
|||
DLL_SUFFIX=".dylib"
|
||||
DSO_LDOPTS=''
|
||||
STRIP="$STRIP -x -S"
|
||||
_PLATFORM_DEFAULT_TOOLKIT='cairo-cocoa'
|
||||
TARGET_NSPR_MDCPUCFG='\"md/_darwin.cfg\"'
|
||||
# The ExceptionHandling framework is needed for Objective-C exception
|
||||
# logging code in nsObjCExceptions.h. Currently we only use that in debug
|
||||
# builds.
|
||||
_SAVE_LDFLAGS=$LDFLAGS
|
||||
AC_MSG_CHECKING([for -framework ExceptionHandling])
|
||||
LDFLAGS="$LDFLAGS -framework ExceptionHandling"
|
||||
AC_TRY_LINK(,[return 0;],
|
||||
ac_cv_have_framework_exceptionhandling="yes",
|
||||
ac_cv_have_framework_exceptionhandling="no")
|
||||
AC_MSG_RESULT([$ac_cv_have_framework_exceptionhandling])
|
||||
if test "$ac_cv_have_framework_exceptionhandling" = "yes"; then
|
||||
MOZ_DEBUG_LDFLAGS="$MOZ_DEBUG_LDFLAGS -framework ExceptionHandling";
|
||||
# Check whether we're targeting OS X or iOS
|
||||
AC_CACHE_CHECK(for iOS target,
|
||||
ac_cv_ios_target,
|
||||
[AC_TRY_COMPILE([#include <TargetConditionals.h>
|
||||
#if !(TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
|
||||
#error not iOS
|
||||
#endif],
|
||||
[],
|
||||
ac_cv_ios_target="yes",
|
||||
ac_cv_ios_target="no")])
|
||||
if test "$ac_cv_ios_target" = "yes"; then
|
||||
AC_DEFINE(XP_IOS)
|
||||
AC_DEFINE(XP_DARWIN)
|
||||
_PLATFORM_DEFAULT_TOOLKIT='cairo-uikit'
|
||||
else
|
||||
AC_DEFINE(XP_MACOSX)
|
||||
AC_DEFINE(XP_DARWIN)
|
||||
_PLATFORM_DEFAULT_TOOLKIT='cairo-cocoa'
|
||||
# The ExceptionHandling framework is needed for Objective-C exception
|
||||
# logging code in nsObjCExceptions.h. Currently we only use that in debug
|
||||
# builds.
|
||||
MOZ_DEBUG_LDFLAGS="$MOZ_DEBUG_LDFLAGS -framework ExceptionHandling";
|
||||
fi
|
||||
LDFLAGS=$_SAVE_LDFLAGS
|
||||
TARGET_NSPR_MDCPUCFG='\"md/_darwin.cfg\"'
|
||||
|
||||
|
||||
if test "x$lto_is_enabled" = "xyes"; then
|
||||
echo "Skipping -dead_strip because lto is enabled."
|
||||
|
@ -4662,6 +4659,7 @@ MOZ_ARG_HEADER(Toolkit Options)
|
|||
-o "$_DEFAULT_TOOLKIT" = "cairo-qt" \
|
||||
-o "$_DEFAULT_TOOLKIT" = "cairo-os2" \
|
||||
-o "$_DEFAULT_TOOLKIT" = "cairo-cocoa" \
|
||||
-o "$_DEFAULT_TOOLKIT" = "cairo-uikit" \
|
||||
-o "$_DEFAULT_TOOLKIT" = "cairo-android"
|
||||
then
|
||||
dnl nglayout only supports building with one toolkit,
|
||||
|
@ -4748,35 +4746,33 @@ cairo-os2)
|
|||
;;
|
||||
|
||||
cairo-cocoa)
|
||||
# Check if we have the Cocoa framework, or if we're targeting Cocoa Touch
|
||||
_SAVE_LDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS -framework Cocoa"
|
||||
AC_TRY_LINK(,[return 0;],_HAVE_FRAMEWORK_COCOA=1,_HAVE_FRAMEWORK_COCOA=)
|
||||
if test -z "$_HAVE_FRAMEWORK_COCOA"; then
|
||||
LDFLAGS="$_SAVE_LDFLAGS -framework UIKit";
|
||||
AC_TRY_LINK(,[return 0;],_HAVE_FRAMEWORK_UIKIT=1,
|
||||
AC_MSG_ERROR([Neither Cocoa nor UIKit frameworks were found. Are you using the correct SDK?]))
|
||||
MOZ_WIDGET_TOOLKIT=uikit
|
||||
AC_DEFINE(MOZ_WIDGET_UIKIT)
|
||||
TK_LIBS='-framework Foundation -framework CoreFoundation -framework CoreGraphics -framework CoreText'
|
||||
else
|
||||
MOZ_WIDGET_TOOLKIT=cocoa
|
||||
AC_DEFINE(MOZ_WIDGET_COCOA)
|
||||
TK_LIBS='-framework QuartzCore -framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook -framework OpenGL'
|
||||
fi
|
||||
MOZ_USER_DIR="Mozilla"
|
||||
AC_DEFINE(XP_MACOSX)
|
||||
|
||||
MOZ_WIDGET_TOOLKIT=cocoa
|
||||
AC_DEFINE(MOZ_WIDGET_COCOA)
|
||||
LDFLAGS="$LDFLAGS -framework Cocoa -lobjc"
|
||||
TK_LIBS='-framework QuartzCore -framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook -framework OpenGL'
|
||||
TK_CFLAGS="-DNO_X11"
|
||||
LDFLAGS="$LDFLAGS -lobjc"
|
||||
CFLAGS="$CFLAGS $TK_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
|
||||
LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL'
|
||||
MOZ_USER_DIR="Mozilla"
|
||||
MOZ_FS_LAYOUT=bundle
|
||||
MOZ_WEBGL=1
|
||||
MOZ_INSTRUMENT_EVENT_LOOP=1
|
||||
;;
|
||||
|
||||
cairo-uikit)
|
||||
MOZ_WIDGET_TOOLKIT=uikit
|
||||
AC_DEFINE(MOZ_WIDGET_UIKIT)
|
||||
LDFLAGS="$LDFLAGS -framework UIKit -lobjc"
|
||||
TK_CFLAGS="-DNO_X11"
|
||||
TK_LIBS='-framework Foundation -framework CoreFoundation -framework CoreGraphics -framework CoreText'
|
||||
CFLAGS="$CFLAGS $TK_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
|
||||
LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL'
|
||||
MOZ_USER_DIR="Mozilla"
|
||||
MOZ_FS_LAYOUT=bundle
|
||||
;;
|
||||
|
||||
cairo-android)
|
||||
AC_DEFINE(MOZ_WIDGET_ANDROID)
|
||||
MOZ_WIDGET_TOOLKIT=android
|
||||
|
@ -7145,8 +7141,6 @@ else
|
|||
AC_DEFINE(MOZ_MEMORY_LINUX)
|
||||
AC_DEFINE(MOZ_MEMORY_ANDROID)
|
||||
_WRAP_MALLOC=1
|
||||
export WRAP_MALLOC_LIB="-L$_objdir/dist/lib -lmozutils"
|
||||
WRAP_MALLOC_CFLAGS="-Wl,--wrap=dlopen -Wl,--wrap=dlclose -Wl,--wrap=dlerror -Wl,--wrap=dlsym -Wl,--wrap=dladdr"
|
||||
;;
|
||||
*-*linux*)
|
||||
AC_DEFINE(MOZ_MEMORY_LINUX)
|
||||
|
@ -7196,6 +7190,13 @@ AC_SUBST(WIN32_CRT_LIBS)
|
|||
dnl Need to set this for make because NSS doesn't have configure
|
||||
AC_SUBST(DLLFLAGS)
|
||||
|
||||
dnl We need to wrap dlopen and related functions on Android because we use
|
||||
dnl our own linker.
|
||||
if test "$OS_TARGET" = Android; then
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -L$_objdir/dist/lib -lmozutils"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=dlopen,--wrap=dlclose,--wrap=dlerror,--wrap=dlsym,--wrap=dladdr"
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use malloc wrapper lib
|
||||
dnl ========================================================
|
||||
|
@ -7205,10 +7206,14 @@ MOZ_ARG_ENABLE_BOOL(wrap-malloc,
|
|||
_WRAP_MALLOC= )
|
||||
|
||||
if test -n "$_WRAP_MALLOC"; then
|
||||
if test "$GNU_CC"; then
|
||||
WRAP_MALLOC_CFLAGS="${LDFLAGS} ${WRAP_MALLOC_CFLAGS} -Wl,--wrap -Wl,malloc -Wl,--wrap -Wl,calloc -Wl,--wrap -Wl,valloc -Wl,--wrap -Wl,free -Wl,--wrap -Wl,realloc -Wl,--wrap -Wl,memalign -Wl,--wrap -Wl,__builtin_new -Wl,--wrap -Wl,__builtin_vec_new -Wl,--wrap -Wl,__builtin_delete -Wl,--wrap -Wl,__builtin_vec_delete -Wl,--wrap -Wl,PR_Free -Wl,--wrap -Wl,PR_Malloc -Wl,--wrap -Wl,PR_Calloc -Wl,--wrap -Wl,PR_Realloc -Wl,--wrap -Wl,strdup -Wl,--wrap -Wl,strndup -Wl,--wrap -Wl,posix_memalign -Wl,--wrap,malloc_usable_size"
|
||||
MKSHLIB="$MKSHLIB"' $(WRAP_MALLOC_CFLAGS) $(WRAP_MALLOC_LIB)'
|
||||
MKCSHLIB="$MKCSHLIB"' $(WRAP_MALLOC_CFLAGS) $(WRAP_MALLOC_LIB)'
|
||||
if test -n "$GNU_CC"; then
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=malloc,--wrap=calloc,--wrap=valloc,--wrap=free,--wrap=realloc,--wrap=memalign"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=__builtin_new,--wrap=__builtin_vec_new,--wrap=__builtin_delete,--wrap=__builtin_vec_delete"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=PR_Free,--wrap=PR_Malloc,--wrap=PR_Calloc,--wrap=PR_Realloc"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=strdup,--wrap=strndup"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=posix_memalign,--wrap=malloc_usable_size"
|
||||
else
|
||||
AC_MSG_ERROR([--enable-wrap-malloc is not supported for non-GNU toolchains])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -7217,7 +7222,7 @@ dnl = Location of malloc wrapper lib
|
|||
dnl ========================================================
|
||||
MOZ_ARG_WITH_STRING(wrap-malloc,
|
||||
[ --with-wrap-malloc=DIR Location of malloc wrapper library],
|
||||
WRAP_MALLOC_LIB=$withval)
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} $withval")
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use JS Call tracing
|
||||
|
@ -8762,8 +8767,7 @@ AC_SUBST(INTEL_ARCHITECTURE)
|
|||
AC_SUBST(MOZ_DISABLE_JAR_PACKAGING)
|
||||
AC_SUBST(MOZ_CHROME_FILE_FORMAT)
|
||||
|
||||
AC_SUBST(WRAP_MALLOC_CFLAGS)
|
||||
AC_SUBST(WRAP_MALLOC_LIB)
|
||||
AC_SUBST(WRAP_LDFLAGS)
|
||||
AC_SUBST(MKSHLIB)
|
||||
AC_SUBST(MKCSHLIB)
|
||||
AC_SUBST(MKSHLIB_FORCE_ALL)
|
||||
|
@ -8810,15 +8814,6 @@ AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
|
|||
AC_SUBST(LIBJPEG_TURBO_X86_ASM)
|
||||
AC_SUBST(LIBJPEG_TURBO_X64_ASM)
|
||||
|
||||
if test "$USING_HCC"; then
|
||||
CC='${topsrcdir}/build/hcc'
|
||||
CC="$CC '$_OLDCC'"
|
||||
CXX='${topsrcdir}/build/hcpp'
|
||||
CXX="$CXX '$_OLDCXX'"
|
||||
AC_SUBST(CC)
|
||||
AC_SUBST(CXX)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for posix_fallocate])
|
||||
AC_TRY_LINK([#define _XOPEN_SOURCE 600
|
||||
#include <fcntl.h>],
|
||||
|
@ -9120,8 +9115,11 @@ unset CONFIG_FILES
|
|||
# No need to run subconfigures when building with LIBXUL_SDK_DIR
|
||||
if test "$COMPILE_ENVIRONMENT" -a -z "$LIBXUL_SDK_DIR"; then
|
||||
|
||||
export WRAP_LDFLAGS
|
||||
|
||||
if test -n "$_WRAP_MALLOC"; then
|
||||
_SUBDIR_CONFIG_ARGS="$_SUBDIR_CONFIG_ARGS --enable-wrap-malloc"
|
||||
# Avoid doubling wrap malloc arguments
|
||||
_SUBDIR_CONFIG_ARGS="`echo $_SUBDIR_CONFIG_ARGS | sed -e 's/--enable-wrap-malloc *//'`"
|
||||
fi
|
||||
|
||||
if test -z "$MOZ_NATIVE_NSPR"; then
|
||||
|
|
|
@ -160,18 +160,7 @@ CPPSRCS = \
|
|||
# Are we targeting x86-32 or x86-64? If so, we want to include SSE2 code for
|
||||
# nsTextFragment.cpp
|
||||
ifneq (,$(INTEL_ARCHITECTURE))
|
||||
|
||||
CPPSRCS += nsTextFragmentSSE2.cpp
|
||||
|
||||
# gcc requires -msse2 for this file since it uses SSE2 intrinsics. (See bug
|
||||
# 585538 comment 12.)
|
||||
ifdef GNU_CC
|
||||
nsTextFragmentSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
|
||||
endif
|
||||
|
||||
ifdef SOLARIS_SUNPRO_CXX
|
||||
nsTextFragmentSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-xarch=sse2 -xO4
|
||||
endif
|
||||
endif
|
||||
|
||||
GQI_SRCS = contentbase.gqi
|
||||
|
@ -220,3 +209,15 @@ INCLUDES += \
|
|||
$(NULL)
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
|
||||
# gcc requires -msse2 for this file since it uses SSE2 intrinsics. (See bug
|
||||
# 585538 comment 12.)
|
||||
ifneq (,$(INTEL_ARCHITECTURE))
|
||||
ifdef GNU_CC
|
||||
nsTextFragmentSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
|
||||
endif
|
||||
|
||||
ifdef SOLARIS_SUNPRO_CXX
|
||||
nsTextFragmentSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-xarch=sse2 -xO4
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -179,19 +179,8 @@ CPPSRCS = \
|
|||
$(NULL)
|
||||
|
||||
# Are we targeting x86 or x64? If so, build gfxAlphaRecoverySSE2.cpp.
|
||||
# The file uses SSE2 intrinsics, so it needs special compile flags on some
|
||||
# compilers.
|
||||
ifneq (,$(INTEL_ARCHITECTURE))
|
||||
CPPSRCS += gfxAlphaRecoverySSE2.cpp
|
||||
|
||||
ifdef GNU_CC
|
||||
gfxAlphaRecoverySSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
|
||||
endif
|
||||
|
||||
ifdef SOLARIS_SUNPRO_CXX
|
||||
gfxAlphaRecoverySSE2.$(OBJ_SUFFIX): OS_CXXFLAGS += -xarch=sse2 -xO4
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
SHARED_LIBRARY_LIBS += \
|
||||
|
@ -400,3 +389,15 @@ endif
|
|||
ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
|
||||
CXXFLAGS += $(CAIRO_FT_CFLAGS) $(MOZ_PANGO_CFLAGS)
|
||||
endif
|
||||
|
||||
# The file uses SSE2 intrinsics, so it needs special compile flags on some
|
||||
# compilers.
|
||||
ifneq (,$(INTEL_ARCHITECTURE))
|
||||
ifdef GNU_CC
|
||||
gfxAlphaRecoverySSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
|
||||
endif
|
||||
|
||||
ifdef SOLARIS_SUNPRO_CXX
|
||||
gfxAlphaRecoverySSE2.$(OBJ_SUFFIX): OS_CXXFLAGS += -xarch=sse2 -xO4
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -25,8 +25,7 @@ CPPSRCS = yuv_convert.cpp \
|
|||
$(NULL)
|
||||
|
||||
# Are we targeting x86 or x64? If so, build yuv_convert_mmx.cpp and
|
||||
# yuv_convert_sse2.cpp. These files use MMX and SSE2 intrinsics, so they need
|
||||
# special compile flags on some compilers.
|
||||
# yuv_convert_sse2.cpp.
|
||||
ifneq (,$(INTEL_ARCHITECTURE))
|
||||
CPPSRCS += yuv_convert_sse2.cpp
|
||||
|
||||
|
@ -38,20 +37,8 @@ endif
|
|||
else
|
||||
CPPSRCS += yuv_convert_mmx.cpp
|
||||
endif
|
||||
|
||||
ifdef GNU_CC
|
||||
yuv_convert_mmx.$(OBJ_SUFFIX): CXXFLAGS += -mmmx
|
||||
yuv_convert_sse2.$(OBJ_SUFFIX): CXXFLAGS += -msse2
|
||||
endif
|
||||
|
||||
ifdef SOLARIS_SUNPRO_CXX
|
||||
yuv_convert_mmx.$(OBJ_SUFFIX): CXXFLAGS += -xarch=mmx -xO4
|
||||
yuv_convert_sse2.$(OBJ_SUFFIX): CXXFLAGS += -xarch=sse2 -xO4
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
|
||||
ifdef _MSC_VER
|
||||
ifeq ($(OS_TEST),x86_64)
|
||||
ifeq (1400,$(_MSC_VER))
|
||||
|
@ -96,3 +83,17 @@ endif
|
|||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
# These files use MMX and SSE2 intrinsics, so they need special compile flags
|
||||
# on some compilers.
|
||||
ifneq (,$(INTEL_ARCHITECTURE))
|
||||
ifdef GNU_CC
|
||||
yuv_convert_mmx.$(OBJ_SUFFIX): CXXFLAGS += -mmmx
|
||||
yuv_convert_sse2.$(OBJ_SUFFIX): CXXFLAGS += -msse2
|
||||
endif
|
||||
|
||||
ifdef SOLARIS_SUNPRO_CXX
|
||||
yuv_convert_mmx.$(OBJ_SUFFIX): CXXFLAGS += -xarch=mmx -xO4
|
||||
yuv_convert_sse2.$(OBJ_SUFFIX): CXXFLAGS += -xarch=sse2 -xO4
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -74,16 +74,6 @@ CPPSRCS = \
|
|||
# version of nsUTF8ToUnicodeSSE2.cpp.
|
||||
ifneq (,$(INTEL_ARCHITECTURE))
|
||||
CPPSRCS += nsUTF8ToUnicodeSSE2.cpp
|
||||
|
||||
# nsUTF8ToUnicodeSSE2.cpp uses SSE2 intrinsics, so we need to pass -msse2 if
|
||||
# we're using gcc. (See bug 585538 comment 12.)
|
||||
ifdef GNU_CC
|
||||
nsUTF8ToUnicodeSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
|
||||
endif
|
||||
|
||||
ifdef SOLARIS_SUNPRO_CXX
|
||||
nsUTF8ToUnicodeSSE2.$(OBJ_SUFFIX): OS_CXXFLAGS += -xarch=sse2 -xO4
|
||||
endif
|
||||
endif
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../util \
|
||||
|
@ -107,3 +97,15 @@ SHARED_LIBRARY_LIBS += \
|
|||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifneq (,$(INTEL_ARCHITECTURE))
|
||||
# nsUTF8ToUnicodeSSE2.cpp uses SSE2 intrinsics, so we need to pass -msse2 if
|
||||
# we're using gcc. (See bug 585538 comment 12.)
|
||||
ifdef GNU_CC
|
||||
nsUTF8ToUnicodeSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
|
||||
endif
|
||||
|
||||
ifdef SOLARIS_SUNPRO_CXX
|
||||
nsUTF8ToUnicodeSSE2.$(OBJ_SUFFIX): OS_CXXFLAGS += -xarch=sse2 -xO4
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -52,8 +52,7 @@ CPPSRCS = \
|
|||
$(NULL)
|
||||
|
||||
ifeq (Android,$(OS_TARGET))
|
||||
WRAP_MALLOC_CFLAGS =
|
||||
WRAP_MALLOC_LIB =
|
||||
WRAP_LDFLAGS =
|
||||
CPPSRCS = MozillaRuntimeMainAndroid.cpp
|
||||
else
|
||||
LIBS += \
|
||||
|
|
111
js/src/build/hcc
111
js/src/build/hcc
|
@ -1,111 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Fix brain-damaged compilers that don't understand -o and -c together
|
||||
#
|
||||
CC=`echo $1 | sed -e "s|'||g" -e 's|"||g'`
|
||||
shift
|
||||
DASH_C=0
|
||||
DASH_O=0
|
||||
DUMMY="XxxXxxX"
|
||||
GET_OBJECT=0
|
||||
OBJ="${DUMMY}"
|
||||
OBJECT="${DUMMY}"
|
||||
|
||||
for i in $*
|
||||
do
|
||||
[ "${CHECK_O}" = yes ] && {
|
||||
case $i in
|
||||
./*/*.o) OBJECT="$i"
|
||||
OPTS="${OPTS} -o"
|
||||
DASH_O=1
|
||||
;;
|
||||
./*.o) OBJECT="`basename $i`"
|
||||
i=""
|
||||
DASH_O=1
|
||||
;;
|
||||
*.o) if [ $i = `basename $i` ]
|
||||
then
|
||||
OBJECT="$i"
|
||||
i=""
|
||||
else
|
||||
OPTS="${OPTS} -o"
|
||||
fi
|
||||
DASH_O=1
|
||||
;;
|
||||
*) OPTS="${OPTS} -o $i"
|
||||
DASH_O=1
|
||||
i=""
|
||||
;;
|
||||
esac
|
||||
CHECK_O=no
|
||||
}
|
||||
case $i in
|
||||
-c) DASH_C=1
|
||||
OPTS="${OPTS} -c"
|
||||
;;
|
||||
-o) CHECK_O=yes
|
||||
;;
|
||||
*.c) C_SRC=$i
|
||||
OPTS="${OPTS} $i"
|
||||
# cc always creates the .o from the .c name
|
||||
OBJ=`basename $C_SRC .c`.o
|
||||
;;
|
||||
*.s) S_SRC=$i
|
||||
OPTS="${OPTS} $i"
|
||||
# or the .o from the .s name
|
||||
OBJ=`basename $S_SRC .s`.o
|
||||
;;
|
||||
*.o) OBJECT=$i
|
||||
OPTS="${OPTS} $i"
|
||||
;;
|
||||
*) OPTS="${OPTS} $i"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
${CC} ${OPTS} || exit $?
|
||||
|
||||
# if there was no -c and -o we're done
|
||||
[ $DASH_C = 1 -a $DASH_O = 1 ] || exit 0
|
||||
|
||||
# if $OBJ and $OBJECT are the same we're done
|
||||
[ $OBJ = $OBJECT ] && exit 0
|
||||
|
||||
[ -f $OBJ ] && mv -f $OBJ $OBJECT
|
|
@ -1,145 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Wrapper for brain-damaged compilers that don't understand -o and -c together.
|
||||
#
|
||||
CXX=`echo $1 | sed -e "s|'||g" -e 's|"||g'`
|
||||
shift
|
||||
DUMMY="XxxXxxX"
|
||||
DASH_C=0
|
||||
DASH_O=0
|
||||
GET_OBJECT=0
|
||||
C_SRC="${DUMMY}"
|
||||
CC_SRC="${DUMMY}"
|
||||
CPP_SRC="${DUMMY}"
|
||||
S_SRC="${DUMMY}"
|
||||
OBJECT="${DUMMY}"
|
||||
NEW_i="${DUMMY}"
|
||||
PLATFORM=`uname -s`
|
||||
|
||||
for i in $*
|
||||
do
|
||||
[ ${GET_OBJECT} -eq 1 ] && {
|
||||
case $i in
|
||||
./*/*.o) OBJECT="$i"
|
||||
OPTS="${OPTS} -o"
|
||||
DASH_O=1
|
||||
;;
|
||||
./*.o) OBJECT="`basename $i`"
|
||||
i=""
|
||||
DASH_O=1
|
||||
;;
|
||||
*.o) if [ $i = `basename $i` ]
|
||||
then
|
||||
i=""
|
||||
else
|
||||
OPTS="${OPTS} -o"
|
||||
DASH_O=1
|
||||
fi
|
||||
;;
|
||||
*) OPTS="${OPTS} -o $i"
|
||||
DASH_O=1
|
||||
i=""
|
||||
;;
|
||||
esac
|
||||
GET_OBJECT=0
|
||||
}
|
||||
case $i in
|
||||
-c)
|
||||
DASH_C=1
|
||||
OPTS="${OPTS} -c"
|
||||
;;
|
||||
-o)
|
||||
GET_OBJECT=1
|
||||
;;
|
||||
*.c)
|
||||
C_SRC="$i"
|
||||
OPTS="${OPTS} $i"
|
||||
# cc always creates the .o from the .c name
|
||||
OBJ=`basename ${C_SRC} .c`.o
|
||||
;;
|
||||
+.*)
|
||||
OPTS="${OPTS} $i"
|
||||
;;
|
||||
*.cpp)
|
||||
CPP_SRC="$i"
|
||||
if [ "${PLATFORM}" = "SCO_SV" ]; then
|
||||
OPTS="${OPTS} +.cpp $i"
|
||||
else
|
||||
OPTS="${OPTS} $i"
|
||||
fi
|
||||
# cc always creates the .o from the .cpp name
|
||||
OBJ=`basename ${CPP_SRC} .cpp`.o
|
||||
;;
|
||||
*.cc)
|
||||
CC_SRC="$i"
|
||||
OPTS="${OPTS} $i"
|
||||
# cc always creates the .o from the .cc name
|
||||
OBJ=`basename ${CC_SRC} .cc`.o
|
||||
;;
|
||||
*.s)
|
||||
S_SRC="$i"
|
||||
OPTS="${OPTS} $i"
|
||||
# cc always creates the .o from the .s name
|
||||
OBJ=`basename ${S_SRC} .s`.o
|
||||
;;
|
||||
*.o) OBJECT=$i
|
||||
OPTS="${OPTS} $i"
|
||||
;;
|
||||
*) OPTS="${OPTS} $i"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
${CXX} ${OPTS} || exit $?
|
||||
rm -f ${NEW_i}
|
||||
|
||||
# LAME!!!
|
||||
if [ -f -O ]; then
|
||||
mv -f -- -O ${OBJECT}
|
||||
fi
|
||||
|
||||
# if there was no -c and -o we're done
|
||||
[ ${DASH_C} -eq 1 -a ${DASH_O} -eq 1 ] || exit 0
|
||||
|
||||
# if $OBJ and $OBJECT are the same we're done
|
||||
[ $OBJ = $OBJECT ] && exit 0
|
||||
|
||||
[ -f $OBJ ] && mv -f $OBJ $OBJECT
|
||||
|
|
@ -177,7 +177,10 @@ _MSC_VER = @_MSC_VER@
|
|||
|
||||
DLL_PREFIX = @DLL_PREFIX@
|
||||
LIB_PREFIX = @LIB_PREFIX@
|
||||
OBJ_SUFFIX = @OBJ_SUFFIX@
|
||||
# We do magic with OBJ_SUFFIX in config.mk, the following ensures we don't
|
||||
# manually use it before config.mk inclusion
|
||||
OBJ_SUFFIX = $(error config/config.mk needs to be included before using OBJ_SUFFIX)
|
||||
_OBJ_SUFFIX = @OBJ_SUFFIX@
|
||||
LIB_SUFFIX = @LIB_SUFFIX@
|
||||
DLL_SUFFIX = @DLL_SUFFIX@
|
||||
BIN_SUFFIX = @BIN_SUFFIX@
|
||||
|
@ -261,8 +264,7 @@ EDITLINE_LIBS = @EDITLINE_LIBS@
|
|||
# to normal behavior. Makefile's that create shared libraries out of
|
||||
# archives use these flags to force in all of the .o files in the
|
||||
# archives into the shared library.
|
||||
WRAP_MALLOC_LIB = @WRAP_MALLOC_LIB@
|
||||
WRAP_MALLOC_CFLAGS = @WRAP_MALLOC_CFLAGS@
|
||||
WRAP_LDFLAGS = @WRAP_LDFLAGS@
|
||||
DSO_CFLAGS = @DSO_CFLAGS@
|
||||
DSO_PIC_CFLAGS = @DSO_PIC_CFLAGS@
|
||||
MKSHLIB = @MKSHLIB@
|
||||
|
|
|
@ -790,3 +790,21 @@ EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) --uselist -- $(MKSHLIB)
|
|||
ifdef STDCXX_COMPAT
|
||||
CHECK_STDCXX = objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null && echo "TEST-UNEXPECTED-FAIL | | We don't want these libstdc++ symbols to be used:" && objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && exit 1 || exit 0
|
||||
endif
|
||||
|
||||
# autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
|
||||
# this file
|
||||
OBJ_SUFFIX := $(_OBJ_SUFFIX)
|
||||
|
||||
# PGO builds with GCC build objects with instrumentation in a first pass,
|
||||
# then objects optimized, without instrumentation, in a second pass. If
|
||||
# we overwrite the ojects from the first pass with those from the second,
|
||||
# we end up not getting instrumentation data for better optimization on
|
||||
# incremental builds. As a consequence, we use a different object suffix
|
||||
# for the first pass.
|
||||
ifndef NO_PROFILE_GUIDED_OPTIMIZE
|
||||
ifdef MOZ_PROFILE_GENERATE
|
||||
ifdef GNU_CC
|
||||
OBJ_SUFFIX := i_o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -93,7 +93,7 @@ class ExpandArgsMore(ExpandArgs):
|
|||
subprocess.call(ar_extract + [os.path.abspath(arg)], cwd=tmp)
|
||||
objs = []
|
||||
for root, dirs, files in os.walk(tmp):
|
||||
objs += [relativize(os.path.join(root, f)) for f in files if os.path.splitext(f)[1] == conf.OBJ_SUFFIX]
|
||||
objs += [relativize(os.path.join(root, f)) for f in files if os.path.splitext(f)[1] in [conf.OBJ_SUFFIX, '.i_o']]
|
||||
newlist += objs
|
||||
else:
|
||||
newlist += [arg]
|
||||
|
|
|
@ -46,7 +46,7 @@ from expandlibs import LibDescriptor
|
|||
def generate(args):
|
||||
desc = LibDescriptor()
|
||||
for arg in args:
|
||||
if os.path.splitext(arg)[1] == conf.OBJ_SUFFIX:
|
||||
if os.path.splitext(arg)[1] in [conf.OBJ_SUFFIX, '.i_o']:
|
||||
desc['OBJS'].append(os.path.abspath(arg))
|
||||
elif os.path.splitext(arg)[1] == conf.LIB_SUFFIX and \
|
||||
(os.path.exists(arg) or os.path.exists(arg + conf.LIBS_DESC_SUFFIX)):
|
||||
|
|
|
@ -423,7 +423,7 @@ endif
|
|||
ALL_TRASH = \
|
||||
$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
|
||||
$(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \
|
||||
$(OBJS:.$(OBJ_SUFFIX)=.i) \
|
||||
$(OBJS:.$(OBJ_SUFFIX)=.i) $(OBJS:.$(OBJ_SUFFIX)=.i_o) \
|
||||
$(HOST_PROGOBJS) $(HOST_OBJS) $(IMPORT_LIBRARY) $(DEF_FILE)\
|
||||
$(EXE_DEF_FILE) so_locations _gen _stubs $(wildcard *.res) $(wildcard *.RES) \
|
||||
$(wildcard *.pdb) $(CODFILE) $(MAPFILE) $(IMPORT_LIBRARY) \
|
||||
|
@ -821,13 +821,22 @@ ifdef MOZ_PROFILE_GENERATE
|
|||
# Clean up profiling data during PROFILE_GENERATE phase
|
||||
export::
|
||||
ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_)
|
||||
-$(RM) *.pgd
|
||||
$(foreach pgd,$(wildcard *.pgd),pgomgr -clear $(pgd);)
|
||||
else
|
||||
ifdef GNU_CC
|
||||
-$(RM) *.gcda
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
|
||||
ifdef GNU_CC
|
||||
# Force rebuilding libraries and programs in both passes because each
|
||||
# pass uses different object files.
|
||||
$(PROGRAM) $(SHARED_LIBRARY) $(LIBRARY): FORCE
|
||||
endif
|
||||
endif
|
||||
|
||||
endif # NO_PROFILE_GUIDED_OPTIMIZE
|
||||
|
||||
##############################################
|
||||
|
@ -888,10 +897,10 @@ ifdef MOZ_PROFILE_GENERATE
|
|||
endif
|
||||
else # !WINNT || GNU_CC
|
||||
ifeq ($(CPP_PROG_LINK),1)
|
||||
$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(WRAP_MALLOC_CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(WRAP_MALLOC_LIB) $(EXE_DEF_FILE)
|
||||
$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
|
||||
@$(call CHECK_STDCXX,$@)
|
||||
else # ! CPP_PROG_LINK
|
||||
$(EXPAND_CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
|
||||
$(EXPAND_CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
|
||||
endif # CPP_PROG_LINK
|
||||
endif # WINNT && !GNU_CC
|
||||
|
||||
|
@ -946,10 +955,10 @@ ifdef MSMANIFEST_TOOL
|
|||
endif # MSVC with manifest tool
|
||||
else
|
||||
ifeq ($(CPP_PROG_LINK),1)
|
||||
$(EXPAND_CCC) $(WRAP_MALLOC_CFLAGS) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(BIN_FLAGS)
|
||||
$(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS)
|
||||
@$(call CHECK_STDCXX,$@)
|
||||
else
|
||||
$(EXPAND_CC) $(WRAP_MALLOC_CFLAGS) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(BIN_FLAGS)
|
||||
$(EXPAND_CC) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS)
|
||||
endif # CPP_PROG_LINK
|
||||
endif # WINNT && !GNU_CC
|
||||
|
||||
|
@ -1060,10 +1069,10 @@ ifdef DTRACE_LIB_DEPENDENT
|
|||
ifndef XP_MACOSX
|
||||
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
|
||||
endif
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
|
||||
@$(RM) $(DTRACE_PROBE_OBJ)
|
||||
else # ! DTRACE_LIB_DEPENDENT
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
|
||||
endif # DTRACE_LIB_DEPENDENT
|
||||
@$(call CHECK_STDCXX,$@)
|
||||
|
||||
|
@ -1340,6 +1349,9 @@ $(topsrcdir)/configure: $(topsrcdir)/configure.in
|
|||
(cd $(topsrcdir) && $(AUTOCONF)) && (cd $(DEPTH) && ./config.status --recheck)
|
||||
endif
|
||||
|
||||
$(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in
|
||||
cd $(DEPTH) && CONFIG_HEADERS= CONFIG_FILES=config/autoconf.mk ./config.status
|
||||
|
||||
###############################################################################
|
||||
# Bunch of things that extend the 'export' rule (in order):
|
||||
###############################################################################
|
||||
|
|
|
@ -946,18 +946,6 @@ EOF
|
|||
;;
|
||||
esac
|
||||
|
||||
dnl Test breaks icc on OS/2 && MSVC
|
||||
if test "$CC" != "icc" -a -z "$_WIN32_MSVC"; then
|
||||
AC_PROG_CC_C_O
|
||||
if grep "NO_MINUS_C_MINUS_O 1" ./confdefs.h >/dev/null; then
|
||||
USING_HCC=1
|
||||
_OLDCC=$CC
|
||||
_OLDCXX=$CXX
|
||||
CC="${srcdir}/build/hcc '$CC'"
|
||||
CXX="${srcdir}/build/hcpp '$CXX'"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CXXCPP
|
||||
|
||||
|
@ -4582,8 +4570,13 @@ MOZ_ARG_ENABLE_BOOL(wrap-malloc,
|
|||
|
||||
if test -n "$_WRAP_MALLOC"; then
|
||||
if test "$GNU_CC"; then
|
||||
WRAP_MALLOC_CFLAGS="${LDFLAGS} -Wl,--wrap -Wl,malloc -Wl,--wrap -Wl,calloc -Wl,--wrap -Wl,valloc -Wl,--wrap -Wl,free -Wl,--wrap -Wl,realloc -Wl,--wrap -Wl,memalign -Wl,--wrap -Wl,__builtin_new -Wl,--wrap -Wl,__builtin_vec_new -Wl,--wrap -Wl,__builtin_delete -Wl,--wrap -Wl,__builtin_vec_delete -Wl,--wrap -Wl,PR_Free -Wl,--wrap -Wl,PR_Malloc -Wl,--wrap -Wl,PR_Calloc -Wl,--wrap -Wl,PR_Realloc -Wl,--wrap -Wl,strdup -Wl,--wrap -Wl,strndup -Wl,--wrap -Wl,posix_memalign"
|
||||
MKSHLIB="$MKSHLIB"' $(WRAP_MALLOC_CFLAGS) $(WRAP_MALLOC_LIB)'
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=malloc,--wrap=calloc,--wrap=valloc,--wrap=free,--wrap=realloc,--wrap=memalign"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=__builtin_new,--wrap=__builtin_vec_new,--wrap=__builtin_delete,--wrap=__builtin_vec_delete"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=PR_Free,--wrap=PR_Malloc,--wrap=PR_Calloc,--wrap=PR_Realloc"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=strdup,--wrap=strndup"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=posix_memalign,--wrap=malloc_usable_size"
|
||||
else
|
||||
AC_MSG_ERROR([--enable-wrap-malloc is not supported for non-GNU toolchains])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -4592,7 +4585,7 @@ dnl = Location of malloc wrapper lib
|
|||
dnl ========================================================
|
||||
MOZ_ARG_WITH_STRING(wrap-malloc,
|
||||
[ --with-wrap-malloc=DIR Location of malloc wrapper library],
|
||||
WRAP_MALLOC_LIB=$withval)
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} $withval")
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use JS Call tracing
|
||||
|
@ -5410,8 +5403,7 @@ AC_SUBST(OS_TEST)
|
|||
AC_SUBST(CPU_ARCH)
|
||||
AC_SUBST(INTEL_ARCHITECTURE)
|
||||
|
||||
AC_SUBST(WRAP_MALLOC_CFLAGS)
|
||||
AC_SUBST(WRAP_MALLOC_LIB)
|
||||
AC_SUBST(WRAP_LDFLAGS)
|
||||
AC_SUBST(MKSHLIB)
|
||||
AC_SUBST(MKCSHLIB)
|
||||
AC_SUBST(MKSHLIB_FORCE_ALL)
|
||||
|
@ -5433,15 +5425,6 @@ AC_SUBST(CC_VERSION)
|
|||
AC_SUBST(CXX_VERSION)
|
||||
AC_SUBST(MSMANIFEST_TOOL)
|
||||
|
||||
if test "$USING_HCC"; then
|
||||
CC='${topsrcdir}/build/hcc'
|
||||
CC="$CC '$_OLDCC'"
|
||||
CXX='${topsrcdir}/build/hcpp'
|
||||
CXX="$CXX '$_OLDCXX'"
|
||||
AC_SUBST(CC)
|
||||
AC_SUBST(CXX)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for posix_fallocate])
|
||||
AC_TRY_LINK([#define _XOPEN_SOURCE 600
|
||||
#include <fcntl.h>],
|
||||
|
|
|
@ -4144,6 +4144,9 @@ AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSScript *script, JS
|
|||
return false;
|
||||
}
|
||||
|
||||
if (script->hasClearedGlobal())
|
||||
return false;
|
||||
|
||||
if (!script->ensureRanInference(cx)) {
|
||||
*pbaseobj = NULL;
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
|
|
|
@ -183,6 +183,11 @@ mjit::Compiler::compile()
|
|||
CompileStatus
|
||||
mjit::Compiler::checkAnalysis(JSScript *script)
|
||||
{
|
||||
if (script->hasClearedGlobal()) {
|
||||
JaegerSpew(JSpew_Abort, "script has a cleared global\n");
|
||||
return Compile_Abort;
|
||||
}
|
||||
|
||||
if (!script->ensureRanBytecode(cx))
|
||||
return Compile_Error;
|
||||
if (cx->typeInferenceEnabled() && !script->ensureRanInference(cx))
|
||||
|
|
|
@ -1422,46 +1422,100 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
static PLDHashOperator LiveShellSizeEnumerator(PresShellPtrKey *aEntry,
|
||||
void *userArg)
|
||||
class MemoryReporter : public nsIMemoryMultiReporter
|
||||
{
|
||||
PresShell *aShell = static_cast<PresShell*>(aEntry->GetKey());
|
||||
PRUint32 *val = (PRUint32*)userArg;
|
||||
*val += aShell->EstimateMemoryUsed();
|
||||
*val += aShell->mPresContext->EstimateMemoryUsed();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator StyleSizeEnumerator(PresShellPtrKey *aEntry,
|
||||
void *userArg)
|
||||
{
|
||||
PresShell *aShell = static_cast<PresShell*>(aEntry->GetKey());
|
||||
PRUint32 *val = (PRUint32*)userArg;
|
||||
*val += aShell->StyleSet()->SizeOf();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PRUint32
|
||||
EstimateShellsMemory(nsTHashtable<PresShellPtrKey>::Enumerator aEnumerator)
|
||||
{
|
||||
PRUint32 result = 0;
|
||||
sLiveShells->EnumerateEntries(aEnumerator, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PRInt64 SizeOfLayoutMemoryReporter() {
|
||||
return EstimateShellsMemory(LiveShellSizeEnumerator);
|
||||
}
|
||||
|
||||
static PRInt64 SizeOfStyleMemoryReporter() {
|
||||
return EstimateShellsMemory(StyleSizeEnumerator);
|
||||
}
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMEMORYMULTIREPORTER
|
||||
protected:
|
||||
static PLDHashOperator SizeEnumerator(PresShellPtrKey *aEntry, void *userArg);
|
||||
};
|
||||
|
||||
protected:
|
||||
void QueryIsActive();
|
||||
nsresult UpdateImageLockingState();
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(PresShell::MemoryReporter, nsIMemoryMultiReporter)
|
||||
|
||||
namespace {
|
||||
|
||||
struct MemoryReporterData
|
||||
{
|
||||
nsIMemoryMultiReporterCallback* callback;
|
||||
nsISupports* closure;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry,
|
||||
void *userArg)
|
||||
{
|
||||
PresShell *aShell = static_cast<PresShell*>(aEntry->GetKey());
|
||||
MemoryReporterData *data = (MemoryReporterData*)userArg;
|
||||
|
||||
// Build the string "explicit/layout/shell(<uri of the document>)"
|
||||
nsCAutoString str("explicit/layout/shell(");
|
||||
|
||||
nsIDocument* doc = aShell->GetDocument();
|
||||
if (doc) {
|
||||
nsIURI* docURI = doc->GetDocumentURI();
|
||||
|
||||
if (docURI) {
|
||||
nsCString spec;
|
||||
docURI->GetSpec(spec);
|
||||
|
||||
// A hack: replace forward slashes with '\\' so they aren't
|
||||
// treated as path separators. Users of the reporters
|
||||
// (such as about:memory) have to undo this change.
|
||||
spec.ReplaceChar('/', '\\');
|
||||
|
||||
str += spec;
|
||||
}
|
||||
}
|
||||
|
||||
str += NS_LITERAL_CSTRING(")");
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(kArenaDesc, "Memory used by layout PresShell, PresContext, and other related areas.");
|
||||
NS_NAMED_LITERAL_CSTRING(kStyleDesc, "Memory used by the style system.");
|
||||
|
||||
nsCAutoString arenaPath = str + NS_LITERAL_CSTRING("/arenas");
|
||||
nsCAutoString stylePath = str + NS_LITERAL_CSTRING("/styledata");
|
||||
|
||||
PRUint32 arenasSize;
|
||||
arenasSize = aShell->EstimateMemoryUsed();
|
||||
arenasSize += aShell->mPresContext->EstimateMemoryUsed();
|
||||
|
||||
PRUint32 styleSize;
|
||||
styleSize = aShell->StyleSet()->SizeOf();
|
||||
|
||||
data->callback->
|
||||
Callback(EmptyCString(), arenaPath, nsIMemoryReporter::KIND_HEAP,
|
||||
nsIMemoryReporter::UNITS_BYTES, arenasSize, kArenaDesc,
|
||||
data->closure);
|
||||
|
||||
data->callback->
|
||||
Callback(EmptyCString(), stylePath, nsIMemoryReporter::KIND_HEAP,
|
||||
nsIMemoryReporter::UNITS_BYTES, styleSize, kStyleDesc,
|
||||
data->closure);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::MemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
||||
nsISupports* aClosure)
|
||||
{
|
||||
MemoryReporterData data;
|
||||
data.callback = aCb;
|
||||
data.closure = aClosure;
|
||||
|
||||
sLiveShells->EnumerateEntries(SizeEnumerator, &data);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsAutoCauseReflowNotifier
|
||||
{
|
||||
public:
|
||||
|
@ -1665,20 +1719,6 @@ NS_NewPresShell(nsIPresShell** aInstancePtrResult)
|
|||
nsTHashtable<PresShell::PresShellPtrKey> *nsIPresShell::sLiveShells = 0;
|
||||
static PRBool sSynthMouseMove = PR_TRUE;
|
||||
|
||||
NS_MEMORY_REPORTER_IMPLEMENT(LayoutPresShell,
|
||||
"explicit/layout/arenas",
|
||||
KIND_HEAP,
|
||||
UNITS_BYTES,
|
||||
PresShell::SizeOfLayoutMemoryReporter,
|
||||
"Memory used by layout PresShell, PresContext, and other related areas.")
|
||||
|
||||
NS_MEMORY_REPORTER_IMPLEMENT(LayoutStyle,
|
||||
"explicit/layout/styledata",
|
||||
KIND_HEAP,
|
||||
UNITS_BYTES,
|
||||
PresShell::SizeOfStyleMemoryReporter,
|
||||
"Memory used by the style system.")
|
||||
|
||||
PresShell::PresShell()
|
||||
: mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
|
||||
{
|
||||
|
@ -1706,8 +1746,7 @@ PresShell::PresShell()
|
|||
|
||||
static bool registeredReporter = false;
|
||||
if (!registeredReporter) {
|
||||
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(LayoutPresShell));
|
||||
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(LayoutStyle));
|
||||
NS_RegisterMemoryMultiReporter(new MemoryReporter);
|
||||
Preferences::AddBoolVarCache(&sSynthMouseMove,
|
||||
"layout.reflow.synthMouseMove", PR_TRUE);
|
||||
registeredReporter = true;
|
||||
|
|
|
@ -299,16 +299,8 @@ GARBAGE += $(VPX_CONVERTED_ASFILES)
|
|||
|
||||
%.asm.$(ASM_SUFFIX): %.asm
|
||||
$(VPX_AS_CONVERSION) < $< > $@
|
||||
|
||||
vpx_asm_offsets.asm: vpx_asm_offsets.$(OBJ_SUFFIX) $(HOST_PROGRAM)
|
||||
./$(HOST_PROGRAM) rvds $< | $(VPX_AS_CONVERSION) > $@
|
||||
|
||||
else
|
||||
ASFILES += $(VPX_ASFILES)
|
||||
|
||||
vpx_asm_offsets.asm: vpx_asm_offsets.$(OBJ_SUFFIX) $(HOST_PROGRAM)
|
||||
./$(HOST_PROGRAM) rvds $< > $@
|
||||
|
||||
endif
|
||||
|
||||
GARBAGE += vpx_asm_offsets.$(OBJ_SUFFIX) vpx_asm_offsets.asm
|
||||
|
@ -326,3 +318,8 @@ filter_c.o: filter_c.c Makefile.in
|
|||
$(CC) -o $@ -c $(patsubst -xO[45],-xO3,$(COMPILE_CFLAGS)) $<
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef VPX_ARM_ASM
|
||||
vpx_asm_offsets.asm: vpx_asm_offsets.$(OBJ_SUFFIX) $(HOST_PROGRAM)
|
||||
./$(HOST_PROGRAM) rvds $< $(if $(VPX_AS_CONVERSION),| $(VPX_AS_CONVERSION)) > $@
|
||||
endif
|
||||
|
|
|
@ -46,7 +46,9 @@ EXPORTS
|
|||
posix_memalign=je_posix_memalign
|
||||
strndup=je_strndup
|
||||
strdup=je_strdup
|
||||
_strdup=je_strdup
|
||||
wcsdup=je_wcsdup
|
||||
_wcsdup=je_wcsdup
|
||||
malloc_usable_size=je_malloc_usable_size
|
||||
jemalloc_stats
|
||||
; A hack to work around the CRT (see giant comment in Makefile.in)
|
||||
|
|
|
@ -3,6 +3,22 @@ README.txt
|
|||
extensions/feedback@mobile.mozilla.org.xpi
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
#if _MSC_VER != 1400
|
||||
@BINPATH@/Microsoft.VC80.CRT.manifest
|
||||
@BINPATH@/msvcm80.dll
|
||||
@BINPATH@/msvcp80.dll
|
||||
@BINPATH@/msvcr80.dll
|
||||
#endif
|
||||
#if _MSC_VER != 1500
|
||||
@BINPATH@/Microsoft.VC90.CRT.manifest
|
||||
@BINPATH@/msvcm90.dll
|
||||
@BINPATH@/msvcp90.dll
|
||||
@BINPATH@/msvcr90.dll
|
||||
#endif
|
||||
#if _MSC_VER != 1600
|
||||
@BINPATH@/msvcp100.dll
|
||||
@BINPATH@/msvcr100.dll
|
||||
#endif
|
||||
mozcrt19.dll
|
||||
mozcpp19.dll
|
||||
#endif
|
||||
|
|
|
@ -314,7 +314,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
|
|||
PostDataError();
|
||||
return;
|
||||
}
|
||||
if (mBIH.compression == BI_RLE4 && mBIH.bpp != 4) {
|
||||
if (mBIH.compression == BI_RLE4 && mBIH.bpp != 4 && mBIH.bpp != 1) {
|
||||
PR_LOG(gBMPLog, PR_LOG_DEBUG,
|
||||
("BMP RLE4 compression only supports 4 bits per pixel\n"));
|
||||
PostDataError();
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSPR_4_9_BETA1
|
||||
NSPR_4_9_BETA2
|
||||
|
|
|
@ -22,7 +22,10 @@ DIST = $(dist_prefix)
|
|||
RELEASE_OBJDIR_NAME = @RELEASE_OBJDIR_NAME@
|
||||
OBJDIR_NAME = @OBJDIR_NAME@
|
||||
OBJDIR = @OBJDIR@
|
||||
OBJ_SUFFIX = @OBJ_SUFFIX@
|
||||
# We do magic with OBJ_SUFFIX in config.mk, the following ensures we don't
|
||||
# manually use it before config.mk inclusion
|
||||
OBJ_SUFFIX = $(error config/config.mk needs to be included before using OBJ_SUFFIX)
|
||||
_OBJ_SUFFIX = @OBJ_SUFFIX@
|
||||
LIB_SUFFIX = @LIB_SUFFIX@
|
||||
DLL_SUFFIX = @DLL_SUFFIX@
|
||||
ASM_SUFFIX = @ASM_SUFFIX@
|
||||
|
@ -88,8 +91,7 @@ PROFILE_USE_CFLAGS = @PROFILE_USE_CFLAGS@
|
|||
PROFILE_USE_LDFLAGS = @PROFILE_USE_LDFLAGS@
|
||||
|
||||
MKSHLIB = @MKSHLIB@
|
||||
WRAP_MALLOC_LIB = @WRAP_MALLOC_LIB@
|
||||
WRAP_MALLOC_CFLAGS = @WRAP_MALLOC_CFLAGS@
|
||||
WRAP_LDFLAGS = @WRAP_LDFLAGS@
|
||||
DSO_CFLAGS = @DSO_CFLAGS@
|
||||
DSO_LDOPTS = @DSO_LDOPTS@
|
||||
|
||||
|
|
|
@ -175,3 +175,19 @@ RELEASE_DIR = $(MOD_DEPTH)/dist/release/$(MOD_NAME)
|
|||
RELEASE_INCLUDE_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/include
|
||||
RELEASE_BIN_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/bin
|
||||
RELEASE_LIB_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/lib
|
||||
|
||||
# autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
|
||||
# this file
|
||||
OBJ_SUFFIX := $(_OBJ_SUFFIX)
|
||||
|
||||
# PGO builds with GCC build objects with instrumentation in a first pass,
|
||||
# then objects optimized, without instrumentation, in a second pass. If
|
||||
# we overwrite the ojects from the first pass with those from the second,
|
||||
# we end up not getting instrumentation data for better optimization on
|
||||
# incremental builds. As a consequence, we use a different object suffix
|
||||
# for the first pass.
|
||||
ifdef MOZ_PROFILE_GENERATE
|
||||
ifdef NS_USE_GCC
|
||||
OBJ_SUFFIX := i_o
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -166,6 +166,7 @@ endif
|
|||
|
||||
ALL_TRASH = $(TARGETS) $(OBJS) $(RES) $(filter-out . .., $(OBJDIR)) LOGS TAGS $(GARBAGE) \
|
||||
$(NOSUCHFILE) \
|
||||
$(OBJS:.$(OBJ_SUFFIX)=.i_o) \
|
||||
so_locations
|
||||
|
||||
ifndef RELEASE_LIBS_DEST
|
||||
|
@ -300,7 +301,7 @@ ifdef MOZ_PROFILE_GENERATE
|
|||
touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink
|
||||
endif # MOZ_PROFILE_GENERATE
|
||||
else # WINNT && !GCC
|
||||
$(CC) -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS)
|
||||
$(CC) -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS) $(WRAP_LDFLAGS)
|
||||
endif # WINNT && !GCC
|
||||
ifdef ENABLE_STRIP
|
||||
$(STRIP) $@
|
||||
|
@ -353,7 +354,7 @@ ifdef MOZ_PROFILE_GENERATE
|
|||
touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink
|
||||
endif # MOZ_PROFILE_GENERATE
|
||||
else # WINNT && !GCC
|
||||
$(MKSHLIB) $(OBJS) $(RES) $(LDFLAGS) $(EXTRA_LIBS)
|
||||
$(MKSHLIB) $(OBJS) $(RES) $(LDFLAGS) $(WRAP_LDFLAGS) $(EXTRA_LIBS)
|
||||
endif # WINNT && !GCC
|
||||
endif # AIX 4.1
|
||||
ifdef ENABLE_STRIP
|
||||
|
@ -376,12 +377,27 @@ $(PROGRAM): pgo.relink
|
|||
endif # WINNT && !GCC
|
||||
endif # MOZ_PROFILE_USE
|
||||
|
||||
ifneq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
|
||||
ifdef NS_USE_GCC
|
||||
# Force rebuilding libraries and programs in both passes because each
|
||||
# pass uses different object files.
|
||||
$(PROGRAM) $(SHARED_LIBRARY) $(LIBRARY): FORCE
|
||||
.PHONY: FORCE
|
||||
endif
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
ifdef MOZ_PROFILE_GENERATE
|
||||
# Clean up profiling data during PROFILE_GENERATE phase
|
||||
export::
|
||||
-$(RM) *.pgd *.gcda
|
||||
ifeq ($(OS_ARCH)_$(NS_USE_GCC), WINNT_)
|
||||
$(foreach pgd,$(wildcard *.pgd),pgomgr -clear $(pgd);)
|
||||
else
|
||||
ifdef NS_USE_GCC
|
||||
-$(RM) *.gcda
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
|
|
@ -942,8 +942,6 @@ echo "configure:903: checking for android platform directory" >&5
|
|||
HOST_LDFLAGS=" "
|
||||
fi
|
||||
|
||||
WRAP_MALLOC_CFLAGS="-Wl,--wrap=dlopen -Wl,--wrap=dlclose -Wl,--wrap=dlerror -Wl,--wrap=dlsym -Wl,--wrap=dladdr"
|
||||
|
||||
cat >> confdefs.h <<\EOF
|
||||
#define ANDROID 1
|
||||
EOF
|
||||
|
@ -1243,7 +1241,7 @@ if test -z "$SKIP_PATH_CHECKS"; then
|
|||
# Extract the first word of "$WHOAMI whoami", so it can be a program name with args.
|
||||
set dummy $WHOAMI whoami; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1247: checking for $ac_word" >&5
|
||||
echo "configure:1245: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_WHOAMI'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1315,13 +1313,13 @@ if test "$target" != "$host" -o -n "$CROSS_COMPILE"; then
|
|||
_SAVE_LDFLAGS="$LDFLAGS"
|
||||
|
||||
echo $ac_n "checking for $host compiler""... $ac_c" 1>&6
|
||||
echo "configure:1319: checking for $host compiler" >&5
|
||||
echo "configure:1317: checking for $host compiler" >&5
|
||||
for ac_prog in $HOST_CC gcc cc /usr/ucb/cc
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1325: checking for $ac_word" >&5
|
||||
echo "configure:1323: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_HOST_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1367,16 +1365,16 @@ test -n "$HOST_CC" || HOST_CC=""""
|
|||
LDFLAGS="$HOST_LDFLAGS"
|
||||
|
||||
echo $ac_n "checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works""... $ac_c" 1>&6
|
||||
echo "configure:1371: checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works" >&5
|
||||
echo "configure:1369: checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works" >&5
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1373 "configure"
|
||||
#line 1371 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() {
|
||||
return(0);
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:1380: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
if { (eval echo configure:1378: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
ac_cv_prog_host_cc_works=1 echo "$ac_t""yes" 1>&6
|
||||
else
|
||||
|
@ -1411,7 +1409,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1415: checking for $ac_word" >&5
|
||||
echo "configure:1413: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1445,7 +1443,7 @@ test -n "$CC" || CC="echo"
|
|||
# Extract the first word of "gcc", so it can be a program name with args.
|
||||
set dummy gcc; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1449: checking for $ac_word" >&5
|
||||
echo "configure:1447: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1475,7 +1473,7 @@ if test -z "$CC"; then
|
|||
# Extract the first word of "cc", so it can be a program name with args.
|
||||
set dummy cc; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1479: checking for $ac_word" >&5
|
||||
echo "configure:1477: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1526,7 +1524,7 @@ fi
|
|||
# Extract the first word of "cl", so it can be a program name with args.
|
||||
set dummy cl; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1530: checking for $ac_word" >&5
|
||||
echo "configure:1528: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1558,7 +1556,7 @@ fi
|
|||
fi
|
||||
|
||||
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
|
||||
echo "configure:1562: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
|
||||
echo "configure:1560: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
|
||||
|
||||
ac_ext=c
|
||||
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
|
||||
|
@ -1569,12 +1567,12 @@ cross_compiling=$ac_cv_prog_cc_cross
|
|||
|
||||
cat > conftest.$ac_ext << EOF
|
||||
|
||||
#line 1573 "configure"
|
||||
#line 1571 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
main(){return(0);}
|
||||
EOF
|
||||
if { (eval echo configure:1578: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:1576: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
ac_cv_prog_cc_works=yes
|
||||
# If we can't run a trivial program, we are probably using a cross compiler.
|
||||
if (./conftest; exit) 2>/dev/null; then
|
||||
|
@ -1600,12 +1598,12 @@ if test $ac_cv_prog_cc_works = no; then
|
|||
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
|
||||
fi
|
||||
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
|
||||
echo "configure:1604: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
|
||||
echo "configure:1602: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
|
||||
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
|
||||
cross_compiling=$ac_cv_prog_cc_cross
|
||||
|
||||
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
|
||||
echo "configure:1609: checking whether we are using GNU C" >&5
|
||||
echo "configure:1607: checking whether we are using GNU C" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1614,7 +1612,7 @@ else
|
|||
yes;
|
||||
#endif
|
||||
EOF
|
||||
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1618: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
|
||||
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1616: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
|
||||
ac_cv_prog_gcc=yes
|
||||
else
|
||||
ac_cv_prog_gcc=no
|
||||
|
@ -1633,7 +1631,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
|
|||
ac_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS=
|
||||
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
|
||||
echo "configure:1637: checking whether ${CC-cc} accepts -g" >&5
|
||||
echo "configure:1635: checking whether ${CC-cc} accepts -g" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1670,7 +1668,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1674: checking for $ac_word" >&5
|
||||
echo "configure:1672: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1706,7 +1704,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1710: checking for $ac_word" >&5
|
||||
echo "configure:1708: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1738,7 +1736,7 @@ test -n "$CXX" || CXX="gcc"
|
|||
|
||||
|
||||
echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
|
||||
echo "configure:1742: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
|
||||
echo "configure:1740: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
|
||||
|
||||
ac_ext=C
|
||||
# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
|
||||
|
@ -1749,12 +1747,12 @@ cross_compiling=$ac_cv_prog_cxx_cross
|
|||
|
||||
cat > conftest.$ac_ext << EOF
|
||||
|
||||
#line 1753 "configure"
|
||||
#line 1751 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main(){return(0);}
|
||||
EOF
|
||||
if { (eval echo configure:1758: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:1756: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
ac_cv_prog_cxx_works=yes
|
||||
# If we can't run a trivial program, we are probably using a cross compiler.
|
||||
if (./conftest; exit) 2>/dev/null; then
|
||||
|
@ -1780,12 +1778,12 @@ if test $ac_cv_prog_cxx_works = no; then
|
|||
{ echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
|
||||
fi
|
||||
echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
|
||||
echo "configure:1784: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
|
||||
echo "configure:1782: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
|
||||
echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
|
||||
cross_compiling=$ac_cv_prog_cxx_cross
|
||||
|
||||
echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
|
||||
echo "configure:1789: checking whether we are using GNU C++" >&5
|
||||
echo "configure:1787: checking whether we are using GNU C++" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1794,7 +1792,7 @@ else
|
|||
yes;
|
||||
#endif
|
||||
EOF
|
||||
if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1798: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
|
||||
if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1796: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
|
||||
ac_cv_prog_gxx=yes
|
||||
else
|
||||
ac_cv_prog_gxx=no
|
||||
|
@ -1813,7 +1811,7 @@ ac_test_CXXFLAGS="${CXXFLAGS+set}"
|
|||
ac_save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS=
|
||||
echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
|
||||
echo "configure:1817: checking whether ${CXX-g++} accepts -g" >&5
|
||||
echo "configure:1815: checking whether ${CXX-g++} accepts -g" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1858,7 +1856,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1862: checking for $ac_word" >&5
|
||||
echo "configure:1860: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1893,7 +1891,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1897: checking for $ac_word" >&5
|
||||
echo "configure:1895: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1928,7 +1926,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1932: checking for $ac_word" >&5
|
||||
echo "configure:1930: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1963,7 +1961,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1967: checking for $ac_word" >&5
|
||||
echo "configure:1965: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_LD'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1998,7 +1996,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2002: checking for $ac_word" >&5
|
||||
echo "configure:2000: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2033,7 +2031,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2037: checking for $ac_word" >&5
|
||||
echo "configure:2035: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_WINDRES'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2068,7 +2066,7 @@ else
|
|||
# Extract the first word of "gcc", so it can be a program name with args.
|
||||
set dummy gcc; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2072: checking for $ac_word" >&5
|
||||
echo "configure:2070: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2098,7 +2096,7 @@ if test -z "$CC"; then
|
|||
# Extract the first word of "cc", so it can be a program name with args.
|
||||
set dummy cc; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2102: checking for $ac_word" >&5
|
||||
echo "configure:2100: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2149,7 +2147,7 @@ fi
|
|||
# Extract the first word of "cl", so it can be a program name with args.
|
||||
set dummy cl; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2153: checking for $ac_word" >&5
|
||||
echo "configure:2151: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2181,7 +2179,7 @@ fi
|
|||
fi
|
||||
|
||||
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
|
||||
echo "configure:2185: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
|
||||
echo "configure:2183: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
|
||||
|
||||
ac_ext=c
|
||||
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
|
||||
|
@ -2192,12 +2190,12 @@ cross_compiling=$ac_cv_prog_cc_cross
|
|||
|
||||
cat > conftest.$ac_ext << EOF
|
||||
|
||||
#line 2196 "configure"
|
||||
#line 2194 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
main(){return(0);}
|
||||
EOF
|
||||
if { (eval echo configure:2201: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:2199: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
ac_cv_prog_cc_works=yes
|
||||
# If we can't run a trivial program, we are probably using a cross compiler.
|
||||
if (./conftest; exit) 2>/dev/null; then
|
||||
|
@ -2223,12 +2221,12 @@ if test $ac_cv_prog_cc_works = no; then
|
|||
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
|
||||
fi
|
||||
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
|
||||
echo "configure:2227: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
|
||||
echo "configure:2225: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
|
||||
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
|
||||
cross_compiling=$ac_cv_prog_cc_cross
|
||||
|
||||
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
|
||||
echo "configure:2232: checking whether we are using GNU C" >&5
|
||||
echo "configure:2230: checking whether we are using GNU C" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2237,7 +2235,7 @@ else
|
|||
yes;
|
||||
#endif
|
||||
EOF
|
||||
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2241: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
|
||||
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2239: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
|
||||
ac_cv_prog_gcc=yes
|
||||
else
|
||||
ac_cv_prog_gcc=no
|
||||
|
@ -2256,7 +2254,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
|
|||
ac_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS=
|
||||
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
|
||||
echo "configure:2260: checking whether ${CC-cc} accepts -g" >&5
|
||||
echo "configure:2258: checking whether ${CC-cc} accepts -g" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2296,7 +2294,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2300: checking for $ac_word" >&5
|
||||
echo "configure:2298: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2328,7 +2326,7 @@ test -n "$CXX" || CXX="gcc"
|
|||
|
||||
|
||||
echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
|
||||
echo "configure:2332: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
|
||||
echo "configure:2330: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
|
||||
|
||||
ac_ext=C
|
||||
# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
|
||||
|
@ -2339,12 +2337,12 @@ cross_compiling=$ac_cv_prog_cxx_cross
|
|||
|
||||
cat > conftest.$ac_ext << EOF
|
||||
|
||||
#line 2343 "configure"
|
||||
#line 2341 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main(){return(0);}
|
||||
EOF
|
||||
if { (eval echo configure:2348: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:2346: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
ac_cv_prog_cxx_works=yes
|
||||
# If we can't run a trivial program, we are probably using a cross compiler.
|
||||
if (./conftest; exit) 2>/dev/null; then
|
||||
|
@ -2370,12 +2368,12 @@ if test $ac_cv_prog_cxx_works = no; then
|
|||
{ echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
|
||||
fi
|
||||
echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
|
||||
echo "configure:2374: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
|
||||
echo "configure:2372: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
|
||||
echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
|
||||
cross_compiling=$ac_cv_prog_cxx_cross
|
||||
|
||||
echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
|
||||
echo "configure:2379: checking whether we are using GNU C++" >&5
|
||||
echo "configure:2377: checking whether we are using GNU C++" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2384,7 +2382,7 @@ else
|
|||
yes;
|
||||
#endif
|
||||
EOF
|
||||
if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:2388: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
|
||||
if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:2386: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
|
||||
ac_cv_prog_gxx=yes
|
||||
else
|
||||
ac_cv_prog_gxx=no
|
||||
|
@ -2403,7 +2401,7 @@ ac_test_CXXFLAGS="${CXXFLAGS+set}"
|
|||
ac_save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS=
|
||||
echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
|
||||
echo "configure:2407: checking whether ${CXX-g++} accepts -g" >&5
|
||||
echo "configure:2405: checking whether ${CXX-g++} accepts -g" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2437,7 +2435,7 @@ fi
|
|||
fi
|
||||
fi
|
||||
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
|
||||
echo "configure:2441: checking how to run the C preprocessor" >&5
|
||||
echo "configure:2439: checking how to run the C preprocessor" >&5
|
||||
# On Suns, sometimes $CPP names a directory.
|
||||
if test -n "$CPP" && test -d "$CPP"; then
|
||||
CPP=
|
||||
|
@ -2452,13 +2450,13 @@ else
|
|||
# On the NeXT, cc -E runs the code through the compiler's parser,
|
||||
# not just through cpp.
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 2456 "configure"
|
||||
#line 2454 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:2462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:2460: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
:
|
||||
|
@ -2469,13 +2467,13 @@ else
|
|||
rm -rf conftest*
|
||||
CPP="${CC-cc} -E -traditional-cpp"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 2473 "configure"
|
||||
#line 2471 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:2479: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:2477: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
:
|
||||
|
@ -2486,13 +2484,13 @@ else
|
|||
rm -rf conftest*
|
||||
CPP="${CC-cc} -nologo -E"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 2490 "configure"
|
||||
#line 2488 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:2496: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:2494: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
:
|
||||
|
@ -2519,7 +2517,7 @@ echo "$ac_t""$CPP" 1>&6
|
|||
# Extract the first word of "ranlib", so it can be a program name with args.
|
||||
set dummy ranlib; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2523: checking for $ac_word" >&5
|
||||
echo "configure:2521: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2551,7 +2549,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2555: checking for $ac_word" >&5
|
||||
echo "configure:2553: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_AS'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2592,7 +2590,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2596: checking for $ac_word" >&5
|
||||
echo "configure:2594: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2633,7 +2631,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2637: checking for $ac_word" >&5
|
||||
echo "configure:2635: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2674,7 +2672,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2678: checking for $ac_word" >&5
|
||||
echo "configure:2676: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_STRIP'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2715,7 +2713,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2719: checking for $ac_word" >&5
|
||||
echo "configure:2717: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_WINDRES'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2783,7 +2781,7 @@ else
|
|||
fi
|
||||
|
||||
echo $ac_n "checking for gcc -pipe support""... $ac_c" 1>&6
|
||||
echo "configure:2787: checking for gcc -pipe support" >&5
|
||||
echo "configure:2785: checking for gcc -pipe support" >&5
|
||||
if test -n "$GNU_CC" && test -n "$GNU_CXX" && test -n "$GNU_AS"; then
|
||||
echo '#include <stdio.h>' > dummy-hello.c
|
||||
echo 'int main() { printf("Hello World\n"); return 0; }' >> dummy-hello.c
|
||||
|
@ -2798,14 +2796,14 @@ if test -n "$GNU_CC" && test -n "$GNU_CXX" && test -n "$GNU_AS"; then
|
|||
_SAVE_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS -pipe"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 2802 "configure"
|
||||
#line 2800 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <stdio.h>
|
||||
int main() {
|
||||
printf("Hello World\n");
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:2809: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
if { (eval echo configure:2807: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
_res_gcc_pipe="yes"
|
||||
else
|
||||
|
@ -2835,16 +2833,16 @@ _SAVE_CFLAGS="$CFLAGS"
|
|||
CFLAGS="$CFLAGS -fprofile-generate -fprofile-correction"
|
||||
|
||||
echo $ac_n "checking whether C compiler supports -fprofile-generate""... $ac_c" 1>&6
|
||||
echo "configure:2839: checking whether C compiler supports -fprofile-generate" >&5
|
||||
echo "configure:2837: checking whether C compiler supports -fprofile-generate" >&5
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 2841 "configure"
|
||||
#line 2839 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:2848: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
if { (eval echo configure:2846: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
PROFILE_GEN_CFLAGS="-fprofile-generate"
|
||||
result="yes"
|
||||
|
@ -2867,7 +2865,7 @@ CFLAGS="$_SAVE_CFLAGS"
|
|||
|
||||
if test "$GNU_CC"; then
|
||||
echo $ac_n "checking for visibility(hidden) attribute""... $ac_c" 1>&6
|
||||
echo "configure:2871: checking for visibility(hidden) attribute" >&5
|
||||
echo "configure:2869: checking for visibility(hidden) attribute" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_visibility_hidden'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2891,7 +2889,7 @@ echo "$ac_t""$ac_cv_visibility_hidden" 1>&6
|
|||
EOF
|
||||
|
||||
echo $ac_n "checking for visibility pragma support""... $ac_c" 1>&6
|
||||
echo "configure:2895: checking for visibility pragma support" >&5
|
||||
echo "configure:2893: checking for visibility pragma support" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_visibility_pragma'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -2944,7 +2942,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:2948: checking for $ac_word" >&5
|
||||
echo "configure:2946: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -3265,14 +3263,14 @@ no)
|
|||
_SAVE_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$arch_flag"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3269 "configure"
|
||||
#line 3267 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() {
|
||||
return sizeof(__thumb2__);
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3276: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
if { (eval echo configure:3274: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
MOZ_THUMB2=1
|
||||
else
|
||||
|
@ -3334,16 +3332,16 @@ if test -n "$all_flags"; then
|
|||
_SAVE_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$all_flags"
|
||||
echo $ac_n "checking whether the chosen combination of compiler flags ($all_flags) works""... $ac_c" 1>&6
|
||||
echo "configure:3338: checking whether the chosen combination of compiler flags ($all_flags) works" >&5
|
||||
echo "configure:3336: checking whether the chosen combination of compiler flags ($all_flags) works" >&5
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3340 "configure"
|
||||
#line 3338 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3347: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
if { (eval echo configure:3345: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
echo "$ac_t""yes" 1>&6
|
||||
else
|
||||
|
@ -3400,17 +3398,17 @@ EOF
|
|||
DSO_LDOPTS='-brtl -bnortllib -bM:SRE -bnoentry -bexpall -blibpath:/usr/lib:/lib'
|
||||
ac_safe=`echo "sys/atomic_op.h" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for sys/atomic_op.h""... $ac_c" 1>&6
|
||||
echo "configure:3404: checking for sys/atomic_op.h" >&5
|
||||
echo "configure:3402: checking for sys/atomic_op.h" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3409 "configure"
|
||||
#line 3407 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <sys/atomic_op.h>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:3414: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:3412: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
|
@ -3564,7 +3562,7 @@ EOF
|
|||
CXXFLAGS="$CXXFLAGS -Wall"
|
||||
MDCPUCFG_H=_linux.cfg
|
||||
PR_MD_CSRCS=linux.c
|
||||
MKSHLIB='$(CC) $(DSO_LDOPTS) $(WRAP_MALLOC_LIB) -o $@'
|
||||
MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
|
||||
DSO_CFLAGS=-fPIC
|
||||
DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
|
||||
_OPTIMIZE_FLAGS=-O2
|
||||
|
@ -3606,7 +3604,7 @@ EOF
|
|||
_DEBUG_FLAGS='-gdwarf-2 -O0'
|
||||
MKSHLIB='$(CCC) $(DSO_LDOPTS) -o $@'
|
||||
echo $ac_n "checking for gethostbyaddr in -lbind""... $ac_c" 1>&6
|
||||
echo "configure:3610: checking for gethostbyaddr in -lbind" >&5
|
||||
echo "configure:3608: checking for gethostbyaddr in -lbind" >&5
|
||||
ac_lib_var=`echo bind'_'gethostbyaddr | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
|
@ -3614,7 +3612,7 @@ else
|
|||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-lbind $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3618 "configure"
|
||||
#line 3616 "configure"
|
||||
#include "confdefs.h"
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
|
@ -3625,7 +3623,7 @@ int main() {
|
|||
gethostbyaddr()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3629: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:3627: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
|
@ -3831,17 +3829,17 @@ EOF
|
|||
fi
|
||||
ac_safe=`echo "crt_externs.h" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for crt_externs.h""... $ac_c" 1>&6
|
||||
echo "configure:3835: checking for crt_externs.h" >&5
|
||||
echo "configure:3833: checking for crt_externs.h" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3840 "configure"
|
||||
#line 3838 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <crt_externs.h>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:3845: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:3843: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
|
@ -4400,7 +4398,7 @@ EOF
|
|||
CXXFLAGS="$CXXFLAGS -Wall"
|
||||
MDCPUCFG_H=_linux.cfg
|
||||
PR_MD_CSRCS=linux.c
|
||||
MKSHLIB='$(CC) $(DSO_LDOPTS) $(WRAP_MALLOC_LIB) -o $@'
|
||||
MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
|
||||
DSO_CFLAGS=-fPIC
|
||||
DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
|
||||
_OPTIMIZE_FLAGS=-O2
|
||||
|
@ -5015,17 +5013,17 @@ EOF
|
|||
_OPTIMIZE_FLAGS="$_OPTIMIZE_FLAGS -Olimit 4000"
|
||||
ac_safe=`echo "machine/builtins.h" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for machine/builtins.h""... $ac_c" 1>&6
|
||||
echo "configure:5019: checking for machine/builtins.h" >&5
|
||||
echo "configure:5017: checking for machine/builtins.h" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 5024 "configure"
|
||||
#line 5022 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <machine/builtins.h>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:5029: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:5027: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
|
@ -5674,7 +5672,7 @@ case $target in
|
|||
;;
|
||||
*)
|
||||
echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
|
||||
echo "configure:5678: checking for dlopen in -ldl" >&5
|
||||
echo "configure:5676: checking for dlopen in -ldl" >&5
|
||||
ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
|
@ -5682,7 +5680,7 @@ else
|
|||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-ldl $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 5686 "configure"
|
||||
#line 5684 "configure"
|
||||
#include "confdefs.h"
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
|
@ -5693,7 +5691,7 @@ int main() {
|
|||
dlopen()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:5697: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:5695: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
|
@ -5710,17 +5708,17 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
|
|||
echo "$ac_t""yes" 1>&6
|
||||
ac_safe=`echo "dlfcn.h" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for dlfcn.h""... $ac_c" 1>&6
|
||||
echo "configure:5714: checking for dlfcn.h" >&5
|
||||
echo "configure:5712: checking for dlfcn.h" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 5719 "configure"
|
||||
#line 5717 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <dlfcn.h>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:5724: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:5722: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
|
@ -5753,13 +5751,13 @@ esac
|
|||
|
||||
if test $ac_cv_prog_gcc = yes; then
|
||||
echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
|
||||
echo "configure:5757: checking whether ${CC-cc} needs -traditional" >&5
|
||||
echo "configure:5755: checking whether ${CC-cc} needs -traditional" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
ac_pattern="Autoconf.*'x'"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 5763 "configure"
|
||||
#line 5761 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <sgtty.h>
|
||||
Autoconf TIOCGETP
|
||||
|
@ -5777,7 +5775,7 @@ rm -f conftest*
|
|||
|
||||
if test $ac_cv_prog_gcc_traditional = no; then
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 5781 "configure"
|
||||
#line 5779 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <termio.h>
|
||||
Autoconf TCGETA
|
||||
|
@ -5801,12 +5799,12 @@ fi
|
|||
for ac_func in lchown strerror
|
||||
do
|
||||
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
|
||||
echo "configure:5805: checking for $ac_func" >&5
|
||||
echo "configure:5803: checking for $ac_func" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 5810 "configure"
|
||||
#line 5808 "configure"
|
||||
#include "confdefs.h"
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $ac_func(); below. */
|
||||
|
@ -5829,7 +5827,7 @@ $ac_func();
|
|||
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:5833: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:5831: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_func_$ac_func=yes"
|
||||
else
|
||||
|
@ -5880,7 +5878,7 @@ do
|
|||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:5884: checking for $ac_word" >&5
|
||||
echo "configure:5882: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_CCACHE'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -5939,7 +5937,7 @@ hpux*)
|
|||
if test -z "$GNU_CC"; then
|
||||
|
||||
echo $ac_n "checking for +Olit support""... $ac_c" 1>&6
|
||||
echo "configure:5943: checking for +Olit support" >&5
|
||||
echo "configure:5941: checking for +Olit support" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_hpux_usable_olit_option'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -5981,7 +5979,7 @@ wince*)
|
|||
*)
|
||||
|
||||
echo $ac_n "checking for pthread_create in -lpthreads""... $ac_c" 1>&6
|
||||
echo "configure:5985: checking for pthread_create in -lpthreads" >&5
|
||||
echo "configure:5983: checking for pthread_create in -lpthreads" >&5
|
||||
echo "
|
||||
#include <pthread.h>
|
||||
void *foo(void *v) { return v; }
|
||||
|
@ -6003,7 +6001,7 @@ echo "
|
|||
echo "$ac_t""no" 1>&6
|
||||
|
||||
echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
|
||||
echo "configure:6007: checking for pthread_create in -lpthread" >&5
|
||||
echo "configure:6005: checking for pthread_create in -lpthread" >&5
|
||||
echo "
|
||||
#include <pthread.h>
|
||||
void *foo(void *v) { return v; }
|
||||
|
@ -6025,7 +6023,7 @@ echo "
|
|||
echo "$ac_t""no" 1>&6
|
||||
|
||||
echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6
|
||||
echo "configure:6029: checking for pthread_create in -lc_r" >&5
|
||||
echo "configure:6027: checking for pthread_create in -lc_r" >&5
|
||||
echo "
|
||||
#include <pthread.h>
|
||||
void *foo(void *v) { return v; }
|
||||
|
@ -6047,7 +6045,7 @@ echo "
|
|||
echo "$ac_t""no" 1>&6
|
||||
|
||||
echo $ac_n "checking for pthread_create in -lc""... $ac_c" 1>&6
|
||||
echo "configure:6051: checking for pthread_create in -lc" >&5
|
||||
echo "configure:6049: checking for pthread_create in -lc" >&5
|
||||
echo "
|
||||
#include <pthread.h>
|
||||
void *foo(void *v) { return v; }
|
||||
|
@ -6165,7 +6163,7 @@ if test -n "$USE_PTHREADS"; then
|
|||
rm -f conftest*
|
||||
ac_cv_have_dash_pthread=no
|
||||
echo $ac_n "checking whether ${CC-cc} accepts -pthread""... $ac_c" 1>&6
|
||||
echo "configure:6169: checking whether ${CC-cc} accepts -pthread" >&5
|
||||
echo "configure:6167: checking whether ${CC-cc} accepts -pthread" >&5
|
||||
echo 'int main() { return 0; }' | cat > conftest.c
|
||||
${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1
|
||||
if test $? -eq 0; then
|
||||
|
@ -6188,7 +6186,7 @@ echo "configure:6169: checking whether ${CC-cc} accepts -pthread" >&5
|
|||
ac_cv_have_dash_pthreads=no
|
||||
if test "$ac_cv_have_dash_pthread" = "no"; then
|
||||
echo $ac_n "checking whether ${CC-cc} accepts -pthreads""... $ac_c" 1>&6
|
||||
echo "configure:6192: checking whether ${CC-cc} accepts -pthreads" >&5
|
||||
echo "configure:6190: checking whether ${CC-cc} accepts -pthreads" >&5
|
||||
echo 'int main() { return 0; }' | cat > conftest.c
|
||||
${CC-cc} -pthreads -o conftest conftest.c > conftest.out 2>&1
|
||||
if test $? -eq 0; then
|
||||
|
@ -6511,18 +6509,21 @@ fi
|
|||
|
||||
|
||||
if test -n "$_WRAP_MALLOC"; then
|
||||
if test "$GNU_CC"; then
|
||||
WRAP_MALLOC_CFLAGS="${LDFLAGS} ${WRAP_MALLOC_CFLAGS} -Wl,--wrap -Wl,malloc -Wl,--wrap -Wl,calloc -Wl,--wrap -Wl,valloc -Wl,--wrap -Wl,free -Wl,--wrap -Wl,realloc -Wl,--wrap -Wl,memalign -Wl,--wrap -Wl,__builtin_new -Wl,--wrap -Wl,__builtin_vec_new -Wl,--wrap -Wl,__builtin_delete -Wl,--wrap -Wl,__builtin_vec_delete -Wl,--wrap -Wl,PR_Free -Wl,--wrap -Wl,PR_Malloc -Wl,--wrap -Wl,PR_Calloc -Wl,--wrap -Wl,PR_Realloc -Wl,--wrap -Wl,strdup -Wl,--wrap -Wl,strndup -Wl,--wrap -Wl,posix_memalign"
|
||||
DSO_LDOPTS="$DSO_LDOPTS $WRAP_MALLOC_CFLAGS"
|
||||
if test -n "$GNU_CC"; then
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=malloc,--wrap=calloc,--wrap=valloc,--wrap=free,--wrap=realloc,--wrap=memalign"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=__builtin_new,--wrap=__builtin_vec_new,--wrap=__builtin_delete,--wrap=__builtin_vec_delete"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=PR_Free,--wrap=PR_Malloc,--wrap=PR_Calloc,--wrap=PR_Realloc"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=strdup,--wrap=strndup"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=posix_memalign,--wrap=malloc_usable_size"
|
||||
else
|
||||
{ echo "configure: error: --enable-wrap-malloc is not supported for non-GNU toolchains" 1>&2; exit 1; }
|
||||
{ echo "configure: error: --enable-wrap-malloc is not supported for non-GNU toolchains" 1>&2; exit 1; }
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check whether --with-wrap-malloc or --without-wrap-malloc was given.
|
||||
if test "${with_wrap_malloc+set}" = set; then
|
||||
withval="$with_wrap_malloc"
|
||||
WRAP_MALLOC_LIB=$withval
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} $withval"
|
||||
fi
|
||||
|
||||
|
||||
|
@ -6628,7 +6629,6 @@ fi
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
MAKEFILES="
|
||||
|
@ -6896,8 +6896,7 @@ s%@OBJ_SUFFIX@%$OBJ_SUFFIX%g
|
|||
s%@LIB_SUFFIX@%$LIB_SUFFIX%g
|
||||
s%@DLL_SUFFIX@%$DLL_SUFFIX%g
|
||||
s%@ASM_SUFFIX@%$ASM_SUFFIX%g
|
||||
s%@WRAP_MALLOC_CFLAGS@%$WRAP_MALLOC_CFLAGS%g
|
||||
s%@WRAP_MALLOC_LIB@%$WRAP_MALLOC_LIB%g
|
||||
s%@WRAP_LDFLAGS@%$WRAP_LDFLAGS%g
|
||||
s%@MKSHLIB@%$MKSHLIB%g
|
||||
s%@DSO_CFLAGS@%$DSO_CFLAGS%g
|
||||
s%@DSO_LDOPTS@%$DSO_LDOPTS%g
|
||||
|
|
|
@ -234,8 +234,6 @@ case "$target" in
|
|||
HOST_LDFLAGS=" "
|
||||
fi
|
||||
|
||||
WRAP_MALLOC_CFLAGS="-Wl,--wrap=dlopen -Wl,--wrap=dlclose -Wl,--wrap=dlerror -Wl,--wrap=dlsym -Wl,--wrap=dladdr"
|
||||
|
||||
AC_DEFINE(ANDROID)
|
||||
;;
|
||||
esac
|
||||
|
@ -1231,7 +1229,7 @@ case "$target" in
|
|||
CXXFLAGS="$CXXFLAGS -Wall"
|
||||
MDCPUCFG_H=_linux.cfg
|
||||
PR_MD_CSRCS=linux.c
|
||||
MKSHLIB='$(CC) $(DSO_LDOPTS) $(WRAP_MALLOC_LIB) -o $@'
|
||||
MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
|
||||
DSO_CFLAGS=-fPIC
|
||||
DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
|
||||
_OPTIMIZE_FLAGS=-O2
|
||||
|
@ -1793,7 +1791,7 @@ tools are selected during the Xcode/Developer Tools installation.])
|
|||
CXXFLAGS="$CXXFLAGS -Wall"
|
||||
MDCPUCFG_H=_linux.cfg
|
||||
PR_MD_CSRCS=linux.c
|
||||
MKSHLIB='$(CC) $(DSO_LDOPTS) $(WRAP_MALLOC_LIB) -o $@'
|
||||
MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
|
||||
DSO_CFLAGS=-fPIC
|
||||
DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
|
||||
_OPTIMIZE_FLAGS=-O2
|
||||
|
@ -3178,11 +3176,14 @@ AC_ARG_ENABLE(wrap-malloc,
|
|||
fi ])
|
||||
|
||||
if test -n "$_WRAP_MALLOC"; then
|
||||
if test "$GNU_CC"; then
|
||||
WRAP_MALLOC_CFLAGS="${LDFLAGS} ${WRAP_MALLOC_CFLAGS} -Wl,--wrap -Wl,malloc -Wl,--wrap -Wl,calloc -Wl,--wrap -Wl,valloc -Wl,--wrap -Wl,free -Wl,--wrap -Wl,realloc -Wl,--wrap -Wl,memalign -Wl,--wrap -Wl,__builtin_new -Wl,--wrap -Wl,__builtin_vec_new -Wl,--wrap -Wl,__builtin_delete -Wl,--wrap -Wl,__builtin_vec_delete -Wl,--wrap -Wl,PR_Free -Wl,--wrap -Wl,PR_Malloc -Wl,--wrap -Wl,PR_Calloc -Wl,--wrap -Wl,PR_Realloc -Wl,--wrap -Wl,strdup -Wl,--wrap -Wl,strndup -Wl,--wrap -Wl,posix_memalign"
|
||||
DSO_LDOPTS="$DSO_LDOPTS $WRAP_MALLOC_CFLAGS"
|
||||
if test -n "$GNU_CC"; then
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=malloc,--wrap=calloc,--wrap=valloc,--wrap=free,--wrap=realloc,--wrap=memalign"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=__builtin_new,--wrap=__builtin_vec_new,--wrap=__builtin_delete,--wrap=__builtin_vec_delete"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=PR_Free,--wrap=PR_Malloc,--wrap=PR_Calloc,--wrap=PR_Realloc"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=strdup,--wrap=strndup"
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=posix_memalign,--wrap=malloc_usable_size"
|
||||
else
|
||||
AC_MSG_ERROR([--enable-wrap-malloc is not supported for non-GNU toolchains])
|
||||
AC_MSG_ERROR([--enable-wrap-malloc is not supported for non-GNU toolchains])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -3191,7 +3192,7 @@ dnl = Location of malloc wrapper lib
|
|||
dnl ========================================================
|
||||
AC_ARG_WITH(wrap-malloc,
|
||||
[ --with-wrap-malloc=SHAREDLIB Location of malloc wrapper library],
|
||||
WRAP_MALLOC_LIB=$withval)
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} $withval")
|
||||
|
||||
dnl ========================================================
|
||||
dnl Substitution of found variables.
|
||||
|
@ -3246,8 +3247,7 @@ AC_SUBST(OBJ_SUFFIX)
|
|||
AC_SUBST(LIB_SUFFIX)
|
||||
AC_SUBST(DLL_SUFFIX)
|
||||
AC_SUBST(ASM_SUFFIX)
|
||||
AC_SUBST(WRAP_MALLOC_CFLAGS)
|
||||
AC_SUBST(WRAP_MALLOC_LIB)
|
||||
AC_SUBST(WRAP_LDFLAGS)
|
||||
AC_SUBST(MKSHLIB)
|
||||
AC_SUBST(DSO_CFLAGS)
|
||||
AC_SUBST(DSO_LDOPTS)
|
||||
|
|
|
@ -162,10 +162,6 @@ EXTRA_LIBS = -lsocket -lnsl
|
|||
export LD_RUN_PATH = $(PWD)/$(dist_libdir)
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),Android)
|
||||
LDOPTS = $(OS_LDFLAGS) $(WRAP_MALLOC_LIB)
|
||||
endif
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# The rules
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include "prthread.h"
|
||||
|
||||
#include <libkern/OSAtomic.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -57,6 +58,8 @@
|
|||
#define _PR_SI_ARCHITECTURE "ppc"
|
||||
#elif defined(__arm__)
|
||||
#define _PR_SI_ARCHITECTURE "arm"
|
||||
#else
|
||||
#error "Unknown CPU architecture"
|
||||
#endif
|
||||
#define PR_DLL_SUFFIX ".dylib"
|
||||
|
||||
|
@ -91,7 +94,7 @@
|
|||
* if you pass an IPv4-mapped IPv6 address to it.
|
||||
*/
|
||||
#define _PR_GHBA_DISALLOW_V4MAPPED
|
||||
#ifdef XP_MACOSX
|
||||
#ifdef __APPLE__
|
||||
#if !defined(MAC_OS_X_VERSION_10_3) || \
|
||||
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3
|
||||
/*
|
||||
|
@ -105,7 +108,7 @@
|
|||
/* Mac OS X 10.2 has inet_ntop and inet_pton. */
|
||||
#define _PR_HAVE_INET_NTOP
|
||||
#endif /* DT >= 10.2 */
|
||||
#endif /* XP_MACOSX */
|
||||
#endif /* __APPLE__ */
|
||||
#define _PR_IPV6_V6ONLY_PROBE
|
||||
/* The IPV6_V6ONLY socket option is not defined on Mac OS X 10.1. */
|
||||
#ifndef IPV6_V6ONLY
|
||||
|
@ -151,6 +154,22 @@ extern PRInt32 _PR_Darwin_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val);
|
|||
#define _MD_ATOMIC_ADD(ptr, val) _PR_Darwin_x86_64_AtomicAdd(ptr, val)
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
#ifdef __arm__
|
||||
#define _PR_HAVE_ATOMIC_OPS
|
||||
#define _MD_INIT_ATOMIC()
|
||||
#define _MD_ATOMIC_INCREMENT(val) OSAtomicIncrement32(val)
|
||||
#define _MD_ATOMIC_DECREMENT(val) OSAtomicDecrement32(val)
|
||||
static inline PRInt32 _MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
|
||||
{
|
||||
PRInt32 oldval;
|
||||
do {
|
||||
oldval = *val;
|
||||
} while (!OSAtomicCompareAndSwap32(oldval, newval, val));
|
||||
return oldval;
|
||||
}
|
||||
#define _MD_ATOMIC_ADD(ptr, val) OSAtomicAdd32(val, ptr)
|
||||
#endif /* __arm__ */
|
||||
|
||||
#define USE_SETJMP
|
||||
|
||||
#if !defined(_PR_PTHREADS)
|
||||
|
|
|
@ -160,6 +160,7 @@ static FILE *logFile = NULL;
|
|||
static PRFileDesc *logFile = 0;
|
||||
#endif
|
||||
static PRBool outputTimeStamp = PR_FALSE;
|
||||
static PRBool appendToLog = PR_FALSE;
|
||||
|
||||
#define LINE_BUF_SIZE 512
|
||||
#define DEFAULT_BUF_SIZE 16384
|
||||
|
@ -247,6 +248,8 @@ void _PR_InitLog(void)
|
|||
}
|
||||
} else if (strcasecmp(module, "timestamp") == 0) {
|
||||
outputTimeStamp = PR_TRUE;
|
||||
} else if (strcasecmp(module, "append") == 0) {
|
||||
appendToLog = PR_TRUE;
|
||||
} else {
|
||||
PRLogModuleInfo *lm = logModules;
|
||||
PRBool skip_modcheck =
|
||||
|
@ -405,7 +408,8 @@ PR_IMPLEMENT(PRBool) PR_SetLogFile(const char *file)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
newLogFile = fopen(file, "w");
|
||||
const char *mode = appendToLog ? "a" : "w";
|
||||
newLogFile = fopen(file, mode);
|
||||
if (!newLogFile)
|
||||
return PR_FALSE;
|
||||
|
||||
|
@ -427,8 +431,14 @@ PR_IMPLEMENT(PRBool) PR_SetLogFile(const char *file)
|
|||
return PR_TRUE;
|
||||
#else
|
||||
PRFileDesc *newLogFile;
|
||||
PRIntn flags = PR_WRONLY|PR_CREATE_FILE;
|
||||
if (appendToLog) {
|
||||
flags |= PR_APPEND;
|
||||
} else {
|
||||
flags |= PR_TRUNCATE;
|
||||
}
|
||||
|
||||
newLogFile = PR_Open(file, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0666);
|
||||
newLogFile = PR_Open(file, flags, 0666);
|
||||
if (newLogFile) {
|
||||
if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
|
||||
PR_Close(logFile);
|
||||
|
|
|
@ -190,6 +190,7 @@ ForkAndExec(
|
|||
#ifdef HAVE_CRT_EXTERNS_H
|
||||
childEnvp = *(_NSGetEnviron());
|
||||
#else
|
||||
/* _NSGetEnviron() is not available on iOS. */
|
||||
PR_DELETE(process);
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
|
||||
return NULL;
|
||||
|
|
|
@ -451,7 +451,6 @@ endif
|
|||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),Android)
|
||||
LDOPTS = $(OS_LDFLAGS) $(WRAP_MALLOC_LIB)
|
||||
LIBPTHREAD =
|
||||
XCFLAGS = $(OS_CFLAGS)
|
||||
endif
|
||||
|
|
|
@ -78,7 +78,6 @@ ifdef MOZ_MEMORY
|
|||
SHARED_LIBRARY_LIBS = $(call EXPAND_LIBNAME_PATH,jemalloc,$(DEPTH)/memory/jemalloc)
|
||||
endif
|
||||
|
||||
WRAP_MALLOC_LIB =
|
||||
WRAP_MALLOC_CFLAGS =
|
||||
WRAP_LDFLAGS =
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -266,7 +266,6 @@ DEFAULT_GMAKE_FLAGS += \
|
|||
OS_PTHREAD= \
|
||||
STANDARDS_CFLAGS="-std=gnu89" \
|
||||
ARCHFLAG="$(CFLAGS) -DCHECK_FORK_GETPID -DRTLD_NOLOAD=0 -DANDROID_VERSION=$(ANDROID_VERSION) -include $(ABS_topsrcdir)/security/manager/android_stub.h" \
|
||||
DSO_LDOPTS="-shared $(LDFLAGS) $(WRAP_MALLOC_CFLAGS) $(WRAP_MALLOC_LIB) " \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -274,9 +273,11 @@ ifndef UNIVERSAL_BINARY
|
|||
SKIP_CHK=1
|
||||
endif
|
||||
endif
|
||||
ifdef WRAP_MALLOC_CFLAGS
|
||||
|
||||
ifdef WRAP_LDFLAGS
|
||||
DEFAULT_GMAKE_FLAGS += \
|
||||
LDFLAGS="$(LDFLAGS) $(WRAP_MALLOC_CFLAGS) $(WRAP_MALLOC_LIB) " \
|
||||
LDFLAGS="$(LDFLAGS) $(WRAP_LDFLAGS)" \
|
||||
DSO_LDOPTS="-shared $(LDFLAGS) $(WRAP_LDFLAGS)" \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@ error.login.reason.no_password2 = Missing password
|
|||
error.login.reason.no_recoverykey= No saved Recovery Key to use
|
||||
error.login.reason.server = Server incorrectly configured
|
||||
|
||||
error.sync.failed_partial = One or more data types could not be synced
|
||||
error.sync.failed_partial = One or more data types could not be synced
|
||||
error.sync.reason.server_maintenance = Firefox Sync server maintenance is underway, syncing will resume automatically.
|
||||
|
||||
invalid-captcha = Incorrect words, try again
|
||||
weak-password = Use a stronger password
|
||||
|
|
|
@ -20,6 +20,7 @@ error.logout.title = Error While Signing Out
|
|||
error.logout.description = Sync encountered an error while connecting. It's probably ok, and you don't have to do anything about it.
|
||||
error.sync.title = Error While Syncing
|
||||
error.sync.description = Sync encountered an error while syncing: %1$S. Sync will automatically retry this action.
|
||||
error.sync.prolonged_failure = Sync has not been able to complete during the last %1$S days. Please check your network settings.
|
||||
error.sync.no_node_found = The Sync server is a little busy right now, but you don't need to do anything about it. We'll start syncing your data as soon as we can!
|
||||
error.sync.no_node_found.title = Sync Delay
|
||||
error.sync.serverStatusButton.label = Server Status
|
||||
|
|
|
@ -49,13 +49,43 @@ const CB_FAIL = {};
|
|||
|
||||
const REASON_ERROR = Ci.mozIStorageStatementCallback.REASON_ERROR;
|
||||
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/*
|
||||
* Helpers for various async operations.
|
||||
*/
|
||||
let Async = {
|
||||
|
||||
/**
|
||||
* Execute an arbitrary number of asynchronous functions one after the
|
||||
* other, passing the callback arguments on to the next one. All functions
|
||||
* must take a callback function as their last argument. The 'this' object
|
||||
* will be whatever chain()'s is.
|
||||
*
|
||||
* @usage this._chain = Async.chain;
|
||||
* this._chain(this.foo, this.bar, this.baz)(args, for, foo)
|
||||
*
|
||||
* This is equivalent to:
|
||||
*
|
||||
* let self = this;
|
||||
* self.foo(args, for, foo, function (bars, args) {
|
||||
* self.bar(bars, args, function (baz, params) {
|
||||
* self.baz(baz, params);
|
||||
* });
|
||||
* });
|
||||
*/
|
||||
chain: function chain() {
|
||||
let funcs = Array.slice(arguments);
|
||||
let thisObj = this;
|
||||
return function callback() {
|
||||
if (funcs.length) {
|
||||
let args = Array.slice(arguments).concat(callback);
|
||||
let f = funcs.shift();
|
||||
f.apply(thisObj, args);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Helpers for making asynchronous calls within a synchronous API possible.
|
||||
*
|
||||
|
@ -97,7 +127,7 @@ let Async = {
|
|||
let thread = Cc["@mozilla.org/thread-manager;1"].getService().currentThread;
|
||||
|
||||
// Keep waiting until our callback is triggered (unless the app is quitting).
|
||||
while (Utils.checkAppReady() && callback.state == CB_READY) {
|
||||
while (Async.checkAppReady() && callback.state == CB_READY) {
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
|
||||
|
@ -114,6 +144,21 @@ let Async = {
|
|||
return callback.value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the app is still ready (not quitting).
|
||||
*/
|
||||
checkAppReady: function checkAppReady() {
|
||||
// Watch for app-quit notification to stop any sync calls
|
||||
Services.obs.addObserver(function onQuitApplication() {
|
||||
Services.obs.removeObserver(onQuitApplication, "quit-application");
|
||||
Async.checkAppReady = function() {
|
||||
throw Components.Exception("App. Quitting", Cr.NS_ERROR_ABORT);
|
||||
};
|
||||
}, "quit-application", false);
|
||||
// In the common case, checkAppReady just returns true
|
||||
return (Async.checkAppReady = function() { return true; })();
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the two things you need to make an asynchronous call synchronous
|
||||
* by spinning the event loop.
|
||||
|
@ -129,157 +174,6 @@ let Async = {
|
|||
return callback;
|
||||
},
|
||||
|
||||
/**
|
||||
* Synchronously invoke a method that takes only a `callback` argument.
|
||||
*/
|
||||
callSpinningly: function callSpinningly(self, method) {
|
||||
let callback = this.makeSpinningCallback();
|
||||
method.call(self, callback);
|
||||
return callback.wait();
|
||||
},
|
||||
|
||||
/*
|
||||
* Produce a sequence of callbacks which -- when all have been executed
|
||||
* successfully *or* any have failed -- invoke the output callback.
|
||||
*
|
||||
* Returns a generator.
|
||||
*
|
||||
* Each input callback should have the signature (error, result), and should
|
||||
* return a truthy value if the computation should be considered to have
|
||||
* failed.
|
||||
*
|
||||
* The contents of ".data" on each input callback are copied to the
|
||||
* resultant callback items. This can save some effort on the caller's side.
|
||||
*
|
||||
* These callbacks are assumed to be single- or double-valued (a "result" and
|
||||
* a "context", say), which covers the common cases without the expense of
|
||||
* `arguments`.
|
||||
*/
|
||||
barrieredCallbacks: function (callbacks, output) {
|
||||
if (!output) {
|
||||
throw "No output callback provided to barrieredCallbacks.";
|
||||
}
|
||||
|
||||
let counter = callbacks.length;
|
||||
function makeCb(input) {
|
||||
let cb = function(error, result, context) {
|
||||
if (!output) {
|
||||
return;
|
||||
}
|
||||
|
||||
let err;
|
||||
try {
|
||||
err = input(error, result, context);
|
||||
} catch (ex) {
|
||||
output(ex);
|
||||
output = undefined;
|
||||
return;
|
||||
}
|
||||
if ((0 == --counter) || err) {
|
||||
output(err);
|
||||
output = undefined;
|
||||
}
|
||||
};
|
||||
cb.data = input.data;
|
||||
return cb;
|
||||
}
|
||||
return (makeCb(i) for each (i in callbacks));
|
||||
},
|
||||
|
||||
/*
|
||||
* Similar to barrieredCallbacks, but with the same callback each time.
|
||||
*/
|
||||
countedCallback: function (componentCb, count, output) {
|
||||
if (!output) {
|
||||
throw "No output callback provided to countedCallback.";
|
||||
}
|
||||
|
||||
if (!count || (count <= 0)) {
|
||||
throw "Invalid count provided to countedCallback.";
|
||||
}
|
||||
|
||||
let counter = count;
|
||||
return function (error, result, context) {
|
||||
if (!output) {
|
||||
return;
|
||||
}
|
||||
|
||||
let err;
|
||||
try {
|
||||
err = componentCb(error, result, context);
|
||||
} catch (ex) {
|
||||
output(ex);
|
||||
// We're done; make sure output callback is only called once.
|
||||
output = undefined;
|
||||
return;
|
||||
}
|
||||
if ((0 == --counter) || err) {
|
||||
output(err); // If this throws, then... oh well.
|
||||
output = undefined;
|
||||
return;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/*
|
||||
* Invoke `f` with each item and a wrapped version of `componentCb`.
|
||||
* When each component callback is invoked, the next invocation of `f` is
|
||||
* begun, unless the return value is truthy. (See barrieredCallbacks.)
|
||||
*
|
||||
* Finally, invoke the output callback.
|
||||
*
|
||||
* If there are no items, the output callback is invoked immediately.
|
||||
*/
|
||||
serially: function serially(items, f, componentCb, output) {
|
||||
if (!output) {
|
||||
throw "No output callback provided to serially.";
|
||||
}
|
||||
|
||||
if (!items || !items.length) {
|
||||
output();
|
||||
return;
|
||||
}
|
||||
|
||||
let count = items.length;
|
||||
let i = 0;
|
||||
function cb(error, result, context) {
|
||||
let err = error;
|
||||
if (!err) {
|
||||
try {
|
||||
err = componentCb(error, result, context);
|
||||
} catch (ex) {
|
||||
err = ex;
|
||||
}
|
||||
}
|
||||
if ((++i == count) || err) {
|
||||
output(err);
|
||||
return;
|
||||
}
|
||||
Utils.nextTick(function () { f(items[i], cb); });
|
||||
}
|
||||
f(items[i], cb);
|
||||
},
|
||||
|
||||
/*
|
||||
* Return a callback which executes `f` then `callback`, regardless of
|
||||
* whether it was invoked with an error. If an exception is thrown during the
|
||||
* evaluation of `f`, it takes precedence over an error provided to the
|
||||
* callback.
|
||||
*
|
||||
* When used to wrap a callback, this offers similar behavior to try..finally
|
||||
* in plain JavaScript.
|
||||
*/
|
||||
finallyCallback: function (callback, f) {
|
||||
return function(err) {
|
||||
try {
|
||||
f();
|
||||
callback(err);
|
||||
} catch (ex) {
|
||||
callback(ex);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
// Prototype for mozIStorageCallback, used in querySpinningly.
|
||||
// This allows us to define the handle* functions just once rather
|
||||
// than on every querySpinningly invocation.
|
||||
|
|
|
@ -162,6 +162,8 @@ CREDENTIALS_CHANGED: "error.sync.reason.credentials_changed",
|
|||
ABORT_SYNC_COMMAND: "aborting sync, process commands said so",
|
||||
NO_SYNC_NODE_FOUND: "error.sync.reason.no_node_found",
|
||||
OVER_QUOTA: "error.sync.reason.over_quota",
|
||||
PROLONGED_SYNC_FAILURE: "error.sync.prolonged_failure",
|
||||
SERVER_MAINTENANCE: "error.sync.reason.server_maintenance",
|
||||
|
||||
RESPONSE_OVER_QUOTA: "14",
|
||||
|
||||
|
|
|
@ -285,7 +285,7 @@ function EngineManagerSvc() {
|
|||
EngineManagerSvc.prototype = {
|
||||
get: function EngMgr_get(name) {
|
||||
// Return an array of engines if we have an array of names
|
||||
if (Utils.isArray(name)) {
|
||||
if (Array.isArray(name)) {
|
||||
let engines = [];
|
||||
name.forEach(function(name) {
|
||||
let engine = this.get(name);
|
||||
|
@ -319,7 +319,7 @@ EngineManagerSvc.prototype = {
|
|||
* @return The engine object if anything failed
|
||||
*/
|
||||
register: function EngMgr_register(engineObject) {
|
||||
if (Utils.isArray(engineObject))
|
||||
if (Array.isArray(engineObject))
|
||||
return engineObject.map(this.register, this);
|
||||
|
||||
try {
|
||||
|
|
|
@ -464,8 +464,10 @@ function BookmarksStore(name) {
|
|||
|
||||
// Explicitly nullify our references to our cached services so we don't leak
|
||||
Svc.Obs.add("places-shutdown", function() {
|
||||
for each ([query, stmt] in Iterator(this._stmts))
|
||||
for each ([query, stmt] in Iterator(this._stmts)) {
|
||||
stmt.finalize();
|
||||
}
|
||||
this._stmts = {};
|
||||
}, this);
|
||||
}
|
||||
BookmarksStore.prototype = {
|
||||
|
@ -689,7 +691,7 @@ BookmarksStore.prototype = {
|
|||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
}
|
||||
|
||||
if (Utils.isArray(record.tags)) {
|
||||
if (Array.isArray(record.tags)) {
|
||||
this._tagURI(uri, record.tags);
|
||||
}
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(newId, record.keyword);
|
||||
|
@ -837,7 +839,7 @@ BookmarksStore.prototype = {
|
|||
PlacesUtils.bookmarks.changeBookmarkURI(itemId, Utils.makeURI(val));
|
||||
break;
|
||||
case "tags":
|
||||
if (Utils.isArray(val)) {
|
||||
if (Array.isArray(val)) {
|
||||
this._tagURI(PlacesUtils.bookmarks.getBookmarkURI(itemId), val);
|
||||
}
|
||||
break;
|
||||
|
@ -1067,8 +1069,9 @@ BookmarksStore.prototype = {
|
|||
|
||||
_stmts: {},
|
||||
_getStmt: function(query) {
|
||||
if (query in this._stmts)
|
||||
if (query in this._stmts) {
|
||||
return this._stmts[query];
|
||||
}
|
||||
|
||||
this._log.trace("Creating SQL statement: " + query);
|
||||
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
|
|
|
@ -88,9 +88,10 @@ function HistoryStore(name) {
|
|||
|
||||
// Explicitly nullify our references to our cached services so we don't leak
|
||||
Svc.Obs.add("places-shutdown", function() {
|
||||
for each ([query, stmt] in Iterator(this._stmts))
|
||||
for each ([query, stmt] in Iterator(this._stmts)) {
|
||||
stmt.finalize();
|
||||
this._stmts = [];
|
||||
}
|
||||
this._stmts = {};
|
||||
}, this);
|
||||
}
|
||||
HistoryStore.prototype = {
|
||||
|
@ -107,8 +108,9 @@ HistoryStore.prototype = {
|
|||
|
||||
_stmts: {},
|
||||
_getStmt: function(query) {
|
||||
if (query in this._stmts)
|
||||
if (query in this._stmts) {
|
||||
return this._stmts[query];
|
||||
}
|
||||
|
||||
this._log.trace("Creating SQL statement: " + query);
|
||||
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
|
@ -127,8 +129,9 @@ HistoryStore.prototype = {
|
|||
setGUID: function setGUID(uri, guid) {
|
||||
uri = uri.spec ? uri.spec : uri;
|
||||
|
||||
if (!guid)
|
||||
if (!guid) {
|
||||
guid = Utils.makeGUID();
|
||||
}
|
||||
|
||||
let stmt = this._setGUIDStm;
|
||||
stmt.params.guid = guid;
|
||||
|
@ -297,13 +300,13 @@ HistoryStore.prototype = {
|
|||
// To avoid creating new objects, we rewrite the query result so we
|
||||
// can simply check for containment below.
|
||||
let curVisits = this._getVisits(record.histUri);
|
||||
for (let i = 0; i < curVisits.length; i++) {
|
||||
let i, k;
|
||||
for (i = 0; i < curVisits.length; i++) {
|
||||
curVisits[i] = curVisits[i].date + "," + curVisits[i].type;
|
||||
}
|
||||
|
||||
// Walk through the visits, make sure we have sound data, and eliminate
|
||||
// dupes. The latter is done by rewriting the array in-place.
|
||||
let k;
|
||||
for (i = 0, k = 0; i < record.visits.length; i++) {
|
||||
let visit = record.visits[k] = record.visits[i];
|
||||
|
||||
|
@ -312,13 +315,15 @@ HistoryStore.prototype = {
|
|||
+ visit.date);
|
||||
throw "Visit has no date!";
|
||||
}
|
||||
|
||||
if (!visit.type || !(visit.type >= PlacesUtils.history.TRANSITION_LINK &&
|
||||
visit.type <= PlacesUtils.history.TRANSITION_FRAMED_LINK)) {
|
||||
this._log.warn("Encountered record with invalid visit type: "
|
||||
+ visit.type);
|
||||
throw "Invalid visit type!";
|
||||
}
|
||||
// Dates need to be integers
|
||||
|
||||
// Dates need to be integers.
|
||||
visit.date = Math.round(visit.date);
|
||||
|
||||
if (curVisits.indexOf(visit.date + "," + visit.type) != -1) {
|
||||
|
@ -358,14 +363,13 @@ HistoryStore.prototype = {
|
|||
},
|
||||
|
||||
itemExists: function HistStore_itemExists(id) {
|
||||
if (this._findURLByGUID(id))
|
||||
return true;
|
||||
return false;
|
||||
return !!this._findURLByGUID(id);
|
||||
},
|
||||
|
||||
urlExists: function HistStore_urlExists(url) {
|
||||
if (typeof(url) == "string")
|
||||
if (typeof(url) == "string") {
|
||||
url = Utils.makeURI(url);
|
||||
}
|
||||
// Don't call isVisited on a null URL to work around crasher bug 492442.
|
||||
return url ? PlacesUtils.history.isVisited(url) : false;
|
||||
},
|
||||
|
@ -378,9 +382,9 @@ HistoryStore.prototype = {
|
|||
record.title = foo.title;
|
||||
record.sortindex = foo.frecency;
|
||||
record.visits = this._getVisits(record.histUri);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
record.deleted = true;
|
||||
}
|
||||
|
||||
return record;
|
||||
},
|
||||
|
@ -437,8 +441,9 @@ HistoryTracker.prototype = {
|
|||
},
|
||||
|
||||
onVisit: function HT_onVisit(uri, vid, time, session, referrer, trans, guid) {
|
||||
if (this.ignoreAll)
|
||||
if (this.ignoreAll) {
|
||||
return;
|
||||
}
|
||||
this._log.trace("onVisit: " + uri.spec);
|
||||
if (this.addChangedID(guid)) {
|
||||
this.score += SCORE_INCREMENT_SMALL;
|
||||
|
@ -446,8 +451,9 @@ HistoryTracker.prototype = {
|
|||
},
|
||||
|
||||
onBeforeDeleteURI: function onBeforeDeleteURI(uri, guid, reason) {
|
||||
if (this.ignoreAll || reason == Ci.nsINavHistoryObserver.REASON_EXPIRED)
|
||||
if (this.ignoreAll || reason == Ci.nsINavHistoryObserver.REASON_EXPIRED) {
|
||||
return;
|
||||
}
|
||||
this._log.trace("onBeforeDeleteURI: " + uri.spec);
|
||||
if (this.addChangedID(guid)) {
|
||||
this._upScoreXLarge();
|
||||
|
|
|
@ -77,7 +77,7 @@ Preferences.prototype = {
|
|||
* @returns the value of the pref, if any; otherwise the default value
|
||||
*/
|
||||
get: function(prefName, defaultValue) {
|
||||
if (isArray(prefName))
|
||||
if (Array.isArray(prefName))
|
||||
return prefName.map(function(v) this.get(v, defaultValue), this);
|
||||
|
||||
if (this._site)
|
||||
|
@ -211,7 +211,7 @@ Preferences.prototype = {
|
|||
* or not the prefs have values
|
||||
*/
|
||||
has: function(prefName) {
|
||||
if (isArray(prefName))
|
||||
if (Array.isArray(prefName))
|
||||
return prefName.map(this.has, this);
|
||||
|
||||
if (this._site)
|
||||
|
@ -243,7 +243,7 @@ Preferences.prototype = {
|
|||
* whether or not the prefs have user-set values
|
||||
*/
|
||||
isSet: function(prefName) {
|
||||
if (isArray(prefName))
|
||||
if (Array.isArray(prefName))
|
||||
return prefName.map(this.isSet, this);
|
||||
|
||||
return (this.has(prefName) && this._prefSvc.prefHasUserValue(prefName));
|
||||
|
@ -257,7 +257,7 @@ Preferences.prototype = {
|
|||
modified: function(prefName) { return this.isSet(prefName) },
|
||||
|
||||
reset: function(prefName) {
|
||||
if (isArray(prefName)) {
|
||||
if (Array.isArray(prefName)) {
|
||||
prefName.map(function(v) this.reset(v), this);
|
||||
return;
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ Preferences.prototype = {
|
|||
* the pref to lock, or an array of prefs to lock
|
||||
*/
|
||||
lock: function(prefName) {
|
||||
if (isArray(prefName))
|
||||
if (Array.isArray(prefName))
|
||||
prefName.map(this.lock, this);
|
||||
|
||||
this._prefSvc.lockPref(prefName);
|
||||
|
@ -309,7 +309,7 @@ Preferences.prototype = {
|
|||
* the pref to lock, or an array of prefs to lock
|
||||
*/
|
||||
unlock: function(prefName) {
|
||||
if (isArray(prefName))
|
||||
if (Array.isArray(prefName))
|
||||
prefName.map(this.unlock, this);
|
||||
|
||||
this._prefSvc.unlockPref(prefName);
|
||||
|
@ -327,7 +327,7 @@ Preferences.prototype = {
|
|||
* whether or not the prefs have user-set values
|
||||
*/
|
||||
locked: function(prefName) {
|
||||
if (isArray(prefName))
|
||||
if (Array.isArray(prefName))
|
||||
return prefName.map(this.locked, this);
|
||||
|
||||
return this._prefSvc.prefIsLocked(prefName);
|
||||
|
@ -515,14 +515,6 @@ PrefObserver.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
function isArray(val) {
|
||||
// We can't check for |val.constructor == Array| here, since the value
|
||||
// might be from a different context whose Array constructor is not the same
|
||||
// as ours, so instead we match based on the name of the constructor.
|
||||
return (typeof val != "undefined" && val != null && typeof val == "object" &&
|
||||
val.constructor.name == "Array");
|
||||
}
|
||||
|
||||
function isObject(val) {
|
||||
// We can't check for |val.constructor == Object| here, since the value
|
||||
// might be from a different context whose Object constructor is not the same
|
||||
|
|
|
@ -142,7 +142,7 @@ function JPAKEClient(observer) {
|
|||
}
|
||||
JPAKEClient.prototype = {
|
||||
|
||||
_chain: Utils.asyncChain,
|
||||
_chain: Async.chain,
|
||||
|
||||
/*
|
||||
* Public API
|
||||
|
|
|
@ -481,7 +481,7 @@ BlockingStreamAppender.prototype = {
|
|||
}
|
||||
this._converterStream.init(
|
||||
this._outputStream, "UTF-8", STREAM_SEGMENT_SIZE,
|
||||
Ci.nsIConverterOutputStream.DEFAULT_REPLACEMENT_CHARACTER);
|
||||
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
|
||||
}
|
||||
return this._converterStream;
|
||||
},
|
||||
|
|
|
@ -52,7 +52,7 @@ let lazies = {
|
|||
"identity.js": ["Identity", "ID"],
|
||||
"jpakeclient.js": ["JPAKEClient"],
|
||||
"notifications.js": ["Notifications", "Notification", "NotificationButton"],
|
||||
"policies.js": ["SyncScheduler"],
|
||||
"policies.js": ["SyncScheduler", "ErrorHandler"],
|
||||
"resource.js": ["Resource", "AsyncResource", "Auth",
|
||||
"BasicAuthenticator", "NoOpAuthenticator"],
|
||||
"service.js": ["Service"],
|
||||
|
|
|
@ -37,9 +37,9 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
const EXPORTED_SYMBOLS = ["SyncScheduler"];
|
||||
const EXPORTED_SYMBOLS = ["SyncScheduler", "ErrorHandler"];
|
||||
|
||||
const Cu = Components.utils;
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
|
@ -88,6 +88,7 @@ let SyncScheduler = {
|
|||
Svc.Obs.add("weave:service:sync:start", this);
|
||||
Svc.Obs.add("weave:service:sync:finish", this);
|
||||
Svc.Obs.add("weave:engine:sync:finish", this);
|
||||
Svc.Obs.add("weave:engine:sync:error", this);
|
||||
Svc.Obs.add("weave:service:login:error", this);
|
||||
Svc.Obs.add("weave:service:logout:finish", this);
|
||||
Svc.Obs.add("weave:service:sync:error", this);
|
||||
|
@ -96,7 +97,7 @@ let SyncScheduler = {
|
|||
Svc.Obs.add("weave:engine:sync:applied", this);
|
||||
Svc.Obs.add("weave:service:setup-complete", this);
|
||||
Svc.Obs.add("weave:service:start-over", this);
|
||||
|
||||
|
||||
if (Status.checkSetup() == STATUS_OK) {
|
||||
Svc.Idle.addIdleObserver(this, Svc.Prefs.get("scheduler.idleTime"));
|
||||
}
|
||||
|
@ -129,8 +130,14 @@ let SyncScheduler = {
|
|||
this.adjustSyncInterval();
|
||||
|
||||
let sync_interval;
|
||||
this._syncErrors = 0;
|
||||
|
||||
if (Status.service == SYNC_FAILED_PARTIAL && this.requiresBackoff) {
|
||||
this.requiresBackoff = false;
|
||||
this.handleSyncError();
|
||||
return;
|
||||
}
|
||||
|
||||
this._syncErrors = 0;
|
||||
if (Status.sync == NO_SYNC_NODE_FOUND) {
|
||||
this._log.trace("Scheduling a sync at interval NO_SYNC_NODE_FOUND.");
|
||||
sync_interval = NO_SYNC_NODE_INTERVAL;
|
||||
|
@ -143,9 +150,16 @@ let SyncScheduler = {
|
|||
this.updateClientMode();
|
||||
}
|
||||
break;
|
||||
case "weave:engine:sync:error":
|
||||
// subject is the exception thrown by an engine's sync() method
|
||||
let exception = subject;
|
||||
if (exception.status >= 500 && exception.status <= 504) {
|
||||
this.requiresBackoff = true;
|
||||
}
|
||||
break;
|
||||
case "weave:service:login:error":
|
||||
this.clearSyncTriggers();
|
||||
|
||||
|
||||
// Try again later, just as if we threw an error... only without the
|
||||
// error count.
|
||||
if (Status.login == MASTER_PASSWORD_LOCKED) {
|
||||
|
@ -158,7 +172,7 @@ let SyncScheduler = {
|
|||
// Start or cancel the sync timer depending on if
|
||||
// logged in or logged out
|
||||
this.checkSyncStatus();
|
||||
break;
|
||||
break;
|
||||
case "weave:service:sync:error":
|
||||
// There may be multiple clients but if the sync fails, client mode
|
||||
// should still be updated so that the next sync has a correct interval.
|
||||
|
@ -182,7 +196,7 @@ let SyncScheduler = {
|
|||
case "weave:engine:sync:applied":
|
||||
let numItems = subject.applied;
|
||||
this._log.trace("Engine " + data + " applied " + numItems + " items.");
|
||||
if (numItems)
|
||||
if (numItems)
|
||||
this.hasIncomingItems = true;
|
||||
break;
|
||||
case "weave:service:setup-complete":
|
||||
|
@ -252,7 +266,7 @@ let SyncScheduler = {
|
|||
*/
|
||||
updateClientMode: function updateClientMode() {
|
||||
// Nothing to do if it's the same amount
|
||||
let {numClients} = Clients.stats;
|
||||
let numClients = Clients.stats.numClients;
|
||||
if (this.numClients == numClients)
|
||||
return;
|
||||
|
||||
|
@ -294,7 +308,7 @@ let SyncScheduler = {
|
|||
|
||||
/**
|
||||
* Call sync() if Master Password is not locked.
|
||||
*
|
||||
*
|
||||
* Otherwise, reschedule a sync for later.
|
||||
*/
|
||||
syncIfMPUnlocked: function syncIfMPUnlocked() {
|
||||
|
@ -413,3 +427,247 @@ let SyncScheduler = {
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
const LOG_PREFIX_SUCCESS = "success-";
|
||||
const LOG_PREFIX_ERROR = "error-";
|
||||
|
||||
let ErrorHandler = {
|
||||
|
||||
/**
|
||||
* Flag that turns on error reporting for all errors, incl. network errors.
|
||||
*/
|
||||
dontIgnoreErrors: false,
|
||||
|
||||
init: function init() {
|
||||
Svc.Obs.add("weave:engine:sync:applied", this);
|
||||
Svc.Obs.add("weave:engine:sync:error", this);
|
||||
Svc.Obs.add("weave:service:login:error", this);
|
||||
Svc.Obs.add("weave:service:sync:error", this);
|
||||
Svc.Obs.add("weave:service:sync:finish", this);
|
||||
|
||||
this.initLogs();
|
||||
},
|
||||
|
||||
initLogs: function initLogs() {
|
||||
this._log = Log4Moz.repository.getLogger("Sync.ErrorHandler");
|
||||
this._log.level = Log4Moz.Level[Svc.Prefs.get("log.logger.service.main")];
|
||||
|
||||
let root = Log4Moz.repository.getLogger("Sync");
|
||||
root.level = Log4Moz.Level[Svc.Prefs.get("log.rootLogger")];
|
||||
|
||||
let formatter = new Log4Moz.BasicFormatter();
|
||||
let capp = new Log4Moz.ConsoleAppender(formatter);
|
||||
capp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.console")];
|
||||
root.addAppender(capp);
|
||||
|
||||
let dapp = new Log4Moz.DumpAppender(formatter);
|
||||
dapp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.dump")];
|
||||
root.addAppender(dapp);
|
||||
|
||||
let fapp = this._logAppender = new Log4Moz.StorageStreamAppender(formatter);
|
||||
fapp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.file.level")];
|
||||
root.addAppender(fapp);
|
||||
},
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
switch(topic) {
|
||||
case "weave:engine:sync:applied":
|
||||
if (subject.newFailed) {
|
||||
// An engine isn't able to apply one or more incoming records.
|
||||
// We don't fail hard on this, but it usually indicates a bug,
|
||||
// so for now treat it as sync error (c.f. Service._syncEngine())
|
||||
Status.engines = [data, ENGINE_APPLY_FAIL];
|
||||
this._log.debug(data + " failed to apply some records.");
|
||||
}
|
||||
break;
|
||||
case "weave:engine:sync:error":
|
||||
let exception = subject; // exception thrown by engine's sync() method
|
||||
let engine_name = data; // engine name that threw the exception
|
||||
|
||||
this.checkServerError(exception);
|
||||
|
||||
Status.engines = [engine_name, exception.failureCode || ENGINE_UNKNOWN_FAIL];
|
||||
this._log.debug(engine_name + " failed: " + Utils.exceptionStr(exception));
|
||||
break;
|
||||
case "weave:service:login:error":
|
||||
if (this.shouldReportError()) {
|
||||
this.resetFileLog(Svc.Prefs.get("log.appender.file.logOnError"),
|
||||
LOG_PREFIX_ERROR);
|
||||
Svc.Obs.notify("weave:ui:login:error");
|
||||
} else {
|
||||
Svc.Obs.notify("weave:ui:clear-error");
|
||||
}
|
||||
|
||||
this.dontIgnoreErrors = false;
|
||||
break;
|
||||
case "weave:service:sync:error":
|
||||
if (Status.sync == CREDENTIALS_CHANGED) {
|
||||
Weave.Service.logout();
|
||||
}
|
||||
|
||||
if (this.shouldReportError()) {
|
||||
this.resetFileLog(Svc.Prefs.get("log.appender.file.logOnError"),
|
||||
LOG_PREFIX_ERROR);
|
||||
Svc.Obs.notify("weave:ui:sync:error");
|
||||
} else {
|
||||
Svc.Obs.notify("weave:ui:sync:finish");
|
||||
}
|
||||
|
||||
this.dontIgnoreErrors = false;
|
||||
break;
|
||||
case "weave:service:sync:finish":
|
||||
if (Status.service == SYNC_FAILED_PARTIAL) {
|
||||
this._log.debug("Some engines did not sync correctly.");
|
||||
this.resetFileLog(Svc.Prefs.get("log.appender.file.logOnError"),
|
||||
LOG_PREFIX_ERROR);
|
||||
|
||||
if (this.shouldReportError()) {
|
||||
this.dontIgnoreErrors = false;
|
||||
Svc.Obs.notify("weave:ui:sync:error");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
this.resetFileLog(Svc.Prefs.get("log.appender.file.logOnSuccess"),
|
||||
LOG_PREFIX_SUCCESS);
|
||||
}
|
||||
this.dontIgnoreErrors = false;
|
||||
Svc.Obs.notify("weave:ui:sync:finish");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Trigger a sync and don't muffle any errors, particularly network errors.
|
||||
*/
|
||||
syncAndReportErrors: function syncAndReportErrors() {
|
||||
this._log.debug("Beginning user-triggered sync.");
|
||||
|
||||
this.dontIgnoreErrors = true;
|
||||
Utils.nextTick(Weave.Service.sync, Weave.Service);
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate a log file for the sync that just completed
|
||||
* and refresh the input & output streams.
|
||||
*
|
||||
* @param flushToFile
|
||||
* the log file to be flushed/reset
|
||||
*
|
||||
* @param filenamePrefix
|
||||
* a value of either LOG_PREFIX_SUCCESS or LOG_PREFIX_ERROR
|
||||
* to be used as the log filename prefix
|
||||
*/
|
||||
resetFileLog: function resetFileLog(flushToFile, filenamePrefix) {
|
||||
let inStream = this._logAppender.getInputStream();
|
||||
this._logAppender.reset();
|
||||
if (flushToFile && inStream) {
|
||||
try {
|
||||
let filename = filenamePrefix + Date.now() + ".txt";
|
||||
let file = FileUtils.getFile("ProfD", ["weave", "logs", filename]);
|
||||
let outStream = FileUtils.openFileOutputStream(file);
|
||||
NetUtil.asyncCopy(inStream, outStream, function () {
|
||||
Svc.Obs.notify("weave:service:reset-file-log");
|
||||
});
|
||||
} catch (ex) {
|
||||
Svc.Obs.notify("weave:service:reset-file-log");
|
||||
}
|
||||
} else {
|
||||
Svc.Obs.notify("weave:service:reset-file-log");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Translates server error codes to meaningful strings.
|
||||
*
|
||||
* @param code
|
||||
* server error code as an integer
|
||||
*/
|
||||
errorStr: function errorStr(code) {
|
||||
switch (code.toString()) {
|
||||
case "1":
|
||||
return "illegal-method";
|
||||
case "2":
|
||||
return "invalid-captcha";
|
||||
case "3":
|
||||
return "invalid-username";
|
||||
case "4":
|
||||
return "cannot-overwrite-resource";
|
||||
case "5":
|
||||
return "userid-mismatch";
|
||||
case "6":
|
||||
return "json-parse-failure";
|
||||
case "7":
|
||||
return "invalid-password";
|
||||
case "8":
|
||||
return "invalid-record";
|
||||
case "9":
|
||||
return "weak-password";
|
||||
default:
|
||||
return "generic-server-error";
|
||||
}
|
||||
},
|
||||
|
||||
shouldReportError: function shouldReportError() {
|
||||
if (Status.login == MASTER_PASSWORD_LOCKED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.dontIgnoreErrors) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let lastSync = Svc.Prefs.get("lastSync");
|
||||
if (lastSync && ((Date.now() - Date.parse(lastSync)) >
|
||||
Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 1000)) {
|
||||
Status.sync = PROLONGED_SYNC_FAILURE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return (Status.sync != SERVER_MAINTENANCE &&
|
||||
[Status.login, Status.sync].indexOf(LOGIN_FAILED_NETWORK_ERROR) == -1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle HTTP response results or exceptions and set the appropriate
|
||||
* Status.* bits.
|
||||
*/
|
||||
checkServerError: function checkServerError(resp) {
|
||||
switch (resp.status) {
|
||||
case 400:
|
||||
if (resp == RESPONSE_OVER_QUOTA) {
|
||||
Status.sync = OVER_QUOTA;
|
||||
}
|
||||
break;
|
||||
|
||||
case 401:
|
||||
Weave.Service.logout();
|
||||
Status.login = LOGIN_FAILED_LOGIN_REJECTED;
|
||||
break;
|
||||
|
||||
case 500:
|
||||
case 502:
|
||||
case 503:
|
||||
case 504:
|
||||
Status.enforceBackoff = true;
|
||||
if (resp.status == 503 && resp.headers["retry-after"]) {
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
Svc.Obs.notify("weave:service:backoff:interval",
|
||||
parseInt(resp.headers["retry-after"], 10));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (resp.result) {
|
||||
case Cr.NS_ERROR_UNKNOWN_HOST:
|
||||
case Cr.NS_ERROR_CONNECTION_REFUSED:
|
||||
case Cr.NS_ERROR_NET_TIMEOUT:
|
||||
case Cr.NS_ERROR_NET_RESET:
|
||||
case Cr.NS_ERROR_NET_INTERRUPT:
|
||||
case Cr.NS_ERROR_PROXY_CONNECTION_REFUSED:
|
||||
// The constant says it's about login, but in fact it just
|
||||
// indicates general network error.
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
break;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -408,7 +408,7 @@ AsyncResource.prototype = {
|
|||
this._doRequest("POST", data, callback);
|
||||
},
|
||||
|
||||
delete: function delete(callback) {
|
||||
delete: function delete_(callback) {
|
||||
this._doRequest("DELETE", undefined, callback);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -58,9 +58,6 @@ const KEYS_WBO = "keys";
|
|||
|
||||
const LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S";
|
||||
|
||||
const LOG_PREFIX_SUCCESS = "success-";
|
||||
const LOG_PREFIX_ERROR = "error-";
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
|
@ -366,7 +363,12 @@ WeaveSvc.prototype = {
|
|||
*/
|
||||
onStartup: function onStartup() {
|
||||
this._migratePrefs();
|
||||
this._initLogs();
|
||||
ErrorHandler.init();
|
||||
|
||||
this._log = Log4Moz.repository.getLogger("Sync.Service");
|
||||
this._log.level =
|
||||
Log4Moz.Level[Svc.Prefs.get("log.logger.service.main")];
|
||||
|
||||
this._log.info("Loading Weave " + WEAVE_VERSION);
|
||||
|
||||
this.enabled = true;
|
||||
|
@ -384,11 +386,6 @@ WeaveSvc.prototype = {
|
|||
}
|
||||
|
||||
Svc.Obs.add("weave:service:setup-complete", this);
|
||||
Svc.Obs.add("weave:service:sync:finish", this);
|
||||
Svc.Obs.add("weave:service:login:error", this);
|
||||
Svc.Obs.add("weave:service:sync:error", this);
|
||||
Svc.Obs.add("weave:engine:sync:applied", this);
|
||||
Svc.Obs.add("weave:resource:status:401", this);
|
||||
Svc.Prefs.observe("engine.", this);
|
||||
|
||||
SyncScheduler.init();
|
||||
|
@ -460,47 +457,6 @@ WeaveSvc.prototype = {
|
|||
Svc.Prefs.set("migrated", true);
|
||||
},
|
||||
|
||||
_initLogs: function WeaveSvc__initLogs() {
|
||||
this._log = Log4Moz.repository.getLogger("Sync.Service");
|
||||
this._log.level =
|
||||
Log4Moz.Level[Svc.Prefs.get("log.logger.service.main")];
|
||||
|
||||
let root = Log4Moz.repository.getLogger("Sync");
|
||||
root.level = Log4Moz.Level[Svc.Prefs.get("log.rootLogger")];
|
||||
|
||||
let formatter = new Log4Moz.BasicFormatter();
|
||||
let capp = new Log4Moz.ConsoleAppender(formatter);
|
||||
capp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.console")];
|
||||
root.addAppender(capp);
|
||||
|
||||
let dapp = new Log4Moz.DumpAppender(formatter);
|
||||
dapp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.dump")];
|
||||
root.addAppender(dapp);
|
||||
|
||||
let fapp = this._logAppender = new Log4Moz.StorageStreamAppender(formatter);
|
||||
fapp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.file.level")];
|
||||
root.addAppender(fapp);
|
||||
},
|
||||
|
||||
_resetFileLog: function _resetFileLog(flushToFile, filenamePrefix) {
|
||||
let inStream = this._logAppender.getInputStream();
|
||||
this._logAppender.reset();
|
||||
if (flushToFile && inStream) {
|
||||
try {
|
||||
let filename = filenamePrefix + Date.now() + ".txt";
|
||||
let file = FileUtils.getFile("ProfD", ["weave", "logs", filename]);
|
||||
let outStream = FileUtils.openFileOutputStream(file);
|
||||
NetUtil.asyncCopy(inStream, outStream, function () {
|
||||
Svc.Obs.notify("weave:service:reset-file-log");
|
||||
});
|
||||
} catch (ex) {
|
||||
Svc.Obs.notify("weave:service:reset-file-log");
|
||||
}
|
||||
} else {
|
||||
Svc.Obs.notify("weave:service:reset-file-log");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Register the built-in engines for certain applications
|
||||
*/
|
||||
|
@ -529,49 +485,6 @@ WeaveSvc.prototype = {
|
|||
if (status != STATUS_DISABLED && status != CLIENT_NOT_CONFIGURED)
|
||||
Svc.Obs.notify("weave:engine:start-tracking");
|
||||
break;
|
||||
case "weave:service:login:error":
|
||||
if (Status.login == LOGIN_FAILED_NETWORK_ERROR &&
|
||||
!Services.io.offline) {
|
||||
this._ignorableErrorCount += 1;
|
||||
} else {
|
||||
this._resetFileLog(Svc.Prefs.get("log.appender.file.logOnError"),
|
||||
LOG_PREFIX_ERROR);
|
||||
}
|
||||
break;
|
||||
case "weave:service:sync:error":
|
||||
switch (Status.sync) {
|
||||
case LOGIN_FAILED_NETWORK_ERROR:
|
||||
if (!Services.io.offline) {
|
||||
this._ignorableErrorCount += 1;
|
||||
}
|
||||
break;
|
||||
case CREDENTIALS_CHANGED:
|
||||
this.logout();
|
||||
break;
|
||||
default:
|
||||
this._resetFileLog(Svc.Prefs.get("log.appender.file.logOnError"),
|
||||
LOG_PREFIX_ERROR);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "weave:service:sync:finish":
|
||||
this._resetFileLog(Svc.Prefs.get("log.appender.file.logOnSuccess"),
|
||||
LOG_PREFIX_SUCCESS);
|
||||
this._ignorableErrorCount = 0;
|
||||
break;
|
||||
case "weave:engine:sync:applied":
|
||||
if (subject.newFailed) {
|
||||
// An engine isn't able to apply one or more incoming records.
|
||||
// We don't fail hard on this, but it usually indicates a bug,
|
||||
// so for now treat it as sync error (c.f. Service._syncEngine())
|
||||
Status.engines = [data, ENGINE_APPLY_FAIL];
|
||||
this._syncError = true;
|
||||
this._log.debug(data + " failed to apply some records.");
|
||||
}
|
||||
break;
|
||||
case "weave:resource:status:401":
|
||||
this._handleResource401(subject);
|
||||
break;
|
||||
case "nsPref:changed":
|
||||
if (this._ignorePrefObserver)
|
||||
return;
|
||||
|
@ -603,7 +516,7 @@ WeaveSvc.prototype = {
|
|||
switch (node.status) {
|
||||
case 400:
|
||||
Status.login = LOGIN_FAILED_LOGIN_REJECTED;
|
||||
fail = "Find cluster denied: " + this._errorStr(node);
|
||||
fail = "Find cluster denied: " + ErrorHandler.errorStr(node);
|
||||
break;
|
||||
case 404:
|
||||
this._log.debug("Using serverURL as data cluster (multi-cluster support disabled)");
|
||||
|
@ -666,11 +579,11 @@ WeaveSvc.prototype = {
|
|||
try {
|
||||
info = new Resource(infoURL).get();
|
||||
} catch (ex) {
|
||||
this._checkServerError(ex);
|
||||
ErrorHandler.checkServerError(ex);
|
||||
throw ex;
|
||||
}
|
||||
if (!info.success) {
|
||||
this._checkServerError(info);
|
||||
ErrorHandler.checkServerError(info);
|
||||
throw "aborting sync, failed to get collections";
|
||||
}
|
||||
return info;
|
||||
|
@ -885,7 +798,7 @@ WeaveSvc.prototype = {
|
|||
|
||||
default:
|
||||
// Server didn't respond with something that we expected
|
||||
this._checkServerError(test);
|
||||
ErrorHandler.checkServerError(test);
|
||||
Status.login = LOGIN_FAILED_SERVER_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
@ -1099,31 +1012,6 @@ WeaveSvc.prototype = {
|
|||
Svc.Obs.notify("weave:service:logout:finish");
|
||||
},
|
||||
|
||||
_errorStr: function WeaveSvc__errorStr(code) {
|
||||
switch (code.toString()) {
|
||||
case "1":
|
||||
return "illegal-method";
|
||||
case "2":
|
||||
return "invalid-captcha";
|
||||
case "3":
|
||||
return "invalid-username";
|
||||
case "4":
|
||||
return "cannot-overwrite-resource";
|
||||
case "5":
|
||||
return "userid-mismatch";
|
||||
case "6":
|
||||
return "json-parse-failure";
|
||||
case "7":
|
||||
return "invalid-password";
|
||||
case "8":
|
||||
return "invalid-record";
|
||||
case "9":
|
||||
return "weak-password";
|
||||
default:
|
||||
return "generic-server-error";
|
||||
}
|
||||
},
|
||||
|
||||
checkAccount: function checkAccount(account) {
|
||||
let username = this._usernameFromAccount(account);
|
||||
let url = this.userAPI + username;
|
||||
|
@ -1144,7 +1032,7 @@ WeaveSvc.prototype = {
|
|||
catch(ex) {}
|
||||
|
||||
// Convert to the error string, or default to generic on exception.
|
||||
return this._errorStr(data);
|
||||
return ErrorHandler.errorStr(data);
|
||||
},
|
||||
|
||||
createAccount: function createAccount(email, password,
|
||||
|
@ -1176,7 +1064,7 @@ WeaveSvc.prototype = {
|
|||
|
||||
// Must have failed, so figure out the reason
|
||||
if (register.status == 400)
|
||||
error = this._errorStr(register);
|
||||
error = ErrorHandler.errorStr(register);
|
||||
}
|
||||
catch(ex) {
|
||||
this._log.warn("Failed to create account: " + ex);
|
||||
|
@ -1248,7 +1136,7 @@ WeaveSvc.prototype = {
|
|||
// abort the server wipe if the GET status was anything other than 404 or 200
|
||||
let status = Records.response.status;
|
||||
if (status != 200 && status != 404) {
|
||||
this._checkServerError(Records.response);
|
||||
ErrorHandler.checkServerError(Records.response);
|
||||
Status.sync = METARECORD_DOWNLOAD_FAIL;
|
||||
this._log.warn("Unknown error while downloading metadata record. " +
|
||||
"Aborting sync.");
|
||||
|
@ -1361,14 +1249,6 @@ WeaveSvc.prototype = {
|
|||
return reason;
|
||||
},
|
||||
|
||||
_ignorableErrorCount: 0,
|
||||
shouldIgnoreError: function shouldIgnoreError() {
|
||||
// Never show an error bar for a locked master password.
|
||||
return (Status.login == MASTER_PASSWORD_LOCKED) ||
|
||||
([Status.login, Status.sync].indexOf(LOGIN_FAILED_NETWORK_ERROR) != -1
|
||||
&& this._ignorableErrorCount < MAX_IGNORE_ERROR_COUNT);
|
||||
},
|
||||
|
||||
sync: function sync() {
|
||||
let dateStr = new Date().toLocaleFormat(LOG_DATE_FORMAT);
|
||||
this._log.debug("User-Agent: " + SyncStorageRequest.prototype.userAgent);
|
||||
|
@ -1510,19 +1390,18 @@ WeaveSvc.prototype = {
|
|||
delete meta.changed;
|
||||
}
|
||||
|
||||
if (this._syncError) {
|
||||
throw "Some engines did not sync correctly";
|
||||
} else {
|
||||
// If there were no sync engine failures
|
||||
if (Status.service != SYNC_FAILED_PARTIAL) {
|
||||
Svc.Prefs.set("lastSync", new Date().toString());
|
||||
Status.sync = SYNC_SUCCEEDED;
|
||||
let syncTime = ((Date.now() - syncStartTime) / 1000).toFixed(2);
|
||||
let dateStr = new Date().toLocaleFormat(LOG_DATE_FORMAT);
|
||||
this._log.info("Sync completed successfully at " + dateStr
|
||||
+ " after " + syncTime + " secs.");
|
||||
}
|
||||
} finally {
|
||||
this._syncError = false;
|
||||
Svc.Prefs.reset("firstSync");
|
||||
|
||||
let syncTime = ((Date.now() - syncStartTime) / 1000).toFixed(2);
|
||||
let dateStr = new Date().toLocaleFormat(LOG_DATE_FORMAT);
|
||||
this._log.info("Sync completed at " + dateStr
|
||||
+ " after " + syncTime + " secs.");
|
||||
}
|
||||
}))(),
|
||||
|
||||
|
@ -1604,19 +1483,12 @@ WeaveSvc.prototype = {
|
|||
// Log out and clear the cluster URL pref. That will make us perform
|
||||
// cluster detection and password check on next sync, which handles
|
||||
// both causes of 401s; in either case, we won't proceed with this
|
||||
// sync, so return false, but kick off a sync for next time.
|
||||
// sync so return false, but kick off a sync for next time.
|
||||
this.logout();
|
||||
Svc.Prefs.reset("clusterURL");
|
||||
Utils.nextTick(this.sync, this);
|
||||
return false;
|
||||
}
|
||||
|
||||
this._checkServerError(e);
|
||||
|
||||
Status.engines = [engine.name, e.failureCode || ENGINE_UNKNOWN_FAIL];
|
||||
|
||||
this._syncError = true;
|
||||
this._log.debug(engine.name + " failed: " + Utils.exceptionStr(e));
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
@ -1700,49 +1572,6 @@ WeaveSvc.prototype = {
|
|||
this.generateNewSymmetricKeys();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle HTTP response results or exceptions and set the appropriate
|
||||
* Status.* bits.
|
||||
*/
|
||||
_checkServerError: function WeaveSvc__checkServerError(resp) {
|
||||
switch (resp.status) {
|
||||
case 400:
|
||||
if (resp == RESPONSE_OVER_QUOTA) {
|
||||
Status.sync = OVER_QUOTA;
|
||||
}
|
||||
break;
|
||||
|
||||
case 401:
|
||||
this.logout();
|
||||
Status.login = LOGIN_FAILED_LOGIN_REJECTED;
|
||||
break;
|
||||
|
||||
case 500:
|
||||
case 502:
|
||||
case 503:
|
||||
case 504:
|
||||
Status.enforceBackoff = true;
|
||||
if (resp.status == 503 && resp.headers["retry-after"]) {
|
||||
Svc.Obs.notify("weave:service:backoff:interval",
|
||||
parseInt(resp.headers["retry-after"], 10));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (resp.result) {
|
||||
case Cr.NS_ERROR_UNKNOWN_HOST:
|
||||
case Cr.NS_ERROR_CONNECTION_REFUSED:
|
||||
case Cr.NS_ERROR_NET_TIMEOUT:
|
||||
case Cr.NS_ERROR_NET_RESET:
|
||||
case Cr.NS_ERROR_NET_INTERRUPT:
|
||||
case Cr.NS_ERROR_PROXY_CONNECTION_REFUSED:
|
||||
// The constant says it's about login, but in fact it just
|
||||
// indicates general network error.
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Wipe user data from the server.
|
||||
*
|
||||
|
|
|
@ -36,13 +36,14 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const EXPORTED_SYMBOLS = ["XPCOMUtils", "Services", "NetUtil", "PlacesUtils",
|
||||
"FileUtils", "Utils", "Svc", "Str"];
|
||||
"FileUtils", "Utils", "Async", "Svc", "Str"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://services-sync/async.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/ext/Observers.js");
|
||||
Cu.import("resource://services-sync/ext/Preferences.js");
|
||||
|
@ -60,36 +61,6 @@ Cu.import("resource://gre/modules/FileUtils.jsm");
|
|||
*/
|
||||
|
||||
let Utils = {
|
||||
/**
|
||||
* Execute an arbitrary number of asynchronous functions one after the
|
||||
* other, passing the callback arguments on to the next one. All functions
|
||||
* must take a callback function as their last argument. The 'this' object
|
||||
* will be whatever asyncChain's is.
|
||||
*
|
||||
* @usage this._chain = Utils.asyncChain;
|
||||
* this._chain(this.foo, this.bar, this.baz)(args, for, foo)
|
||||
*
|
||||
* This is equivalent to:
|
||||
*
|
||||
* let self = this;
|
||||
* self.foo(args, for, foo, function (bars, args) {
|
||||
* self.bar(bars, args, function (baz, params) {
|
||||
* self.baz(baz, params);
|
||||
* });
|
||||
* });
|
||||
*/
|
||||
asyncChain: function asyncChain() {
|
||||
let funcs = Array.slice(arguments);
|
||||
let thisObj = this;
|
||||
return function callback() {
|
||||
if (funcs.length) {
|
||||
let args = Array.slice(arguments).concat(callback);
|
||||
let f = funcs.shift();
|
||||
f.apply(thisObj, args);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Wrap a function to catch all exceptions and log them
|
||||
*
|
||||
|
@ -202,25 +173,6 @@ let Utils = {
|
|||
}
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* Partition the input array into an array of arrays. Return a generator.
|
||||
*/
|
||||
slices: function slices(arr, sliceSize) {
|
||||
if (!sliceSize || sliceSize <= 0)
|
||||
throw "Invalid slice size.";
|
||||
|
||||
if (sliceSize > arr.length) {
|
||||
yield arr;
|
||||
} else {
|
||||
let offset = 0;
|
||||
while (arr.length > offset) {
|
||||
yield arr.slice(offset, offset + sliceSize);
|
||||
offset += sliceSize;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
byteArrayToString: function byteArrayToString(bytes) {
|
||||
return [String.fromCharCode(byte) for each (byte in bytes)].join("");
|
||||
},
|
||||
|
@ -289,7 +241,7 @@ let Utils = {
|
|||
* Property name to defer (or an array of property names)
|
||||
*/
|
||||
deferGetSet: function Utils_deferGetSet(obj, defer, prop) {
|
||||
if (Utils.isArray(prop))
|
||||
if (Array.isArray(prop))
|
||||
return prop.map(function(prop) Utils.deferGetSet(obj, defer, prop));
|
||||
|
||||
let prot = obj.prototype;
|
||||
|
@ -309,16 +261,6 @@ let Utils = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine if some value is an array
|
||||
*
|
||||
* @param val
|
||||
* Value to check (can be null, undefined, etc.)
|
||||
* @return True if it's an array; false otherwise
|
||||
*/
|
||||
isArray: function Utils_isArray(val) val != null && typeof val == "object" &&
|
||||
val.constructor.name == "Array",
|
||||
|
||||
lazyStrings: function Weave_lazyStrings(name) {
|
||||
let bundle = "chrome://weave/locale/services/" + name + ".properties";
|
||||
return function() new StringBundle(bundle);
|
||||
|
@ -355,7 +297,7 @@ let Utils = {
|
|||
return thing;
|
||||
let ret;
|
||||
|
||||
if (Utils.isArray(thing)) {
|
||||
if (Array.isArray(thing)) {
|
||||
ret = [];
|
||||
for (let i = 0; i < thing.length; i++)
|
||||
ret.push(Utils.deepCopy(thing[i], noSort));
|
||||
|
@ -468,21 +410,6 @@ let Utils = {
|
|||
return hex;
|
||||
},
|
||||
|
||||
_sha256: function _sha256(message) {
|
||||
let hasher = Cc["@mozilla.org/security/hash;1"].
|
||||
createInstance(Ci.nsICryptoHash);
|
||||
hasher.init(hasher.SHA256);
|
||||
return Utils.digestUTF8(message, hasher);
|
||||
},
|
||||
|
||||
sha256: function sha256(message) {
|
||||
return Utils.bytesAsHex(Utils._sha256(message));
|
||||
},
|
||||
|
||||
sha256Base64: function (message) {
|
||||
return btoa(Utils._sha256(message));
|
||||
},
|
||||
|
||||
_sha1: function _sha1(message) {
|
||||
let hasher = Cc["@mozilla.org/security/hash;1"].
|
||||
createInstance(Ci.nsICryptoHash);
|
||||
|
@ -498,10 +425,6 @@ let Utils = {
|
|||
return Utils.encodeBase32(Utils._sha1(message));
|
||||
},
|
||||
|
||||
sha1Base64: function (message) {
|
||||
return btoa(Utils._sha1(message));
|
||||
},
|
||||
|
||||
/**
|
||||
* Produce an HMAC key object from a key string.
|
||||
*/
|
||||
|
@ -519,26 +442,6 @@ let Utils = {
|
|||
return hasher;
|
||||
},
|
||||
|
||||
/**
|
||||
* Some HMAC convenience functions for tests and backwards compatibility:
|
||||
*
|
||||
* sha1HMACBytes: hashes byte string, returns bytes string
|
||||
* sha256HMAC: hashes UTF-8 encoded string, returns hex string
|
||||
* sha256HMACBytes: hashes byte string, returns bytes string
|
||||
*/
|
||||
sha1HMACBytes: function sha1HMACBytes(message, key) {
|
||||
let h = Utils.makeHMACHasher(Ci.nsICryptoHMAC.SHA1, key);
|
||||
return Utils.digestBytes(message, h);
|
||||
},
|
||||
sha256HMAC: function sha256HMAC(message, key) {
|
||||
let h = Utils.makeHMACHasher(Ci.nsICryptoHMAC.SHA256, key);
|
||||
return Utils.bytesAsHex(Utils.digestUTF8(message, h));
|
||||
},
|
||||
sha256HMACBytes: function sha256HMACBytes(message, key) {
|
||||
let h = Utils.makeHMACHasher(Ci.nsICryptoHMAC.SHA256, key);
|
||||
return Utils.digestBytes(message, h);
|
||||
},
|
||||
|
||||
/**
|
||||
* HMAC-based Key Derivation Step 2 according to RFC 5869.
|
||||
*/
|
||||
|
@ -1198,20 +1101,6 @@ let Utils = {
|
|||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the app is ready (not quitting)
|
||||
*/
|
||||
checkAppReady: function checkAppReady() {
|
||||
// Watch for app-quit notification to stop any sync calls
|
||||
Svc.Obs.add("quit-application", function() {
|
||||
Utils.checkAppReady = function() {
|
||||
throw Components.Exception("App. Quitting", Cr.NS_ERROR_ABORT);
|
||||
};
|
||||
});
|
||||
// In the common case, checkAppReady just returns true
|
||||
return (Utils.checkAppReady = function() true)();
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a value for a backoff interval. Maximum is eight hours, unless
|
||||
* Status.backoffInterval is higher.
|
||||
|
|
|
@ -15,6 +15,8 @@ pref("services.sync.scheduler.activeInterval", 300); // 5 minutes
|
|||
pref("services.sync.scheduler.immediateInterval", 60); // 1 minute
|
||||
pref("services.sync.scheduler.idleTime", 300); // 5 minutes
|
||||
|
||||
pref("services.sync.errorhandler.networkFailureReportTimeout", 604800); // 1 week
|
||||
|
||||
pref("services.sync.engine.bookmarks", true);
|
||||
pref("services.sync.engine.history", true);
|
||||
pref("services.sync.engine.passwords", true);
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
"test_privbrw_tabs.js",
|
||||
"test_bookmarks_in_same_named_folder.js",
|
||||
"test_client_wipe.js",
|
||||
"test_special_tabs.js"
|
||||
"test_special_tabs.js",
|
||||
"test_mozmill_sanity.js"
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* * ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is MozMill Test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Clint Talbert <cmtalbert@gmail.com>
|
||||
* Jonathan Griffin <jgriffin@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* **** END LICENSE BLOCK ***** */
|
||||
|
||||
var jum = {}; Components.utils.import('resource://mozmill/modules/jum.js', jum);
|
||||
|
||||
var setupModule = function(module) {
|
||||
controller = mozmill.getBrowserController();
|
||||
jum.assert(true, "SetupModule passes");
|
||||
}
|
||||
|
||||
var setupTest = function(module) {
|
||||
jum.assert(true, "SetupTest passes");
|
||||
}
|
||||
|
||||
var testTestStep = function() {
|
||||
jum.assert(true, "test Passes");
|
||||
controller.open("http://www.mozilla.org");
|
||||
}
|
||||
|
||||
var teardownTest = function () {
|
||||
jum.assert(true, "teardownTest passes");
|
||||
}
|
||||
|
||||
var teardownModule = function() {
|
||||
jum.assert(true, "teardownModule passes");
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var jum = {}; Components.utils.import('resource://mozmill/modules/jum.js', jum);
|
||||
|
||||
var setupModule = function(module) {
|
||||
module.controller = mozmill.getBrowserController();
|
||||
};
|
||||
|
||||
var testGetNode = function() {
|
||||
controller.open("about:support");
|
||||
controller.waitForPageLoad();
|
||||
|
||||
var appbox = new elementslib.ID(controller.tabs.activeTab, "application-box");
|
||||
jum.assert(appbox.getNode().innerHTML == 'Firefox', 'correct app name');
|
||||
};
|
||||
|
||||
const NAV_BAR = '/id("main-window")/id("tab-view-deck")/{"flex":"1"}' +
|
||||
'/id("navigator-toolbox")/id("nav-bar")';
|
||||
const SEARCH_BAR = NAV_BAR + '/id("search-container")/id("searchbar")';
|
||||
const SEARCH_TEXTBOX = SEARCH_BAR + '/anon({"anonid":"searchbar-textbox"})';
|
||||
const SEARCH_DROPDOWN = SEARCH_TEXTBOX + '/[0]/anon({"anonid":"searchbar-engine-button"})';
|
||||
const SEARCH_POPUP = SEARCH_DROPDOWN + '/anon({"anonid":"searchbar-popup"})';
|
||||
const SEARCH_INPUT = SEARCH_TEXTBOX + '/anon({"class":"autocomplete-textbox-container"})' +
|
||||
'/anon({"anonid":"textbox-input-box"})' +
|
||||
'/anon({"anonid":"input"})';
|
||||
const SEARCH_CONTEXT = SEARCH_TEXTBOX + '/anon({"anonid":"textbox-input-box"})' +
|
||||
'/anon({"anonid":"input-box-contextmenu"})';
|
||||
const SEARCH_GO_BUTTON = SEARCH_TEXTBOX + '/anon({"class":"search-go-container"})' +
|
||||
'/anon({"class":"search-go-button"})';
|
||||
const SEARCH_AUTOCOMPLETE = '/id("main-window")/id("mainPopupSet")/id("PopupAutoComplete")';
|
||||
|
||||
var testLookupExpressions = function() {
|
||||
var item;
|
||||
item = new elementslib.Lookup(controller.window.document, NAV_BAR);
|
||||
controller.click(item);
|
||||
item = new elementslib.Lookup(controller.window.document, SEARCH_BAR);
|
||||
controller.click(item);
|
||||
item = new elementslib.Lookup(controller.window.document, SEARCH_TEXTBOX);
|
||||
controller.click(item);
|
||||
item = new elementslib.Lookup(controller.window.document, SEARCH_DROPDOWN);
|
||||
controller.click(item);
|
||||
item = new elementslib.Lookup(controller.window.document, SEARCH_POPUP);
|
||||
controller.click(item);
|
||||
item = new elementslib.Lookup(controller.window.document, SEARCH_INPUT);
|
||||
controller.click(item);
|
||||
item = new elementslib.Lookup(controller.window.document, SEARCH_CONTEXT);
|
||||
controller.click(item);
|
||||
item = new elementslib.Lookup(controller.window.document, SEARCH_GO_BUTTON);
|
||||
controller.click(item);
|
||||
item = new elementslib.Lookup(controller.window.document, SEARCH_AUTOCOMPLETE);
|
||||
controller.click(item);
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
* The list of phases mapped to their corresponding profiles. The object
|
||||
* here must be in strict JSON format, as it will get parsed by the Python
|
||||
* testrunner (no single quotes, extra comma's, etc).
|
||||
*/
|
||||
|
||||
var phases = { "phase1": "profile1",
|
||||
"phase2": "profile2" };
|
||||
|
||||
/*
|
||||
* Test phases
|
||||
*/
|
||||
|
||||
Phase('phase1', [
|
||||
[RunMozmillTest, 'mozmill_sanity.js'],
|
||||
[Sync, SYNC_WIPE_SERVER]
|
||||
]);
|
||||
|
||||
Phase('phase2', [
|
||||
[Sync],
|
||||
[RunMozmillTest, 'mozmill_sanity2.js'],
|
||||
]);
|
|
@ -82,6 +82,14 @@ function FakeGUIDService() {
|
|||
}
|
||||
|
||||
|
||||
function fakeSHA256HMAC(message) {
|
||||
message = message.substr(0, 64);
|
||||
while (message.length < 64) {
|
||||
message += " ";
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mock implementation of WeaveCrypto. It does not encrypt or
|
||||
* decrypt, merely returning the input verbatim.
|
||||
|
@ -91,24 +99,13 @@ function FakeCryptoService() {
|
|||
|
||||
delete Svc.Crypto; // get rid of the getter first
|
||||
Svc.Crypto = this;
|
||||
Utils.sha256HMAC = this.sha256HMAC;
|
||||
|
||||
CryptoWrapper.prototype.ciphertextHMAC = this.ciphertextHMAC;
|
||||
CryptoWrapper.prototype.ciphertextHMAC = function ciphertextHMAC(keyBundle) {
|
||||
return fakeSHA256HMAC(this.ciphertext);
|
||||
};
|
||||
}
|
||||
FakeCryptoService.prototype = {
|
||||
|
||||
sha256HMAC: function Utils_sha256HMAC(message, hasher) {
|
||||
message = message.substr(0, 64);
|
||||
while (message.length < 64) {
|
||||
message += " ";
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
ciphertextHMAC: function CryptoWrapper_ciphertextHMAC(keyBundle) {
|
||||
return Utils.sha256HMAC(this.ciphertext);
|
||||
},
|
||||
|
||||
encrypt: function(aClearText, aSymmetricKey, aIV) {
|
||||
return aClearText;
|
||||
},
|
||||
|
@ -187,7 +184,7 @@ Cu.import("resource://services-sync/identity.js");
|
|||
* Test setup helpers.
|
||||
*/
|
||||
|
||||
// Turn WBO cleartext into "encrypted" payload as it goes over the wire
|
||||
// Turn WBO cleartext into fake "encrypted" payload as it goes over the wire.
|
||||
function encryptPayload(cleartext) {
|
||||
if (typeof cleartext == "object") {
|
||||
cleartext = JSON.stringify(cleartext);
|
||||
|
@ -195,7 +192,7 @@ function encryptPayload(cleartext) {
|
|||
|
||||
return {ciphertext: cleartext, // ciphertext == cleartext with fake crypto
|
||||
IV: "irrelevant",
|
||||
hmac: Utils.sha256HMAC(cleartext, Utils.makeHMACKey(""))};
|
||||
hmac: fakeSHA256HMAC(cleartext, Utils.makeHMACKey(""))};
|
||||
}
|
||||
|
||||
function generateNewKeys(collections) {
|
||||
|
|
|
@ -4,13 +4,24 @@
|
|||
function new_timestamp() {
|
||||
return Math.round(Date.now() / 10) / 100;
|
||||
}
|
||||
|
||||
|
||||
function httpd_setup (handlers) {
|
||||
let server = new nsHttpServer();
|
||||
let port = 8080;
|
||||
for (let path in handlers) {
|
||||
server.registerPathHandler(path, handlers[path]);
|
||||
}
|
||||
server.start(8080);
|
||||
try {
|
||||
server.start(port);
|
||||
} catch (ex) {
|
||||
_("==========================================");
|
||||
_("Got exception starting HTTP server on port " + port);
|
||||
_("Error: " + Utils.exceptionStr(ex));
|
||||
_("Is there a process already listening on port " + port + "?");
|
||||
_("==========================================");
|
||||
do_throw(ex);
|
||||
}
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/async.js");
|
||||
|
||||
function run_test() {
|
||||
_("Chain a few async methods, making sure the 'this' object is correct.");
|
||||
|
@ -18,7 +18,7 @@ function run_test() {
|
|||
callback(-x);
|
||||
}
|
||||
};
|
||||
methods.chain = Utils.asyncChain;
|
||||
methods.chain = Async.chain;
|
||||
|
||||
// ((1 + 1 + 1) * (-1) + 1) * 2 + 1 = -3
|
||||
methods.chain(methods.save, methods.addX, methods.addX, methods.neg,
|
|
@ -1,297 +0,0 @@
|
|||
Cu.import("resource://services-sync/async.js");
|
||||
|
||||
function chain(fs) {
|
||||
fs.reduce(function (prev, next) next.bind(this, prev),
|
||||
run_next_test)();
|
||||
}
|
||||
|
||||
// barrieredCallbacks.
|
||||
add_test(function test_barrieredCallbacks() {
|
||||
let s1called = false;
|
||||
let s2called = false;
|
||||
|
||||
function reset() {
|
||||
_(" > reset.");
|
||||
s1called = s2called = false;
|
||||
}
|
||||
function succeed1(err, result) {
|
||||
_(" > succeed1.");
|
||||
s1called = true;
|
||||
}
|
||||
function succeed2(err, result) {
|
||||
_(" > succeed2.");
|
||||
s2called = true;
|
||||
}
|
||||
function fail1(err, result) {
|
||||
_(" > fail1.");
|
||||
return "failed";
|
||||
}
|
||||
function throw1(err, result) {
|
||||
_(" > throw1.");
|
||||
throw "Aieeee!";
|
||||
}
|
||||
|
||||
function doneSequential(next, err) {
|
||||
_(" > doneSequential.");
|
||||
do_check_eq(err, "failed");
|
||||
do_check_true(s1called);
|
||||
do_check_true(s2called);
|
||||
next();
|
||||
}
|
||||
function doneFailFirst(next, err) {
|
||||
_(" > doneFailFirst.");
|
||||
do_check_eq(err, "failed");
|
||||
do_check_false(s1called);
|
||||
do_check_false(s2called);
|
||||
next();
|
||||
}
|
||||
function doneOnlySucceed(next, err) {
|
||||
_(" > doneOnlySucceed.");
|
||||
do_check_true(!err);
|
||||
do_check_true(s1called);
|
||||
do_check_true(s2called);
|
||||
next();
|
||||
}
|
||||
function doneThrow(next, err) {
|
||||
_(" > doneThrow.");
|
||||
do_check_eq(err, "Aieeee!");
|
||||
do_check_true(s1called);
|
||||
do_check_false(s2called);
|
||||
next();
|
||||
}
|
||||
|
||||
function sequence_test(label, parts, end) {
|
||||
return function (next) {
|
||||
_("Sequence test '" + label + "':");
|
||||
reset();
|
||||
for (let cb in Async.barrieredCallbacks(parts, end.bind(this, next)))
|
||||
cb();
|
||||
};
|
||||
}
|
||||
|
||||
chain(
|
||||
[sequence_test("failFirst",
|
||||
[fail1, succeed1, succeed2],
|
||||
doneFailFirst),
|
||||
|
||||
sequence_test("sequentially",
|
||||
[succeed1, succeed2, fail1],
|
||||
doneSequential),
|
||||
|
||||
sequence_test("onlySucceed",
|
||||
[succeed1, succeed2],
|
||||
doneOnlySucceed),
|
||||
|
||||
sequence_test("throw",
|
||||
[succeed1, throw1, succeed2],
|
||||
doneThrow)]);
|
||||
|
||||
});
|
||||
|
||||
add_test(function test_empty_barrieredCallbacks() {
|
||||
let err;
|
||||
try {
|
||||
Async.barrieredCallbacks([], function (err) { }).next();
|
||||
} catch (ex) {
|
||||
err = ex;
|
||||
}
|
||||
_("err is " + err);
|
||||
do_check_true(err instanceof StopIteration);
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_no_output_barrieredCallbacks() {
|
||||
let err;
|
||||
try {
|
||||
Async.barrieredCallbacks([function (x) {}], null);
|
||||
} catch (ex) {
|
||||
err = ex;
|
||||
}
|
||||
do_check_eq(err, "No output callback provided to barrieredCallbacks.");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_serially() {
|
||||
let called = {};
|
||||
let i = 1;
|
||||
function reset() {
|
||||
called = {};
|
||||
i = 0;
|
||||
}
|
||||
|
||||
function f(x, cb) {
|
||||
called[x] = ++i;
|
||||
cb(null, x);
|
||||
}
|
||||
|
||||
function err_on(expected) {
|
||||
return function (err, result, context) {
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (result == expected) {
|
||||
return expected;
|
||||
}
|
||||
_("Got " + result + ", passing.");
|
||||
};
|
||||
}
|
||||
|
||||
// Fail in the middle.
|
||||
reset();
|
||||
Async.serially(["a", "b", "d"], f, err_on("b"), function (err) {
|
||||
do_check_eq(1, called["a"]);
|
||||
do_check_eq(2, called["b"]);
|
||||
do_check_false(!!called["d"]);
|
||||
do_check_eq(err, "b");
|
||||
|
||||
// Don't fail.
|
||||
reset();
|
||||
Async.serially(["a", "d", "b"], f, err_on("x"), function (err) {
|
||||
do_check_eq(1, called["a"]);
|
||||
do_check_eq(3, called["b"]);
|
||||
do_check_eq(2, called["d"]);
|
||||
do_check_false(!!err);
|
||||
|
||||
// Empty inputs.
|
||||
reset();
|
||||
Async.serially([], f, err_on("a"), function (err) {
|
||||
do_check_false(!!err);
|
||||
|
||||
reset();
|
||||
Async.serially(undefined, f, err_on("a"), function (err) {
|
||||
do_check_false(!!err);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_countedCallback() {
|
||||
let error = null;
|
||||
let output = null;
|
||||
let context = null;
|
||||
let counter = 0;
|
||||
function cb(err, result, ctx) {
|
||||
counter++;
|
||||
output = result;
|
||||
error = err;
|
||||
context = ctx;
|
||||
if (err == "error!")
|
||||
return "Oh dear.";
|
||||
}
|
||||
|
||||
let c1;
|
||||
|
||||
c1 = Async.countedCallback(cb, 3, function (err) {
|
||||
do_check_eq(2, counter);
|
||||
do_check_eq("error!", error);
|
||||
do_check_eq(2, output);
|
||||
do_check_eq("b", context);
|
||||
do_check_eq(err, "Oh dear.");
|
||||
|
||||
// If we call the counted callback again (once this output function is
|
||||
// done, that is), then the component callback is not invoked.
|
||||
Utils.nextTick(function () {
|
||||
_("Don't expect component callback.");
|
||||
c1("not", "running", "now");
|
||||
do_check_eq(2, counter);
|
||||
do_check_eq("error!", error);
|
||||
do_check_eq(2, output);
|
||||
do_check_eq("b", context);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
c1(1, "foo", "a");
|
||||
do_check_eq(1, counter);
|
||||
do_check_eq(1, error);
|
||||
do_check_eq("foo", output);
|
||||
do_check_eq("a", context);
|
||||
|
||||
c1("error!", 2, "b");
|
||||
// Subsequent checks must now take place inside the 'done' callback... read
|
||||
// above!
|
||||
});
|
||||
|
||||
add_test(function test_finallyCallback() {
|
||||
let fnCalled = false;
|
||||
let cbCalled = false;
|
||||
let error = undefined;
|
||||
|
||||
function reset() {
|
||||
fnCalled = cbCalled = false;
|
||||
error = undefined;
|
||||
}
|
||||
|
||||
function fn(arg) {
|
||||
do_check_false(!!arg);
|
||||
fnCalled = true;
|
||||
}
|
||||
|
||||
function fnThrow(arg) {
|
||||
do_check_false(!!arg);
|
||||
fnCalled = true;
|
||||
throw "Foo";
|
||||
}
|
||||
|
||||
function cb(next, err) {
|
||||
_("Called with " + err);
|
||||
cbCalled = true;
|
||||
error = err;
|
||||
next();
|
||||
}
|
||||
|
||||
function allGood(next) {
|
||||
reset();
|
||||
let callback = cb.bind(this, function() {
|
||||
do_check_true(fnCalled);
|
||||
do_check_true(cbCalled);
|
||||
do_check_false(!!error);
|
||||
next();
|
||||
});
|
||||
Async.finallyCallback(callback, fn)(null);
|
||||
}
|
||||
|
||||
function inboundErr(next) {
|
||||
reset();
|
||||
let callback = cb.bind(this, function() {
|
||||
do_check_true(fnCalled);
|
||||
do_check_true(cbCalled);
|
||||
do_check_eq(error, "Baz");
|
||||
next();
|
||||
});
|
||||
Async.finallyCallback(callback, fn)("Baz");
|
||||
}
|
||||
|
||||
function throwsNoErr(next) {
|
||||
reset();
|
||||
let callback = cb.bind(this, function() {
|
||||
do_check_true(fnCalled);
|
||||
do_check_true(cbCalled);
|
||||
do_check_eq(error, "Foo");
|
||||
next();
|
||||
});
|
||||
Async.finallyCallback(callback, fnThrow)(null);
|
||||
}
|
||||
|
||||
function throwsOverrulesErr(next) {
|
||||
reset();
|
||||
let callback = cb.bind(this, function() {
|
||||
do_check_true(fnCalled);
|
||||
do_check_true(cbCalled);
|
||||
do_check_eq(error, "Foo");
|
||||
next();
|
||||
});
|
||||
Async.finallyCallback(callback, fnThrow)("Bar");
|
||||
}
|
||||
|
||||
chain([throwsOverrulesErr,
|
||||
throwsNoErr,
|
||||
inboundErr,
|
||||
allGood]);
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
|
@ -0,0 +1,841 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/engines/clients.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/policies.js");
|
||||
Cu.import("resource://services-sync/status.js");
|
||||
|
||||
Svc.DefaultPrefs.set("registerEngines", "");
|
||||
Cu.import("resource://services-sync/service.js");
|
||||
|
||||
const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
|
||||
const LOG_PREFIX_SUCCESS = "success-";
|
||||
const LOG_PREFIX_ERROR = "error-";
|
||||
|
||||
const PROLONGED_ERROR_DURATION =
|
||||
(Svc.Prefs.get('errorhandler.networkFailureReportTimeout') * 2) * 1000;
|
||||
|
||||
const NON_PROLONGED_ERROR_DURATION =
|
||||
(Svc.Prefs.get('errorhandler.networkFailureReportTimeout') / 2) * 1000;
|
||||
|
||||
function setLastSync(lastSyncValue) {
|
||||
Svc.Prefs.set("lastSync", (new Date(Date.now() -
|
||||
lastSyncValue)).toString());
|
||||
}
|
||||
|
||||
function CatapultEngine() {
|
||||
SyncEngine.call(this, "Catapult");
|
||||
}
|
||||
CatapultEngine.prototype = {
|
||||
__proto__: SyncEngine.prototype,
|
||||
exception: null, // tests fill this in
|
||||
_sync: function _sync() {
|
||||
throw this.exception;
|
||||
}
|
||||
};
|
||||
|
||||
Engines.register(CatapultEngine);
|
||||
|
||||
function run_test() {
|
||||
initTestLogging("Trace");
|
||||
|
||||
Log4Moz.repository.getLogger("Sync.Service").level = Log4Moz.Level.Trace;
|
||||
Log4Moz.repository.getLogger("Sync.SyncScheduler").level = Log4Moz.Level.Trace;
|
||||
Log4Moz.repository.getLogger("Sync.ErrorHandler").level = Log4Moz.Level.Trace;
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function generateCredentialsChangedFailure() {
|
||||
// Make sync fail due to changed credentials. We simply re-encrypt
|
||||
// the keys with a different Sync Key, without changing the local one.
|
||||
let newSyncKeyBundle = new SyncKeyBundle(PWDMGR_PASSPHRASE_REALM, Service.username);
|
||||
newSyncKeyBundle.keyStr = "23456234562345623456234562";
|
||||
let keys = CollectionKeys.asWBO();
|
||||
keys.encrypt(newSyncKeyBundle);
|
||||
keys.upload(Service.cryptoKeysURL);
|
||||
}
|
||||
|
||||
function sync_httpd_setup() {
|
||||
let global = new ServerWBO("global", {
|
||||
syncID: Service.syncID,
|
||||
storageVersion: STORAGE_VERSION,
|
||||
engines: {clients: {version: Clients.version,
|
||||
syncID: Clients.syncID}}
|
||||
});
|
||||
let clientsColl = new ServerCollection({}, true);
|
||||
|
||||
// Tracking info/collections.
|
||||
let collectionsHelper = track_collections_helper();
|
||||
let upd = collectionsHelper.with_updated_collection;
|
||||
|
||||
let handler_401 = httpd_handler(401, "Unauthorized");
|
||||
return httpd_setup({
|
||||
"/1.1/johndoe/storage/meta/global": upd("meta", global.handler()),
|
||||
"/1.1/johndoe/info/collections": collectionsHelper.handler,
|
||||
"/1.1/johndoe/storage/crypto/keys":
|
||||
upd("crypto", (new ServerWBO("keys")).handler()),
|
||||
"/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler()),
|
||||
|
||||
"/1.1/janedoe/storage/meta/global": handler_401,
|
||||
"/1.1/janedoe/info/collections": handler_401,
|
||||
});
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
Service.clusterURL = "http://localhost:8080/";
|
||||
|
||||
generateNewKeys();
|
||||
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
|
||||
serverKeys.encrypt(Service.syncKeyBundle);
|
||||
return serverKeys.upload(Service.cryptoKeysURL).success;
|
||||
}
|
||||
|
||||
add_test(function test_401_logout() {
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
// By calling sync, we ensure we're logged in.
|
||||
Service.sync();
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
do_check_true(Service.isLoggedIn);
|
||||
|
||||
// Make sync fail due to login rejected.
|
||||
Service.username = "janedoe";
|
||||
Service.sync();
|
||||
|
||||
do_check_eq(Status.login, LOGIN_FAILED_LOGIN_REJECTED);
|
||||
do_check_false(Service.isLoggedIn);
|
||||
|
||||
// Clean up.
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function test_credentials_changed_logout() {
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
// By calling sync, we ensure we're logged in.
|
||||
Service.sync();
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
do_check_true(Service.isLoggedIn);
|
||||
|
||||
generateCredentialsChangedFailure();
|
||||
Service.sync();
|
||||
|
||||
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
|
||||
do_check_false(Service.isLoggedIn);
|
||||
|
||||
// Clean up.
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function test_no_lastSync_pref() {
|
||||
// Test reported error.
|
||||
Status.resetSync();
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test unreported error.
|
||||
Status.resetSync();
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_shouldReportError() {
|
||||
Status.login = MASTER_PASSWORD_LOCKED;
|
||||
do_check_false(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, non-network, non-prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.login = LOGIN_FAILED_NO_PASSWORD;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, non-network, non-prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, non-network, prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.login = LOGIN_FAILED_NO_PASSWORD;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, non-network, prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, network, non-prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, network, non-prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, network, prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, network, prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test non-network, prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NO_PASSWORD;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test non-network, prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test network, prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test network, prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test non-network, non-prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NO_PASSWORD;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test non-network, non-prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test network, non-prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_false(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test network, non-prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_false(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test server maintenance errors are not reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
do_check_false(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test prolonged server maintenance errors are reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, server maintenance errors are reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, prolonged, server maintenance
|
||||
// errors are reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
do_check_true(ErrorHandler.shouldReportError());
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_shouldReportError_master_password() {
|
||||
_("Test error ignored due to locked master password");
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
// Monkey patch Service.verifyLogin to imitate
|
||||
// master password being locked.
|
||||
Service._verifyLogin = Service.verifyLogin;
|
||||
Service.verifyLogin = function () {
|
||||
Status.login = MASTER_PASSWORD_LOCKED;
|
||||
return false;
|
||||
};
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
Service.sync();
|
||||
do_check_false(ErrorHandler.shouldReportError());
|
||||
|
||||
// Clean up.
|
||||
Service.verifyLogin = Service._verifyLogin;
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function test_login_syncAndReportErrors_non_network_error() {
|
||||
// Test non-network errors are reported
|
||||
// when calling syncAndReportErrors
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
Service.password = "";
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
|
||||
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.syncAndReportErrors();
|
||||
});
|
||||
|
||||
add_test(function test_sync_syncAndReportErrors_non_network_error() {
|
||||
// Test non-network errors are reported
|
||||
// when calling syncAndReportErrors
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
// By calling sync, we ensure we're logged in.
|
||||
Service.sync();
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
do_check_true(Service.isLoggedIn);
|
||||
|
||||
generateCredentialsChangedFailure();
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
|
||||
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.syncAndReportErrors();
|
||||
});
|
||||
|
||||
add_test(function test_login_syncAndReportErrors_prolonged_non_network_error() {
|
||||
// Test prolonged, non-network errors are
|
||||
// reported when calling syncAndReportErrors.
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
Service.password = "";
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
|
||||
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.syncAndReportErrors();
|
||||
});
|
||||
|
||||
add_test(function test_sync_syncAndReportErrors_prolonged_non_network_error() {
|
||||
// Test prolonged, non-network errors are
|
||||
// reported when calling syncAndReportErrors.
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
// By calling sync, we ensure we're logged in.
|
||||
Service.sync();
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
do_check_true(Service.isLoggedIn);
|
||||
|
||||
generateCredentialsChangedFailure();
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
|
||||
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.syncAndReportErrors();
|
||||
});
|
||||
|
||||
add_test(function test_login_syncAndReportErrors_network_error() {
|
||||
// Test network errors are reported when calling syncAndReportErrors.
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
Service.clusterURL = "http://localhost:8080/";
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
|
||||
|
||||
Service.startOver();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.syncAndReportErrors();
|
||||
});
|
||||
|
||||
|
||||
add_test(function test_sync_syncAndReportErrors_network_error() {
|
||||
// Test network errors are reported when calling syncAndReportErrors.
|
||||
Services.io.offline = true;
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
|
||||
Services.io.offline = false;
|
||||
Service.startOver();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.syncAndReportErrors();
|
||||
});
|
||||
|
||||
add_test(function test_login_syncAndReportErrors_prolonged_network_error() {
|
||||
// Test prolonged, network errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
Service.clusterURL = "http://localhost:8080/";
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
|
||||
Service.startOver();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.syncAndReportErrors();
|
||||
});
|
||||
|
||||
add_test(function test_sync_syncAndReportErrors_prolonged_network_error() {
|
||||
// Test prolonged, network errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
Services.io.offline = true;
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
|
||||
Services.io.offline = false;
|
||||
Service.startOver();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.syncAndReportErrors();
|
||||
});
|
||||
|
||||
add_test(function test_login_prolonged_non_network_error() {
|
||||
// Test prolonged, non-network errors are reported
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
Service.password = "";
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Service.sync();
|
||||
});
|
||||
|
||||
add_test(function test_sync_prolonged_non_network_error() {
|
||||
// Test prolonged, non-network errors are reported
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
// By calling sync, we ensure we're logged in.
|
||||
Service.sync();
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
do_check_true(Service.isLoggedIn);
|
||||
|
||||
generateCredentialsChangedFailure();
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Service.sync();
|
||||
});
|
||||
|
||||
add_test(function test_login_prolonged_network_error() {
|
||||
// Test prolonged, network errors are reported
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
Service.clusterURL = "http://localhost:8080/";
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
|
||||
Service.startOver();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Service.sync();
|
||||
});
|
||||
|
||||
add_test(function test_sync_prolonged_network_error() {
|
||||
// Test prolonged, network errors are reported
|
||||
Services.io.offline = true;
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
|
||||
Services.io.offline = false;
|
||||
Service.startOver();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Service.sync();
|
||||
});
|
||||
|
||||
add_test(function test_login_non_network_error() {
|
||||
// Test non-network errors are reported
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
Service.password = "";
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
|
||||
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
Service.sync();
|
||||
});
|
||||
|
||||
|
||||
add_test(function test_sync_non_network_error() {
|
||||
// Test non-network errors are reported
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
// By calling sync, we ensure we're logged in.
|
||||
Service.sync();
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
do_check_true(Service.isLoggedIn);
|
||||
|
||||
generateCredentialsChangedFailure();
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
|
||||
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
Service.sync();
|
||||
});
|
||||
|
||||
add_test(function test_login_network_error() {
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
Service.clusterURL = "http://localhost:8080/";
|
||||
|
||||
// Test network errors are not reported.
|
||||
Svc.Obs.add("weave:ui:clear-error", function onClearError() {
|
||||
Svc.Obs.remove("weave:ui:clear-error", onClearError);
|
||||
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
|
||||
|
||||
Service.startOver();
|
||||
Status.resetSync();
|
||||
Services.io.offline = false;
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
Service.sync();
|
||||
});
|
||||
|
||||
add_test(function test_sync_network_error() {
|
||||
// Test network errors are not reported.
|
||||
Services.io.offline = true;
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:finish", function onUIUpdate() {
|
||||
Svc.Obs.remove("weave:ui:sync:finish", onUIUpdate);
|
||||
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
|
||||
Service.startOver();
|
||||
Services.io.offline = false;
|
||||
Status.resetSync();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
Service.sync();
|
||||
});
|
||||
|
||||
add_test(function test_sync_server_maintenance_error() {
|
||||
// Test server maintenance errors are not reported.
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
const BACKOFF = 42;
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = true;
|
||||
engine.exception = {status: 503,
|
||||
headers: {"retry-after": BACKOFF}};
|
||||
|
||||
function onUIUpdate() {
|
||||
do_throw("Shouldn't get here!");
|
||||
}
|
||||
Svc.Obs.add("weave:ui:sync:error", onUIUpdate);
|
||||
|
||||
do_check_eq(Status.service, STATUS_OK);
|
||||
|
||||
// Last sync was 2 days ago
|
||||
Svc.Prefs.set("lastSync", (new Date(Date.now() - 172800000)).toString());
|
||||
Service.sync();
|
||||
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
do_check_eq(Status.sync, SERVER_MAINTENANCE);
|
||||
|
||||
Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
|
||||
Service.startOver();
|
||||
Status.resetSync();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function test_sync_prolonged_server_maintenance_error() {
|
||||
// Test prolonged server maintenance errors are reported.
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
const BACKOFF = 42;
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = true;
|
||||
engine.exception = {status: 503,
|
||||
headers: {"retry-after": BACKOFF}};
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
|
||||
Service.startOver();
|
||||
Status.resetSync();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
do_check_eq(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Service.sync();
|
||||
});
|
||||
|
||||
add_test(function test_syncAndReportErrors_server_maintenance_error() {
|
||||
// Test server maintenance errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
const BACKOFF = 42;
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = true;
|
||||
engine.exception = {status: 503,
|
||||
headers: {"retry-after": BACKOFF}};
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
do_check_eq(Status.sync, SERVER_MAINTENANCE);
|
||||
|
||||
Service.startOver();
|
||||
Status.resetSync();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
do_check_eq(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.syncAndReportErrors();
|
||||
});
|
||||
|
||||
add_test(function test_syncAndReportErrors_prolonged_server_maintenance_error() {
|
||||
// Test prolonged server maintenance errors are
|
||||
// reported when calling syncAndReportErrors.
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
const BACKOFF = 42;
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = true;
|
||||
engine.exception = {status: 503,
|
||||
headers: {"retry-after": BACKOFF}};
|
||||
|
||||
Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
do_check_eq(Status.sync, SERVER_MAINTENANCE);
|
||||
|
||||
Service.startOver();
|
||||
Status.resetSync();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
do_check_eq(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
ErrorHandler.syncAndReportErrors();
|
||||
});
|
||||
|
||||
add_test(function test_sync_engine_generic_fail() {
|
||||
let server = sync_httpd_setup();
|
||||
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = true;
|
||||
engine.sync = function sync() {
|
||||
Svc.Obs.notify("weave:engine:sync:error", "", "steam");
|
||||
};
|
||||
|
||||
let log = Log4Moz.repository.getLogger("Sync.ErrorHandler");
|
||||
Svc.Prefs.set("log.appender.file.logOnError", true);
|
||||
|
||||
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
||||
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
||||
|
||||
// Test Error log was written on SYNC_FAILED_PARTIAL.
|
||||
let entries = logsdir.directoryEntries;
|
||||
do_check_true(entries.hasMoreElements());
|
||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||
do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
|
||||
LOG_PREFIX_ERROR);
|
||||
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
do_check_eq(Status.engines["steam"], undefined);
|
||||
|
||||
do_check_true(setUp());
|
||||
|
||||
Service.sync();
|
||||
|
||||
do_check_eq(Status.engines["steam"], ENGINE_UNKNOWN_FAIL);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
});
|
||||
|
||||
// This test should be the last one since it monkeypatches the engine object
|
||||
// and we should only have one engine object throughout the file (bug 629664).
|
||||
add_test(function test_engine_applyFailed() {
|
||||
let server = sync_httpd_setup();
|
||||
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = true;
|
||||
delete engine.exception;
|
||||
engine.sync = function sync() {
|
||||
Svc.Obs.notify("weave:engine:sync:applied", {newFailed:1}, "steam");
|
||||
};
|
||||
|
||||
let log = Log4Moz.repository.getLogger("Sync.ErrorHandler");
|
||||
Svc.Prefs.set("log.appender.file.logOnError", true);
|
||||
|
||||
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
||||
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
||||
|
||||
// Test Error log was written on SYNC_FAILED_PARTIAL.
|
||||
let entries = logsdir.directoryEntries;
|
||||
do_check_true(entries.hasMoreElements());
|
||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||
do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
|
||||
LOG_PREFIX_ERROR);
|
||||
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
do_check_eq(Status.engines["steam"], undefined);
|
||||
|
||||
do_check_true(setUp());
|
||||
|
||||
Service.sync();
|
||||
|
||||
do_check_eq(Status.engines["steam"], ENGINE_APPLY_FAIL);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
});
|
|
@ -9,6 +9,14 @@ const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
|
|||
const LOG_PREFIX_SUCCESS = "success-";
|
||||
const LOG_PREFIX_ERROR = "error-";
|
||||
|
||||
const PROLONGED_ERROR_DURATION =
|
||||
(Svc.Prefs.get('errorhandler.networkFailureReportTimeout') * 2) * 1000;
|
||||
|
||||
function setLastSync(lastSyncValue) {
|
||||
Svc.Prefs.set("lastSync", (new Date(Date.now() -
|
||||
lastSyncValue)).toString());
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -100,7 +108,7 @@ add_test(function test_logOnSuccess_true() {
|
|||
Svc.Obs.notify("weave:service:sync:finish");
|
||||
});
|
||||
|
||||
add_test(function test_logOnError_false() {
|
||||
add_test(function test_sync_error_logOnError_false() {
|
||||
Svc.Prefs.set("log.appender.file.logOnError", false);
|
||||
|
||||
let log = Log4Moz.repository.getLogger("Sync.Test.FileLog");
|
||||
|
@ -115,11 +123,12 @@ add_test(function test_logOnError_false() {
|
|||
run_next_test();
|
||||
});
|
||||
|
||||
// Fake an unsuccessful sync.
|
||||
// Fake an unsuccessful sync due to prolonged failure.
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Svc.Obs.notify("weave:service:sync:error");
|
||||
});
|
||||
|
||||
add_test(function test_logOnError_true() {
|
||||
add_test(function test_sync_error_logOnError_true() {
|
||||
Svc.Prefs.set("log.appender.file.logOnError", true);
|
||||
|
||||
let log = Log4Moz.repository.getLogger("Sync.Test.FileLog");
|
||||
|
@ -156,6 +165,69 @@ add_test(function test_logOnError_true() {
|
|||
});
|
||||
});
|
||||
|
||||
// Fake an unsuccessful sync.
|
||||
// Fake an unsuccessful sync due to prolonged failure.
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Svc.Obs.notify("weave:service:sync:error");
|
||||
});
|
||||
|
||||
add_test(function test_login_error_logOnError_false() {
|
||||
Svc.Prefs.set("log.appender.file.logOnError", false);
|
||||
|
||||
let log = Log4Moz.repository.getLogger("Sync.Test.FileLog");
|
||||
log.info("this won't show up");
|
||||
|
||||
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
||||
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
||||
// No log file was written.
|
||||
do_check_false(logsdir.directoryEntries.hasMoreElements());
|
||||
|
||||
Svc.Prefs.resetBranch("");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
// Fake an unsuccessful login due to prolonged failure.
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Svc.Obs.notify("weave:service:login:error");
|
||||
});
|
||||
|
||||
add_test(function test_login_error_logOnError_true() {
|
||||
Svc.Prefs.set("log.appender.file.logOnError", true);
|
||||
|
||||
let log = Log4Moz.repository.getLogger("Sync.Test.FileLog");
|
||||
const MESSAGE = "this WILL show up";
|
||||
log.info(MESSAGE);
|
||||
|
||||
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
||||
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
||||
|
||||
// Exactly one log file was written.
|
||||
let entries = logsdir.directoryEntries;
|
||||
do_check_true(entries.hasMoreElements());
|
||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||
do_check_eq(logfile.leafName.slice(-4), ".txt");
|
||||
do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
|
||||
LOG_PREFIX_ERROR);
|
||||
do_check_false(entries.hasMoreElements());
|
||||
|
||||
// Ensure the log message was actually written to file.
|
||||
readFile(logfile, function (error, data) {
|
||||
do_check_true(Components.isSuccessCode(error));
|
||||
do_check_neq(data.indexOf(MESSAGE), -1);
|
||||
|
||||
// Clean up.
|
||||
try {
|
||||
logfile.remove(false);
|
||||
} catch(ex) {
|
||||
dump("Couldn't delete file: " + ex + "\n");
|
||||
// Stupid Windows box.
|
||||
}
|
||||
|
||||
Svc.Prefs.resetBranch("");
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
// Fake an unsuccessful login due to prolonged failure.
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Svc.Obs.notify("weave:service:login:error");
|
||||
});
|
|
@ -1,6 +1,7 @@
|
|||
Cu.import("resource://services-sync/engines.js");
|
||||
Cu.import("resource://services-sync/status.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/policies.js");
|
||||
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Svc.DefaultPrefs.set("registerEngines", "");
|
||||
|
@ -15,7 +16,7 @@ function CatapultEngine() {
|
|||
CatapultEngine.prototype = {
|
||||
__proto__: SyncEngine.prototype,
|
||||
exception: null, // tests fill this in
|
||||
sync: function sync() {
|
||||
_sync: function _sync() {
|
||||
throw this.exception;
|
||||
}
|
||||
};
|
||||
|
@ -80,6 +81,8 @@ add_test(function test_backoff500() {
|
|||
Service.login();
|
||||
Service.sync();
|
||||
do_check_true(Status.enforceBackoff);
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
} finally {
|
||||
Status.resetBackoff();
|
||||
Service.startOver();
|
||||
|
@ -113,8 +116,11 @@ add_test(function test_backoff503() {
|
|||
|
||||
do_check_true(Status.enforceBackoff);
|
||||
do_check_eq(backoffInterval, BACKOFF);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
do_check_eq(Status.sync, SERVER_MAINTENANCE);
|
||||
} finally {
|
||||
Status.resetBackoff();
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
}
|
||||
server.stop(run_next_test);
|
||||
|
@ -139,6 +145,7 @@ add_test(function test_overQuota() {
|
|||
Service.sync();
|
||||
|
||||
do_check_eq(Status.sync, OVER_QUOTA);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
} finally {
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
|
@ -151,7 +158,6 @@ add_test(function test_service_networkError() {
|
|||
setUp();
|
||||
// Provoke connection refused.
|
||||
Service.clusterURL = "http://localhost:12345/";
|
||||
Service._ignorableErrorCount = 0;
|
||||
|
||||
try {
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
|
@ -160,7 +166,7 @@ add_test(function test_service_networkError() {
|
|||
Service.sync();
|
||||
|
||||
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
do_check_eq(Service._ignorableErrorCount, 1);
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
} finally {
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
|
@ -172,7 +178,6 @@ add_test(function test_service_offline() {
|
|||
_("Test: Wanting to sync in offline mode leads to the right status code but does not increment the ignorable error count.");
|
||||
setUp();
|
||||
Services.io.offline = true;
|
||||
Service._ignorableErrorCount = 0;
|
||||
|
||||
try {
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
|
@ -181,7 +186,7 @@ add_test(function test_service_offline() {
|
|||
Service.sync();
|
||||
|
||||
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
do_check_eq(Service._ignorableErrorCount, 0);
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
} finally {
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
|
@ -190,38 +195,10 @@ add_test(function test_service_offline() {
|
|||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_service_reset_ignorableErrorCount() {
|
||||
_("Test: Successful sync resets the ignorable error count.");
|
||||
setUp();
|
||||
let server = sync_httpd_setup();
|
||||
Service._ignorableErrorCount = 10;
|
||||
|
||||
// Disable the engine so that sync completes.
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = false;
|
||||
|
||||
try {
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
|
||||
do_check_true(generateAndUploadKeys());
|
||||
|
||||
Service.login();
|
||||
Service.sync();
|
||||
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
do_check_eq(Service._ignorableErrorCount, 0);
|
||||
} finally {
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
}
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function test_engine_networkError() {
|
||||
_("Test: Network related exceptions from engine.sync() lead to the right status code.");
|
||||
setUp();
|
||||
let server = sync_httpd_setup();
|
||||
Service._ignorableErrorCount = 0;
|
||||
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = true;
|
||||
|
@ -237,7 +214,7 @@ add_test(function test_engine_networkError() {
|
|||
Service.sync();
|
||||
|
||||
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
do_check_eq(Service._ignorableErrorCount, 1);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
} finally {
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
|
@ -264,6 +241,7 @@ add_test(function test_resource_timeout() {
|
|||
Service.sync();
|
||||
|
||||
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
} finally {
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
|
@ -271,39 +249,6 @@ add_test(function test_resource_timeout() {
|
|||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
|
||||
// Slightly misplaced test as it doesn't actually test checkServerError,
|
||||
// but the observer for "weave:engine:sync:apply-failed".
|
||||
// This test should be the last one since it monkeypatches the engine object
|
||||
// and we should only have one engine object throughout the file (bug 629664).
|
||||
add_test(function test_engine_applyFailed() {
|
||||
setUp();
|
||||
let server = sync_httpd_setup();
|
||||
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = true;
|
||||
delete engine.exception;
|
||||
engine.sync = function sync() {
|
||||
Svc.Obs.notify("weave:engine:sync:applied", {newFailed:1}, "steam");
|
||||
};
|
||||
|
||||
try {
|
||||
do_check_eq(Status.engines["steam"], undefined);
|
||||
|
||||
do_check_true(generateAndUploadKeys());
|
||||
|
||||
Service.login();
|
||||
Service.sync();
|
||||
|
||||
do_check_eq(Status.engines["steam"], ENGINE_APPLY_FAIL);
|
||||
} finally {
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
}
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
|
||||
function run_test() {
|
||||
Engines.register(CatapultEngine);
|
||||
run_next_test();
|
|
@ -4,6 +4,11 @@ Cu.import("resource://services-sync/record.js");
|
|||
Cu.import("resource://services-sync/constants.js");
|
||||
btoa = Cu.import("resource://services-sync/util.js").btoa;
|
||||
|
||||
function sha256HMAC(message, key) {
|
||||
let h = Utils.makeHMACHasher(Ci.nsICryptoHMAC.SHA256, key);
|
||||
return Utils.digestBytes(message, h);
|
||||
}
|
||||
|
||||
function test_time_keyFromString(iterations) {
|
||||
let k;
|
||||
let o;
|
||||
|
@ -11,10 +16,10 @@ function test_time_keyFromString(iterations) {
|
|||
let d = Utils.decodeKeyBase32("ababcdefabcdefabcdefabcdef");
|
||||
b.generateRandom();
|
||||
|
||||
_("Running " + iterations + " iterations of hmacKeyObject + sha256HMACBytes.");
|
||||
_("Running " + iterations + " iterations of hmacKeyObject + sha256HMAC.");
|
||||
for (let i = 0; i < iterations; ++i) {
|
||||
let k = b.hmacKeyObject;
|
||||
o = Utils.sha256HMACBytes(d, k);
|
||||
o = sha256HMAC(d, k);
|
||||
}
|
||||
do_check_true(!!o);
|
||||
_("Done.");
|
||||
|
@ -23,8 +28,8 @@ function test_time_keyFromString(iterations) {
|
|||
function test_repeated_hmac() {
|
||||
let testKey = "ababcdefabcdefabcdefabcdef";
|
||||
let k = Utils.makeHMACKey("foo");
|
||||
let one = Utils.sha256HMACBytes(Utils.decodeKeyBase32(testKey), k);
|
||||
let two = Utils.sha256HMACBytes(Utils.decodeKeyBase32(testKey), k);
|
||||
let one = sha256HMAC(Utils.decodeKeyBase32(testKey), k);
|
||||
let two = sha256HMAC(Utils.decodeKeyBase32(testKey), k);
|
||||
do_check_eq(one, two);
|
||||
}
|
||||
|
||||
|
@ -45,10 +50,10 @@ function test_keymanager() {
|
|||
|
||||
let sha256inputE = "" + HMAC_INPUT + username + "\x01";
|
||||
let key = Utils.makeHMACKey(Utils.decodeKeyBase32(testKey));
|
||||
let encryptKey = Utils.sha256HMACBytes(sha256inputE, key);
|
||||
let encryptKey = sha256HMAC(sha256inputE, key);
|
||||
|
||||
let sha256inputH = encryptKey + HMAC_INPUT + username + "\x02";
|
||||
let hmacKey = Utils.sha256HMACBytes(sha256inputH, key);
|
||||
let hmacKey = sha256HMAC(sha256inputH, key);
|
||||
|
||||
// Encryption key is stored in base64 for WeaveCrypto convenience.
|
||||
do_check_eq(btoa(encryptKey), new SyncKeyBundle(null, username, testKey).encryptionKey);
|
||||
|
|
|
@ -76,7 +76,7 @@ function test_resource_user_agent() {
|
|||
});
|
||||
}
|
||||
|
||||
Utils.asyncChain(
|
||||
Async.chain(
|
||||
test_fetchInfo,
|
||||
test_desktop_post,
|
||||
test_desktop_get,
|
||||
|
|
|
@ -29,10 +29,8 @@ add_test(function test_offline() {
|
|||
try {
|
||||
_("The right bits are set when we're offline.");
|
||||
Services.io.offline = true;
|
||||
do_check_eq(Service._ignorableErrorCount, 0);
|
||||
do_check_false(!!Service.login());
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
|
||||
do_check_eq(Service._ignorableErrorCount, 0);
|
||||
Services.io.offline = false;
|
||||
} finally {
|
||||
Svc.Prefs.resetBranch("");
|
||||
|
|
|
@ -12,6 +12,19 @@ Cu.import("resource://services-sync/status.js");
|
|||
Svc.DefaultPrefs.set("registerEngines", "");
|
||||
Cu.import("resource://services-sync/service.js");
|
||||
|
||||
function CatapultEngine() {
|
||||
SyncEngine.call(this, "Catapult");
|
||||
}
|
||||
CatapultEngine.prototype = {
|
||||
__proto__: SyncEngine.prototype,
|
||||
exception: null, // tests fill this in
|
||||
_sync: function _sync() {
|
||||
throw this.exception;
|
||||
}
|
||||
};
|
||||
|
||||
Engines.register(CatapultEngine);
|
||||
|
||||
function sync_httpd_setup() {
|
||||
let global = new ServerWBO("global", {
|
||||
syncID: Service.syncID,
|
||||
|
@ -30,7 +43,8 @@ function sync_httpd_setup() {
|
|||
"/1.1/johndoe/info/collections": collectionsHelper.handler,
|
||||
"/1.1/johndoe/storage/crypto/keys":
|
||||
upd("crypto", (new ServerWBO("keys")).handler()),
|
||||
"/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler())
|
||||
"/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler()),
|
||||
"/user/1.0/johndoe/node/weave": httpd_handler(200, "OK", "null")
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -43,7 +57,7 @@ function setUp() {
|
|||
generateNewKeys();
|
||||
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
|
||||
serverKeys.encrypt(Service.syncKeyBundle);
|
||||
return serverKeys.upload(Service.cryptoKeysURL);
|
||||
return serverKeys.upload(Service.cryptoKeysURL).success;
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
|
@ -485,3 +499,82 @@ add_test(function test_idle_adjustSyncInterval() {
|
|||
SyncScheduler.setDefaults();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_no_sync_node() {
|
||||
// Test when Status.sync == NO_SYNC_NODE_FOUND
|
||||
// it is not overwritten on sync:finish
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.serverURL = "http://localhost:8080/";
|
||||
|
||||
Service.sync();
|
||||
do_check_eq(Status.sync, NO_SYNC_NODE_FOUND);
|
||||
do_check_eq(SyncScheduler.syncTimer.delay, NO_SYNC_NODE_INTERVAL);
|
||||
|
||||
// Clean up.
|
||||
Service.startOver();
|
||||
Status.resetSync();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function test_sync_failed_partial_500s() {
|
||||
_("Test a 5xx status calls handleSyncError.");
|
||||
SyncScheduler._syncErrors = MAX_ERROR_COUNT_BEFORE_BACKOFF;
|
||||
let server = sync_httpd_setup();
|
||||
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = true;
|
||||
engine.exception = {status: 500};
|
||||
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
|
||||
do_check_true(setUp());
|
||||
|
||||
Service.sync();
|
||||
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
|
||||
let maxInterval = SyncScheduler._syncErrors * (2 * MINIMUM_BACKOFF_INTERVAL);
|
||||
do_check_eq(Status.backoffInterval, 0);
|
||||
do_check_true(Status.enforceBackoff);
|
||||
do_check_eq(SyncScheduler._syncErrors, 4);
|
||||
do_check_true(SyncScheduler.nextSync <= (Date.now() + maxInterval));
|
||||
do_check_true(SyncScheduler.syncTimer.delay <= maxInterval);
|
||||
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function test_sync_failed_partial_400s() {
|
||||
_("Test a non-5xx status doesn't call handleSyncError.");
|
||||
SyncScheduler._syncErrors = MAX_ERROR_COUNT_BEFORE_BACKOFF;
|
||||
let server = sync_httpd_setup();
|
||||
|
||||
let engine = Engines.get("catapult");
|
||||
engine.enabled = true;
|
||||
engine.exception = {status: 400};
|
||||
|
||||
// Have multiple devices for an active interval.
|
||||
Clients._store.create({id: "foo", cleartext: "bar"});
|
||||
|
||||
do_check_eq(Status.sync, SYNC_SUCCEEDED);
|
||||
|
||||
do_check_true(setUp());
|
||||
|
||||
Service.sync();
|
||||
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
do_check_eq(SyncScheduler.syncInterval, SyncScheduler.activeInterval);
|
||||
|
||||
do_check_eq(Status.backoffInterval, 0);
|
||||
do_check_false(Status.enforceBackoff);
|
||||
do_check_eq(SyncScheduler._syncErrors, 0);
|
||||
do_check_true(SyncScheduler.nextSync <= (Date.now() + SyncScheduler.activeInterval));
|
||||
do_check_true(SyncScheduler.syncTimer.delay <= SyncScheduler.activeInterval);
|
||||
|
||||
Status.resetSync();
|
||||
Service.startOver();
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
|
|
@ -59,6 +59,11 @@ let tc3 = {
|
|||
"9d201395faa4b61a96c8"
|
||||
};
|
||||
|
||||
function sha256HMAC(message, key) {
|
||||
let h = Utils.makeHMACHasher(Ci.nsICryptoHMAC.SHA256, key);
|
||||
return Utils.digestBytes(message, h);
|
||||
}
|
||||
|
||||
function _hexToString(hex) {
|
||||
let ret = "";
|
||||
if (hex.length % 2 != 0) {
|
||||
|
@ -75,8 +80,7 @@ function _hexToString(hex) {
|
|||
function extract_hex(salt, ikm) {
|
||||
salt = _hexToString(salt);
|
||||
ikm = _hexToString(ikm);
|
||||
return Utils.bytesAsHex(
|
||||
Utils.sha256HMACBytes(ikm, Utils.makeHMACKey(salt)));
|
||||
return Utils.bytesAsHex(sha256HMAC(ikm, Utils.makeHMACKey(salt)));
|
||||
}
|
||||
|
||||
function expand_hex(prk, info, len) {
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
let undef;
|
||||
|
||||
function run_test() {
|
||||
do_check_true(Utils.isArray([]));
|
||||
do_check_true(Utils.isArray([1, 2]));
|
||||
do_check_false(Utils.isArray({}));
|
||||
do_check_false(Utils.isArray(1.0));
|
||||
do_check_false(Utils.isArray("string"));
|
||||
do_check_false(Utils.isArray(null));
|
||||
do_check_false(Utils.isArray(undef));
|
||||
do_check_false(Utils.isArray(new Date()));
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function _hexToString(hex) {
|
||||
var ret = '';
|
||||
if (hex.length % 2 != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < hex.length; i += 2) {
|
||||
var cur = hex[i] + hex[i + 1];
|
||||
ret += String.fromCharCode(parseInt(cur, 16));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let test_data =
|
||||
[{test_case: 1,
|
||||
key: _hexToString("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
|
||||
key_len: 20,
|
||||
data: "Hi There",
|
||||
data_len: 8,
|
||||
digest: "b617318655057264e28bc0b6fb378c8ef146be00"},
|
||||
|
||||
{test_case: 2,
|
||||
key: "Jefe",
|
||||
key_len: 4,
|
||||
data: "what do ya want for nothing?",
|
||||
data_len: 28,
|
||||
digest: "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"}];
|
||||
|
||||
let d;
|
||||
// Testing repeated hashing.
|
||||
d = test_data[0];
|
||||
do_check_eq(Utils.bytesAsHex(Utils.sha1HMACBytes(d.data, Utils.makeHMACKey(d.key))), d.digest);
|
||||
d = test_data[1];
|
||||
do_check_eq(Utils.bytesAsHex(Utils.sha1HMACBytes(d.data, Utils.makeHMACKey(d.key))), d.digest);
|
||||
d = test_data[0];
|
||||
do_check_eq(Utils.bytesAsHex(Utils.sha1HMACBytes(d.data, Utils.makeHMACKey(d.key))), d.digest);
|
||||
d = test_data[1];
|
||||
do_check_eq(Utils.bytesAsHex(Utils.sha1HMACBytes(d.data, Utils.makeHMACKey(d.key))), d.digest);
|
||||
let kk = Utils.makeHMACKey(d.key);
|
||||
do_check_eq(
|
||||
Utils.bytesAsHex(
|
||||
Utils.sha1HMACBytes(
|
||||
Utils.sha1HMACBytes(
|
||||
Utils.sha1HMACBytes(d.data, kk),
|
||||
kk),
|
||||
kk)),
|
||||
Utils.bytesAsHex(
|
||||
Utils.sha1HMACBytes(
|
||||
Utils.sha1HMACBytes(
|
||||
Utils.sha1HMACBytes(d.data, kk),
|
||||
kk),
|
||||
kk)));
|
||||
|
||||
d = test_data[0];
|
||||
kk = Utils.makeHMACKey(d.key);
|
||||
do_check_eq(Utils.bytesAsHex(Utils.sha1HMACBytes(d.data, kk)), d.digest);
|
||||
do_check_eq(Utils.bytesAsHex(Utils.sha1HMACBytes(d.data, kk)), d.digest);
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
_("Make sure sha256 hmac works with various messages and keys");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
let key1 = Utils.makeHMACKey("key1");
|
||||
let key2 = Utils.makeHMACKey("key2");
|
||||
|
||||
let mes1 = "message 1";
|
||||
let mes2 = "message 2";
|
||||
|
||||
_("Make sure right sha256 hmacs are generated");
|
||||
let hmac11 = Utils.sha256HMAC(mes1, key1);
|
||||
do_check_eq(hmac11, "54f035bfbd6b44445d771c7c430e0753f1c00823974108fb4723703782552296");
|
||||
let hmac12 = Utils.sha256HMAC(mes1, key2);
|
||||
do_check_eq(hmac12, "1dbeae48de1b12f69517d828fb32969c74c8adc0715babc41b8f50254a980e70");
|
||||
let hmac21 = Utils.sha256HMAC(mes2, key1);
|
||||
do_check_eq(hmac21, "e00e91db4e86973868de8b3e818f4c968894d4135a3209bfea7b9e699484f07a");
|
||||
let hmac22 = Utils.sha256HMAC(mes2, key2);
|
||||
do_check_eq(hmac22, "4624312da31ada485b87beeecef0e5f0311cd5de60ea12291ce34cab158e0cc7");
|
||||
|
||||
_("Repeated hmacs shouldn't change the digest");
|
||||
do_check_eq(Utils.sha256HMAC(mes1, key1), hmac11);
|
||||
do_check_eq(Utils.sha256HMAC(mes1, key2), hmac12);
|
||||
do_check_eq(Utils.sha256HMAC(mes2, key1), hmac21);
|
||||
do_check_eq(Utils.sha256HMAC(mes2, key2), hmac22);
|
||||
|
||||
// RFC tests for SHA256-HMAC.
|
||||
let k1 = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
|
||||
let d1 = "\x48\x69\x20\x54\x68\x65\x72\x65";
|
||||
let o1 = "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7";
|
||||
|
||||
// Sample data for Marcus Wohlschon.
|
||||
let k2 = "78xR6gnAnBja7nYl6vkECo5bTlax5iHelP/jenj+dhQ=";
|
||||
let d2 = "4F5T+hK0VFBx880sYlMtfkBD2ZGe337tgbbQRTFxndFEgCC1fRrJkvzZ6Wytr+DySw3rxJ05O4Lqfn9F8Kxlvc4pcnAX//TK6MvRLs1NmcZr6HTo3NPurNB1VRTnJCE6";
|
||||
let o2 = "3dd17eb5091e0f2400a733f9e2cf8264d59206b6351078c2ce88499f1971f9b0";
|
||||
|
||||
do_check_eq(Utils.sha256HMACBytes(d1, Utils.makeHMACKey(k1)), o1);
|
||||
do_check_eq(Utils.sha256HMAC(d2, Utils.makeHMACKey(k2)), o2);
|
||||
|
||||
// Checking HMAC exceptions.
|
||||
let ex;
|
||||
try {
|
||||
Utils.throwHMACMismatch("aaa", "bbb");
|
||||
}
|
||||
catch (e) {
|
||||
ex = e;
|
||||
}
|
||||
do_check_true(Utils.isHMACMismatch(ex));
|
||||
do_check_false(!!Utils.isHMACMismatch(new Error()));
|
||||
do_check_false(!!Utils.isHMACMismatch(null));
|
||||
do_check_false(!!Utils.isHMACMismatch("Error"));
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
let input = [1, 2, 3, 4, 5];
|
||||
|
||||
let err;
|
||||
try {
|
||||
Utils.slices(input, 0).next();
|
||||
} catch (ex) {
|
||||
err = ex;
|
||||
}
|
||||
do_check_eq("Invalid slice size.", err);
|
||||
|
||||
err = undefined;
|
||||
try {
|
||||
Utils.slices(input).next();
|
||||
} catch (ex) {
|
||||
err = ex;
|
||||
}
|
||||
do_check_eq("Invalid slice size.", err);
|
||||
|
||||
function slurp(g) [x for each (x in g)]
|
||||
|
||||
let sliced1 = slurp(Utils.slices(input, 1));
|
||||
let sliced2 = slurp(Utils.slices(input, 2));
|
||||
let sliced3 = slurp(Utils.slices(input, 5));
|
||||
let sliced4 = slurp(Utils.slices(input, 7));
|
||||
|
||||
do_check_eq(sliced1.length, 5);
|
||||
do_check_eq(sliced2.length, 3);
|
||||
do_check_eq(sliced3.length, 1);
|
||||
do_check_eq(sliced4.length, 1);
|
||||
sliced1.every(function(x) x.length == 1);
|
||||
_(JSON.stringify(sliced2));
|
||||
do_check_eq(sliced2[0].length, 2);
|
||||
do_check_eq(sliced2[1].length, 2);
|
||||
do_check_eq(sliced2[2].length, 1);
|
||||
sliced3.every(function(x) x.length == 5);
|
||||
sliced4.every(function(x) x.length == 5);
|
||||
|
||||
let sliced5 = slurp(Utils.slices(["foo"], 50));
|
||||
do_check_eq(sliced5.length, 1);
|
||||
do_check_eq(sliced5[0], "foo");
|
||||
|
||||
let sliced6 = slurp(Utils.slices([], 50));
|
||||
do_check_eq(sliced6.length, 1);
|
||||
do_check_eq(sliced6[0].length, 0);
|
||||
}
|
|
@ -4,7 +4,7 @@ tail =
|
|||
|
||||
[test_Observers.js]
|
||||
[test_Preferences.js]
|
||||
[test_async_helpers.js]
|
||||
[test_async_chain.js]
|
||||
[test_async_querySpinningly.js]
|
||||
[test_auth_manager.js]
|
||||
[test_bookmark_batch_fail.js]
|
||||
|
@ -25,6 +25,15 @@ tail =
|
|||
[test_engine.js]
|
||||
[test_engine_abort.js]
|
||||
[test_enginemanager.js]
|
||||
[test_errorhandler.js]
|
||||
[test_errorhandler_filelog.js]
|
||||
# Bug 664090: this test persistently fails on Windows opt builds.
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = (os == "win" && !debug) || os == "android"
|
||||
[test_errorhandler_sync_checkServerError.js]
|
||||
# Bug 604565: this test intermittently hangs on OS X debug builds.
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = (os == "mac" && debug) || os == "android"
|
||||
[test_forms_store.js]
|
||||
[test_forms_tracker.js]
|
||||
[test_history_engine.js]
|
||||
|
@ -59,10 +68,6 @@ skip-if = os == "win" || os == "android"
|
|||
[test_service_cluster.js]
|
||||
[test_service_createAccount.js]
|
||||
[test_service_detect_upgrade.js]
|
||||
[test_service_filelog.js]
|
||||
# Bug 664090: this test persistently fails on Windows opt builds.
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = (os == "win" && !debug) || os == "android"
|
||||
[test_service_getStorageInfo.js]
|
||||
[test_service_login.js]
|
||||
[test_service_migratePrefs.js]
|
||||
|
@ -71,10 +76,6 @@ skip-if = (os == "win" && !debug) || os == "android"
|
|||
[test_service_startOver.js]
|
||||
[test_service_startup.js]
|
||||
[test_service_sync_401.js]
|
||||
[test_service_sync_checkServerError.js]
|
||||
# Bug 604565: this test intermittently hangs on OS X debug builds.
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = (os == "mac" && debug) || os == "android"
|
||||
[test_service_sync_locked.js]
|
||||
[test_service_sync_remoteSetup.js]
|
||||
# Bug 604565: this test intermittently hangs on OS X debug builds.
|
||||
|
@ -101,7 +102,6 @@ skip-if = (os == "mac" && debug) || os == "android"
|
|||
[test_tab_tracker.js]
|
||||
[test_tracker_addChanged.js]
|
||||
[test_upgrade_old_sync_key.js]
|
||||
[test_utils_asyncChain.js]
|
||||
[test_utils_atob.js]
|
||||
[test_utils_catch.js]
|
||||
[test_utils_deepCopy.js]
|
||||
|
@ -113,7 +113,6 @@ skip-if = (os == "mac" && debug) || os == "android"
|
|||
[test_utils_getErrorString.js]
|
||||
[test_utils_getIcon.js]
|
||||
[test_utils_hkdfExpand.js]
|
||||
[test_utils_isArray.js]
|
||||
[test_utils_json.js]
|
||||
[test_utils_lazyStrings.js]
|
||||
[test_utils_lock.js]
|
||||
|
@ -124,8 +123,5 @@ skip-if = (os == "mac" && debug) || os == "android"
|
|||
[test_utils_passphrase.js]
|
||||
[test_utils_pbkdf2.js]
|
||||
[test_utils_sha1.js]
|
||||
[test_utils_sha1hmac.js]
|
||||
[test_utils_sha256HMAC.js]
|
||||
[test_utils_slices.js]
|
||||
[test_utils_stackTrace.js]
|
||||
[test_utils_utf8.js]
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
resource mozmill resource/
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
/* debugging prefs */
|
||||
pref("browser.dom.window.dump.enabled", true);
|
||||
pref("javascript.options.showInConsole", true);
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0"?>
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>mozmill@mozilla.com</em:id>
|
||||
<em:name>MozMill</em:name>
|
||||
<em:version>2.0b1</em:version>
|
||||
<em:creator>Adam Christian</em:creator>
|
||||
<em:description>A testing extension based on the Windmill Testing Framework client source</em:description>
|
||||
<em:unpack>true</em:unpack>
|
||||
<em:targetApplication>
|
||||
<!-- Firefox -->
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>3.5</em:minVersion>
|
||||
<em:maxVersion>9.*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
<em:targetApplication>
|
||||
<!-- Thunderbird -->
|
||||
<Description>
|
||||
<em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
|
||||
<em:minVersion>3.0a1pre</em:minVersion>
|
||||
<em:maxVersion>9.*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
<em:targetApplication>
|
||||
<!-- Sunbird -->
|
||||
<Description>
|
||||
<em:id>{718e30fb-e89b-41dd-9da7-e25a45638b28}</em:id>
|
||||
<em:minVersion>0.6a1</em:minVersion>
|
||||
<em:maxVersion>1.0pre</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
<em:targetApplication>
|
||||
<!-- SeaMonkey -->
|
||||
<Description>
|
||||
<em:id>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</em:id>
|
||||
<em:minVersion>2.0a1</em:minVersion>
|
||||
<em:maxVersion>9.*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
<em:targetApplication>
|
||||
<!-- Songbird -->
|
||||
<Description>
|
||||
<em:id>songbird@songbirdnest.com</em:id>
|
||||
<em:minVersion>0.3pre</em:minVersion>
|
||||
<em:maxVersion>1.3.0a</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>toolkit@mozilla.org</em:id>
|
||||
<em:minVersion>1.9.1</em:minVersion>
|
||||
<em:maxVersion>9.*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
</RDF>
|
|
@ -0,0 +1,410 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is MozMill Test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Henrik Skupin <mail@hskupin.info> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Use the frame module of Mozmill to raise non-fatal failures
|
||||
var mozmillFrame = {};
|
||||
Cu.import('resource://mozmill/modules/frame.js', mozmillFrame);
|
||||
|
||||
|
||||
/**
|
||||
* @name assertions
|
||||
* @namespace Defines expect and assert methods to be used for assertions.
|
||||
*/
|
||||
var assertions = exports;
|
||||
|
||||
|
||||
/* non-fatal assertions */
|
||||
var Expect = function() {}
|
||||
|
||||
Expect.prototype = {
|
||||
|
||||
/**
|
||||
* Log a test as failing by adding a fail frame.
|
||||
*
|
||||
* @param {object} aResult
|
||||
* Test result details used for reporting.
|
||||
* <dl>
|
||||
* <dd>fileName</dd>
|
||||
* <dt>Name of the file in which the assertion failed.</dt>
|
||||
* <dd>function</dd>
|
||||
* <dt>Function in which the assertion failed.</dt>
|
||||
* <dd>lineNumber</dd>
|
||||
* <dt>Line number of the file in which the assertion failed.</dt>
|
||||
* <dd>message</dd>
|
||||
* <dt>Message why the assertion failed.</dt>
|
||||
* </dl>
|
||||
*/
|
||||
_logFail: function Expect__logFail(aResult) {
|
||||
mozmillFrame.events.fail({fail: aResult});
|
||||
},
|
||||
|
||||
/**
|
||||
* Log a test as passing by adding a pass frame.
|
||||
*
|
||||
* @param {object} aResult
|
||||
* Test result details used for reporting.
|
||||
* <dl>
|
||||
* <dd>fileName</dd>
|
||||
* <dt>Name of the file in which the assertion failed.</dt>
|
||||
* <dd>function</dd>
|
||||
* <dt>Function in which the assertion failed.</dt>
|
||||
* <dd>lineNumber</dd>
|
||||
* <dt>Line number of the file in which the assertion failed.</dt>
|
||||
* <dd>message</dd>
|
||||
* <dt>Message why the assertion failed.</dt>
|
||||
* </dl>
|
||||
*/
|
||||
_logPass: function Expect__logPass(aResult) {
|
||||
mozmillFrame.events.pass({pass: aResult});
|
||||
},
|
||||
|
||||
/**
|
||||
* Test the condition and mark test as passed or failed
|
||||
*
|
||||
* @param {boolean} aCondition
|
||||
* Condition to test.
|
||||
* @param {string} aMessage
|
||||
* Message to show for the test result
|
||||
* @param {string} aDiagnosis
|
||||
* Diagnose message to show for the test result
|
||||
* @returns {boolean} Result of the test.
|
||||
*/
|
||||
_test: function Expect__test(aCondition, aMessage, aDiagnosis) {
|
||||
let diagnosis = aDiagnosis || "";
|
||||
let message = aMessage || "";
|
||||
|
||||
if (diagnosis)
|
||||
message = aMessage ? message + " - " + diagnosis : diagnosis;
|
||||
|
||||
// Build result data
|
||||
let frame = Components.stack;
|
||||
let result = {
|
||||
'fileName' : frame.filename.replace(/(.*)-> /, ""),
|
||||
'function' : frame.name,
|
||||
'lineNumber' : frame.lineNumber,
|
||||
'message' : message
|
||||
};
|
||||
|
||||
// Log test result
|
||||
if (aCondition)
|
||||
this._logPass(result);
|
||||
else
|
||||
this._logFail(result);
|
||||
|
||||
return aCondition;
|
||||
},
|
||||
|
||||
/**
|
||||
* Perform an always passing test
|
||||
*
|
||||
* @param {string} aMessage
|
||||
* Message to show for the test result.
|
||||
* @returns {boolean} Always returns true.
|
||||
*/
|
||||
pass: function Expect_pass(aMessage) {
|
||||
return this._test(true, aMessage, undefined);
|
||||
},
|
||||
|
||||
/**
|
||||
* Perform an always failing test
|
||||
*
|
||||
* @param {string} aMessage
|
||||
* Message to show for the test result.
|
||||
* @returns {boolean} Always returns false.
|
||||
*/
|
||||
fail: function Expect_fail(aMessage) {
|
||||
return this._test(false, aMessage, undefined);
|
||||
},
|
||||
|
||||
/**
|
||||
* Test if the value pass
|
||||
*
|
||||
* @param {boolean|string|number|object} aValue
|
||||
* Value to test.
|
||||
* @param {string} aMessage
|
||||
* Message to show for the test result.
|
||||
* @returns {boolean} Result of the test.
|
||||
*/
|
||||
ok: function Expect_ok(aValue, aMessage) {
|
||||
let condition = !!aValue;
|
||||
let diagnosis = "got '" + aValue + "'";
|
||||
|
||||
return this._test(condition, aMessage, diagnosis);
|
||||
},
|
||||
|
||||
/**
|
||||
* Test if both specified values are identical.
|
||||
*
|
||||
* @param {boolean|string|number|object} aValue
|
||||
* Value to test.
|
||||
* @param {boolean|string|number|object} aExpected
|
||||
* Value to strictly compare with.
|
||||
* @param {string} aMessage
|
||||
* Message to show for the test result
|
||||
* @returns {boolean} Result of the test.
|
||||
*/
|
||||
equal: function Expect_equal(aValue, aExpected, aMessage) {
|
||||
let condition = (aValue === aExpected);
|
||||
let diagnosis = "got '" + aValue + "', expected '" + aExpected + "'";
|
||||
|
||||
return this._test(condition, aMessage, diagnosis);
|
||||
},
|
||||
|
||||
/**
|
||||
* Test if both specified values are not identical.
|
||||
*
|
||||
* @param {boolean|string|number|object} aValue
|
||||
* Value to test.
|
||||
* @param {boolean|string|number|object} aExpected
|
||||
* Value to strictly compare with.
|
||||
* @param {string} aMessage
|
||||
* Message to show for the test result
|
||||
* @returns {boolean} Result of the test.
|
||||
*/
|
||||
notEqual: function Expect_notEqual(aValue, aExpected, aMessage) {
|
||||
let condition = (aValue !== aExpected);
|
||||
let diagnosis = "got '" + aValue + "', not expected '" + aExpected + "'";
|
||||
|
||||
return this._test(condition, aMessage, diagnosis);
|
||||
},
|
||||
|
||||
/**
|
||||
* Test if the regular expression matches the string.
|
||||
*
|
||||
* @param {string} aString
|
||||
* String to test.
|
||||
* @param {RegEx} aRegex
|
||||
* Regular expression to use for testing that a match exists.
|
||||
* @param {string} aMessage
|
||||
* Message to show for the test result
|
||||
* @returns {boolean} Result of the test.
|
||||
*/
|
||||
match: function Expect_match(aString, aRegex, aMessage) {
|
||||
// XXX Bug 634948
|
||||
// Regex objects are transformed to strings when evaluated in a sandbox
|
||||
// For now lets re-create the regex from its string representation
|
||||
let pattern = flags = "";
|
||||
try {
|
||||
let matches = aRegex.toString().match(/\/(.*)\/(.*)/);
|
||||
|
||||
pattern = matches[1];
|
||||
flags = matches[2];
|
||||
}
|
||||
catch (ex) {
|
||||
}
|
||||
|
||||
let regex = new RegExp(pattern, flags);
|
||||
let condition = (aString.match(regex) !== null);
|
||||
let diagnosis = "'" + regex + "' matches for '" + aString + "'";
|
||||
|
||||
return this._test(condition, aMessage, diagnosis);
|
||||
},
|
||||
|
||||
/**
|
||||
* Test if the regular expression does not match the string.
|
||||
*
|
||||
* @param {string} aString
|
||||
* String to test.
|
||||
* @param {RegEx} aRegex
|
||||
* Regular expression to use for testing that a match does not exist.
|
||||
* @param {string} aMessage
|
||||
* Message to show for the test result
|
||||
* @returns {boolean} Result of the test.
|
||||
*/
|
||||
notMatch: function Expect_notMatch(aString, aRegex, aMessage) {
|
||||
// XXX Bug 634948
|
||||
// Regex objects are transformed to strings when evaluated in a sandbox
|
||||
// For now lets re-create the regex from its string representation
|
||||
let pattern = flags = "";
|
||||
try {
|
||||
let matches = aRegex.toString().match(/\/(.*)\/(.*)/);
|
||||
|
||||
pattern = matches[1];
|
||||
flags = matches[2];
|
||||
}
|
||||
catch (ex) {
|
||||
}
|
||||
|
||||
let regex = new RegExp(pattern, flags);
|
||||
let condition = (aString.match(regex) === null);
|
||||
let diagnosis = "'" + regex + "' doesn't match for '" + aString + "'";
|
||||
|
||||
return this._test(condition, aMessage, diagnosis);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Test if a code block throws an exception.
|
||||
*
|
||||
* @param {string} block
|
||||
* function to call to test for exception
|
||||
* @param {RegEx} error
|
||||
* the expected error class
|
||||
* @param {string} message
|
||||
* message to present if assertion fails
|
||||
* @returns {boolean} Result of the test.
|
||||
*/
|
||||
throws : function Expect_throws(block, /*optional*/error, /*optional*/message) {
|
||||
return this._throws.apply(this, [true].concat(Array.prototype.slice.call(arguments)));
|
||||
},
|
||||
|
||||
/**
|
||||
* Test if a code block doesn't throw an exception.
|
||||
*
|
||||
* @param {string} block
|
||||
* function to call to test for exception
|
||||
* @param {RegEx} error
|
||||
* the expected error class
|
||||
* @param {string} message
|
||||
* message to present if assertion fails
|
||||
* @returns {boolean} Result of the test.
|
||||
*/
|
||||
doesNotThrow : function Expect_doesNotThrow(block, /*optional*/error, /*optional*/message) {
|
||||
return this._throws.apply(this, [false].concat(Array.prototype.slice.call(arguments)));
|
||||
},
|
||||
|
||||
/* Tests whether a code block throws the expected exception
|
||||
class. helper for throws() and doesNotThrow()
|
||||
|
||||
adapted from node.js's assert._throws()
|
||||
https://github.com/joyent/node/blob/master/lib/assert.js
|
||||
*/
|
||||
_throws : function Expect__throws(shouldThrow, block, expected, message) {
|
||||
var actual;
|
||||
|
||||
if (typeof expected === 'string') {
|
||||
message = expected;
|
||||
expected = null;
|
||||
}
|
||||
|
||||
try {
|
||||
block();
|
||||
} catch (e) {
|
||||
actual = e;
|
||||
}
|
||||
|
||||
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
|
||||
(message ? ' ' + message : '.');
|
||||
|
||||
if (shouldThrow && !actual) {
|
||||
return this._test(false, message, 'Missing expected exception');
|
||||
}
|
||||
|
||||
if (!shouldThrow && this._expectedException(actual, expected)) {
|
||||
return this._test(false, message, 'Got unwanted exception');
|
||||
}
|
||||
|
||||
if ((shouldThrow && actual && expected &&
|
||||
!this._expectedException(actual, expected)) || (!shouldThrow && actual)) {
|
||||
throw actual;
|
||||
}
|
||||
return this._test(true, message);
|
||||
},
|
||||
|
||||
_expectedException : function Expect__expectedException(actual, expected) {
|
||||
if (!actual || !expected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expected instanceof RegExp) {
|
||||
return expected.test(actual);
|
||||
} else if (actual instanceof expected) {
|
||||
return true;
|
||||
} else if (expected.call({}, actual) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AssertionError
|
||||
*
|
||||
* Error object thrown by failing assertions
|
||||
*/
|
||||
function AssertionError(message, fileName, lineNumber) {
|
||||
var err = new Error();
|
||||
if (err.stack) {
|
||||
this.stack = err.stack;
|
||||
}
|
||||
this.message = message === undefined ? err.message : message;
|
||||
this.fileName = fileName === undefined ? err.fileName : fileName;
|
||||
this.lineNumber = lineNumber === undefined ? err.lineNumber : lineNumber;
|
||||
};
|
||||
AssertionError.prototype = new Error();
|
||||
AssertionError.prototype.constructor = AssertionError;
|
||||
AssertionError.prototype.name = 'AssertionError';
|
||||
|
||||
|
||||
var Assert = function() {}
|
||||
|
||||
Assert.prototype = new Expect();
|
||||
|
||||
Assert.prototype.AssertionError = AssertionError;
|
||||
|
||||
/**
|
||||
* The Assert class implements fatal assertions, and can be used in cases
|
||||
* when a failing test has to directly abort the current test function. All
|
||||
* remaining tasks will not be performed.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Log a test as failing by throwing an AssertionException.
|
||||
*
|
||||
* @param {object} aResult
|
||||
* Test result details used for reporting.
|
||||
* <dl>
|
||||
* <dd>fileName</dd>
|
||||
* <dt>Name of the file in which the assertion failed.</dt>
|
||||
* <dd>function</dd>
|
||||
* <dt>Function in which the assertion failed.</dt>
|
||||
* <dd>lineNumber</dd>
|
||||
* <dt>Line number of the file in which the assertion failed.</dt>
|
||||
* <dd>message</dd>
|
||||
* <dt>Message why the assertion failed.</dt>
|
||||
* </dl>
|
||||
* @throws {AssertionError }
|
||||
*/
|
||||
Assert.prototype._logFail = function Assert__logFail(aResult) {
|
||||
throw new AssertionError(aResult);
|
||||
}
|
||||
|
||||
|
||||
// Export of variables
|
||||
assertions.Expect = Expect;
|
||||
assertions.Assert = Assert;
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,478 @@
|
|||
// ***** BEGIN LICENSE BLOCK *****// ***** BEGIN LICENSE BLOCK *****
|
||||
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public License Version
|
||||
// 1.1 (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
// http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS" basis,
|
||||
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
// for the specific language governing rights and limitations under the
|
||||
// License.
|
||||
//
|
||||
// The Original Code is Mozilla Corporation Code.
|
||||
//
|
||||
// The Initial Developer of the Original Code is
|
||||
// Adam Christian.
|
||||
// Portions created by the Initial Developer are Copyright (C) 2008
|
||||
// the Initial Developer. All Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
// Adam Christian <adam.christian@gmail.com>
|
||||
// Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
// in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
// of those above. If you wish to allow use of your version of this file only
|
||||
// under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
// use your version of this file under the terms of the MPL, indicate your
|
||||
// decision by deleting the provisions above and replace them with the notice
|
||||
// and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
// the provisions above, a recipient may use your version of this file under
|
||||
// the terms of any one of the MPL, the GPL or the LGPL.
|
||||
//
|
||||
// ***** END LICENSE BLOCK *****
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Elem", "ID", "Link", "XPath", "Selector", "Name", "Anon", "AnonXPath",
|
||||
"Lookup", "_byID", "_byName", "_byAttrib", "_byAnonAttrib",
|
||||
];
|
||||
|
||||
var utils = {}; Components.utils.import('resource://mozmill/modules/utils.js', utils);
|
||||
var strings = {}; Components.utils.import('resource://mozmill/stdlib/strings.js', strings);
|
||||
var arrays = {}; Components.utils.import('resource://mozmill/stdlib/arrays.js', arrays);
|
||||
var json2 = {}; Components.utils.import('resource://mozmill/stdlib/json2.js', json2);
|
||||
var withs = {}; Components.utils.import('resource://mozmill/stdlib/withs.js', withs);
|
||||
var dom = {}; Components.utils.import('resource://mozmill/stdlib/dom.js', dom);
|
||||
var objects = {}; Components.utils.import('resource://mozmill/stdlib/objects.js', objects);
|
||||
|
||||
var countQuotes = function(str){
|
||||
var count = 0;
|
||||
var i = 0;
|
||||
while(i < str.length) {
|
||||
i = str.indexOf('"', i);
|
||||
if (i != -1) {
|
||||
count++;
|
||||
i++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
/**
|
||||
* smartSplit()
|
||||
*
|
||||
* Takes a lookup string as input and returns
|
||||
* a list of each node in the string
|
||||
*/
|
||||
var smartSplit = function (str) {
|
||||
// Ensure we have an even number of quotes
|
||||
if (countQuotes(str) % 2 != 0) {
|
||||
throw new Error ("Invalid Lookup Expression");
|
||||
}
|
||||
|
||||
/**
|
||||
* This regex matches a single "node" in a lookup string.
|
||||
* In otherwords, it matches the part between the two '/'s
|
||||
*
|
||||
* Regex Explanation:
|
||||
* \/ - start matching at the first forward slash
|
||||
* ([^\/"]*"[^"]*")* - match as many pairs of quotes as possible until we hit a slash (ignore slashes inside quotes)
|
||||
* [^\/]* - match the remainder of text outside of last quote but before next slash
|
||||
*/
|
||||
var re = /\/([^\/"]*"[^"]*")*[^\/]*/g
|
||||
var ret = []
|
||||
var match = re.exec(str);
|
||||
while (match != null) {
|
||||
ret.push(match[0].replace(/^\//, ""));
|
||||
match = re.exec(str);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* defaultDocuments()
|
||||
*
|
||||
* Returns a list of default documents in which to search for elements
|
||||
* if no document is provided
|
||||
*/
|
||||
function defaultDocuments() {
|
||||
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator);
|
||||
win = windowManager.getMostRecentWindow("navigator:browser");
|
||||
return [win.gBrowser.selectedBrowser.contentDocument, win.document];
|
||||
};
|
||||
|
||||
/**
|
||||
* nodeSearch()
|
||||
*
|
||||
* Takes an optional document, callback and locator string
|
||||
* Returns a handle to the located element or null
|
||||
*/
|
||||
function nodeSearch(doc, func, string) {
|
||||
if (doc != undefined) {
|
||||
var documents = [doc];
|
||||
} else {
|
||||
var documents = defaultDocuments();
|
||||
}
|
||||
var e = null;
|
||||
var element = null;
|
||||
//inline function to recursively find the element in the DOM, cross frame.
|
||||
var search = function(win, func, string) {
|
||||
if (win == null)
|
||||
return;
|
||||
|
||||
//do the lookup in the current window
|
||||
element = func.call(win, string);
|
||||
|
||||
if (!element || (element.length == 0)) {
|
||||
var frames = win.frames;
|
||||
for (var i=0; i < frames.length; i++) {
|
||||
search(frames[i], func, string);
|
||||
}
|
||||
}
|
||||
else { e = element; }
|
||||
};
|
||||
|
||||
for (var i = 0; i < documents.length; ++i) {
|
||||
var win = documents[i].defaultView;
|
||||
search(win, func, string);
|
||||
if (e) break;
|
||||
}
|
||||
return e;
|
||||
};
|
||||
|
||||
/**
|
||||
* Selector()
|
||||
*
|
||||
* Finds an element by selector string
|
||||
*/
|
||||
function Selector(_document, selector, index) {
|
||||
if (selector == undefined) {
|
||||
throw new Error('Selector constructor did not recieve enough arguments.');
|
||||
}
|
||||
this.selector = selector;
|
||||
this.getNodeForDocument = function (s) {
|
||||
return this.document.querySelectorAll(s);
|
||||
};
|
||||
var nodes = nodeSearch(_document, this.getNodeForDocument, this.selector);
|
||||
return nodes ? nodes[index || 0] : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* ID()
|
||||
*
|
||||
* Finds an element by ID
|
||||
*/
|
||||
function ID(_document, nodeID) {
|
||||
if (nodeID == undefined) {
|
||||
throw new Error('ID constructor did not recieve enough arguments.');
|
||||
}
|
||||
this.getNodeForDocument = function (nodeID) {
|
||||
return this.document.getElementById(nodeID);
|
||||
};
|
||||
return nodeSearch(_document, this.getNodeForDocument, nodeID);
|
||||
};
|
||||
|
||||
/**
|
||||
* Link()
|
||||
*
|
||||
* Finds a link by innerHTML
|
||||
*/
|
||||
function Link(_document, linkName) {
|
||||
if (linkName == undefined) {
|
||||
throw new Error('Link constructor did not recieve enough arguments.');
|
||||
}
|
||||
|
||||
this.getNodeForDocument = function (linkName) {
|
||||
var getText = function(el){
|
||||
var text = "";
|
||||
if (el.nodeType == 3){ //textNode
|
||||
if (el.data != undefined){
|
||||
text = el.data;
|
||||
} else {
|
||||
text = el.innerHTML;
|
||||
}
|
||||
text = text.replace(/n|r|t/g, " ");
|
||||
}
|
||||
if (el.nodeType == 1){ //elementNode
|
||||
for (var i = 0; i < el.childNodes.length; i++) {
|
||||
var child = el.childNodes.item(i);
|
||||
text += getText(child);
|
||||
}
|
||||
if (el.tagName == "P" || el.tagName == "BR" || el.tagName == "HR" || el.tagName == "DIV") {
|
||||
text += "n";
|
||||
}
|
||||
}
|
||||
return text;
|
||||
};
|
||||
|
||||
//sometimes the windows won't have this function
|
||||
try {
|
||||
var links = this.document.getElementsByTagName('a'); }
|
||||
catch(err){ // ADD LOG LINE mresults.write('Error: '+ err, 'lightred');
|
||||
}
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
var el = links[i];
|
||||
//if (getText(el).indexOf(this.linkName) != -1) {
|
||||
if (el.innerHTML.indexOf(linkName) != -1){
|
||||
return el;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return nodeSearch(_document, this.getNodeForDocument, linkName);
|
||||
};
|
||||
|
||||
/**
|
||||
* XPath()
|
||||
*
|
||||
* Finds an element by XPath
|
||||
*/
|
||||
function XPath(_document, expr) {
|
||||
if (expr == undefined) {
|
||||
throw new Error('XPath constructor did not recieve enough arguments.');
|
||||
}
|
||||
|
||||
this.getNodeForDocument = function (s) {
|
||||
var aNode = this.document;
|
||||
var aExpr = s;
|
||||
var xpe = null;
|
||||
|
||||
if (this.document.defaultView == null) {
|
||||
xpe = new getMethodInWindows('XPathEvaluator')();
|
||||
} else {
|
||||
xpe = new this.document.defaultView.XPathEvaluator();
|
||||
}
|
||||
var nsResolver = xpe.createNSResolver(aNode.ownerDocument == null ? aNode.documentElement : aNode.ownerDocument.documentElement);
|
||||
var result = xpe.evaluate(aExpr, aNode, nsResolver, 0, null);
|
||||
var found = [];
|
||||
var res;
|
||||
while (res = result.iterateNext())
|
||||
found.push(res);
|
||||
return found[0];
|
||||
};
|
||||
return nodeSearch(_document, this.getNodeForDocument, expr);
|
||||
};
|
||||
|
||||
/**
|
||||
* Name()
|
||||
*
|
||||
* Finds an element by Name
|
||||
*/
|
||||
function Name(_document, nName) {
|
||||
if (nName == undefined) {
|
||||
throw new Error('Name constructor did not recieve enough arguments.');
|
||||
}
|
||||
this.getNodeForDocument = function (s) {
|
||||
try{
|
||||
var els = this.document.getElementsByName(s);
|
||||
if (els.length > 0) { return els[0]; }
|
||||
}
|
||||
catch(err){};
|
||||
return null;
|
||||
};
|
||||
return nodeSearch(_document, this.getNodeForDocument, nName);
|
||||
};
|
||||
|
||||
|
||||
var _returnResult = function (results) {
|
||||
if (results.length == 0) {
|
||||
return null
|
||||
} else if (results.length == 1) {
|
||||
return results[0];
|
||||
} else {
|
||||
return results;
|
||||
}
|
||||
}
|
||||
var _forChildren = function (element, name, value) {
|
||||
var results = [];
|
||||
var nodes = [e for each (e in element.childNodes) if (e)]
|
||||
for (var i in nodes) {
|
||||
var n = nodes[i];
|
||||
if (n[name] == value) {
|
||||
results.push(n);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
var _forAnonChildren = function (_document, element, name, value) {
|
||||
var results = [];
|
||||
var nodes = [e for each (e in _document.getAnoymousNodes(element)) if (e)];
|
||||
for (var i in nodes ) {
|
||||
var n = nodes[i];
|
||||
if (n[name] == value) {
|
||||
results.push(n);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
var _byID = function (_document, parent, value) {
|
||||
return _returnResult(_forChildren(parent, 'id', value));
|
||||
}
|
||||
var _byName = function (_document, parent, value) {
|
||||
return _returnResult(_forChildren(parent, 'tagName', value));
|
||||
}
|
||||
var _byAttrib = function (parent, attributes) {
|
||||
var results = [];
|
||||
|
||||
var nodes = parent.childNodes;
|
||||
for (var i in nodes) {
|
||||
var n = nodes[i];
|
||||
requirementPass = 0;
|
||||
requirementLength = 0;
|
||||
for (var a in attributes) {
|
||||
requirementLength++;
|
||||
try {
|
||||
if (n.getAttribute(a) == attributes[a]) {
|
||||
requirementPass++;
|
||||
}
|
||||
} catch (err) {
|
||||
// Workaround any bugs in custom attribute crap in XUL elements
|
||||
}
|
||||
}
|
||||
if (requirementPass == requirementLength) {
|
||||
results.push(n);
|
||||
}
|
||||
}
|
||||
return _returnResult(results)
|
||||
}
|
||||
var _byAnonAttrib = function (_document, parent, attributes) {
|
||||
var results = [];
|
||||
|
||||
if (objects.getLength(attributes) == 1) {
|
||||
for (var i in attributes) {var k = i; var v = attributes[i]; }
|
||||
var result = _document.getAnonymousElementByAttribute(parent, k, v)
|
||||
if (result) {
|
||||
return result;
|
||||
|
||||
}
|
||||
}
|
||||
var nodes = [n for each (n in _document.getAnonymousNodes(parent)) if (n.getAttribute)];
|
||||
function resultsForNodes (nodes) {
|
||||
for (var i in nodes) {
|
||||
var n = nodes[i];
|
||||
requirementPass = 0;
|
||||
requirementLength = 0;
|
||||
for (var a in attributes) {
|
||||
requirementLength++;
|
||||
if (n.getAttribute(a) == attributes[a]) {
|
||||
requirementPass++;
|
||||
}
|
||||
}
|
||||
if (requirementPass == requirementLength) {
|
||||
results.push(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
resultsForNodes(nodes)
|
||||
if (results.length == 0) {
|
||||
resultsForNodes([n for each (n in parent.childNodes) if (n != undefined && n.getAttribute)])
|
||||
}
|
||||
return _returnResult(results)
|
||||
}
|
||||
var _byIndex = function (_document, parent, i) {
|
||||
if (parent instanceof Array) {
|
||||
return parent[i];
|
||||
}
|
||||
return parent.childNodes[i];
|
||||
}
|
||||
var _anonByName = function (_document, parent, value) {
|
||||
return _returnResult(_forAnonChildren(_document, parent, 'tagName', value));
|
||||
}
|
||||
var _anonByAttrib = function (_document, parent, value) {
|
||||
return _byAnonAttrib(_document, parent, value);
|
||||
}
|
||||
var _anonByIndex = function (_document, parent, i) {
|
||||
return _document.getAnonymousNodes(parent)[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup()
|
||||
*
|
||||
* Finds an element by Lookup expression
|
||||
*/
|
||||
function Lookup (_document, expression) {
|
||||
if (expression == undefined) {
|
||||
throw new Error('Lookup constructor did not recieve enough arguments.');
|
||||
}
|
||||
|
||||
var expSplit = [e for each (e in smartSplit(expression) ) if (e != '')];
|
||||
expSplit.unshift(_document)
|
||||
var nCases = {'id':_byID, 'name':_byName, 'attrib':_byAttrib, 'index':_byIndex};
|
||||
var aCases = {'name':_anonByName, 'attrib':_anonByAttrib, 'index':_anonByIndex};
|
||||
|
||||
|
||||
var reduceLookup = function (parent, exp) {
|
||||
// Handle case where only index is provided
|
||||
var cases = nCases;
|
||||
|
||||
// Handle ending index before any of the expression gets mangled
|
||||
if (withs.endsWith(exp, ']')) {
|
||||
var expIndex = json2.JSON.parse(strings.vslice(exp, '[', ']'));
|
||||
}
|
||||
// Handle anon
|
||||
if (withs.startsWith(exp, 'anon')) {
|
||||
var exp = strings.vslice(exp, '(', ')');
|
||||
var cases = aCases;
|
||||
}
|
||||
if (withs.startsWith(exp, '[')) {
|
||||
try {
|
||||
var obj = json2.JSON.parse(strings.vslice(exp, '[', ']'));
|
||||
} catch (err) {
|
||||
throw new Error(err+'. String to be parsed was || '+strings.vslice(exp, '[', ']')+' ||');
|
||||
}
|
||||
var r = cases['index'](_document, parent, obj);
|
||||
if (r == null) {
|
||||
throw new Error('Expression "'+exp+'" returned null. Anonymous == '+(cases == aCases));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
for (var c in cases) {
|
||||
if (withs.startsWith(exp, c)) {
|
||||
try {
|
||||
var obj = json2.JSON.parse(strings.vslice(exp, '(', ')'))
|
||||
} catch(err) {
|
||||
throw new Error(err+'. String to be parsed was || '+strings.vslice(exp, '(', ')')+' ||');
|
||||
}
|
||||
var result = cases[c](_document, parent, obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
if ( withs.startsWith(exp, '{') ) {
|
||||
try {
|
||||
var obj = json2.JSON.parse(exp)
|
||||
} catch(err) {
|
||||
throw new Error(err+'. String to be parsed was || '+exp+' ||');
|
||||
}
|
||||
|
||||
if (cases == aCases) {
|
||||
var result = _anonByAttrib(_document, parent, obj)
|
||||
} else {
|
||||
var result = _byAttrib(parent, obj)
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
throw new Error('Expression "'+exp+'" returned null. Anonymous == '+(cases == aCases));
|
||||
}
|
||||
}
|
||||
|
||||
// Final return
|
||||
if (expIndex) {
|
||||
// TODO: Check length and raise error
|
||||
return result[expIndex];
|
||||
} else {
|
||||
// TODO: Check length and raise error
|
||||
return result;
|
||||
}
|
||||
// Maybe we should cause an exception here
|
||||
return false;
|
||||
};
|
||||
return expSplit.reduce(reduceLookup);
|
||||
};
|
|
@ -0,0 +1,595 @@
|
|||
// ***** BEGIN LICENSE BLOCK *****// ***** BEGIN LICENSE BLOCK *****
|
||||
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public License Version
|
||||
// 1.1 (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
// http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS" basis,
|
||||
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
// for the specific language governing rights and limitations under the
|
||||
// License.
|
||||
//
|
||||
// The Original Code is Mozilla Corporation Code.
|
||||
//
|
||||
// The Initial Developer of the Original Code is
|
||||
// Mikeal Rogers.
|
||||
// Portions created by the Initial Developer are Copyright (C) 2008
|
||||
// the Initial Developer. All Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
// Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
// in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
// of those above. If you wish to allow use of your version of this file only
|
||||
// under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
// use your version of this file under the terms of the MPL, indicate your
|
||||
// decision by deleting the provisions above and replace them with the notice
|
||||
// and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
// the provisions above, a recipient may use your version of this file under
|
||||
// the terms of any one of the MPL, the GPL or the LGPL.
|
||||
//
|
||||
// ***** END LICENSE BLOCK *****
|
||||
|
||||
var EXPORTED_SYMBOLS = ['loadFile','Collector','Runner','events',
|
||||
'jsbridge', 'runTestFile', 'log', 'getThread',
|
||||
'timers', 'persisted'];
|
||||
|
||||
var httpd = {}; Components.utils.import('resource://mozmill/stdlib/httpd.js', httpd);
|
||||
var os = {}; Components.utils.import('resource://mozmill/stdlib/os.js', os);
|
||||
var strings = {}; Components.utils.import('resource://mozmill/stdlib/strings.js', strings);
|
||||
var arrays = {}; Components.utils.import('resource://mozmill/stdlib/arrays.js', arrays);
|
||||
var withs = {}; Components.utils.import('resource://mozmill/stdlib/withs.js', withs);
|
||||
var utils = {}; Components.utils.import('resource://mozmill/modules/utils.js', utils);
|
||||
var securableModule = {}; Components.utils.import('resource://mozmill/stdlib/securable-module.js', securableModule);
|
||||
|
||||
var aConsoleService = Components.classes["@mozilla.org/consoleservice;1"].
|
||||
getService(Components.interfaces.nsIConsoleService);
|
||||
var ios = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
var subscriptLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Components.interfaces.mozIJSSubScriptLoader);
|
||||
var uuidgen = Components.classes["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Components.interfaces.nsIUUIDGenerator);
|
||||
|
||||
var persisted = {};
|
||||
|
||||
var moduleLoader = new securableModule.Loader({
|
||||
rootPaths: ["resource://mozmill/modules/"],
|
||||
defaultPrincipal: "system",
|
||||
globals : { Cc: Components.classes,
|
||||
Ci: Components.interfaces,
|
||||
Cu: Components.utils,
|
||||
Cr: Components.results}
|
||||
});
|
||||
|
||||
arrayRemove = function(array, from, to) {
|
||||
var rest = array.slice((to || from) + 1 || array.length);
|
||||
array.length = from < 0 ? array.length + from : from;
|
||||
return array.push.apply(array, rest);
|
||||
};
|
||||
|
||||
mozmill = undefined; mozelement = undefined;
|
||||
|
||||
var loadTestResources = function () {
|
||||
// load resources we want in our tests
|
||||
if (mozmill == undefined) {
|
||||
mozmill = {};
|
||||
Components.utils.import("resource://mozmill/modules/mozmill.js", mozmill);
|
||||
}
|
||||
if (mozelement == undefined) {
|
||||
mozelement = {};
|
||||
Components.utils.import("resource://mozmill/modules/mozelement.js", mozelement);
|
||||
}
|
||||
}
|
||||
|
||||
var loadFile = function(path, collector) {
|
||||
// load a test module from a file and add some candy
|
||||
var file = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
file.initWithPath(path);
|
||||
var uri = ios.newFileURI(file).spec;
|
||||
|
||||
loadTestResources();
|
||||
var assertions = moduleLoader.require("./assertions");
|
||||
var module = {
|
||||
collector: collector,
|
||||
mozmill: mozmill,
|
||||
elementslib: mozelement,
|
||||
findElement: mozelement,
|
||||
persisted: persisted,
|
||||
Cc: Components.classes,
|
||||
Ci: Components.interfaces,
|
||||
Cu: Components.utils,
|
||||
Cr: Components.results,
|
||||
log: log,
|
||||
assert: new assertions.Assert(),
|
||||
expect: new assertions.Expect()
|
||||
}
|
||||
|
||||
module.require = function (mod) {
|
||||
var loader = new securableModule.Loader({
|
||||
rootPaths: [ios.newFileURI(file.parent).spec,
|
||||
"resource://mozmill/modules/"],
|
||||
defaultPrincipal: "system",
|
||||
globals : { mozmill: mozmill,
|
||||
elementslib: mozelement, // This a quick hack to maintain backwards compatibility with 1.5.x
|
||||
findElement: mozelement,
|
||||
persisted: persisted,
|
||||
Cc: Components.classes,
|
||||
Ci: Components.interfaces,
|
||||
Cu: Components.utils,
|
||||
log: log }
|
||||
});
|
||||
return loader.require(mod);
|
||||
}
|
||||
|
||||
if (collector != undefined) {
|
||||
collector.current_file = file;
|
||||
collector.current_path = path;
|
||||
}
|
||||
try {
|
||||
subscriptLoader.loadSubScript(uri, module, "UTF-8");
|
||||
} catch(e) {
|
||||
events.fail(e);
|
||||
var obj = {
|
||||
'filename':path,
|
||||
'passed':false,
|
||||
'failed':true,
|
||||
'passes':0,
|
||||
'fails' :1,
|
||||
'name' :'Unknown Test',
|
||||
};
|
||||
events.fireEvent('endTest', obj);
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
|
||||
module.__file__ = path;
|
||||
module.__uri__ = uri;
|
||||
return module;
|
||||
}
|
||||
|
||||
function stateChangeBase (possibilties, restrictions, target, cmeta, v) {
|
||||
if (possibilties) {
|
||||
if (!arrays.inArray(possibilties, v)) {
|
||||
// TODO Error value not in this.poss
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (restrictions) {
|
||||
for (var i in restrictions) {
|
||||
var r = restrictions[i];
|
||||
if (!r(v)) {
|
||||
// TODO error value did not pass restriction
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fire jsbridge notification, logging notification, listener notifications
|
||||
events[target] = v;
|
||||
events.fireEvent(cmeta, target);
|
||||
}
|
||||
|
||||
timers = [];
|
||||
|
||||
var events = {
|
||||
'currentState' : null,
|
||||
'currentModule': null,
|
||||
'currentTest' : null,
|
||||
'userShutdown' : false,
|
||||
'appQuit' : false,
|
||||
'listeners' : {},
|
||||
}
|
||||
events.setState = function (v) {
|
||||
return stateChangeBase(['dependencies', 'setupModule', 'teardownModule',
|
||||
'setupTest', 'teardownTest', 'test', 'collection'],
|
||||
null, 'currentState', 'setState', v);
|
||||
}
|
||||
events.toggleUserShutdown = function (obj){
|
||||
if (this.userShutdown) {
|
||||
this.fail({'function':'frame.events.toggleUserShutdown', 'message':'Shutdown expected but none detected before timeout', 'userShutdown': obj});
|
||||
}
|
||||
this.userShutdown = obj;
|
||||
}
|
||||
events.isUserShutdown = function () {
|
||||
return Boolean(this.userShutdown);
|
||||
}
|
||||
events.setTest = function (test, invokedFromIDE) {
|
||||
test.__passes__ = [];
|
||||
test.__fails__ = [];
|
||||
test.__invokedFromIDE__ = invokedFromIDE;
|
||||
events.currentTest = test;
|
||||
test.__start__ = Date.now();
|
||||
var obj = {'filename':events.currentModule.__file__,
|
||||
'name':test.__name__,
|
||||
}
|
||||
events.fireEvent('setTest', obj);
|
||||
}
|
||||
events.endTest = function (test) {
|
||||
// report the end of a test
|
||||
test.status = 'done';
|
||||
events.currentTest = null;
|
||||
test.__end__ = Date.now();
|
||||
var obj = {'filename':events.currentModule.__file__,
|
||||
'passed':test.__passes__.length,
|
||||
'failed':test.__fails__.length,
|
||||
'passes':test.__passes__,
|
||||
'fails' :test.__fails__,
|
||||
'name' :test.__name__,
|
||||
'time_start':test.__start__,
|
||||
'time_end':test.__end__
|
||||
}
|
||||
if (test.skipped) {
|
||||
obj['skipped'] = true;
|
||||
obj.skipped_reason = test.skipped_reason;
|
||||
}
|
||||
if (test.meta) {
|
||||
obj.meta = test.meta;
|
||||
}
|
||||
|
||||
// Report the test result only if the test is a true test or if it is a
|
||||
// failing setup/teardown
|
||||
var shouldSkipReporting = false;
|
||||
if (test.__passes__ &&
|
||||
(test.__name__ == 'setupModule' ||
|
||||
test.__name__ == 'setupTest' ||
|
||||
test.__name__ == 'teardownTest' ||
|
||||
test.__name__ == 'teardownModule')) {
|
||||
shouldSkipReporting = true;
|
||||
}
|
||||
|
||||
if (!shouldSkipReporting) {
|
||||
events.fireEvent('endTest', obj);
|
||||
}
|
||||
}
|
||||
|
||||
events.setModule = function (v) {
|
||||
return stateChangeBase( null, [function (v) {return (v.__file__ != undefined)}],
|
||||
'currentModule', 'setModule', v);
|
||||
}
|
||||
|
||||
events.pass = function (obj) {
|
||||
// a low level event, such as a keystroke, succeeds
|
||||
if (events.currentTest) {
|
||||
events.currentTest.__passes__.push(obj);
|
||||
}
|
||||
for each(var timer in timers) {
|
||||
timer.actions.push(
|
||||
{"currentTest":events.currentModule.__file__+"::"+events.currentTest.__name__, "obj":obj,
|
||||
"result":"pass"}
|
||||
);
|
||||
}
|
||||
events.fireEvent('pass', obj);
|
||||
}
|
||||
events.fail = function (obj) {
|
||||
var error = obj.exception;
|
||||
if(error) {
|
||||
// Error objects aren't enumerable https://bugzilla.mozilla.org/show_bug.cgi?id=637207
|
||||
obj.exception = {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
lineNumber: error.lineNumber,
|
||||
fileName: error.fileName,
|
||||
stack: error.stack
|
||||
};
|
||||
}
|
||||
// a low level event, such as a keystroke, fails
|
||||
if (events.currentTest) {
|
||||
events.currentTest.__fails__.push(obj);
|
||||
}
|
||||
for each(var time in timers) {
|
||||
timer.actions.push(
|
||||
{"currentTest":events.currentModule.__file__+"::"+events.currentTest.__name__, "obj":obj,
|
||||
"result":"fail"}
|
||||
);
|
||||
}
|
||||
events.fireEvent('fail', obj);
|
||||
}
|
||||
events.skip = function (reason) {
|
||||
// this is used to report skips associated with setupModule and setupTest
|
||||
// and nothing else
|
||||
events.currentTest.skipped = true;
|
||||
events.currentTest.skipped_reason = reason;
|
||||
for each(var timer in timers) {
|
||||
timer.actions.push(
|
||||
{"currentTest":events.currentModule.__file__+"::"+events.currentTest.__name__, "obj":reason,
|
||||
"result":"skip"}
|
||||
);
|
||||
}
|
||||
events.fireEvent('skip', reason);
|
||||
}
|
||||
events.fireEvent = function (name, obj) {
|
||||
if (this.listeners[name]) {
|
||||
for (var i in this.listeners[name]) {
|
||||
this.listeners[name][i](obj);
|
||||
}
|
||||
}
|
||||
for each(var listener in this.globalListeners) {
|
||||
listener(name, obj);
|
||||
}
|
||||
}
|
||||
events.globalListeners = [];
|
||||
events.addListener = function (name, listener) {
|
||||
if (this.listeners[name]) {
|
||||
this.listeners[name].push(listener);
|
||||
} else if (name =='') {
|
||||
this.globalListeners.push(listener)
|
||||
} else {
|
||||
this.listeners[name] = [listener];
|
||||
}
|
||||
}
|
||||
events.removeListener = function(listener) {
|
||||
for (var listenerIndex in this.listeners) {
|
||||
var e = this.listeners[listenerIndex];
|
||||
for (var i in e){
|
||||
if (e[i] == listener) {
|
||||
this.listeners[listenerIndex] = arrayRemove(e, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i in this.globalListeners) {
|
||||
if (this.globalListeners[i] == listener) {
|
||||
this.globalListeners = arrayRemove(this.globalListeners, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var log = function (obj) {
|
||||
events.fireEvent('log', obj);
|
||||
}
|
||||
|
||||
try {
|
||||
var jsbridge = {}; Components.utils.import('resource://jsbridge/modules/events.js', jsbridge);
|
||||
} catch(err) {
|
||||
var jsbridge = null;
|
||||
|
||||
aConsoleService.logStringMessage("jsbridge not available.");
|
||||
}
|
||||
|
||||
if (jsbridge) {
|
||||
events.addListener('', function (name, obj) {jsbridge.fireEvent('mozmill.'+name, obj)} );
|
||||
}
|
||||
|
||||
function Collector () {
|
||||
// the collector handles HTTPD and initilizing the module
|
||||
this.test_modules_by_filename = {};
|
||||
this.testing = [];
|
||||
this.httpd_started = false;
|
||||
this.http_port = 43336;
|
||||
this.http_server = httpd.getServer(this.http_port);
|
||||
}
|
||||
|
||||
Collector.prototype.startHttpd = function () {
|
||||
while (this.httpd == undefined) {
|
||||
try {
|
||||
this.http_server.start(this.http_port);
|
||||
this.httpd = this.http_server;
|
||||
} catch(e) { // Failure most likely due to port conflict
|
||||
this.http_port++;
|
||||
this.http_server = httpd.getServer(this.http_port);
|
||||
};
|
||||
}
|
||||
}
|
||||
Collector.prototype.stopHttpd = function () {
|
||||
if (this.httpd) {
|
||||
this.httpd.stop(function(){}); // Callback needed to pause execution until the server has been properly shutdown
|
||||
this.httpd = null;
|
||||
}
|
||||
}
|
||||
Collector.prototype.addHttpResource = function (directory, ns) {
|
||||
if (!this.httpd) {
|
||||
this.startHttpd();
|
||||
}
|
||||
|
||||
if (!ns) {
|
||||
ns = '/';
|
||||
} else {
|
||||
ns = '/' + ns + '/';
|
||||
}
|
||||
|
||||
var lp = Components.classes["@mozilla.org/file/local;1"].
|
||||
createInstance(Components.interfaces.nsILocalFile);
|
||||
lp.initWithPath(os.abspath(directory, this.current_file));
|
||||
this.httpd.registerDirectory(ns, lp);
|
||||
|
||||
return 'http://localhost:' + this.http_port + ns
|
||||
}
|
||||
|
||||
Collector.prototype.initTestModule = function (filename, name) {
|
||||
var test_module = loadFile(filename, this);
|
||||
test_module.__tests__ = [];
|
||||
for (var i in test_module) {
|
||||
if (typeof(test_module[i]) == "function") {
|
||||
test_module[i].__name__ = i;
|
||||
if (i == "setupTest") {
|
||||
test_module.__setupTest__ = test_module[i];
|
||||
} else if (i == "setupModule") {
|
||||
test_module.__setupModule__ = test_module[i];
|
||||
} else if (i == "teardownTest") {
|
||||
test_module.__teardownTest__ = test_module[i];
|
||||
} else if (i == "teardownModule") {
|
||||
test_module.__teardownModule__ = test_module[i];
|
||||
} else if (withs.startsWith(i, "test")) {
|
||||
if (name && (i != name)) {
|
||||
continue;
|
||||
}
|
||||
name = null;
|
||||
test_module.__tests__.push(test_module[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test_module.collector = this;
|
||||
test_module.status = 'loaded';
|
||||
this.test_modules_by_filename[filename] = test_module;
|
||||
return test_module;
|
||||
}
|
||||
|
||||
// Observer which gets notified when the application quits
|
||||
function AppQuitObserver() {
|
||||
this.register();
|
||||
}
|
||||
AppQuitObserver.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
events.appQuit = true;
|
||||
},
|
||||
register: function() {
|
||||
var obsService = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
obsService.addObserver(this, "quit-application", false);
|
||||
},
|
||||
unregister: function() {
|
||||
var obsService = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
obsService.removeObserver(this, "quit-application");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Runner (collector, invokedFromIDE) {
|
||||
this.collector = collector;
|
||||
this.invokedFromIDE = invokedFromIDE
|
||||
events.fireEvent('startRunner', true);
|
||||
var m = {}; Components.utils.import('resource://mozmill/modules/mozmill.js', m);
|
||||
this.platform = m.platform;
|
||||
}
|
||||
|
||||
Runner.prototype.runTestFile = function (filename, name) {
|
||||
this.collector.initTestModule(filename, name);
|
||||
this.runTestModule(this.collector.test_modules_by_filename[filename]);
|
||||
}
|
||||
Runner.prototype.end = function () {
|
||||
try {
|
||||
events.fireEvent('persist', persisted);
|
||||
} catch(e) {
|
||||
events.fireEvent('error', "persist serialization failed.");
|
||||
}
|
||||
this.collector.stopHttpd();
|
||||
events.fireEvent('endRunner', true);
|
||||
}
|
||||
|
||||
Runner.prototype.wrapper = function (func, arg) {
|
||||
thread = Components.classes["@mozilla.org/thread-manager;1"]
|
||||
.getService(Components.interfaces.nsIThreadManager)
|
||||
.currentThread;
|
||||
|
||||
// skip excluded platforms
|
||||
if (func.EXCLUDED_PLATFORMS != undefined) {
|
||||
if (arrays.inArray(func.EXCLUDED_PLATFORMS, this.platform)) {
|
||||
events.skip("Platform exclusion");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// skip function if requested
|
||||
if (func.__force_skip__ != undefined) {
|
||||
events.skip(func.__force_skip__);
|
||||
return;
|
||||
}
|
||||
|
||||
// execute the test function
|
||||
try {
|
||||
if (arg) {
|
||||
func(arg);
|
||||
} else {
|
||||
func();
|
||||
}
|
||||
|
||||
// If a user shutdown was expected but the application hasn't quit, throw a failure
|
||||
if (events.isUserShutdown()) {
|
||||
utils.sleep(500); // Prevents race condition between mozrunner hard process kill and normal FFx shutdown
|
||||
if (events.userShutdown['user'] && !events.appQuit) {
|
||||
events.fail({'function':'Runner.wrapper',
|
||||
'message':'Shutdown expected but none detected before end of test',
|
||||
'userShutdown': events.userShutdown});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Allow the exception if a user shutdown was expected
|
||||
if (!events.isUserShutdown()) {
|
||||
events.fail({'exception': e, 'test':func})
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Runner.prototype.runTestModule = function (module) {
|
||||
events.setModule(module);
|
||||
module.__status__ = 'running';
|
||||
if (module.__setupModule__) {
|
||||
events.setState('setupModule');
|
||||
events.setTest(module.__setupModule__);
|
||||
this.wrapper(module.__setupModule__, module);
|
||||
var setupModulePassed = (events.currentTest.__fails__.length == 0 && !events.currentTest.skipped);
|
||||
events.endTest(module.__setupModule__);
|
||||
} else {
|
||||
var setupModulePassed = true;
|
||||
}
|
||||
if (setupModulePassed) {
|
||||
var observer = new AppQuitObserver();
|
||||
for (var i in module.__tests__) {
|
||||
events.appQuit = false;
|
||||
var test = module.__tests__[i];
|
||||
|
||||
// TODO: introduce per-test timeout:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=574871
|
||||
|
||||
if (module.__setupTest__) {
|
||||
events.setState('setupTest');
|
||||
events.setTest(module.__setupTest__);
|
||||
this.wrapper(module.__setupTest__, test);
|
||||
var setupTestPassed = (events.currentTest.__fails__.length == 0 && !events.currentTest.skipped);
|
||||
events.endTest(module.__setupTest__);
|
||||
} else {
|
||||
var setupTestPassed = true;
|
||||
}
|
||||
events.setState('test');
|
||||
events.setTest(test, this.invokedFromIDE);
|
||||
if (setupTestPassed) {
|
||||
this.wrapper(test);
|
||||
if (events.userShutdown && !events.userShutdown['user']) {
|
||||
events.endTest(test);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
events.skip("setupTest failed.");
|
||||
}
|
||||
if (module.__teardownTest__) {
|
||||
events.setState('teardownTest');
|
||||
events.setTest(module.__teardownTest__);
|
||||
this.wrapper(module.__teardownTest__, test);
|
||||
events.endTest(module.__teardownTest__);
|
||||
}
|
||||
events.endTest(test)
|
||||
}
|
||||
observer.unregister();
|
||||
} else {
|
||||
for each(var test in module.__tests__) {
|
||||
events.setTest(test);
|
||||
events.skip("setupModule failed.");
|
||||
events.endTest(test);
|
||||
}
|
||||
}
|
||||
if (module.__teardownModule__) {
|
||||
events.setState('teardownModule');
|
||||
events.setTest(module.__teardownModule__);
|
||||
this.wrapper(module.__teardownModule__, module);
|
||||
events.endTest(module.__teardownModule__);
|
||||
}
|
||||
module.__status__ = 'done';
|
||||
}
|
||||
|
||||
var runTestFile = function (filename, invokedFromIDE, name) {
|
||||
var runner = new Runner(new Collector(), invokedFromIDE);
|
||||
runner.runTestFile(filename, name);
|
||||
runner.end();
|
||||
return true;
|
||||
}
|
||||
|
||||
var getThread = function () {
|
||||
return thread;
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Adam Christian.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Adam Christian <adam.christian@gmail.com>
|
||||
* Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||
* Henrik Skupin <hskupin@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var frame = {}; Components.utils.import('resource://mozmill/modules/frame.js', frame);
|
||||
|
||||
/**
|
||||
* Console listener which listens for error messages in the console and forwards
|
||||
* them to the Mozmill reporting system for output.
|
||||
*/
|
||||
function ConsoleListener() {
|
||||
this.register();
|
||||
}
|
||||
ConsoleListener.prototype = {
|
||||
observe: function(aMessage) {
|
||||
var msg = aMessage.message;
|
||||
var re = /^\[.*Error:.*(chrome|resource):\/\/.*/i;
|
||||
if (msg.match(re)) {
|
||||
frame.events.fail(aMessage);
|
||||
}
|
||||
},
|
||||
QueryInterface: function (iid) {
|
||||
if (!iid.equals(Components.interfaces.nsIConsoleListener) && !iid.equals(Components.interfaces.nsISupports)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
register: function() {
|
||||
var aConsoleService = Components.classes["@mozilla.org/consoleservice;1"]
|
||||
.getService(Components.interfaces.nsIConsoleService);
|
||||
aConsoleService.registerListener(this);
|
||||
},
|
||||
unregister: function() {
|
||||
var aConsoleService = Components.classes["@mozilla.org/consoleservice;1"]
|
||||
.getService(Components.interfaces.nsIConsoleService);
|
||||
aConsoleService.unregisterListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
// start listening
|
||||
var consoleListener = new ConsoleListener();
|
||||
|
||||
var EXPORTED_SYMBOLS = ["mozmill"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
var mozmill = Cu.import('resource://mozmill/modules/mozmill.js');
|
||||
|
||||
// Observer for new top level windows
|
||||
var windowObserver = {
|
||||
observe: function(subject, topic, data) {
|
||||
attachEventListeners(subject);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Attach event listeners
|
||||
*/
|
||||
function attachEventListeners(window) {
|
||||
// These are the event handlers
|
||||
function pageShowHandler(event) {
|
||||
var doc = event.originalTarget;
|
||||
var tab = window.gBrowser.getBrowserForDocument(doc);
|
||||
|
||||
if (tab) {
|
||||
//log("*** Loaded tab: location=" + doc.location + ", baseURI=" + doc.baseURI + "\n");
|
||||
tab.mozmillDocumentLoaded = true;
|
||||
} else {
|
||||
//log("*** Loaded HTML location=" + doc.location + ", baseURI=" + doc.baseURI + "\n");
|
||||
doc.defaultView.mozmillDocumentLoaded = true;
|
||||
}
|
||||
|
||||
// We need to add/remove the unload/pagehide event listeners to preserve caching.
|
||||
window.gBrowser.addEventListener("beforeunload", beforeUnloadHandler, true);
|
||||
window.gBrowser.addEventListener("pagehide", pageHideHandler, true);
|
||||
};
|
||||
|
||||
var DOMContentLoadedHandler = function(event) {
|
||||
var errorRegex = /about:.+(error)|(blocked)\?/;
|
||||
if (errorRegex.exec(event.target.baseURI)) {
|
||||
// Wait about 1s to be sure the DOM is ready
|
||||
mozmill.utils.sleep(1000);
|
||||
|
||||
var tab = window.gBrowser.getBrowserForDocument(event.target);
|
||||
if (tab)
|
||||
tab.mozmillDocumentLoaded = true;
|
||||
|
||||
// We need to add/remove the unload event listener to preserve caching.
|
||||
window.gBrowser.addEventListener("beforeunload", beforeUnloadHandler, true);
|
||||
}
|
||||
};
|
||||
|
||||
// beforeunload is still needed because pagehide doesn't fire before the page is unloaded.
|
||||
// still use pagehide for cases when beforeunload doesn't get fired
|
||||
function beforeUnloadHandler(event) {
|
||||
var doc = event.originalTarget;
|
||||
var tab = window.gBrowser.getBrowserForDocument(event.target);
|
||||
|
||||
if (tab) {
|
||||
//log("*** Unload tab: location=" + doc.location + ", baseURI=" + doc.baseURI + "\n");
|
||||
tab.mozmillDocumentLoaded = false;
|
||||
} else {
|
||||
//log("*** Unload HTML location=" + doc.location + ", baseURI=" + doc.baseURI + "\n");
|
||||
doc.defaultView.mozmillDocumentLoaded = false;
|
||||
}
|
||||
|
||||
window.gBrowser.removeEventListener("beforeunload", beforeUnloadHandler, true);
|
||||
};
|
||||
|
||||
var pageHideHandler = function(event) {
|
||||
// If event.persisted is false, the beforeUnloadHandler should fire
|
||||
// and there is no need for this event handler.
|
||||
if (event.persisted) {
|
||||
var doc = event.originalTarget;
|
||||
var tab = window.gBrowser.getBrowserForDocument(event.target);
|
||||
|
||||
if (tab) {
|
||||
//log("*** Unload tab: location=" + doc.location + ", baseURI=" + doc.baseURI + "\n");
|
||||
tab.mozmillDocumentLoaded = false;
|
||||
} else {
|
||||
//log("*** Unload HTML location=" + doc.location + ", baseURI=" + doc.baseURI + "\n");
|
||||
doc.defaultView.mozmillDocumentLoaded = false;
|
||||
}
|
||||
|
||||
window.gBrowser.removeEventListener("beforeunload", beforeUnloadHandler, true);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Add the event handlers to the tabbedbrowser once its window has loaded
|
||||
window.addEventListener("load", function(event) {
|
||||
window.mozmillDocumentLoaded = true;
|
||||
|
||||
|
||||
if (window.gBrowser) {
|
||||
// Page is ready
|
||||
window.gBrowser.addEventListener("pageshow", pageShowHandler, true);
|
||||
|
||||
// Note: Error pages will never fire a "load" event. For those we
|
||||
// have to wait for the "DOMContentLoaded" event. That's the final state.
|
||||
// Error pages will always have a baseURI starting with
|
||||
// "about:" followed by "error" or "blocked".
|
||||
window.gBrowser.addEventListener("DOMContentLoaded", DOMContentLoadedHandler, true);
|
||||
|
||||
// Leave page (use caching)
|
||||
window.gBrowser.addEventListener("pagehide", pageHideHandler, true);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Mozmill
|
||||
*/
|
||||
function initialize() {
|
||||
// Activate observer for new top level windows
|
||||
var observerService = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
observerService.addObserver(windowObserver, "toplevel-window-ready", false);
|
||||
|
||||
// Attach event listeners to all open windows
|
||||
var enumerator = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator).getEnumerator("");
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var win = enumerator.getNext();
|
||||
attachEventListeners(win);
|
||||
|
||||
// For windows or dialogs already open we have to explicitly set the property
|
||||
// otherwise windows which load really quick never gets the property set and
|
||||
// we fail to create the controller
|
||||
win.mozmillDocumentLoaded = true;
|
||||
};
|
||||
}
|
||||
|
||||
initialize();
|
||||
|
|
@ -0,0 +1,396 @@
|
|||
// ***** BEGIN LICENSE BLOCK *****
|
||||
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public License Version
|
||||
// 1.1 (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
// http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS" basis,
|
||||
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
// for the specific language governing rights and limitations under the
|
||||
// License.
|
||||
//
|
||||
// The Original Code is Mozilla Corporation Code.
|
||||
//
|
||||
// The Initial Developer of the Original Code is
|
||||
// Mikeal Rogers.
|
||||
// Portions created by the Initial Developer are Copyright (C) 2008
|
||||
// the Initial Developer. All Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
// Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
// in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
// of those above. If you wish to allow use of your version of this file only
|
||||
// under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
// use your version of this file under the terms of the MPL, indicate your
|
||||
// decision by deleting the provisions above and replace them with the notice
|
||||
// and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
// the provisions above, a recipient may use your version of this file under
|
||||
// the terms of any one of the MPL, the GPL or the LGPL.
|
||||
//
|
||||
// ***** END LICENSE BLOCK *****
|
||||
|
||||
var EXPORTED_SYMBOLS = ["inspectElement"]
|
||||
|
||||
var elementslib = {}; Components.utils.import('resource://mozmill/modules/elementslib.js', elementslib);
|
||||
var mozmill = {}; Components.utils.import('resource://mozmill/modules/mozmill.js', mozmill);
|
||||
var utils = {}; Components.utils.import('resource://mozmill/modules/utils.js', utils);
|
||||
|
||||
var arrays = {}; Components.utils.import('resource://mozmill/stdlib/arrays.js', arrays);
|
||||
var dom = {}; Components.utils.import('resource://mozmill/stdlib/dom.js', dom);
|
||||
var objects = {}; Components.utils.import('resource://mozmill/stdlib/objects.js', objects);
|
||||
var json2 = {}; Components.utils.import('resource://mozmill/stdlib/json2.js', json2);
|
||||
var withs = {}; Components.utils.import('resource://mozmill/stdlib/withs.js', withs);
|
||||
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
|
||||
var isNotAnonymous = function (elem, result) {
|
||||
if (result == undefined) {
|
||||
var result = true;
|
||||
}
|
||||
if ( elem.parentNode ) {
|
||||
var p = elem.parentNode;
|
||||
return isNotAnonymous(p, result == arrays.inArray(p.childNodes, elem) == true);
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
var elemIsAnonymous = function (elem) {
|
||||
if (elem.getAttribute('anonid') || !arrays.inArray(elem.parentNode.childNodes, elem)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var getXPath = function (node, path) {
|
||||
path = path || [];
|
||||
|
||||
if(node.parentNode) {
|
||||
path = getXPath(node.parentNode, path);
|
||||
}
|
||||
|
||||
if(node.previousSibling) {
|
||||
var count = 1;
|
||||
var sibling = node.previousSibling
|
||||
do {
|
||||
if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {count++;}
|
||||
sibling = sibling.previousSibling;
|
||||
} while(sibling);
|
||||
if(count == 1) {count = null;}
|
||||
} else if(node.nextSibling) {
|
||||
var sibling = node.nextSibling;
|
||||
do {
|
||||
if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {
|
||||
var count = 1;
|
||||
sibling = null;
|
||||
} else {
|
||||
var count = null;
|
||||
sibling = sibling.previousSibling;
|
||||
}
|
||||
} while(sibling);
|
||||
}
|
||||
|
||||
if(node.nodeType == 1) {
|
||||
// if ($('absXpaths').checked){
|
||||
path.push(node.nodeName.toLowerCase() + (node.id ? "[@id='"+node.id+"']" : count > 0 ? "["+count+"]" : ''));
|
||||
// }
|
||||
// else{
|
||||
// path.push(node.nodeName.toLowerCase() + (node.id ? "" : count > 0 ? "["+count+"]" : ''));
|
||||
// }
|
||||
}
|
||||
return path;
|
||||
};
|
||||
|
||||
function getXSPath(node){
|
||||
var xpArray = getXPath(node);
|
||||
var stringXpath = xpArray.join('/');
|
||||
stringXpath = '/'+stringXpath;
|
||||
stringXpath = stringXpath.replace('//','/');
|
||||
return stringXpath;
|
||||
}
|
||||
function getXULXpath (el, xml) {
|
||||
var xpath = '';
|
||||
var pos, tempitem2;
|
||||
|
||||
while(el !== xml.documentElement) {
|
||||
pos = 0;
|
||||
tempitem2 = el;
|
||||
while(tempitem2) {
|
||||
if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) {
|
||||
// If it is ELEMENT_NODE of the same name
|
||||
pos += 1;
|
||||
}
|
||||
tempitem2 = tempitem2.previousSibling;
|
||||
}
|
||||
|
||||
xpath = "*[name()='"+el.nodeName+"' and namespace-uri()='"+(el.namespaceURI===null?'':el.namespaceURI)+"']["+pos+']'+'/'+xpath;
|
||||
|
||||
el = el.parentNode;
|
||||
}
|
||||
xpath = '/*'+"[name()='"+xml.documentElement.nodeName+"' and namespace-uri()='"+(el.namespaceURI===null?'':el.namespaceURI)+"']"+'/'+xpath;
|
||||
xpath = xpath.replace(/\/$/, '');
|
||||
return xpath;
|
||||
}
|
||||
|
||||
var getDocument = function (elem) {
|
||||
while (elem.parentNode) {
|
||||
var elem = elem.parentNode;
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
var getTopWindow = function(doc) {
|
||||
return utils.getChromeWindow(doc.defaultView);
|
||||
}
|
||||
|
||||
var attributeToIgnore = ['focus', 'focused', 'selected', 'select', 'flex', // General Omissions
|
||||
'linkedpanel', 'last-tab', 'afterselected', // From Tabs UI, thanks Farhad
|
||||
'style', // Gets set dynamically all the time, also effected by dx display code
|
||||
];
|
||||
|
||||
var getUniqueAttributesReduction = function (attributes, node) {
|
||||
for (var i in attributes) {
|
||||
if ( node.getAttribute(i) == attributes[i] || arrays.inArray(attributeToIgnore, i) || arrays.inArray(attributeToIgnore, attributes[i]) || i == 'id') {
|
||||
delete attributes[i];
|
||||
}
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
var getLookupExpression = function (_document, elem) {
|
||||
expArray = [];
|
||||
while ( elem.parentNode ) {
|
||||
var exp = getLookupForElem(_document, elem);
|
||||
expArray.push(exp);
|
||||
var elem = elem.parentNode;
|
||||
}
|
||||
expArray.reverse();
|
||||
return '/' + expArray.join('/');
|
||||
}
|
||||
|
||||
var getLookupForElem = function (_document, elem) {
|
||||
if ( !elemIsAnonymous(elem) ) {
|
||||
if (elem.id != "" && !withs.startsWith(elem.id, 'panel')) {
|
||||
identifier = {'name':'id', 'value':elem.id};
|
||||
} else if ((elem.name != "") && (typeof(elem.name) != "undefined")) {
|
||||
identifier = {'name':'name', 'value':elem.name};
|
||||
} else {
|
||||
identifier = null;
|
||||
}
|
||||
|
||||
if (identifier) {
|
||||
var result = {'id':elementslib._byID, 'name':elementslib._byName}[identifier.name](_document, elem.parentNode, identifier.value);
|
||||
if ( typeof(result != 'array') ) {
|
||||
return identifier.name+'('+json2.JSON.stringify(identifier.value)+')';
|
||||
}
|
||||
}
|
||||
|
||||
// At this point there is either no identifier or it returns multiple
|
||||
var parse = [n for each (n in elem.parentNode.childNodes) if
|
||||
(n.getAttribute && n != elem)
|
||||
];
|
||||
parse.unshift(dom.getAttributes(elem));
|
||||
var uniqueAttributes = parse.reduce(getUniqueAttributesReduction);
|
||||
|
||||
if (!result) {
|
||||
var result = elementslib._byAttrib(elem.parentNode, uniqueAttributes);
|
||||
}
|
||||
|
||||
if (!identifier && typeof(result) == 'array' ) {
|
||||
return json2.JSON.stringify(uniqueAttributes) + '['+arrays.indexOf(result, elem)+']'
|
||||
} else {
|
||||
var aresult = elementslib._byAttrib(elem.parentNode, uniqueAttributes);
|
||||
if ( typeof(aresult != 'array') ) {
|
||||
if (objects.getLength(uniqueAttributes) == 0) {
|
||||
return '['+arrays.indexOf(elem.parentNode.childNodes, elem)+']'
|
||||
}
|
||||
return json2.JSON.stringify(uniqueAttributes)
|
||||
} else if ( result.length > aresult.length ) {
|
||||
return json2.JSON.stringify(uniqueAttributes) + '['+arrays.indexOf(aresult, elem)+']'
|
||||
} else {
|
||||
return identifier.name+'('+json2.JSON.stringify(identifier.value)+')' + '['+arrays.indexOf(result, elem)+']'
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Handle Anonymous Nodes
|
||||
var parse = [n for each (n in _document.getAnonymousNodes(elem.parentNode)) if
|
||||
(n.getAttribute && n != elem)
|
||||
];
|
||||
parse.unshift(dom.getAttributes(elem));
|
||||
var uniqueAttributes = parse.reduce(getUniqueAttributesReduction);
|
||||
if (uniqueAttributes.anonid && typeof(elementslib._byAnonAttrib(_document,
|
||||
elem.parentNode, {'anonid':uniqueAttributes.anonid})) != 'array') {
|
||||
uniqueAttributes = {'anonid':uniqueAttributes.anonid};
|
||||
}
|
||||
|
||||
if (objects.getLength(uniqueAttributes) == 0) {
|
||||
return 'anon(['+arrays.indexOf(_document.getAnonymousNodes(elem.parentNode), elem)+'])';
|
||||
} else if (arrays.inArray(uniqueAttributes, 'anonid')) {
|
||||
return 'anon({"anonid":"'+uniqueAttributes['anonid']+'"})';
|
||||
} else {
|
||||
return 'anon('+json2.JSON.stringify(uniqueAttributes)+')';
|
||||
}
|
||||
|
||||
}
|
||||
return 'broken '+elemIsAnonymous(elem)
|
||||
}
|
||||
|
||||
var removeHTMLTags = function(str){
|
||||
str = str.replace(/&(lt|gt);/g, function (strMatch, p1){
|
||||
return (p1 == "lt")? "<" : ">";
|
||||
});
|
||||
var strTagStrippedText = str.replace(/<\/?[^>]+(>|$)/g, "");
|
||||
strTagStrippedText = strTagStrippedText.replace(/ /g,"");
|
||||
return strTagStrippedText;
|
||||
}
|
||||
|
||||
var isMagicAnonymousDiv = function (_document, node) {
|
||||
if (node.getAttribute && node.getAttribute('class') == 'anonymous-div') {
|
||||
if (!arrays.inArray(node.parentNode.childNodes, node) && (_document.getAnonymousNodes(node) == null ||
|
||||
!arrays.inArray(_document.getAnonymousNodes(node), node) ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var copyToClipboard = function(str){
|
||||
const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"] .getService(Components.interfaces.nsIClipboardHelper);
|
||||
gClipboardHelper.copyString(str);
|
||||
}
|
||||
|
||||
var getControllerAndDocument = function (_document, _window) {
|
||||
var windowtype = _window.document.documentElement.getAttribute('windowtype');
|
||||
var controllerString, documentString, activeTab;
|
||||
|
||||
// TODO replace with object based cases
|
||||
switch(windowtype) {
|
||||
case 'navigator:browser':
|
||||
controllerString = 'mozmill.getBrowserController()';
|
||||
activeTab = mozmill.getBrowserController().tabs.activeTab;
|
||||
break;
|
||||
case 'Browser:Preferences':
|
||||
controllerString = 'mozmill.getPreferencesController()';
|
||||
break;
|
||||
case 'Extension:Manager':
|
||||
controllerString = 'mozmill.getAddonsController()';
|
||||
break;
|
||||
default:
|
||||
if(windowtype)
|
||||
controllerString = 'new mozmill.controller.MozMillController(mozmill.utils.getWindowByType("' + windowtype + '"))';
|
||||
else if(_window.document.title)
|
||||
controllerString = 'new mozmill.controller.MozMillController(mozmill.utils.getWindowByTitle("'+_window.document.title+'"))';
|
||||
else
|
||||
controllerString = 'Cannot find window';
|
||||
break;
|
||||
}
|
||||
|
||||
if(activeTab == _document) {
|
||||
documentString = 'controller.tabs.activeTab';
|
||||
} else if(activeTab == _document.defaultView.top.document) {
|
||||
// if this document is from an iframe in the active tab
|
||||
var stub = getDocumentStub(_document, activeTab.defaultView);
|
||||
documentString = 'controller.tabs.activeTab.defaultView' + stub;
|
||||
} else {
|
||||
var stub = getDocumentStub(_document, _window);
|
||||
if(stub)
|
||||
documentString = 'controller.window' + stub;
|
||||
else
|
||||
documentString = 'Cannot find document';
|
||||
}
|
||||
return {'controllerString':controllerString, 'documentString':documentString}
|
||||
}
|
||||
|
||||
getDocumentStub = function( _document, _window) {
|
||||
if(_window.document == _document)
|
||||
return '.document';
|
||||
for(var i = 0; i < _window.frames.length; i++) {
|
||||
var stub = getDocumentStub(_document, _window.frames[i]);
|
||||
if (stub)
|
||||
return '.frames['+i+']' + stub;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
var inspectElement = function(e){
|
||||
if (e.originalTarget != undefined) {
|
||||
target = e.originalTarget;
|
||||
} else {
|
||||
target = e.target;
|
||||
}
|
||||
|
||||
//Element highlighting
|
||||
try {
|
||||
if (this.lastEvent)
|
||||
this.lastEvent.target.style.outline = "";
|
||||
} catch(err) {}
|
||||
|
||||
this.lastEvent = e;
|
||||
|
||||
try {
|
||||
e.target.style.outline = "1px solid darkblue";
|
||||
} catch(err){}
|
||||
|
||||
var _document = getDocument(target);
|
||||
|
||||
|
||||
if (isMagicAnonymousDiv(_document, target)) {
|
||||
target = target.parentNode;
|
||||
}
|
||||
|
||||
var windowtype = _document.documentElement.getAttribute('windowtype');
|
||||
var _window = getTopWindow(_document);
|
||||
r = getControllerAndDocument(_document, _window);
|
||||
|
||||
// displayText = "Controller: " + r.controllerString + '\n\n';
|
||||
if ( isNotAnonymous(target) ) {
|
||||
// Logic for which identifier to use is duplicated above
|
||||
if (target.id != "" && !withs.startsWith(target.id, 'panel')) {
|
||||
elemText = "new elementslib.ID("+ r.documentString + ', "' + target.id + '")';
|
||||
var telem = new elementslib.ID(_document, target.id);
|
||||
} else if ((target.name != "") && (typeof(target.name) != "undefined")) {
|
||||
elemText = "new elementslib.Name("+ r.documentString + ', "' + target.name + '")';
|
||||
var telem = new elementslib.Name(_document, target.name);
|
||||
} else if (target.nodeName == "A") {
|
||||
var linkText = removeHTMLTags(target.innerHTML);
|
||||
elemText = "new elementslib.Link("+ r.documentString + ', "' + linkText + '")';
|
||||
var telem = new elementslib.Link(_document, linkText);
|
||||
}
|
||||
}
|
||||
// Fallback on XPath
|
||||
if (telem == undefined || telem.getNode() != target) {
|
||||
if (windowtype == null) {
|
||||
var stringXpath = getXSPath(target);
|
||||
} else {
|
||||
var stringXpath = getXULXpath(target, _document);
|
||||
}
|
||||
var telem = new elementslib.XPath(_document, stringXpath);
|
||||
if ( telem.getNode() == target ) {
|
||||
elemText = "new elementslib.XPath("+ r.documentString + ', "' + stringXpath + '")';
|
||||
}
|
||||
}
|
||||
// Fallback to Lookup
|
||||
if (telem == undefined || telem.getNode() != target) {
|
||||
var exp = getLookupExpression(_document, target);
|
||||
elemText = "new elementslib.Lookup("+ r.documentString + ", '" + exp + "')";
|
||||
var telem = new elementslib.Lookup(_document, exp);
|
||||
}
|
||||
|
||||
return {'validation':( target == telem.getNode() ),
|
||||
'elementText':elemText,
|
||||
'elementType':telem.constructor.name,
|
||||
'controllerText':r.controllerString,
|
||||
'documentString':r.documentString,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
// ***** BEGIN LICENSE BLOCK *****
|
||||
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public License Version
|
||||
// 1.1 (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
// http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS" basis,
|
||||
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
// for the specific language governing rights and limitations under the
|
||||
// License.
|
||||
//
|
||||
// The Original Code is Mozilla Corporation Code.
|
||||
//
|
||||
// The Initial Developer of the Original Code is
|
||||
// Adam Christian.
|
||||
// Portions created by the Initial Developer are Copyright (C) 2008
|
||||
// the Initial Developer. All Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
// Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||
// M.-A. Darche <mozdev@cynode.org>
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
// in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
// of those above. If you wish to allow use of your version of this file only
|
||||
// under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
// use your version of this file under the terms of the MPL, indicate your
|
||||
// decision by deleting the provisions above and replace them with the notice
|
||||
// and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
// the provisions above, a recipient may use your version of this file under
|
||||
// the terms of any one of the MPL, the GPL or the LGPL.
|
||||
//
|
||||
// ***** END LICENSE BLOCK *****
|
||||
|
||||
var EXPORTED_SYMBOLS = ["assert", "assertTrue", "assertFalse", "assertEquals", "assertNotEquals",
|
||||
"assertNull", "assertNotNull", "assertUndefined", "assertNotUndefined",
|
||||
"assertNaN", "assertNotNaN", "assertArrayContains", "fail", "pass"];
|
||||
|
||||
|
||||
// Array.isArray comes with JavaScript 1.8.5 (Firefox 4)
|
||||
// cf. https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
|
||||
Array.isArray = Array.isArray || function(o) { return Object.prototype.toString.call(o) === '[object Array]'; };
|
||||
|
||||
var frame = {}; Components.utils.import("resource://mozmill/modules/frame.js", frame);
|
||||
|
||||
var ifJSONable = function (v) {
|
||||
if (typeof(v) == 'function') {
|
||||
return undefined;
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
var assert = function (booleanValue, comment) {
|
||||
if (booleanValue) {
|
||||
frame.events.pass({'function':'jum.assert', 'value':ifJSONable(booleanValue), 'comment':comment});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assert', 'value':ifJSONable(booleanValue), 'comment':comment});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertTrue = function (booleanValue, comment) {
|
||||
if (typeof(booleanValue) != 'boolean') {
|
||||
frame.events.fail({'function':'jum.assertTrue', 'value':ifJSONable(booleanValue),
|
||||
'message':'Bad argument, value type '+typeof(booleanValue)+' != "boolean"',
|
||||
'comment':comment});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (booleanValue) {
|
||||
frame.events.pass({'function':'jum.assertTrue', 'value':ifJSONable(booleanValue),
|
||||
'comment':comment});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assertTrue', 'value':ifJSONable(booleanValue),
|
||||
'comment':comment});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertFalse = function (booleanValue, comment) {
|
||||
if (typeof(booleanValue) != 'boolean') {
|
||||
frame.events.fail({'function':'jum.assertFalse', 'value':ifJSONable(booleanValue),
|
||||
'message':'Bad argument, value type '+typeof(booleanValue)+' != "boolean"',
|
||||
'comment':comment});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!booleanValue) {
|
||||
frame.events.pass({'function':'jum.assertFalse', 'value':ifJSONable(booleanValue),
|
||||
'comment':comment});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assertFalse', 'value':ifJSONable(booleanValue),
|
||||
'comment':comment});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertEquals = function (value1, value2, comment) {
|
||||
// Case where value1 is an array
|
||||
if (Array.isArray(value1)) {
|
||||
|
||||
if (!Array.isArray(value2)) {
|
||||
frame.events.fail({'function':'jum.assertEquals', 'comment':comment,
|
||||
'message':'Bad argument, value1 is an array and value2 type ' +
|
||||
typeof(value2)+' != "array"',
|
||||
'value2':ifJSONable(value2)});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value1.length != value2.length) {
|
||||
frame.events.fail({'function':'jum.assertEquals', 'comment':comment,
|
||||
'message':"The arrays do not have the same length",
|
||||
'value1':ifJSONable(value1), 'value2':ifJSONable(value2)});
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < value1.length; i++) {
|
||||
if (value1[i] !== value2[i]) {
|
||||
frame.events.fail(
|
||||
{'function':'jum.assertEquals', 'comment':comment,
|
||||
'message':"The element of the arrays are different at index " + i,
|
||||
'value1':ifJSONable(value1), 'value2':ifJSONable(value2)});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
frame.events.pass({'function':'jum.assertEquals', 'comment':comment,
|
||||
'value1':ifJSONable(value1), 'value2':ifJSONable(value2)});
|
||||
return true;
|
||||
}
|
||||
|
||||
// Case where value1 is not an array
|
||||
if (value1 == value2) {
|
||||
frame.events.pass({'function':'jum.assertEquals', 'comment':comment,
|
||||
'value1':ifJSONable(value1), 'value2':ifJSONable(value2)});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assertEquals', 'comment':comment,
|
||||
'value1':ifJSONable(value1), 'value2':ifJSONable(value2)});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertNotEquals = function (value1, value2, comment) {
|
||||
if (value1 != value2) {
|
||||
frame.events.pass({'function':'jum.assertNotEquals', 'comment':comment,
|
||||
'value1':ifJSONable(value1), 'value2':ifJSONable(value2)});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assertNotEquals', 'comment':comment,
|
||||
'value1':ifJSONable(value1), 'value2':ifJSONable(value2)});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertNull = function (value, comment) {
|
||||
if (value == null) {
|
||||
frame.events.pass({'function':'jum.assertNull', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assertNull', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertNotNull = function (value, comment) {
|
||||
if (value != null) {
|
||||
frame.events.pass({'function':'jum.assertNotNull', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assertNotNull', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertUndefined = function (value, comment) {
|
||||
if (value == undefined) {
|
||||
frame.events.pass({'function':'jum.assertUndefined', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assertUndefined', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertNotUndefined = function (value, comment) {
|
||||
if (value != undefined) {
|
||||
frame.events.pass({'function':'jum.assertNotUndefined', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assertNotUndefined', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertNaN = function (value, comment) {
|
||||
if (isNaN(value)) {
|
||||
frame.events.pass({'function':'jum.assertNaN', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assertNaN', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertNotNaN = function (value, comment) {
|
||||
if (!isNaN(value)) {
|
||||
frame.events.pass({'function':'jum.assertNotNaN', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return true;
|
||||
} else {
|
||||
frame.events.fail({'function':'jum.assertNotNaN', 'comment':comment,
|
||||
'value':ifJSONable(value)});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var assertArrayContains = function(array, value, comment) {
|
||||
if (!Array.isArray(array)) {
|
||||
frame.events.fail({'function':'jum.assertArrayContains', 'comment':comment,
|
||||
'message':'Bad argument, value type '+typeof(array)+' != "array"',
|
||||
'value':ifJSONable(array)});
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
if (array[i] === value) {
|
||||
frame.events.pass({'function':'jum.assertArrayContains', 'comment':comment,
|
||||
'value1':ifJSONable(array), 'value2':ifJSONable(value)});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
frame.events.fail({'function':'jum.assertArrayContains', 'comment':comment,
|
||||
'value1':ifJSONable(array), 'value2':ifJSONable(value)});
|
||||
return false;
|
||||
}
|
||||
|
||||
var fail = function (comment) {
|
||||
frame.events.fail({'function':'jum.fail', 'comment':comment});
|
||||
return false;
|
||||
}
|
||||
|
||||
var pass = function (comment) {
|
||||
frame.events.pass({'function':'jum.pass', 'comment':comment});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is MozMill Test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Henrik Skupin <mail@hskupin.info> (Original Author)
|
||||
* Adrian Kalla <akalla@aviary.pl>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* @namespace Defines useful methods to work with localized content
|
||||
*/
|
||||
var l10n = exports;
|
||||
|
||||
/**
|
||||
* Retrieve the localized content for a given DTD entity
|
||||
*
|
||||
* @memberOf l10n
|
||||
* @param {String[]} aDTDs Array of URLs for DTD files.
|
||||
* @param {String} aEntityId ID of the entity to get the localized content of.
|
||||
*
|
||||
* @returns {String} Localized content
|
||||
*/
|
||||
function getEntity(aDTDs, aEntityId) {
|
||||
// Add xhtml11.dtd to prevent missing entity errors with XHTML files
|
||||
aDTDs.push("resource:///res/dtd/xhtml11.dtd");
|
||||
|
||||
// Build a string of external entities
|
||||
var references = "";
|
||||
for (i = 0; i < aDTDs.length; i++) {
|
||||
var id = 'dtd' + i;
|
||||
references += '<!ENTITY % ' + id + ' SYSTEM "' + aDTDs[i] + '">%' + id + ';';
|
||||
}
|
||||
|
||||
var header = '<?xml version="1.0"?><!DOCTYPE elem [' + references + ']>';
|
||||
var element = '<elem id="entity">&' + aEntityId + ';</elem>';
|
||||
var content = header + element;
|
||||
|
||||
var parser = Cc["@mozilla.org/xmlextras/domparser;1"].
|
||||
createInstance(Ci.nsIDOMParser);
|
||||
var doc = parser.parseFromString(content, 'text/xml');
|
||||
var node = doc.querySelector('elem[id="entity"]');
|
||||
|
||||
if (!node) {
|
||||
throw new Error("Unkown entity '" + aEntityId + "'");
|
||||
}
|
||||
|
||||
return node.textContent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the localized content for a given property
|
||||
*
|
||||
* @memberOf l10n
|
||||
* @param {String} aURL URL of the .properties file.
|
||||
* @param {String} aProperty The property to get the value of.
|
||||
*
|
||||
* @returns {String} Value of the requested property
|
||||
*/
|
||||
function getProperty(aURL, aProperty) {
|
||||
var sbs = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService);
|
||||
var bundle = sbs.createBundle(aURL);
|
||||
|
||||
try {
|
||||
return bundle.GetStringFromName(aProperty);
|
||||
}
|
||||
catch (ex) {
|
||||
throw new Error("Unkown property '" + aProperty + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Export of functions
|
||||
l10n.getEntity = getEntity;
|
||||
l10n.getProperty = getProperty;
|
|
@ -0,0 +1,702 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozmill Elements.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Andrew Halberstadt <halbersa@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Elem", "Selector", "ID", "Link", "XPath", "Name", "Lookup",
|
||||
"MozMillElement", "MozMillCheckBox", "MozMillRadio", "MozMillDropList",
|
||||
"MozMillTextBox", "subclasses",
|
||||
];
|
||||
|
||||
var EventUtils = {}; Components.utils.import('resource://mozmill/stdlib/EventUtils.js', EventUtils);
|
||||
var frame = {}; Components.utils.import('resource://mozmill/modules/frame.js', frame);
|
||||
var utils = {}; Components.utils.import('resource://mozmill/modules/utils.js', utils);
|
||||
var elementslib = {}; Components.utils.import('resource://mozmill/modules/elementslib.js', elementslib);
|
||||
|
||||
// A list of all the subclasses available. Shared modules can push their own subclasses onto this list
|
||||
var subclasses = [MozMillCheckBox, MozMillRadio, MozMillDropList, MozMillTextBox];
|
||||
|
||||
/**
|
||||
* createInstance()
|
||||
*
|
||||
* Returns an new instance of a MozMillElement
|
||||
* The type of the element is automatically determined
|
||||
*/
|
||||
function createInstance(locatorType, locator, elem) {
|
||||
if (elem) {
|
||||
var args = {"element":elem};
|
||||
for (var i = 0; i < subclasses.length; ++i) {
|
||||
if (subclasses[i].isType(elem)) {
|
||||
return new subclasses[i](locatorType, locator, args);
|
||||
}
|
||||
}
|
||||
if (MozMillElement.isType(elem)) return new MozMillElement(locatorType, locator, args);
|
||||
}
|
||||
throw new Error("could not find element " + locatorType + ": " + locator);
|
||||
};
|
||||
|
||||
var Elem = function(node) {
|
||||
return createInstance("Elem", node, node);
|
||||
};
|
||||
|
||||
var Selector = function(_document, selector, index) {
|
||||
return createInstance("Selector", selector, elementslib.Selector(_document, selector, index));
|
||||
};
|
||||
|
||||
var ID = function(_document, nodeID) {
|
||||
return createInstance("ID", nodeID, elementslib.ID(_document, nodeID));
|
||||
};
|
||||
|
||||
var Link = function(_document, linkName) {
|
||||
return createInstance("Link", linkName, elementslib.Link(_document, linkName));
|
||||
};
|
||||
|
||||
var XPath = function(_document, expr) {
|
||||
return createInstance("XPath", expr, elementslib.XPath(_document, expr));
|
||||
};
|
||||
|
||||
var Name = function(_document, nName) {
|
||||
return createInstance("Name", nName, elementslib.Name(_document, nName));
|
||||
};
|
||||
|
||||
var Lookup = function(_document, expression) {
|
||||
return createInstance("Lookup", expression, elementslib.Lookup(_document, expression));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* MozMillElement
|
||||
* The base class for all mozmill elements
|
||||
*/
|
||||
function MozMillElement(locatorType, locator, args) {
|
||||
args = args || {};
|
||||
this._locatorType = locatorType;
|
||||
this._locator = locator;
|
||||
this._element = args["element"];
|
||||
this._document = args["document"];
|
||||
this._owner = args["owner"];
|
||||
// Used to maintain backwards compatibility with controller.js
|
||||
this.isElement = true;
|
||||
}
|
||||
|
||||
// Static method that returns true if node is of this element type
|
||||
MozMillElement.isType = function(node) {
|
||||
return true;
|
||||
};
|
||||
|
||||
// This getter is the magic behind lazy loading (note distinction between _element and element)
|
||||
MozMillElement.prototype.__defineGetter__("element", function() {
|
||||
if (this._element == undefined) {
|
||||
if (elementslib[this._locatorType]) {
|
||||
this._element = elementslib[this._locatorType](this._document, this._locator);
|
||||
} else if (this._locatorType == "Elem") {
|
||||
this._element = this._locator;
|
||||
} else {
|
||||
throw new Error("Unknown locator type: " + this._locatorType);
|
||||
}
|
||||
}
|
||||
return this._element;
|
||||
});
|
||||
|
||||
// Returns the actual wrapped DOM node
|
||||
MozMillElement.prototype.getNode = function() {
|
||||
return this.element;
|
||||
};
|
||||
|
||||
MozMillElement.prototype.getInfo = function() {
|
||||
return this._locatorType + ": " + this._locator;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sometimes an element which once existed will no longer exist in the DOM
|
||||
* This function re-searches for the element
|
||||
*/
|
||||
MozMillElement.prototype.exists = function() {
|
||||
this._element = undefined;
|
||||
if (this.element) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesize a keypress event on the given element
|
||||
*
|
||||
* @param {string} aKey
|
||||
* Key to use for synthesizing the keypress event. It can be a simple
|
||||
* character like "k" or a string like "VK_ESCAPE" for command keys
|
||||
* @param {object} aModifiers
|
||||
* Information about the modifier keys to send
|
||||
* Elements: accelKey - Hold down the accelerator key (ctrl/meta)
|
||||
* [optional - default: false]
|
||||
* altKey - Hold down the alt key
|
||||
* [optional - default: false]
|
||||
* ctrlKey - Hold down the ctrl key
|
||||
* [optional - default: false]
|
||||
* metaKey - Hold down the meta key (command key on Mac)
|
||||
* [optional - default: false]
|
||||
* shiftKey - Hold down the shift key
|
||||
* [optional - default: false]
|
||||
* @param {object} aExpectedEvent
|
||||
* Information about the expected event to occur
|
||||
* Elements: target - Element which should receive the event
|
||||
* [optional - default: current element]
|
||||
* type - Type of the expected key event
|
||||
*/
|
||||
MozMillElement.prototype.keypress = function(aKey, aModifiers, aExpectedEvent) {
|
||||
if (!this.element) {
|
||||
throw new Error("Could not find element " + this.getInfo());
|
||||
}
|
||||
|
||||
var win = this.element.ownerDocument? this.element.ownerDocument.defaultView : this.element;
|
||||
this.element.focus();
|
||||
|
||||
if (aExpectedEvent) {
|
||||
var target = aExpectedEvent.target? aExpectedEvent.target.getNode() : this.element;
|
||||
EventUtils.synthesizeKeyExpectEvent(aKey, aModifiers || {}, target, aExpectedEvent.type,
|
||||
"MozMillElement.keypress()", win);
|
||||
} else {
|
||||
EventUtils.synthesizeKey(aKey, aModifiers || {}, win);
|
||||
}
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.keypress()'});
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Synthesize a general mouse event on the given element
|
||||
*
|
||||
* @param {ElemBase} aTarget
|
||||
* Element which will receive the mouse event
|
||||
* @param {number} aOffsetX
|
||||
* Relative x offset in the elements bounds to click on
|
||||
* @param {number} aOffsetY
|
||||
* Relative y offset in the elements bounds to click on
|
||||
* @param {object} aEvent
|
||||
* Information about the event to send
|
||||
* Elements: accelKey - Hold down the accelerator key (ctrl/meta)
|
||||
* [optional - default: false]
|
||||
* altKey - Hold down the alt key
|
||||
* [optional - default: false]
|
||||
* button - Mouse button to use
|
||||
* [optional - default: 0]
|
||||
* clickCount - Number of counts to click
|
||||
* [optional - default: 1]
|
||||
* ctrlKey - Hold down the ctrl key
|
||||
* [optional - default: false]
|
||||
* metaKey - Hold down the meta key (command key on Mac)
|
||||
* [optional - default: false]
|
||||
* shiftKey - Hold down the shift key
|
||||
* [optional - default: false]
|
||||
* type - Type of the mouse event ('click', 'mousedown',
|
||||
* 'mouseup', 'mouseover', 'mouseout')
|
||||
* [optional - default: 'mousedown' + 'mouseup']
|
||||
* @param {object} aExpectedEvent
|
||||
* Information about the expected event to occur
|
||||
* Elements: target - Element which should receive the event
|
||||
* [optional - default: current element]
|
||||
* type - Type of the expected mouse event
|
||||
*/
|
||||
MozMillElement.prototype.mouseEvent = function(aOffsetX, aOffsetY, aEvent, aExpectedEvent) {
|
||||
if (!this.element) {
|
||||
throw new Error(arguments.callee.name + ": could not find element " + this.getInfo());
|
||||
}
|
||||
|
||||
// If no offset is given we will use the center of the element to click on.
|
||||
var rect = this.element.getBoundingClientRect();
|
||||
if (isNaN(aOffsetX)) {
|
||||
aOffsetX = rect.width / 2;
|
||||
}
|
||||
if (isNaN(aOffsetY)) {
|
||||
aOffsetY = rect.height / 2;
|
||||
}
|
||||
|
||||
// Scroll element into view otherwise the click will fail
|
||||
if (this.element.scrollIntoView) {
|
||||
this.element.scrollIntoView();
|
||||
}
|
||||
|
||||
if (aExpectedEvent) {
|
||||
// The expected event type has to be set
|
||||
if (!aExpectedEvent.type)
|
||||
throw new Error(arguments.callee.name + ": Expected event type not specified");
|
||||
|
||||
// If no target has been specified use the specified element
|
||||
var target = aExpectedEvent.target ? aExpectedEvent.target.getNode() : this.element;
|
||||
if (!target) {
|
||||
throw new Error(arguments.callee.name + ": could not find element " + aExpectedEvent.target.getInfo());
|
||||
}
|
||||
|
||||
EventUtils.synthesizeMouseExpectEvent(this.element, aOffsetX, aOffsetY, aEvent,
|
||||
target, aExpectedEvent.event,
|
||||
"MozMillElement.mouseEvent()",
|
||||
this.element.ownerDocument.defaultView);
|
||||
} else {
|
||||
EventUtils.synthesizeMouse(this.element, aOffsetX, aOffsetY, aEvent,
|
||||
this.element.ownerDocument.defaultView);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesize a mouse click event on the given element
|
||||
*/
|
||||
MozMillElement.prototype.click = function(left, top, expectedEvent) {
|
||||
// Handle menu items differently
|
||||
if (this.element && this.element.tagName == "menuitem") {
|
||||
this.element.click();
|
||||
} else {
|
||||
this.mouseEvent(left, top, {}, expectedEvent);
|
||||
}
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.click()'});
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesize a double click on the given element
|
||||
*/
|
||||
MozMillElement.prototype.doubleClick = function(left, top, expectedEvent) {
|
||||
this.mouseEvent(left, top, {clickCount: 2}, expectedEvent);
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.doubleClick()'});
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesize a mouse down event on the given element
|
||||
*/
|
||||
MozMillElement.prototype.mouseDown = function (button, left, top, expectedEvent) {
|
||||
this.mouseEvent(left, top, {button: button, type: "mousedown"}, expectedEvent);
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.mouseDown()'});
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesize a mouse out event on the given element
|
||||
*/
|
||||
MozMillElement.prototype.mouseOut = function (button, left, top, expectedEvent) {
|
||||
this.mouseEvent(left, top, {button: button, type: "mouseout"}, expectedEvent);
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.mouseOut()'});
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesize a mouse over event on the given element
|
||||
*/
|
||||
MozMillElement.prototype.mouseOver = function (button, left, top, expectedEvent) {
|
||||
this.mouseEvent(left, top, {button: button, type: "mouseover"}, expectedEvent);
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.mouseOver()'});
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesize a mouse up event on the given element
|
||||
*/
|
||||
MozMillElement.prototype.mouseUp = function (button, left, top, expectedEvent) {
|
||||
this.mouseEvent(left, top, {button: button, type: "mouseup"}, expectedEvent);
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.mouseUp()'});
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesize a mouse middle click event on the given element
|
||||
*/
|
||||
MozMillElement.prototype.middleClick = function(left, top, expectedEvent) {
|
||||
this.mouseEvent(left, top, {button: 1}, expectedEvent);
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.middleClick()'});
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesize a mouse right click event on the given element
|
||||
*/
|
||||
MozMillElement.prototype.rightClick = function(left, top, expectedEvent) {
|
||||
this.mouseEvent(left, top, {type : "contextmenu", button: 2 }, expectedEvent);
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.rightClick()'});
|
||||
return true;
|
||||
};
|
||||
|
||||
MozMillElement.prototype.waitForElement = function(timeout, interval) {
|
||||
var elem = this;
|
||||
utils.waitFor(function() {
|
||||
return elem.exists();
|
||||
}, "Timeout exceeded for waitForElement " + this.getInfo(), timeout, interval);
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.waitForElement()'});
|
||||
};
|
||||
|
||||
MozMillElement.prototype.waitForElementNotPresent = function(timeout, interval) {
|
||||
var elem = this;
|
||||
utils.waitFor(function() {
|
||||
return !elem.exists();
|
||||
}, "Timeout exceeded for waitForElementNotPresent " + this.getInfo(), timeout, interval);
|
||||
|
||||
frame.events.pass({'function':'MozMillElement.waitForElementNotPresent()'});
|
||||
};
|
||||
|
||||
MozMillElement.prototype.waitThenClick = function (timeout, interval, left, top, expectedEvent) {
|
||||
this.waitForElement(timeout, interval);
|
||||
this.click(left, top, expectedEvent);
|
||||
};
|
||||
|
||||
// Dispatches an HTMLEvent
|
||||
MozMillElement.prototype.dispatchEvent = function (eventType, canBubble, modifiers) {
|
||||
canBubble = canBubble || true;
|
||||
var evt = this.element.ownerDocument.createEvent('HTMLEvents');
|
||||
evt.shiftKey = modifiers["shift"];
|
||||
evt.metaKey = modifiers["meta"];
|
||||
evt.altKey = modifiers["alt"];
|
||||
evt.ctrlKey = modifiers["ctrl"];
|
||||
evt.initEvent(eventType, canBubble, true);
|
||||
this.element.dispatchEvent(evt);
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* MozMillCheckBox
|
||||
* Checkbox element, inherits from MozMillElement
|
||||
*/
|
||||
MozMillCheckBox.prototype = new MozMillElement();
|
||||
MozMillCheckBox.prototype.parent = MozMillElement.prototype;
|
||||
MozMillCheckBox.prototype.constructor = MozMillCheckBox;
|
||||
function MozMillCheckBox(locatorType, locator, args) {
|
||||
this.parent.constructor.call(this, locatorType, locator, args);
|
||||
}
|
||||
|
||||
// Static method returns true if node is this type of element
|
||||
MozMillCheckBox.isType = function(node) {
|
||||
if ((node.localName.toLowerCase() == "input" && node.getAttribute("type") == "checkbox") ||
|
||||
(node.localName.toLowerCase() == 'toolbarbutton' && node.getAttribute('type') == 'checkbox') ||
|
||||
(node.localName.toLowerCase() == 'checkbox')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Enable/Disable a checkbox depending on the target state
|
||||
*/
|
||||
MozMillCheckBox.prototype.check = function(state) {
|
||||
var result = false;
|
||||
|
||||
if (!this.element) {
|
||||
throw new Error("could not find element " + this.getInfo());
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we have a XUL element, unwrap its XPCNativeWrapper
|
||||
if (this.element.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul") {
|
||||
this.element = utils.unwrapNode(this.element);
|
||||
}
|
||||
|
||||
state = (typeof(state) == "boolean") ? state : false;
|
||||
if (state != this.element.checked) {
|
||||
this.click();
|
||||
var element = this.element;
|
||||
utils.waitFor(function() {
|
||||
return element.checked == state;
|
||||
}, "Checkbox " + this.getInfo() + " could not be checked/unchecked", 500);
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
frame.events.pass({'function':'MozMillCheckBox.check(' + this.getInfo() + ', state: ' + state + ')'});
|
||||
return result;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* MozMillRadio
|
||||
* Radio button inherits from MozMillElement
|
||||
*/
|
||||
MozMillRadio.prototype = new MozMillElement();
|
||||
MozMillRadio.prototype.parent = MozMillElement.prototype;
|
||||
MozMillRadio.prototype.constructor = MozMillRadio;
|
||||
function MozMillRadio(locatorType, locator, args) {
|
||||
this.parent.constructor.call(this, locatorType, locator, args);
|
||||
}
|
||||
|
||||
// Static method returns true if node is this type of element
|
||||
MozMillRadio.isType = function(node) {
|
||||
if ((node.localName.toLowerCase() == 'input' && node.getAttribute('type') == 'radio') ||
|
||||
(node.localName.toLowerCase() == 'toolbarbutton' && node.getAttribute('type') == 'radio') ||
|
||||
(node.localName.toLowerCase() == 'radio') ||
|
||||
(node.localName.toLowerCase() == 'radiogroup')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Select the given radio button
|
||||
*
|
||||
* index - Specifies which radio button in the group to select (only applicable to radiogroup elements)
|
||||
* Defaults to the first radio button in the group
|
||||
*/
|
||||
MozMillRadio.prototype.select = function(index) {
|
||||
if (!this.element) {
|
||||
throw new Error("could not find element " + this.getInfo());
|
||||
}
|
||||
|
||||
if (this.element.localName.toLowerCase() == "radiogroup") {
|
||||
var element = this.element.getElementsByTagName("radio")[index || 0];
|
||||
new MozMillRadio("Elem", element).click();
|
||||
} else {
|
||||
var element = this.element;
|
||||
this.click();
|
||||
}
|
||||
|
||||
utils.waitFor(function() {
|
||||
// If we have a XUL element, unwrap its XPCNativeWrapper
|
||||
if (element.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul") {
|
||||
element = utils.unwrapNode(element);
|
||||
return element.selected == true;
|
||||
}
|
||||
return element.checked == true;
|
||||
}, "Radio button " + this.getInfo() + " could not be selected", 500);
|
||||
|
||||
frame.events.pass({'function':'MozMillRadio.select(' + this.getInfo() + ')'});
|
||||
return true;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* MozMillDropList
|
||||
* DropList inherits from MozMillElement
|
||||
*/
|
||||
MozMillDropList.prototype = new MozMillElement();
|
||||
MozMillDropList.prototype.parent = MozMillElement.prototype;
|
||||
MozMillDropList.prototype.constructor = MozMillDropList;
|
||||
function MozMillDropList(locatorType, locator, args) {
|
||||
this.parent.constructor.call(this, locatorType, locator, args);
|
||||
};
|
||||
|
||||
// Static method returns true if node is this type of element
|
||||
MozMillDropList.isType = function(node) {
|
||||
if ((node.localName.toLowerCase() == 'toolbarbutton' && (node.getAttribute('type') == 'menu' || node.getAttribute('type') == 'menu-button')) ||
|
||||
(node.localName.toLowerCase() == 'menu') ||
|
||||
(node.localName.toLowerCase() == 'menulist') ||
|
||||
(node.localName.toLowerCase() == 'select' )) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/* Select the specified option and trigger the relevant events of the element */
|
||||
MozMillDropList.prototype.select = function (indx, option, value) {
|
||||
if (!this.element){
|
||||
throw new Error("Could not find element " + this.getInfo());
|
||||
}
|
||||
|
||||
//if we have a select drop down
|
||||
if (this.element.localName.toLowerCase() == "select"){
|
||||
var item = null;
|
||||
|
||||
// The selected item should be set via its index
|
||||
if (indx != undefined) {
|
||||
// Resetting a menulist has to be handled separately
|
||||
if (indx == -1) {
|
||||
this.dispatchEvent('focus', false);
|
||||
this.element.selectedIndex = indx;
|
||||
this.dispatchEvent('change', true);
|
||||
|
||||
frame.events.pass({'function':'MozMillDropList.select()'});
|
||||
return true;
|
||||
} else {
|
||||
item = this.element.options.item(indx);
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < this.element.options.length; i++) {
|
||||
var entry = this.element.options.item(i);
|
||||
if (option != undefined && entry.innerHTML == option ||
|
||||
value != undefined && entry.value == value) {
|
||||
item = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Click the item
|
||||
try {
|
||||
// EventUtils.synthesizeMouse doesn't work.
|
||||
this.dispatchEvent('focus', false);
|
||||
item.selected = true;
|
||||
this.dispatchEvent('change', true);
|
||||
|
||||
frame.events.pass({'function':'MozMillDropList.select()'});
|
||||
return true;
|
||||
} catch (ex) {
|
||||
throw new Error("No item selected for element " + this.getInfo());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//if we have a xul menupopup select accordingly
|
||||
else if (this.element.namespaceURI.toLowerCase() == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul") {
|
||||
var ownerDoc = this.element.ownerDocument;
|
||||
// Unwrap the XUL element's XPCNativeWrapper
|
||||
this.element = utils.unwrapNode(this.element);
|
||||
// Get the list of menuitems
|
||||
menuitems = this.element.getElementsByTagName("menupopup")[0].getElementsByTagName("menuitem");
|
||||
|
||||
var item = null;
|
||||
|
||||
if (indx != undefined) {
|
||||
if (indx == -1) {
|
||||
this.dispatchEvent('focus', false);
|
||||
this.element.boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject).activeChild = null;
|
||||
this.dispatchEvent('change', true);
|
||||
|
||||
frame.events.pass({'function':'MozMillDropList.select()'});
|
||||
return true;
|
||||
} else {
|
||||
item = menuitems[indx];
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < menuitems.length; i++) {
|
||||
var entry = menuitems[i];
|
||||
if (option != undefined && entry.label == option ||
|
||||
value != undefined && entry.value == value) {
|
||||
item = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Click the item
|
||||
try {
|
||||
EventUtils.synthesizeMouse(this.element, 1, 1, {}, ownerDoc.defaultView);
|
||||
|
||||
// Scroll down until item is visible
|
||||
for (var i = 0; i <= menuitems.length; ++i) {
|
||||
var selected = this.element.boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject).activeChild;
|
||||
if (item == selected) {
|
||||
break;
|
||||
}
|
||||
EventUtils.synthesizeKey("VK_DOWN", {}, ownerDoc.defaultView);
|
||||
}
|
||||
|
||||
EventUtils.synthesizeMouse(item, 1, 1, {}, ownerDoc.defaultView);
|
||||
|
||||
frame.events.pass({'function':'MozMillDropList.select()'});
|
||||
return true;
|
||||
} catch (ex) {
|
||||
throw new Error('No item selected for element ' + this.getInfo());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* MozMillTextBox
|
||||
* TextBox inherits from MozMillElement
|
||||
*/
|
||||
MozMillTextBox.prototype = new MozMillElement();
|
||||
MozMillTextBox.prototype.parent = MozMillElement.prototype;
|
||||
MozMillTextBox.prototype.constructor = MozMillTextBox;
|
||||
function MozMillTextBox(locatorType, locator, args) {
|
||||
this.parent.constructor.call(this, locatorType, locator, args);
|
||||
};
|
||||
|
||||
// Static method returns true if node is this type of element
|
||||
MozMillTextBox.isType = function(node) {
|
||||
if ((node.localName.toLowerCase() == 'input' && (node.getAttribute('type') == 'text' || node.getAttribute('type') == 'search')) ||
|
||||
(node.localName.toLowerCase() == 'textarea') ||
|
||||
(node.localName.toLowerCase() == 'textbox')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesize keypress events for each character on the given element
|
||||
*
|
||||
* @param {string} aText
|
||||
* The text to send as single keypress events
|
||||
* @param {object} aModifiers
|
||||
* Information about the modifier keys to send
|
||||
* Elements: accelKey - Hold down the accelerator key (ctrl/meta)
|
||||
* [optional - default: false]
|
||||
* altKey - Hold down the alt key
|
||||
* [optional - default: false]
|
||||
* ctrlKey - Hold down the ctrl key
|
||||
* [optional - default: false]
|
||||
* metaKey - Hold down the meta key (command key on Mac)
|
||||
* [optional - default: false]
|
||||
* shiftKey - Hold down the shift key
|
||||
* [optional - default: false]
|
||||
* @param {object} aExpectedEvent
|
||||
* Information about the expected event to occur
|
||||
* Elements: target - Element which should receive the event
|
||||
* [optional - default: current element]
|
||||
* type - Type of the expected key event
|
||||
*/
|
||||
MozMillTextBox.prototype.sendKeys = function (aText, aModifiers, aExpectedEvent) {
|
||||
if (!this.element) {
|
||||
throw new Error("could not find element " + this.getInfo());
|
||||
}
|
||||
|
||||
var element = this.element;
|
||||
Array.forEach(aText, function(letter) {
|
||||
var win = element.ownerDocument? element.ownerDocument.defaultView : element;
|
||||
element.focus();
|
||||
|
||||
if (aExpectedEvent) {
|
||||
var target = aExpectedEvent.target ? aExpectedEvent.target.getNode() : element;
|
||||
EventUtils.synthesizeKeyExpectEvent(letter, aModifiers || {}, target, aExpectedEvent.type,
|
||||
"MozMillTextBox.sendKeys()", win);
|
||||
} else {
|
||||
EventUtils.synthesizeKey(letter, aModifiers || {}, win);
|
||||
}
|
||||
});
|
||||
|
||||
frame.events.pass({'function':'MozMillTextBox.type()'});
|
||||
return true;
|
||||
};
|
|
@ -0,0 +1,263 @@
|
|||
// ***** BEGIN LICENSE BLOCK *****
|
||||
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public License Version
|
||||
// 1.1 (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
// http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS" basis,
|
||||
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
// for the specific language governing rights and limitations under the
|
||||
// License.
|
||||
//
|
||||
// The Original Code is Mozilla Corporation Code.
|
||||
//
|
||||
// The Initial Developer of the Original Code is
|
||||
// Mikeal Rogers.
|
||||
// Portions created by the Initial Developer are Copyright (C) 2008
|
||||
// the Initial Developer. All Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
// Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||
// Gary Kwong <nth10sd@gmail.com>
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
// in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
// of those above. If you wish to allow use of your version of this file only
|
||||
// under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
// use your version of this file under the terms of the MPL, indicate your
|
||||
// decision by deleting the provisions above and replace them with the notice
|
||||
// and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
// the provisions above, a recipient may use your version of this file under
|
||||
// the terms of any one of the MPL, the GPL or the LGPL.
|
||||
//
|
||||
// ***** END LICENSE BLOCK *****
|
||||
|
||||
var EXPORTED_SYMBOLS = ["controller", "utils", "elementslib", "os",
|
||||
"getBrowserController", "newBrowserController",
|
||||
"getAddonsController", "getPreferencesController",
|
||||
"newMail3PaneController", "getMail3PaneController",
|
||||
"wm", "platform", "getAddrbkController",
|
||||
"getMsgComposeController", "getDownloadsController",
|
||||
"Application", "cleanQuit",
|
||||
"getPlacesController", 'isMac', 'isLinux', 'isWindows',
|
||||
"firePythonCallback"
|
||||
];
|
||||
|
||||
// imports
|
||||
var controller = {}; Components.utils.import('resource://mozmill/modules/controller.js', controller);
|
||||
var utils = {}; Components.utils.import('resource://mozmill/modules/utils.js', utils);
|
||||
var elementslib = {}; Components.utils.import('resource://mozmill/modules/elementslib.js', elementslib);
|
||||
var frame = {}; Components.utils.import('resource://mozmill/modules/frame.js', frame);
|
||||
var os = {}; Components.utils.import('resource://mozmill/stdlib/os.js', os);
|
||||
|
||||
try {
|
||||
Components.utils.import("resource://gre/modules/AddonManager.jsm");
|
||||
} catch(e) { /* Firefox 4 only */ }
|
||||
|
||||
// platform information
|
||||
var platform = os.getPlatform();
|
||||
var isMac = false;
|
||||
var isWindows = false;
|
||||
var isLinux = false;
|
||||
if (platform == "darwin"){
|
||||
isMac = true;
|
||||
}
|
||||
if (platform == "winnt"){
|
||||
isWindows = true;
|
||||
}
|
||||
if (platform == "linux"){
|
||||
isLinux = true;
|
||||
}
|
||||
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
|
||||
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
|
||||
.getService(Components.interfaces.nsIXULAppInfo);
|
||||
|
||||
var locale = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
|
||||
.getService(Components.interfaces.nsIXULChromeRegistry)
|
||||
.getSelectedLocale("global");
|
||||
|
||||
var aConsoleService = Components.classes["@mozilla.org/consoleservice;1"].
|
||||
getService(Components.interfaces.nsIConsoleService);
|
||||
|
||||
|
||||
applicationDictionary = {
|
||||
"{718e30fb-e89b-41dd-9da7-e25a45638b28}": "Sunbird",
|
||||
"{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}": "SeaMonkey",
|
||||
"{ec8030f7-c20a-464f-9b0e-13a3a9e97384}": "Firefox",
|
||||
"{3550f703-e582-4d05-9a08-453d09bdfdc6}": 'Thunderbird',
|
||||
}
|
||||
|
||||
var Application = applicationDictionary[appInfo.ID];
|
||||
|
||||
if (Application == undefined) {
|
||||
// Default to Firefox
|
||||
var Application = 'Firefox';
|
||||
}
|
||||
|
||||
// get startup time if available
|
||||
// see http://blog.mozilla.com/tglek/2011/04/26/measuring-startup-speed-correctly/
|
||||
var startupInfo = {};
|
||||
try {
|
||||
var _startupInfo = Components.classes["@mozilla.org/toolkit/app-startup;1"]
|
||||
.getService(Components.interfaces.nsIAppStartup).getStartupInfo();
|
||||
for (var i in _startupInfo) {
|
||||
startupInfo[i] = _startupInfo[i].getTime(); // convert from Date object to ms since epoch
|
||||
}
|
||||
} catch(e) {
|
||||
startupInfo = null;
|
||||
}
|
||||
|
||||
|
||||
// keep list of installed addons to send to jsbridge for test run report
|
||||
var addons = "null"; // this will be JSON parsed
|
||||
if(typeof AddonManager != "undefined") {
|
||||
AddonManager.getAllAddons(function(addonList) {
|
||||
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
|
||||
converter.charset = 'utf-8';
|
||||
|
||||
function replacer(key, value) {
|
||||
if (typeof(value) == "string") {
|
||||
try {
|
||||
return converter.ConvertToUnicode(value);
|
||||
} catch(e) {
|
||||
var newstring = '';
|
||||
for (var i=0; i < value.length; i++) {
|
||||
replacement = '';
|
||||
if ((32 <= value.charCodeAt(i)) && (value.charCodeAt(i) < 127)) {
|
||||
// eliminate non-convertable characters;
|
||||
newstring += value.charAt(i);
|
||||
} else {
|
||||
newstring += replacement;
|
||||
}
|
||||
}
|
||||
return newstring;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
addons = converter.ConvertToUnicode(JSON.stringify(addonList, replacer))
|
||||
});
|
||||
}
|
||||
|
||||
function cleanQuit () {
|
||||
utils.getMethodInWindows('goQuitApplication')();
|
||||
}
|
||||
|
||||
function addHttpResource (directory, namespace) {
|
||||
return 'http://localhost:4545/'+namespace;
|
||||
}
|
||||
|
||||
function newBrowserController () {
|
||||
return new controller.MozMillController(utils.getMethodInWindows('OpenBrowserWindow')());
|
||||
}
|
||||
|
||||
function getBrowserController () {
|
||||
var browserWindow = wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow == null) {
|
||||
return newBrowserController();
|
||||
}
|
||||
else {
|
||||
return new controller.MozMillController(browserWindow);
|
||||
}
|
||||
}
|
||||
|
||||
function getPlacesController () {
|
||||
utils.getMethodInWindows('PlacesCommandHook').showPlacesOrganizer('AllBookmarks');
|
||||
return new controller.MozMillController(wm.getMostRecentWindow(''));
|
||||
}
|
||||
|
||||
function getAddonsController () {
|
||||
if (Application == 'SeaMonkey') {
|
||||
utils.getMethodInWindows('toEM')();
|
||||
} else if (Application == 'Thunderbird') {
|
||||
utils.getMethodInWindows('openAddonsMgr')();
|
||||
} else if (Application == 'Sunbird') {
|
||||
utils.getMethodInWindows('goOpenAddons')();
|
||||
} else {
|
||||
utils.getMethodInWindows('BrowserOpenAddonsMgr')();
|
||||
}
|
||||
return new controller.MozMillController(wm.getMostRecentWindow(''));
|
||||
}
|
||||
|
||||
function getDownloadsController() {
|
||||
utils.getMethodInWindows('BrowserDownloadsUI')();
|
||||
return new controller.MozMillController(wm.getMostRecentWindow(''));
|
||||
}
|
||||
|
||||
function getPreferencesController() {
|
||||
if (Application == 'Thunderbird') {
|
||||
utils.getMethodInWindows('openOptionsDialog')();
|
||||
} else {
|
||||
utils.getMethodInWindows('openPreferences')();
|
||||
}
|
||||
return new controller.MozMillController(wm.getMostRecentWindow(''));
|
||||
}
|
||||
|
||||
// Thunderbird functions
|
||||
function newMail3PaneController () {
|
||||
return new controller.MozMillController(utils.getMethodInWindows('toMessengerWindow')());
|
||||
}
|
||||
|
||||
function getMail3PaneController () {
|
||||
var mail3PaneWindow = wm.getMostRecentWindow("mail:3pane");
|
||||
if (mail3PaneWindow == null) {
|
||||
return newMail3PaneController();
|
||||
}
|
||||
else {
|
||||
return new controller.MozMillController(mail3PaneWindow);
|
||||
}
|
||||
}
|
||||
|
||||
// Thunderbird - Address book window
|
||||
function newAddrbkController () {
|
||||
utils.getMethodInWindows("toAddressBook")();
|
||||
utils.sleep(2000);
|
||||
var addyWin = wm.getMostRecentWindow("mail:addressbook");
|
||||
return new controller.MozMillController(addyWin);
|
||||
}
|
||||
|
||||
function getAddrbkController () {
|
||||
var addrbkWindow = wm.getMostRecentWindow("mail:addressbook");
|
||||
if (addrbkWindow == null) {
|
||||
return newAddrbkController();
|
||||
}
|
||||
else {
|
||||
return new controller.MozMillController(addrbkWindow);
|
||||
}
|
||||
}
|
||||
|
||||
function firePythonCallback (filename, method, args, kwargs) {
|
||||
obj = {'filename': filename, 'method': method};
|
||||
obj['test'] = frame.events.currentModule.__file__;
|
||||
obj['args'] = args || [];
|
||||
obj['kwargs'] = kwargs || {};
|
||||
frame.events.fireEvent("firePythonCallback", obj);
|
||||
}
|
||||
|
||||
function timer (name) {
|
||||
this.name = name;
|
||||
this.timers = {};
|
||||
frame.timers.push(this);
|
||||
this.actions = [];
|
||||
}
|
||||
timer.prototype.start = function (name) {
|
||||
this.timers[name].startTime = (new Date).getTime();
|
||||
}
|
||||
timer.prototype.stop = function (name) {
|
||||
var t = this.timers[name];
|
||||
t.endTime = (new Date).getTime();
|
||||
t.totalTime = (t.endTime - t.startTime);
|
||||
}
|
||||
timer.prototype.end = function () {
|
||||
frame.events.fireEvent("timer", this);
|
||||
frame.timers.remove(this);
|
||||
}
|
|
@ -0,0 +1,557 @@
|
|||
// ***** BEGIN LICENSE BLOCK *****
|
||||
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public License Version
|
||||
// 1.1 (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
// http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS" basis,
|
||||
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
// for the specific language governing rights and limitations under the
|
||||
// License.
|
||||
//
|
||||
// The Original Code is Mozilla Corporation Code.
|
||||
//
|
||||
// The Initial Developer of the Original Code is
|
||||
// Adam Christian.
|
||||
// Portions created by the Initial Developer are Copyright (C) 2008
|
||||
// the Initial Developer. All Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
// Adam Christian <adam.christian@gmail.com>
|
||||
// Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||
// Henrik Skupin <hskupin@mozilla.com>
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
// in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
// of those above. If you wish to allow use of your version of this file only
|
||||
// under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
// use your version of this file under the terms of the MPL, indicate your
|
||||
// decision by deleting the provisions above and replace them with the notice
|
||||
// and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
// the provisions above, a recipient may use your version of this file under
|
||||
// the terms of any one of the MPL, the GPL or the LGPL.
|
||||
//
|
||||
// ***** END LICENSE BLOCK *****
|
||||
|
||||
var EXPORTED_SYMBOLS = ["openFile", "saveFile", "saveAsFile", "genBoiler",
|
||||
"getFile", "Copy", "getChromeWindow", "getWindows", "runEditor",
|
||||
"runFile", "getWindowByTitle", "getWindowByType", "tempfile",
|
||||
"getMethodInWindows", "getPreference", "setPreference",
|
||||
"sleep", "assert", "unwrapNode", "TimeoutError", "waitFor",
|
||||
"takeScreenshot",
|
||||
];
|
||||
|
||||
var hwindow = Components.classes["@mozilla.org/appshell/appShellService;1"]
|
||||
.getService(Components.interfaces.nsIAppShellService)
|
||||
.hiddenDOMWindow;
|
||||
|
||||
var uuidgen = Components.classes["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Components.interfaces.nsIUUIDGenerator);
|
||||
|
||||
function Copy (obj) {
|
||||
for (var n in obj) {
|
||||
this[n] = obj[n];
|
||||
}
|
||||
}
|
||||
|
||||
function getChromeWindow(aWindow) {
|
||||
var chromeWin = aWindow
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindow)
|
||||
.QueryInterface(Components.interfaces.nsIDOMChromeWindow);
|
||||
return chromeWin;
|
||||
}
|
||||
|
||||
function getWindows(type) {
|
||||
if (type == undefined) {
|
||||
type = "";
|
||||
}
|
||||
var windows = []
|
||||
var enumerator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator)
|
||||
.getEnumerator(type);
|
||||
while(enumerator.hasMoreElements()) {
|
||||
windows.push(enumerator.getNext());
|
||||
}
|
||||
if (type == "") {
|
||||
windows.push(hwindow);
|
||||
}
|
||||
return windows;
|
||||
}
|
||||
|
||||
function getMethodInWindows (methodName) {
|
||||
for each(w in getWindows()) {
|
||||
if (w[methodName] != undefined) {
|
||||
return w[methodName];
|
||||
}
|
||||
}
|
||||
throw new Error("Method with name: '" + methodName + "' is not in any open window.");
|
||||
}
|
||||
|
||||
function getWindowByTitle(title) {
|
||||
for each(w in getWindows()) {
|
||||
if (w.document.title && w.document.title == title) {
|
||||
return w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getWindowByType(type) {
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
return wm.getMostRecentWindow(type);
|
||||
}
|
||||
|
||||
function tempfile(appention) {
|
||||
if (appention == undefined) {
|
||||
var appention = "mozmill.utils.tempfile"
|
||||
}
|
||||
var tempfile = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties).get("TmpD", Components.interfaces.nsIFile);
|
||||
tempfile.append(uuidgen.generateUUID().toString().replace('-', '').replace('{', '').replace('}',''))
|
||||
tempfile.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0777);
|
||||
tempfile.append(appention);
|
||||
tempfile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
|
||||
// do whatever you need to the created file
|
||||
return tempfile.clone()
|
||||
}
|
||||
|
||||
var checkChrome = function() {
|
||||
var loc = window.document.location.href;
|
||||
try {
|
||||
loc = window.top.document.location.href;
|
||||
} catch (e) {}
|
||||
|
||||
if (/^chrome:\/\//.test(loc)) { return true; }
|
||||
else { return false; }
|
||||
}
|
||||
|
||||
|
||||
var runFile = function(w){
|
||||
//define the interface
|
||||
var nsIFilePicker = Components.interfaces.nsIFilePicker;
|
||||
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
|
||||
//define the file picker window
|
||||
fp.init(w, "Select a File", nsIFilePicker.modeOpen);
|
||||
fp.appendFilter("JavaScript Files","*.js");
|
||||
//show the window
|
||||
var res = fp.show();
|
||||
//if we got a file
|
||||
if (res == nsIFilePicker.returnOK){
|
||||
var thefile = fp.file;
|
||||
//create the paramObj with a files array attrib
|
||||
var paramObj = {};
|
||||
paramObj.files = [];
|
||||
paramObj.files.push(thefile.path);
|
||||
}
|
||||
};
|
||||
|
||||
var saveFile = function(w, content, filename){
|
||||
//define the file interface
|
||||
var file = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
//point it at the file we want to get at
|
||||
file.initWithPath(filename);
|
||||
|
||||
// file is nsIFile, data is a string
|
||||
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
|
||||
// use 0x02 | 0x10 to open file for appending.
|
||||
foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
|
||||
// write, create, truncate
|
||||
// In a c file operation, we have no need to set file mode with or operation,
|
||||
// directly using "r" or "w" usually.
|
||||
|
||||
foStream.write(content, content.length);
|
||||
foStream.close();
|
||||
};
|
||||
|
||||
var saveAsFile = function(w, content){
|
||||
//define the interface
|
||||
var nsIFilePicker = Components.interfaces.nsIFilePicker;
|
||||
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
|
||||
//define the file picker window
|
||||
fp.init(w, "Select a File", nsIFilePicker.modeSave);
|
||||
fp.appendFilter("JavaScript Files","*.js");
|
||||
//show the window
|
||||
var res = fp.show();
|
||||
//if we got a file
|
||||
if ((res == nsIFilePicker.returnOK) || (res == nsIFilePicker.returnReplace)){
|
||||
var thefile = fp.file;
|
||||
|
||||
//forcing the user to save as a .js file
|
||||
if (thefile.path.indexOf(".js") == -1){
|
||||
//define the file interface
|
||||
var file = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
//point it at the file we want to get at
|
||||
file.initWithPath(thefile.path+".js");
|
||||
var thefile = file;
|
||||
}
|
||||
|
||||
// file is nsIFile, data is a string
|
||||
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
|
||||
// use 0x02 | 0x10 to open file for appending.
|
||||
foStream.init(thefile, 0x02 | 0x08 | 0x20, 0666, 0);
|
||||
// write, create, truncate
|
||||
// In a c file operation, we have no need to set file mode with or operation,
|
||||
// directly using "r" or "w" usually.
|
||||
foStream.write(content, content.length);
|
||||
foStream.close();
|
||||
return thefile.path;
|
||||
}
|
||||
};
|
||||
|
||||
var openFile = function(w){
|
||||
//define the interface
|
||||
var nsIFilePicker = Components.interfaces.nsIFilePicker;
|
||||
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
|
||||
//define the file picker window
|
||||
fp.init(w, "Select a File", nsIFilePicker.modeOpen);
|
||||
fp.appendFilter("JavaScript Files","*.js");
|
||||
//show the window
|
||||
var res = fp.show();
|
||||
//if we got a file
|
||||
if (res == nsIFilePicker.returnOK){
|
||||
var thefile = fp.file;
|
||||
//create the paramObj with a files array attrib
|
||||
var data = getFile(thefile.path);
|
||||
|
||||
return {path:thefile.path, data:data};
|
||||
}
|
||||
};
|
||||
|
||||
var getFile = function(path){
|
||||
//define the file interface
|
||||
var file = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
//point it at the file we want to get at
|
||||
file.initWithPath(path);
|
||||
// define file stream interfaces
|
||||
var data = "";
|
||||
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIFileInputStream);
|
||||
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Components.interfaces.nsIScriptableInputStream);
|
||||
fstream.init(file, -1, 0, 0);
|
||||
sstream.init(fstream);
|
||||
|
||||
//pull the contents of the file out
|
||||
var str = sstream.read(4096);
|
||||
while (str.length > 0) {
|
||||
data += str;
|
||||
str = sstream.read(4096);
|
||||
}
|
||||
|
||||
sstream.close();
|
||||
fstream.close();
|
||||
|
||||
//data = data.replace(/\r|\n|\r\n/g, "");
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called to get the state of an individual preference.
|
||||
*
|
||||
* @param aPrefName string The preference to get the state of.
|
||||
* @param aDefaultValue any The default value if preference was not found.
|
||||
*
|
||||
* @returns any The value of the requested preference
|
||||
*
|
||||
* @see setPref
|
||||
* Code by Henrik Skupin: <hskupin@gmail.com>
|
||||
*/
|
||||
function getPreference(aPrefName, aDefaultValue) {
|
||||
try {
|
||||
var branch = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
switch (typeof aDefaultValue) {
|
||||
case ('boolean'):
|
||||
return branch.getBoolPref(aPrefName);
|
||||
case ('string'):
|
||||
return branch.getCharPref(aPrefName);
|
||||
case ('number'):
|
||||
return branch.getIntPref(aPrefName);
|
||||
default:
|
||||
return branch.getComplexValue(aPrefName);
|
||||
}
|
||||
} catch(e) {
|
||||
return aDefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to set the state of an individual preference.
|
||||
*
|
||||
* @param aPrefName string The preference to set the state of.
|
||||
* @param aValue any The value to set the preference to.
|
||||
*
|
||||
* @returns boolean Returns true if value was successfully set.
|
||||
*
|
||||
* @see getPref
|
||||
* Code by Henrik Skupin: <hskupin@gmail.com>
|
||||
*/
|
||||
function setPreference(aName, aValue) {
|
||||
try {
|
||||
var branch = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
switch (typeof aValue) {
|
||||
case ('boolean'):
|
||||
branch.setBoolPref(aName, aValue);
|
||||
break;
|
||||
case ('string'):
|
||||
branch.setCharPref(aName, aValue);
|
||||
break;
|
||||
case ('number'):
|
||||
branch.setIntPref(aName, aValue);
|
||||
break;
|
||||
default:
|
||||
branch.setComplexValue(aName, aValue);
|
||||
}
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep for the given amount of milliseconds
|
||||
*
|
||||
* @param {number} milliseconds
|
||||
* Sleeps the given number of milliseconds
|
||||
*/
|
||||
function sleep(milliseconds) {
|
||||
// We basically just call this once after the specified number of milliseconds
|
||||
var timeup = false;
|
||||
function wait() { timeup = true; }
|
||||
hwindow.setTimeout(wait, milliseconds);
|
||||
|
||||
var thread = Components.classes["@mozilla.org/thread-manager;1"].
|
||||
getService().currentThread;
|
||||
while(!timeup) {
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the callback function evaluates to true
|
||||
*/
|
||||
function assert(callback, message, thisObject) {
|
||||
var result = callback.call(thisObject);
|
||||
|
||||
if (!result) {
|
||||
throw new Error(message || arguments.callee.name + ": Failed for '" + callback + "'");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a node which is wrapped into a XPCNativeWrapper or XrayWrapper
|
||||
*
|
||||
* @param {DOMnode} Wrapped DOM node
|
||||
* @returns {DOMNode} Unwrapped DOM node
|
||||
*/
|
||||
function unwrapNode(aNode) {
|
||||
var node = aNode;
|
||||
if (node) {
|
||||
// unwrap is not available on older branches (3.5 and 3.6) - Bug 533596
|
||||
if ("unwrap" in XPCNativeWrapper) {
|
||||
node = XPCNativeWrapper.unwrap(node);
|
||||
}
|
||||
else if (node.wrappedJSObject != null) {
|
||||
node = node.wrappedJSObject;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* TimeoutError
|
||||
*
|
||||
* Error object used for timeouts
|
||||
*/
|
||||
function TimeoutError(message, fileName, lineNumber) {
|
||||
var err = new Error();
|
||||
if (err.stack) {
|
||||
this.stack = err.stack;
|
||||
}
|
||||
this.message = message === undefined ? err.message : message;
|
||||
this.fileName = fileName === undefined ? err.fileName : fileName;
|
||||
this.lineNumber = lineNumber === undefined ? err.lineNumber : lineNumber;
|
||||
};
|
||||
TimeoutError.prototype = new Error();
|
||||
TimeoutError.prototype.constructor = TimeoutError;
|
||||
TimeoutError.prototype.name = 'TimeoutError';
|
||||
|
||||
/**
|
||||
* Waits for the callback evaluates to true
|
||||
*/
|
||||
function waitFor(callback, message, timeout, interval, thisObject) {
|
||||
timeout = timeout || 5000;
|
||||
interval = interval || 100;
|
||||
|
||||
var self = {counter: 0, result: callback.call(thisObject)};
|
||||
|
||||
function wait() {
|
||||
self.counter += interval;
|
||||
self.result = callback.call(thisObject);
|
||||
}
|
||||
|
||||
var timeoutInterval = hwindow.setInterval(wait, interval);
|
||||
var thread = Components.classes["@mozilla.org/thread-manager;1"].
|
||||
getService().currentThread;
|
||||
|
||||
while((self.result != true) && (self.counter < timeout)) {
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
|
||||
hwindow.clearInterval(timeoutInterval);
|
||||
|
||||
if (self.counter >= timeout) {
|
||||
message = message || arguments.callee.name + ": Timeout exceeded for '" + callback + "'";
|
||||
throw new TimeoutError(message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the x and y chrome offset for an element
|
||||
* See https://developer.mozilla.org/en/DOM/window.innerHeight
|
||||
*
|
||||
* Note this function will not work if the user has custom toolbars (via extension) at the bottom or left/right of the screen
|
||||
*/
|
||||
function getChromeOffset(elem) {
|
||||
var win = elem.ownerDocument.defaultView;
|
||||
// Calculate x offset
|
||||
var chromeWidth = 0;
|
||||
if (win["name"] != "sidebar") {
|
||||
chromeWidth = win.outerWidth - win.innerWidth;
|
||||
}
|
||||
|
||||
// Calculate y offset
|
||||
var chromeHeight = win.outerHeight - win.innerHeight;
|
||||
// chromeHeight == 0 means elem is already in the chrome and doesn't need the addonbar offset
|
||||
if (chromeHeight > 0) {
|
||||
// window.innerHeight doesn't include the addon or find bar, so account for these if present
|
||||
var addonbar = win.document.getElementById("addon-bar");
|
||||
if (addonbar) {
|
||||
chromeHeight -= addonbar.scrollHeight;
|
||||
}
|
||||
var findbar = win.document.getElementById("FindToolbar");
|
||||
if (findbar) {
|
||||
chromeHeight -= findbar.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return {'x':chromeWidth, 'y':chromeHeight};
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a screenshot of the specified DOM node
|
||||
*/
|
||||
function takeScreenshot(node, name, highlights) {
|
||||
var rect, win, width, height, left, top, needsOffset;
|
||||
// node can be either a window or an arbitrary DOM node
|
||||
try {
|
||||
win = node.ownerDocument.defaultView; // node is an arbitrary DOM node
|
||||
rect = node.getBoundingClientRect();
|
||||
width = rect.width;
|
||||
height = rect.height;
|
||||
top = rect.top;
|
||||
left = rect.left;
|
||||
// offset for highlights not needed as they will be relative to this node
|
||||
needsOffset = false;
|
||||
} catch (e) {
|
||||
win = node; // node is a window
|
||||
width = win.innerWidth;
|
||||
height = win.innerHeight;
|
||||
top = 0;
|
||||
left = 0;
|
||||
// offset needed for highlights to take 'outerHeight' of window into account
|
||||
needsOffset = true;
|
||||
}
|
||||
|
||||
var canvas = win.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
var ctx = canvas.getContext("2d");
|
||||
// Draws the DOM contents of the window to the canvas
|
||||
ctx.drawWindow(win, left, top, width, height, "rgb(255,255,255)");
|
||||
|
||||
// This section is for drawing a red rectangle around each element passed in via the highlights array
|
||||
if (highlights) {
|
||||
ctx.lineWidth = "2";
|
||||
ctx.strokeStyle = "red";
|
||||
ctx.save();
|
||||
|
||||
for (var i = 0; i < highlights.length; ++i) {
|
||||
var elem = highlights[i];
|
||||
rect = elem.getBoundingClientRect();
|
||||
|
||||
var offsetY = 0, offsetX = 0;
|
||||
if (needsOffset) {
|
||||
var offset = getChromeOffset(elem);
|
||||
offsetX = offset.x;
|
||||
offsetY = offset.y;
|
||||
} else {
|
||||
// Don't need to offset the window chrome, just make relative to containing node
|
||||
offsetY = -top;
|
||||
offsetX = -left;
|
||||
}
|
||||
|
||||
// Draw the rectangle
|
||||
ctx.strokeRect(rect.left + offsetX, rect.top + offsetY, rect.width, rect.height);
|
||||
}
|
||||
} // end highlights
|
||||
|
||||
// if there is a name save the file, else return dataURL
|
||||
if (name) {
|
||||
return saveCanvas(canvas, name);
|
||||
}
|
||||
return canvas.toDataURL("image/png","");
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a canvas as input and saves it to the file tempdir/name.png
|
||||
* Returns the filepath of the saved file
|
||||
*/
|
||||
function saveCanvas(canvas, name) {
|
||||
var file = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties)
|
||||
.get("TmpD", Components.interfaces.nsIFile);
|
||||
file.append("mozmill_screens");
|
||||
file.append(name + ".png");
|
||||
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
|
||||
|
||||
// create a data url from the canvas and then create URIs of the source and targets
|
||||
var io = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
var source = io.newURI(canvas.toDataURL("image/png", ""), "UTF8", null);
|
||||
var target = io.newFileURI(file)
|
||||
|
||||
// prepare to save the canvas data
|
||||
var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
|
||||
.createInstance(Components.interfaces.nsIWebBrowserPersist);
|
||||
|
||||
persist.persistFlags = Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
|
||||
persist.persistFlags |= Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
|
||||
|
||||
// save the canvas data to the file
|
||||
persist.saveURI(source, null, null, null, null, file);
|
||||
|
||||
return file.path;
|
||||
}
|
|
@ -0,0 +1,820 @@
|
|||
// Export all available functions for Mozmill
|
||||
var EXPORTED_SYMBOLS = ["sendMouseEvent", "sendChar", "sendString", "sendKey",
|
||||
"synthesizeMouse", "synthesizeMouseScroll", "synthesizeKey",
|
||||
"synthesizeMouseExpectEvent", "synthesizeKeyExpectEvent",
|
||||
"synthesizeDragStart", "synthesizeDrop", "synthesizeText",
|
||||
"disableNonTestMouseEvents", "synthesizeComposition",
|
||||
"synthesizeQuerySelectedText", "synthesizeQueryTextContent",
|
||||
"synthesizeQueryCaretRect", "synthesizeQueryTextRect",
|
||||
"synthesizeQueryEditorRect", "synthesizeCharAtPoint",
|
||||
"synthesizeSelectionSet"];
|
||||
|
||||
/**
|
||||
* Get the array with available key events
|
||||
*/
|
||||
function getKeyEvent(aWindow) {
|
||||
var win = aWindow.wrappedJSObject ? aWindow.wrappedJSObject : aWindow;
|
||||
return win.KeyEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* EventUtils provides some utility methods for creating and sending DOM events.
|
||||
* Current methods:
|
||||
* sendMouseEvent
|
||||
* sendChar
|
||||
* sendString
|
||||
* sendKey
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send a mouse event to the node aTarget (aTarget can be an id, or an
|
||||
* actual node) . The "event" passed in to aEvent is just a JavaScript
|
||||
* object with the properties set that the real mouse event object should
|
||||
* have. This includes the type of the mouse event.
|
||||
* E.g. to send an click event to the node with id 'node' you might do this:
|
||||
*
|
||||
* sendMouseEvent({type:'click'}, 'node');
|
||||
*/
|
||||
function sendMouseEvent(aEvent, aTarget, aWindow) {
|
||||
if (['click', 'mousedown', 'mouseup', 'mouseover', 'mouseout'].indexOf(aEvent.type) == -1) {
|
||||
throw new Error("sendMouseEvent doesn't know about event type '"+aEvent.type+"'");
|
||||
}
|
||||
|
||||
if (!aWindow) {
|
||||
aWindow = window;
|
||||
}
|
||||
|
||||
if (!(aTarget instanceof Element)) {
|
||||
aTarget = aWindow.document.getElementById(aTarget);
|
||||
}
|
||||
|
||||
var event = aWindow.document.createEvent('MouseEvent');
|
||||
|
||||
var typeArg = aEvent.type;
|
||||
var canBubbleArg = true;
|
||||
var cancelableArg = true;
|
||||
var viewArg = aWindow;
|
||||
var detailArg = aEvent.detail || (aEvent.type == 'click' ||
|
||||
aEvent.type == 'mousedown' ||
|
||||
aEvent.type == 'mouseup' ? 1 : 0);
|
||||
var screenXArg = aEvent.screenX || 0;
|
||||
var screenYArg = aEvent.screenY || 0;
|
||||
var clientXArg = aEvent.clientX || 0;
|
||||
var clientYArg = aEvent.clientY || 0;
|
||||
var ctrlKeyArg = aEvent.ctrlKey || false;
|
||||
var altKeyArg = aEvent.altKey || false;
|
||||
var shiftKeyArg = aEvent.shiftKey || false;
|
||||
var metaKeyArg = aEvent.metaKey || false;
|
||||
var buttonArg = aEvent.button || 0;
|
||||
var relatedTargetArg = aEvent.relatedTarget || null;
|
||||
|
||||
event.initMouseEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg,
|
||||
screenXArg, screenYArg, clientXArg, clientYArg,
|
||||
ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg,
|
||||
buttonArg, relatedTargetArg);
|
||||
|
||||
aTarget.dispatchEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the char aChar to the node with id aTarget. If aTarget is not
|
||||
* provided, use "target". This method handles casing of chars (sends the
|
||||
* right charcode, and sends a shift key for uppercase chars). No other
|
||||
* modifiers are handled at this point.
|
||||
*
|
||||
* For now this method only works for English letters (lower and upper case)
|
||||
* and the digits 0-9.
|
||||
*
|
||||
* Returns true if the keypress event was accepted (no calls to preventDefault
|
||||
* or anything like that), false otherwise.
|
||||
*/
|
||||
function sendChar(aChar, aTarget) {
|
||||
// DOM event charcodes match ASCII (JS charcodes) for a-zA-Z0-9.
|
||||
var hasShift = (aChar == aChar.toUpperCase());
|
||||
var charCode = aChar.charCodeAt(0);
|
||||
var keyCode = charCode;
|
||||
if (!hasShift) {
|
||||
// For lowercase letters, the keyCode is actually 32 less than the charCode
|
||||
keyCode -= 0x20;
|
||||
}
|
||||
|
||||
return __doEventDispatch(aTarget, charCode, keyCode, hasShift);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the string aStr to the node with id aTarget. If aTarget is not
|
||||
* provided, use "target".
|
||||
*
|
||||
* For now this method only works for English letters (lower and upper case)
|
||||
* and the digits 0-9.
|
||||
*/
|
||||
function sendString(aStr, aTarget) {
|
||||
for (var i = 0; i < aStr.length; ++i) {
|
||||
sendChar(aStr.charAt(i), aTarget);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the non-character key aKey to the node with id aTarget. If aTarget is
|
||||
* not provided, use "target". The name of the key should be a lowercase
|
||||
* version of the part that comes after "DOM_VK_" in the KeyEvent constant
|
||||
* name for this key. No modifiers are handled at this point.
|
||||
*
|
||||
* Returns true if the keypress event was accepted (no calls to preventDefault
|
||||
* or anything like that), false otherwise.
|
||||
*/
|
||||
function sendKey(aKey, aTarget, aWindow) {
|
||||
if (!aWindow)
|
||||
aWindow = window;
|
||||
|
||||
keyName = "DOM_VK_" + aKey.toUpperCase();
|
||||
|
||||
if (!getKeyEvent(aWindow)[keyName]) {
|
||||
throw "Unknown key: " + keyName;
|
||||
}
|
||||
|
||||
return __doEventDispatch(aTarget, 0, getKeyEvent(aWindow)[keyName], false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually perform event dispatch given a charCode, keyCode, and boolean for
|
||||
* whether "shift" was pressed. Send the event to the node with id aTarget. If
|
||||
* aTarget is not provided, use "target".
|
||||
*
|
||||
* Returns true if the keypress event was accepted (no calls to preventDefault
|
||||
* or anything like that), false otherwise.
|
||||
*/
|
||||
function __doEventDispatch(aTarget, aCharCode, aKeyCode, aHasShift) {
|
||||
if (aTarget === undefined) {
|
||||
aTarget = "target";
|
||||
}
|
||||
|
||||
var event = document.createEvent("KeyEvents");
|
||||
event.initKeyEvent("keydown", true, true, document.defaultView,
|
||||
false, false, aHasShift, false,
|
||||
aKeyCode, 0);
|
||||
var accepted = $(aTarget).dispatchEvent(event);
|
||||
|
||||
// Preventing the default keydown action also prevents the default
|
||||
// keypress action.
|
||||
event = document.createEvent("KeyEvents");
|
||||
if (aCharCode) {
|
||||
event.initKeyEvent("keypress", true, true, document.defaultView,
|
||||
false, false, aHasShift, false,
|
||||
0, aCharCode);
|
||||
} else {
|
||||
event.initKeyEvent("keypress", true, true, document.defaultView,
|
||||
false, false, aHasShift, false,
|
||||
aKeyCode, 0);
|
||||
}
|
||||
if (!accepted) {
|
||||
event.preventDefault();
|
||||
}
|
||||
accepted = $(aTarget).dispatchEvent(event);
|
||||
|
||||
// Always send keyup
|
||||
var event = document.createEvent("KeyEvents");
|
||||
event.initKeyEvent("keyup", true, true, document.defaultView,
|
||||
false, false, aHasShift, false,
|
||||
aKeyCode, 0);
|
||||
$(aTarget).dispatchEvent(event);
|
||||
return accepted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the key modifier flags from aEvent. Used to share code between
|
||||
* synthesizeMouse and synthesizeKey.
|
||||
*/
|
||||
function _parseModifiers(aEvent)
|
||||
{
|
||||
var hwindow = Components.classes["@mozilla.org/appshell/appShellService;1"]
|
||||
.getService(Components.interfaces.nsIAppShellService)
|
||||
.hiddenDOMWindow;
|
||||
|
||||
const masks = Components.interfaces.nsIDOMNSEvent;
|
||||
var mval = 0;
|
||||
if (aEvent.shiftKey)
|
||||
mval |= masks.SHIFT_MASK;
|
||||
if (aEvent.ctrlKey)
|
||||
mval |= masks.CONTROL_MASK;
|
||||
if (aEvent.altKey)
|
||||
mval |= masks.ALT_MASK;
|
||||
if (aEvent.metaKey)
|
||||
mval |= masks.META_MASK;
|
||||
if (aEvent.accelKey)
|
||||
mval |= (hwindow.navigator.platform.indexOf("Mac") >= 0) ? masks.META_MASK :
|
||||
masks.CONTROL_MASK;
|
||||
|
||||
return mval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a mouse event on a target. The actual client point is determined
|
||||
* by taking the aTarget's client box and offseting it by aOffsetX and
|
||||
* aOffsetY. This allows mouse clicks to be simulated by calling this method.
|
||||
*
|
||||
* aEvent is an object which may contain the properties:
|
||||
* shiftKey, ctrlKey, altKey, metaKey, accessKey, clickCount, button, type
|
||||
*
|
||||
* If the type is specified, an mouse event of that type is fired. Otherwise,
|
||||
* a mousedown followed by a mouse up is performed.
|
||||
*
|
||||
* aWindow is optional, and defaults to the current window object.
|
||||
*/
|
||||
function synthesizeMouse(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
|
||||
{
|
||||
if (!aWindow)
|
||||
aWindow = window;
|
||||
|
||||
var utils = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
if (utils) {
|
||||
var button = aEvent.button || 0;
|
||||
var clickCount = aEvent.clickCount || 1;
|
||||
var modifiers = _parseModifiers(aEvent);
|
||||
|
||||
var rect = aTarget.getBoundingClientRect();
|
||||
|
||||
var left = rect.left + aOffsetX;
|
||||
var top = rect.top + aOffsetY;
|
||||
|
||||
if (aEvent.type) {
|
||||
utils.sendMouseEvent(aEvent.type, left, top, button, clickCount, modifiers);
|
||||
}
|
||||
else {
|
||||
utils.sendMouseEvent("mousedown", left, top, button, clickCount, modifiers);
|
||||
utils.sendMouseEvent("mouseup", left, top, button, clickCount, modifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a mouse scroll event on a target. The actual client point is determined
|
||||
* by taking the aTarget's client box and offseting it by aOffsetX and
|
||||
* aOffsetY.
|
||||
*
|
||||
* aEvent is an object which may contain the properties:
|
||||
* shiftKey, ctrlKey, altKey, metaKey, accessKey, button, type, axis, delta, hasPixels
|
||||
*
|
||||
* If the type is specified, a mouse scroll event of that type is fired. Otherwise,
|
||||
* "DOMMouseScroll" is used.
|
||||
*
|
||||
* If the axis is specified, it must be one of "horizontal" or "vertical". If not specified,
|
||||
* "vertical" is used.
|
||||
*
|
||||
* 'delta' is the amount to scroll by (can be positive or negative). It must
|
||||
* be specified.
|
||||
*
|
||||
* 'hasPixels' specifies whether kHasPixels should be set in the scrollFlags.
|
||||
*
|
||||
* aWindow is optional, and defaults to the current window object.
|
||||
*/
|
||||
function synthesizeMouseScroll(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
|
||||
{
|
||||
if (!aWindow)
|
||||
aWindow = window;
|
||||
|
||||
var utils = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
if (utils) {
|
||||
// See nsMouseScrollFlags in nsGUIEvent.h
|
||||
const kIsVertical = 0x02;
|
||||
const kIsHorizontal = 0x04;
|
||||
const kHasPixels = 0x08;
|
||||
|
||||
var button = aEvent.button || 0;
|
||||
var modifiers = _parseModifiers(aEvent);
|
||||
|
||||
var rect = aTarget.getBoundingClientRect();
|
||||
|
||||
var left = rect.left;
|
||||
var top = rect.top;
|
||||
|
||||
var type = aEvent.type || "DOMMouseScroll";
|
||||
var axis = aEvent.axis || "vertical";
|
||||
var scrollFlags = (axis == "horizontal") ? kIsHorizontal : kIsVertical;
|
||||
if (aEvent.hasPixels) {
|
||||
scrollFlags |= kHasPixels;
|
||||
}
|
||||
utils.sendMouseScrollEvent(type, left + aOffsetX, top + aOffsetY, button,
|
||||
scrollFlags, aEvent.delta, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a key event. It is targeted at whatever would be targeted by an
|
||||
* actual keypress by the user, typically the focused element.
|
||||
*
|
||||
* aKey should be either a character or a keycode starting with VK_ such as
|
||||
* VK_ENTER.
|
||||
*
|
||||
* aEvent is an object which may contain the properties:
|
||||
* shiftKey, ctrlKey, altKey, metaKey, accessKey, type
|
||||
*
|
||||
* If the type is specified, a key event of that type is fired. Otherwise,
|
||||
* a keydown, a keypress and then a keyup event are fired in sequence.
|
||||
*
|
||||
* aWindow is optional, and defaults to the current window object.
|
||||
*/
|
||||
function synthesizeKey(aKey, aEvent, aWindow)
|
||||
{
|
||||
if (!aWindow)
|
||||
aWindow = window;
|
||||
|
||||
var utils = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
if (utils) {
|
||||
var keyCode = 0, charCode = 0;
|
||||
if (aKey.indexOf("VK_") == 0)
|
||||
keyCode = getKeyEvent(aWindow)["DOM_" + aKey];
|
||||
else
|
||||
charCode = aKey.charCodeAt(0);
|
||||
|
||||
var modifiers = _parseModifiers(aEvent);
|
||||
|
||||
if (aEvent.type) {
|
||||
utils.sendKeyEvent(aEvent.type, keyCode, charCode, modifiers);
|
||||
}
|
||||
else {
|
||||
var keyDownDefaultHappened =
|
||||
utils.sendKeyEvent("keydown", keyCode, charCode, modifiers);
|
||||
utils.sendKeyEvent("keypress", keyCode, charCode, modifiers,
|
||||
!keyDownDefaultHappened);
|
||||
utils.sendKeyEvent("keyup", keyCode, charCode, modifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _gSeenEvent = false;
|
||||
|
||||
/**
|
||||
* Indicate that an event with an original target of aExpectedTarget and
|
||||
* a type of aExpectedEvent is expected to be fired, or not expected to
|
||||
* be fired.
|
||||
*/
|
||||
function _expectEvent(aExpectedTarget, aExpectedEvent, aTestName)
|
||||
{
|
||||
if (!aExpectedTarget || !aExpectedEvent)
|
||||
return null;
|
||||
|
||||
_gSeenEvent = false;
|
||||
|
||||
var type = (aExpectedEvent.charAt(0) == "!") ?
|
||||
aExpectedEvent.substring(1) : aExpectedEvent;
|
||||
var eventHandler = function(event) {
|
||||
var epassed = (!_gSeenEvent && event.originalTarget == aExpectedTarget &&
|
||||
event.type == type);
|
||||
if (!epassed)
|
||||
throw new Error(aTestName + " " + type + " event target " +
|
||||
(_gSeenEvent ? "twice" : ""));
|
||||
_gSeenEvent = true;
|
||||
};
|
||||
|
||||
aExpectedTarget.addEventListener(type, eventHandler, false);
|
||||
return eventHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the event was fired or not. The event handler aEventHandler
|
||||
* will be removed.
|
||||
*/
|
||||
function _checkExpectedEvent(aExpectedTarget, aExpectedEvent, aEventHandler, aTestName)
|
||||
{
|
||||
if (aEventHandler) {
|
||||
var expectEvent = (aExpectedEvent.charAt(0) != "!");
|
||||
var type = expectEvent ? aExpectedEvent : aExpectedEvent.substring(1);
|
||||
aExpectedTarget.removeEventListener(type, aEventHandler, false);
|
||||
var desc = type + " event";
|
||||
if (expectEvent)
|
||||
desc += " not";
|
||||
if (_gSeenEvent != expectEvent)
|
||||
throw new Error(aTestName + ": " + desc + " fired.");
|
||||
}
|
||||
|
||||
_gSeenEvent = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to synthesizeMouse except that a test is performed to see if an
|
||||
* event is fired at the right target as a result.
|
||||
*
|
||||
* aExpectedTarget - the expected originalTarget of the event.
|
||||
* aExpectedEvent - the expected type of the event, such as 'select'.
|
||||
* aTestName - the test name when outputing results
|
||||
*
|
||||
* To test that an event is not fired, use an expected type preceded by an
|
||||
* exclamation mark, such as '!select'. This might be used to test that a
|
||||
* click on a disabled element doesn't fire certain events for instance.
|
||||
*
|
||||
* aWindow is optional, and defaults to the current window object.
|
||||
*/
|
||||
function synthesizeMouseExpectEvent(aTarget, aOffsetX, aOffsetY, aEvent,
|
||||
aExpectedTarget, aExpectedEvent, aTestName,
|
||||
aWindow)
|
||||
{
|
||||
var eventHandler = _expectEvent(aExpectedTarget, aExpectedEvent, aTestName);
|
||||
synthesizeMouse(aTarget, aOffsetX, aOffsetY, aEvent, aWindow);
|
||||
_checkExpectedEvent(aExpectedTarget, aExpectedEvent, eventHandler, aTestName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to synthesizeKey except that a test is performed to see if an
|
||||
* event is fired at the right target as a result.
|
||||
*
|
||||
* aExpectedTarget - the expected originalTarget of the event.
|
||||
* aExpectedEvent - the expected type of the event, such as 'select'.
|
||||
* aTestName - the test name when outputing results
|
||||
*
|
||||
* To test that an event is not fired, use an expected type preceded by an
|
||||
* exclamation mark, such as '!select'.
|
||||
*
|
||||
* aWindow is optional, and defaults to the current window object.
|
||||
*/
|
||||
function synthesizeKeyExpectEvent(key, aEvent, aExpectedTarget, aExpectedEvent,
|
||||
aTestName, aWindow)
|
||||
{
|
||||
var eventHandler = _expectEvent(aExpectedTarget, aExpectedEvent, aTestName);
|
||||
synthesizeKey(key, aEvent, aWindow);
|
||||
_checkExpectedEvent(aExpectedTarget, aExpectedEvent, eventHandler, aTestName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulate a dragstart event.
|
||||
* element - element to fire the dragstart event on
|
||||
* expectedDragData - the data you expect the data transfer to contain afterwards
|
||||
* This data is in the format:
|
||||
* [ [ {type: value, data: value, test: function}, ... ], ... ]
|
||||
* can be null
|
||||
* aWindow - optional; defaults to the current window object.
|
||||
* x - optional; initial x coordinate
|
||||
* y - optional; initial y coordinate
|
||||
* Returns null if data matches.
|
||||
* Returns the event.dataTransfer if data does not match
|
||||
*
|
||||
* eqTest is an optional function if comparison can't be done with x == y;
|
||||
* function (actualData, expectedData) {return boolean}
|
||||
* @param actualData from dataTransfer
|
||||
* @param expectedData from expectedDragData
|
||||
* see bug 462172 for example of use
|
||||
*
|
||||
*/
|
||||
function synthesizeDragStart(element, expectedDragData, aWindow, x, y)
|
||||
{
|
||||
if (!aWindow)
|
||||
aWindow = window;
|
||||
x = x || 2;
|
||||
y = y || 2;
|
||||
const step = 9;
|
||||
|
||||
var result = "trapDrag was not called";
|
||||
var trapDrag = function(event) {
|
||||
try {
|
||||
var dataTransfer = event.dataTransfer;
|
||||
result = null;
|
||||
if (!dataTransfer)
|
||||
throw "no dataTransfer";
|
||||
if (expectedDragData == null ||
|
||||
dataTransfer.mozItemCount != expectedDragData.length)
|
||||
throw dataTransfer;
|
||||
for (var i = 0; i < dataTransfer.mozItemCount; i++) {
|
||||
var dtTypes = dataTransfer.mozTypesAt(i);
|
||||
if (dtTypes.length != expectedDragData[i].length)
|
||||
throw dataTransfer;
|
||||
for (var j = 0; j < dtTypes.length; j++) {
|
||||
if (dtTypes[j] != expectedDragData[i][j].type)
|
||||
throw dataTransfer;
|
||||
var dtData = dataTransfer.mozGetDataAt(dtTypes[j],i);
|
||||
if (expectedDragData[i][j].eqTest) {
|
||||
if (!expectedDragData[i][j].eqTest(dtData, expectedDragData[i][j].data))
|
||||
throw dataTransfer;
|
||||
}
|
||||
else if (expectedDragData[i][j].data != dtData)
|
||||
throw dataTransfer;
|
||||
}
|
||||
}
|
||||
} catch(ex) {
|
||||
result = ex;
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
aWindow.addEventListener("dragstart", trapDrag, false);
|
||||
synthesizeMouse(element, x, y, { type: "mousedown" }, aWindow);
|
||||
x += step; y += step;
|
||||
synthesizeMouse(element, x, y, { type: "mousemove" }, aWindow);
|
||||
x += step; y += step;
|
||||
synthesizeMouse(element, x, y, { type: "mousemove" }, aWindow);
|
||||
aWindow.removeEventListener("dragstart", trapDrag, false);
|
||||
synthesizeMouse(element, x, y, { type: "mouseup" }, aWindow);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulate a drop by emulating a dragstart and firing events dragenter, dragover, and drop.
|
||||
* srcElement - the element to use to start the drag, usually the same as destElement
|
||||
* but if destElement isn't suitable to start a drag on pass a suitable
|
||||
* element for srcElement
|
||||
* destElement - the element to fire the dragover, dragleave and drop events
|
||||
* dragData - the data to supply for the data transfer
|
||||
* This data is in the format:
|
||||
* [ [ {type: value, data: value}, ...], ... ]
|
||||
* dropEffect - the drop effect to set during the dragstart event, or 'move' if null
|
||||
* aWindow - optional; defaults to the current window object.
|
||||
*
|
||||
* Returns the drop effect that was desired.
|
||||
*/
|
||||
function synthesizeDrop(srcElement, destElement, dragData, dropEffect, aWindow)
|
||||
{
|
||||
if (!aWindow)
|
||||
aWindow = window;
|
||||
|
||||
var dataTransfer;
|
||||
var trapDrag = function(event) {
|
||||
dataTransfer = event.dataTransfer;
|
||||
for (var i = 0; i < dragData.length; i++) {
|
||||
var item = dragData[i];
|
||||
for (var j = 0; j < item.length; j++) {
|
||||
dataTransfer.mozSetDataAt(item[j].type, item[j].data, i);
|
||||
}
|
||||
}
|
||||
dataTransfer.dropEffect = dropEffect || "move";
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
// need to use real mouse action
|
||||
aWindow.addEventListener("dragstart", trapDrag, true);
|
||||
synthesizeMouse(srcElement, 2, 2, { type: "mousedown" }, aWindow);
|
||||
synthesizeMouse(srcElement, 11, 11, { type: "mousemove" }, aWindow);
|
||||
synthesizeMouse(srcElement, 20, 20, { type: "mousemove" }, aWindow);
|
||||
aWindow.removeEventListener("dragstart", trapDrag, true);
|
||||
|
||||
event = aWindow.document.createEvent("DragEvents");
|
||||
event.initDragEvent("dragenter", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
|
||||
destElement.dispatchEvent(event);
|
||||
|
||||
var event = aWindow.document.createEvent("DragEvents");
|
||||
event.initDragEvent("dragover", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
|
||||
if (destElement.dispatchEvent(event)) {
|
||||
synthesizeMouse(destElement, 20, 20, { type: "mouseup" }, aWindow);
|
||||
return "none";
|
||||
}
|
||||
|
||||
if (dataTransfer.dropEffect != "none") {
|
||||
event = aWindow.document.createEvent("DragEvents");
|
||||
event.initDragEvent("drop", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
|
||||
destElement.dispatchEvent(event);
|
||||
}
|
||||
synthesizeMouse(destElement, 20, 20, { type: "mouseup" }, aWindow);
|
||||
|
||||
return dataTransfer.dropEffect;
|
||||
}
|
||||
|
||||
function disableNonTestMouseEvents(aDisable)
|
||||
{
|
||||
var utils =
|
||||
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
if (utils)
|
||||
utils.disableNonTestMouseEvents(aDisable);
|
||||
}
|
||||
|
||||
function _getDOMWindowUtils(aWindow)
|
||||
{
|
||||
if (!aWindow) {
|
||||
aWindow = window;
|
||||
}
|
||||
return aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a composition event.
|
||||
*
|
||||
* @param aIsCompositionStart If true, this synthesize compositionstart event.
|
||||
* Otherwise, compositionend event.
|
||||
* @param aWindow Optional (If null, current |window| will be used)
|
||||
*/
|
||||
function synthesizeComposition(aIsCompositionStart, aWindow)
|
||||
{
|
||||
var utils = _getDOMWindowUtils(aWindow);
|
||||
if (!utils) {
|
||||
return;
|
||||
}
|
||||
|
||||
utils.sendCompositionEvent(aIsCompositionStart ?
|
||||
"compositionstart" : "compositionend");
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a text event.
|
||||
*
|
||||
* @param aEvent The text event's information, this has |composition|
|
||||
* and |caret| members. |composition| has |string| and
|
||||
* |clauses| members. |clauses| must be array object. Each
|
||||
* object has |length| and |attr|. And |caret| has |start| and
|
||||
* |length|. See the following tree image.
|
||||
*
|
||||
* aEvent
|
||||
* +-- composition
|
||||
* | +-- string
|
||||
* | +-- clauses[]
|
||||
* | +-- length
|
||||
* | +-- attr
|
||||
* +-- caret
|
||||
* +-- start
|
||||
* +-- length
|
||||
*
|
||||
* Set the composition string to |composition.string|. Set its
|
||||
* clauses information to the |clauses| array.
|
||||
*
|
||||
* When it's composing, set the each clauses' length to the
|
||||
* |composition.clauses[n].length|. The sum of the all length
|
||||
* values must be same as the length of |composition.string|.
|
||||
* Set nsIDOMWindowUtils.COMPOSITION_ATTR_* to the
|
||||
* |composition.clauses[n].attr|.
|
||||
*
|
||||
* When it's not composing, set 0 to the
|
||||
* |composition.clauses[0].length| and
|
||||
* |composition.clauses[0].attr|.
|
||||
*
|
||||
* Set caret position to the |caret.start|. It's offset from
|
||||
* the start of the composition string. Set caret length to
|
||||
* |caret.length|. If it's larger than 0, it should be wide
|
||||
* caret. However, current nsEditor doesn't support wide
|
||||
* caret, therefore, you should always set 0 now.
|
||||
*
|
||||
* @param aWindow Optional (If null, current |window| will be used)
|
||||
*/
|
||||
function synthesizeText(aEvent, aWindow)
|
||||
{
|
||||
var utils = _getDOMWindowUtils(aWindow);
|
||||
if (!utils) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aEvent.composition || !aEvent.composition.clauses ||
|
||||
!aEvent.composition.clauses[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
var firstClauseLength = aEvent.composition.clauses[0].length;
|
||||
var firstClauseAttr = aEvent.composition.clauses[0].attr;
|
||||
var secondClauseLength = 0;
|
||||
var secondClauseAttr = 0;
|
||||
var thirdClauseLength = 0;
|
||||
var thirdClauseAttr = 0;
|
||||
if (aEvent.composition.clauses[1]) {
|
||||
secondClauseLength = aEvent.composition.clauses[1].length;
|
||||
secondClauseAttr = aEvent.composition.clauses[1].attr;
|
||||
if (aEvent.composition.clauses[2]) {
|
||||
thirdClauseLength = aEvent.composition.clauses[2].length;
|
||||
thirdClauseAttr = aEvent.composition.clauses[2].attr;
|
||||
}
|
||||
}
|
||||
|
||||
var caretStart = -1;
|
||||
var caretLength = 0;
|
||||
if (aEvent.caret) {
|
||||
caretStart = aEvent.caret.start;
|
||||
caretLength = aEvent.caret.length;
|
||||
}
|
||||
|
||||
utils.sendTextEvent(aEvent.composition.string,
|
||||
firstClauseLength, firstClauseAttr,
|
||||
secondClauseLength, secondClauseAttr,
|
||||
thirdClauseLength, thirdClauseAttr,
|
||||
caretStart, caretLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a query selected text event.
|
||||
*
|
||||
* @param aWindow Optional (If null, current |window| will be used)
|
||||
* @return An nsIQueryContentEventResult object. If this failed,
|
||||
* the result might be null.
|
||||
*/
|
||||
function synthesizeQuerySelectedText(aWindow)
|
||||
{
|
||||
var utils = _getDOMWindowUtils(aWindow);
|
||||
if (!utils) {
|
||||
return nsnull;
|
||||
}
|
||||
return utils.sendQueryContentEvent(utils.QUERY_SELECTED_TEXT, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a query text content event.
|
||||
*
|
||||
* @param aOffset The character offset. 0 means the first character in the
|
||||
* selection root.
|
||||
* @param aLength The length of getting text. If the length is too long,
|
||||
* the extra length is ignored.
|
||||
* @param aWindow Optional (If null, current |window| will be used)
|
||||
* @return An nsIQueryContentEventResult object. If this failed,
|
||||
* the result might be null.
|
||||
*/
|
||||
function synthesizeQueryTextContent(aOffset, aLength, aWindow)
|
||||
{
|
||||
var utils = _getDOMWindowUtils(aWindow);
|
||||
if (!utils) {
|
||||
return nsnull;
|
||||
}
|
||||
return utils.sendQueryContentEvent(utils.QUERY_TEXT_CONTENT,
|
||||
aOffset, aLength, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a query caret rect event.
|
||||
*
|
||||
* @param aOffset The caret offset. 0 means left side of the first character
|
||||
* in the selection root.
|
||||
* @param aWindow Optional (If null, current |window| will be used)
|
||||
* @return An nsIQueryContentEventResult object. If this failed,
|
||||
* the result might be null.
|
||||
*/
|
||||
function synthesizeQueryCaretRect(aOffset, aWindow)
|
||||
{
|
||||
var utils = _getDOMWindowUtils(aWindow);
|
||||
if (!utils) {
|
||||
return nsnull;
|
||||
}
|
||||
return utils.sendQueryContentEvent(utils.QUERY_CARET_RECT,
|
||||
aOffset, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a query text rect event.
|
||||
*
|
||||
* @param aOffset The character offset. 0 means the first character in the
|
||||
* selection root.
|
||||
* @param aLength The length of the text. If the length is too long,
|
||||
* the extra length is ignored.
|
||||
* @param aWindow Optional (If null, current |window| will be used)
|
||||
* @return An nsIQueryContentEventResult object. If this failed,
|
||||
* the result might be null.
|
||||
*/
|
||||
function synthesizeQueryTextRect(aOffset, aLength, aWindow)
|
||||
{
|
||||
var utils = _getDOMWindowUtils(aWindow);
|
||||
if (!utils) {
|
||||
return nsnull;
|
||||
}
|
||||
return utils.sendQueryContentEvent(utils.QUERY_TEXT_RECT,
|
||||
aOffset, aLength, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a query editor rect event.
|
||||
*
|
||||
* @param aWindow Optional (If null, current |window| will be used)
|
||||
* @return An nsIQueryContentEventResult object. If this failed,
|
||||
* the result might be null.
|
||||
*/
|
||||
function synthesizeQueryEditorRect(aWindow)
|
||||
{
|
||||
var utils = _getDOMWindowUtils(aWindow);
|
||||
if (!utils) {
|
||||
return nsnull;
|
||||
}
|
||||
return utils.sendQueryContentEvent(utils.QUERY_EDITOR_RECT, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a character at point event.
|
||||
*
|
||||
* @param aX, aY The offset in the client area of the DOM window.
|
||||
* @param aWindow Optional (If null, current |window| will be used)
|
||||
* @return An nsIQueryContentEventResult object. If this failed,
|
||||
* the result might be null.
|
||||
*/
|
||||
function synthesizeCharAtPoint(aX, aY, aWindow)
|
||||
{
|
||||
var utils = _getDOMWindowUtils(aWindow);
|
||||
if (!utils) {
|
||||
return nsnull;
|
||||
}
|
||||
return utils.sendQueryContentEvent(utils.QUERY_CHARACTER_AT_POINT,
|
||||
0, 0, aX, aY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a selection set event.
|
||||
*
|
||||
* @param aOffset The character offset. 0 means the first character in the
|
||||
* selection root.
|
||||
* @param aLength The length of the text. If the length is too long,
|
||||
* the extra length is ignored.
|
||||
* @param aReverse If true, the selection is from |aOffset + aLength| to
|
||||
* |aOffset|. Otherwise, from |aOffset| to |aOffset + aLength|.
|
||||
* @param aWindow Optional (If null, current |window| will be used)
|
||||
* @return True, if succeeded. Otherwise false.
|
||||
*/
|
||||
function synthesizeSelectionSet(aOffset, aLength, aReverse, aWindow)
|
||||
{
|
||||
var utils = _getDOMWindowUtils(aWindow);
|
||||
if (!utils) {
|
||||
return false;
|
||||
}
|
||||
return utils.sendSelectionSetEvent(aOffset, aLength, aReverse);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// ***** BEGIN LICENSE BLOCK *****// ***** BEGIN LICENSE BLOCK *****
|
||||
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public License Version
|
||||
// 1.1 (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
// http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS" basis,
|
||||
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
// for the specific language governing rights and limitations under the
|
||||
// License.
|
||||
//
|
||||
// The Original Code is Mozilla Corporation Code.
|
||||
//
|
||||
// The Initial Developer of the Original Code is
|
||||
// Mikeal Rogers.
|
||||
// Portions created by the Initial Developer are Copyright (C) 2008
|
||||
// the Initial Developer. All Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
// Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
// in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
// of those above. If you wish to allow use of your version of this file only
|
||||
// under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
// use your version of this file under the terms of the MPL, indicate your
|
||||
// decision by deleting the provisions above and replace them with the notice
|
||||
// and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
// the provisions above, a recipient may use your version of this file under
|
||||
// the terms of any one of the MPL, the GPL or the LGPL.
|
||||
//
|
||||
// ***** END LICENSE BLOCK *****
|
||||
|
||||
var EXPORTED_SYMBOLS = ['inArray', 'getSet', 'indexOf', 'rindexOf', 'compare'];
|
||||
|
||||
function inArray (array, value) {
|
||||
for (i in array) {
|
||||
if (value == array[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSet (array) {
|
||||
var narray = [];
|
||||
for (i in array) {
|
||||
if ( !inArray(narray, array[i]) ) {
|
||||
narray.push(array[i]);
|
||||
}
|
||||
}
|
||||
return narray;
|
||||
}
|
||||
|
||||
function indexOf (array, v, offset) {
|
||||
for (i in array) {
|
||||
if (offset == undefined || i >= offset) {
|
||||
if ( !isNaN(i) && array[i] == v) {
|
||||
return new Number(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function rindexOf (array, v) {
|
||||
var l = array.length;
|
||||
for (i in array) {
|
||||
if (!isNaN(i)) {
|
||||
var i = new Number(i)
|
||||
}
|
||||
if (!isNaN(i) && array[l - i] == v) {
|
||||
return l - i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function compare (array, carray) {
|
||||
if (array.length != carray.length) {
|
||||
return false;
|
||||
}
|
||||
for (i in array) {
|
||||
if (array[i] != carray[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// ***** BEGIN LICENSE BLOCK *****// ***** BEGIN LICENSE BLOCK *****
|
||||
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public License Version
|
||||
// 1.1 (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
// http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS" basis,
|
||||
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
// for the specific language governing rights and limitations under the
|
||||
// License.
|
||||
//
|
||||
// The Original Code is Mozilla Corporation Code.
|
||||
//
|
||||
// The Initial Developer of the Original Code is
|
||||
// Mikeal Rogers.
|
||||
// Portions created by the Initial Developer are Copyright (C) 2008
|
||||
// the Initial Developer. All Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
// Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
// in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
// of those above. If you wish to allow use of your version of this file only
|
||||
// under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
// use your version of this file under the terms of the MPL, indicate your
|
||||
// decision by deleting the provisions above and replace them with the notice
|
||||
// and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
// the provisions above, a recipient may use your version of this file under
|
||||
// the terms of any one of the MPL, the GPL or the LGPL.
|
||||
//
|
||||
// ***** END LICENSE BLOCK *****
|
||||
|
||||
var EXPORTED_SYMBOLS = ['getAttributes'];
|
||||
|
||||
|
||||
var getAttributes = function (node) {
|
||||
var attributes = {};
|
||||
for (i in node.attributes) {
|
||||
if ( !isNaN(i) ) {
|
||||
try {
|
||||
var attr = node.attributes[i];
|
||||
attributes[attr.name] = attr.value;
|
||||
} catch (err) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче