merge mozilla-central to accessibility

--HG--
rename : widget/src/gtk2/nsWindow.cpp => widget/gtk2/nsWindow.cpp
rename : widget/src/gtk2/nsWindow.h => widget/gtk2/nsWindow.h
This commit is contained in:
Trevor Saunders 2012-01-05 21:43:01 -05:00
commit 94931765ea
1443 changed files with 30774 additions and 30856 deletions

View File

@ -36,3 +36,6 @@ _OPT\.OBJ/
# Java HTML5 parser classes
^parser/html/java/(html|java)parser/
# SVN directories
\.svn/

View File

@ -819,7 +819,7 @@ called, Windows sends the window in question a <a
href="http://lxr.mozilla.org/seamonkey/search?string=WM_GETOBJECT">WM_GETOBJECT</a>
message requesting an IAccessible for your root object in the window. In
our case, this event is received in <a
href="http://lxr.mozilla.org/seamonkey/source/widget/src/windows/nsWindow.cpp#4370">mozilla/widget/src/windows/nsWindow.cpp</a>.
href="http://lxr.mozilla.org/mozilla-central/source/widget/windows/nsWindow.cpp#4370">mozilla/widget/windows/nsWindow.cpp</a>.
We send back an IAccessible pointer which can be used by the client to
get information about this root object. The assistive technology will
use that root IAccessible to traverse the rest of the object tree, by

View File

@ -40,7 +40,7 @@
#import "mozView.h"
/* This protocol's primary use is so widget/src/cocoa can talk back to us
/* This protocol's primary use is so widget/cocoa can talk back to us
properly.
ChildView owns the topmost mozRootAccessible, and needs to take care of setting up

View File

@ -384,7 +384,7 @@ pref("security.fileuri.strict_origin_policy", false);
// Temporarily force-enable GL compositing. This is default-disabled
// deep within the bowels of the widgetry system. Remove me when GL
// compositing isn't default disabled in widget/src/android.
// compositing isn't default disabled in widget/android.
pref("layers.acceleration.force-enabled", true);
// screen.enabled and screen.brightness properties.

View File

@ -71,6 +71,8 @@ ifdef MOZ_INSTALLER
# uninstaller is included with the application for mar file generation.
libs::
$(MAKE) -C installer/windows uninstaller
ifdef MOZ_MAINTENANCE_SERVICE
$(MAKE) -C installer/windows maintenanceservice_installer
endif
endif
endif

View File

@ -46,6 +46,10 @@
#include <sys/resource.h>
#endif
#ifdef XP_MACOSX
#include "MacQuirks.h"
#endif
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
@ -208,6 +212,10 @@ int main(int argc, char* argv[])
{
char exePath[MAXPATHLEN];
#ifdef XP_MACOSX
TriggerQuirks();
#endif
nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
if (NS_FAILED(rv)) {
Output("Couldn't calculate the application directory.\n");

View File

@ -200,6 +200,11 @@ pref("app.update.showInstalledUI", false);
// versions.
pref("app.update.incompatible.mode", 0);
// Whether or not to attempt using the service for updates.
#ifdef MOZ_MAINTENANCE_SERVICE
pref("app.update.service.enabled", true);
#endif
// Symmetric (can be overridden by individual extensions) update preferences.
// e.g.
// extensions.{GUID}.update.enabled

View File

@ -188,9 +188,13 @@ appUpdater.prototype =
// true when there is an update already staged / ready to be applied.
get isPending() {
if (this.update)
return this.update.state == "pending";
return this.um.activeUpdate && this.um.activeUpdate.state == "pending";
if (this.update) {
return this.update.state == "pending" ||
this.update.state == "pending-service";
}
return this.um.activeUpdate &&
(this.um.activeUpdate.state == "pending" ||
this.um.activeUpdate.state == "pending-service");
},
// true when there is an update download in progress.

View File

@ -140,7 +140,7 @@
<menuitem id="context-copyimage-contents"
label="&copyImageContentsCmd.label;"
accesskey="&copyImageContentsCmd.accesskey;"
oncommand="goDoCommand('cmd_copyImageContents');"/>
oncommand="goDoCommand('cmd_copyImage');"/>
#endif
<menuitem id="context-copyimage"
label="&copyImageCmd.label;"

View File

@ -13,6 +13,7 @@ tabbrowser {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabs");
}
#tabbrowser-tabs:not([overflow="true"]) ~ #alltabs-button,
#tabbrowser-tabs:not([overflow="true"]) + #new-tab-button,
#tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
#TabsToolbar[currentset]:not([currentset*="tabbrowser-tabs,new-tab-button"]) > #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
@ -20,6 +21,10 @@ tabbrowser {
visibility: collapse;
}
#tabbrowser-tabs:not([overflow="true"])[using-closing-tabs-spacer] ~ #alltabs-button {
visibility: hidden; /* temporary space to keep a tab's close button under the cursor */
}
.tabbrowser-tab {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tab");
}

View File

@ -4707,10 +4707,12 @@ var XULBrowserWindow = {
document.documentElement.removeAttribute("disablechrome");
// Disable find commands in documents that ask for them to be disabled.
let docElt = content.document.documentElement;
let disableFind = aLocationURI &&
(docElt && docElt.getAttribute("disablefastfind") == "true") &&
(aLocationURI.schemeIs("about") || aLocationURI.schemeIs("chrome"));
let disableFind = false;
if (aLocationURI &&
(aLocationURI.schemeIs("about") || aLocationURI.schemeIs("chrome"))) {
let docElt = content.document.documentElement;
disableFind = docElt && docElt.getAttribute("disablefastfind") == "true";
}
let findCommands = [document.getElementById("cmd_find"),
document.getElementById("cmd_findAgain"),
document.getElementById("cmd_findPrevious")];

View File

@ -2927,7 +2927,6 @@
<field name="_tabDefaultMaxWidth">NaN</field>
<field name="_lastTabClosedByMouse">false</field>
<field name="_hasTabTempMaxWidth">false</field>
<field name="_usingClosingTabsSpacer">false</field>
<!-- Try to keep the active tab's close button under the mouse cursor -->
<method name="_lockTabSizing">
@ -2995,7 +2994,7 @@
<body><![CDATA[
let spacer = this._closingTabsSpacer;
spacer.style.width = parseFloat(spacer.style.width) + pixels + "px";
this._usingClosingTabsSpacer = true;
this.setAttribute("using-closing-tabs-spacer", "true");
this.tabbrowser.addEventListener("mousemove", this, false);
window.addEventListener("mouseout", this, false);
]]></body>
@ -3005,14 +3004,16 @@
<body><![CDATA[
this.tabbrowser.removeEventListener("mousemove", this, false);
window.removeEventListener("mouseout", this, false);
if (this._hasTabTempMaxWidth) {
this._hasTabTempMaxWidth = false;
let tabs = this.tabbrowser.visibleTabs;
for (let i = 0; i < tabs.length; i++)
tabs[i].style.maxWidth = "";
}
if (this._usingClosingTabsSpacer) {
this._usingClosingTabsSpacer = false;
if (this.hasAttribute("using-closing-tabs-spacer")) {
this.removeAttribute("using-closing-tabs-spacer");
this._closingTabsSpacer.style.width = 0;
}
]]></body>

View File

@ -531,6 +531,25 @@ var gAdvancedPane = {
// the warnIncompatible checkbox value is set by readAddonWarn
warnIncompatible.disabled = radiogroup.disabled || modePref.locked ||
!enabledPref.value || !autoPref.value;
#ifdef MOZ_MAINTENANCE_SERVICE
// Check to see if the maintenance service is installed.
// If it is don't show the preference at all.
var installed;
try {
var wrk = Components.classes["@mozilla.org/windows-registry-key;1"]
.createInstance(Components.interfaces.nsIWindowsRegKey);
wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
"SOFTWARE\\Mozilla\\MaintenanceService",
wrk.ACCESS_READ | wrk.WOW64_64);
installed = wrk.readIntValue("Installed");
wrk.close();
} catch(e) {
}
if (installed != 1) {
document.getElementById("useService").hidden = true;
}
#endif
},
/**

View File

@ -108,6 +108,12 @@
<preference id="app.update.disable_button.showUpdateHistory"
name="app.update.disable_button.showUpdateHistory"
type="bool"/>
#ifdef MOZ_MAINTENANCE_SERVICE
<preference id="app.update.service.enabled"
name="app.update.service.enabled"
type="bool"/>
#endif
#endif
<preference id="browser.search.update" name="browser.search.update" type="bool"/>
@ -336,6 +342,13 @@
preference="app.update.disable_button.showUpdateHistory"
oncommand="gAdvancedPane.showUpdates();"/>
</hbox>
#ifdef MOZ_MAINTENANCE_SERVICE
<checkbox id="useService"
label="&useService.label;"
accesskey="&useService.accesskey;"
preference="app.update.service.enabled"/>
#endif
</groupbox>
#endif
<groupbox id="updateOthers">

View File

@ -41,6 +41,12 @@ MOZ_APP_VENDOR=Mozilla
MOZ_UPDATER=1
MOZ_PHOENIX=1
if test "$OS_ARCH" = "WINNT"; then
if ! test "$HAVE_64BIT_OS"; then
MOZ_MAINTENANCE_SERVICE=1
fi
fi
MOZ_CHROME_FILE_FORMAT=omni
MOZ_SAFE_BROWSING=1
MOZ_SERVICES_SYNC=1

View File

@ -332,21 +332,7 @@ var Scratchpad = {
"Scratchpad", 1);
}
catch (ex) {
this.openWebConsole();
let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
let scriptError = Cc["@mozilla.org/scripterror;1"].
createInstance(Ci.nsIScriptError);
scriptError.initWithWindowID(ex.message + "\n" + ex.stack, ex.fileName,
"", ex.lineNumber, 0, scriptError.errorFlag,
"content javascript",
this.getInnerWindowId(contentWindow));
Services.console.logMessage(scriptError);
error = true;
error = ex;
}
return [error, result];
@ -368,11 +354,7 @@ var Scratchpad = {
"Scratchpad", 1);
}
catch (ex) {
Cu.reportError(ex);
Cu.reportError(ex.stack);
this.openErrorConsole();
error = true;
error = ex;
}
return [error, result];
@ -397,12 +379,30 @@ var Scratchpad = {
/**
* Execute the selected text (if any) or the entire editor content in the
* current context.
* @return mixed
* The script evaluation result.
*/
run: function SP_run()
execute: function SP_execute()
{
let selection = this.selectedText || this.getText();
let [error, result] = this.evalForContext(selection);
this.deselect();
return [selection, error, result];
},
/**
* Execute the selected text (if any) or the entire editor content in the
* current context.
*/
run: function SP_run()
{
let [selection, error, result] = this.execute();
if (!error) {
this.deselect();
} else {
this.writeAsErrorComment(error);
}
return [selection, error, result];
},
@ -413,10 +413,13 @@ var Scratchpad = {
*/
inspect: function SP_inspect()
{
let [selection, error, result] = this.run();
let [selection, error, result] = this.execute();
if (!error) {
this.deselect();
this.openPropertyPanel(selection, result);
} else {
this.writeAsErrorComment(error);
}
},
@ -427,25 +430,48 @@ var Scratchpad = {
* selected text.
*/
display: function SP_display()
{
let [selectedText, error, result] = this.execute();
if (!error) {
this.writeAsComment(result);
} else {
this.writeAsErrorComment(error);
}
},
/**
* Write out a value at the current insertion point as a block comment
* @param object aValue
* The Object to write out as a string
*/
writeAsComment: function SP_writeAsComment(aValue)
{
let selection = this.getSelectionRange();
let insertionPoint = selection.start != selection.end ?
selection.end : // after selected text
this.editor.getCharCount(); // after text end
let [selectedText, error, result] = this.run();
if (error) {
return;
}
let newComment = "/*\n" + result + "\n*/";
let newComment = "/*\n" + aValue + "\n*/";
this.setText(newComment, insertionPoint, insertionPoint);
// Select the new comment.
this.selectRange(insertionPoint, insertionPoint + newComment.length);
},
/**
* Write out an error at the current insertion point as a block comment
* @param object aValue
* The Error object to write out the message and stack trace
*/
writeAsErrorComment: function SP_writeAsErrorComment(aError)
{
let newComment = "Exception: " + aError.message + "\n" + aError.stack.substring(0, aError.stack.length - 1);
this.writeAsComment(newComment);
},
/**
* Open the Property Panel to inspect the given object.
*

View File

@ -61,6 +61,7 @@ _BROWSER_TEST_FILES = \
head.js \
browser_scratchpad_bug_653427_confirm_close.js \
browser_scratchpad_bug684546_reset_undo.js \
browser_scratchpad_bug690552_display_outputs_errors.js \
libs:: $(_BROWSER_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)

View File

@ -0,0 +1,53 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function browserLoad() {
gBrowser.selectedBrowser.removeEventListener("load", browserLoad, true);
openScratchpad(runTests, {"state":{"text":""}});
}, true);
content.location = "data:text/html,<p>test that exceptions our output as " +
"comments for 'display' and not sent to the console in Scratchpad";
}
function runTests()
{
scratchpad = gScratchpadWindow.Scratchpad;
var message = "\"Hello World!\""
var openComment = "/*\n";
var closeComment = "\n*/";
var error = "throw new Error(\"Ouch!\")";
let messageArray = {};
let count = {};
scratchpad.setText(message);
scratchpad.display();
is(scratchpad.getText(),
message + openComment + "Hello World!" + closeComment,
"message display output");
scratchpad.setText(error);
scratchpad.display();
is(scratchpad.getText(),
error + openComment + "Exception: Ouch!\n@Scratchpad:1" + closeComment,
"error display output");
scratchpad.setText(message);
scratchpad.run();
is(scratchpad.getText(), message, "message run output");
scratchpad.setText(error);
scratchpad.run();
is(scratchpad.getText(),
error + openComment + "Exception: Ouch!\n@Scratchpad:1" + closeComment,
"error display output");
finish();
}

View File

@ -1361,6 +1361,11 @@ function HUD_SERVICE()
HUD_SERVICE.prototype =
{
/**
* Last value entered
*/
lastInputValue: "",
/**
* L10N shortcut function
*

View File

@ -544,6 +544,13 @@ bin/libfreebl_32int64_3.so
@BINPATH@/updater@BIN_SUFFIX@
#endif
; [MaintenanceService]
;
#ifdef MOZ_MAINTENANCE_SERVICE
@BINPATH@/maintenanceservice.exe
@BINPATH@/maintenanceservice_installer.exe
#endif
; [Crash Reporter]
;
#ifdef MOZ_CRASHREPORTER

View File

@ -1452,3 +1452,7 @@ extensions/inspector@mozilla.org/chrome/icons/default/winInspectorMain.ico
components/nsPlacesTransactionsService.js
components/browserplaces.xpt
components/nsPlacesDBFlush.js
#ifndef MOZ_MAINTENANCE_SERVICE
maintenanceservice.exe
maintenanceservice_installer.exe
#endif

View File

@ -61,6 +61,13 @@ INSTALLER_FILES = \
nsis/shared.nsh \
$(NULL)
ifdef MOZ_MAINTENANCE_SERVICE
INSTALLER_FILES += \
nsis/maintenanceservice_installer.nsi \
$(NULL)
endif
BRANDING_FILES = \
branding.nsi \
wizHeader.bmp \
@ -104,6 +111,17 @@ uninstaller::
--preprocess-locale $(topsrcdir) \
$(PPL_LOCALE_ARGS) $(AB_CD) $(CONFIG_DIR)
# For building the maintenanceservice installer
ifdef MOZ_MAINTENANCE_SERVICE
maintenanceservice_installer::
$(INSTALL) $(addprefix $(srcdir)/,$(INSTALLER_FILES)) $(CONFIG_DIR)
$(PYTHON) $(topsrcdir)/config/Preprocessor.py -Fsubstitution $(DEFINES) $(ACDEFINES) \
$(srcdir)/nsis/defines.nsi.in > $(CONFIG_DIR)/defines.nsi
$(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \
--preprocess-locale $(topsrcdir) \
$(PPL_LOCALE_ARGS) $(AB_CD) $(CONFIG_DIR)
endif
$(CONFIG_DIR)/setup.exe::
$(RM) -r $(CONFIG_DIR)
$(MKDIR) $(CONFIG_DIR)

View File

@ -17,6 +17,9 @@
!define NO_UNINSTALL_SURVEY
!define CERTIFICATE_NAME "Mozilla Corporation"
!define CERTIFICATE_ISSUER "Thawte Code Signing CA - G2"
# LSP_CATEGORIES is the permitted LSP categories for the application. Each LSP
# category value is ANDed together to set multiple permitted categories.
# See http://msdn.microsoft.com/en-us/library/ms742253%28VS.85%29.aspx
@ -43,6 +46,10 @@
!define MinSupportedVer "Microsoft Windows 2000"
#endif
#ifdef MOZ_MAINTENANCE_SERVICE
!define MOZ_MAINTENANCE_SERVICE
#endif
# File details shared by both the installer and uninstaller
VIProductVersion "1.0.0.0"
VIAddVersionKey "ProductName" "${BrandShortName}"

View File

@ -19,6 +19,7 @@
#
# Contributor(s):
# Robert Strong <robert.bugzilla@gmail.com>
# Brian R. Bondy <netzen@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
@ -35,11 +36,12 @@
# ***** END LICENSE BLOCK *****
# Required Plugins:
# AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in
# ApplicationID http://nsis.sourceforge.net/ApplicationID_plug-in
# CityHash http://mxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash
# ShellLink http://nsis.sourceforge.net/ShellLink_plug-in
# UAC http://nsis.sourceforge.net/UAC_plug-in
# AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in
# ApplicationID http://nsis.sourceforge.net/ApplicationID_plug-in
# CityHash http://mxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash
# ShellLink http://nsis.sourceforge.net/ShellLink_plug-in
# UAC http://nsis.sourceforge.net/UAC_plug-in
# ServicesHelper Mozilla specific plugin that is located in /other-licenses/nsis
; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
!verbose 3
@ -59,6 +61,7 @@ Var InstallType
Var AddStartMenuSC
Var AddQuickLaunchSC
Var AddDesktopSC
Var InstallMaintenanceService
Var PageName
; By defining NO_STARTMENU_DIR an installer that doesn't provide an option for
@ -111,6 +114,7 @@ VIAddVersionKey "OriginalFilename" "setup.exe"
!insertmacro InitHashAppModelId
!insertmacro IsHandlerForInstallDir
!insertmacro IsPinnedToTaskBar
!insertmacro IsUserAdmin
!insertmacro LogDesktopShortcut
!insertmacro LogQuickLaunchShortcut
!insertmacro LogStartMenuShortcut
@ -183,6 +187,11 @@ Page custom preOptions leaveOptions
!define MUI_DIRECTORYPAGE_VERIFYONLEAVE
!insertmacro MUI_PAGE_DIRECTORY
; Custom Components Page
!ifdef MOZ_MAINTENANCE_SERVICE
Page custom preComponents leaveComponents
!endif
; Custom Shortcuts Page
Page custom preShortcuts leaveShortcuts
@ -373,6 +382,37 @@ Section "-Application" APP_IDX
${EndIf}
${EndIf}
!ifdef MOZ_MAINTENANCE_SERVICE
; If the maintenance service page was displayed then a value was already
; explicitly selected for installing the maintenance service and
; and so InstallMaintenanceService will already be 0 or 1.
; If the maintenance service page was not displayed then
; InstallMaintenanceService will be equal to "".
${If} $InstallMaintenanceService == ""
Call IsUserAdmin
Pop $R0
${If} $R0 == "true"
; Only proceed if we have HKLM write access
${AndIf} $TmpVal == "HKLM"
; On Windows 2000 we do not install the maintenance service.
${AndIf} ${AtLeastWinXP}
; The user is an admin so we should default to install service yes
StrCpy $InstallMaintenanceService "1"
${Else}
; The user is not admin so we should default to install service no
StrCpy $InstallMaintenanceService "0"
${EndIf}
${EndIf}
${If} $InstallMaintenanceService == "1"
; The user wants to install the maintenance service, so execute
; the pre-packaged maintenance service installer.
; This option can only be turned on if the user is an admin so there
; is no need to use ExecShell w/ verb runas to enforce elevated.
nsExec::Exec "$INSTDIR\maintenanceservice_installer.exe"
${EndIf}
!endif
; These need special handling on uninstall since they may be overwritten by
; an install into a different location.
StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\App Paths\${FileMainEXE}"
@ -426,7 +466,7 @@ Section "-Application" APP_IDX
${Unless} ${Errors}
GetFunctionAddress $0 FixShortcutAppModelIDs
UAC::ExecCodeSegment $0
${EndIf}
${EndUnless}
; UAC only allows elevating to an Admin account so there is no need to add
; the Start Menu or Desktop shortcuts from the original unelevated process
@ -482,6 +522,13 @@ Section "-Application" APP_IDX
${EndIf}
${EndUnless}
${EndIf}
!ifdef MOZ_MAINTENANCE_SERVICE
${If} $TmpVal == "HKLM"
; Add the registry keys for allowed certificates.
${AddMaintCertKeys}
${EndIf}
!endif
SectionEnd
; Cleanup operations to perform at the end of the installation.
@ -799,6 +846,58 @@ Function leaveShortcuts
${EndIf}
FunctionEnd
!ifdef MOZ_MAINTENANCE_SERVICE
Function preComponents
; If the service already exists, don't show this page
ServicesHelper::IsInstalled "MozillaMaintenance"
Pop $R9
${If} $R9 == 1
; The service already exists so don't show this page.
Abort
${EndIf}
; On Windows 2000 we do not install the maintenance service.
${Unless} ${AtLeastWinXP}
Abort
${EndUnless}
; Don't show the custom components page if the
; user is not an admin
Call IsUserAdmin
Pop $R9
${If} $R9 != "true"
Abort
${EndIf}
; Only show the maintenance service page if we have write access to HKLM
ClearErrors
WriteRegStr HKLM "Software\Mozilla" \
"${BrandShortName}InstallerTest" "Write Test"
${If} ${Errors}
ClearErrors
Abort
${Else}
DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
${EndIf}
StrCpy $PageName "Components"
${CheckCustomCommon}
!insertmacro MUI_HEADER_TEXT "$(COMPONENTS_PAGE_TITLE)" "$(COMPONENTS_PAGE_SUBTITLE)"
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "components.ini"
FunctionEnd
Function leaveComponents
${MUI_INSTALLOPTIONS_READ} $0 "components.ini" "Settings" "State"
${If} $0 != 0
Abort
${EndIf}
${MUI_INSTALLOPTIONS_READ} $InstallMaintenanceService "components.ini" "Field 2" "State"
${If} $InstallType == ${INSTALLTYPE_CUSTOM}
Call CheckExistingInstall
${EndIf}
FunctionEnd
!endif
Function preSummary
StrCpy $PageName "Summary"
; Setup the summary.ini file for the Custom Summary Page
@ -934,6 +1033,7 @@ Function .onInit
!insertmacro InitInstallOptionsFile "options.ini"
!insertmacro InitInstallOptionsFile "shortcuts.ini"
!insertmacro InitInstallOptionsFile "components.ini"
!insertmacro InitInstallOptionsFile "summary.ini"
WriteINIStr "$PLUGINSDIR\options.ini" "Settings" NumFields "5"
@ -947,7 +1047,7 @@ Function .onInit
WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Type "RadioButton"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Text "$(OPTION_STANDARD_RADIO)"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Left "15"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Left "0"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Right "-1"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Top "25"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Bottom "35"
@ -956,7 +1056,7 @@ Function .onInit
WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Type "RadioButton"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Text "$(OPTION_CUSTOM_RADIO)"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Left "15"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Left "0"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Right "-1"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Top "55"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Bottom "65"
@ -964,14 +1064,14 @@ Function .onInit
WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Type "label"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Text "$(OPTION_STANDARD_DESC)"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Left "30"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Left "15"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Right "-1"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Top "37"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Bottom "57"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Type "label"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Text "$(OPTION_CUSTOM_DESC)"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Left "30"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Left "15"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Right "-1"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Top "67"
WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Bottom "87"
@ -993,7 +1093,7 @@ Function .onInit
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Type "checkbox"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Text "$(ICONS_DESKTOP)"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Left "15"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Left "0"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Right "-1"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Top "20"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Bottom "30"
@ -1002,7 +1102,7 @@ Function .onInit
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Type "checkbox"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Text "$(ICONS_STARTMENU)"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Left "15"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Left "0"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Right "-1"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Top "40"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Bottom "50"
@ -1012,13 +1112,32 @@ Function .onInit
${Unless} ${AtLeastWin7}
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Type "checkbox"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Text "$(ICONS_QUICKLAUNCH)"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Left "15"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Left "0"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Right "-1"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Top "60"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Bottom "70"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" State "1"
${EndUnless}
; Setup the components.ini file for the Components Page
WriteINIStr "$PLUGINSDIR\components.ini" "Settings" NumFields "2"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Type "label"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Text "$(OPTIONAL_COMPONENTS_DESC)"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Left "0"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Right "-1"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Top "5"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Bottom "15"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Type "checkbox"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Text "$(MAINTENANCE_SERVICE_CHECKBOX_DESC)"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Left "0"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Right "-1"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Top "20"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Bottom "30"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" State "1"
WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Flags "GROUP"
; There must always be a core directory.
${GetSize} "$EXEDIR\core\" "/S=0K" $R5 $R7 $R8
SectionSetSize ${APP_IDX} $R5

View File

@ -0,0 +1,269 @@
# ***** 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 an NSIS installer for the maintenance service
#
# 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):
# Brian R. Bondy <netzen@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 *****
; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
!verbose 3
; 7-Zip provides better compression than the lzma from NSIS so we add the files
; uncompressed and use 7-Zip to create a SFX archive of it
SetDatablockOptimize on
SetCompress off
CRCCheck on
RequestExecutionLevel admin
!addplugindir ./
; Variables
Var TempMaintServiceName
Var BrandFullNameDA
Var BrandFullName
; Other included files may depend upon these includes!
; The following includes are provided by NSIS.
!include FileFunc.nsh
!include LogicLib.nsh
!include MUI.nsh
!include WinMessages.nsh
!include WinVer.nsh
!include WordFunc.nsh
!insertmacro GetOptions
!insertmacro GetParameters
!insertmacro GetSize
; The test slaves use this fallback key to run tests.
; And anyone that wants to run tests themselves should already have
; this installed.
!define FallbackKey \
"SOFTWARE\Mozilla\MaintenanceService\3932ecacee736d366d6436db0f55bce4"
!define CompanyName "Mozilla Corporation"
!define BrandFullNameInternal ""
; The following includes are custom.
!include defines.nsi
; We keep defines.nsi defined so that we get other things like
; the version number, but we redefine BrandFullName
!define MaintFullName "Mozilla Maintenance Service"
!undef BrandFullName
!define BrandFullName "${MaintFullName}"
!include common.nsh
!include locales.nsi
VIAddVersionKey "FileDescription" "${MaintFullName} Installer"
VIAddVersionKey "OriginalFilename" "maintenanceservice_installer.exe"
Name "${MaintFullName}"
OutFile "maintenanceservice_installer.exe"
; Get installation folder from registry if available
InstallDirRegKey HKLM "Software\Mozilla\MaintenanceService" ""
SetOverwrite on
!define MaintUninstallKey \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\MozillaMaintenanceService"
; The HAVE_64BIT_OS define also means that we have an x64 build,
; not just an x64 OS.
!ifdef HAVE_64BIT_OS
; See below, we actually abort the install for x64 builds currently.
InstallDir "$PROGRAMFILES64\${MaintFullName}\"
!else
InstallDir "$PROGRAMFILES32\${MaintFullName}\"
!endif
ShowUnInstDetails nevershow
################################################################################
# Modern User Interface - MUI
!define MUI_ICON setup.ico
!define MUI_UNICON setup.ico
!define MUI_WELCOMEPAGE_TITLE_3LINES
!define MUI_UNWELCOMEFINISHPAGE_BITMAP wizWatermark.bmp
;Interface Settings
!define MUI_ABORTWARNING
; Uninstaller Pages
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
################################################################################
# Language
!insertmacro MOZ_MUI_LANGUAGE 'baseLocale'
!verbose push
!verbose 3
!include "overrideLocale.nsh"
!include "customLocale.nsh"
!verbose pop
; Set this after the locale files to override it if it is in the locale
; using " " for BrandingText will hide the "Nullsoft Install System..." branding
BrandingText " "
Function .onInit
SetSilent silent
!ifdef HAVE_64BIT_OS
; We plan to eventually enable 64bit native builds to use the maintenance
; service, but for the initial release, to reduce testing and development,
; 64-bit builds will not install the maintenanceservice.
Abort
!endif
; On Windows 2000 we do not install the maintenance service.
; We won't run this installer from the parent installer, but just in case
; someone tries to execute it on Windows 2000...
${Unless} ${AtLeastWinXP}
Abort
${EndUnless}
FunctionEnd
Function un.onInit
StrCpy $BrandFullNameDA "${MaintFullName}"
StrCpy $BrandFullName "${MaintFullName}"
FunctionEnd
Section "MaintenanceService"
AllowSkipFiles off
CreateDirectory $INSTDIR
SetOutPath $INSTDIR
; If the service already exists, then it will be stopped when upgrading it
; via the maintenanceservice_tmp.exe command executed below.
; The maintenanceservice_tmp.exe command will rename the file to
; maintenanceservice.exe if maintenanceservice_tmp.exe is newer.
; If the service does not exist yet, we install it and drop the file on
; disk as maintenanceservice.exe directly.
StrCpy $TempMaintServiceName "maintenanceservice.exe"
IfFileExists "$INSTDIR\maintenanceservice.exe" 0 skipAlreadyExists
StrCpy $TempMaintServiceName "maintenanceservice_tmp.exe"
skipAlreadyExists:
; We always write out a copy and then decide whether to install it or
; not via calling its 'install' cmdline which works by version comparison.
CopyFiles "$EXEDIR\maintenanceservice.exe" "$INSTDIR\$TempMaintServiceName"
; Install the application maintenance service.
; If a service already exists, the command line parameter will stop the
; service and only install itself if it is newer than the already installed
; service. If successful it will remove the old maintenanceservice.exe
; and replace it with maintenanceservice_tmp.exe.
ClearErrors
${GetParameters} $0
${GetOptions} "$0" "/Upgrade" $0
${If} ${Errors}
nsExec::Exec '"$INSTDIR\$TempMaintServiceName" install'
${Else}
; The upgrade cmdline is the same as install except
; It will fail if the service isn't already installed.
nsExec::Exec '"$INSTDIR\$TempMaintServiceName" upgrade'
${EndIf}
WriteUninstaller "$INSTDIR\Uninstall.exe"
WriteRegStr HKLM "${MaintUninstallKey}" "DisplayName" "${MaintFullName}"
WriteRegStr HKLM "${MaintUninstallKey}" "UninstallString" \
'"$INSTDIR\uninstall.exe"'
WriteRegStr HKLM "${MaintUninstallKey}" "DisplayIcon" \
"$INSTDIR\Uninstall.exe,0"
WriteRegStr HKLM "${MaintUninstallKey}" "DisplayVersion" "${AppVersion}"
WriteRegStr HKLM "${MaintUninstallKey}" "Publisher" "Mozilla"
WriteRegStr HKLM "${MaintUninstallKey}" "Comments" \
"${BrandFullName} ${AppVersion} (${ARCH} ${AB_CD})"
${GetSize} "$INSTDIR" "/S=0K" $R2 $R3 $R4
WriteRegDWORD HKLM "${MaintUninstallKey}" "EstimatedSize" $R2
; Write out that a maintenance service was attempted.
; We do this because on upgrades we will check this value and we only
; want to install once on the first upgrade to maintenance service.
; Also write out that we are currently installed, preferences will check
; this value to determine if we should show the service update pref.
; Since the Maintenance service can be installed either x86 or x64,
; always use the 64-bit registry for checking if an attempt was made.
SetRegView 64
WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Attempted" 1
WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Installed" 1
; Included here for debug purposes only.
; These keys are used to bypass the installation dir is a valid installation
; check from the service so that tests can be run.
; WriteRegStr HKLM "${FallbackKey}\0" "name" "Mozilla Corporation"
; WriteRegStr HKLM "${FallbackKey}\0" "issuer" "Thawte Code Signing CA - G2"
SetRegView lastused
SectionEnd
; By renaming before deleting we improve things slightly in case
; there is a file in use error. In this case a new install can happen.
Function un.RenameDelete
Pop $9
; If the .moz-delete file already exists previously, delete it
; If it doesn't exist, the call is ignored.
; We don't need to pass /REBOOTOK here since it was already marked that way
; if it exists.
Delete "$9.moz-delete"
Rename "$9" "$9.moz-delete"
${If} ${Errors}
Delete /REBOOTOK "$9"
${Else}
Delete /REBOOTOK "$9.moz-delete"
${EndIf}
ClearErrors
FunctionEnd
Section "Uninstall"
; Delete the service so that no updates will be attempted
nsExec::Exec '"$INSTDIR\maintenanceservice.exe" uninstall'
Push "$INSTDIR\maintenanceservice.exe"
Call un.RenameDelete
Push "$INSTDIR\maintenanceservice_tmp.exe"
Call un.RenameDelete
Push "$INSTDIR\Uninstall.exe"
Call un.RenameDelete
RMDir /REBOOTOK "$INSTDIR"
DeleteRegKey HKLM "${MaintUninstallKey}"
SetRegView 64
DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "Installed"
DeleteRegKey HKLM "${FallbackKey}\"
SetRegView lastused
SectionEnd

View File

@ -19,6 +19,7 @@
#
# Contributor(s):
# Robert Strong <robert.bugzilla@gmail.com>
# Brian R. Bondy <netzen@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
@ -105,6 +106,46 @@
${CleanVirtualStore}
${RemoveDeprecatedFiles}
!ifdef MOZ_MAINTENANCE_SERVICE
Call IsUserAdmin
Pop $R0
${If} $R0 == "true"
; Only proceed if we have HKLM write access
${AndIf} $TmpVal == "HKLM"
; On Windows 2000 we do not install the maintenance service.
${AndIf} ${AtLeastWinXP}
; Add the registry keys for allowed certificates.
${AddMaintCertKeys}
; We check to see if the maintenance service install was already attempted.
; Since the Maintenance service can be installed either x86 or x64,
; always use the 64-bit registry for checking if an attempt was made.
SetRegView 64
ReadRegDWORD $5 HKLM "Software\Mozilla\MaintenanceService" "Attempted"
ClearErrors
SetRegView lastused
; If the maintenance service is already installed, do nothing.
; The maintenance service will launch:
; maintenanceservice_installer.exe /Upgrade to upgrade the maintenance
; service if necessary. If the update was done from updater.exe without
; the service (i.e. service is failing), updater.exe will do the update of
; the service. The reasons we do not do it here is because we don't want
; to have to prompt for limited user accounts when the service isn't used
; and we currently call the PostUpdate twice, once for the user and once
; for the SYSTEM account. Also, this would stop the maintenance service
; and we need a return result back to the service when run that way.
${If} $5 == ""
; An install of maintenance service was never attempted.
; We call ExecShell (which is ShellExecute) with the verb "runas"
; to ask for elevation if the user isn't already elevated. If the user
; is already elevated it will just launch the program.
ExecShell "runas" "$INSTDIR\maintenanceservice_installer.exe"
${EndIf}
${EndIf}
!endif
!macroend
!define PostUpdate "!insertmacro PostUpdate"
@ -437,38 +478,51 @@
!macro SetUninstallKeys
StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})"
StrCpy $2 ""
ClearErrors
WriteRegStr HKLM "$0" "${BrandShortName}InstallerTest" "Write Test"
${If} ${Errors}
StrCpy $1 "HKCU"
SetShellVarContext current ; Set SHCTX to the current user (e.g. HKCU)
; If the uninstall keys already exist in HKLM don't create them in HKCU
ClearErrors
ReadRegStr $2 "HKLM" $0 "DisplayName"
${If} $2 == ""
; Otherwise we don't have any keys for this product in HKLM so proceeed
; to create them in HKCU. Better handling for this will be done in:
; Bug 711044 - Better handling for 2 uninstall icons
StrCpy $1 "HKCU"
SetShellVarContext current ; Set SHCTX to the current user (e.g. HKCU)
${EndIf}
ClearErrors
${Else}
StrCpy $1 "HKLM"
SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM)
DeleteRegValue HKLM "$0" "${BrandShortName}InstallerTest"
${EndIf}
${GetLongPath} "$INSTDIR" $8
${If} $2 == ""
${GetLongPath} "$INSTDIR" $8
; Write the uninstall registry keys
${WriteRegStr2} $1 "$0" "Comments" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0
${WriteRegStr2} $1 "$0" "DisplayIcon" "$8\${FileMainEXE},0" 0
${WriteRegStr2} $1 "$0" "DisplayName" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0
${WriteRegStr2} $1 "$0" "DisplayVersion" "${AppVersion}" 0
${WriteRegStr2} $1 "$0" "InstallLocation" "$8" 0
${WriteRegStr2} $1 "$0" "Publisher" "Mozilla" 0
${WriteRegStr2} $1 "$0" "UninstallString" "$8\uninstall\helper.exe" 0
${WriteRegStr2} $1 "$0" "URLInfoAbout" "${URLInfoAbout}" 0
${WriteRegStr2} $1 "$0" "URLUpdateInfo" "${URLUpdateInfo}" 0
${WriteRegDWORD2} $1 "$0" "NoModify" 1 0
${WriteRegDWORD2} $1 "$0" "NoRepair" 1 0
; Write the uninstall registry keys
${WriteRegStr2} $1 "$0" "Comments" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0
${WriteRegStr2} $1 "$0" "DisplayIcon" "$8\${FileMainEXE},0" 0
${WriteRegStr2} $1 "$0" "DisplayName" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0
${WriteRegStr2} $1 "$0" "DisplayVersion" "${AppVersion}" 0
${WriteRegStr2} $1 "$0" "InstallLocation" "$8" 0
${WriteRegStr2} $1 "$0" "Publisher" "Mozilla" 0
${WriteRegStr2} $1 "$0" "UninstallString" "$8\uninstall\helper.exe" 0
${WriteRegStr2} $1 "$0" "URLInfoAbout" "${URLInfoAbout}" 0
${WriteRegStr2} $1 "$0" "URLUpdateInfo" "${URLUpdateInfo}" 0
${WriteRegDWORD2} $1 "$0" "NoModify" 1 0
${WriteRegDWORD2} $1 "$0" "NoRepair" 1 0
${GetSize} "$8" "/S=0K" $R2 $R3 $R4
${WriteRegDWORD2} $1 "$0" "EstimatedSize" $R2 0
${GetSize} "$8" "/S=0K" $R2 $R3 $R4
${WriteRegDWORD2} $1 "$0" "EstimatedSize" $R2 0
${If} "$TmpVal" == "HKLM"
SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM)
${Else}
SetShellVarContext current ; Set SHCTX to the current user (e.g. HKCU)
${If} "$TmpVal" == "HKLM"
SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM)
${Else}
SetShellVarContext current ; Set SHCTX to the current user (e.g. HKCU)
${EndIf}
${EndIf}
!macroend
!define SetUninstallKeys "!insertmacro SetUninstallKeys"
@ -547,6 +601,35 @@
!macroend
!define UpdateProtocolHandlers "!insertmacro UpdateProtocolHandlers"
!ifdef MOZ_MAINTENANCE_SERVICE
; Adds maintenance service certificate keys for the install dir.
; For the cert to work, it must also be signed by a trusted cert for the user.
!macro AddMaintCertKeys
Push $R0
; Allow main Mozilla cert information for updates
; This call will push the needed key on the stack
ServicesHelper::PathToUniqueRegistryPath "$INSTDIR"
Pop $R0
${If} $R0 != ""
; More than one certificate can be specified in a different subfolder
; for example: $R0\1, but each individual binary can be signed
; with at most one certificate. A fallback certificate can only be used
; if the binary is replaced with a different certificate.
; We always use the 64bit registry for certs.
; This call is ignored on 32-bit systems.
SetRegView 64
DeleteRegKey HKLM "$R0"
WriteRegStr HKLM "$R0\0" "name" "${CERTIFICATE_NAME}"
WriteRegStr HKLM "$R0\0" "issuer" "${CERTIFICATE_ISSUER}"
SetRegView lastused
ClearErrors
${EndIf}
; Restore the previously used value back
Pop $R0
!macroend
!define AddMaintCertKeys "!insertmacro AddMaintCertKeys"
!endif
; Removes various registry entries for reasons noted below (does not use SHCTX).
!macro RemoveDeprecatedKeys
StrCpy $0 "SOFTWARE\Classes"
@ -1020,7 +1103,6 @@ Function SetAsDefaultAppUserHKCU
${EndUnless}
${EndIf}
${RemoveDeprecatedKeys}
${PinToTaskBar}
FunctionEnd

View File

@ -61,6 +61,7 @@ RequestExecutionLevel user
!define NO_LOG
Var TmpVal
Var MaintCertKey
; Other included files may depend upon these includes!
; The following includes are provided by NSIS.
@ -96,6 +97,7 @@ VIAddVersionKey "OriginalFilename" "helper.exe"
!insertmacro InitHashAppModelId
!insertmacro IsHandlerForInstallDir
!insertmacro IsPinnedToTaskBar
!insertmacro IsUserAdmin
!insertmacro LogDesktopShortcut
!insertmacro LogQuickLaunchShortcut
!insertmacro LogStartMenuShortcut
@ -380,6 +382,21 @@ Section "Uninstall"
; removed and other ugly things will happen like recreation of the app's
; clients registry key by the OS under some conditions.
System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
!ifdef MOZ_MAINTENANCE_SERVICE
; Get the path the allowed cert is at and remove it
; Keep this block of code last since it modfies the reg view
ServicesHelper::PathToUniqueRegistryPath "$INSTDIR"
Pop $MaintCertKey
${If} $MaintCertKey != ""
; We always use the 64bit registry for certs
; This call is ignored on 32-bit systems.
SetRegView 64
DeleteRegKey HKLM "$MaintCertKey\"
SetRegView lastused
${EndIf}
!endif
SectionEnd
################################################################################

View File

@ -83,9 +83,9 @@
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
background-color: transparent;
border: 1px solid hsla(210,8%,5%,.6);
border-radius: 20px;
border-radius: 2px;
background-color: transparent;
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-repeat: no-repeat;
background-position: 4px 3px, top left, top left;

View File

@ -500,7 +500,10 @@ class NetworkTools:
return None
def getLanIp(self):
ip = socket.gethostbyname(socket.gethostname())
try:
ip = socket.gethostbyname(socket.gethostname())
except socket.gaierror:
ip = socket.gethostbyname(socket.gethostname() + ".local") # for Mac OS X
if ip.startswith("127.") and os.name != "nt":
interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
for ifname in interfaces:

View File

@ -192,3 +192,4 @@ https://redirproxy.example.com:443 privileged,redir=test1.example.com
http://bug704464-1.example.com:80 privileged
http://bug704464-2.example.com:80 privileged
http://bug704464-3.example.com:80 privileged
http://bug702292.example.com:80 privileged

View File

@ -193,9 +193,8 @@ class SortFunction(Function):
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
d = list(self._arguments[0].resolvesplit(makefile, variables, setting))
d.sort()
util.joiniter(fd, d)
d = set(self._arguments[0].resolvesplit(makefile, variables, setting))
util.joiniter(fd, sorted(d))
class WordFunction(Function):
name = 'word'

View File

@ -0,0 +1,4 @@
# sort should remove duplicates
all:
@test "$(sort x a y b z c a z b x c y)" = "a b c x y z"
@echo "TEST-PASS"

View File

@ -294,7 +294,6 @@ $(CONFIGURES): %: %.in $(EXTRA_CONFIG_DEPS)
CONFIG_STATUS_DEPS := \
$(wildcard $(CONFIGURES)) \
$(TOPSRCDIR)/allmakefiles.sh \
$(TOPSRCDIR)/.mozconfig.mk \
$(wildcard $(TOPSRCDIR)/nsprpub/configure) \
$(wildcard $(TOPSRCDIR)/config/milestone.txt) \
$(wildcard $(TOPSRCDIR)/js/src/config/milestone.txt) \

View File

@ -94,7 +94,6 @@ OMNIJAR_NAME = @OMNIJAR_NAME@
MOZ_WIDGET_TOOLKIT = @MOZ_WIDGET_TOOLKIT@
MOZ_GFX_OPTIMIZE_MOBILE = @MOZ_GFX_OPTIMIZE_MOBILE@
MOZ_DFB = @MOZ_DFB@
MOZ_X11 = @MOZ_X11@
MOZ_PANGO = @MOZ_PANGO@
@ -137,6 +136,7 @@ ACCESSIBILITY = @ACCESSIBILITY@
MOZ_BRANDING_DIRECTORY = @MOZ_BRANDING_DIRECTORY@
XPCOM_USE_LEA = @XPCOM_USE_LEA@
MOZ_INSTALLER = @MOZ_INSTALLER@
MOZ_MAINTENANCE_SERVICE = @MOZ_MAINTENANCE_SERVICE@
MOZ_UPDATER = @MOZ_UPDATER@
MOZ_UPDATE_CHANNEL = @MOZ_UPDATE_CHANNEL@
MOZ_UPDATE_PACKAGING = @MOZ_UPDATE_PACKAGING@
@ -371,6 +371,7 @@ HAVE_64BIT_OS = @HAVE_64BIT_OS@
CC = @CC@
CXX = @CXX@
CPP = @CPP@
CC_VERSION = @CC_VERSION@
CXX_VERSION = @CXX_VERSION@

View File

@ -113,11 +113,6 @@ fusion/protocol.h
fusion/fusion.h
fusion/arena.h
fusion/object.h
directfbgl.h
directfb_version.h
directfb.h
directfb_util.h
directfb_keynames.h
dgiff.h
direct/util.h
direct/memcpy.h

View File

@ -4799,7 +4799,6 @@ MOZ_ARG_HEADER(Toolkit Options)
Mac OS X - cairo-cocoa
OS/2 - cairo-os2
Win32 - cairo-windows
Gtk2 with DirectFB - cairo-gtk2-dfb
* - cairo-gtk2
* - cairo-qt],
[ _DEFAULT_TOOLKIT=$enableval ],
@ -4807,7 +4806,6 @@ MOZ_ARG_HEADER(Toolkit Options)
if test "$_DEFAULT_TOOLKIT" = "cairo-windows" \
-o "$_DEFAULT_TOOLKIT" = "cairo-gtk2" \
-o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-dfb" \
-o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-x11" \
-o "$_DEFAULT_TOOLKIT" = "cairo-qt" \
-o "$_DEFAULT_TOOLKIT" = "cairo-os2" \
@ -4854,24 +4852,6 @@ cairo-gtk2|cairo-gtk2-x11)
MOZ_INSTRUMENT_EVENT_LOOP=1
;;
cairo-gtk2-dfb)
MOZ_WIDGET_TOOLKIT=gtk2
MOZ_ENABLE_GTK2=1
MOZ_WEBGL=
AC_DEFINE(MOZ_DFB)
MOZ_DFB=1
TK_CFLAGS='$(MOZ_GTK2_CFLAGS)'
TK_LIBS='$(MOZ_GTK2_LIBS)'
AC_DEFINE(MOZ_WIDGET_GTK2)
if test "$no_x" != "yes"; then
AC_MSG_WARN([Disabling X when DirectFB is specified.])
no_x=yes
fi
MOZ_PDF_PRINTING=1
;;
cairo-qt)
MOZ_WIDGET_TOOLKIT=qt
MOZ_ENABLE_QT=1
@ -4967,9 +4947,6 @@ if test "$COMPILE_ENVIRONMENT"; then
if test "$MOZ_ENABLE_GTK2"; then
if test "$MOZ_X11"; then
GDK_PACKAGES=gdk-x11-2.0
elif test "$MOZ_DFB"; then
PKG_CHECK_MODULES(MOZ_DFB, directfb >= 1.1.0)
GDK_PACKAGES=directfb
fi
PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 glib-2.0 gobject-2.0 $GDK_PACKAGES)
@ -5127,7 +5104,6 @@ AC_SUBST(MOZ_QT_LIBS)
AC_SUBST(MOC)
AC_SUBST(RCC)
AC_SUBST(MOZ_DFB)
AC_SUBST(MOZ_X11)
dnl ========================================================
@ -5337,7 +5313,7 @@ then
if test "$MOZ_ENABLE_GCONF"
then
PKG_CHECK_MODULES(MOZ_GCONF, gconf-2.0 >= $GCONF_VERSION gobject-2.0 ,[
MOZ_GCONF_LIBS=`echo $MOZ_GCONF_LIBS | sed 's/-llinc\>//'`
MOZ_GCONF_LIBS=`$PKG_CONFIG --libs gobject-2.0`
MOZ_ENABLE_GCONF=1
],[
if test "$MOZ_ENABLE_GCONF" = "force"
@ -6357,6 +6333,23 @@ AC_CHECK_PROGS(WGET, wget, "")
AC_MSG_RESULT([$WGET])
AC_SUBST(WGET)
dnl ========================================================
dnl Maintenance Service
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(maintenance-service,
[ --enable-maintenance-service Enable building of maintenanceservice],
MOZ_MAINTENANCE_SERVICE=1,
MOZ_MAINTENANCE_SERVICE= )
if test -n "$MOZ_MAINTENANCE_SERVICE"; then
if test "$OS_ARCH" = "WINNT"; then
AC_DEFINE(MOZ_MAINTENANCE_SERVICE)
else
AC_MSG_ERROR([Can only build with --enable-maintenance-service with a Windows target])
fi
fi
dnl ========================================================
dnl Updater
dnl ========================================================
@ -8448,6 +8441,7 @@ AC_SUBST(MOZ_SPELLCHECK)
AC_SUBST(MOZ_JAVA_COMPOSITOR)
AC_SUBST(MOZ_USER_DIR)
AC_SUBST(MOZ_CRASHREPORTER)
AC_SUBST(MOZ_MAINTENANCE_SERVICE)
AC_SUBST(MOZ_UPDATER)
AC_SUBST(MOZ_ANGLE)
AC_SUBST(MOZ_DIRECTX_SDK_PATH)

View File

@ -82,6 +82,7 @@ static fp_except_t oldmask = fpsetmask(~allmask);
#include "nsHtml5Parser.h"
#include "nsIFragmentContentSink.h"
#include "nsMathUtils.h"
#include "nsCharSeparatedTokenizer.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/GuardObjects.h"
@ -1942,6 +1943,9 @@ private:
static nsString* sModifierSeparator;
};
typedef nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
HTMLSplitOnSpacesTokenizer;
#define NS_HOLD_JS_OBJECTS(obj, clazz) \
nsContentUtils::HoldJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz), \
&NS_CYCLE_COLLECTION_NAME(clazz))

View File

@ -70,13 +70,13 @@ class nsIBlobBuilder;
nsresult NS_NewBlobBuilder(nsISupports* *aSupports);
using namespace mozilla::dom;
class nsDOMFileBase : public nsIDOMFile,
public nsIXHRSendable,
public nsIMutable
{
public:
typedef mozilla::dom::indexedDB::FileInfo FileInfo;
nsDOMFileBase(const nsAString& aName, const nsAString& aContentType,
PRUint64 aLength)
: mIsFile(true), mImmutable(false), mContentType(aContentType),
@ -143,7 +143,7 @@ protected:
PRUint64 mLength;
// Protected by IndexedDatabaseManager::FileMutex()
nsTArray<nsRefPtr<indexedDB::FileInfo> > mFileInfos;
nsTArray<nsRefPtr<FileInfo> > mFileInfos;
};
class nsDOMFileFile : public nsDOMFileBase,
@ -174,7 +174,7 @@ public:
// Create as a stored file
nsDOMFileFile(const nsAString& aName, const nsAString& aContentType,
PRUint64 aLength, nsIFile* aFile,
indexedDB::FileInfo* aFileInfo)
FileInfo* aFileInfo)
: nsDOMFileBase(aName, aContentType, aLength),
mFile(aFile), mWholeFile(true), mStoredFile(true)
{
@ -184,7 +184,7 @@ public:
// Create as a stored blob
nsDOMFileFile(const nsAString& aContentType, PRUint64 aLength,
nsIFile* aFile, indexedDB::FileInfo* aFileInfo)
nsIFile* aFile, FileInfo* aFileInfo)
: nsDOMFileBase(aContentType, aLength),
mFile(aFile), mWholeFile(true), mStoredFile(true)
{
@ -233,10 +233,10 @@ protected:
mImmutable = aOther->mImmutable;
if (mStoredFile) {
indexedDB::FileInfo* fileInfo;
FileInfo* fileInfo;
if (!indexedDB::IndexedDatabaseManager::IsClosed()) {
indexedDB::IndexedDatabaseManager::FileMutex().Lock();
if (!mozilla::dom::indexedDB::IndexedDatabaseManager::IsClosed()) {
mozilla::dom::indexedDB::IndexedDatabaseManager::FileMutex().Lock();
}
NS_ASSERTION(!aOther->mFileInfos.IsEmpty(),
@ -244,8 +244,8 @@ protected:
fileInfo = aOther->mFileInfos.ElementAt(0);
if (!indexedDB::IndexedDatabaseManager::IsClosed()) {
indexedDB::IndexedDatabaseManager::FileMutex().Unlock();
if (!mozilla::dom::indexedDB::IndexedDatabaseManager::IsClosed()) {
mozilla::dom::indexedDB::IndexedDatabaseManager::FileMutex().Unlock();
}
mFileInfos.AppendElement(fileInfo);

View File

@ -70,6 +70,7 @@
#include "prmem.h"
using namespace mozilla;
using namespace mozilla::dom;
// XXXkhuey the input stream that we pass out of a DOMFile
// can outlive the actual DOMFile object. Thus, we must

View File

@ -292,11 +292,13 @@ WebGLContext::WebGLContext()
WebGLMemoryReporter::AddWebGLContext(this);
mContextLost = false;
mAllowRestore = false;
mAllowRestore = true;
mRobustnessTimerRunning = false;
mDrawSinceRobustnessTimerSet = false;
mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
mContextStatus = ContextStable;
mContextLostErrorSet = false;
mContextLostDueToTest = false;
}
WebGLContext::~WebGLContext()
@ -801,7 +803,7 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
LayerManager *aManager)
{
if (mContextLost)
if (!IsContextStable())
return nsnull;
if (!mResetLayer && aOldLayer &&
@ -865,7 +867,7 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
NS_IMETHODIMP
WebGLContext::GetContextAttributes(jsval *aResult)
{
if (mContextLost)
if (!IsContextStable())
{
*aResult = OBJECT_TO_JSVAL(NULL);
return NS_OK;
@ -909,7 +911,7 @@ WebGLContext::GetContextAttributes(jsval *aResult)
NS_IMETHODIMP
WebGLContext::MozGetUnderlyingParamString(PRUint32 pname, nsAString& retval)
{
if (mContextLost)
if (!IsContextStable())
return NS_OK;
retval.SetIsVoid(true);
@ -948,7 +950,7 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
// We always support this extension.
isSupported = true;
break;
case WebGL_WEBGL_EXT_lose_context:
case WebGL_MOZ_WEBGL_lose_context:
// We always support this extension.
isSupported = true;
break;
@ -963,7 +965,7 @@ NS_IMETHODIMP
WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
{
*retval = nsnull;
if (mContextLost)
if (!IsContextStable())
return NS_OK;
if (mDisableExtensions) {
@ -980,9 +982,9 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
if (IsExtensionSupported(WebGL_OES_standard_derivatives))
ei = WebGL_OES_standard_derivatives;
}
else if (aName.EqualsLiteral("WEBGL_EXT_lose_context")) {
if (IsExtensionSupported(WebGL_WEBGL_EXT_lose_context))
ei = WebGL_WEBGL_EXT_lose_context;
else if (aName.EqualsLiteral("MOZ_WEBGL_lose_context")) {
if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
ei = WebGL_MOZ_WEBGL_lose_context;
}
if (ei != WebGLExtensionID_Max) {
@ -991,7 +993,7 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
case WebGL_OES_standard_derivatives:
mEnabledExtensions[ei] = new WebGLExtensionStandardDerivatives(this);
break;
case WebGL_WEBGL_EXT_lose_context:
case WebGL_MOZ_WEBGL_lose_context:
mEnabledExtensions[ei] = new WebGLExtensionLoseContext(this);
break;
// create an extension for any types that don't
@ -1097,10 +1099,69 @@ WebGLContext::EnsureBackbufferClearedAsNeeded()
Invalidate();
}
// We use this timer for many things. Here are the things that it is activated for:
// 1) If a script is using the MOZ_WEBGL_lose_context extension.
// 2) If we are using EGL and _NOT ANGLE_, we query periodically to see if the
// CONTEXT_LOST_WEBGL error has been triggered.
// 3) If we are using ANGLE, or anything that supports ARB_robustness, query the
// GPU periodically to see if the reset status bit has been set.
// In all of these situations, we use this timer to send the script context lost
// and restored events asynchronously. For example, if it triggers a context loss,
// the webglcontextlost event will be sent to it the next time the robustness timer
// fires.
// Note that this timer mechanism is not used unless one of these 3 criteria
// are met.
// At a bare minimum, from context lost to context restores, it would take 3
// full timer iterations: detection, webglcontextlost, webglcontextrestored.
NS_IMETHODIMP
WebGLContext::Notify(nsITimer* timer)
{
TerminateRobustnessTimer();
// If the context has been lost and we're waiting for it to be restored, do
// that now.
if (mContextStatus == ContextLostAwaitingEvent) {
bool defaultAction;
nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
(nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
NS_LITERAL_STRING("webglcontextlost"),
PR_TRUE,
PR_TRUE,
&defaultAction);
// If the script didn't handle the event, we don't allow restores.
if (defaultAction)
mAllowRestore = false;
// If the script handled the event and we are allowing restores, then
// mark it to be restored. Otherwise, leave it as context lost
// (unusable).
if (!defaultAction && mAllowRestore) {
ForceRestoreContext();
// Restart the timer so that it will be restored on the next
// callback.
SetupRobustnessTimer();
} else {
mContextStatus = ContextLost;
}
} else if (mContextStatus == ContextLostAwaitingRestore) {
// Try to restore the context. If it fails, try again later.
if (NS_FAILED(SetDimensions(mWidth, mHeight))) {
SetupRobustnessTimer();
return NS_OK;
}
mContextStatus = ContextStable;
nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
(nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
NS_LITERAL_STRING("webglcontextrestored"),
PR_TRUE,
PR_TRUE);
// Set all flags back to the state they were in before the context was
// lost.
mContextLostErrorSet = false;
mContextLostDueToTest = false;
mAllowRestore = true;
}
MaybeRestoreContext();
return NS_OK;
}
@ -1108,18 +1169,25 @@ WebGLContext::Notify(nsITimer* timer)
void
WebGLContext::MaybeRestoreContext()
{
if (mContextLost || mAllowRestore)
// Don't try to handle it if we already know it's busted.
if (mContextStatus != ContextStable || gl == nsnull)
return;
bool isEGL = gl->GetContextType() == GLContext::ContextTypeEGL,
isANGLE = gl->IsANGLE();
// If was lost due to a forced context loss, don't try to handle it.
// Also, we also don't try to handle if if we don't have robustness.
// Note that the code in this function is used only for situations where
// we have an actual context loss, and not a simulated one.
if (mContextLostDueToTest ||
(!mHasRobustness && !isEGL))
return;
GLContext::ContextResetARB resetStatus = GLContext::CONTEXT_NO_ERROR;
if (mHasRobustness) {
gl->MakeCurrent();
resetStatus = (GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
// This call is safe as it does not actually interact with GL, so the
// context does not have to be current.
} else if (isEGL) {
// Simulate a ARB_robustness guilty context loss for when we
// get an EGL_CONTEXT_LOST error. It may not actually be guilty,
@ -1143,10 +1211,11 @@ WebGLContext::MaybeRestoreContext()
// run it again some time later.
if (mDrawSinceRobustnessTimerSet)
SetupRobustnessTimer();
return;
break;
case GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB:
NS_WARNING("WebGL content on the page caused the graphics card to reset; not restoring the context");
return;
mAllowRestore = false;
break;
case GLContext::CONTEXT_INNOCENT_CONTEXT_RESET_ARB:
break;
case GLContext::CONTEXT_UNKNOWN_CONTEXT_RESET_ARB:
@ -1156,45 +1225,25 @@ WebGLContext::MaybeRestoreContext()
// This means that we can't restore it or risk restoring a guilty context. Should this ever change,
// we can get rid of the whole IsANGLE() junk from GLContext.h since, as of writing, this is the
// only use for it. See ANGLE issue 261.
return;
mAllowRestore = false;
}
break;
}
ForceRestoreContext();
}
void
WebGLContext::ForceLoseContext()
{
TerminateRobustnessTimer();
mWebGLError = LOCAL_GL_CONTEXT_LOST;
bool defaultAction;
mContextLost = true;
mContextStatus = ContextLostAwaitingEvent;
// Queue up a task to restore the event.
SetupRobustnessTimer();
DestroyResourcesAndContext();
nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
(nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
NS_LITERAL_STRING("webglcontextlost"),
PR_TRUE,
PR_TRUE,
&defaultAction);
if (defaultAction)
mAllowRestore = false;
}
void
WebGLContext::ForceRestoreContext()
{
mContextLost = false;
mAllowRestore = false;
SetDimensions(mHeight, mWidth);
nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
(nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
NS_LITERAL_STRING("webglcontextrestored"),
PR_TRUE,
PR_TRUE);
mContextStatus = ContextLostAwaitingRestore;
}
//
@ -1372,7 +1421,7 @@ NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
NS_IMETHODIMP
WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth)
{
if (mContextLost)
if (!IsContextStable())
return NS_OK;
*aWidth = mWidth;
@ -1383,7 +1432,7 @@ WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth)
NS_IMETHODIMP
WebGLContext::GetDrawingBufferHeight(WebGLsizei *aHeight)
{
if (mContextLost)
if (!IsContextStable())
return NS_OK;
*aHeight = mHeight;
@ -1455,7 +1504,7 @@ NS_IMETHODIMP
WebGLContext::GetSupportedExtensions(nsIVariant **retval)
{
*retval = nsnull;
if (mContextLost)
if (!IsContextStable())
return NS_OK;
if (mDisableExtensions) {
@ -1471,8 +1520,8 @@ WebGLContext::GetSupportedExtensions(nsIVariant **retval)
extList.InsertElementAt(extList.Length(), "OES_texture_float");
if (IsExtensionSupported(WebGL_OES_standard_derivatives))
extList.InsertElementAt(extList.Length(), "OES_standard_derivatives");
if (IsExtensionSupported(WebGL_WEBGL_EXT_lose_context))
extList.InsertElementAt(extList.Length(), "WEBGL_EXT_lose_context");
if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
extList.InsertElementAt(extList.Length(), "MOZ_WEBGL_lose_context");
nsresult rv;
if (extList.Length() > 0) {
@ -1491,7 +1540,13 @@ WebGLContext::GetSupportedExtensions(nsIVariant **retval)
NS_IMETHODIMP
WebGLContext::IsContextLost(WebGLboolean *retval)
{
*retval = mContextLost;
*retval = mContextStatus != ContextStable;
return NS_OK;
}
// Internalized version of IsContextLost.
bool
WebGLContext::IsContextStable()
{
return mContextStatus == ContextStable;
}

View File

@ -575,10 +575,17 @@ public:
return mMinCapability;
}
// See the comment over WebGLContext::Notify() for more information on this.
bool ShouldEnableRobustnessTimer() {
return mHasRobustness ||
IsExtensionEnabled(WebGL_MOZ_WEBGL_lose_context) ||
(gl != nsnull && gl->GetContextType() == gl::GLContext::ContextTypeEGL);
}
// Sets up the GL_ARB_robustness timer if it isn't already, so that if the
// driver gets restarted, the context may get reset with it.
void SetupRobustnessTimer() {
if (mContextLost || (!mHasRobustness && gl->GetContextType() != gl::GLContext::ContextTypeEGL))
if (!ShouldEnableRobustnessTimer())
return;
// If the timer was already running, don't restart it here. Instead,
@ -668,11 +675,30 @@ protected:
PRInt32 mGLMaxFragmentUniformVectors;
PRInt32 mGLMaxVertexUniformVectors;
// Represents current status, or state, of the context. That is, is it lost
// or stable and what part of the context lost process are we currently at.
// This is used to support the WebGL spec's asyncronous nature in handling
// context loss.
enum ContextStatus {
// The context is stable; there either are none or we don't know of any.
ContextStable,
// The context has been lost, but we have not yet sent an event to the
// script informing it of this.
ContextLostAwaitingEvent,
// The context has been lost, and we have sent the script an event
// informing it of this.
ContextLost,
// The context is lost, an event has been sent to the script, and the
// script correctly handled the event. We are waiting for the context to
// be restored.
ContextLostAwaitingRestore
};
// extensions
enum WebGLExtensionID {
WebGL_OES_texture_float,
WebGL_OES_standard_derivatives,
WebGL_WEBGL_EXT_lose_context,
WebGL_MOZ_WEBGL_lose_context,
WebGLExtensionID_Max
};
nsCOMPtr<WebGLExtension> mEnabledExtensions[WebGLExtensionID_Max];
@ -805,6 +831,7 @@ protected:
const GLvoid *data);
void MaybeRestoreContext();
bool IsContextStable();
void ForceLoseContext();
void ForceRestoreContext();
@ -861,10 +888,12 @@ protected:
int mBackbufferClearingStatus;
nsCOMPtr<nsITimer> mContextRestorer;
bool mContextLost;
bool mAllowRestore;
bool mRobustnessTimerRunning;
bool mDrawSinceRobustnessTimerSet;
ContextStatus mContextStatus;
bool mContextLostErrorSet;
bool mContextLostDueToTest;
public:
// console logging helpers

File diff suppressed because it is too large Load Diff

View File

@ -1195,7 +1195,7 @@ nsCanvasRenderingContext2DAzure::Redraw(const mgfx::Rect &r)
nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement());
gfxRect tmpR = GFXRect(r);
gfxRect tmpR = ThebesRect(r);
HTMLCanvasElement()->InvalidateCanvasContent(&tmpR);
return;

View File

@ -1,4 +1,4 @@
This is a local copy of the WebGL conformance suite, SVN revision 16237
This is a local copy of the WebGL conformance suite, SVN revision 16456
The canonical location for this testsuite is:

View File

@ -11,7 +11,10 @@ var wtu = WebGLTestUtils;
var canvas;
var gl;
var shouldGenerateGLError;
var extension_name = "WEBGL_EXT_lose_context";
var extensionNames = [
"WEBKIT_WEBGL_lose_context",
"MOZ_WEBGL_lose_context",
];
var extension;
var bufferObjects;
var program;
@ -33,22 +36,19 @@ function init()
testLosingContext();
}
function runTest1()
{
testLosingAndRestoringContext();
finishTest();
}
function setupTest()
{
canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = 1;
gl = wtu.create3DContext(canvas);
extension = gl.getExtension(extension_name);
for (var ii = 0; ii < extensionNames.length; ++ii) {
extension = gl.getExtension(extensionNames[ii]);
if (extension)
break;
}
if (!extension) {
debug(extension_name + " extension not found.");
debug("Could not find lose_context extension under the following names: " + extensionNames.join(" "));
return false;
}
return true;
@ -61,13 +61,13 @@ function testLosingContext()
debug("Test losing a context and inability to restore it.");
canvas.addEventListener("webglcontextlost", function() {
testLostContext();
canvas.addEventListener("webglcontextlost", function(e) {
testLostContext(e);
// restore the context after this event has exited.
setTimeout(function() {
// we didn't call prevent default so we should not be able to restore the context
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "extension.restoreContext()");
testLosingAndRetoreingContext();
testLosingAndRestoringContext();
}, 1);
});
canvas.addEventListener("webglcontextrestored", testShouldNotRestoreContext);
@ -82,7 +82,7 @@ function testLosingContext()
shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
shouldBe("gl.getError()", "gl.NO_ERROR");
// gl methods should be no-ops
shouldGenerateGLError(gl, gl.NO_ERROR, gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP));
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)");
// but the event should not have been fired.
shouldBeFalse("contextLostEventFired");
}
@ -95,8 +95,8 @@ function testLosingAndRestoringContext()
debug("");
debug("Test losing and restoring a context.");
canvas.addEventListener("webglcontextlost", function() {
testLostContext();
canvas.addEventListener("webglcontextlost", function(e) {
testLostContext(e);
// restore the context after this event has exited.
setTimeout(function() {
shouldGenerateGLError(gl, gl.NO_ERROR, "extension.restoreContext()");
@ -105,7 +105,7 @@ function testLosingAndRestoringContext()
shouldBeTrue("gl.isContextLost()");
shouldBe("gl.getError()", "gl.NO_ERROR");
// gl methods should still be no-ops
shouldGenerateGLError(gl, gl.NO_ERROR, gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP));
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)");
}, 1);
});
canvas.addEventListener("webglcontextrestored", function() {
@ -123,7 +123,7 @@ function testLosingAndRestoringContext()
shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
shouldBe("gl.getError()", "gl.NO_ERROR");
// gl methods should be no-ops
shouldGenerateGLError(gl, gl.NO_ERROR, gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP));
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)");
// but the event should not have been fired.
shouldBeFalse("contextLostEventFired");
}

View File

@ -11,7 +11,11 @@ var wtu;
var canvas;
var gl;
var shouldGenerateGLError;
var extension_name = "WEBGL_EXT_lose_context";
var extensionNames = [
"WEBKIT_WEBGL_lose_context",
"MOZ_WEBGL_lose_context",
];
var extensionName;
var extension;
var buffer;
@ -48,11 +52,17 @@ function init()
// for the isContextLost() method, which we want to do regardless of the extension's presence.
testValidContext();
extension = gl.getExtension(extension_name);
for (var ii = 0; ii < extensionNames.length; ++ii) {
extension = gl.getExtension(extensionNames[ii]);
if (extension) {
extensionName = extensionNames[ii];
break;
}
}
if (!extension) {
debug(extension_name + " extension not found.");
debug("Could not find lose_context extension under the following names: " + extensionNames.join(" "));
finishTest();
return;
return false;
}
canvas.addEventListener("webglcontextlost", testLostContext, false);
@ -67,7 +77,7 @@ function loseContext()
// Note: this will cause the context to be lost, but the
// webglcontextlost event listener to be queued.
shouldGenerateGLError(gl, gl.NO_ERROR, "extension.loseContext()");
extension.loseContext();
debug("");
}
@ -283,7 +293,7 @@ function testLostContext()
"gl.getUniformLocation(program, 'vPosition')",
"gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)",
"gl.getSupportedExtensions()",
"gl.getExtension('" + extension_name + "')",
"gl.getExtension('" + extensionName + "')",
];
for (var i = 0; i < nullTests.length; ++i) {
shouldBeNull(nullTests[i]);

View File

@ -1,5 +1,7 @@
functions/00_test_list.txt
implicit/00_test_list.txt
# commented out for version 1.0.1 of the conforamnce tests.
#matrices/00_test_list.txt
misc/00_test_list.txt
reserved/00_test_list.txt
# commented out for version 1.0.1 of the conforamnce tests.

View File

@ -5,7 +5,7 @@ invalid-passed-params.html
is-object.html
null-object-behaviour.html
object-deletion-behaviour.html
#shader-precision-format.html
type-conversion-test.html
uninitialized-test.html
webgl-specific.html

View File

@ -81,6 +81,7 @@ shouldThrowWithNew(WebGLRenderbuffer, 'WebGLRenderbuffer');
shouldThrowWithNew(WebGLShader, 'WebGLShader');
shouldThrowWithNew(WebGLTexture, 'WebGLTexture');
shouldThrowWithNew(WebGLUniformLocation, 'WebGLUniformLocation');
shouldThrowWithNew(WebGLShaderPrecisionFormat, 'WebGLShaderPrecisionFormat');
successfullyParsed = true;
</script>

View File

@ -1,5 +1,8 @@
<!--
Copyright (c) 2011 The Chromium Authors. All rights reserved.
Copyright (c) 2011 The Chromium Authors.
Copyright (c) 2011 Mozilla Foundation.
All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
@ -32,7 +35,7 @@ var fragmentShader = wtu.loadStandardFragmentShader(gl);
assertMsg(fragmentShader, "fragment shader loaded");
var program = gl.createProgram();
shouldBeTrue("program != null");
shouldBeNonNull("program");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.attachShader(program, vertexShader)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.attachShader(program, fragmentShader)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.linkProgram(program)");
@ -57,13 +60,13 @@ debug("");
debug("texture deletion");
var fbo = gl.createFramebuffer(), fbo2 = gl.createFramebuffer(), fbo3 = gl.createFramebuffer();
shouldBeTrue("fbo != null");
shouldBeTrue("fbo2 != null");
shouldBeTrue("fbo3 != null");
shouldBeNonNull("fbo");
shouldBeNonNull("fbo2");
shouldBeNonNull("fbo3");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
var tex = gl.createTexture();
shouldBeTrue("tex != null");
shouldBeNonNull("tex");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "tex");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
@ -80,7 +83,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
var texCubeMap = gl.createTexture();
shouldBeTrue("texCubeMap != null");
shouldBeNonNull("texCubeMap");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap)");
shouldBe("gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP)", "texCubeMap");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(texCubeMap)");
@ -90,7 +93,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_CUBE_MAP, texC
shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP)");
var t = gl.createTexture();
shouldBeTrue("t != null");
shouldBeNonNull("t");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(t)");
@ -98,7 +101,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t)");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)");
var t2 = gl.createTexture();
shouldBeTrue("t2 != null");
shouldBeNonNull("t2");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE0)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t2)");
shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "t2");
@ -114,9 +117,9 @@ debug("");
debug("renderbuffer deletion");
var rbo = gl.createRenderbuffer(), rbo2 = gl.createRenderbuffer(), rbo3 = gl.createRenderbuffer();
shouldBeTrue("rbo != null");
shouldBeTrue("rbo2 != null");
shouldBeTrue("rbo3 != null");
shouldBeNonNull("rbo");
shouldBeNonNull("rbo2");
shouldBeNonNull("rbo3");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rbo");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
@ -175,23 +178,23 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER,
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
var rbo2 = gl.createRenderbuffer();
rbo2 = gl.createRenderbuffer();
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo2)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
// attach rbo2 at two attachment points incompatible with it
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rbo2)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo2)");
shouldBeTrue("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) == rbo2");
shouldBeTrue("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) == rbo2");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo2");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo2");
// fbo can't be complete as rbo2 is attached at incompatible attachment points
shouldBeFalse("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE");
shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// now we delete rbo2, which detaches it from the two attachment points where it currently is attached
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo2)");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
// we should now be in the same state as before with only rbo attached, so fbo should be complete again
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
shouldBeTrue("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) == rbo");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo");
}
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
@ -229,7 +232,7 @@ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
debug("");
debug("using deleted renderbuffer");
rbo = gl.createRenderbuffer();
shouldBeTrue("rbo != null");
shouldBeNonNull("rbo");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
@ -249,19 +252,19 @@ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
// delete renderbuffer. It should still be attached to fbo2 though.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
// fbo has no attachments
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// Use fbo2 that has deleted rbo.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green")');
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,0,255,255], "fbo should be blue")');
shouldBeTrue("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) == rbo");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "rbo");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
shouldGenerateGLError(gl, gl.NONE, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// Bind backbuffer.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
@ -270,7 +273,7 @@ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
debug("");
debug("using deleted texture");
tex = gl.createTexture();
shouldBeTrue("tex != null");
shouldBeNonNull("tex");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
@ -285,19 +288,19 @@ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
// delete texture. It should still be attached to fbo2 though.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
// fbo has no attachments
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// Use fbo that has deleted texture.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE");
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,255,0,255], "fbo should be green")');
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,0,255,255], "fbo should be blue")');
shouldBeTrue("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) == tex");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "tex");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// Bind backbuffer.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
@ -307,7 +310,7 @@ debug("");
debug("buffer deletion");
var buffer = gl.createBuffer();
shouldBeTrue("buffer != null");
shouldBeNonNull("buffer");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)");
shouldBe("gl.getParameter(gl.ARRAY_BUFFER_BINDING)", "buffer");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(buffer)");
@ -317,7 +320,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)")
shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
var buffer2 = gl.createBuffer();
shouldBeTrue("buffer2 != null");
shouldBeNonNull("buffer2");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer2)");
shouldBe("gl.getParameter(gl.ARRAY_BUFFER_BINDING)", "buffer2");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, null)");
@ -328,7 +331,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer2)"
shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
var bufferElement = gl.createBuffer();
shouldBeTrue("bufferElement != null");
shouldBeNonNull("bufferElement");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferElement)");
shouldBe("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)", "bufferElement");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferElement)");
@ -338,7 +341,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, b
shouldBeNull("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)");
var b = gl.createBuffer();
shouldBeTrue("b != null");
shouldBeNonNull("b");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(b)");
@ -346,12 +349,12 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b)");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW)");
var b1 = gl.createBuffer();
shouldBeTrue("b1 != null");
shouldBeNonNull("b1");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b1);");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(1);");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);");
var b2 = gl.createBuffer();
shouldBeTrue("b2 != null");
shouldBeNonNull("b2");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b2);");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(2);");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(2, 4, gl.FLOAT, false, 0, 0);");
@ -384,8 +387,8 @@ shouldBe("gl.getParameter(gl.FRAMEBUFFER_BINDING)", "fbo2");
fbo = gl.createFramebuffer();
rbo = gl.createRenderbuffer();
shouldBeTrue("fbo != null");
shouldBeTrue("rbo != null");
shouldBeNonNull("fbo");
shouldBeNonNull("rbo");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");

View File

@ -1,5 +1,8 @@
<!--
Copyright (c) 2011 The Chromium Authors. All rights reserved.
Copyright (c) 2011 The Chromium Authors.
Copyright (c) 2011 Mozilla Foundation.
All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
@ -31,7 +34,7 @@ const ALLOW_COMPLETE = 0x01;
const ALLOW_UNSUPPORTED = 0x02;
const ALLOW_INCOMPLETE_ATTACHMENT = 0x04;
function CheckFramebufferForAllowedStatuses(allowedStatuses)
function checkFramebufferForAllowedStatuses(allowedStatuses)
{
// If the framebuffer is in an error state for multiple reasons,
// we can't guarantee which one will be reported.
@ -53,7 +56,7 @@ function testAttachment(attachment, buffer, allowedStatuses)
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, buffer);
glErrorShouldBe(gl, gl.NO_ERROR);
CheckFramebufferForAllowedStatuses(allowedStatuses);
checkFramebufferForAllowedStatuses(allowedStatuses);
if ((allowedStatuses & ALLOW_COMPLETE) == 0) {
gl.clear(gl.COLOR_BUFFER_BIT);
glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION);
@ -72,7 +75,7 @@ function testAttachments(attachment0, buffer0, attachment1, buffer1, allowedStat
glErrorShouldBe(gl, gl.NO_ERROR);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment1, gl.RENDERBUFFER, buffer1);
glErrorShouldBe(gl, gl.NO_ERROR);
CheckFramebufferForAllowedStatuses(allowedStatuses);
checkFramebufferForAllowedStatuses(allowedStatuses);
gl.deleteFramebuffer(fbo);
}
@ -238,7 +241,7 @@ if (checkValidColorDepthCombination()) {
testUsingIncompleteFramebuffer();
}
function CheckFramebuffer(expected) {
function checkFramebuffer(expected) {
var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
var msg = "gl.checkFramebufferStatus(gl.FRAMEBUFFER) should be " + wtu.glEnumToString(gl, expected) + " was " + wtu.glEnumToString(gl, actual);
if (expected != gl.FRAMEBUFFER_COMPLETE) {
@ -274,18 +277,18 @@ function testUsingIncompleteFramebuffer() {
gl.FRAMEBUFFER, depthAttachment, gl.RENDERBUFFER, depthBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16);
glErrorShouldBe(gl, gl.NO_ERROR);
CheckFramebuffer(gl.FRAMEBUFFER_COMPLETE);
checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
// We pick this combination because it works on desktop OpenGL but should not work on OpenGL ES 2.0
gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 32, 16);
CheckFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
debug("");
debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
testRenderingAndReading();
shouldBeNonNull("fbo2 = gl.createFramebuffer()");
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
CheckFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
debug("");
debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
testRenderingAndReading();
@ -325,20 +328,20 @@ function testFramebufferIncompleteAttachment() {
gl.framebufferRenderbuffer(
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
CheckFramebuffer(gl.FRAMEBUFFER_COMPLETE);
checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
debug("");
debug("Wrong storage type for type of attachment be FRAMEBUFFER_INCOMPLETE_ATTACHMENT (OpenGL ES 2.0 4.4.5)");
gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16);
CheckFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
CheckFramebuffer(gl.FRAMEBUFFER_COMPLETE);
checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
debug("");
debug("0 size attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT (OpenGL ES 2.0 4.4.5)");
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0);
CheckFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
glErrorShouldBe(gl, gl.NO_ERROR);
}
@ -348,18 +351,18 @@ function testFramebufferIncompleteMissingAttachment() {
debug("No attachments should be INCOMPLETE_FRAMEBUFFER_MISSING_ATTACHMENT (OpenGL ES 2.0 4.4.5)");
shouldBeNonNull("fbo = gl.createFramebuffer()");
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
CheckFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
shouldBeNonNull("colorBuffer = gl.createRenderbuffer()");
gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
gl.framebufferRenderbuffer(
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
CheckFramebuffer(gl.FRAMEBUFFER_COMPLETE);
checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
gl.framebufferRenderbuffer(
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
CheckFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
glErrorShouldBe(gl, gl.NO_ERROR);
}
@ -382,17 +385,17 @@ function testFramebufferIncompleteDimensions() {
gl.FRAMEBUFFER, depthAttachment, gl.RENDERBUFFER, depthBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16);
glErrorShouldBe(gl, gl.NO_ERROR);
CheckFramebuffer(gl.FRAMEBUFFER_COMPLETE);
checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 32, 16);
CheckFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16);
CheckFramebuffer(gl.FRAMEBUFFER_COMPLETE);
checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 32);
CheckFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
CheckFramebuffer(gl.FRAMEBUFFER_COMPLETE);
checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
glErrorShouldBe(gl, gl.NO_ERROR);
var tex = gl.createTexture();
@ -405,9 +408,9 @@ function testFramebufferIncompleteDimensions() {
}
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
CheckFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
CheckFramebuffer(gl.FRAMEBUFFER_COMPLETE);
checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
glErrorShouldBe(gl, gl.NO_ERROR);
}

View File

@ -132,12 +132,15 @@ var bvecTypes = [
var replaceRE = /\$\((\w+)\)/g;
var replaceParams = function(str, params) {
var replaceParams = function(str) {
var args = arguments;
return str.replace(replaceRE, function(str, p1, offset, s) {
if (params[p1] === undefined) {
throw "unknown string param '" + p1 + "'";
for (var ii = 1; ii < args.length; ++ii) {
if (args[ii][p1] !== undefined) {
return args[ii][p1];
}
}
return params[p1];
throw "unknown string param '" + p1 + "'";
});
};
@ -443,6 +446,233 @@ var runFeatureTest = function(params) {
};
var runBasicTest = function(params) {
if (window.initNonKhronosFramework) {
window.initNonKhronosFramework(false);
}
var wtu = WebGLTestUtils;
var gridRes = params.gridRes;
var vertexTolerance = params.tolerance || 0;
var fragmentTolerance = vertexTolerance;
if ('fragmentTolerance' in params)
fragmentTolerance = params.fragmentTolerance || 0;
description("Testing : " + document.getElementsByTagName("title")[0].innerText);
var width = 32;
var height = 32;
var console = document.getElementById("console");
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var gl = wtu.create3DContext(canvas);
if (!gl) {
testFailed("context does not exist");
finishTest();
return;
}
var canvas2d = document.createElement('canvas');
canvas2d.width = width;
canvas2d.height = height;
var ctx = canvas2d.getContext("2d");
var imgData = ctx.getImageData(0, 0, width, height);
var shaderInfos = [
{ type: "vertex",
input: "color",
output: "vColor",
vertexShaderTemplate: vertexShaderTemplate,
fragmentShaderTemplate: baseFragmentShader,
tolerance: vertexTolerance
},
{ type: "fragment",
input: "vColor",
output: "gl_FragColor",
vertexShaderTemplate: baseVertexShader,
fragmentShaderTemplate: fragmentShaderTemplate,
tolerance: fragmentTolerance
}
];
for (var ss = 0; ss < shaderInfos.length; ++ss) {
var shaderInfo = shaderInfos[ss];
var tests = params.tests;
// var testTypes = params.emuFuncs || (params.bvecTest ? bvecTypes : types);
// Test vertex shaders
for (var ii = 0; ii < tests.length; ++ii) {
var test = tests[ii];
debug("");
debug("Testing: " + test.name + " in " + shaderInfo.type + " shader");
function genShader(shaderInfo, template, shader, subs) {
shader = replaceParams(shader, subs, {
input: shaderInfo.input,
output: shaderInfo.output
});
shader = replaceParams(template, subs, {
test: shader,
emu: "",
extra: ""
});
return shader;
}
var referenceVertexShaderSource = genShader(
shaderInfo,
shaderInfo.vertexShaderTemplate,
test.reference.shader,
test.reference.subs);
var referenceFragmentShaderSource = genShader(
shaderInfo,
shaderInfo.fragmentShaderTemplate,
test.reference.shader,
test.reference.subs);
var testVertexShaderSource = genShader(
shaderInfo,
shaderInfo.vertexShaderTemplate,
test.test.shader,
test.test.subs);
var testFragmentShaderSource = genShader(
shaderInfo,
shaderInfo.fragmentShaderTemplate,
test.test.shader,
test.test.subs);
debug("");
addShaderSource(
"reference vertex shader", referenceVertexShaderSource);
addShaderSource(
"reference fragment shader", referenceFragmentShaderSource);
addShaderSource(
"test vertex shader", testVertexShaderSource);
addShaderSource(
"test fragment shader", testFragmentShaderSource);
debug("");
var refData = draw(
canvas, referenceVertexShaderSource, referenceFragmentShaderSource);
var refImg = makeImage(canvas);
if (ss == 0) {
var testData = draw(
canvas, testVertexShaderSource, referenceFragmentShaderSource);
} else {
var testData = draw(
canvas, referenceVertexShaderSource, testFragmentShaderSource);
}
var testImg = makeImage(canvas);
reportResults(refData, refImg, testData, testImg, shaderInfo.tolerance);
}
}
finishTest();
function addShaderSource(label, source) {
var div = document.createElement("div");
var s = document.createElement("pre");
s.className = "shader-source";
s.style.display = "none";
var ol = document.createElement("ol");
//s.appendChild(document.createTextNode(source));
var lines = source.split("\n");
for (var ii = 0; ii < lines.length; ++ii) {
var line = lines[ii];
var li = document.createElement("li");
li.appendChild(document.createTextNode(line));
ol.appendChild(li);
}
s.appendChild(ol);
var l = document.createElement("a");
l.href = "show-shader-source";
l.appendChild(document.createTextNode(label));
l.addEventListener('click', function(event) {
if (event.preventDefault) {
event.preventDefault();
}
s.style.display = (s.style.display == 'none') ? 'block' : 'none';
return false;
}, false);
div.appendChild(l);
div.appendChild(s);
console.appendChild(div);
}
function reportResults(refData, refImage, testData, testImage, tolerance) {
var same = true;
for (var yy = 0; yy < height; ++yy) {
for (var xx = 0; xx < width; ++xx) {
var offset = (yy * width + xx) * 4;
var imgOffset = ((height - yy - 1) * width + xx) * 4;
imgData.data[imgOffset + 0] = 0;
imgData.data[imgOffset + 1] = 0;
imgData.data[imgOffset + 2] = 0;
imgData.data[imgOffset + 3] = 255;
if (Math.abs(refData[offset + 0] - testData[offset + 0]) > tolerance ||
Math.abs(refData[offset + 1] - testData[offset + 1]) > tolerance ||
Math.abs(refData[offset + 2] - testData[offset + 2]) > tolerance ||
Math.abs(refData[offset + 3] - testData[offset + 3]) > tolerance) {
imgData.data[imgOffset] = 255;
same = false;
}
}
}
var diffImg = null;
if (!same) {
ctx.putImageData(imgData, 0, 0);
diffImg = makeImage(canvas2d);
}
var div = document.createElement("div");
div.className = "testimages";
insertImg(div, "ref", refImg);
insertImg(div, "test", testImg);
if (diffImg) {
insertImg(div, "diff", diffImg);
}
div.appendChild(document.createElement('br'));
function insertImg(element, caption, img) {
var div = document.createElement("div");
div.appendChild(img);
var label = document.createElement("div");
label.appendChild(document.createTextNode(caption));
div.appendChild(label);
element.appendChild(div);
}
console.appendChild(div);
if (!same) {
testFailed("images are different");
} else {
testPassed("images are the same");
}
console.appendChild(document.createElement('hr'));
}
function draw(canvas, vsSource, fsSource) {
var program = wtu.loadProgram(gl, vsSource, fsSource, testFailed);
var posLoc = gl.getAttribLocation(program, "aPosition");
WebGLTestUtils.setupQuad(gl, gridRes, posLoc);
gl.useProgram(program);
gl.clearColor(0, 0, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, gridRes * gridRes * 6, gl.UNSIGNED_SHORT, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
var img = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, img);
return img;
}
};
return {
/**
* runs a bunch of GLSL tests using the passed in parameters
@ -507,6 +737,82 @@ return {
*/
runFeatureTest: runFeatureTest,
/*
* Runs a bunch of GLSL tests using the passed in parameters
*
* The parameters are:
*
* tests:
* Array of tests. For each test the following parameters are expected
*
* name:
* some description of the test
* reference:
* parameters for the reference shader (see below)
* test:
* parameters for the test shader (see below)
*
* The parameter for the reference and test shaders are
*
* shader: the GLSL for the shader
* subs: any substitutions you wish to define for the shader.
*
* Each shader is created from a basic template that
* defines an input and an output. You can see the
* templates at the top of this file. The input and output
* change depending on whether or not we are generating
* a vertex or fragment shader.
*
* All this code function does is a bunch of string substitutions.
* A substitution is defined by $(name). If name is found in
* the 'subs' parameter it is replaced. 4 special names exist.
*
* 'input' the input to your GLSL. Always a vec4. All change
* from 0 to 1 over the quad to be drawn.
*
* 'output' the output color. Also a vec4
*
* 'emu' a place to insert extra stuff
* 'extra' a place to insert extra stuff.
*
* You can think of the templates like this
*
* $(extra)
* $(emu)
*
* void main() {
* // do math to calculate input
* ...
*
* $(shader)
* }
*
* Your shader first has any subs you provided applied as well
* as 'input' and 'output'
*
* It is then inserted into the template which is also provided
* with your subs.
*
* gridRes: (optional)
* The resolution of the mesh to generate. The default is a
* 1x1 grid but many vertex shaders need a higher resolution
* otherwise the only values passed in are the 4 corners
* which often have the same value.
*
* tolerance: (optional)
* Allow some tolerance in the comparisons. The tolerance is applied to
* both vertex and fragment shaders. The default tolerance is 0, meaning
* the values have to be identical.
*
* fragmentTolerance: (optional)
* Specify a tolerance which only applies to fragment shaders. The
* fragment-only tolerance will override the shared tolerance for
* fragment shaders if both are specified. Fragment shaders usually
* use mediump float precision so they sometimes require higher tolerance
* than vertex shaders which use highp.
*/
runBasicTest: runBasicTest,
none: false
};

View File

@ -905,6 +905,17 @@ var loadShaderFromFile = function(gl, file, type, opt_errorCallback) {
return loadShader(gl, shaderSource, type, opt_errorCallback);
};
/**
* Gets the content of script.
*/
var getScript = function(scriptId) {
var shaderScript = document.getElementById(scriptId);
if (!shaderScript) {
throw("*** Error: unknown script element" + scriptId);
}
return shaderScript.text;
};
/**
* Loads a shader from a script tag.
* @param {!WebGLContext} gl The WebGLContext to use.
@ -1123,6 +1134,7 @@ return {
endsWith: endsWith,
getFileListAsync: getFileListAsync,
getLastError: getLastError,
getScript: getScript,
getUrlArguments: getUrlArguments,
glEnumToString: glEnumToString,
glErrorShouldBe: glErrorShouldBe,

View File

@ -399,6 +399,18 @@ function runTests(imgs) {
// The image should be red.
checkPixelRange(buf, middle, center, [ 255, 0, 0, 255 ], 10);
debug("")
debug("check calling texImage2D with NULL clears the texture");
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB,
imgs['../resources/red-indexed.png'].width,
imgs['../resources/red-indexed.png'].height,
0, gl.RGB, gl.UNSIGNED_BYTE, null);
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
wtu.drawQuad(gl);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
// The image should be white.
checkPixelRange(buf, middle, center, [ 0, 0, 0, 255 ], 10);
debug("");
successfullyParsed = true;
shouldBeTrue("successfullyParsed");

View File

@ -1,5 +1,5 @@
# HG changeset patch
# Parent 9c1a90f789e3d43455cb18a9a911627c80c0d9ac
# Parent 07fbbfde4173da7d8e513bb2d52ae07e333dbf43
diff --git a/content/canvas/test/webgl/conformance/more/functions/readPixelsBadArgs.html b/content/canvas/test/webgl/conformance/more/functions/readPixelsBadArgs.html
--- a/content/canvas/test/webgl/conformance/more/functions/readPixelsBadArgs.html
+++ b/content/canvas/test/webgl/conformance/more/functions/readPixelsBadArgs.html

View File

@ -0,0 +1,109 @@
<!--
Copyright (c) 2011 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charset="utf-8">
<title>WebGL ouf of bounds uniform array access.</title>
<link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../resources/js-test-pre.js"></script>
<script src="../conformance/resources/webgl-test-utils.js"> </script>
</head>
<body style="background: #666;">
<div id="description"></div>
<div id="console"></div>
<div>elem mult: <span id="elemMultDisplay"></span></div>
<input type="range" id="elemMult" value="4" min="0" max="2048" style="width: 100%;"/>
<div>line width: <span id="lineWidthDisplay"></span></div>
<input type="range" id="lineWidth" value="512" min="0" max="2540" style="width: 100%;"/>
<canvas id="example" width="256" height="256" style="background: black;">
</canvas>
<script id="vshader" type="x-shader/x-vertex">
attribute vec4 vPosition;
varying vec4 v_color;
uniform float lineWidth;
uniform int elemMult;
uniform vec4 someArray[2];
void main()
{
vec2 texcoord = vec2(vPosition.xy * 0.5 + vec2(0.5, 0.5));
int index = int(texcoord.x + texcoord.y * lineWidth) * elemMult;
v_color = someArray[index];
gl_Position = vPosition;
}
</script>
<script id="fshader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 v_color;
void main()
{
gl_FragColor = v_color * vec4(1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0) + vec4(0,0,0,0.5);
}
</script>
<script>
window.onload = main;
debug("Tests a WebGL program that accesses out of bounds uniform array elements");
function main() {
var wtu = WebGLTestUtils;
var canvas = document.getElementById("example");
var gl = wtu.create3DContext(canvas);
var program = wtu.setupProgram(
gl,
[wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
['vPosition'], [0]);
var gridRes = 255;
wtu.setupQuad(gl, gridRes, 0);
var lineWidthLoc = gl.getUniformLocation(program, "lineWidth");
var elemMultLoc = gl.getUniformLocation(program, "elemMult");
assertMsg(gl.getError() == gl.NO_ERROR, "Should be no errors from setup.");
var lineWidth = 512;
var lineWidthElem = document.getElementById("lineWidth");
var lineWidthDisplayElem = document.getElementById("lineWidthDisplay");
lineWidthElem.value = lineWidth;
lineWidthElem.addEventListener('change', function(event) {
//console.log(event.target.value);
lineWidth = event.target.value;
draw();
}, false);
var elemMult = 4;
var elemMultElem = document.getElementById("elemMult");
var elemMultDisplayElem = document.getElementById("elemMultDisplay");
elemMultElem.value = elemMult;
elemMultElem.addEventListener('change', function(event) {
//console.log(event.target.value);
elemMult = event.target.value;
draw();
}, false);
draw();
function draw() {
lineWidthDisplayElem.innerText = lineWidth;
elemMultDisplayElem.innerText = elemMult;
gl.uniform1f(lineWidthLoc, lineWidth);
gl.uniform1i(elemMultLoc, elemMult);
gl.drawElements(gl.TRIANGLES, gridRes * gridRes * 6, gl.UNSIGNED_SHORT, 0);
}
successfullyParsed = true;
}
</script>
</body>
</html>

View File

@ -1,4 +1,3 @@
conformance/context/context-lost-restored.html
conformance/context/premultiplyalpha-test.html
conformance/glsl/misc/glsl-long-variable-names.html
conformance/glsl/misc/shader-with-256-character-identifier.frag.html

View File

@ -1,4 +1,3 @@
conformance/context/context-lost-restored.html
conformance/context/premultiplyalpha-test.html
conformance/glsl/misc/glsl-function-nodes.html
conformance/glsl/misc/glsl-long-variable-names.html

View File

@ -1,4 +1,3 @@
conformance/context/context-lost-restored.html
conformance/context/premultiplyalpha-test.html
conformance/glsl/functions/glsl-function-atan.html
conformance/glsl/functions/glsl-function-atan-xy.html

View File

@ -1,5 +1,5 @@
# HG changeset patch
# Parent 4ed0bad4933ba69927ee5f75cf67093d3e99566a
# Parent 1910ae60536dce7272cb0478089bf40806666de8
diff --git a/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html b/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html
--- a/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html

View File

@ -1,5 +1,5 @@
# HG changeset patch
# Parent bf9d7872738cdb7cf425e6dd060ae62882487e1a
# Parent a41d853e5110aca4f2c77c63db502f670d0e50a1
diff --git a/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html b/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html
--- a/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html
+++ b/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html

View File

@ -217,27 +217,52 @@ function evalAndLog(_a)
return _av;
}
function shouldBe(_a, _b)
function shouldBe(_a, _b, quiet)
{
if (typeof _a != "string" || typeof _b != "string")
debug("WARN: shouldBe() expects string arguments");
var exception;
var _av;
try {
_av = eval(_a);
} catch (e) {
exception = e;
}
var _bv = eval(_b);
if (typeof _a != "string" || typeof _b != "string")
debug("WARN: shouldBe() expects string arguments");
var exception;
var _av;
try {
_av = eval(_a);
} catch (e) {
exception = e;
}
var _bv = eval(_b);
if (exception)
testFailed(_a + " should be " + _bv + ". Threw exception " + exception);
else if (isResultCorrect(_av, _bv))
testPassed(_a + " is " + _b);
else if (typeof(_av) == typeof(_bv))
testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + ".");
else
testFailed(_a + " should be " + _bv + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
if (exception)
testFailed(_a + " should be " + _bv + ". Threw exception " + exception);
else if (isResultCorrect(_av, _bv)) {
if (!quiet) {
testPassed(_a + " is " + _b);
}
} else if (typeof(_av) == typeof(_bv))
testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + ".");
else
testFailed(_a + " should be " + _bv + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
}
function shouldNotBe(_a, _b, quiet)
{
if (typeof _a != "string" || typeof _b != "string")
debug("WARN: shouldNotBe() expects string arguments");
var exception;
var _av;
try {
_av = eval(_a);
} catch (e) {
exception = e;
}
var _bv = eval(_b);
if (exception)
testFailed(_a + " should not be " + _bv + ". Threw exception " + exception);
else if (!isResultCorrect(_av, _bv)) {
if (!quiet) {
testPassed(_a + " is not " + _b);
}
} else
testFailed(_a + " should not be " + _bv + ".");
}
function shouldBeTrue(_a) { shouldBe(_a, "true"); }

View File

@ -1,6 +1,5 @@
# HG changeset patch
# Parent 41137626edf2a358f2be1b7ed3f83211230ab4f5
# Parent fb36d18f04ef9b01ca87d3fde539d50c204f9bba
diff --git a/content/canvas/test/webgl/resources/webgl-test-harness.js b/content/canvas/test/webgl/resources/webgl-test-harness.js
--- a/content/canvas/test/webgl/resources/webgl-test-harness.js
+++ b/content/canvas/test/webgl/resources/webgl-test-harness.js

View File

@ -114,7 +114,6 @@
#include "mozAutoDocUpdate.h"
#include "nsContentCreatorFunctions.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsContentUtils.h"
#include "nsRadioVisitor.h"
@ -3904,8 +3903,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
bool
nsHTMLInputElement::IsValidEmailAddressList(const nsAString& aValue)
{
nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
tokenizer(aValue, ',');
HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
while (tokenizer.hasMoreTokens()) {
if (!IsValidEmailAddress(tokenizer.nextToken())) {
@ -4124,8 +4122,7 @@ nsHTMLInputElement::GetFilterFromAccept()
nsAutoString accept;
GetAttr(kNameSpaceID_None, nsGkAtoms::accept, accept);
nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
tokenizer(accept, ',');
HTMLSplitOnSpacesTokenizer tokenizer(accept, ',');
while (tokenizer.hasMoreTokens()) {
const nsDependentSubstring token = tokenizer.nextToken();

View File

@ -1170,7 +1170,7 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
bool shouldInitializeEditor = false;
nsCOMPtr<nsIEditor> newEditor; // the editor that we might create
nsresult rv;
nsresult rv = NS_OK;
if (!mEditor) {
shouldInitializeEditor = true;

View File

@ -1514,8 +1514,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(IDBFactory, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBRequest, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBRequest, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBDatabase, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBObjectStore, nsDOMGenericSH,
@ -4683,15 +4683,6 @@ nsDOMClassInfo::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsDOMClassInfo::Trace(nsIXPConnectWrappedNative *wrapper, JSTracer *trc,
JSObject *obj)
{
NS_WARNING("nsDOMClassInfo::Trace Don't call me!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsDOMClassInfo::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
JSObject * obj, const jsval &val, bool *bp)

View File

@ -2039,3 +2039,19 @@ nsDOMWindowUtils::GetPCCountScriptContents(PRInt32 script, JSContext* cx, nsAStr
result = str;
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetPaintingSuppressed(bool *aPaintingSuppressed)
{
NS_ENSURE_TRUE(mWindow, NS_ERROR_FAILURE);
nsIDocShell *docShell = mWindow->GetDocShell();
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIPresShell> presShell;
docShell->GetPresShell(getter_AddRefs(presShell));
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
*aPaintingSuppressed = presShell->IsPaintingSuppressed();
return NS_OK;
}

View File

@ -44,6 +44,7 @@
#include "nsContentUtils.h"
#include "nsProxyRelease.h"
#include "nsThreadUtils.h"
#include "nsWrapperCacheInlines.h"
#include "IDBEvents.h"
#include "IDBTransaction.h"
@ -145,11 +146,18 @@ HelperBase::WrapNative(JSContext* aCx,
NS_ASSERTION(aResult, "Null pointer!");
NS_ASSERTION(mRequest, "Null request!");
JSObject* global = mRequest->ScriptContext()->GetNativeGlobal();
NS_ENSURE_TRUE(global, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
JSObject* obj;
if (mRequest->ScriptContext()) {
obj = mRequest->ScriptContext()->GetNativeGlobal();
}
else {
obj = mRequest->GetWrapper();
}
NS_ENSURE_TRUE(obj, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsresult rv =
nsContentUtils::WrapNative(aCx, global, aNative, aResult);
nsContentUtils::WrapNative(aCx, obj, aNative, aResult);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
return NS_OK;

View File

@ -77,6 +77,11 @@ GetIndexedDBPermissions(const nsACString& aASCIIOrigin,
return nsIPermissionManager::DENY_ACTION;
}
// No window here means chrome access
if (!aWindow) {
return nsIPermissionManager::ALLOW_ACTION;
}
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(aWindow));
NS_ENSURE_TRUE(sop, nsIPermissionManager::DENY_ACTION);

View File

@ -76,7 +76,6 @@ public:
mPromptResult(0)
{
NS_ASSERTION(aHelper, "Null pointer!");
NS_ASSERTION(aWindow, "Null pointer!");
NS_ASSERTION(!aASCIIOrigin.IsEmpty(), "Empty origin!");
}

View File

@ -57,7 +57,6 @@
#include "IDBTransaction.h"
#include "IDBFactory.h"
#include "IndexedDatabaseManager.h"
#include "LazyIdleThread.h"
#include "TransactionThreadPool.h"
#include "DictionaryHelpers.h"
@ -715,6 +714,10 @@ IDBDatabase::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
NS_ENSURE_TRUE(aVisitor.mDOMEvent, NS_ERROR_UNEXPECTED);
if (!mOwner) {
return NS_OK;
}
if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault) {
nsString type;
nsresult rv = aVisitor.mDOMEvent->GetType(type);

View File

@ -106,19 +106,20 @@ public:
nsIScriptContext* ScriptContext()
{
NS_ASSERTION(mScriptContext, "This should never be null!");
return mScriptContext;
}
nsPIDOMWindow* Owner()
{
NS_ASSERTION(mOwner, "This should never be null!");
return mOwner;
}
already_AddRefed<nsIDocument> GetOwnerDocument()
{
NS_ASSERTION(mOwner, "This should never be null!");
if (!mOwner) {
return nsnull;
}
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mOwner->GetExtantDocument());
return doc.forget();
}

View File

@ -69,7 +69,6 @@
#include "IDBKeyRange.h"
#include "IndexedDatabaseManager.h"
#include "Key.h"
#include "LazyIdleThread.h"
#include "nsIScriptSecurityManager.h"
using namespace mozilla;
@ -101,17 +100,18 @@ already_AddRefed<nsIIDBFactory>
IDBFactory::Create(nsPIDOMWindow* aWindow)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aWindow, "Must have a window!");
if (aWindow->IsOuterWindow()) {
if (aWindow && aWindow->IsOuterWindow()) {
aWindow = aWindow->GetCurrentInnerWindow();
NS_ENSURE_TRUE(aWindow, nsnull);
}
NS_ENSURE_TRUE(aWindow, nsnull);
nsRefPtr<IDBFactory> factory = new IDBFactory();
factory->mWindow = do_GetWeakReference(aWindow);
NS_ENSURE_TRUE(factory->mWindow, nsnull);
if (aWindow) {
factory->mWindow = do_GetWeakReference(aWindow);
NS_ENSURE_TRUE(factory->mWindow, nsnull);
}
return factory.forget();
}
@ -427,14 +427,20 @@ IDBFactory::OpenCommon(const nsAString& aName,
ContentChild::GetSingleton()->GetIndexedDBPath();
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsCOMPtr<nsPIDOMWindow> window;
nsCOMPtr<nsIScriptGlobalObject> sgo;
nsIScriptContext* context = nsnull;
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
NS_ENSURE_TRUE(sgo, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsIScriptContext* context = sgo->GetContext();
NS_ENSURE_TRUE(context, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (mWindow) {
window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
sgo = do_QueryInterface(window);
NS_ENSURE_TRUE(sgo, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
context = sgo->GetContext();
NS_ENSURE_TRUE(context, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
nsCString origin;
nsresult rv =

View File

@ -40,6 +40,7 @@
#include "IDBRequest.h"
#include "nsIJSContextStack.h"
#include "nsIScriptContext.h"
#include "nsComponentManagerUtils.h"
@ -50,11 +51,11 @@
#include "nsPIDOMWindow.h"
#include "nsStringGlue.h"
#include "nsThreadUtils.h"
#include "nsWrapperCacheInlines.h"
#include "AsyncConnectionHelper.h"
#include "IDBEvents.h"
#include "IDBTransaction.h"
#include "nsContentUtils.h"
USING_INDEXEDDB_NAMESPACE
@ -87,12 +88,6 @@ IDBRequest::Create(nsISupports* aSource,
IDBTransaction* aTransaction)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (!aScriptContext || !aOwner) {
NS_ERROR("Null context and owner!");
return nsnull;
}
nsRefPtr<IDBRequest> request(new IDBRequest());
request->mSource = aSource;
@ -140,15 +135,29 @@ IDBRequest::NotifyHelperCompleted(HelperBase* aHelper)
}
// Otherwise we need to get the result from the helper.
JSContext* cx = mScriptContext->GetNativeContext();
NS_ASSERTION(cx, "Failed to get a context!");
JSContext* cx = nsnull;
JSObject* obj = nsnull;
if (mScriptContext) {
cx = mScriptContext->GetNativeContext();
NS_ASSERTION(cx, "Failed to get a context!");
JSObject* global = mScriptContext->GetNativeGlobal();
NS_ASSERTION(global, "Failed to get global object!");
obj = mScriptContext->GetNativeGlobal();
NS_ASSERTION(obj, "Failed to get global object!");
}
else {
nsIThreadJSContextStack* cxStack = nsContentUtils::ThreadJSContextStack();
NS_ASSERTION(cxStack, "Failed to get thread context stack!");
NS_ENSURE_SUCCESS(cxStack->GetSafeJSContext(&cx),
NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
obj = GetWrapper();
NS_ENSURE_TRUE(obj, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, global)) {
if (!ac.enter(cx, obj)) {
rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
else {
@ -290,7 +299,7 @@ IDBRequest::GetOnerror(nsIDOMEventListener** aErrorListener)
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBRequest,
nsDOMEventTargetHelper)
nsDOMEventTargetWrapperCache)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnSuccessListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener)
@ -300,7 +309,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBRequest,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBRequest,
nsDOMEventTargetHelper)
nsDOMEventTargetWrapperCache)
if (tmp->mResultValRooted) {
tmp->mResultVal = JSVAL_VOID;
tmp->UnrootResultVal();
@ -311,7 +320,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBRequest,
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTransaction)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBRequest)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(IDBRequest,
nsDOMEventTargetWrapperCache)
if (JSVAL_IS_GCTHING(tmp->mResultVal)) {
void *gcThing = JSVAL_TO_GCTHING(tmp->mResultVal);
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mResultVal")
@ -321,10 +331,10 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBRequest)
NS_INTERFACE_MAP_ENTRY(nsIIDBRequest)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBRequest)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetWrapperCache)
NS_IMPL_ADDREF_INHERITED(IDBRequest, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(IDBRequest, nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(IDBRequest, nsDOMEventTargetWrapperCache)
NS_IMPL_RELEASE_INHERITED(IDBRequest, nsDOMEventTargetWrapperCache)
DOMCI_DATA(IDBRequest, IDBRequest)
@ -353,12 +363,6 @@ IDBOpenDBRequest::Create(nsIScriptContext* aScriptContext,
nsPIDOMWindow* aOwner)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (!aScriptContext || !aOwner) {
NS_ERROR("Null context and owner!");
return nsnull;
}
nsRefPtr<IDBOpenDBRequest> request(new IDBOpenDBRequest());
request->mScriptContext = aScriptContext;

View File

@ -57,14 +57,14 @@ BEGIN_INDEXEDDB_NAMESPACE
class HelperBase;
class IDBTransaction;
class IDBRequest : public nsDOMEventTargetHelper,
class IDBRequest : public nsDOMEventTargetWrapperCache,
public nsIIDBRequest
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIIDBREQUEST
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(IDBRequest,
nsDOMEventTargetHelper)
nsDOMEventTargetWrapperCache)
static
already_AddRefed<IDBRequest> Create(nsISupports* aSource,
@ -94,13 +94,11 @@ public:
nsIScriptContext* ScriptContext()
{
NS_ASSERTION(mScriptContext, "This should never be null!");
return mScriptContext;
}
nsPIDOMWindow* Owner()
{
NS_ASSERTION(mOwner, "This should never be null!");
return mOwner;
}

View File

@ -40,6 +40,7 @@
#include "IndexedDatabaseManager.h"
#include "DatabaseInfo.h"
#include "nsIDOMScriptObjectFactory.h"
#include "nsIFile.h"
#include "nsIObserverService.h"
#include "nsIScriptObjectPrincipal.h"
@ -48,6 +49,7 @@
#include "nsISimpleEnumerator.h"
#include "nsITimer.h"
#include "mozilla/LazyIdleThread.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/storage.h"
@ -63,7 +65,7 @@
#include "IDBDatabase.h"
#include "IDBEvents.h"
#include "IDBFactory.h"
#include "LazyIdleThread.h"
#include "IDBKeyRange.h"
#include "OpenDatabaseHelper.h"
#include "TransactionThreadPool.h"
@ -85,6 +87,8 @@ USING_INDEXEDDB_NAMESPACE
using namespace mozilla::services;
using mozilla::Preferences;
static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
namespace {
PRInt32 gShutdown = 0;
@ -605,10 +609,10 @@ IndexedDatabaseManager::SetCurrentWindowInternal(nsPIDOMWindow* aWindow)
PR_SetThreadPrivate(mCurrentWindowIndex, aWindow);
}
else {
#ifdef DEBUG
NS_ASSERTION(PR_GetThreadPrivate(mCurrentWindowIndex),
"Somebody forgot to clear the current window!");
#endif
// We cannot assert PR_GetThreadPrivate(mCurrentWindowIndex) here
// because we cannot distinguish between the thread private became
// null and that it was set to null on the first place,
// because we didn't have a window.
PR_SetThreadPrivate(mCurrentWindowIndex, nsnull);
}
}
@ -890,6 +894,13 @@ IndexedDatabaseManager::GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow,
NS_ASSERTION(NS_IsMainThread(),
"We're about to touch a window off the main thread!");
if (!aWindow) {
aASCIIOrigin.AssignLiteral("chrome");
NS_ASSERTION(nsContentUtils::IsCallerChrome(),
"Null window but not chrome!");
return NS_OK;
}
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow);
NS_ENSURE_TRUE(sop, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@ -1588,6 +1599,48 @@ IndexedDatabaseManager::SynchronizedOp::DispatchDelayedRunnables()
mDelayedRunnables.Clear();
}
NS_IMETHODIMP
IndexedDatabaseManager::InitWindowless(const jsval& aObj, JSContext* aCx)
{
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
// Instantiating this class will register exception providers so even
// in xpcshell we will get typed (dom) exceptions, instead of general exceptions.
nsCOMPtr<nsIDOMScriptObjectFactory> sof(do_GetService(kDOMSOF_CID));
// Defining IDBKeyrange static functions on the global.
if (JSVAL_IS_PRIMITIVE(aObj)) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIIDBFactory> factory = IDBFactory::Create(nsnull);
NS_ASSERTION(factory, "IDBFactory should not be null.");
JSObject* obj = JSVAL_TO_OBJECT(aObj);
jsval mozIndexedDBVal;
nsresult rv = nsContentUtils::WrapNative(aCx, obj, factory, &mozIndexedDBVal);
NS_ENSURE_SUCCESS(rv, rv);
if (!JS_DefineProperty(aCx, obj, "mozIndexedDB", mozIndexedDBVal,
nsnull, nsnull, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
JSObject* keyrangeObj = JS_NewObject(aCx, nsnull, nsnull, nsnull);
NS_ENSURE_TRUE(keyrangeObj, NS_ERROR_OUT_OF_MEMORY);
if (!IDBKeyRange::DefineConstructors(aCx, keyrangeObj)) {
return NS_ERROR_FAILURE;
}
if (!JS_DefineProperty(aCx, obj, "IDBKeyRange", OBJECT_TO_JSVAL(keyrangeObj),
nsnull, nsnull, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMPL_THREADSAFE_ISUPPORTS1(IndexedDatabaseManager::AsyncDeleteFileRunnable,
nsIRunnable)

View File

@ -395,7 +395,6 @@ class AutoEnterWindow
public:
AutoEnterWindow(nsPIDOMWindow* aWindow)
{
NS_ASSERTION(aWindow, "This should never be null!");
IndexedDatabaseManager::SetCurrentWindow(aWindow);
}

View File

@ -68,7 +68,6 @@ CPPSRCS = \
IDBTransaction.cpp \
IDBFactory.cpp \
IndexedDatabaseManager.cpp \
LazyIdleThread.cpp \
OpenDatabaseHelper.cpp \
TransactionThreadPool.cpp \
Key.cpp \
@ -87,7 +86,6 @@ EXPORTS_mozilla/dom/indexedDB = \
IndexedDatabaseManager.h \
IDBFactory.h \
Key.h \
LazyIdleThread.h \
FileManager.h \
FileInfo.h \
$(NULL)
@ -99,6 +97,7 @@ LOCAL_INCLUDES = \
-I$(topsrcdir)/dom/src/storage \
-I$(topsrcdir)/content/base/src \
-I$(topsrcdir)/content/events/src \
-I$(topsrcdir)/js/xpconnect/src \
$(NULL)
DEFINES += -D_IMPL_NS_LAYOUT

View File

@ -1611,10 +1611,7 @@ OpenDatabaseHelper::DoDatabaseWork()
NS_ASSERTION(mOpenDBRequest, "This should never be null!");
// Once we support IDB outside of Windows this assertion will no longer hold.
nsPIDOMWindow* window = mOpenDBRequest->Owner();
NS_ASSERTION(window, "This should never be null");
AutoEnterWindow autoWindow(window);
nsCOMPtr<nsIFile> dbDirectory;
@ -2399,6 +2396,9 @@ DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_WARNING("Failed to delete file directory!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
rv = fileManagerDirectory->Remove(true);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;

View File

@ -52,7 +52,7 @@ interface nsIIndexedDatabaseUsageCallback : nsISupports
in unsigned long long aFileUsage);
};
[scriptable, builtinclass, uuid(415f5684-6c84-4a8b-b777-d01f5df778f2)]
[scriptable, builtinclass, uuid(02256aa7-70d8-473f-bf3b-8cb35d28fd75)]
interface nsIIndexedDatabaseManager : nsISupports
{
/**
@ -88,4 +88,14 @@ interface nsIIndexedDatabaseManager : nsISupports
* The URI whose databases are to be cleared.
*/
void clearDatabasesForURI(in nsIURI aURI);
/**
* Defines mozIndexedDB and IDBKeyrange with its static functions on
* aObject and initializes DOM exception providers if needed.
*
* @param aObject
* The object, mozIndexedDB and IDBKeyrange should be defined on.
*/
[implicit_jscontext]
void initWindowless(in jsval aObject);
};

View File

@ -40,10 +40,15 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = dom/indexedDB/test
DIRS += unit
include $(DEPTH)/config/autoconf.mk
XPCSHELL_TESTS = unit
include $(topsrcdir)/config/rules.mk
TEST_FILES = \
bfcache_iframe1.html \
bfcache_iframe2.html \
@ -145,6 +150,8 @@ BROWSER_TEST_FILES = \
browser_quotaPromptDeny.js \
browser_quotaPromptDatabases.html \
browser_quotaPromptDatabases.js \
browser_quotaPromptDelete.html \
browser_quotaPromptDelete.js \
head.js \
$(NULL)

View File

@ -0,0 +1,97 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Test</title>
<script type="text/javascript;version=1.7">
const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
let db;
let name = window.location.pathname;
function onAddMore() {
let transaction = db.transaction("foo", READ_WRITE);
transaction.oncomplete = function(event) {
setTimeout(testFinishedCallback, 0, "complete");
}
transaction.onabort = function(event) {
setTimeout(testFinishedCallback, 0, "abort");
}
let objectStore = transaction.objectStore("foo");
let obj = {
foo: " ",
bar: " ",
baz: " "
};
for (let i = 0; i < 1000; i++) {
objectStore.add(obj).onerror = errorHandler;
}
}
function onDone() {
window.removeEventListener("indexedDB-addMore", onAddMore, true);
window.removeEventListener("indexedDB-done", onDone, true);
window.removeEventListener("indexedDB-reset", onReset, true);
testResult = "finished";
testException = undefined;
finishTest();
}
function onReset() {
db.close();
// N.B. the spec provides no ordering guarantee w.r.t deleteDatabase.
let deleteRequest = mozIndexedDB.deleteDatabase(name);
deleteRequest.onerror = errorHandler;
deleteRequest.onsuccess = function () {
// It is imperative that we open a different database this time.
let request = mozIndexedDB.open("take2", 1);
request.onerror = errorHandler;
request.onupgradeneeded = function(event) {
db = event.target.result;
db.createObjectStore("foo", { autoIncrement: true });
}
request.onsuccess = function ()
{ setTimeout(testFinishedCallback, 0, "resetDone"); };
request.onblocked = errorHandler;
}
}
function testSteps()
{
window.addEventListener("indexedDB-addMore", onAddMore, true);
window.addEventListener("indexedDB-reset", onReset, true);
window.addEventListener("indexedDB-done", onDone, true);
let request = mozIndexedDB.open(name, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
db = event.target.result;
db.onversionchange = function () { db.close(); };
db.createObjectStore("foo", { autoIncrement: true });
request.onsuccess = grabEventAndContinueHandler;
yield;
setTimeout(testFinishedCallback, 0, "ready");
yield;
}
</script>
<script type="text/javascript;version=1.7" src="browserHelpers.js"></script>
</head>
<body onload="runTest();" onunload="finishTestNow();"></body>
</html>

View File

@ -0,0 +1,100 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Make sure this is a unique origin or the tests will randomly fail!
const testPageURL = "http://bug702292.example.com/browser/" +
"dom/indexedDB/test/browser_quotaPromptDelete.html";
const notificationID = "indexedDB-quota-prompt";
function test()
{
waitForExplicitFinish();
requestLongerTimeout(10);
setPermission(testPageURL, "indexedDB");
removePermission(testPageURL, "indexedDB-unlimited");
Services.prefs.setIntPref("dom.indexedDB.warningQuota", 2);
executeSoon(test1);
}
let addMoreTest1Count = 0;
let haveReset = false;
let secondTimeCount = 0;
function test1()
{
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
let seenPopupCount;
setFinishedCallback(function(result) {
is(result, "ready", "Got 'ready' result");
setFinishedCallback(function(result) {
if (result == "abort") {
setFinishedCallback(function(result) {
is(result, "resetDone", "Got 'resetDone' result");
function secondTimeThroughCallback(result) {
is(result, "complete", "Got 'complete' result");
// If we hit the quota on the Nth iteration last time, we should
// be able to go N-1 iterations without hitting it after
// obliterating the db.
if (++secondTimeCount < addMoreTest1Count - 1) {
secondTimeThroughAddMore();
} else {
setFinishedCallback(function(result) {
is(result, "finished", "Got 'finished' result");
is(getPermission(testPageURL, "indexedDB-unlimited"),
Components.interfaces.nsIPermissionManager.DENY_ACTION,
"Correct permission set");
gBrowser.removeCurrentTab();
unregisterAllPopupEventHandlers();
executeSoon(finish);
});
executeSoon(function() { dispatchEvent("indexedDB-done"); });
}
}
function secondTimeThroughAddMore() {
setFinishedCallback(secondTimeThroughCallback);
executeSoon(function() { dispatchEvent("indexedDB-addMore"); });
}
haveReset = true;
secondTimeThroughAddMore();
});
executeSoon(function() { dispatchEvent("indexedDB-reset"); });
}
else {
++addMoreTest1Count;
executeSoon(function() { dispatchEvent("indexedDB-addMore"); });
}
});
++addMoreTest1Count;
executeSoon(function() { dispatchEvent("indexedDB-addMore"); });
});
registerPopupEventHandler("popupshowing", function () {
ok(true, "prompt showing");
seenPopupCount = addMoreTest1Count - 1;
});
registerPopupEventHandler("popupshown", function () {
ok(true, "prompt shown");
ok(!haveReset, "Shouldn't get here twice!");
triggerSecondaryCommand(this, 0);
});
registerPopupEventHandler("popuphidden", function () {
ok(true, "prompt hidden");
});
}, true);
info("loading test page: " + testPageURL);
content.location = testPageURL;
}

View File

@ -5,6 +5,11 @@
var testGenerator = testSteps();
function executeSoon(aFun)
{
SimpleTest.executeSoon(aFun);
}
function runTest()
{
allowIndexedDB();

View File

@ -9,165 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const name = window.location.pathname;
let openRequest = mozIndexedDB.open(name, 1);
openRequest.onerror = errorHandler;
openRequest.onupgradeneeded = grabEventAndContinueHandler;
openRequest.onsuccess = unexpectedSuccessHandler;
let event = yield;
let db = event.target.result;
let trans = event.target.transaction;
for each (let autoincrement in [true, false]) {
for each (let keypath in [false, true, "missing", "invalid"]) {
for each (let method in ["put", "add"]) {
for each (let explicit in [true, false, undefined, "invalid"]) {
for each (let existing in [true, false]) {
let speccedNoKey = (keypath == false || keypath == "missing") &&
!explicit;
// We can't do 'existing' checks if we use autogenerated key
if (speccedNoKey && autoincrement && existing) {
continue;
}
// Create store
if (db.objectStoreNames.contains("mystore"))
db.deleteObjectStore("mystore");
let store = db.createObjectStore("mystore",
{ autoIncrement: autoincrement,
keyPath: (keypath ? "id" : null) });
test = " for test " + JSON.stringify({ autoincrement: autoincrement,
keypath: keypath,
method: method,
explicit: explicit === undefined ? "undefined" : explicit,
existing: existing });
// Insert "existing" data if needed
if (existing) {
if (keypath)
store.add({ existing: "data", id: 5 }).onsuccess = grabEventAndContinueHandler;
else
store.add({ existing: "data" }, 5).onsuccess = grabEventAndContinueHandler;
let e = yield;
is(e.type, "success", "success inserting existing" + test);
is(e.target.result, 5, "inserted correct key" + test);
}
// Set up value to be inserted
let value = { theObj: true };
if (keypath === true) {
value.id = 5;
}
else if (keypath === "invalid") {
value.id = /x/;
}
// Which arguments are passed to function
args = [value];
if (explicit === true) {
args.push(5);
}
else if (explicit === undefined) {
args.push(undefined);
}
else if (explicit === "invalid") {
args.push(/x/);
}
let expected = expectedResult(method, keypath, explicit, autoincrement, existing);
let valueJSON = JSON.stringify(value);
ok(true, "making call" + test);
// Make function call for throwing functions
if (expected === "throw") {
try {
store[method].apply(store, args);
ok(false, "should have thrown" + test);
}
catch (ex) {
ok(true, "did throw" + test);
ok(ex instanceof IDBDatabaseException, "Got a IDBDatabaseException" + test);
is(ex.code, IDBDatabaseException.DATA_ERR, "expect a DATA_ERR" + test);
is(JSON.stringify(value), valueJSON, "call didn't modify value" + test);
}
continue;
}
// Make non-throwing function call
let req = store[method].apply(store, args);
is(JSON.stringify(value), valueJSON, "call didn't modify value" + test);
req.onsuccess = req.onerror = grabEventAndContinueHandler;
let e = yield;
// Figure out what key we used
let key = 5;
if (autoincrement && speccedNoKey) {
key = 1;
}
// Adjust value if expected
if (autoincrement && keypath && speccedNoKey) {
value.id = key;
}
// Check result
if (expected === "error") {
is(e.type, "error", "write should fail" + test);
e.preventDefault();
e.stopPropagation();
continue;
}
is(e.type, "success", "write should succeed" + test);
is(e.target.result, key, "write should return correct key" + test);
store.get(key).onsuccess = grabEventAndContinueHandler;
e = yield;
is(e.type, "success", "read back should succeed" + test);
is(JSON.stringify(e.target.result),
JSON.stringify(value),
"read back should return correct value" + test);
}
}
}
}
}
function expectedResult(method, keypath, explicit, autoincrement, existing) {
if (keypath && explicit)
return "throw";
if (!keypath && !explicit && !autoincrement)
return "throw";
if (keypath == "invalid")
return "throw";
if (keypath == "missing" && !autoincrement)
return "throw";
if (explicit == "invalid")
return "throw";
if (method == "add" && existing)
return "error";
return "success";
}
openRequest.onsuccess = grabEventAndContinueHandler;
yield;
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_add_put.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,40 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const name = window.location.pathname;
const description = "My Test Database";
let request = mozIndexedDB.open(name, 1, description);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db = request.result;
ok(event.target === request, "Good event target");
let objectStore = db.createObjectStore("foo", { keyPath: null });
let key = 10;
request = objectStore.add({}, key);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(request.result, key, "Correct key");
request = objectStore.add({}, key);
request.onerror = new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
request.onsuccess = unexpectedSuccessHandler;
yield;
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_add_twice_failure.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,193 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const dataCount = 30;
let request = mozIndexedDB.open(window.location.pathname, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db = event.target.result;
db.onerror = errorHandler;
event.target.onsuccess = continueToNextStep;
let objectStore = db.createObjectStore("", { keyPath: "key" });
objectStore.createIndex("", "index");
for (let i = 0; i < dataCount; i++) {
objectStore.add({ key: i, index: i });
}
yield;
function getObjectStore() {
return db.transaction("").objectStore("");
}
function getIndex() {
return db.transaction("").objectStore("").index("");
}
let count = 0;
getObjectStore().openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
count++;
cursor.continue();
}
else {
continueToNextStep();
}
};
yield;
is(count, dataCount, "Saw all data");
count = 0;
getObjectStore().openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.primaryKey, count, "Got correct object");
if (count) {
count++;
cursor.continue();
}
else {
count = 10;
cursor.advance(10);
}
}
else {
continueToNextStep();
}
};
yield;
is(count, dataCount, "Saw all data");
count = 0;
getIndex().openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.primaryKey, count, "Got correct object");
if (count) {
count++;
cursor.continue();
}
else {
count = 10;
cursor.advance(10);
}
}
else {
continueToNextStep();
}
};
yield;
is(count, dataCount, "Saw all data");
count = 0;
getIndex().openKeyCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.primaryKey, count, "Got correct object");
if (count) {
count++;
cursor.continue();
}
else {
count = 10;
cursor.advance(10);
}
}
else {
continueToNextStep();
}
};
yield;
is(count, dataCount, "Saw all data");
count = 0;
getObjectStore().openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.primaryKey, count, "Got correct object");
if (count == 0) {
cursor.advance(dataCount + 1);
}
else {
ok(false, "Should never get here!");
cursor.continue();
}
}
else {
continueToNextStep();
}
};
yield;
is(count, 0, "Saw all data");
count = dataCount - 1;
getObjectStore().openCursor(null, IDBCursor.PREV).onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.primaryKey, count, "Got correct object");
count--;
if (count == dataCount - 2) {
cursor.advance(10);
count -= 9;
}
else {
cursor.continue();
}
}
else {
continueToNextStep();
}
};
yield;
is(count, -1, "Saw all data");
count = dataCount - 1;
getObjectStore().openCursor(null, IDBCursor.PREV).onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.primaryKey, count, "Got correct object");
if (count == dataCount - 1) {
cursor.advance(dataCount + 1);
}
else {
ok(false, "Should never get here!");
cursor.continue();
}
}
else {
continueToNextStep();
}
};
yield;
is(count, dataCount - 1, "Saw all data");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_advance.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,57 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
let request = mozIndexedDB.open(window.location.pathname, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db = request.result;
db.onerror = errorHandler;
let objectStore = db.createObjectStore("foo", { keyPath: "id",
autoIncrement: true });
objectStore.createIndex("first","first");
objectStore.createIndex("second","second");
objectStore.createIndex("third","third");
let data = { first: "foo", second: "foo", third: "foo" };
objectStore.add(data).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 1, "Added entry");
request.onsuccess = grabEventAndContinueHandler;
event = yield;
let objectStore = db.transaction("foo").objectStore("foo");
let first = objectStore.index("first");
let second = objectStore.index("second");
let third = objectStore.index("third");
first.get("foo").onsuccess = grabEventAndContinueHandler;
event = yield;
is (event.target.result.id, 1, "Entry in first");
second.get("foo").onsuccess = grabEventAndContinueHandler;
event = yield;
is (event.target.result.id, 1, "Entry in second");
third.get("foo").onsuccess = grabEventAndContinueHandler;
event = yield;
is (event.target.result.id, 1, "Entry in third");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_autoIncrement_indexes.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,97 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
const name = window.location.pathname;
const description = "My Test Database";
const entryCount = 1000;
let request = mozIndexedDB.open(name, 1, description);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db = request.result;
event.target.onsuccess = continueToNextStep;
let objectStore = db.createObjectStore("foo", { autoIncrement: true });
let firstKey;
for (let i = 0; i < entryCount; i++) {
request = objectStore.add({});
request.onerror = errorHandler;
if (!i) {
request.onsuccess = function(event) {
firstKey = event.target.result;
};
}
}
yield;
isnot(firstKey, undefined, "got first key");
let seenEntryCount = 0;
request = db.transaction("foo").objectStore("foo").openCursor();
request.onerror = errorHandler;
request.onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
seenEntryCount++;
cursor.continue();
}
else {
continueToNextStep();
}
}
yield;
is(seenEntryCount, entryCount, "Correct entry count");
try {
db.transaction("foo").objectStore("foo").clear();
ok(false, "clear should throw on READ_ONLY transactions");
}
catch (e) {
ok(true, "clear should throw on READ_ONLY transactions");
}
request = db.transaction("foo", READ_WRITE).objectStore("foo").clear();
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
ok(event.target.result === undefined, "Correct event.target.result");
ok(request.result === undefined, "Correct request.result");
ok(request === event.target, "Correct event.target");
request = db.transaction("foo").objectStore("foo").openCursor();
request.onerror = errorHandler;
request.onsuccess = function(event) {
let cursor = request.result;
if (cursor) {
ok(false, "Shouldn't have any entries");
}
continueToNextStep();
}
yield;
request = db.transaction("foo", READ_WRITE).objectStore("foo").add({});
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
isnot(event.target.result, firstKey, "Got a different key");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_clear.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -1,4 +1,4 @@
<!--
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
@ -9,355 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const name = window.location.pathname;
const objectStoreName = "People";
const objectStoreData = [
{ key: "237-23-7732", value: { name: "Bob", height: 60, weight: 120 } },
{ key: "237-23-7733", value: { name: "Ann", height: 52, weight: 110 } },
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } },
{ key: "237-23-7735", value: { name: "Sue", height: 58, weight: 130 } },
{ key: "237-23-7736", value: { name: "Joe", height: 65, weight: 150 } },
{ key: "237-23-7737", value: { name: "Pat", height: 65 } },
{ key: "237-23-7738", value: { name: "Mel", height: 66, weight: {} } },
{ key: "237-23-7739", value: { name: "Tom", height: 62, weight: 130 } }
];
const indexData = {
name: "weight",
keyPath: "weight",
options: { unique: false }
};
const weightSort = [1, 0, 3, 7, 4, 2];
let request = mozIndexedDB.open(name, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
is(event.type, "upgradeneeded", "Got correct event type");
let db = event.target.result;
db.onerror = errorHandler;
let objectStore = db.createObjectStore(objectStoreName, { });
objectStore.createIndex(indexData.name, indexData.keyPath,
indexData.options);
for each (let data in objectStoreData) {
objectStore.add(data.value, data.key);
}
event = yield;
is(event.type, "success", "Got correct event type");
objectStore = db.transaction(db.objectStoreNames)
.objectStore(objectStoreName);
objectStore.count().onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreData.length,
"Correct number of object store entries for all keys");
objectStore.count(null).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreData.length,
"Correct number of object store entries for null key");
objectStore.count(objectStoreData[2].key).onsuccess =
grabEventAndContinueHandler;
event = yield;
is(event.target.result, 1,
"Correct number of object store entries for single existing key");
objectStore.count("foo").onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 0,
"Correct number of object store entries for single non-existing key");
let keyRange = IDBKeyRange.only(objectStoreData[2].key);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 1,
"Correct number of object store entries for existing only keyRange");
keyRange = IDBKeyRange.only("foo");
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 0,
"Correct number of object store entries for non-existing only keyRange");
keyRange = IDBKeyRange.lowerBound(objectStoreData[2].key);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreData.length - 2,
"Correct number of object store entries for lowerBound keyRange");
keyRange = IDBKeyRange.lowerBound(objectStoreData[2].key, true);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreData.length - 3,
"Correct number of object store entries for lowerBound keyRange");
keyRange = IDBKeyRange.lowerBound("foo");
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 0,
"Correct number of object store entries for lowerBound keyRange");
keyRange = IDBKeyRange.upperBound(objectStoreData[2].key, false);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 3,
"Correct number of object store entries for upperBound keyRange");
keyRange = IDBKeyRange.upperBound(objectStoreData[2].key, true);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 2,
"Correct number of object store entries for upperBound keyRange");
keyRange = IDBKeyRange.upperBound("foo", true);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreData.length,
"Correct number of object store entries for upperBound keyRange");
keyRange = IDBKeyRange.bound(objectStoreData[0].key,
objectStoreData[objectStoreData.length - 1].key);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreData.length,
"Correct number of object store entries for bound keyRange");
keyRange = IDBKeyRange.bound(objectStoreData[0].key,
objectStoreData[objectStoreData.length - 1].key,
true);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreData.length - 1,
"Correct number of object store entries for bound keyRange");
keyRange = IDBKeyRange.bound(objectStoreData[0].key,
objectStoreData[objectStoreData.length - 1].key,
true, true);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreData.length - 2,
"Correct number of object store entries for bound keyRange");
keyRange = IDBKeyRange.bound("foo", "foopy", true, true);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 0,
"Correct number of object store entries for bound keyRange");
keyRange = IDBKeyRange.bound(objectStoreData[0].key, "foo", true, true);
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, objectStoreData.length - 1,
"Correct number of object store entries for bound keyRange");
let index = objectStore.index(indexData.name);
index.count().onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length,
"Correct number of index entries for no key");
index.count(objectStoreData[7].value.weight).onsuccess =
grabEventAndContinueHandler;
event = yield;
is(event.target.result, 2,
"Correct number of index entries for duplicate key");
index.count(objectStoreData[0].value.weight).onsuccess =
grabEventAndContinueHandler;
event = yield;
is(event.target.result, 1,
"Correct number of index entries for single key");
keyRange = IDBKeyRange.only(objectStoreData[0].value.weight);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 1,
"Correct number of index entries for only existing keyRange");
keyRange = IDBKeyRange.only("foo");
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 0,
"Correct number of index entries for only non-existing keyRange");
keyRange = IDBKeyRange.only(objectStoreData[7].value.weight);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 2,
"Correct number of index entries for only duplicate keyRange");
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[0]].value.weight);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length,
"Correct number of index entries for lowerBound keyRange");
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[1]].value.weight);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length - 1,
"Correct number of index entries for lowerBound keyRange");
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[0]].value.weight - 1);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length,
"Correct number of index entries for lowerBound keyRange");
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[0]].value.weight,
true);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length - 1,
"Correct number of index entries for lowerBound keyRange");
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 1,
"Correct number of index entries for lowerBound keyRange");
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight,
true);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 0,
"Correct number of index entries for lowerBound keyRange");
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight + 1,
true);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 0,
"Correct number of index entries for lowerBound keyRange");
keyRange = IDBKeyRange.upperBound(objectStoreData[weightSort[0]].value.weight);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 1,
"Correct number of index entries for upperBound keyRange");
keyRange = IDBKeyRange.upperBound(objectStoreData[weightSort[0]].value.weight,
true);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 0,
"Correct number of index entries for upperBound keyRange");
keyRange = IDBKeyRange.upperBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length,
"Correct number of index entries for upperBound keyRange");
keyRange = IDBKeyRange.upperBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight,
true);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length - 1,
"Correct number of index entries for upperBound keyRange");
keyRange = IDBKeyRange.upperBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight,
true);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length - 1,
"Correct number of index entries for upperBound keyRange");
keyRange = IDBKeyRange.upperBound("foo");
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length,
"Correct number of index entries for upperBound keyRange");
keyRange = IDBKeyRange.bound("foo", "foopy");
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, 0,
"Correct number of index entries for bound keyRange");
keyRange = IDBKeyRange.bound(objectStoreData[weightSort[0]].value.weight,
objectStoreData[weightSort[weightSort.length - 1]].value.weight);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length,
"Correct number of index entries for bound keyRange");
keyRange = IDBKeyRange.bound(objectStoreData[weightSort[0]].value.weight,
objectStoreData[weightSort[weightSort.length - 1]].value.weight,
true);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length - 1,
"Correct number of index entries for bound keyRange");
keyRange = IDBKeyRange.bound(objectStoreData[weightSort[0]].value.weight,
objectStoreData[weightSort[weightSort.length - 1]].value.weight,
true, true);
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, weightSort.length - 2,
"Correct number of index entries for bound keyRange");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_count.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,126 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore;
const nsIIDBTransaction = Components.interfaces.nsIIDBTransaction;
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreInfo = [
{ name: "a", options: { keyPath: "id", autoIncrement: true } },
{ name: "b", options: { keyPath: "id", autoIncrement: false } },
];
const indexInfo = [
{ name: "1", keyPath: "unique_value", options: { unique: true } },
{ name: "2", keyPath: "value", options: { unique: false } },
{ name: "3", keyPath: "value", options: { unique: false } },
{ name: "", keyPath: "value", options: { unique: false } },
{ name: null, keyPath: "value", options: { unique: false } },
{ name: undefined, keyPath: "value", options: { unique: false } },
];
let request = mozIndexedDB.open(name, 1, description);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db = event.target.result;
for (let i = 0; i < objectStoreInfo.length; i++) {
let info = objectStoreInfo[i];
let objectStore = info.hasOwnProperty("options") ?
db.createObjectStore(info.name, info.options) :
db.createObjectStore(info.name);
try {
request = objectStore.createIndex("Hola");
ok(false, "createIndex with no keyPath should throw");
}
catch(e) {
ok(true, "createIndex with no keyPath should throw");
}
try {
request = objectStore.createIndex("Hola", ["foo"], { multiEntry: true });
ok(false, "createIndex with array keyPath and multiEntry should throw");
}
catch(e) {
ok(true, "createIndex with array keyPath and multiEntry should throw");
}
try {
request = objectStore.createIndex("Hola", []);
ok(false, "createIndex with empty array keyPath should throw");
}
catch(e) {
ok(true, "createIndex with empty array keyPath should throw");
}
try {
request = objectStore.createIndex("foo", "bar", 10);
ok(false, "createIndex with bad options should throw");
}
catch(e) {
ok(true, "createIndex with bad options threw");
}
ok(objectStore.createIndex("foo", "bar", { foo: "" }),
"createIndex with unknown options should not throw");
objectStore.deleteIndex("foo");
// Test index creation, and that it ends up in indexNames.
let objectStoreName = info.name;
for (let j = 0; j < indexInfo.length; j++) {
let info = indexInfo[j];
let count = objectStore.indexNames.length;
let index = info.hasOwnProperty("options") ?
objectStore.createIndex(info.name, info.keyPath,
info.options) :
objectStore.createIndex(info.name, info.keyPath);
let name = info.name;
if (name === null) {
name = "null";
}
else if (name === undefined) {
name = "undefined";
}
is(index.name, name, "correct name");
is(index.keyPath, info.keyPath, "correct keyPath");
is(index.unique, info.options.unique, "correct uniqueness");
is(objectStore.indexNames.length, count + 1,
"indexNames grew in size");
let found = false;
for (let k = 0; k < objectStore.indexNames.length; k++) {
if (objectStore.indexNames.item(k) == name) {
found = true;
break;
}
}
ok(found, "Name is on objectStore.indexNames");
ok(event.target.transaction, "event has a transaction");
ok(event.target.transaction.db === db,
"transaction has the right db");
is(event.target.transaction.readyState, nsIIDBTransaction.LOADING,
"transaction has the correct readyState");
is(event.target.transaction.mode, nsIIDBTransaction.VERSION_CHANGE,
"transaction has the correct mode");
is(event.target.transaction.objectStoreNames.length, i + 1,
"transaction only has one object store");
is(event.target.transaction.objectStoreNames.item(0), objectStoreName,
"transaction has the correct object store");
}
}
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_create_index.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,67 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const data = { id: new Date().getTime(),
num: parseInt(Math.random() * 1000) };
let request = mozIndexedDB.open(window.location.pathname, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db = event.target.result;
db.onerror = errorHandler;
event.target.onsuccess = continueToNextStep;
// Make object store, add data.
let objectStore = db.createObjectStore("foo", { keyPath: "id" });
objectStore.add(data);
yield;
db.close();
let request = mozIndexedDB.open(window.location.pathname, 2);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db2 = event.target.result;
db2.onerror = errorHandler;
event.target.onsuccess = continueToNextStep;
// Create index.
event.target.transaction.objectStore("foo").createIndex("foo", "num");
yield;
// Make sure our object made it into the index.
let seenCount = 0;
db2.transaction("foo").objectStore("foo").index("foo")
.openKeyCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.key, data.num, "Good key");
is(cursor.primaryKey, data.id, "Good value");
seenCount++;
cursor.continue();
}
else {
continueToNextStep();
}
};
yield;
is(seenCount, 1, "Saw our entry");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_create_index_with_integer_keys.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,116 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const objectStoreData = [
// This one will be removed.
{ ss: "237-23-7732", name: "Bob" },
// These will always be included.
{ ss: "237-23-7733", name: "Ann" },
{ ss: "237-23-7734", name: "Ron" },
{ ss: "237-23-7735", name: "Sue" },
{ ss: "237-23-7736", name: "Joe" },
// This one will be added.
{ ss: "237-23-7737", name: "Pat" }
];
// Post-add and post-remove data ordered by name.
const objectStoreDataNameSort = [ 1, 4, 5, 2, 3 ];
let request = mozIndexedDB.open(window.location.pathname, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db = event.target.result;
event.target.onsuccess = continueToNextStep;
let objectStore = db.createObjectStore("foo", { keyPath: "ss" });
objectStore.createIndex("name", "name", { unique: true });
for (let i = 0; i < objectStoreData.length - 1; i++) {
objectStore.add(objectStoreData[i]);
}
yield;
let count = 0;
let sawAdded = false;
let sawRemoved = false;
db.transaction("foo").objectStore("foo").openCursor().onsuccess =
function(event) {
event.target.transaction.oncomplete = continueToNextStep;
let cursor = event.target.result;
if (cursor) {
if (cursor.value.name == objectStoreData[0].name) {
sawRemoved = true;
}
if (cursor.value.name ==
objectStoreData[objectStoreData.length - 1].name) {
sawAdded = true;
}
cursor.continue();
count++;
}
};
yield;
is(count, objectStoreData.length - 1, "Good initial count");
is(sawAdded, false, "Didn't see item that is about to be added");
is(sawRemoved, true, "Saw item that is about to be removed");
count = 0;
sawAdded = false;
sawRemoved = false;
db.transaction("foo", IDBTransaction.READ_WRITE).objectStore("foo")
.index("name").openCursor().onsuccess = function(event) {
event.target.transaction.oncomplete = continueToNextStep;
let cursor = event.target.result;
if (cursor) {
if (cursor.value.name == objectStoreData[0].name) {
sawRemoved = true;
}
if (cursor.value.name ==
objectStoreData[objectStoreData.length - 1].name) {
sawAdded = true;
}
is(cursor.value.name,
objectStoreData[objectStoreDataNameSort[count++]].name,
"Correct name");
if (count == 1) {
let objectStore = event.target.transaction.objectStore("foo");
objectStore.delete(objectStoreData[0].ss)
.onsuccess = function(event) {
objectStore.add(objectStoreData[objectStoreData.length - 1])
.onsuccess =
function(event) {
cursor.continue();
};
};
}
else {
cursor.continue();
}
}
};
yield;
is(count, objectStoreData.length - 1, "Good final count");
is(sawAdded, true, "Saw item that was added");
is(sawRemoved, false, "Didn't see item that was removed");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_cursor_mutation.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,98 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore;
const nsIIDBTransaction = Components.interfaces.nsIIDBTransaction;
const name = window.location.pathname;
const description = "My Test Database";
const START_DATA = "hi";
const END_DATA = "bye";
const objectStoreInfo = [
{ name: "1", options: { keyPath: null }, key: 1,
entry: { data: START_DATA } },
{ name: "2", options: { keyPath: "foo" },
entry: { foo: 1, data: START_DATA } },
{ name: "3", options: { keyPath: null, autoIncrement: true },
entry: { data: START_DATA } },
{ name: "4", options: { keyPath: "foo", autoIncrement: true },
entry: { data: START_DATA } },
];
for (let i = 0; i < objectStoreInfo.length; i++) {
// Create our object stores.
let info = objectStoreInfo[i];
ok(true, "1");
request = mozIndexedDB.open(name, i + 1, description);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
event = yield;
let db = event.target.result;
ok(true, "2");
let objectStore = info.hasOwnProperty("options") ?
db.createObjectStore(info.name, info.options) :
db.createObjectStore(info.name);
// Create the indexes on 'data' on the object store.
let index = objectStore.createIndex("data_index", "data",
{ unique: false });
let uniqueIndex = objectStore.createIndex("unique_data_index", "data",
{ unique: true });
// Populate the object store with one entry of data.
request = info.hasOwnProperty("key") ?
objectStore.add(info.entry, info.key) :
objectStore.add(info.entry);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
ok(true, "3");
// Use a cursor to update 'data' to END_DATA.
request = objectStore.openCursor();
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
ok(true, "4");
let cursor = request.result;
let obj = cursor.value;
obj.data = END_DATA;
request = cursor.update(obj);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
ok(true, "5");
// Check both indexes to make sure that they were updated.
request = index.get(END_DATA);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
ok(true, "6");
SimpleTest.ok(obj.data, event.target.result.data,
"Non-unique index was properly updated.");
request = uniqueIndex.get(END_DATA);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
ok(true, "7");
SimpleTest.ok(obj.data, event.target.result.data,
"Unique index was properly updated.");
db.close();
}
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_cursor_update_updates_indexes.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,362 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const name = window.location.pathname;
const description = "My Test Database";
const keys = [1, -1, 0, 10, 2000, "q", "z", "two", "b", "a"];
const sortedKeys = [-1, 0, 1, 10, 2000, "a", "b", "q", "two", "z"];
is(keys.length, sortedKeys.length, "Good key setup");
let request = mozIndexedDB.open(name, 1, description);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db = event.target.result;
let objectStore = db.createObjectStore("autoIncrement",
{ autoIncrement: true });
request = objectStore.openCursor();
request.onerror = errorHandler;
request.onsuccess = function (event) {
ok(!event.target.result, "No results");
testGenerator.next();
}
yield;
objectStore = db.createObjectStore("autoIncrementKeyPath",
{ keyPath: "foo",
autoIncrement: true });
request = objectStore.openCursor();
request.onerror = errorHandler;
request.onsuccess = function (event) {
ok(!event.target.result, "No results");
testGenerator.next();
}
yield;
objectStore = db.createObjectStore("keyPath", { keyPath: "foo" });
request = objectStore.openCursor();
request.onerror = errorHandler;
request.onsuccess = function (event) {
ok(!event.target.result, "No results");
testGenerator.next();
}
yield;
objectStore = db.createObjectStore("foo");
request = objectStore.openCursor();
request.onerror = errorHandler;
request.onsuccess = function (event) {
ok(!event.target.result, "No results");
testGenerator.next();
}
yield;
let keyIndex = 0;
for (let i in keys) {
request = objectStore.add("foo", keys[i]);
request.onerror = errorHandler;
request.onsuccess = function(event) {
if (++keyIndex == keys.length) {
testGenerator.next();
}
};
}
yield;
keyIndex = 0;
request = objectStore.openCursor();
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
cursor.continue();
try {
cursor.continue();
ok(false, "continue twice should throw");
}
catch (e) {
ok(e instanceof IDBDatabaseException, "got a database exception");
is(e.code, IDBDatabaseException.NOT_ALLOWED_ERR, "correct code");
}
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
keyIndex++;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, keys.length, "Saw all added items");
keyIndex = 4;
let range = IDBKeyRange.bound(2000, "q");
request = objectStore.openCursor(range);
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
cursor.continue();
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
keyIndex++;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, 8, "Saw all the expected keys");
keyIndex = 0;
request = objectStore.openCursor();
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
if (keyIndex) {
cursor.continue();
}
else {
cursor.continue("b");
}
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
keyIndex += keyIndex ? 1: 6;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, keys.length, "Saw all the expected keys");
keyIndex = 0;
request = objectStore.openCursor();
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
if (keyIndex) {
cursor.continue();
}
else {
cursor.continue(10);
}
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
keyIndex += keyIndex ? 1: 3;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, keys.length, "Saw all the expected keys");
keyIndex = 0;
request = objectStore.openCursor();
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
if (keyIndex) {
cursor.continue();
}
else {
cursor.continue("c");
}
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
keyIndex += keyIndex ? 1 : 7;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, keys.length, "Saw all the expected keys");
keyIndex = 0;
request = objectStore.openCursor();
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
if (keyIndex == 4) {
request = cursor.update("bar");
request.onerror = errorHandler;
request.onsuccess = function(event) {
keyIndex++;
cursor.continue();
};
}
else {
keyIndex++;
cursor.continue();
}
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, keys.length, "Saw all the expected keys");
request = objectStore.get(sortedKeys[4]);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, "bar", "Update succeeded");
request = objectStore.put("foo", sortedKeys[4]);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
keyIndex = 0;
let gotRemoveEvent = false;
let retval = false;
request = objectStore.openCursor(null, IDBCursor.NEXT);
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
if (keyIndex == 4) {
request = cursor.delete();
request.onerror = errorHandler;
request.onsuccess = function(event) {
ok(event.target.result === undefined, "Should be undefined");
is(keyIndex, 5, "Got result of remove before next continue");
gotRemoveEvent = true;
};
}
keyIndex++;
cursor.continue();
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, keys.length, "Saw all the expected keys");
is(gotRemoveEvent, true, "Saw the remove event");
request = objectStore.get(sortedKeys[4]);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result, undefined, "Entry was deleted");
request = objectStore.add("foo", sortedKeys[4]);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
keyIndex = sortedKeys.length - 1;
request = objectStore.openCursor(null, IDBCursor.PREV);
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
cursor.continue();
is(cursor.key, sortedKeys[keyIndex], "Correct key");
is(cursor.primaryKey, sortedKeys[keyIndex], "Correct primary key");
is(cursor.value, "foo", "Correct value");
keyIndex--;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, -1, "Saw all added items");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_cursors.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -101,6 +101,13 @@
event = yield;
ok(true, "deleteDatabase on a non-existent database succeeded");
let request = mozIndexedDB.open("thisDatabaseHadBetterNotExist");
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
ok(true, "after deleting a non-existent database, open should work");
finishTest();
yield;
}

