mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
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:
commit
94931765ea
@ -36,3 +36,6 @@ _OPT\.OBJ/
|
||||
|
||||
# Java HTML5 parser classes
|
||||
^parser/html/java/(html|java)parser/
|
||||
|
||||
# SVN directories
|
||||
\.svn/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -140,7 +140,7 @@
|
||||
<menuitem id="context-copyimage-contents"
|
||||
label="©ImageContentsCmd.label;"
|
||||
accesskey="©ImageContentsCmd.accesskey;"
|
||||
oncommand="goDoCommand('cmd_copyImageContents');"/>
|
||||
oncommand="goDoCommand('cmd_copyImage');"/>
|
||||
#endif
|
||||
<menuitem id="context-copyimage"
|
||||
label="©ImageCmd.label;"
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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")];
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -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">
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
@ -1361,6 +1361,11 @@ function HUD_SERVICE()
|
||||
|
||||
HUD_SERVICE.prototype =
|
||||
{
|
||||
/**
|
||||
* Last value entered
|
||||
*/
|
||||
lastInputValue: "",
|
||||
|
||||
/**
|
||||
* L10N shortcut function
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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}"
|
||||
|
@ -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
|
||||
|
269
browser/installer/windows/nsis/maintenanceservice_installer.nsi
Normal file
269
browser/installer/windows/nsis/maintenanceservice_installer.nsi
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
################################################################################
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
4
build/pymake/tests/sort.mk
Normal file
4
build/pymake/tests/sort.mk
Normal 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"
|
@ -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) \
|
||||
|
@ -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@
|
||||
|
@ -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
|
||||
|
44
configure.in
44
configure.in
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
@ -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;
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -81,6 +81,7 @@ shouldThrowWithNew(WebGLRenderbuffer, 'WebGLRenderbuffer');
|
||||
shouldThrowWithNew(WebGLShader, 'WebGLShader');
|
||||
shouldThrowWithNew(WebGLTexture, 'WebGLTexture');
|
||||
shouldThrowWithNew(WebGLUniformLocation, 'WebGLUniformLocation');
|
||||
shouldThrowWithNew(WebGLShaderPrecisionFormat, 'WebGLShaderPrecisionFormat');
|
||||
|
||||
successfullyParsed = true;
|
||||
</script>
|
||||
|
@ -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)");
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"); }
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -76,7 +76,6 @@ public:
|
||||
mPromptResult(0)
|
||||
{
|
||||
NS_ASSERTION(aHelper, "Null pointer!");
|
||||
NS_ASSERTION(aWindow, "Null pointer!");
|
||||
NS_ASSERTION(!aASCIIOrigin.IsEmpty(), "Empty origin!");
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -395,7 +395,6 @@ class AutoEnterWindow
|
||||
public:
|
||||
AutoEnterWindow(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
NS_ASSERTION(aWindow, "This should never be null!");
|
||||
IndexedDatabaseManager::SetCurrentWindow(aWindow);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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)
|
||||
|
||||
|
97
dom/indexedDB/test/browser_quotaPromptDelete.html
Normal file
97
dom/indexedDB/test/browser_quotaPromptDelete.html
Normal 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>
|
100
dom/indexedDB/test/browser_quotaPromptDelete.js
Normal file
100
dom/indexedDB/test/browser_quotaPromptDelete.js
Normal 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;
|
||||
}
|
@ -5,6 +5,11 @@
|
||||
|
||||
var testGenerator = testSteps();
|
||||
|
||||
function executeSoon(aFun)
|
||||
{
|
||||
SimpleTest.executeSoon(aFun);
|
||||
}
|
||||
|
||||
function runTest()
|
||||
{
|
||||
allowIndexedDB();
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user