Merge from mozilla-central.

This commit is contained in:
David Anderson 2012-02-24 13:26:30 -08:00
commit edbe86098f
321 changed files with 7356 additions and 9291 deletions

View File

@ -853,6 +853,11 @@ nsAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
// the DOM parent chain.
nsDocAccessible* contentDocAcc = GetAccService()->
GetDocAccessible(content->OwnerDoc());
// contentDocAcc in some circumstances can be NULL
// See https://bugzilla.mozilla.org/show_bug.cgi?id=729861
NS_ENSURE_TRUE(contentDocAcc, fallbackAnswer);
nsAccessible* accessible = contentDocAcc->GetAccessibleOrContainer(content);
if (!accessible)
return fallbackAnswer;

View File

@ -106,6 +106,7 @@ pref("mozilla.widget.force-24bpp", true);
pref("mozilla.widget.use-buffer-pixmap", true);
pref("mozilla.widget.disable-native-theme", true);
pref("layout.reflow.synthMouseMove", false);
pref("dom.send_after_paint_to_content", true);
/* download manager (don't show the window or alert) */
pref("browser.download.useDownloadDir", true);
@ -353,9 +354,6 @@ pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
// the database.
pref("urlclassifier.confirm-age", 2700);
// Maximum size of the sqlite3 cache during an update, in bytes
pref("urlclassifier.updatecachemax", 4194304);
// URL for checking the reason for a malware warning.
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
#endif
@ -392,6 +390,7 @@ pref("layers.acceleration.force-enabled", true);
// screen.enabled and screen.brightness properties.
pref("dom.screenEnabledProperty.enabled", true);
pref("dom.screenBrightnessProperty.enabled", true);
pref("dom.mozScreenWhitelist", "http://localhost:7777");
// handle links targeting new windows
// 1=current window/tab, 2=new window, 3=new tab in most recent window
@ -430,6 +429,10 @@ pref("layout.frame_rate.precise", true);
pref("b2g.remote-js.enabled", true);
pref("b2g.remote-js.port", 9999);
// Handle hardware buttons in the b2g chrome package
pref("b2g.keys.menu.enabled", true);
pref("b2g.keys.search.enabled", false);
// Screen timeout in minutes
pref("power.screen.timeout", 60);

View File

@ -37,6 +37,23 @@ XPCOMUtils.defineLazyServiceGetter(Services, 'fm', function(){
.getService(Ci.nsFocusManager);
});
#ifndef MOZ_WIDGET_GONK
// In order to use http:// scheme instead of file:// scheme
// (that is much more restricted) the following code kick-off
// a local http server listening on http://127.0.0.1:7777 and
// http://localhost:7777.
function startupHttpd(baseDir, port) {
const httpdURL = 'chrome://browser/content/httpd.js';
let httpd = {};
Services.scriptloader.loadSubScript(httpdURL, httpd);
let server = new httpd.nsHttpServer();
server.registerDirectory('/', new LocalFile(baseDir));
server.registerContentType('appcache', 'text/cache-manifest');
server.start(port);
}
#endif
// FIXME Bug 707625
// until we have a proper security model, add some rights to
// the pre-installed web applications
@ -105,7 +122,21 @@ var shell = {
let fileScheme = 'file://';
if (homeURL.substring(0, fileScheme.length) == fileScheme) {
#ifndef MOZ_WIDGET_GONK
homeURL = homeURL.replace(fileScheme, '');
let baseDir = homeURL.split('/');
baseDir.pop();
baseDir = baseDir.join('/');
const SERVER_PORT = 7777;
startupHttpd(baseDir, SERVER_PORT);
let baseHost = 'http://localhost';
homeURL = homeURL.replace(baseDir, baseHost + ':' + SERVER_PORT);
#else
homeURL = 'http://localhost:7777' + homeURL.replace(fileScheme, '');
#endif
}
addPermissions([homeURL]);
} catch (e) {
@ -213,10 +244,12 @@ var shell = {
case 'AppCommand':
switch (evt.command) {
case 'Menu':
this.sendEvent(content, 'menu');
if (Services.prefs.getBoolPref('b2g.keys.menu.enabled'))
this.sendEvent(content, 'menu');
break;
case 'Search':
this.toggleDebug();
if (Services.prefs.getBoolPref('b2g.keys.search.enabled'))
this.toggleDebug();
break;
case 'VolumeUp':
this.changeVolume(1);

View File

@ -20,11 +20,18 @@
#ifndef MOZ_TOUCH
<script type="application/javascript" src="chrome://browser/content/touch.js"/>
#endif
#ifndef MOZ_WIDGET_GONK
<script type="application/javascript" src="chrome://browser/content/httpd.js"/>
#endif
<commandset id="mainCommandSet">
<command id="cmd_close" oncommand="CommandUpdater.doCommand(this.id);"/>
</commandset>
<browser id="homescreen" type="content-primary" flex="1" style="overflow: hidden;"/>
<browser id="homescreen"
type="content-primary"
flex="1"
style="overflow: hidden;"
src="data:text/html;base64,PCFET0NUWVBFIGh0bWw+PGh0bWw+PGJvZHkgc3R5bGU9ImJhY2tncm91bmQ6YmxhY2s7Ij48L2JvZHk+PC9odG1sPgo="/>
</window>

View File

@ -84,6 +84,18 @@ XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
content.dispatchEvent(event);
}
function maybeShowIme(targetElement) {
// FIXME/bug 729623: work around apparent bug in the IME manager
// in gecko.
let readonly = targetElement.getAttribute('readonly');
if (readonly)
return false;
let type = targetElement.type;
fireEvent('showime', { type: type });
return true;
}
let constructor = {
handleEvent: function vkm_handleEvent(evt) {
switch (evt.type) {
@ -102,9 +114,7 @@ XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
if (evt.target != activeElement || isKeyboardOpened)
return;
let type = activeElement.type;
fireEvent('showime', { type: type });
isKeyboardOpened = true;
isKeyboardOpened = maybeShowIme(activeElement);
break;
}
},
@ -112,11 +122,10 @@ XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
let shouldOpen = parseInt(data);
if (shouldOpen && !isKeyboardOpened) {
activeElement = Services.fm.focusedElement;
if (!activeElement)
if (!activeElement || !maybeShowIme(activeElement)) {
activeElement = null;
return;
let type = activeElement.type;
fireEvent('showime', { type: type });
}
} else if (!shouldOpen && isKeyboardOpened) {
fireEvent('hideime');
}
@ -313,7 +322,7 @@ const KineticPanning = {
return this.target !== null;
},
_target: null,
target: null,
start: function kp_start(target) {
this.target = target;

View File

@ -5,12 +5,14 @@ chrome.jar:
% content browser %content/
* content/shell.xul (content/shell.xul)
content/shell.js (content/shell.js)
* content/shell.js (content/shell.js)
#ifndef MOZ_TOUCH
content/touch.js (content/touch.js)
#endif
content/commandUtil.js (content/commandUtil.js)
#ifndef MOZ_WIDGET_GONK
content/httpd.js (content/httpd.js)
#endif
content/webapi.js (content/webapi.js)
content/content.css (content/content.css)

View File

@ -759,12 +759,6 @@ pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
// the database.
pref("urlclassifier.confirm-age", 2700);
// Maximum size of the sqlite3 cache during an update, in bytes
pref("urlclassifier.updatecachemax", 41943040);
// Maximum size of the sqlite3 cache for lookups, in bytes
pref("urlclassifier.lookupcachemax", 1048576);
// URL for checking the reason for a malware warning.
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");

View File

@ -165,24 +165,25 @@ var StarUI = {
return;
}
var loadObserver = {
_self: this,
_itemId: aItemId,
_anchorElement: aAnchorElement,
_position: aPosition,
observe: function (aSubject, aTopic, aData) {
this._overlayLoading = true;
document.loadOverlay(
"chrome://browser/content/places/editBookmarkOverlay.xul",
(function (aSubject, aTopic, aData) {
//XXX We just caused localstore.rdf to be re-applied (bug 640158)
retrieveToolbarIconsizesFromTheme();
this._self._overlayLoading = false;
this._self._overlayLoaded = true;
this._self._doShowEditBookmarkPanel(this._itemId, this._anchorElement,
this._position);
}
};
this._overlayLoading = true;
document.loadOverlay("chrome://browser/content/places/editBookmarkOverlay.xul",
loadObserver);
// Move the header (star, title, button) into the grid,
// so that it aligns nicely with the other items (bug 484022).
let header = this._element("editBookmarkPanelHeader");
let rows = this._element("editBookmarkPanelGrid").lastChild;
rows.insertBefore(header, rows.firstChild);
header.hidden = false;
this._overlayLoading = false;
this._overlayLoaded = true;
this._doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition);
}).bind(this)
);
},
_doShowEditBookmarkPanel:
@ -192,13 +193,6 @@ var StarUI = {
this._blockCommands(); // un-done in the popuphiding handler
// Move the header (star, title, possibly a button) into the grid,
// so that it aligns nicely with the other items (bug 484022).
var rows = this._element("editBookmarkPanelGrid").lastChild;
var header = this._element("editBookmarkPanelHeader");
rows.insertBefore(header, rows.firstChild);
header.hidden = false;
// Set panel title:
// if we are batching, i.e. the bookmark has been added now,
// then show Page Bookmarked, else if the bookmark did already exist,

View File

@ -3573,7 +3573,6 @@ const BrowserSearch = {
loadAddEngines: function BrowserSearch_loadAddEngines() {
var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
var where = newWindowPref == 3 ? "tab" : "window";
var regionBundle = document.getElementById("bundle_browser_region");
var searchEnginesURL = formatURL("browser.search.searchEnginesURL", true);
openUILinkIn(searchEnginesURL, where);
}

View File

@ -224,7 +224,6 @@ FirefoxProfileMigrator.prototype = {
migrate : function Firefox_migrate(aItems, aStartup, aProfile)
{
if (aStartup) {
aStartup.doStartup();
this._replaceBookmarks = true;
}
@ -246,6 +245,11 @@ FirefoxProfileMigrator.prototype = {
if (aItems & MIGRATOR.PASSWORDS)
this._migratePasswords();
// The password manager encryption key must be copied before startup.
if (aStartup) {
aStartup.doStartup();
}
if (aItems & MIGRATOR.FORMDATA)
this._migrateFormData();

View File

@ -153,6 +153,7 @@ var gEngineManagerDialog = {
while (Services.prompt.prompt(window, title, msg, alias, null, {})) {
var bduplicate = false;
var eduplicate = false;
var dupName = "";
if (alias.value != "") {
try {
@ -168,6 +169,7 @@ var gEngineManagerDialog = {
if (engine.alias == alias.value &&
engine.name != selectedEngine.name) {
eduplicate = true;
dupName = engine.name;
break;
}
}
@ -177,8 +179,7 @@ var gEngineManagerDialog = {
if (eduplicate || bduplicate) {
var dtitle = strings.getString("duplicateTitle");
var bmsg = strings.getString("duplicateBookmarkMsg");
var emsg = strings.getFormattedString("duplicateEngineMsg",
[engine.name]);
var emsg = strings.getFormattedString("duplicateEngineMsg", [dupName]);
Services.prompt.alert(window, dtitle, eduplicate ? emsg : bmsg);
} else {

View File

@ -50,9 +50,9 @@
]>
<bindings id="SearchBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="searchbar">
<resources>
@ -96,13 +96,12 @@
<xul:image class="search-go-button"
anonid="search-go-button"
onclick="handleSearchCommand(event);"
tooltiptext="&searchEndCap.label;" />
tooltiptext="&searchEndCap.label;"/>
</xul:hbox>
</xul:textbox>
</content>
<implementation implements="nsIObserver">
<constructor><![CDATA[
if (this.parentNode.parentNode.localName == "toolbarpaletteitem")
return;
@ -164,7 +163,7 @@
<getter><![CDATA[
var currentEngine = this.searchService.currentEngine;
// Return a dummy engine if there is no currentEngine
return currentEngine || {name:"", uri:null};
return currentEngine || {name: "", uri: null};
]]></getter>
</property>
@ -335,7 +334,8 @@
// indexes as items are removed.
var items = popup.childNodes;
for (var i = items.length - 1; i >= 0; i--) {
if (items[i].getAttribute("class").indexOf("addengine") != -1)
if (items[i].classList.contains("addengine-item") ||
items[i].classList.contains("addengine-separator"))
popup.removeChild(items[i]);
}
@ -444,7 +444,7 @@
<body><![CDATA[
// Find the new index
var newIndex = this.engines.indexOf(this.currentEngine);
newIndex += (isNextEngine) ? 1 : -1;
newIndex += isNextEngine ? 1 : -1;
if (newIndex >= 0 && newIndex < this.engines.length)
this.currentEngine = this.engines[newIndex];
@ -495,13 +495,12 @@
openUILinkIn(submission.uri.spec, aWhere, null, submission.postData);
]]></body>
</method>
</implementation>
<handlers>
<handler event="command"><![CDATA[
const target = event.originalTarget;
if (target.getAttribute("class").indexOf("addengine-item") != -1) {
if (target.classList.contains("addengine-item")) {
var searchService =
Components.classes["@mozilla.org/browser/search-service;1"]
.getService(Components.interfaces.nsIBrowserSearchService);
@ -719,7 +718,7 @@
</body>
</method>
<!-- overload |onTextEntered| in autocomplete.xml -->
<!-- override |onTextEntered| in autocomplete.xml -->
<method name="onTextEntered">
<parameter name="aEvent"/>
<body><![CDATA[

View File

@ -164,6 +164,7 @@
@BINPATH@/components/dom_indexeddb.xpt
@BINPATH@/components/dom_offline.xpt
@BINPATH@/components/dom_json.xpt
@BINPATH@/components/dom_power.xpt
@BINPATH@/components/dom_range.xpt
@BINPATH@/components/dom_sidebar.xpt
@BINPATH@/components/dom_sms.xpt

View File

@ -169,11 +169,11 @@ libs:: $(addsuffix .xml,$(SEARCH_PLUGINS))
done
install:: $(addsuffix .xml,$(SEARCH_PLUGINS))
$(NSINSTALL) -D $(DESTDIR)$mozappdir/searchplugins
$(NSINSTALL) -D $(DESTDIR)$(mozappdir)/searchplugins
for i in $^; do \
SEARCH_PLUGIN_BASE=`basename $$SEARCH_PLUGIN`;\
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \
$$SEARCH_PLUGIN > $(DESTDIR)$mozappdir/searchplugins/$$SEARCH_PLUGIN_BASE; \
$$SEARCH_PLUGIN > $(DESTDIR)$(mozappdir)/searchplugins/$$SEARCH_PLUGIN_BASE; \
done

View File

@ -75,13 +75,13 @@ OrganizerQueryAllBookmarks=All Bookmarks
OrganizerQueryTags=Tags
# LOCALIZATION NOTE (tagResultLabel) :
# This is what we use to form the label (for screen readers)
# for url bar autocomplete results of type "tag"
# Noun used to describe the location bar autocomplete result type
# to users with screen readers
# See createResultLabel() in urlbarBindings.xml
tagResultLabel=Tag
# LOCALIZATION NOTE (bookmarkResultLabel) :
# This is what we use to form the label (for screen readers)
# for url bar autocomplete results of type "bookmark"
# Noun used to describe the location bar autocomplete result type
# to users with screen readers
# See createResultLabel() in urlbarBindings.xml
bookmarkResultLabel=Bookmark

View File

@ -61,7 +61,6 @@ class DMError(Exception):
def __str__(self):
return self.msg
def abstractmethod(method):
line = method.func_code.co_firstlineno
filename = method.func_code.co_filename
@ -70,9 +69,18 @@ def abstractmethod(method):
'should be implemented by a concrete class' %
(repr(method), filename,line))
return not_implemented
class DeviceManager:
@abstractmethod
def shell(self, cmd, outputfile, env=None, cwd=None):
"""
executes shell command on device
returns:
success: Return code from command
failure: None
"""
@abstractmethod
def pushFile(self, localname, destname):
"""
@ -168,25 +176,27 @@ class DeviceManager:
success: array of process tuples
failure: None
"""
@abstractmethod
def fireProcess(self, appname, failIfRunning=False):
"""
external function
DEPRECATED: Use shell() or launchApplication() for new code
returns:
success: pid
failure: None
"""
@abstractmethod
def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = '', failIfRunning=False):
"""
external function
DEPRECATED: Use shell() or launchApplication() for new code
returns:
success: output filename
failure: None
"""
def communicate(self, process, timeout = 600, interval = 5):
"""
loops until 'process' has exited or 'timeout' seconds is reached
@ -581,3 +591,35 @@ class NetworkTools:
print "Socket error trying to find open port"
return seed
def _pop_last_line(file):
'''
Utility function to get the last line from a file (shared between ADB and
SUT device managers). Function also removes it from the file. Intended to
strip off the return code from a shell command.
'''
bytes_from_end = 1
file.seek(0, 2)
length = file.tell() + 1
while bytes_from_end <= length:
file.seek((-1)*bytes_from_end, 2)
data = file.read()
if bytes_from_end == length and len(data) == 0: # no data, return None
return None
if data[0] == '\n' or bytes_from_end == length:
# found the last line, which should have the return value
if data[0] == '\n':
data = data[1:]
# truncate off the return code line
file.truncate(length - bytes_from_end)
file.seek(0,2)
file.write('\0')
return data
bytes_from_end += 1
return None

View File

@ -1,5 +1,5 @@
import subprocess
from devicemanager import DeviceManager, DMError
from devicemanager import DeviceManager, DMError, _pop_last_line
import re
import os
import sys
@ -63,6 +63,47 @@ class DeviceManagerADB(DeviceManager):
else:
print "restarting as root failed"
# external function: executes shell command on device
# returns:
# success: <return code>
# failure: None
def shell(self, cmd, outputfile, env=None, cwd=None):
# need to quote special characters here
for (index, arg) in enumerate(cmd):
if arg.find(" ") or arg.find("(") or arg.find(")") or arg.find("\""):
cmd[index] = '\'%s\'' % arg
# This is more complex than you'd think because adb doesn't actually
# return the return code from a process, so we have to capture the output
# to get it
# FIXME: this function buffers all output of the command into memory,
# always. :(
cmdline = subprocess.list2cmdline(cmd) + "; echo $?"
# prepend cwd and env to command if necessary
if cwd:
cmdline = "cd %s; %s" % (cwd, cmdline)
if env:
envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems()))
cmdline = envstr + "; " + cmdline
# all output should be in stdout
proc = subprocess.Popen(["adb", "shell", cmdline],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
outputfile.write(stdout.rstrip('\n'))
lastline = _pop_last_line(outputfile)
if lastline:
m = re.search('([0-9]+)', lastline)
if m:
return_code = m.group(1)
outputfile.seek(-2, 2)
outputfile.truncate() # truncate off the return code
return return_code
return None
# external function
# returns:
# success: True
@ -264,6 +305,7 @@ class DeviceManagerADB(DeviceManager):
return ret
# external function
# DEPRECATED: Use shell() or launchApplication() for new code
# returns:
# success: pid
# failure: None
@ -275,6 +317,7 @@ class DeviceManagerADB(DeviceManager):
return self.launchProcess(parts, failIfRunning)
# external function
# DEPRECATED: Use shell() or launchApplication() for new code
# returns:
# success: output filename
# failure: None
@ -327,6 +370,7 @@ class DeviceManagerADB(DeviceManager):
if name == appname:
p = self.runCmdAs(["shell", "kill", pid])
return p.stdout.read()
return None
# external function
@ -611,7 +655,7 @@ class DeviceManagerADB(DeviceManager):
args.insert(1, "run-as")
args.insert(2, self.packageName)
args.insert(0, "adb")
return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
def runCmdAs(self, args):
if self.useRunAs:

View File

@ -47,7 +47,18 @@ import subprocess
from threading import Thread
import traceback
import sys
from devicemanager import DeviceManager, DMError, FileError, NetworkTools
import StringIO
from devicemanager import DeviceManager, DMError, FileError, NetworkTools, _pop_last_line
class AgentError(Exception):
"SUTAgent-specific exception."
def __init__(self, msg= '', fatal = False):
self.msg = msg
self.fatal = fatal
def __str__(self):
return self.msg
class DeviceManagerSUT(DeviceManager):
host = ''
@ -76,7 +87,7 @@ class DeviceManagerSUT(DeviceManager):
self._sock = None
self.getDeviceRoot()
def cmdNeedsResponse(self, cmd):
def _cmdNeedsResponse(self, cmd):
""" Not all commands need a response from the agent:
* if the cmd matches the pushRE then it is the first half of push
and therefore we want to wait until the second half before looking
@ -93,18 +104,44 @@ class DeviceManagerSUT(DeviceManager):
for c in noResponseCmds:
if (c.match(cmd)):
return False
# If the command is not in our list, then it gets a response
return True
def shouldCmdCloseSocket(self, cmd):
def _stripPrompt(self, data):
'''
internal function
take a data blob and strip instances of the prompt '$>\x00'
'''
promptre = re.compile(self.prompt_regex + '.*')
retVal = []
lines = data.split('\n')
for line in lines:
foundPrompt = False
try:
while (promptre.match(line)):
foundPrompt = True
pieces = line.split(self.prompt_sep)
index = pieces.index('$>')
pieces.pop(index)
line = self.prompt_sep.join(pieces)
except(ValueError):
pass
# we don't want to append lines that are blank after stripping the
# prompt (those are basically "prompts")
if not foundPrompt or line:
retVal.append(line)
return '\n'.join(retVal)
def _shouldCmdCloseSocket(self, cmd):
""" Some commands need to close the socket after they are sent:
* push
* rebt
* uninst
* quit
"""
socketClosingCmds = [re.compile('^push .*$'),
re.compile('^quit.*'),
re.compile('^rebt.*'),
@ -116,85 +153,86 @@ class DeviceManagerSUT(DeviceManager):
return False
# convenience function to enable checks for agent errors
def verifySendCMD(self, cmdline, newline = True):
return self.sendCMD(cmdline, newline, False)
#
# create a wrapper for sendCMD that loops up to self.retrylimit iterations.
# this allows us to move the retry logic outside of the _doCMD() to make it
# easier for debugging in the future.
# note that since cmdline is a list of commands, they will all be retried if
# one fails. this is necessary in particular for pushFile(), where we don't want
# to accidentally send extra data if a failure occurs during data transmission.
#
def sendCMD(self, cmdline, newline = True, ignoreAgentErrors = True):
def sendCmds(self, cmdlist, outputfile, timeout = None, newline = True):
'''
a wrapper for _doCmds that loops up to self.retrylimit iterations.
this allows us to move the retry logic outside of the _doCmds() to make it
easier for debugging in the future.
note that since cmdlist is a list of commands, they will all be retried if
one fails. this is necessary in particular for pushFile(), where we don't want
to accidentally send extra data if a failure occurs during data transmission.
'''
done = False
while (not done):
retVal = self._doCMD(cmdline, newline)
if (retVal is None):
while self.retries < self.retrylimit:
try:
self._doCmds(cmdlist, outputfile, timeout, newline)
return
except AgentError, err:
# re-raise error if it's fatal (i.e. the device got the command but
# couldn't execute it). retry otherwise
if err.fatal:
raise err
if self.debug >= 2:
print err
self.retries += 1
else:
self.retries = 0
if ignoreAgentErrors == False:
if (self.agentErrorRE.match(retVal)):
raise DMError("error on the agent executing '%s'" % cmdline)
return retVal
if (self.retries >= self.retrylimit):
done = True
raise AgentError("unable to connect to %s after %s attempts" % (self.host, self.retrylimit))
raise DMError("unable to connect to %s after %s attempts" % (self.host, self.retrylimit))
def runCmds(self, cmdlist, timeout = None, newline = True):
'''
similar to sendCmds, but just returns any output as a string instead of
writing to a file. this is normally what you want to call to send a set
of commands to the agent
'''
outputfile = StringIO.StringIO()
self.sendCmds(cmdlist, outputfile, timeout, newline)
outputfile.seek(0)
return outputfile.read()
def _doCMD(self, cmdline, newline = True):
def _doCmds(self, cmdlist, outputfile, timeout, newline):
promptre = re.compile(self.prompt_regex + '$')
data = ""
shouldCloseSocket = False
recvGuard = 1000
if (self._sock == None):
if not self._sock:
try:
if (self.debug >= 1):
if self.debug >= 1:
print "reconnecting socket"
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
self._sock = None
if (self.debug >= 2):
print "unable to create socket"
return None
raise AgentError("unable to create socket")
try:
self._sock.connect((self.host, int(self.port)))
self._sock.recv(1024)
except:
self._sock.close()
self._sock = None
if (self.debug >= 2):
print "unable to connect socket"
return None
for cmd in cmdline:
raise AgentError("unable to connect socket")
for cmd in cmdlist:
if newline: cmd += '\r\n'
try:
numbytes = self._sock.send(cmd)
if (numbytes != len(cmd)):
print "ERROR: our cmd was " + str(len(cmd)) + " bytes and we only sent " + str(numbytes)
return None
raise AgentError("ERROR: our cmd was %s bytes and we only sent %s" % (len(cmd),
numbytes))
if (self.debug >= 4): print "send cmd: " + str(cmd)
except:
self._sock.close()
self._sock = None
return None
return False
# Check if the command should close the socket
shouldCloseSocket = self.shouldCmdCloseSocket(cmd)
shouldCloseSocket = self._shouldCmdCloseSocket(cmd)
# Handle responses from commands
if (self.cmdNeedsResponse(cmd)):
if (self._cmdNeedsResponse(cmd)):
found = False
loopguard = 0
data = ""
while (found == False and (loopguard < recvGuard)):
temp = ''
@ -207,14 +245,14 @@ class DeviceManagerSUT(DeviceManager):
except:
self._sock.close()
self._sock = None
return None
raise AgentError("Error receiving data from socket")
data += temp
# If something goes wrong in the agent it will send back a string that
# starts with '##AGENT-ERROR##'
if self.agentErrorRE.match(data):
break
raise AgentError("Agent Error processing command: %s" % cmd, fatal=True)
for line in data.splitlines():
if promptre.match(line):
@ -222,40 +260,54 @@ class DeviceManagerSUT(DeviceManager):
data = self._stripPrompt(data)
break
# periodically flush data to output file to make sure it doesn't get
# too big/unwieldly
if len(data) > 1024:
outputfile.write(data[0:1024])
data = data[1024:]
# If we violently lose the connection to the device, this loop tends to spin,
# this guard prevents that
if (temp == ''):
loopguard += 1
if (shouldCloseSocket == True):
# Write any remaining data to outputfile
outputfile.write(data)
if shouldCloseSocket:
try:
self._sock.close()
self._sock = None
except:
self._sock = None
return None
raise AgentError("Error closing socket")
return data
# internal function
# take a data blob and strip instances of the prompt '$>\x00'
def _stripPrompt(self, data):
promptre = re.compile(self.prompt_regex + '.*')
retVal = []
lines = data.split('\n')
for line in lines:
try:
while (promptre.match(line)):
pieces = line.split(self.prompt_sep)
index = pieces.index('$>')
pieces.pop(index)
line = self.prompt_sep.join(pieces)
except(ValueError):
pass
retVal.append(line)
# external function: executes shell command on device
# returns:
# success: <return code>
# failure: None
def shell(self, cmd, outputfile, env=None, cwd=None):
cmdline = subprocess.list2cmdline(cmd)
if env:
cmdline = '%s %s' % (self.formatEnvString(env), cmdline)
return '\n'.join(retVal)
try:
if cwd:
self.sendCmds(['execcwd %s %s' % (cwd, cmdline)], outputfile)
else:
self.sendCmds(['exec %s' % cmdline], outputfile)
except AgentError:
return None
# dig through the output to get the return code
lastline = _pop_last_line(outputfile)
if lastline:
m = re.search('return code \[([0-9]+)\]', lastline)
if m:
return m.group(1)
# woops, we couldn't find an end of line/return value
return None
# external function
# returns:
@ -286,8 +338,8 @@ class DeviceManagerSUT(DeviceManager):
f.close()
try:
retVal = self.verifySendCMD(['push ' + destname + ' ' + str(filesize) + '\r\n', data], newline = False)
except(DMError):
retVal = self.runCmds(['push ' + destname + ' ' + str(filesize) + '\r\n', data], newline = False)
except AgentError:
retVal = False
if (self.debug >= 3): print "push returned: " + str(retVal)
@ -323,8 +375,8 @@ class DeviceManagerSUT(DeviceManager):
return name
else:
try:
retVal = self.verifySendCMD(['mkdr ' + name])
except(DMError):
retVal = self.runCmds(['mkdr ' + name])
except AgentError:
retVal = None
return retVal
@ -376,8 +428,8 @@ class DeviceManagerSUT(DeviceManager):
match = ".*" + dirname + "$"
dirre = re.compile(match)
try:
data = self.verifySendCMD(['cd ' + dirname, 'cwd'])
except(DMError):
data = self.runCmds(['cd ' + dirname, 'cwd'])
except AgentError:
return False
found = False
@ -412,8 +464,8 @@ class DeviceManagerSUT(DeviceManager):
if (self.dirExists(rootdir) == False):
return []
try:
data = self.verifySendCMD(['cd ' + rootdir, 'ls'])
except(DMError):
data = self.runCmds(['cd ' + rootdir, 'ls'])
except AgentError:
return []
files = filter(lambda x: x, data.splitlines())
@ -429,8 +481,8 @@ class DeviceManagerSUT(DeviceManager):
def removeFile(self, filename):
if (self.debug>= 2): print "removing file: " + filename
try:
retVal = self.verifySendCMD(['rm ' + filename])
except(DMError):
retVal = self.runCmds(['rm ' + filename])
except AgentError:
return None
return retVal
@ -442,8 +494,8 @@ class DeviceManagerSUT(DeviceManager):
# failure: None
def removeDir(self, remoteDir):
try:
retVal = self.verifySendCMD(['rmdr ' + remoteDir])
except(DMError):
retVal = self.runCmds(['rmdr ' + remoteDir])
except AgentError:
return None
return retVal
@ -454,8 +506,8 @@ class DeviceManagerSUT(DeviceManager):
# failure: []
def getProcessList(self):
try:
data = self.verifySendCMD(['ps'])
except DMError:
data = self.runCmds(['ps'])
except AgentError:
return []
files = []
@ -470,6 +522,7 @@ class DeviceManagerSUT(DeviceManager):
return files
# external function
# DEPRECATED: Use shell() or launchApplication() for new code
# returns:
# success: pid
# failure: None
@ -486,8 +539,8 @@ class DeviceManagerSUT(DeviceManager):
return None
try:
data = self.verifySendCMD(['exec ' + appname])
except(DMError):
data = self.runCmds(['exec ' + appname])
except AgentError:
return None
# wait up to 30 seconds for process to start up
@ -503,6 +556,7 @@ class DeviceManagerSUT(DeviceManager):
return process
# external function
# DEPRECATED: Use shell() or launchApplication() for new code
# returns:
# success: output filename
# failure: None
@ -532,8 +586,8 @@ class DeviceManagerSUT(DeviceManager):
# failure: None
def killProcess(self, appname):
try:
data = self.verifySendCMD(['kill ' + appname])
except(DMError):
data = self.runCmds(['kill ' + appname])
except AgentError:
return None
return data
@ -544,8 +598,8 @@ class DeviceManagerSUT(DeviceManager):
# failure: None
def getTempDir(self):
try:
data = self.verifySendCMD(['tmpd'])
except(DMError):
data = self.runCmds(['tmpd'])
except AgentError:
return None
return data.strip()
@ -556,12 +610,12 @@ class DeviceManagerSUT(DeviceManager):
# failure: None
def catFile(self, remoteFile):
try:
data = self.verifySendCMD(['cat ' + remoteFile])
except(DMError):
data = self.runCmds(['cat ' + remoteFile])
except AgentError:
return None
return data
# external function
# returns:
# success: output of pullfile, string
@ -625,8 +679,8 @@ class DeviceManagerSUT(DeviceManager):
# or, if error,
# <filename>,-1\n<error message>
try:
data = self.verifySendCMD(['pull ' + remoteFile])
except(DMError):
data = self.runCmds(['pull ' + remoteFile])
except AgentError:
return None
# read metadata; buffer the rest
@ -744,8 +798,8 @@ class DeviceManagerSUT(DeviceManager):
# Throws a FileError exception when null (invalid dir/filename)
def isDir(self, remotePath):
try:
data = self.verifySendCMD(['isdir ' + remotePath])
except(DMError):
data = self.runCmds(['isdir ' + remotePath])
except AgentError:
# normally there should be no error here; a nonexistent file/directory will
# return the string "<filename>: No such file or directory".
# However, I've seen AGENT-WARNING returned before.
@ -780,8 +834,8 @@ class DeviceManagerSUT(DeviceManager):
# failure: None
def getRemoteHash(self, filename):
try:
data = self.verifySendCMD(['hash ' + filename])
except(DMError):
data = self.runCmds(['hash ' + filename])
except AgentError:
return None
retVal = None
@ -809,7 +863,7 @@ class DeviceManagerSUT(DeviceManager):
# failure: None
def getDeviceRoot(self):
try:
data = self.verifySendCMD(['testroot'])
data = self.runCmds(['testroot'])
except:
return None
@ -823,7 +877,7 @@ class DeviceManagerSUT(DeviceManager):
def getAppRoot(self, packageName):
try:
data = self.verifySendCMD(['getapproot '+packageName])
data = self.runCmds(['getapproot '+packageName])
except:
return None
@ -851,8 +905,8 @@ class DeviceManagerSUT(DeviceManager):
return None
try:
data = self.verifySendCMD(['cd ' + dir, 'unzp ' + filename])
except(DMError):
data = self.runCmds(['cd ' + dir, 'unzp ' + filename])
except AgentError:
return None
return data
@ -872,8 +926,8 @@ class DeviceManagerSUT(DeviceManager):
try:
destname = '/data/data/com.mozilla.SUTAgentAndroid/files/update.info'
data = "%s,%s\rrebooting\r" % (ipAddr, port)
self.verifySendCMD(['push ' + destname + ' ' + str(len(data)) + '\r\n', data], newline = False)
except(DMError):
self.runCmds(['push ' + destname + ' ' + str(len(data)) + '\r\n', data], newline = False)
except AgentError:
return None
ip, port = self.getCallbackIpAndPort(ipAddr, port)
@ -882,8 +936,8 @@ class DeviceManagerSUT(DeviceManager):
callbacksvr = callbackServer(ip, port, self.debug)
try:
status = self.verifySendCMD([cmd])
except(DMError):
status = self.runCmds([cmd])
except AgentError:
return None
if (ipAddr is not None):
@ -918,7 +972,7 @@ class DeviceManagerSUT(DeviceManager):
directives = [directive]
for d in directives:
data = self.verifySendCMD(['info ' + d])
data = self.runCmds(['info ' + d])
if (data is None):
continue
data = collapseSpaces.sub(' ', data)
@ -955,8 +1009,8 @@ class DeviceManagerSUT(DeviceManager):
if destPath:
cmd += ' ' + destPath
try:
data = self.verifySendCMD([cmd])
except(DMError):
data = self.runCmds([cmd])
except AgentError:
return None
f = re.compile('Failure')
@ -981,8 +1035,8 @@ class DeviceManagerSUT(DeviceManager):
if installPath:
cmd += ' ' + installPath
try:
data = self.verifySendCMD([cmd])
except(DMError):
data = self.runCmds([cmd])
except AgentError:
return None
if (self.debug > 3): print "uninstallAppAndReboot: " + str(data)
@ -1026,8 +1080,8 @@ class DeviceManagerSUT(DeviceManager):
if (self.debug >= 3): print "INFO: updateApp using command: " + str(cmd)
try:
status = self.verifySendCMD([cmd])
except(DMError):
status = self.runCmds([cmd])
except AgentError:
return None
if ipAddr is not None:
@ -1046,8 +1100,8 @@ class DeviceManagerSUT(DeviceManager):
# failure: None
def getCurrentTime(self):
try:
data = self.verifySendCMD(['clok'])
except(DMError):
data = self.runCmds(['clok'])
except AgentError:
return None
return data.strip()
@ -1079,8 +1133,8 @@ class DeviceManagerSUT(DeviceManager):
return None
try:
data = self.verifySendCMD(['cd ' + dir, 'unzp ' + filename])
except(DMError):
data = self.runCmds(['cd ' + dir, 'unzp ' + filename])
except AgentError:
return None
return data
@ -1150,9 +1204,9 @@ class DeviceManagerSUT(DeviceManager):
if (self.debug >= 3): print "INFO: adjusting screen resolution to %s, %s and rebooting" % (width, height)
try:
self.verifySendCMD(["exec setprop persist.tegra.dpy%s.mode.width %s" % (screentype, width)])
self.verifySendCMD(["exec setprop persist.tegra.dpy%s.mode.height %s" % (screentype, height)])
except(DMError):
self.runCmds(["exec setprop persist.tegra.dpy%s.mode.width %s" % (screentype, width)])
self.runCmds(["exec setprop persist.tegra.dpy%s.mode.height %s" % (screentype, height)])
except AgentError:
return False
return True

87
build/mobile/droid.py Normal file
View File

@ -0,0 +1,87 @@
# ***** 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 Test Automation Framework.
#
# The Initial Developer of the Original Code is
# Mozilla foundation
#
# Portions created by the Initial Developer are Copyright (C) 2009
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Joel Maher <joel.maher@gmail.com> (Original Developer)
# William Lachance <wlachance@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
from devicemanagerADB import DeviceManagerADB
from devicemanagerSUT import DeviceManagerSUT
class DroidMixin(object):
"""Mixin to extend DeviceManager with Android-specific functionality"""
def launchApplication(self, app, activity="App",
intent="android.intent.action.VIEW", env=None,
url=None, extra_args=None):
"""
Launches an Android application
returns:
success: True
failure: False
"""
# only one instance of an application may be running at once
if self.processExist(app):
return False
acmd = [ "am", "start", "-a", intent, "-W", "-n", "%s/.%s" % (app, activity)]
if extra_args:
acmd.extend(["--es", "args", " ".join(args)])
if env:
envCnt = 0
# env is expected to be a dict of environment variables
for envkey, envval in env.iteritems():
acmd.extend(["--es", "env" + str(envCnt), envkey + "=" + envval])
envCnt += 1
if url:
acmd.extend(["-d", ''.join(['"', url, '"'])])
# shell output not that interesting and debugging logs should already
# show what's going on here... so just create an empty memory buffer
# and ignore
shellOutput = StringIO.StringIO()
if self.shell(acmd, shellOutput) == 0:
return True
return False
class DroidADB(DeviceManagerADB, DroidMixin):
pass
class DroidSUT(DeviceManagerSUT, DroidMixin):
pass

View File

@ -136,12 +136,13 @@ public class DoCommand {
String ffxProvider = "org.mozilla.ffxcp";
String fenProvider = "org.mozilla.fencp";
private final String prgVersion = "SUTAgentAndroid Version 1.05";
private final String prgVersion = "SUTAgentAndroid Version 1.06";
public enum Command
{
RUN ("run"),
EXEC ("exec"),
EXECCWD ("execcwd"),
ENVRUN ("envrun"),
KILL ("kill"),
PS ("ps"),
@ -692,7 +693,25 @@ public class DoCommand {
theArgs[lcv - 1] = Argv[lcv];
}
strReturn = StartPrg2(theArgs, cmdOut);
strReturn = StartPrg2(theArgs, cmdOut, null);
}
else
{
strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
}
break;
case EXECCWD:
if (Argc >= 3)
{
String [] theArgs = new String [Argc - 2];
for (int lcv = 2; lcv < Argc; lcv++)
{
theArgs[lcv - 2] = Argv[lcv];
}
strReturn = StartPrg2(theArgs, cmdOut, Argv[1]);
}
else
{
@ -1262,6 +1281,11 @@ private void CancelNotification()
{
String sRet = null;
File tmpFile = new java.io.File("/data/local/tests");
if (tmpFile.exists() && tmpFile.isDirectory())
{
return("/data/local");
}
if (Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED))
{
sRet = Environment.getExternalStorageDirectory().getAbsolutePath();
@ -3463,7 +3487,7 @@ private void CancelNotification()
return (sRet);
}
public String StartPrg2(String [] progArray, OutputStream out)
public String StartPrg2(String [] progArray, OutputStream out, String cwd)
{
String sRet = "";
@ -3553,7 +3577,15 @@ private void CancelNotification()
if (theArgs[0].contains("/") || theArgs[0].contains("\\") || !theArgs[0].contains("."))
{
pProc = Runtime.getRuntime().exec(theArgs, envArray);
if (cwd != null)
{
File f = new File(cwd);
pProc = Runtime.getRuntime().exec(theArgs, envArray, f);
}
else
{
pProc = Runtime.getRuntime().exec(theArgs, envArray);
}
RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
outThrd.start();

View File

@ -52,7 +52,7 @@ interface nsIContentSecurityPolicy;
[ptr] native JSContext(JSContext);
[ptr] native JSPrincipals(JSPrincipals);
[scriptable, uuid(B406A2DB-E547-4C95-B8E2-AD09ECB54CE0)]
[scriptable, uuid(1f83b0e0-6b63-4bdc-a50a-b9afe256bd25)]
interface nsIPrincipal : nsISerializable
{
/**
@ -206,6 +206,12 @@ interface nsIPrincipal : nsISerializable
*/
boolean subsumes(in nsIPrincipal other);
/**
* Same as the previous method, subsumes(), but for codebase principals
* ignores changes to document.domain.
*/
boolean subsumesIgnoringDomain(in nsIPrincipal other);
/**
* Checks whether this principal is allowed to load the network resource
* located at the given URI under the same-origin policy. This means that

View File

@ -336,6 +336,12 @@ nsNullPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
return NS_OK;
}
NS_IMETHODIMP
nsNullPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
{
return Subsumes(aOther, aResult);
}
NS_IMETHODIMP
nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
{

View File

@ -377,6 +377,12 @@ nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
return Equals(aOther, aResult);
}
NS_IMETHODIMP
nsPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
{
return EqualsIgnoringDomain(aOther, aResult);
}
static bool
URIIsLocalFile(nsIURI *aURI)
{

View File

@ -125,6 +125,13 @@ nsSystemPrincipal::Subsumes(nsIPrincipal *other, bool *result)
return NS_OK;
}
NS_IMETHODIMP
nsSystemPrincipal::SubsumesIgnoringDomain(nsIPrincipal *other, bool *result)
{
*result = true;
return NS_OK;
}
NS_IMETHODIMP
nsSystemPrincipal::CheckMayLoad(nsIURI* uri, bool aReport)
{

View File

@ -697,6 +697,8 @@ JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@
MOZ_INSTRUMENT_EVENT_LOOP = @MOZ_INSTRUMENT_EVENT_LOOP@
MOZ_SYSTEM_PLY = @MOZ_SYSTEM_PLY@
# We only want to do the pymake sanity on Windows, other os's can cope
ifeq ($(HOST_OS_ARCH),WINNT)
# Ensure invariants between GNU Make and pymake

View File

@ -792,8 +792,10 @@ EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist $(if $(REORDER),--reorder $(REORDER))-
EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) --uselist $(if $(REORDER),--reorder $(REORDER))-- $(MKSHLIB)
ifdef STDCXX_COMPAT
ifneq ($(OS_ARCH),Darwin)
CHECK_STDCXX = objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null && echo "TEST-UNEXPECTED-FAIL | | We don't want these libstdc++ symbols to be used:" && objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && exit 1 || exit 0
endif
endif
# autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
# this file

View File

@ -1049,6 +1049,16 @@ if test -z "$PYTHON"; then
AC_MSG_ERROR([python was not found in \$PATH])
fi
MOZ_ARG_WITH_BOOL(system-ply,
[ --with-system-ply Use system installed python ply library],
[if $PYTHON -c 'import ply' 2>&5; then
MOZ_SYSTEM_PLY=1
else
AC_MSG_ERROR([python ply library is not found but --with-system-ply was requested])
fi])
AC_SUBST(MOZ_SYSTEM_PLY)
if test -z "$COMPILE_ENVIRONMENT"; then
NSINSTALL_BIN='$(PYTHON) $(topsrcdir)/config/nsinstall.py'
fi
@ -3718,20 +3728,23 @@ AC_CHECK_FUNCS(random strerror lchown fchmod snprintf statvfs memmove rint stat6
AC_CHECK_FUNCS(flockfile getpagesize)
AC_CHECK_FUNCS(localtime_r strtok_r)
dnl check for clock_gettime(), the CLOCK_MONOTONIC clock, and -lrt
_SAVE_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -lrt"
AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC) and -lrt,
ac_cv_have_clock_monotonic,
[AC_TRY_LINK([#include <time.h>],
[ struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); ],
ac_cv_have_clock_monotonic=yes,
ac_cv_have_clock_monotonic=no)])
LDFLAGS=$_SAVE_LDFLAGS
if test "$ac_cv_have_clock_monotonic" = "yes"; then
dnl check for clock_gettime(), the CLOCK_MONOTONIC clock
AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC),
ac_cv_clock_monotonic,
[for libs in "" -lrt; do
_SAVE_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $libs"
AC_TRY_LINK([#include <time.h>],
[ struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); ],
ac_cv_clock_monotonic=$libs
break,
ac_cv_clock_monotonic=no)
LDFLAGS="$_SAVE_LDFLAGS"
done])
if test "$ac_cv_clock_monotonic" != "no"; then
HAVE_CLOCK_MONOTONIC=1
REALTIME_LIBS=-lrt
REALTIME_LIBS=$ac_cv_clock_monotonic
AC_DEFINE(HAVE_CLOCK_MONOTONIC)
AC_SUBST(HAVE_CLOCK_MONOTONIC)
AC_SUBST(REALTIME_LIBS)

View File

@ -131,7 +131,6 @@ class nsIInterfaceRequestor;
template<class E> class nsCOMArray;
template<class K, class V> class nsRefPtrHashtable;
struct JSRuntime;
class nsIUGenCategory;
class nsIWidget;
class nsIDragSession;
class nsIPresShell;
@ -625,11 +624,6 @@ public:
return sWordBreaker;
}
static nsIUGenCategory* GetGenCat()
{
return sGenCat;
}
/**
* Regster aObserver as a shutdown observer. A strong reference is held
* to aObserver until UnregisterShutdownObserver is called.
@ -2017,7 +2011,6 @@ private:
static nsILineBreaker* sLineBreaker;
static nsIWordBreaker* sWordBreaker;
static nsIUGenCategory* sGenCat;
static nsIScriptRuntime* sScriptRuntimes[NS_STID_ARRAY_UBOUND];
static PRInt32 sScriptRootCount[NS_STID_ARRAY_UBOUND];

View File

@ -691,6 +691,7 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
rv = nsCopySupport::GetTransferableForNode(nodeToSerialize, doc,
getter_AddRefs(transferable));
}
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupportsString> data;
PRUint32 dataSize;

View File

@ -122,6 +122,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsLWBrkCIID.h"
#include "nsILineBreaker.h"
#include "nsIWordBreaker.h"
#include "nsUnicodeProperties.h"
#include "jsdbgapi.h"
#include "nsIJSRuntimeService.h"
#include "nsIDOMDocumentXBL.h"
@ -154,7 +155,6 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsGenericHTMLElement.h"
#include "nsAttrValue.h"
#include "nsReferencedElement.h"
#include "nsIUGenCategory.h"
#include "nsIDragService.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
@ -260,7 +260,6 @@ nsIContentPolicy *nsContentUtils::sContentPolicyService;
bool nsContentUtils::sTriedToGetContentPolicy = false;
nsILineBreaker *nsContentUtils::sLineBreaker;
nsIWordBreaker *nsContentUtils::sWordBreaker;
nsIUGenCategory *nsContentUtils::sGenCat;
nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
PRUint32 nsContentUtils::sJSGCThingRootCount;
@ -389,9 +388,6 @@ nsContentUtils::Init()
rv = CallGetService(NS_WBRK_CONTRACTID, &sWordBreaker);
NS_ENSURE_SUCCESS(rv, rv);
rv = CallGetService(NS_UNICHARCATEGORY_CONTRACTID, &sGenCat);
NS_ENSURE_SUCCESS(rv, rv);
if (!InitializeEventTable())
return NS_ERROR_FAILURE;
@ -977,7 +973,7 @@ nsContentUtils::IsPunctuationMarkAt(const nsTextFragment* aFrag, PRUint32 aOffse
// static
bool nsContentUtils::IsAlphanumeric(PRUint32 aChar)
{
nsIUGenCategory::nsUGenCategory cat = sGenCat->Get(aChar);
nsIUGenCategory::nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
return (cat == nsIUGenCategory::kLetter || cat == nsIUGenCategory::kNumber);
}
@ -1138,7 +1134,6 @@ nsContentUtils::Shutdown()
NS_IF_RELEASE(sIOService);
NS_IF_RELEASE(sLineBreaker);
NS_IF_RELEASE(sWordBreaker);
NS_IF_RELEASE(sGenCat);
#ifdef MOZ_XTF
NS_IF_RELEASE(sXTFService);
#endif

View File

@ -480,10 +480,14 @@ nsDOMAttribute::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
}
NS_IMETHODIMP
nsDOMAttribute::CloneNode(bool aDeep, nsIDOMNode** aResult)
nsDOMAttribute::CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aResult)
{
OwnerDoc()->WarnOnceAbout(nsIDocument::eCloneNode);
if (!aOptionalArgc) {
aDeep = true;
}
return nsNodeUtils::CloneNodeImpl(this, aDeep, true, aResult);
}

View File

@ -5830,8 +5830,12 @@ nsDocument::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
}
NS_IMETHODIMP
nsDocument::CloneNode(bool aDeep, nsIDOMNode** aReturn)
nsDocument::CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aReturn)
{
if (!aOptionalArgc) {
aDeep = true;
}
return nsNodeUtils::CloneNodeImpl(this, aDeep, !mCreatingStaticClone, aReturn);
}
@ -8062,7 +8066,7 @@ nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
nsCOMPtr<nsISupports> originalContainer = GetContainer();
SetContainer(aCloneContainer);
nsCOMPtr<nsIDOMNode> clonedNode;
nsresult rv = domDoc->CloneNode(true, getter_AddRefs(clonedNode));
nsresult rv = domDoc->CloneNode(true, 1, getter_AddRefs(clonedNode));
SetContainer(originalContainer);
nsCOMPtr<nsIDocument> clonedDoc;

View File

@ -143,8 +143,12 @@ public:
nsresult IsSupported(const nsAString& aFeature,
const nsAString& aVersion,
bool* aReturn);
nsresult CloneNode(bool aDeep, nsIDOMNode** aReturn)
nsresult CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aReturn)
{
if (!aOptionalArgc) {
aDeep = true;
}
return nsNodeUtils::CloneNodeImpl(this, aDeep, true, aReturn);
}

View File

@ -437,8 +437,12 @@ public:
// nsIDOMElement method implementation
NS_DECL_NSIDOMELEMENT
nsresult CloneNode(bool aDeep, nsIDOMNode **aResult)
nsresult CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode **aResult)
{
if (!aOptionalArgc) {
aDeep = true;
}
return nsNodeUtils::CloneNodeImpl(this, aDeep, true, aResult);
}

View File

@ -1596,7 +1596,7 @@ nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
cutValue);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> clone;
rv = charData->CloneNode(false, getter_AddRefs(clone));
rv = charData->CloneNode(false, 1, getter_AddRefs(clone));
NS_ENSURE_SUCCESS(rv, rv);
clone->SetNodeValue(cutValue);
nodeToResult = clone;
@ -1656,7 +1656,7 @@ nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
{
if (retval) {
nsCOMPtr<nsIDOMNode> clone;
rv = node->CloneNode(false, getter_AddRefs(clone));
rv = node->CloneNode(false, 1, getter_AddRefs(clone));
NS_ENSURE_SUCCESS(rv, rv);
nodeToResult = clone;
}
@ -1827,7 +1827,7 @@ nsRange::CloneParentsBetween(nsIDOMNode *aAncestor,
{
nsCOMPtr<nsIDOMNode> clone, tmpNode;
res = parent->CloneNode(false, getter_AddRefs(clone));
res = parent->CloneNode(false, 1, getter_AddRefs(clone));
if (NS_FAILED(res)) return res;
if (!clone) return NS_ERROR_FAILURE;
@ -1928,7 +1928,7 @@ nsRange::CloneContents(nsIDOMDocumentFragment** aReturn)
// Clone the current subtree!
nsCOMPtr<nsIDOMNode> clone;
res = node->CloneNode(deepClone, getter_AddRefs(clone));
res = node->CloneNode(deepClone, 1, getter_AddRefs(clone));
if (NS_FAILED(res)) return res;
// If it's CharacterData, make sure we only clone what

View File

@ -555,6 +555,7 @@ _TEST_FILES2 = \
file_bug717511_2.html \
file_bug717511_2.html^headers^ \
test_bug726364.html \
test_bug698381.html \
$(NULL)
_CHROME_FILES = \

View File

@ -0,0 +1,56 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=698381
-->
<head>
<title>Test for Bug 698381</title>
<script type="text/javascript"
src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"
type="text/javascript"></script>
<link rel="stylesheet" type="text/css"
href="/tests/SimpleTest/test.css" />
</head>
<body onload="runTests();">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=698381">
Mozilla Bug 698381</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<div id="noChildren" style="display: none"></div>
<div id="hasChildren" style="display: none">
<div id="childOne" style="display: none"></div>
</div>
<pre id="test">
<script type="text/javascript">
/*
Checks to see if default parameter handling is correct when 0
parameters are passed.
If none are passed, then Node.cloneNode should default aDeep
to true.
*/
SimpleTest.waitForExplicitFinish();
var hasChildren = document.getElementById("hasChildren"),
noChildren = document.getElementById("noChildren"),
clonedNode;
function runTests() {
// Test Node.cloneNode when no arguments are given
clonedNode = hasChildren.cloneNode();
is(clonedNode.hasChildNodes(), true, "Node.cloneNode with true " +
"default on a node with children clones the child nodes.");
clonedNode = noChildren.cloneNode();
is(clonedNode.hasChildNodes(), false, "Node.cloneNode with true " +
"default on a node without children doesn't clone child nodes." );
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

View File

@ -71,6 +71,7 @@ CPPSRCS += \
WebGLContextReporter.cpp \
WebGLContextValidate.cpp \
WebGLExtensionStandardDerivatives.cpp \
WebGLExtensionTextureFilterAnisotropic.cpp \
WebGLExtensionLoseContext.cpp \
$(NULL)

View File

@ -820,7 +820,6 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
switch (ei) {
case WebGL_OES_texture_float:
MakeContextCurrent();
isSupported = gl->IsExtensionSupported(gl->IsGLES2() ? GLContext::OES_texture_float
: GLContext::ARB_texture_float);
break;
@ -828,6 +827,9 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
// We always support this extension.
isSupported = true;
break;
case WebGL_EXT_texture_filter_anisotropic:
isSupported = gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
break;
case WebGL_MOZ_WEBGL_lose_context:
// We always support this extension.
isSupported = true;
@ -860,6 +862,10 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
if (IsExtensionSupported(WebGL_OES_standard_derivatives))
ei = WebGL_OES_standard_derivatives;
}
else if (aName.EqualsLiteral("MOZ_EXT_texture_filter_anisotropic")) {
if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
ei = WebGL_EXT_texture_filter_anisotropic;
}
else if (aName.EqualsLiteral("MOZ_WEBGL_lose_context")) {
if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
ei = WebGL_MOZ_WEBGL_lose_context;
@ -871,6 +877,9 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
case WebGL_OES_standard_derivatives:
mEnabledExtensions[ei] = new WebGLExtensionStandardDerivatives(this);
break;
case WebGL_EXT_texture_filter_anisotropic:
mEnabledExtensions[ei] = new WebGLExtensionTextureFilterAnisotropic(this);
break;
case WebGL_MOZ_WEBGL_lose_context:
mEnabledExtensions[ei] = new WebGLExtensionLoseContext(this);
break;
@ -1295,6 +1304,11 @@ NS_INTERFACE_MAP_BEGIN(WebGLExtensionStandardDerivatives)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionStandardDerivatives)
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
NS_IMPL_ADDREF(WebGLExtensionTextureFilterAnisotropic)
NS_IMPL_RELEASE(WebGLExtensionTextureFilterAnisotropic)
DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, WebGLExtensionTextureFilterAnisotropic)
NS_IMPL_ADDREF(WebGLExtensionLoseContext)
NS_IMPL_RELEASE(WebGLExtensionLoseContext)
@ -1409,6 +1423,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_EXT_texture_filter_anisotropic))
extList.InsertElementAt(extList.Length(), "MOZ_EXT_texture_filter_anisotropic");
if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
extList.InsertElementAt(extList.Length(), "MOZ_WEBGL_lose_context");

View File

@ -745,6 +745,7 @@ protected:
enum WebGLExtensionID {
WebGL_OES_texture_float,
WebGL_OES_standard_derivatives,
WebGL_EXT_texture_filter_anisotropic,
WebGL_MOZ_WEBGL_lose_context,
WebGLExtensionID_Max
};

View File

@ -2210,6 +2210,15 @@ WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
break;
// float
case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
GLfloat f = 0.f;
gl->fGetFloatv(pname, &f);
wrval->SetAsFloat(f);
} else {
return ErrorInvalidEnum("getParameter: parameter", pname);
}
break;
case LOCAL_GL_DEPTH_CLEAR_VALUE:
case LOCAL_GL_LINE_WIDTH:
case LOCAL_GL_POLYGON_OFFSET_FACTOR:
@ -2679,6 +2688,7 @@ nsresult WebGLContext::TexParameter_base(WebGLenum target, WebGLenum pname,
return ErrorInvalidOperation("texParameter: no texture is bound to this target");
bool pnameAndParamAreIncompatible = false;
bool paramValueInvalid = false;
switch (pname) {
case LOCAL_GL_TEXTURE_MIN_FILTER:
@ -2727,18 +2737,33 @@ nsresult WebGLContext::TexParameter_base(WebGLenum target, WebGLenum pname,
pnameAndParamAreIncompatible = true;
}
break;
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
if (floatParamPtr && floatParam < 1.f)
paramValueInvalid = true;
else if (intParamPtr && intParam < 1)
paramValueInvalid = true;
}
else
pnameAndParamAreIncompatible = true;
break;
default:
return ErrorInvalidEnumInfo("texParameter: pname", pname);
}
if (pnameAndParamAreIncompatible) {
// note that currently all params are enums, and the tex-input-validation test wants INVALID_ENUM errors
// even for texParameterf. why not.
if (intParamPtr)
return ErrorInvalidEnum("texParameteri: pname %x and param %x (decimal %d) are mutually incompatible",
pname, intParam, intParam);
else
return ErrorInvalidEnum("texParameterf: pname %x and floating-point param %e are mutually incompatible",
return ErrorInvalidEnum("texParameterf: pname %x and param %g are mutually incompatible",
pname, floatParam);
} else if (paramValueInvalid) {
if (intParamPtr)
return ErrorInvalidValue("texParameteri: pname %x and param %x (decimal %d) is invalid",
pname, intParam, intParam);
else
return ErrorInvalidValue("texParameterf: pname %x and param %g is invalid",
pname, floatParam);
}
@ -2799,6 +2824,15 @@ WebGLContext::GetTexParameter(WebGLenum target, WebGLenum pname, nsIVariant **re
wrval->SetAsInt32(i);
}
break;
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
GLfloat f = 0.f;
gl->fGetTexParameterfv(target, pname, &f);
wrval->SetAsFloat(f);
}
else
return ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
break;
default:
return ErrorInvalidEnumInfo("getTexParameter: parameter", pname);

View File

@ -55,4 +55,5 @@ DOMCI_DATA(WebGLShaderPrecisionFormat, void)
DOMCI_DATA(WebGLActiveInfo, void)
DOMCI_DATA(WebGLExtension, void)
DOMCI_DATA(WebGLExtensionStandardDerivatives, void)
DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, void)
DOMCI_DATA(WebGLExtensionLoseContext, void)

View File

@ -0,0 +1,64 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Florian Boesch <pyalot@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <stdarg.h>
#include "WebGLContext.h"
#include "WebGLExtensions.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
NS_INTERFACE_MAP_BEGIN(WebGLExtensionTextureFilterAnisotropic)
NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionTextureFilterAnisotropic)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionTextureFilterAnisotropic)
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
WebGLExtensionTextureFilterAnisotropic::WebGLExtensionTextureFilterAnisotropic(WebGLContext* context) :
WebGLExtension(context)
{
}
WebGLExtensionTextureFilterAnisotropic::~WebGLExtensionTextureFilterAnisotropic()
{
}

View File

@ -41,9 +41,6 @@
namespace mozilla {
class WebGLExtensionLoseContext;
class WebGLExtensionStandardDerivatives;
class WebGLExtensionLoseContext :
public nsIWebGLExtensionLoseContext,
public WebGLExtension
@ -68,6 +65,18 @@ public:
NS_DECL_NSIWEBGLEXTENSION
};
class WebGLExtensionTextureFilterAnisotropic :
public nsIWebGLExtensionTextureFilterAnisotropic,
public WebGLExtension
{
public:
WebGLExtensionTextureFilterAnisotropic(WebGLContext* context);
virtual ~WebGLExtensionTextureFilterAnisotropic();
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBGLEXTENSION
};
}
#endif // WEBGLEXTENSIONS_H_

View File

@ -1,4 +1,5 @@
oes-standard-derivatives.html
ext-texture-filter-anisotropic.html
oes-texture-float.html
oes-vertex-array-object.html
webgl-debug-renderer-info.html

View File

@ -0,0 +1,157 @@
<!--
Copyright (c) 2012 Florian Boesch <pyalot@gmail.com>. 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>
<html>
<head>
<meta charset="utf-8">
<title>WebGL EXT_texture_filter_anisotropic Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../resources/desktop-gl-constants.js" type="text/javascript"></script>
<script src="../../resources/js-test-pre.js"></script>
<script src="../resources/webgl-test.js"></script>
<script src="../resources/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
<div id="console"></div>
<script>
description("This test verifies the functionality of the EXT_texture_filter_anisotropic extension, if it is available.");
debug("");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = create3DContext(canvas);
var ext = null;
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
// Run tests with extension disabled
runHintTestDisabled();
// Query the extension and store globally so shouldBe can access it
ext = gl.getExtension("MOZ_EXT_texture_filter_anisotropic");
if (!ext) {
testPassed("No EXT_texture_filter_anisotropic support -- this is legal");
runSupportedTest(false);
} else {
testPassed("Successfully enabled EXT_texture_filter_anisotropic extension");
runSupportedTest(true);
runHintTestEnabled();
}
}
function runSupportedTest(extensionEnabled) {
var supported = gl.getSupportedExtensions();
if (supported.indexOf("MOZ_EXT_texture_filter_anisotropic") >= 0) {
if (extensionEnabled) {
testPassed("EXT_texture_filter_anisotropic listed as supported and getExtension succeeded");
} else {
testFailed("EXT_texture_filter_anisotropic listed as supported but getExtension failed");
}
} else {
if (extensionEnabled) {
testFailed("EXT_texture_filter_anisotropic not listed as supported but getExtension succeeded");
} else {
testPassed("EXt_texture_filter_anisotropic not listed as supported and getExtension failed -- this is legal");
}
}
}
function runHintTestDisabled() {
debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension disabled");
var MAX_TEXTURE_MAX_ANISOTROPY = 0x84FF;
gl.getParameter(MAX_TEXTURE_MAX_ANISOTROPY);
glErrorShouldBe(gl, gl.INVALID_ENUM, "MAX_TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
var TEXTURE_MAX_ANISOTROPY = 0x84FE;
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.getTexParameter(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY);
glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
gl.texParameterf(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
gl.texParameteri(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
gl.deleteTexture(texture);
}
function runHintTestEnabled() {
debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension enabled");
shouldBe("ext.MAX_TEXTURE_MAX_ANISOTROPY", "0x84FF");
var max_anisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY);
glErrorShouldBe(gl, gl.NO_ERROR, "MAX_TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
if(max_anisotropy >= 2){
testPassed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0");
}
else{
testFailed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0, returned values was: " + max_anisotropy);
}
// TODO make a texture and verify initial value == 1 and setting to less than 1 is invalid value
debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
shouldBe("ext.TEXTURE_MAX_ANISOTROPY", "0x84FE");
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
glErrorShouldBe(gl, gl.NO_ERROR, "TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
if(queried_value == 1){
testPassed("Initial value of TEXTURE_MAX_ANISOTROPY is 1.0");
}
else{
testFailed("Initial value of TEXTURE_MAX_ANISOTROPY should be 1.0, returned value was: " + queried_value);
}
gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameterf TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameteri TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
glErrorShouldBe(gl, gl.NO_ERROR, "texParameterf TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
glErrorShouldBe(gl, gl.NO_ERROR, "texParameteri TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
if(queried_value == max_anisotropy){
testPassed("Set value of TEXTURE_MAX_ANISOTROPY matches expecation");
}
else{
testFailed("Set value of TEXTURE_MAX_ANISOTROPY should be: " + max_anisotropy + " , returned value was: " + queried_value);
}
gl.deleteTexture(texture);
}
debug("");
successfullyParsed = true;
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>

View File

@ -0,0 +1,174 @@
diff --git a/content/canvas/test/webgl/conformance/extensions/00_test_list.txt b/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
--- a/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
+++ b/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
@@ -1,7 +1,8 @@
oes-standard-derivatives.html
+ext-texture-filter-anisotropic.html
oes-texture-float.html
oes-vertex-array-object.html
webgl-debug-renderer-info.html
webgl-debug-shaders.html
--min-version 1.0.2 webgl-experimental-compressed-textures.html
diff --git a/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html b/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
@@ -0,0 +1,157 @@
+<!--
+Copyright (c) 2012 Florian Boesch <pyalot@gmail.com>. 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>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_texture_filter_anisotropic Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../resources/desktop-gl-constants.js" type="text/javascript"></script>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../resources/webgl-test.js"></script>
+<script src="../resources/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+
+<script>
+description("This test verifies the functionality of the EXT_texture_filter_anisotropic extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = create3DContext(canvas);
+var ext = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ // Run tests with extension disabled
+ runHintTestDisabled();
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("MOZ_EXT_texture_filter_anisotropic");
+ if (!ext) {
+ testPassed("No EXT_texture_filter_anisotropic support -- this is legal");
+
+ runSupportedTest(false);
+ } else {
+ testPassed("Successfully enabled EXT_texture_filter_anisotropic extension");
+
+ runSupportedTest(true);
+ runHintTestEnabled();
+ }
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.indexOf("MOZ_EXT_texture_filter_anisotropic") >= 0) {
+ if (extensionEnabled) {
+ testPassed("EXT_texture_filter_anisotropic listed as supported and getExtension succeeded");
+ } else {
+ testFailed("EXT_texture_filter_anisotropic listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ testFailed("EXT_texture_filter_anisotropic not listed as supported but getExtension succeeded");
+ } else {
+ testPassed("EXt_texture_filter_anisotropic not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runHintTestDisabled() {
+ debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension disabled");
+
+ var MAX_TEXTURE_MAX_ANISOTROPY = 0x84FF;
+ gl.getParameter(MAX_TEXTURE_MAX_ANISOTROPY);
+ glErrorShouldBe(gl, gl.INVALID_ENUM, "MAX_TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
+
+ debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
+ var TEXTURE_MAX_ANISOTROPY = 0x84FE;
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ gl.getTexParameter(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY);
+ glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
+
+ gl.texParameterf(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
+ glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
+
+ gl.texParameteri(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
+ glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
+
+ gl.deleteTexture(texture);
+}
+
+function runHintTestEnabled() {
+ debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension enabled");
+
+ shouldBe("ext.MAX_TEXTURE_MAX_ANISOTROPY", "0x84FF");
+
+ var max_anisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY);
+ glErrorShouldBe(gl, gl.NO_ERROR, "MAX_TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
+
+ if(max_anisotropy >= 2){
+ testPassed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0");
+ }
+ else{
+ testFailed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0, returned values was: " + max_anisotropy);
+ }
+
+ // TODO make a texture and verify initial value == 1 and setting to less than 1 is invalid value
+
+ debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
+ shouldBe("ext.TEXTURE_MAX_ANISOTROPY", "0x84FE");
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
+ glErrorShouldBe(gl, gl.NO_ERROR, "TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
+
+ if(queried_value == 1){
+ testPassed("Initial value of TEXTURE_MAX_ANISOTROPY is 1.0");
+ }
+ else{
+ testFailed("Initial value of TEXTURE_MAX_ANISOTROPY should be 1.0, returned value was: " + queried_value);
+ }
+
+ gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameterf TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
+
+ gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameteri TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
+
+ gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
+ glErrorShouldBe(gl, gl.NO_ERROR, "texParameterf TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
+
+ gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
+ glErrorShouldBe(gl, gl.NO_ERROR, "texParameteri TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
+
+ var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
+ if(queried_value == max_anisotropy){
+ testPassed("Set value of TEXTURE_MAX_ANISOTROPY matches expecation");
+ }
+ else{
+ testFailed("Set value of TEXTURE_MAX_ANISOTROPY should be: " + max_anisotropy + " , returned value was: " + queried_value);
+ }
+
+ gl.deleteTexture(texture);
+}
+
+debug("");
+successfullyParsed = true;
+</script>
+<script src="../../resources/js-test-post.js"></script>
+
+</body>
+</html>

View File

@ -808,7 +808,7 @@ nsHTMLSelectElement::SetLength(PRUint32 aLength)
if (i + 1 < aLength) {
nsCOMPtr<nsIDOMNode> newNode;
rv = node->CloneNode(true, getter_AddRefs(newNode));
rv = node->CloneNode(true, 1, getter_AddRefs(newNode));
NS_ENSURE_SUCCESS(rv, rv);
node = newNode;

View File

@ -849,15 +849,11 @@ nsTextInputListener::EditAction()
nsCOMPtr<nsIEditor> editor;
frame->GetEditor(getter_AddRefs(editor));
nsCOMPtr<nsITransactionManager> manager;
editor->GetTransactionManager(getter_AddRefs(manager));
NS_ENSURE_TRUE(manager, NS_ERROR_FAILURE);
// Get the number of undo / redo items
PRInt32 numUndoItems = 0;
PRInt32 numRedoItems = 0;
manager->GetNumberOfUndoItems(&numUndoItems);
manager->GetNumberOfRedoItems(&numRedoItems);
editor->GetNumberOfUndoItems(&numUndoItems);
editor->GetNumberOfRedoItems(&numRedoItems);
if ((numUndoItems && !mHadUndoItems) || (!numUndoItems && mHadUndoItems) ||
(numRedoItems && !mHadRedoItems) || (!numRedoItems && mHadRedoItems)) {
// Modify the menu if undo or redo items are different

View File

@ -94,7 +94,8 @@ nsSMILAnimationFunction::nsSMILAnimationFunction()
mLastValue(false),
mHasChanged(true),
mValueNeedsReparsingEverySample(false),
mPrevSampleWasSingleValueAnimation(false)
mPrevSampleWasSingleValueAnimation(false),
mWasSkippedInPrevSample(false)
{
}
@ -233,6 +234,7 @@ nsSMILAnimationFunction::ComposeResult(const nsISMILAttr& aSMILAttr,
{
mHasChanged = false;
mPrevSampleWasSingleValueAnimation = false;
mWasSkippedInPrevSample = false;
// Skip animations that are inactive or in error
if (!IsActiveOrFrozen() || mErrorFlags != 0)

View File

@ -247,6 +247,24 @@ public:
*/
bool UpdateCachedTarget(const nsSMILTargetIdentifier& aNewTarget);
/**
* Returns true if this function was skipped in the previous sample (because
* there was a higher-priority non-additive animation). If a skipped animation
* function is later used, then the animation sandwich must be recomposited.
*/
bool WasSkippedInPrevSample() const {
return mWasSkippedInPrevSample;
}
/**
* Mark this animation function as having been skipped. By marking the
* function as skipped, if it is used in a subsequent sample we'll know to
* recomposite the sandwich.
*/
void SetWasSkipped() {
mWasSkippedInPrevSample = true;
}
// Comparator utility class, used for sorting nsSMILAnimationFunctions
class Comparator {
public:
@ -466,12 +484,13 @@ protected:
nsSMILWeakTargetIdentifier mLastTarget;
// Boolean flags
bool mIsActive:1;
bool mIsFrozen:1;
bool mLastValue:1;
bool mHasChanged:1;
bool mValueNeedsReparsingEverySample:1;
bool mPrevSampleWasSingleValueAnimation:1;
bool mIsActive:1;
bool mIsFrozen:1;
bool mLastValue:1;
bool mHasChanged:1;
bool mValueNeedsReparsingEverySample:1;
bool mPrevSampleWasSingleValueAnimation:1;
bool mWasSkippedInPrevSample:1;
};
#endif // NS_SMILANIMATIONFUNCTION_H_

View File

@ -173,16 +173,31 @@ nsSMILCompositor::GetFirstFuncToAffectSandwich()
PRUint32 i;
for (i = mAnimationFunctions.Length(); i > 0; --i) {
nsSMILAnimationFunction* curAnimFunc = mAnimationFunctions[i-1];
if (curAnimFunc->UpdateCachedTarget(mKey) ||
(!mForceCompositing && curAnimFunc->HasChanged())) {
mForceCompositing = true;
}
// In the following, the lack of short-circuit behavior of |= means that we
// will ALWAYS run UpdateCachedTarget (even if mForceCompositing is true)
// but only call HasChanged and WasSkippedInPrevSample if necessary. This
// is important since we need UpdateCachedTarget to run in order to detect
// changes to the target in subsequent samples.
mForceCompositing |=
curAnimFunc->UpdateCachedTarget(mKey) ||
curAnimFunc->HasChanged() ||
curAnimFunc->WasSkippedInPrevSample();
if (curAnimFunc->WillReplace()) {
--i;
break;
}
}
// Mark remaining animation functions as having been skipped so if we later
// use them we'll know to force compositing.
// Note that we only really need to do this if something has changed
// (otherwise we would have set the flag on a previous sample) and if
// something has changed mForceCompositing will be true.
if (mForceCompositing) {
for (PRUint32 j = i; j > 0; --j) {
mAnimationFunctions[j-1]->SetWasSkipped();
}
}
return i;
}

View File

@ -131,7 +131,7 @@ public:
bool mForceCompositing;
// Cached base value, so we can detect & force-recompose when it changes
// from one sample to the next. (nsSMILAnimationController copies this
// from one sample to the next. (nsSMILAnimationController copies this
// forward from the previous sample's compositor.)
nsAutoPtr<nsSMILValue> mCachedBaseValue;
};

View File

@ -615,11 +615,6 @@ nsSMILParserUtils::ParseValuesGeneric(const nsAString& aSpec,
}
}
// Disallow ;-terminated values lists.
if (tokenizer.lastTokenEndedWithSeparator()) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}

View File

@ -55,6 +55,7 @@
#include "nsString.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/Util.h"
#include "nsCharSeparatedTokenizer.h"
using namespace mozilla;
@ -1271,10 +1272,6 @@ nsSMILTimedElement::SetBeginOrEndSpec(const nsAString& aSpec,
bool aIsBegin,
RemovalTestFunction aRemove)
{
PRInt32 start;
PRInt32 end = -1;
PRInt32 length;
nsresult rv = NS_OK;
TimeValueSpecList& timeSpecsList = aIsBegin ? mBeginSpecs : mEndSpecs;
InstanceTimeList& instances = aIsBegin ? mBeginInstances : mEndInstances;
@ -1282,17 +1279,20 @@ nsSMILTimedElement::SetBeginOrEndSpec(const nsAString& aSpec,
AutoIntervalUpdateBatcher updateBatcher(*this);
do {
start = end + 1;
end = aSpec.FindChar(';', start);
length = (end == -1) ? -1 : end - start;
nsCharSeparatedTokenizer tokenizer(aSpec, ';');
if (!tokenizer.hasMoreTokens()) { // Empty list
return NS_ERROR_FAILURE;
}
nsresult rv = NS_OK;
while (tokenizer.hasMoreTokens() && NS_SUCCEEDED(rv)) {
nsAutoPtr<nsSMILTimeValueSpec>
spec(new nsSMILTimeValueSpec(*this, aIsBegin));
rv = spec->SetSpec(Substring(aSpec, start, length), aContextNode);
rv = spec->SetSpec(tokenizer.nextToken(), aContextNode);
if (NS_SUCCEEDED(rv)) {
timeSpecsList.AppendElement(spec.forget());
}
} while (end != -1 && NS_SUCCEEDED(rv));
}
if (NS_FAILED(rv)) {
ClearSpecs(timeSpecsList, instances, aRemove);

View File

@ -91,6 +91,7 @@ _TEST_FILES = \
test_smilTiming.xhtml \
test_smilTimingZeroIntervals.xhtml \
test_smilUpdatedInterval.xhtml \
test_smilValues.xhtml \
test_smilXHR.xhtml \
$(NULL)

View File

@ -40,6 +40,8 @@
/* Lists of valid & invalid values for the various <animateMotion> attributes */
const gValidValues = [
"10 10",
"10 10;", // Trailing semicolons are allowed
"10 10; ",
" 10 10em ",
"1 2 ; 3,4",
"1,2;3,4",
@ -49,7 +51,6 @@ const gValidValues = [
const gInvalidValues = [
";10 10",
"10 10;", // We treat semicolon-terminated value-lists as failure cases
"10 10;;",
"1 2 3",
"1 2 3 4",
@ -128,3 +129,30 @@ const gValidPathWithErrors = [
"m0 0 L30,,30",
"M10 10 L50 50 abc",
];
const gValidKeyPoints = [
"0; 0.5; 1",
"0;.5;1",
"0; 0; 1",
"0; 1; 1",
"0; 0; 1;", // Trailing semicolons are allowed
"0; 0; 1; ",
"0; 0.000; 1",
"0; 0.000001; 1",
];
const gInvalidKeyPoints = [
"0; 1",
"0; 1;",
"0",
"1",
"a",
"",
" ",
"0; -0.1; 1",
"0; 1.1; 1",
"0; 0.1; 1.1",
"-0.1; 0.1; 1",
"0; a; 1",
"0;;1",
];

View File

@ -64,6 +64,13 @@ function testAttr(aAttrName, aAttrValueArray, aIsValid, aIsTodo)
// our value is rejected.
anim.setAttribute("rotate", Math.PI/4);
componentsToCheck = CTMUtil.CTM_COMPONENTS_ALL;
if (aAttrName == "keyPoints") {
// Add three times so we can test a greater range of values for
// keyPoints
anim.setAttribute("values", "0 0; 25 25; 50 50");
anim.setAttribute("keyTimes", "0; 0.5; 1");
anim.setAttribute("calcMode", "discrete");
}
}
var curCTM = gRect.getCTM();
@ -158,6 +165,9 @@ function main()
testAttr("path", gInvalidPath, false, false);
testAttr("path", gValidPathWithErrors, true, false);
testAttr("keyPoints", gValidKeyPoints, true, false);
testAttr("keyPoints", gInvalidKeyPoints, false, false);
testMpathElem(gValidPath, true, false);
testMpathElem(gInvalidPath, false, false);

View File

@ -18,91 +18,268 @@
/** Test for SMIL timing **/
/* Global Variables */
const svgns="http://www.w3.org/2000/svg";
var svg = document.getElementById("svg");
var circle = document.getElementById('circle');
const svgns = "http://www.w3.org/2000/svg";
var gSvg = document.getElementById("svg");
var gCircle = document.getElementById('circle');
SimpleTest.waitForExplicitFinish();
function createAnim() {
function main() {
ok(gSvg.animationsPaused(), "should be paused by <svg> load handler");
is(gSvg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
var testCases = Array();
const secPerMin = 60;
const secPerHour = secPerMin * 60;
// In the following tests that compare start times, getStartTime will round
// the start time to three decimal places since we expect our implementation
// to be millisecond accurate.
// Offset syntax
// -- Basic tests, sign and whitespace
testCases.push(StartTimeTest('3s', 3));
testCases.push(StartTimeTest('0s', 0));
testCases.push(StartTimeTest('+2s', 2));
testCases.push(StartTimeTest('-1s\t\r', -1));
testCases.push(StartTimeTest('- 1s', -1));
testCases.push(StartTimeTest(' -1s', -1));
testCases.push(StartTimeTest(' - 1s', -1));
testCases.push(StartTimeTest(' \t\n\r-1s', -1));
testCases.push(StartTimeTest('+\n5s', 5));
testCases.push(StartTimeTest('-\n5s', -5));
testCases.push(StartTimeTest('\t 5s', 5));
// -- These tests are from SMILANIM 3.6.7
testCases.push(StartTimeTest('02:30:03', 2*secPerHour + 30*secPerMin + 3));
testCases.push(StartTimeTest('50:00:10.25', 50*secPerHour + 10.25));
testCases.push(StartTimeTest('02:33', 2*secPerMin + 33));
testCases.push(StartTimeTest('00:10.5', 10.5));
testCases.push(StartTimeTest('3.2h', 3.2*secPerHour));
testCases.push(StartTimeTest('45min', 45*secPerMin));
testCases.push(StartTimeTest('30s', 30));
testCases.push(StartTimeTest('5ms', 0.005));
testCases.push(StartTimeTest('12.467', 12.467));
testCases.push(StartTimeTest('00.5s', 0.5));
testCases.push(StartTimeTest('00:00.005', 0.005));
// -- Additional tests
testCases.push(StartTimeTest('61:59:59', 61*secPerHour + 59*secPerMin + 59));
testCases.push(StartTimeTest('02:59.999999999999999999999', 3*secPerMin));
testCases.push(StartTimeTest('1234:23:45',
1234*secPerHour + 23*secPerMin + 45));
testCases.push(StartTimeTest('61min', 61*secPerMin));
testCases.push(StartTimeTest('0:30:03', 30*secPerMin + 3));
// -- Fractional precision
testCases.push(StartTimeTest('25.4567', 25.457));
testCases.push(StartTimeTest('0.123456789', 0.123));
testCases.push(StartTimeTest('0.00000000000000000000001', 0));
testCases.push(StartTimeTest('-0.00000000000000000000001', 0));
testCases.push(StartTimeTest('0.0009', 0.001));
testCases.push(StartTimeTest('0.99999999999999999999999999999999999999', 1));
testCases.push(StartTimeTest('23.4567ms', 0.023));
testCases.push(StartTimeTest('23.7ms', 0.024));
// -- Test errors
testCases.push(StartTimeTest(' + +3s', 'none'));
testCases.push(StartTimeTest(' +-3s', 'none'));
testCases.push(StartTimeTest('1:12:12:12', 'none'));
testCases.push(StartTimeTest('4:50:60', 'none'));
testCases.push(StartTimeTest('4:60:0', 'none'));
testCases.push(StartTimeTest('4:60', 'none'));
testCases.push(StartTimeTest('4:-1:00', 'none'));
testCases.push(StartTimeTest('4 5m', 'none'));
testCases.push(StartTimeTest('4 5ms', 'none'));
testCases.push(StartTimeTest('02:3:03', 'none'));
testCases.push(StartTimeTest('45.7 s', 'none'));
testCases.push(StartTimeTest(' 3 h ', 'none'));
testCases.push(StartTimeTest('2:33 ', 'none'));
testCases.push(StartTimeTest('02:33 2', 'none'));
testCases.push(StartTimeTest('\u000B 02:33', 'none'));
testCases.push(StartTimeTest('h', 'none'));
testCases.push(StartTimeTest('23.s', 'none'));
testCases.push(StartTimeTest('23.', 'none'));
testCases.push(StartTimeTest('23.54.2s', 'none'));
testCases.push(StartTimeTest('23sec', 'none'));
testCases.push(StartTimeTest('five', 'none'));
testCases.push(StartTimeTest('', 'none'));
testCases.push(StartTimeTest('02:33s', 'none'));
testCases.push(StartTimeTest('02:33 s', 'none'));
testCases.push(StartTimeTest('2.54e6', 'none'));
testCases.push(StartTimeTest('02.5:33', 'none'));
testCases.push(StartTimeTest('2:-45:33', 'none'));
testCases.push(StartTimeTest('2:4.5:33', 'none'));
testCases.push(StartTimeTest('45m', 'none'));
testCases.push(StartTimeTest(':20:30', 'none'));
testCases.push(StartTimeTest('1.5:30', 'none'));
testCases.push(StartTimeTest('15:-30', 'none'));
testCases.push(StartTimeTest('::30', 'none'));
testCases.push(StartTimeTest('15:30s', 'none'));
testCases.push(StartTimeTest('2:1.:30', 'none'));
testCases.push(StartTimeTest('2:.1:30', 'none'));
testCases.push(StartTimeTest('2.0:15:30', 'none'));
testCases.push(StartTimeTest('2.:15:30', 'none'));
testCases.push(StartTimeTest('.2:15:30', 'none'));
testCases.push(StartTimeTest('70:15', 'none'));
testCases.push(StartTimeTest('media', 'none'));
testCases.push(StartTimeTest('5mi', 'none'));
testCases.push(StartTimeTest('5hours', 'none'));
testCases.push(StartTimeTest('h05:30', 'none'));
testCases.push(StartTimeTest('05:40\x9A', 'none'));
testCases.push(StartTimeTest('05:40\u30D5', 'none'));
testCases.push(StartTimeTest('05:40β', 'none'));
// List syntax
testCases.push(StartTimeTest('3', 3));
testCases.push(StartTimeTest('3;', 3));
testCases.push(StartTimeTest('3; ', 3));
testCases.push(StartTimeTest('3 ; ', 3));
testCases.push(StartTimeTest('3;;', 'none'));
testCases.push(StartTimeTest('3;; ', 'none'));
testCases.push(StartTimeTest(';3', 'none'));
testCases.push(StartTimeTest(' ;3', 'none'));
testCases.push(StartTimeTest('3;4', 3));
testCases.push(StartTimeTest(' 3 ; 4 ', 3));
// List syntax on end times
testCases.push({
'attr' : { 'begin': '0s',
'end': '1s; 2s' },
'times': [ [ 0, 0 ],
[ 1, -100 ] ]
});
testCases.push({
'attr' : { 'begin': '0s',
'end': '1s; 2s; ' },
'times': [ [ 0, 0 ],
[ 1, -100 ] ]
});
testCases.push({
'attr' : { 'begin': '0s',
'end': '3s; 2s' },
'times': [ [ 0, 0 ],
[ 1, 10 ],
[ 2, -100 ] ]
});
// Simple case
testCases.push({
'attr' : { 'begin': '3s' },
'times': [ [ 0, -100 ],
[ 4, 10 ] ]
});
// Multiple begins
testCases.push({
'attr' : { 'begin': '2s; 6s',
'dur': '2s' },
'times': [ [ 0, -100 ],
[ 3, 50 ],
[ 4, -100 ],
[ 7, 50 ],
[ 8, -100 ] ]
});
// Negative begins
testCases.push({
'attr' : { 'begin': '-3s; 1s ; 4s',
'dur': '2s ',
'fill': 'freeze' },
'times': [ [ 0, -100 ],
[ 0.5, -100 ],
[ 1, 0 ],
[ 2, 50 ],
[ 3, 100 ],
[ 5, 50 ] ]
});
// Sorting
testCases.push({
'attr' : { 'begin': '-3s; 110s; 1s; 4s; -5s; -10s',
'end': '111s; -5s; -15s; 6s; -5s; 1.2s',
'dur': '2s ',
'fill': 'freeze' },
'times': [ [ 0, -100 ],
[ 1, 0 ],
[ 2, 10 ],
[ 4, 0 ],
[ 5, 50 ],
[ 109, 100 ],
[ 110, 0 ],
[ 112, 50 ] ]
});
for (var i = 0; i < testCases.length; i++) {
gSvg.setCurrentTime(0);
var test = testCases[i];
// Generate string version of params for output messages
var params = "";
for (var name in test.attr) {
params += name + '="' + test.attr[name] + '" ';
}
params = params.trim();
// Create animation elements
var anim = createAnim(test.attr);
// Run samples
if ('times' in test) {
for (var j = 0; j < test.times.length; j++) {
var curSample = test.times[j];
checkSample(curSample[0], curSample[1], params);
}
}
// Check start time
if ('startTime' in test) {
is(getStartTime(anim), test.startTime,
"Got unexpected start time for " + params);
}
anim.parentNode.removeChild(anim);
}
SimpleTest.finish();
}
function createAnim(attr) {
var anim = document.createElementNS(svgns,'animate');
anim.setAttribute('attributeName','cx');
anim.setAttribute('from','0');
anim.setAttribute('to','100');
anim.setAttribute('dur','10s');
anim.setAttribute('begin','indefinite');
return circle.appendChild(anim);
}
function removeAnim(anim) {
anim.parentNode.removeChild(anim);
}
function main() {
ok(svg.animationsPaused(), "should be paused by <svg> load handler");
is(svg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
var tests =
[ testOffsetStartup,
testMultipleBegins,
testNegativeBegins,
testSorting
];
for (var i = 0; i < tests.length; i++) {
var anim = createAnim();
svg.setCurrentTime(0);
tests[i](anim);
removeAnim(anim);
for (name in attr) {
anim.setAttribute(name, attr[name]);
}
SimpleTest.finish();
return gCircle.appendChild(anim);
}
function checkSample(time, expectedValue) {
svg.setCurrentTime(time);
is(circle.cx.animVal.value, expectedValue);
function checkSample(time, expectedValue, params) {
gSvg.setCurrentTime(time);
var msg = "Unexpected sample value for " + params +
" at t=" + time + ": ";
is(gCircle.cx.animVal.value, expectedValue);
}
function testOffsetStartup(anim) {
anim.setAttribute('begin', '3s');
checkSample(0,-100);
checkSample(4,10);
function getStartTime(anim) {
var startTime;
try {
startTime = anim.getStartTime();
// We round start times to 3 decimal places to make comparisons simpler
startTime = parseFloat(startTime.toFixed(3));
} catch(e) {
if (e.code == DOMException.INVALID_STATE_ERR) {
startTime = 'none';
} else {
ok(false, "Unexpected exception: " + e);
}
}
return startTime;
}
function testMultipleBegins(anim) {
anim.setAttribute('begin', '2s; 6s');
anim.setAttribute('dur', ' 2s');
checkSample(0,-100);
checkSample(3,50);
checkSample(4,-100);
checkSample(7,50);
checkSample(8,-100);
}
function testNegativeBegins(anim) {
anim.setAttribute('begin', '-3s; 1s ; 4s');
anim.setAttribute('dur', '2s ');
anim.setAttribute('fill', 'freeze');
checkSample(0,-100);
checkSample(0.5,-100);
checkSample(1,0);
checkSample(2,50);
checkSample(3,100);
checkSample(5,50);
}
function testSorting(anim) {
anim.setAttribute('begin', '-3s; 110s; 1s; 4s; -5s; -10s');
anim.setAttribute('end', '111s; -5s; -15s; 6s; -5s; 1.2s');
anim.setAttribute('dur', '2s ');
anim.setAttribute('fill', 'freeze');
checkSample(0,-100);
checkSample(1,0);
checkSample(2,10);
checkSample(4,0);
checkSample(5,50);
checkSample(109,100);
checkSample(110,0);
checkSample(112,50);
function StartTimeTest(beginSpec, expectedStartTime) {
return { 'attr' : { 'begin': beginSpec },
'startTime': expectedStartTime };
}
window.addEventListener("load", main, false);

View File

@ -0,0 +1,170 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test for SMIL values</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=557885">Mozilla Bug
474742</a>
<p id="display"></p>
<div id="content" style="display: none">
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px">
<circle cx="-100" cy="20" r="15" fill="blue" id="circle"/>
</svg>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
/** Test for SMIL values **/
var gSvg = document.getElementById("svg");
SimpleTest.waitForExplicitFinish();
function main()
{
gSvg.pauseAnimations();
var testCases = Array();
// Single value
testCases.push({
'attr' : { 'values': 'a' },
'times': [ [ 0, 'a' ] ]
});
// The parsing below is based on the following discussion:
//
// http://lists.w3.org/Archives/Public/www-svg/2011Nov/0136.html
//
// In summary:
// * Values lists are semi-colon delimited and semi-colon terminated.
// * However, if there are extra non-whitespace characters after the final
// semi-colon then there's an implied semi-colon at the end.
//
// This differs to what is specified in SVG 1.1 but is consistent with the
// majority of browsers and with existing content (particularly that generated
// by Ikivo Animator).
// Trailing semi-colon
testCases.push({
'attr' : { 'values': 'a;' },
'times': [ [ 0, 'a' ], [ 10, 'a' ] ]
});
// Trailing semi-colon + whitespace
testCases.push({
'attr' : { 'values': 'a; ' },
'times': [ [ 0, 'a' ], [ 10, 'a' ] ]
});
// Whitespace + trailing semi-colon
testCases.push({
'attr' : { 'values': 'a ;' },
'times': [ [ 0, 'a' ], [ 10, 'a' ] ]
});
// Empty at end
testCases.push({
'attr' : { 'values': 'a;;' },
'times': [ [ 0, 'a' ], [ 5, '' ], [ 10, '' ] ]
});
// Empty at end + whitespace
testCases.push({
'attr' : { 'values': 'a;; ' },
'times': [ [ 0, 'a' ], [ 4, 'a' ], [ 5, '' ], [ 10, '' ] ]
});
// Empty in middle
testCases.push({
'attr' : { 'values': 'a;;b' },
'times': [ [ 0, 'a' ], [ 5, '' ], [ 10, 'b' ] ]
});
// Empty in middle + trailing semi-colon
testCases.push({
'attr' : { 'values': 'a;;b;' },
'times': [ [ 0, 'a' ], [ 5, '' ], [ 10, 'b' ] ]
});
// Whitespace in middle
testCases.push({
'attr' : { 'values': 'a; ;b' },
'times': [ [ 0, 'a' ], [ 5, '' ], [ 10, 'b' ] ]
});
// Empty at start
testCases.push({
'attr' : { 'values': ';a' },
'times': [ [ 0, '' ], [ 5, 'a' ], [ 10, 'a' ] ]
});
// Whitespace at start
testCases.push({
'attr' : { 'values': ' ;a' },
'times': [ [ 0, '' ], [ 5, 'a' ], [ 10, 'a' ] ]
});
// Embedded whitespace
testCases.push({
'attr' : { 'values': ' a b ; c d ' },
'times': [ [ 0, 'a b' ], [ 5, 'c d' ], [ 10, 'c d' ] ]
});
// Whitespace only
testCases.push({
'attr' : { 'values': ' ' },
'times': [ [ 0, '' ], [ 10, '' ] ]
});
for (var i = 0; i < testCases.length; i++) {
gSvg.setCurrentTime(0);
var test = testCases[i];
// Create animation elements
var anim = createAnim(test.attr);
// Run samples
for (var j = 0; j < test.times.length; j++) {
var curSample = test.times[j];
gSvg.setCurrentTime(curSample[0]);
checkSample(anim, curSample[1], curSample[0], i);
}
anim.parentNode.removeChild(anim);
}
SimpleTest.finish();
}
function createAnim(attr)
{
const svgns = "http://www.w3.org/2000/svg";
var anim = document.createElementNS(svgns, 'animate');
anim.setAttribute('attributeName','class');
anim.setAttribute('dur','10s');
anim.setAttribute('begin','0s');
anim.setAttribute('fill','freeze');
for (name in attr) {
anim.setAttribute(name, attr[name]);
}
return document.getElementById('circle').appendChild(anim);
}
function checkSample(anim, expectedValue, sampleTime, caseNum)
{
var msg = "Test case " + caseNum +
" (values: '" + anim.getAttribute('values') + "')," +
"t=" + sampleTime +
": Unexpected sample value:";
is(anim.targetElement.className.animVal, expectedValue, msg);
}
window.addEventListener("load", main, false);
]]>
</script>
</pre>
</body>
</html>

View File

@ -447,7 +447,7 @@ SVGMotionSMILAnimationFunction::SetKeyPoints(const nsAString& aKeyPoints,
void
SVGMotionSMILAnimationFunction::UnsetKeyPoints()
{
mKeyTimes.Clear();
mKeyPoints.Clear();
SetKeyPointsErrorFlag(false);
mHasChanged = true;
}

View File

@ -153,7 +153,7 @@ NS_IMETHODIMP nsXPathNamespace::HasChildNodes(bool *aResult)
}
/* nsIDOMNode cloneNode (in boolean deep); */
NS_IMETHODIMP nsXPathNamespace::CloneNode(bool deep, nsIDOMNode **aResult)
NS_IMETHODIMP nsXPathNamespace::CloneNode(bool deep, PRUint8 aOptionalArgc, nsIDOMNode **aResult)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -677,7 +677,7 @@ nsXULContentBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode,
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMNode> clonedNode;
tmplTextNode->CloneNode(false, getter_AddRefs(clonedNode));
tmplTextNode->CloneNode(false, 1, getter_AddRefs(clonedNode));
nsCOMPtr<nsIContent> clonedContent = do_QueryInterface(clonedNode);
if (!clonedContent) {
NS_ERROR("failed to clone textnode");

View File

@ -2310,34 +2310,6 @@ nsDocShell::HistoryTransactionRemoved(PRInt32 aIndex)
return NS_OK;
}
static
nsresult
GetPrincipalDomain(nsIPrincipal* aPrincipal, nsACString& aDomain)
{
aDomain.Truncate();
nsCOMPtr<nsIURI> codebaseURI;
nsresult rv = aPrincipal->GetDomain(getter_AddRefs(codebaseURI));
NS_ENSURE_SUCCESS(rv, rv);
if (!codebaseURI) {
rv = aPrincipal->GetURI(getter_AddRefs(codebaseURI));
NS_ENSURE_SUCCESS(rv, rv);
}
if (!codebaseURI)
return NS_OK;
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(codebaseURI);
NS_ASSERTION(innerURI, "Failed to get innermost URI");
NS_ENSURE_SUCCESS(rv, rv);
rv = innerURI->GetAsciiHost(aDomain);
if (NS_FAILED(rv))
return rv;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
const nsAString& aDocumentURI,
@ -2367,15 +2339,15 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
aCreate,
aStorage);
nsCAutoString currentDomain;
rv = GetPrincipalDomain(aPrincipal, currentDomain);
nsXPIDLCString origin;
rv = aPrincipal->GetOrigin(getter_Copies(origin));
if (NS_FAILED(rv))
return rv;
if (currentDomain.IsEmpty())
if (origin.IsEmpty())
return NS_OK;
if (!mStorages.Get(currentDomain, aStorage) && aCreate) {
if (!mStorages.Get(origin, aStorage) && aCreate) {
nsCOMPtr<nsIDOMStorage> newstorage =
do_CreateInstance("@mozilla.org/dom/storage;2");
if (!newstorage)
@ -2384,11 +2356,12 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
nsCOMPtr<nsPIDOMStorage> pistorage = do_QueryInterface(newstorage);
if (!pistorage)
return NS_ERROR_FAILURE;
rv = pistorage->InitAsSessionStorage(aPrincipal, aDocumentURI);
if (NS_FAILED(rv))
return rv;
if (!mStorages.Put(currentDomain, newstorage))
if (!mStorages.Put(origin, newstorage))
return NS_ERROR_OUT_OF_MEMORY;
newstorage.swap(*aStorage);
@ -2399,22 +2372,32 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
#endif
}
else if (*aStorage) {
nsCOMPtr<nsPIDOMStorage> piStorage = do_QueryInterface(*aStorage);
if (piStorage) {
bool canAccess = piStorage->CanAccess(aPrincipal);
NS_ASSERTION(canAccess,
"GetSessionStorageForPrincipal got a storage "
"that could not be accessed!");
if (!canAccess) {
NS_RELEASE(*aStorage);
return NS_ERROR_DOM_SECURITY_ERR;
}
}
nsCOMPtr<nsPIDOMStorage> piStorage = do_QueryInterface(*aStorage);
if (piStorage) {
nsCOMPtr<nsIPrincipal> storagePrincipal = piStorage->Principal();
// The origin string used to map items in the hash table is
// an implicit security check. That check is double-confirmed
// by checking the principal a storage was demanded for
// really is the principal for which that storage was originally
// created. Originally, the check was hidden in the CanAccess
// method but it's implementation has changed.
bool equals;
nsresult rv = aPrincipal->EqualsIgnoringDomain(storagePrincipal, &equals);
NS_ASSERTION(NS_SUCCEEDED(rv) && equals,
"GetSessionStorageForPrincipal got a storage "
"that could not be accessed!");
if (NS_FAILED(rv) || !equals) {
NS_RELEASE(*aStorage);
return NS_ERROR_DOM_SECURITY_ERR;
}
}
#if defined(PR_LOGGING) && defined(DEBUG)
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsDocShell[%p]: returns existing sessionStorage %p",
this, *aStorage));
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsDocShell[%p]: returns existing sessionStorage %p",
this, *aStorage));
#endif
}
@ -2499,16 +2482,16 @@ nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal,
if (topItem) {
nsCOMPtr<nsIDocShell> topDocShell = do_QueryInterface(topItem);
if (topDocShell == this) {
nsCAutoString currentDomain;
rv = GetPrincipalDomain(aPrincipal, currentDomain);
nsXPIDLCString origin;
rv = aPrincipal->GetOrigin(getter_Copies(origin));
if (NS_FAILED(rv))
return rv;
if (currentDomain.IsEmpty())
if (origin.IsEmpty())
return NS_ERROR_FAILURE;
// Do not replace an existing session storage.
if (mStorages.GetWeak(currentDomain))
if (mStorages.GetWeak(origin))
return NS_ERROR_NOT_AVAILABLE;
#if defined(PR_LOGGING) && defined(DEBUG)
@ -2516,7 +2499,7 @@ nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal,
("nsDocShell[%p]: was added a sessionStorage %p",
this, aStorage));
#endif
if (!mStorages.Put(currentDomain, aStorage))
if (!mStorages.Put(origin, aStorage))
return NS_ERROR_OUT_OF_MEMORY;
}
else {

173
dom/base/DOMRequest.cpp Normal file
View File

@ -0,0 +1,173 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DOMRequest.h"
#include "mozilla/Util.h"
#include "nsDOMClassInfo.h"
#include "DOMError.h"
#include "nsEventDispatcher.h"
#include "nsIPrivateDOMEvent.h"
#include "nsDOMEvent.h"
using mozilla::dom::DOMRequest;
using mozilla::dom::DOMRequestService;
DOMRequest::DOMRequest(nsIDOMWindow* aWindow)
: mDone(false)
, mResult(JSVAL_VOID)
, mRooted(false)
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
mOwner = window->IsInnerWindow() ? window.get() :
window->GetCurrentInnerWindow();
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aWindow);
mScriptContext = sgo->GetContext();
}
DOMCI_DATA(DOMRequest, DOMRequest)
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMRequest,
nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(success)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(error)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMRequest,
nsDOMEventTargetHelper)
tmp->mResult = JSVAL_VOID;
tmp->UnrootResultVal();
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(success)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(error)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DOMRequest,
nsDOMEventTargetHelper)
// Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
// nsDOMEventTargetHelper does it for us.
if (JSVAL_IS_GCTHING(tmp->mResult)) {
void *gcThing = JSVAL_TO_GCTHING(tmp->mResult);
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mResult")
}
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMRequest)
NS_INTERFACE_MAP_ENTRY(nsIDOMDOMRequest)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMRequest)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(DOMRequest, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(DOMRequest, nsDOMEventTargetHelper)
NS_IMPL_EVENT_HANDLER(DOMRequest, success);
NS_IMPL_EVENT_HANDLER(DOMRequest, error);
NS_IMETHODIMP
DOMRequest::GetReadyState(nsAString& aReadyState)
{
mDone ? aReadyState.AssignLiteral("done") :
aReadyState.AssignLiteral("pending");
return NS_OK;
}
NS_IMETHODIMP
DOMRequest::GetResult(jsval* aResult)
{
NS_ASSERTION(mDone || mResult == JSVAL_VOID,
"Result should be undefined when pending");
*aResult = mResult;
return NS_OK;
}
NS_IMETHODIMP
DOMRequest::GetError(nsIDOMDOMError** aError)
{
NS_ASSERTION(mDone || !mError,
"Error should be null when pending");
NS_IF_ADDREF(*aError = mError);
return NS_OK;
}
void
DOMRequest::FireSuccess(jsval aResult)
{
NS_ABORT_IF_FALSE(!mDone, "Already fired success/error");
mDone = true;
RootResultVal();
mResult = aResult;
FireEvent(NS_LITERAL_STRING("success"));
}
void
DOMRequest::FireError(const nsAString& aError)
{
NS_ABORT_IF_FALSE(!mDone, "Already fired success/error");
mDone = true;
mError = DOMError::CreateWithName(aError);
FireEvent(NS_LITERAL_STRING("error"));
}
void
DOMRequest::FireEvent(const nsAString& aType)
{
if (NS_FAILED(CheckInnerWindowCorrectness())) {
return;
}
nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
nsresult rv = event->InitEvent(aType, false, false);
if (NS_FAILED(rv)) {
return;
}
rv = event->SetTrusted(PR_TRUE);
if (NS_FAILED(rv)) {
return;
}
bool dummy;
DispatchEvent(event, &dummy);
}
NS_IMPL_ISUPPORTS1(DOMRequestService, nsIDOMRequestService)
NS_IMETHODIMP
DOMRequestService::CreateRequest(nsIDOMWindow* aWindow,
nsIDOMDOMRequest** aRequest)
{
NS_ADDREF(*aRequest = new DOMRequest(aWindow));
return NS_OK;
}
NS_IMETHODIMP
DOMRequestService::FireSuccess(nsIDOMDOMRequest* aRequest,
const jsval& aResult)
{
static_cast<DOMRequest*>(aRequest)->FireSuccess(aResult);
return NS_OK;
}
NS_IMETHODIMP
DOMRequestService::FireError(nsIDOMDOMRequest* aRequest,
const nsAString& aError)
{
static_cast<DOMRequest*>(aRequest)->FireError(aError);
return NS_OK;
}

89
dom/base/DOMRequest.h Normal file
View File

@ -0,0 +1,89 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_domrequest_h__
#define mozilla_dom_domrequest_h__
#include "nsIDOMDOMRequest.h"
#include "nsIDOMDOMError.h"
#include "nsDOMEventTargetHelper.h"
#include "nsContentUtils.h"
#include "nsCOMPtr.h"
namespace mozilla {
namespace dom {
class DOMRequest : public nsDOMEventTargetHelper,
public nsIDOMDOMRequest
{
bool mDone;
jsval mResult;
nsCOMPtr<nsIDOMDOMError> mError;
bool mRooted;
NS_DECL_EVENT_HANDLER(success)
NS_DECL_EVENT_HANDLER(error)
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMDOMREQUEST
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(DOMRequest,
nsDOMEventTargetHelper)
void FireSuccess(jsval aResult);
void FireError(const nsAString& aError);
DOMRequest(nsIDOMWindow* aWindow);
virtual ~DOMRequest()
{
UnrootResultVal();
}
private:
void FireEvent(const nsAString& aType);
void RootResultVal()
{
if (!mRooted) {
NS_HOLD_JS_OBJECTS(this, DOMRequest);
mRooted = true;
}
}
void UnrootResultVal()
{
if (mRooted) {
NS_DROP_JS_OBJECTS(this, DOMRequest);
mRooted = false;
}
}
};
class DOMRequestService : public nsIDOMRequestService
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMREQUESTSERVICE
// Returns an owning reference! No one should call this but the factory.
static DOMRequestService* FactoryCreate()
{
DOMRequestService* res = new DOMRequestService;
NS_ADDREF(res);
return res;
}
};
} // namespace dom
} // namespace mozilla
#define DOMREQUEST_SERVICE_CONTRACTID "@mozilla.org/dom/dom-request-service;1"
#endif // mozilla_dom_domrequest_h__

View File

@ -47,6 +47,10 @@ LIBRARY_NAME = jsdombase_s
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
DIRS = \
test \
$(NULL)
EXTRA_PP_COMPONENTS = \
ConsoleAPI.js \
ConsoleAPI.manifest \
@ -67,6 +71,7 @@ endif
XPIDLSRCS = \
nsIDOMDOMError.idl \
nsIDOMDOMRequest.idl \
nsIEntropyCollector.idl \
nsIScriptChannel.idl \
$(NULL)
@ -105,6 +110,7 @@ EXPORTS = \
EXPORTS_NAMESPACES = mozilla/dom
EXPORTS_mozilla/dom = \
DOMError.h \
DOMRequest.h \
StructuredCloneTags.h \
$(NULL)
@ -135,6 +141,7 @@ CPPSRCS = \
nsPerformance.cpp \
nsDOMMemoryReporter.cpp \
DOMError.cpp \
DOMRequest.cpp \
Navigator.cpp \
$(NULL)

View File

@ -537,6 +537,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
#endif
#include "DOMError.h"
#include "DOMRequest.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -1543,6 +1544,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionStandardDerivatives, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionTextureFilterAnisotropic, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionLoseContext, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -1638,6 +1641,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(DOMError, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DOMRequest, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
};
// Objects that should be constructable through |new Name();|
@ -4204,6 +4210,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionStandardDerivatives, nsIWebGLExtensionStandardDerivatives)
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionStandardDerivatives)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionTextureFilterAnisotropic, nsIWebGLExtensionTextureFilterAnisotropic)
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionTextureFilterAnisotropic)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionLoseContext, nsIWebGLExtensionLoseContext)
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionLoseContext)
@ -4381,6 +4391,11 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMError)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(DOMRequest, nsIDOMDOMRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_END
#ifdef NS_DEBUG
{
PRUint32 i = ArrayLength(sClassInfoData);

View File

@ -486,6 +486,7 @@ DOMCI_CLASS(WebGLShaderPrecisionFormat)
DOMCI_CLASS(WebGLActiveInfo)
DOMCI_CLASS(WebGLExtension)
DOMCI_CLASS(WebGLExtensionStandardDerivatives)
DOMCI_CLASS(WebGLExtensionTextureFilterAnisotropic)
DOMCI_CLASS(WebGLExtensionLoseContext)
DOMCI_CLASS(PaintRequest)
@ -545,3 +546,4 @@ DOMCI_CLASS(BluetoothAdapter)
#endif
DOMCI_CLASS(DOMError)
DOMCI_CLASS(DOMRequest)

View File

@ -2343,8 +2343,17 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
return NS_OK;
nsCOMPtr<nsIContent> startContent = aStartContent;
if (!startContent && aType != MOVEFOCUS_CARET)
startContent = aWindow->GetFocusedNode();
if (!startContent && aType != MOVEFOCUS_CARET) {
if (aType == MOVEFOCUS_FORWARDDOC || aType == MOVEFOCUS_BACKWARDDOC) {
// When moving between documents, make sure to get the right
// starting content in a descendant.
nsCOMPtr<nsPIDOMWindow> focusedWindow;
startContent = GetFocusedDescendant(aWindow, true, getter_AddRefs(focusedWindow));
}
else {
startContent = aWindow->GetFocusedNode();
}
}
nsCOMPtr<nsIDocument> doc;
if (startContent)
@ -2362,11 +2371,11 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
return NS_OK;
}
if (aType == MOVEFOCUS_FORWARDDOC) {
NS_IF_ADDREF(*aNextContent = GetNextTabbableDocument(true));
NS_IF_ADDREF(*aNextContent = GetNextTabbableDocument(startContent, true));
return NS_OK;
}
if (aType == MOVEFOCUS_BACKWARDDOC) {
NS_IF_ADDREF(*aNextContent = GetNextTabbableDocument(false));
NS_IF_ADDREF(*aNextContent = GetNextTabbableDocument(startContent, false));
return NS_OK;
}
@ -3136,66 +3145,192 @@ nsFocusManager::GetPreviousDocShell(nsIDocShellTreeItem* aItem,
}
nsIContent*
nsFocusManager::GetNextTabbableDocument(bool aForward)
nsFocusManager::GetNextTabbablePanel(nsIDocument* aDocument, nsIFrame* aCurrentPopup, bool aForward)
{
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
if (!pm)
return nsnull;
// Iterate through the array backwards if aForward is false.
nsTArray<nsIFrame *> popups = pm->GetVisiblePopups();
PRInt32 i = aForward ? 0 : popups.Length() - 1;
PRInt32 end = aForward ? popups.Length() : -1;
for (; i != end; aForward ? i++ : i--) {
nsIFrame* popupFrame = popups[i];
if (aCurrentPopup) {
// If the current popup is set, then we need to skip over this popup and
// wait until the currently focused popup is found. Once found, the
// current popup will be cleared so that the next popup is used.
if (aCurrentPopup == popupFrame)
aCurrentPopup = nsnull;
continue;
}
// Skip over non-panels
if (popupFrame->GetContent()->Tag() != nsGkAtoms::panel ||
(aDocument && popupFrame->GetContent()->GetCurrentDoc() != aDocument)) {
continue;
}
// Find the first focusable content within the popup. If there isn't any
// focusable content in the popup, skip to the next popup.
nsIPresShell* presShell = popupFrame->PresContext()->GetPresShell();
if (presShell) {
nsCOMPtr<nsIContent> nextFocus;
nsIContent* popup = popupFrame->GetContent();
nsresult rv = GetNextTabbableContent(presShell, popup,
nsnull, popup,
true, 1, false,
getter_AddRefs(nextFocus));
if (NS_SUCCEEDED(rv) && nextFocus) {
return nextFocus.get();
}
}
}
return nsnull;
}
nsIContent*
nsFocusManager::GetNextTabbableDocument(nsIContent* aStartContent, bool aForward)
{
// If currentPopup is set, then the starting content is in a panel.
nsIFrame* currentPopup = nsnull;
nsCOMPtr<nsIDocument> doc;
nsCOMPtr<nsIDocShellTreeItem> startItem;
if (mFocusedWindow) {
if (aStartContent) {
doc = aStartContent->GetCurrentDoc();
if (doc) {
startItem = do_QueryInterface(doc->GetWindow()->GetDocShell());
}
// Check if the starting content is inside a panel. Document navigation
// must start from this panel instead of the document root.
nsIContent* content = aStartContent;
while (content) {
if (content->NodeInfo()->Equals(nsGkAtoms::panel, kNameSpaceID_XUL)) {
currentPopup = content->GetPrimaryFrame();
break;
}
content = content->GetParent();
}
}
else if (mFocusedWindow) {
startItem = do_QueryInterface(mFocusedWindow->GetDocShell());
doc = do_QueryInterface(mFocusedWindow->GetExtantDocument());
}
else {
nsCOMPtr<nsIWebNavigation> webnav = do_GetInterface(mActiveWindow);
startItem = do_QueryInterface(webnav);
if (mActiveWindow) {
doc = do_QueryInterface(mActiveWindow->GetExtantDocument());
}
}
if (!startItem)
return nsnull;
// perform a depth first search (preorder) of the docshell tree
// looking for an HTML Frame or a chrome document
nsIContent* content = nsnull;
nsIContent* content = aStartContent;
nsCOMPtr<nsIDocShellTreeItem> curItem = startItem;
nsCOMPtr<nsIDocShellTreeItem> nextItem;
do {
if (aForward) {
GetNextDocShell(curItem, getter_AddRefs(nextItem));
if (!nextItem) {
// wrap around to the beginning, which is the top of the tree
startItem->GetRootTreeItem(getter_AddRefs(nextItem));
}
}
else {
GetPreviousDocShell(curItem, getter_AddRefs(nextItem));
if (!nextItem) {
// wrap around to the end, which is the last item in the tree
nsCOMPtr<nsIDocShellTreeItem> rootItem;
startItem->GetRootTreeItem(getter_AddRefs(rootItem));
GetLastDocShell(rootItem, getter_AddRefs(nextItem));
// If moving forward, check for a panel in the starting document. If one
// exists with focusable content, return that content instead of the next
// document. If currentPopup is set, then, another panel may exist. If no
// such panel exists, then continue on to check the next document.
// When moving backwards, and the starting content is in a panel, then
// check for additional panels in the starting document. If the starting
// content is not in a panel, move back to the previous document and check
// for panels there.
bool checkPopups = false;
nsCOMPtr<nsPIDOMWindow> nextFrame = nsnull;
if (doc && (aForward || currentPopup)) {
nsIContent* popupContent = GetNextTabbablePanel(doc, currentPopup, aForward);
if (popupContent)
return popupContent;
if (!aForward && currentPopup) {
// The starting content was in a popup, yet no other popups were
// found. Move onto the starting content's document.
nextFrame = doc->GetWindow();
}
}
curItem = nextItem;
nsCOMPtr<nsPIDOMWindow> nextFrame = do_GetInterface(nextItem);
// Look for the next or previous document.
if (!nextFrame) {
if (aForward) {
GetNextDocShell(curItem, getter_AddRefs(nextItem));
if (!nextItem) {
// wrap around to the beginning, which is the top of the tree
startItem->GetRootTreeItem(getter_AddRefs(nextItem));
}
}
else {
GetPreviousDocShell(curItem, getter_AddRefs(nextItem));
if (!nextItem) {
// wrap around to the end, which is the last item in the tree
nsCOMPtr<nsIDocShellTreeItem> rootItem;
startItem->GetRootTreeItem(getter_AddRefs(rootItem));
GetLastDocShell(rootItem, getter_AddRefs(nextItem));
}
// When going back to the previous document, check for any focusable
// popups in that previous document first.
checkPopups = true;
}
curItem = nextItem;
nextFrame = do_GetInterface(nextItem);
}
if (!nextFrame)
return nsnull;
nsCOMPtr<nsIDocument> doc = do_QueryInterface(nextFrame->GetExtantDocument());
if (doc && !doc->EventHandlingSuppressed()) {
content = GetRootForFocus(nextFrame, doc, true, true);
if (content && !GetRootForFocus(nextFrame, doc, false, false)) {
// if the found content is in a chrome shell or a frameset, navigate
// forward one tabbable item so that the first item is focused. Note
// that we always go forward and not back here.
nsCOMPtr<nsIContent> nextFocus;
Element* rootElement = doc->GetRootElement();
nsIPresShell* presShell = doc->GetShell();
if (presShell) {
nsresult rv = GetNextTabbableContent(presShell, rootElement,
nsnull, rootElement,
true, 1, false,
getter_AddRefs(nextFocus));
return NS_SUCCEEDED(rv) ? nextFocus.get() : nsnull;
}
// Clear currentPopup for the next iteration
currentPopup = nsnull;
// If event handling is suppressed, move on to the next document. Set
// content to null so that the popup check will be skipped on the next
// loop iteration.
doc = do_QueryInterface(nextFrame->GetExtantDocument());
if (!doc || doc->EventHandlingSuppressed()) {
content = nsnull;
continue;
}
if (checkPopups) {
// When iterating backwards, check the panels of the previous document
// first. If a panel exists that has focusable content, focus that.
// Otherwise, continue on to focus the document.
nsIContent* popupContent = GetNextTabbablePanel(doc, nsnull, false);
if (popupContent)
return popupContent;
}
content = GetRootForFocus(nextFrame, doc, true, true);
if (content && !GetRootForFocus(nextFrame, doc, false, false)) {
// if the found content is in a chrome shell or a frameset, navigate
// forward one tabbable item so that the first item is focused. Note
// that we always go forward and not back here.
nsCOMPtr<nsIContent> nextFocus;
Element* rootElement = doc->GetRootElement();
nsIPresShell* presShell = doc->GetShell();
if (presShell) {
nsresult rv = GetNextTabbableContent(presShell, rootElement,
nsnull, rootElement,
true, 1, false,
getter_AddRefs(nextFocus));
return NS_SUCCEEDED(rv) ? nextFocus.get() : nsnull;
}
}
} while (!content);
return content;

View File

@ -459,16 +459,31 @@ protected:
nsIDocShellTreeItem** aResult);
/**
* Get the tabbable next document from the currently focused frame if
* aForward is true, or the previously tabbable document if aForward is
* false. If this document is a chrome or frameset document, returns
* the first focusable element within this document, otherwise, returns
* the root node of the document.
* Determine the first panel with focusable content in document tab order
* from the given document. aForward indicates the direction to scan. If
* aCurrentPopup is set to a panel, the next or previous popup after
* aCurrentPopup after it is used. If aCurrentPopup is null, then the first
* or last popup is used. If a panel has no focusable content, it is skipped.
* Null is returned if no panel is open or no open panel contains a focusable
* element.
*/
nsIContent* GetNextTabbablePanel(nsIDocument* aDocument, nsIFrame* aCurrentPopup, bool aForward);
/**
* Get the tabbable next document from aStartContent or, if null, the
* currently focused frame if aForward is true, or the previously tabbable
* document if aForward is false. If this document is a chrome or frameset
* document, returns the first focusable element within this document,
* otherwise, returns the root node of the document.
*
*
* Panels with focusable content are also placed in the cycling order, just
* after the document containing that panel.
*
* This method would be used for document navigation, which is typically
* invoked by pressing F6.
*/
nsIContent* GetNextTabbableDocument(bool aForward);
nsIContent* GetNextTabbableDocument(nsIContent* aStartContent, bool aForward);
/**
* Retreives a focusable element within the current selection of aWindow.

View File

@ -0,0 +1,31 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIDOMEventTarget.idl"
interface nsIDOMDOMError;
interface nsIDOMWindow;
[scriptable, builtinclass, uuid(a3ad2846-ffb2-48d7-a786-2254cb82560d)]
interface nsIDOMDOMRequest : nsIDOMEventTarget
{
readonly attribute DOMString readyState; // "pending" or "done"
readonly attribute jsval result;
readonly attribute nsIDOMDOMError error;
attribute nsIDOMEventListener onsuccess;
attribute nsIDOMEventListener onerror;
};
[scriptable, builtinclass, uuid(eebcdf29-f8fa-4c36-bbc7-2146b1cbaf7b)]
interface nsIDOMRequestService : nsISupports
{
nsIDOMDOMRequest createRequest(in nsIDOMWindow window);
void fireSuccess(in nsIDOMDOMRequest request, in jsval result);
void fireError(in nsIDOMDOMRequest request, in DOMString error);
};

View File

@ -3275,8 +3275,9 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
if (!sCleanupSinceLastGC && aExtraForgetSkippableCalls >= 0) {
nsCycleCollector_forgetSkippable();
}
PRUint32 collected = nsCycleCollector_collect(aListener);
sCCollectedWaitingForGC += collected;
nsCycleCollectorResults ccResults;
nsCycleCollector_collect(&ccResults, aListener);
sCCollectedWaitingForGC += ccResults.mFreedRefCounted + ccResults.mFreedGCed;
// If we collected a substantial amount of cycles, poke the GC since more objects
// might be unreachable now.
@ -3303,16 +3304,23 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
sFirstCollectionTime = now;
}
nsString gcmsg;
if (ccResults.mForcedGC) {
gcmsg.AssignLiteral(", forced a GC");
}
NS_NAMED_MULTILINE_LITERAL_STRING(kFmt,
NS_LL("CC(T+%.1f) collected: %lu (%lu waiting for GC), suspected: %lu, duration: %llu ms.\n")
NS_LL("CC(T+%.1f) duration: %llums, suspected: %lu, visited: %lu RCed and %lu GCed, collected: %lu RCed and %lu GCed (%lu waiting for GC)%s\n")
NS_LL("ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, removed: %lu"));
nsString msg;
PRUint32 cleanups = sForgetSkippableBeforeCC ? sForgetSkippableBeforeCC : 1;
sMinForgetSkippableTime = (sMinForgetSkippableTime == PR_UINT32_MAX)
? 0 : sMinForgetSkippableTime;
msg.Adopt(nsTextFormatter::smprintf(kFmt.get(), double(delta) / PR_USEC_PER_SEC,
collected, sCCollectedWaitingForGC, suspected,
(now - start) / PR_USEC_PER_MSEC,
(now - start) / PR_USEC_PER_MSEC, suspected,
ccResults.mVisitedRefCounted, ccResults.mVisitedGCed,
ccResults.mFreedRefCounted, ccResults.mFreedGCed,
sCCollectedWaitingForGC, gcmsg.get(),
sForgetSkippableBeforeCC,
sMinForgetSkippableTime / PR_USEC_PER_MSEC,
sMaxForgetSkippableTime / PR_USEC_PER_MSEC,

View File

@ -45,6 +45,7 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsIDocShellTreeItem.h"
#include "nsLayoutUtils.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
@ -262,9 +263,7 @@ nsScreen::GetAvailRect(nsRect& aRect)
namespace {
bool
IsChromeType(nsIDocShell *aDocShell)
{
bool IsWhiteListed(nsIDocShell *aDocShell) {
nsCOMPtr<nsIDocShellTreeItem> ds = do_QueryInterface(aDocShell);
if (!ds) {
return false;
@ -272,7 +271,21 @@ IsChromeType(nsIDocShell *aDocShell)
PRInt32 itemType;
ds->GetItemType(&itemType);
return itemType == nsIDocShellTreeItem::typeChrome;
if (itemType == nsIDocShellTreeItem::typeChrome) {
return true;
}
nsCOMPtr<nsIDocument> doc = do_GetInterface(aDocShell);
nsIPrincipal *principal = doc->NodePrincipal();
nsCOMPtr<nsIURI> principalURI;
principal->GetURI(getter_AddRefs(principalURI));
if (nsContentUtils::URIIsChromeOrInPref(principalURI,
"dom.mozScreenWhitelist")) {
return true;
}
return false;
}
} // anonymous namespace
@ -280,7 +293,7 @@ IsChromeType(nsIDocShell *aDocShell)
nsresult
nsScreen::GetMozEnabled(bool *aEnabled)
{
if (!sAllowScreenEnabledProperty || !IsChromeType(mDocShell)) {
if (!sAllowScreenEnabledProperty || !IsWhiteListed(mDocShell)) {
*aEnabled = true;
return NS_OK;
}
@ -292,7 +305,7 @@ nsScreen::GetMozEnabled(bool *aEnabled)
nsresult
nsScreen::SetMozEnabled(bool aEnabled)
{
if (!sAllowScreenEnabledProperty || !IsChromeType(mDocShell)) {
if (!sAllowScreenEnabledProperty || !IsWhiteListed(mDocShell)) {
return NS_OK;
}
@ -305,7 +318,7 @@ nsScreen::SetMozEnabled(bool aEnabled)
nsresult
nsScreen::GetMozBrightness(double *aBrightness)
{
if (!sAllowScreenBrightnessProperty || !IsChromeType(mDocShell)) {
if (!sAllowScreenEnabledProperty || !IsWhiteListed(mDocShell)) {
*aBrightness = 1;
return NS_OK;
}
@ -317,7 +330,7 @@ nsScreen::GetMozBrightness(double *aBrightness)
nsresult
nsScreen::SetMozBrightness(double aBrightness)
{
if (!sAllowScreenBrightnessProperty || !IsChromeType(mDocShell)) {
if (!sAllowScreenEnabledProperty || !IsWhiteListed(mDocShell)) {
return NS_OK;
}

53
dom/base/test/Makefile.in Normal file
View File

@ -0,0 +1,53 @@
# ***** 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 Indexed Database Test Code.
#
# The Initial Developer of the Original Code is
# The Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2010
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Shawn Wilsher <me@shawnwilsher.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 *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = dom/base/test
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
TEST_FILES = \
test_domrequest.html \
$(NULL)
libs:: $(TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)

View File

@ -0,0 +1,63 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for XMLHttpRequest</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">
"use strict";
var reqserv = SpecialPowers.getDOMRequestService();
ok("createRequest" in reqserv, "appears to be a service");
// create a request
var req = reqserv.createRequest(window);
ok("result" in req, "request has result");
ok("error" in req, "request has error");
ok("onsuccess" in req, "request has onsuccess");
ok("onerror" in req, "request has onerror");
ok("readyState" in req, "request has readyState");
is(req.readyState, "pending", "readyState is pending");
is(req.result, undefined, "result is undefined");
is(req.onsuccess, null, "onsuccess is null");
is(req.onerror, null, "onerror is null");
// fire success
var ev = null;
req.onsuccess = function(e) {
ev = e;
}
reqserv.fireSuccess(req, "my result");
ok(ev, "got success event");
is(ev.type, "success", "correct type during success");
is(ev.target, req, "correct target during success");
is(req.readyState, "done", "correct readyState after success");
is(req.error, null, "correct error after success");
is(req.result, "my result", "correct result after success");
// fire error
req = reqserv.createRequest(window);
ev = null;
req.onerror = function(e) {
ev = e;
}
reqserv.fireError(req, "OhMyError");
ok(ev, "got success event");
is(ev.type, "error", "correct type during error");
is(ev.target, req, "correct target during error");
is(req.readyState, "done", "correct readyState after error");
is(req.error.name, "OhMyError", "correct error after error");
is(req.result, undefined, "correct result after error");
</script>
</pre>
</body>
</html>

View File

@ -4,36 +4,160 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BluetoothAdapter.h"
#include "nsDOMClassInfo.h"
#include "nsDOMEvent.h"
#include "nsThreadUtils.h"
#include "nsXPCOMCIDInternal.h"
#include "mozilla/LazyIdleThread.h"
#include "BluetoothAdapter.h"
#if defined(MOZ_WIDGET_GONK)
#include <bluedroid/bluetooth.h>
#endif
#define POWERED_EVENT_NAME NS_LITERAL_STRING("powered")
BEGIN_BLUETOOTH_NAMESPACE
class ToggleBtResultTask : public nsRunnable
{
public:
ToggleBtResultTask(bool result, nsRefPtr<BluetoothAdapter>& adapterPtr)
: mResult(result)
{
MOZ_ASSERT(!NS_IsMainThread()); // This should be running on the worker thread
mAdapterPtr.swap(adapterPtr);
}
NS_IMETHOD Run() {
MOZ_ASSERT(NS_IsMainThread()); // This method is supposed to run on the main thread!
mAdapterPtr->FirePowered();
return NS_OK;
}
private:
bool mResult;
nsRefPtr<BluetoothAdapter> mAdapterPtr;
};
class ToggleBtTask : public nsRunnable
{
public:
ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
: mOnOff(onOff),
mAdapterPtr(adapterPtr)
{
MOZ_ASSERT(NS_IsMainThread()); // The constructor should be running on the main thread.
}
NS_IMETHOD Run() {
bool result;
MOZ_ASSERT(!NS_IsMainThread()); // This should be running on the worker thread.
//Toggle BT here
#if defined(MOZ_WIDGET_GONK)
if (mOnOff) {
result = bt_enable();
} else {
result = bt_disable();
}
#else
result = true;
#endif
// Create a result thread and pass it to Main Thread,
nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(result, mAdapterPtr);
NS_DispatchToMainThread(resultRunnable);
return NS_OK;
}
private:
nsRefPtr<BluetoothAdapter> mAdapterPtr;
bool mOnOff;
};
END_BLUETOOTH_NAMESPACE
DOMCI_DATA(BluetoothAdapter, mozilla::dom::bluetooth::BluetoothAdapter)
USING_BLUETOOTH_NAMESPACE
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothAdapter)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
BluetoothAdapter::BluetoothAdapter() : mPower(false)
{
}
NS_INTERFACE_MAP_BEGIN(BluetoothAdapter)
NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothAdapter)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(BluetoothAdapter)
NS_IMPL_RELEASE(BluetoothAdapter)
DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
NS_IMETHODIMP
BluetoothAdapter::GetPower(bool* aPower)
{
#if defined(MOZ_WIDGET_GONK)
*aPower = bt_is_enabled();
#else
*aPower = mPower;
#endif
return NS_OK;
}
NS_IMETHODIMP
BluetoothAdapter::SetPower(bool aPower)
{
mPower = aPower;
if (mPower != aPower) {
mPower = aPower;
ToggleBluetoothAsync();
}
return NS_OK;
}
void
BluetoothAdapter::ToggleBluetoothAsync()
{
if (!mToggleBtThread) {
mToggleBtThread = new LazyIdleThread(15000);
}
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(mPower, this);
mToggleBtThread->Dispatch(r, 0);
}
nsresult
BluetoothAdapter::FirePowered()
{
nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
nsresult rv = event->InitEvent(POWERED_EVENT_NAME, false, false);
NS_ENSURE_SUCCESS(rv, rv);
bool dummy;
rv = DispatchEvent(event, &dummy);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, powered)

View File

@ -8,20 +8,35 @@
#define mozilla_dom_bluetooth_bluetoothadapter_h__
#include "BluetoothCommon.h"
#include "nsDOMEventTargetHelper.h"
#include "nsIDOMBluetoothAdapter.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothAdapter : public nsIDOMBluetoothAdapter
,public nsDOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMBLUETOOTHADAPTER
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
BluetoothAdapter();
nsresult FirePowered();
protected:
bool mPower;
NS_DECL_EVENT_HANDLER(powered)
private:
nsCOMPtr<nsIEventTarget> mToggleBtThread;
void ToggleBluetoothAsync();
};
END_BLUETOOTH_NAMESPACE

View File

@ -4,10 +4,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
#include "nsIDOMEventTarget.idl"
[scriptable, builtinclass, uuid(29689a22-45ff-4ccf-b552-5364ce3a3642)]
interface nsIDOMBluetoothAdapter : nsISupports
interface nsIDOMEventListener;
[scriptable, builtinclass, uuid(3dbaa9f4-5c93-11e1-8592-ff9bfcc3ab4b)]
interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
{
attribute boolean power;
attribute nsIDOMEventListener onpowered;
};

View File

@ -168,6 +168,13 @@ interface nsIWebGLExtensionLoseContext : nsIWebGLExtension
void restoreContext();
};
[scriptable, uuid(73bfb64d-94bd-4a7a-9eab-6b6d32e57aa0)]
interface nsIWebGLExtensionTextureFilterAnisotropic : nsIWebGLExtension
{
const WebGLenum TEXTURE_MAX_ANISOTROPY = 0x84FE;
const WebGLenum MAX_TEXTURE_MAX_ANISOTROPY = 0x84FF;
};
[scriptable, builtinclass, uuid(f000afac-11b3-4c06-a35f-8db411f1cf54)]
interface nsIDOMWebGLRenderingContext : nsISupports
{

View File

@ -52,7 +52,7 @@ interface nsIDOMUserDataHandler;
* http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
*/
[scriptable, uuid(ce82fb71-60f2-4c38-be31-de5f2f90dada)]
[scriptable, uuid(5e9bcec9-5928-4f77-8a9c-424ef01c20e1)]
interface nsIDOMNode : nsISupports
{
const unsigned short ELEMENT_NODE = 1;
@ -94,7 +94,8 @@ interface nsIDOMNode : nsISupports
nsIDOMNode appendChild(in nsIDOMNode newChild)
raises(DOMException);
boolean hasChildNodes();
nsIDOMNode cloneNode(in boolean deep);
// Modified in DOM Level 4:
[optional_argc] nsIDOMNode cloneNode([optional] in boolean deep);
// Modified in DOM Level 2:
void normalize();
// Introduced in DOM Level 2:

View File

@ -353,16 +353,6 @@ nsNPAPIPlugin::RunPluginOOP(const nsPluginTag *aPluginTag)
}
#endif
#ifdef XP_WIN
OSVERSIONINFO osVerInfo = {0};
osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo);
GetVersionEx(&osVerInfo);
// Always disabled on 2K or less. (bug 536303)
if (osVerInfo.dwMajorVersion < 5 ||
(osVerInfo.dwMajorVersion == 5 && osVerInfo.dwMinorVersion == 0))
return false;
#endif
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (!prefs) {
return false;

View File

@ -57,7 +57,6 @@
#include "nsString.h"
#include "nsILocalFile.h"
#include "nsUnicharUtils.h"
#include "nsSetDllDirectory.h"
using namespace mozilla;
@ -303,7 +302,7 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary)
}
if (protectCurrentDirectory) {
mozilla::NS_SetDllDirectory(NULL);
SetDllDirectory(NULL);
}
nsresult rv = plugin->Load(outLibrary);
@ -311,7 +310,7 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary)
*outLibrary = NULL;
if (protectCurrentDirectory) {
mozilla::NS_SetDllDirectory(L"");
SetDllDirectory(L"");
}
if (restoreOrigDir) {

View File

@ -147,7 +147,7 @@ PluginProcessChild::Init()
}
if (protectCurrentDirectory) {
SanitizeEnvironmentVariables();
NS_SetDllDirectory(L"");
SetDllDirectory(L"");
}
#else

View File

@ -1848,8 +1848,7 @@ nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring
if (!mStorage)
return NS_ERROR_OUT_OF_MEMORY;
// Leave security checks only for domain (nsDOMStorage implementation)
mStorage->mSecurityChecker = mStorage;
mStorage->mSecurityChecker = this;
mPrincipal = aPrincipal;
mDocumentURI = aDocumentURI;
@ -1949,7 +1948,7 @@ nsDOMStorage2::CanAccess(nsIPrincipal *aPrincipal)
// Allow more powerful principals (e.g. system) to access the storage
bool subsumes;
nsresult rv = aPrincipal->Subsumes(mPrincipal, &subsumes);
nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes);
if (NS_FAILED(rv))
return false;

View File

@ -76,6 +76,10 @@ AudioManager::SetMasterVolume(float aMasterVolume)
if (AudioSystem::setMasterVolume(aMasterVolume)) {
return NS_ERROR_FAILURE;
}
// For now, just set the voice volume at the same level
if (AudioSystem::setVoiceVolume(aMasterVolume)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}

View File

@ -24,7 +24,6 @@ var ConsoleObserver = {
if (aTopic == "console-storage-cache-event") {
apiCallCount ++;
if (apiCallCount == 4) {
// remove the observer so we don't trigger this test again
Services.obs.removeObserver(this, "console-storage-cache-event");
try {
@ -42,12 +41,13 @@ var ConsoleObserver = {
// make sure a closed window's events are in fact removed from the
// storage cache
win.console.log("adding a new event");
// close the window - the storage cache should now be empty
// Close the window.
gBrowser.removeTab(tab, {animate: false});
// Ensure actual window destruction is not delayed (too long).
window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).garbageCollect();
// Ensure "inner-window-destroyed" event is processed,
// so the storage cache is cleared.
executeSoon(function () {
// use the old windowID again to see if we have any stray cached messages
messages = ConsoleAPIStorage.getEvents(windowID);
@ -71,6 +71,12 @@ function tearDown()
function test()
{
// Don't cache removed tabs, so "clear console cache on tab close" triggers.
Services.prefs.setIntPref("browser.tabs.max_tabs_undo", 0);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("browser.tabs.max_tabs_undo");
});
registerCleanupFunction(tearDown);
ConsoleObserver.init();

View File

@ -74,6 +74,8 @@ _TEST_FILES = \
test_moving_xhr.xul \
test_nodesFromRect.html \
489127.html \
test_focus_docnav.xul \
window_focus_docnav.xul \
$(NULL)
ifeq (WINNT,$(OS_ARCH))

View File

@ -3,7 +3,8 @@
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
SimpleTest.waitForFocus(function () opener.framesetWindowLoaded(window));
if (opener)
SimpleTest.waitForFocus(function () opener.framesetWindowLoaded(window));
</script>
<frameset rows="30%, 70%">

View File

@ -0,0 +1,28 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window onload="runTest();"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script>
SimpleTest.waitForExplicitFinish();
function runTest()
{
window.open("window_focus_docnav.xul", "_blank", "chrome,width=600,height=550");
}
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display">
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</window>

View File

@ -0,0 +1,104 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window onload="start()"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<textbox id="textbox"/>
<panel id="panel2" onpopupshown="runTests(this, 2);" onpopuphidden="document.getElementById('panel').hidePopup()">
<textbox id="p2textbox" value="Popup2"/>
</panel>
<panel id="panel" onpopupshown="runTests(this, 1);"
onpopuphidden="done()">
<textbox id="p1textbox" value="Popup1"/>
</panel>
<browser id="browser" type="content" src="focus_frameset.html" width="500" height="400"/>
<script type="application/javascript">
<![CDATA[
var fm = Components.classes["@mozilla.org/focus-manager;1"].
getService(Components.interfaces.nsIFocusManager);
function is(l, r, n) { window.opener.wrappedJSObject.SimpleTest.is(l,r,n); }
function ok(v, n) { window.opener.wrappedJSObject.SimpleTest.ok(v,n); }
function done()
{
var opener = window.opener;
window.close();
opener.wrappedJSObject.SimpleTest.finish();
}
function previous(expectedWindow, expectedElement, desc)
{
synthesizeKey("VK_F6", { shiftKey: true });
is(fm.focusedWindow, expectedWindow, desc);
is(fm.focusedElement, expectedElement, desc + " element");
}
function next(expectedWindow, expectedElement, desc)
{
synthesizeKey("VK_F6", { });
is(fm.focusedWindow, expectedWindow, desc);
is(fm.focusedElement, expectedElement, desc + " element" + "::" + (fm.focusedElement ? fm.focusedElement.parentNode.id : "<none>"));
}
// This test runs through three cases. Document navigation forward and
// backward using the F6 key when no popups are open, with one popup open and
// with two popups open.
function runTests(panel, popupCount)
{
if (!popupCount || popupCount > 2)
popupCount = 0;
fm.clearFocus(window);
var childwin = document.getElementById("browser").contentWindow;
if (popupCount) {
if (popupCount == 2) {
next(window, document.getElementById("p2textbox").inputField, "First into popup 2 with " + popupCount);
}
next(window, document.getElementById("p1textbox").inputField, "First into popup 1 with " + popupCount);
}
next(childwin.frames[0], childwin.frames[0].document.documentElement, "First with " + popupCount);
next(childwin.frames[1], childwin.frames[1].document.documentElement, "Second with " + popupCount);
previous(childwin.frames[0], childwin.frames[0].document.documentElement, "Second back with " + popupCount);
if (popupCount) {
previous(window, document.getElementById("p1textbox").inputField, "First back from popup 1 with " + popupCount);
if (popupCount == 2) {
previous(window, document.getElementById("p2textbox").inputField, "First back from popup 2 with " + popupCount);
}
}
previous(window, document.getElementById("textbox").inputField, "First back with " + popupCount);
if (panel == document.getElementById("panel"))
document.getElementById("panel2").openPopup(null, "after_start", 100, 20);
else if (panel == document.getElementById("panel2"))
panel.hidePopup();
else
document.getElementById("panel").openPopup(null, "after_start");
}
function start()
{
window.opener.wrappedJSObject.SimpleTest.waitForExplicitFinish();
window.opener.wrappedJSObject.SimpleTest.waitForFocus(
function() { runTests(null, 0); },
document.getElementById("browser").contentWindow);
}
]]></script>
</window>

View File

@ -16,7 +16,7 @@ function startTest()
sessionStorage;
}
catch (e) {
is(e.result, 2152923145,
is(e.result, Components.results.NS_ERROR_NOT_AVAILABLE,
"Testing that we get the expected exception.");
exceptionCaught = true;
}

View File

@ -55,7 +55,7 @@ interface nsIEditActionListener;
interface nsIInlineSpellChecker;
interface nsITransferable;
[scriptable, uuid(94479B76-7FD7-47D3-BB1E-5B77846339D2)]
[scriptable, uuid(656005d2-d900-4839-81bf-6274a3c38537)]
interface nsIEditor : nsISupports
{
@ -205,6 +205,16 @@ interface nsIEditor : nsISupports
*/
void enableUndo(in boolean enable);
/**
* The number of items on the undo stack.
*/
readonly attribute long numberOfUndoItems;
/**
* The number of items on the redo stack.
*/
readonly attribute long numberOfRedoItems;
/** undo reverses the effects of the last Do operation,
* if Undo is enabled in the editor.
* It is provided here so clients need no knowledge of whether

View File

@ -98,7 +98,7 @@ NS_IMETHODIMP SplitElementTxn::DoTransaction(void)
if (!mExistingRightNode || !mEditor) { return NS_ERROR_NOT_INITIALIZED; }
// create a new node
nsresult result = mExistingRightNode->CloneNode(false, getter_AddRefs(mNewLeftNode));
nsresult result = mExistingRightNode->CloneNode(false, 1, getter_AddRefs(mNewLeftNode));
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element.");
NS_ENSURE_SUCCESS(result, result);
NS_ENSURE_TRUE(mNewLeftNode, NS_ERROR_NULL_POINTER);

View File

@ -750,6 +750,19 @@ nsEditor::EnableUndo(bool aEnable)
return NS_OK;
}
NS_IMETHODIMP
nsEditor::GetNumberOfUndoItems(PRInt32* aNumItems)
{
*aNumItems = 0;
return mTxnMgr ? mTxnMgr->GetNumberOfUndoItems(aNumItems) : NS_OK;
}
NS_IMETHODIMP
nsEditor::GetNumberOfRedoItems(PRInt32* aNumItems)
{
*aNumItems = 0;
return mTxnMgr ? mTxnMgr->GetNumberOfRedoItems(aNumItems) : NS_OK;
}
NS_IMETHODIMP
nsEditor::GetTransactionManager(nsITransactionManager* *aTxnManager)

View File

@ -117,6 +117,12 @@ function doTest()
// synthesizeDrop(text, textarea, [[{type: "text/plain", data: "Somewhat Longer Text"}]], "copy");
// is(textarea.value, "Somewhat Longer Text", "Drag text/plain onto textarea");
// -------- Test dragging special text type of text/plain to contenteditable
selection.selectAllChildren(text);
synthesizeDrop(text, input, [[{type: "text/x-moz-text-internal", data: "Some Special Text"}]], "copy");
is(input.value, "Some Plain Text", "Drag text/x-moz-text-internal onto input");
// -------- Test dragging regular text of text/plain to contenteditable
selection.selectAllChildren(text);

View File

@ -169,12 +169,16 @@ nsresult nsPlaintextEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTran
nsCOMPtr<nsIVariant> data;
aDataTransfer->MozGetDataAt(NS_LITERAL_STRING("text/plain"), aIndex,
getter_AddRefs(data));
nsAutoString insertText;
data->GetAsAString(insertText);
nsContentUtils::PlatformToDOMLineBreaks(insertText);
if (data) {
nsAutoString insertText;
data->GetAsAString(insertText);
nsContentUtils::PlatformToDOMLineBreaks(insertText);
nsAutoEditBatch beginBatching(this);
return InsertTextAt(insertText, aDestinationNode, aDestOffset, aDoDeleteSelection);
nsAutoEditBatch beginBatching(this);
return InsertTextAt(insertText, aDestinationNode, aDestOffset, aDoDeleteSelection);
}
return NS_OK;
}
nsresult nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)

View File

@ -2970,7 +2970,7 @@ nsWebBrowserPersist::GetNodeToFixup(nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut)
{
if (!(mPersistFlags & PERSIST_FLAGS_FIXUP_ORIGINAL_DOM))
{
nsresult rv = aNodeIn->CloneNode(false, aNodeOut);
nsresult rv = aNodeIn->CloneNode(false, 1, aNodeOut);
NS_ENSURE_SUCCESS(rv, rv);
}
else

View File

@ -107,33 +107,14 @@ static const char *MapErrorCode(int rc)
//-----------------------------------------------------------------------------
static HINSTANCE sspi_lib;
static PSecurityFunctionTableW sspi;
static nsresult
InitSSPI()
{
PSecurityFunctionTableW (*initFun)(void);
LOG((" InitSSPI\n"));
sspi_lib = LoadLibraryW(L"secur32.dll");
if (!sspi_lib) {
sspi_lib = LoadLibraryW(L"security.dll");
if (!sspi_lib) {
LOG(("SSPI library not found"));
return NS_ERROR_UNEXPECTED;
}
}
initFun = (PSecurityFunctionTableW (*)(void))
GetProcAddress(sspi_lib, "InitSecurityInterfaceW");
if (!initFun) {
LOG(("InitSecurityInterfaceW not found"));
return NS_ERROR_UNEXPECTED;
}
sspi = initFun();
sspi = InitSecurityInterfaceW();
if (!sspi) {
LOG(("InitSecurityInterfaceW failed"));
return NS_ERROR_UNEXPECTED;

View File

@ -41,6 +41,7 @@
#include "nsIServiceManager.h"
#include "nsUnicharUtils.h"
#include "nsUnicharUtilCIID.h"
#include "nsUnicodeProperties.h"
#include "nsCRT.h"
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozEnglishWordUtils)
@ -52,8 +53,7 @@ NS_INTERFACE_MAP_BEGIN(mozEnglishWordUtils)
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozEnglishWordUtils)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_2(mozEnglishWordUtils,
mCategories,
NS_IMPL_CYCLE_COLLECTION_1(mozEnglishWordUtils,
mURLDetector)
mozEnglishWordUtils::mozEnglishWordUtils()
@ -62,7 +62,6 @@ mozEnglishWordUtils::mozEnglishWordUtils()
nsresult rv;
mURLDetector = do_CreateInstance(MOZ_TXTTOHTMLCONV_CONTRACTID, &rv);
mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID);
}
mozEnglishWordUtils::~mozEnglishWordUtils()
@ -168,7 +167,7 @@ NS_IMETHODIMP mozEnglishWordUtils::GetRootForm(const PRUnichar *aWord, PRUint32
bool mozEnglishWordUtils::ucIsAlpha(PRUnichar aChar)
{
// XXX we have to fix callers to handle the full Unicode range
return nsIUGenCategory::kLetter == mCategories->Get(PRUint32(aChar));
return nsIUGenCategory::kLetter == mozilla::unicode::GetGenCategory(aChar);
}
/* void FindNextWord (in wstring word, in PRUint32 length, in PRUint32 offset, out PRUint32 begin, out PRUint32 end); */

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