View File

@ -9,34 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Objects";
var request = mozIndexedDB.open(name, 1, description);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
var event = yield;
is(event.target.source, null, "correct event.target.source");
var db = event.target.result;
var objectStore = db.createObjectStore(objectStoreName,
{ autoIncrement: true });
request = objectStore.add({});
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
ok(event.target.source === objectStore, "correct event.source");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_event_source.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,161 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const name = window.location.pathname;
const description = "My Test Database";
const values = [ "a", "1", 1, "foo", 300, true, false, 4.5, null ];
let request = mozIndexedDB.open(name, 1, description);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db = event.target.result;
let objectStore = db.createObjectStore("foo", { autoIncrement: true });
request.onsuccess = grabEventAndContinueHandler;
request = objectStore.getAll();
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result instanceof Array, true, "Got an array object");
is(event.target.result.length, 0, "No elements");
let addedCount = 0;
for (let i in values) {
request = objectStore.add(values[i]);
request.onerror = errorHandler;
request.onsuccess = function(event) {
if (++addedCount == values.length) {
SimpleTest.executeSoon(function() { testGenerator.next(); });
}
}
}
yield;
yield;
request = db.transaction("foo").objectStore("foo").getAll();
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result instanceof Array, true, "Got an array object");
is(event.target.result.length, values.length, "Same length");
for (let i in event.target.result) {
is(event.target.result[i], values[i], "Same value");
}
request = db.transaction("foo").objectStore("foo").getAll(null, 5);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result instanceof Array, true, "Got an array object");
is(event.target.result.length, 5, "Correct length");
for (let i in event.target.result) {
is(event.target.result[i], values[i], "Same value");
}
let keyRange = IDBKeyRange.bound(1, 9);
request = db.transaction("foo").objectStore("foo").getAll(keyRange);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result instanceof Array, true, "Got an array object");
is(event.target.result.length, values.length, "Correct length");
for (let i in event.target.result) {
is(event.target.result[i], values[i], "Same value");
}
keyRange = IDBKeyRange.bound(4, 7);
request = db.transaction("foo").objectStore("foo").getAll(keyRange);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result instanceof Array, true, "Got an array object");
is(event.target.result.length, 4, "Correct length");
for (let i in event.target.result) {
is(event.target.result[i], values[parseInt(i) + 3], "Same value");
}
// Get should take a key range also but it doesn't return an array.
request = db.transaction("foo").objectStore("foo").get(keyRange);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result instanceof Array, false, "Not an array object");
is(event.target.result, values[3], "Correct value");
request = db.transaction("foo").objectStore("foo").getAll(keyRange, 2);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result instanceof Array, true, "Got an array object");
is(event.target.result.length, 2, "Correct length");
for (let i in event.target.result) {
is(event.target.result[i], values[parseInt(i) + 3], "Same value");
}
keyRange = IDBKeyRange.bound(4, 7);
request = db.transaction("foo").objectStore("foo").getAll(keyRange, 50);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result instanceof Array, true, "Got an array object");
is(event.target.result.length, 4, "Correct length");
for (let i in event.target.result) {
is(event.target.result[i], values[parseInt(i) + 3], "Same value");
}
keyRange = IDBKeyRange.bound(4, 7);
request = db.transaction("foo").objectStore("foo").getAll(keyRange, 0);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result instanceof Array, true, "Got an array object");
is(event.target.result.length, 0, "Correct length");
keyRange = IDBKeyRange.bound(4, 7, true, true);
request = db.transaction("foo").objectStore("foo").getAll(keyRange);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
is(event.target.result instanceof Array, true, "Got an array object");
is(event.target.result.length, 2, "Correct length");
for (let i in event.target.result) {
is(event.target.result[i], values[parseInt(i) + 4], "Same value");
}
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_getAll.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,59 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const name = window.location.pathname;
const description = "My Test Database";
const objectStore = { name: "Objects",
options: { keyPath: "id", autoIncrement: true } };
let request = mozIndexedDB.open(name, 1, description);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
let db1 = event.target.result;
is(db1.objectStoreNames.length, 0, "No objectStores in db1");
db1.createObjectStore(objectStore.name, objectStore.options);
continueToNextStep();
yield;
request = mozIndexedDB.open(name, 1, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield;
let db2 = event.target.result;
ok(db1 !== db2, "Databases are not the same object");
is(db1.objectStoreNames.length, 1, "1 objectStore in db1");
is(db1.objectStoreNames.item(0), objectStore.name, "Correct name");
is(db2.objectStoreNames.length, 1, "1 objectStore in db2");
is(db2.objectStoreNames.item(0), objectStore.name, "Correct name");
let objectStore1 = db1.transaction(objectStore.name)
.objectStore(objectStore.name);
is(objectStore1.name, objectStore.name, "Same name");
is(objectStore1.keyPath, objectStore.options.keyPath, "Same keyPath");
let objectStore2 = db2.transaction(objectStore.name)
.objectStore(objectStore.name);
ok(objectStore1 !== objectStore2, "Different objectStores");
is(objectStore1.name, objectStore2.name, "Same name");
is(objectStore1.keyPath, objectStore2.keyPath, "Same keyPath");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_global_data.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

View File

@ -9,84 +9,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const name = window.location.pathname;
const objectStoreData = [
{ key: "1", value: "foo" },
{ key: "2", value: "bar" },
{ key: "3", value: "baz" }
];
let request = mozIndexedDB.open(name, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield; // upgradeneeded
let db = event.target.result;
let objectStore = db.createObjectStore("data", { keyPath: null });
// First, add all our data to the object store.
let addedData = 0;
for (let i in objectStoreData) {
request = objectStore.add(objectStoreData[i].value,
objectStoreData[i].key);
request.onerror = errorHandler;
request.onsuccess = function(event) {
if (++addedData == objectStoreData.length) {
testGenerator.send(event);
}
}
}
event = yield; // testGenerator.send
// Now create the index.
objectStore.createIndex("set", "", { unique: true });
yield; // success
let trans = db.transaction("data", IDBTransaction.READ_WRITE);
objectStore = trans.objectStore("data");
index = objectStore.index("set");
let request = index.get("bar");
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
is(event.target.result, "bar", "Got correct result");
let request = objectStore.add("foopy", 4);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
yield;
let request = index.get("foopy");
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
is(event.target.result, "foopy", "Got correct result");
let request = objectStore.add("foopy", 5);
request.onerror = new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
request.onsuccess = unexpectedSuccessHandler;
trans.oncomplete = grabEventAndContinueHandler;
yield;
yield;
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="unit/test_index_empty_keyPath.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>

Some files were not shown because too many files have changed in this diff Show More