Merge mozilla-central to mozilla-inbound

This commit is contained in:
Ed Morley 2011-09-01 08:49:23 +01:00
Родитель 12f840102f c62c25def9
Коммит e4c3394a35
129 изменённых файлов: 14823 добавлений и 2126 удалений

Просмотреть файл

@ -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
Просмотреть файл

@ -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

Просмотреть файл

@ -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):
###############################################################################

Просмотреть файл

@ -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 += \

Просмотреть файл

@ -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
################################################################################

241
nsprpub/configure поставляемый
Просмотреть файл

@ -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(/&nbsp;/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;
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше