зеркало из https://github.com/mozilla/pjs.git
Merge m-c to s-c.
This commit is contained in:
Коммит
8381eca623
|
@ -1494,28 +1494,24 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
|
||||||
* Rules for non-bordered tables with 2-4 columns and 2+ rows from here on forward
|
* Rules for non-bordered tables with 2-4 columns and 2+ rows from here on forward
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Check for styled background color across the row
|
// Check for styled background color across rows (alternating background
|
||||||
// Alternating background color is a common way
|
// color is a common feature for data tables).
|
||||||
nsCOMPtr<nsIDOMNodeList> nodeList;
|
PRUint32 childCount = GetChildCount();
|
||||||
nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mContent));
|
nsAutoString rowColor, prevRowColor;
|
||||||
tableElt->GetElementsByTagName(NS_LITERAL_STRING("tr"), getter_AddRefs(nodeList));
|
for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||||
NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
|
nsAccessible* child = GetChildAt(childIdx);
|
||||||
PRUint32 length;
|
if (child->Role() == roles::ROW) {
|
||||||
nodeList->GetLength(&length);
|
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
|
||||||
nsAutoString color, lastRowColor;
|
nsCoreUtils::GetComputedStyleDeclaration(EmptyString(),
|
||||||
for (PRUint32 rowCount = 0; rowCount < length; rowCount ++) {
|
child->GetContent());
|
||||||
nsCOMPtr<nsIDOMNode> rowNode;
|
if (styleDecl) {
|
||||||
nodeList->Item(rowCount, getter_AddRefs(rowNode));
|
prevRowColor = rowColor;
|
||||||
nsCOMPtr<nsIContent> rowContent(do_QueryInterface(rowNode));
|
styleDecl->GetPropertyValue(NS_LITERAL_STRING("background-color"),
|
||||||
|
rowColor);
|
||||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
|
if (childIdx > 0 && !prevRowColor.Equals(rowColor)) {
|
||||||
nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), rowContent);
|
RETURN_LAYOUT_ANSWER(false, "2 styles of row background color, non-bordered");
|
||||||
NS_ENSURE_TRUE(styleDecl, NS_ERROR_FAILURE);
|
}
|
||||||
|
}
|
||||||
lastRowColor = color;
|
|
||||||
styleDecl->GetPropertyValue(NS_LITERAL_STRING("background-color"), color);
|
|
||||||
if (rowCount > 0 && false == lastRowColor.Equals(color)) {
|
|
||||||
RETURN_LAYOUT_ANSWER(false, "2 styles of row background color, non-bordered");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1631,6 +1631,9 @@ nsHyperTextAccessible::GetCaretOffset(PRInt32 *aCaretOffset)
|
||||||
NS_ENSURE_ARG_POINTER(aCaretOffset);
|
NS_ENSURE_ARG_POINTER(aCaretOffset);
|
||||||
*aCaretOffset = -1;
|
*aCaretOffset = -1;
|
||||||
|
|
||||||
|
if (IsDefunct())
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
// Not focused focusable accessible except document accessible doesn't have
|
// Not focused focusable accessible except document accessible doesn't have
|
||||||
// a caret.
|
// a caret.
|
||||||
if (!IsDoc() && !FocusMgr()->IsFocused(this) &&
|
if (!IsDoc() && !FocusMgr()->IsFocused(this) &&
|
||||||
|
|
|
@ -48,6 +48,7 @@ include $(topsrcdir)/config/rules.mk
|
||||||
_TEST_FILES =\
|
_TEST_FILES =\
|
||||||
test_ariadialog.html \
|
test_ariadialog.html \
|
||||||
test_colorpicker.xul \
|
test_colorpicker.xul \
|
||||||
|
test_cssoverflow.html \
|
||||||
test_contextmenu.xul \
|
test_contextmenu.xul \
|
||||||
test_doc.html \
|
test_doc.html \
|
||||||
test_gencontent.html \
|
test_gencontent.html \
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Testing HTML scrollable frames (css overflow style)</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css"
|
||||||
|
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||||
|
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="../common.js"></script>
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="../events.js"></script>
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Invokers
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change scroll range to not empty size and inserts a child into container
|
||||||
|
* to trigger tree update of the container. Prior to bug 677154 not empty
|
||||||
|
* size resulted to accessible creation for scroll area, container tree
|
||||||
|
* update picked up that accessible unattaching scroll area accessible
|
||||||
|
* subtree.
|
||||||
|
*/
|
||||||
|
function changeScrollRange(aContainerID, aScrollAreaID)
|
||||||
|
{
|
||||||
|
this.containerNode = getNode(aContainerID);
|
||||||
|
this.container = getAccessible(this.containerNode);
|
||||||
|
this.scrollAreaNode = getNode(aScrollAreaID);
|
||||||
|
|
||||||
|
this.eventSeq = [
|
||||||
|
new invokerChecker(EVENT_REORDER, this.container)
|
||||||
|
];
|
||||||
|
|
||||||
|
this.invoke = function changeScrollRange_invoke()
|
||||||
|
{
|
||||||
|
this.scrollAreaNode.style.width = "20px";
|
||||||
|
this.containerNode.appendChild(document.createElement("input"));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.finalCheck = function changeScrollRange_finalCheck()
|
||||||
|
{
|
||||||
|
var accTree =
|
||||||
|
{ SECTION: [ // container
|
||||||
|
{ SECTION: [ // scroll area
|
||||||
|
{ ENTRY: [] } // child content
|
||||||
|
] },
|
||||||
|
{ ENTRY: [] } // inserted input
|
||||||
|
] };
|
||||||
|
testAccessibleTree(this.container, accTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function changeScrollRange_getID()
|
||||||
|
{
|
||||||
|
return "change scroll range for " + prettyName(aScrollAreaID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change scrollbar styles from hidden to auto. That makes us to create an
|
||||||
|
* accessible for scroll area.
|
||||||
|
*/
|
||||||
|
function changeScrollbarStyles(aContainerID, aScrollAreaID)
|
||||||
|
{
|
||||||
|
this.container = getAccessible(aContainerID);
|
||||||
|
this.scrollAreaNode = getNode(aScrollAreaID);
|
||||||
|
|
||||||
|
this.eventSeq = [
|
||||||
|
new invokerChecker(EVENT_SHOW, getAccessible, this.scrollAreaNode),
|
||||||
|
new invokerChecker(EVENT_REORDER, this.container)
|
||||||
|
];
|
||||||
|
|
||||||
|
this.invoke = function changeScrollbarStyles_invoke()
|
||||||
|
{
|
||||||
|
var accTree =
|
||||||
|
{ SECTION: [] };
|
||||||
|
testAccessibleTree(this.container, accTree);
|
||||||
|
|
||||||
|
this.scrollAreaNode.style.overflow = "auto";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.finalCheck = function changeScrollbarStyles_finalCheck()
|
||||||
|
{
|
||||||
|
var accTree =
|
||||||
|
{ SECTION: [ // container
|
||||||
|
{ SECTION: [] } // scroll area
|
||||||
|
] };
|
||||||
|
testAccessibleTree(this.container, accTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function changeScrollbarStyles_getID()
|
||||||
|
{
|
||||||
|
return "change scrollbar styles " + prettyName(aScrollAreaID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Do tests
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var gQueue = null;
|
||||||
|
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||||
|
//gA11yEventDumpToConsole = true;
|
||||||
|
|
||||||
|
function doTests()
|
||||||
|
{
|
||||||
|
gQueue = new eventQueue();
|
||||||
|
|
||||||
|
gQueue.push(new changeScrollRange("container", "scrollarea"));
|
||||||
|
gQueue.push(new changeScrollbarStyles("container2", "scrollarea2"));
|
||||||
|
|
||||||
|
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
addA11yLoadEvent(doTests);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<a target="_blank"
|
||||||
|
href="https://bugzilla.mozilla.org/show_bug.cgi?id=677154"
|
||||||
|
title="Detached document accessibility tree">
|
||||||
|
Mozilla Bug 677154</a>
|
||||||
|
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none"></div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
<div id="eventdump"></div>
|
||||||
|
|
||||||
|
<div id="container"><div id="scrollarea" style="overflow:auto;"><input></div></div>
|
||||||
|
<div id="container2"><div id="scrollarea2" style="overflow:hidden;"></div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -17,6 +17,7 @@ builtin(include, build/autoconf/acwinpaths.m4)dnl
|
||||||
builtin(include, build/autoconf/lto.m4)dnl
|
builtin(include, build/autoconf/lto.m4)dnl
|
||||||
builtin(include, build/autoconf/gcc-pr49911.m4)dnl
|
builtin(include, build/autoconf/gcc-pr49911.m4)dnl
|
||||||
builtin(include, build/autoconf/frameptr.m4)dnl
|
builtin(include, build/autoconf/frameptr.m4)dnl
|
||||||
|
builtin(include, build/autoconf/compiler-opts.m4)dnl
|
||||||
|
|
||||||
MOZ_PROG_CHECKMSYS()
|
MOZ_PROG_CHECKMSYS()
|
||||||
|
|
||||||
|
|
|
@ -426,7 +426,13 @@ pref("media.realtime_decoder.enabled", true);
|
||||||
// by bug 710563.
|
// by bug 710563.
|
||||||
pref("layout.frame_rate.precise", true);
|
pref("layout.frame_rate.precise", true);
|
||||||
|
|
||||||
|
// Temporary remote js console hack
|
||||||
|
pref("b2g.remote-js.enabled", true);
|
||||||
|
pref("b2g.remote-js.port", 9999);
|
||||||
|
|
||||||
// Screen timeout in minutes
|
// Screen timeout in minutes
|
||||||
pref("power.screen.timeout", 60);
|
pref("power.screen.timeout", 60);
|
||||||
|
|
||||||
pref("full-screen-api.enabled", true);
|
pref("full-screen-api.enabled", true);
|
||||||
|
|
||||||
|
pref("media.volume.steps", 10);
|
||||||
|
|
|
@ -8,6 +8,7 @@ const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
const CC = Components.Constructor;
|
const CC = Components.Constructor;
|
||||||
|
const Cr = Components.results;
|
||||||
|
|
||||||
const LocalFile = CC('@mozilla.org/file/local;1',
|
const LocalFile = CC('@mozilla.org/file/local;1',
|
||||||
'nsILocalFile',
|
'nsILocalFile',
|
||||||
|
@ -25,11 +26,18 @@ XPCOMUtils.defineLazyGetter(Services, 'ss', function() {
|
||||||
return Cc['@mozilla.org/content/style-sheet-service;1']
|
return Cc['@mozilla.org/content/style-sheet-service;1']
|
||||||
.getService(Ci.nsIStyleSheetService);
|
.getService(Ci.nsIStyleSheetService);
|
||||||
});
|
});
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(Services, 'idle', function() {
|
XPCOMUtils.defineLazyGetter(Services, 'idle', function() {
|
||||||
return Cc['@mozilla.org/widget/idleservice;1']
|
return Cc['@mozilla.org/widget/idleservice;1']
|
||||||
.getService(Ci.nsIIdleService);
|
.getService(Ci.nsIIdleService);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyServiceGetter(Services, 'fm', function(){
|
||||||
|
return Cc['@mozilla.org/focus-managr;1']
|
||||||
|
.getService(Ci.nsFocusManager);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// In order to use http:// scheme instead of file:// scheme
|
// In order to use http:// scheme instead of file:// scheme
|
||||||
// (that is much more restricted) the following code kick-off
|
// (that is much more restricted) the following code kick-off
|
||||||
// a local http server listening on http://127.0.0.1:7777 and
|
// a local http server listening on http://127.0.0.1:7777 and
|
||||||
|
@ -105,6 +113,7 @@ var shell = {
|
||||||
window.addEventListener('keypress', this);
|
window.addEventListener('keypress', this);
|
||||||
window.addEventListener('MozApplicationManifest', this);
|
window.addEventListener('MozApplicationManifest', this);
|
||||||
window.addEventListener("AppCommand", this);
|
window.addEventListener("AppCommand", this);
|
||||||
|
window.addEventListener('mozfullscreenchange', this);
|
||||||
this.contentBrowser.addEventListener('load', this, true);
|
this.contentBrowser.addEventListener('load', this, true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -186,6 +195,24 @@ var shell = {
|
||||||
Services.prefs.setBoolPref("nglayout.debug.paint_flashing", false);
|
Services.prefs.setBoolPref("nglayout.debug.paint_flashing", false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
changeVolume: function shell_changeVolume(aDelta) {
|
||||||
|
let audioManager = Cc["@mozilla.org/telephony/audiomanager;1"].getService(Ci.nsIAudioManager);
|
||||||
|
|
||||||
|
let steps = 10;
|
||||||
|
try {
|
||||||
|
steps = Services.prefs.getIntPref("media.volume.steps");
|
||||||
|
if (steps <= 0)
|
||||||
|
steps = 1;
|
||||||
|
} catch(e) {}
|
||||||
|
|
||||||
|
let volume = audioManager.masterVolume + aDelta / steps;
|
||||||
|
if (volume > 1)
|
||||||
|
volume = 1;
|
||||||
|
if (volume < 0)
|
||||||
|
volume = 0;
|
||||||
|
audioManager.masterVolume = volume;
|
||||||
|
},
|
||||||
|
|
||||||
handleEvent: function shell_handleEvent(evt) {
|
handleEvent: function shell_handleEvent(evt) {
|
||||||
switch (evt.type) {
|
switch (evt.type) {
|
||||||
|
@ -217,8 +244,22 @@ var shell = {
|
||||||
case 'Search':
|
case 'Search':
|
||||||
this.toggleDebug();
|
this.toggleDebug();
|
||||||
break;
|
break;
|
||||||
|
case 'VolumeUp':
|
||||||
|
this.changeVolume(1);
|
||||||
|
break;
|
||||||
|
case 'VolumeDown':
|
||||||
|
this.changeVolume(-1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'mozfullscreenchange':
|
||||||
|
// When the screen goes fullscreen make sure to set the focus to the
|
||||||
|
// main window so noboby can prevent the ESC key to get out fullscreen
|
||||||
|
// mode
|
||||||
|
if (document.mozFullScreen)
|
||||||
|
Services.fm.focusedWindow = window;
|
||||||
|
break;
|
||||||
case 'load':
|
case 'load':
|
||||||
this.contentBrowser.removeEventListener('load', this, true);
|
this.contentBrowser.removeEventListener('load', this, true);
|
||||||
this.turnScreenOn();
|
this.turnScreenOn();
|
||||||
|
@ -339,3 +380,50 @@ Services.obs.addObserver(function onConsoleAPILogEvent(subject, topic, data) {
|
||||||
" in " + (message.functionName || "anonymous") + ": ";
|
" in " + (message.functionName || "anonymous") + ": ";
|
||||||
Services.console.logStringMessage(prefix + Array.join(message.arguments, " "));
|
Services.console.logStringMessage(prefix + Array.join(message.arguments, " "));
|
||||||
}, "console-api-log-event", false);
|
}, "console-api-log-event", false);
|
||||||
|
|
||||||
|
(function Repl() {
|
||||||
|
if (!Services.prefs.getBoolPref('b2g.remote-js.enabled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const prompt = 'JS> ';
|
||||||
|
let output;
|
||||||
|
let reader = {
|
||||||
|
onInputStreamReady : function repl_readInput(input) {
|
||||||
|
let sin = Cc['@mozilla.org/scriptableinputstream;1']
|
||||||
|
.createInstance(Ci.nsIScriptableInputStream);
|
||||||
|
sin.init(input);
|
||||||
|
try {
|
||||||
|
let val = eval(sin.read(sin.available()));
|
||||||
|
let ret = (typeof val === 'undefined') ? 'undefined\n' : val + '\n';
|
||||||
|
output.write(ret, ret.length);
|
||||||
|
// TODO: check if socket has been closed
|
||||||
|
} catch (e) {
|
||||||
|
if (e.result === Cr.NS_BASE_STREAM_CLOSED ||
|
||||||
|
(typeof e === 'object' && e.result === Cr.NS_BASE_STREAM_CLOSED)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let message = (typeof e === 'object') ? e.message + '\n' : e + '\n';
|
||||||
|
output.write(message, message.length);
|
||||||
|
}
|
||||||
|
output.write(prompt, prompt.length);
|
||||||
|
input.asyncWait(reader, 0, 0, Services.tm.mainThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let listener = {
|
||||||
|
onSocketAccepted: function repl_acceptConnection(serverSocket, clientSocket) {
|
||||||
|
dump('Accepted connection on ' + clientSocket.host + '\n');
|
||||||
|
let input = clientSocket.openInputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0)
|
||||||
|
.QueryInterface(Ci.nsIAsyncInputStream);
|
||||||
|
output = clientSocket.openOutputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0);
|
||||||
|
output.write(prompt, prompt.length);
|
||||||
|
input.asyncWait(reader, 0, 0, Services.tm.mainThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let serverPort = Services.prefs.getIntPref('b2g.remote-js.port');
|
||||||
|
let serverSocket = Cc['@mozilla.org/network/server-socket;1']
|
||||||
|
.createInstance(Ci.nsIServerSocket);
|
||||||
|
serverSocket.init(serverPort, true, -1);
|
||||||
|
dump('Opened socket on ' + serverSocket.port + '\n');
|
||||||
|
serverSocket.asyncListen(listener);
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
|
@ -177,19 +177,22 @@ const ContentPanning = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
position: {
|
position: new Point(0 , 0),
|
||||||
origin: new Point(0, 0),
|
|
||||||
current: new Point(0 , 0)
|
|
||||||
},
|
|
||||||
|
|
||||||
onTouchStart: function cp_onTouchStart(evt) {
|
onTouchStart: function cp_onTouchStart(evt) {
|
||||||
this.dragging = true;
|
this.dragging = true;
|
||||||
KineticPanning.stop();
|
|
||||||
|
// If there is a pan animation running (from a previous pan gesture) and
|
||||||
|
// the user touch back the screen, stop this animation immediatly and
|
||||||
|
// prevent the possible click action.
|
||||||
|
if (KineticPanning.active) {
|
||||||
|
KineticPanning.stop();
|
||||||
|
this.preventNextClick = true;
|
||||||
|
}
|
||||||
|
|
||||||
this.scrollCallback = this.getPannable(evt.originalTarget);
|
this.scrollCallback = this.getPannable(evt.originalTarget);
|
||||||
this.position.origin.set(evt.screenX, evt.screenY);
|
this.position.set(evt.screenX, evt.screenY);
|
||||||
this.position.current.set(evt.screenX, evt.screenY);
|
KineticPanning.record(new Point(0, 0), evt.timeStamp);
|
||||||
KineticPanning.record(new Point(0, 0));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onTouchEnd: function cp_onTouchEnd(evt) {
|
onTouchEnd: function cp_onTouchEnd(evt) {
|
||||||
|
@ -197,26 +200,29 @@ const ContentPanning = {
|
||||||
return;
|
return;
|
||||||
this.dragging = false;
|
this.dragging = false;
|
||||||
|
|
||||||
if (this.isPan()) {
|
this.onTouchMove(evt);
|
||||||
if (evt.detail) // The event will generate a click
|
|
||||||
evt.target.addEventListener('click', this, true);
|
|
||||||
|
|
||||||
|
let pan = KineticPanning.isPan();
|
||||||
|
let click = evt.detail;
|
||||||
|
if (click && (pan || this.preventNextClick))
|
||||||
|
evt.target.addEventListener('click', this, true);
|
||||||
|
|
||||||
|
this.preventNextClick = false;
|
||||||
|
|
||||||
|
if (pan)
|
||||||
KineticPanning.start(this);
|
KineticPanning.start(this);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onTouchMove: function cp_onTouchMove(evt) {
|
onTouchMove: function cp_onTouchMove(evt) {
|
||||||
if (!this.dragging || !this.scrollCallback)
|
if (!this.dragging || !this.scrollCallback)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let current = this.position.current;
|
let current = this.position;
|
||||||
let delta = new Point(evt.screenX - current.x, evt.screenY - current.y);
|
let delta = new Point(evt.screenX - current.x, evt.screenY - current.y);
|
||||||
current.set(evt.screenX, evt.screenY);
|
current.set(evt.screenX, evt.screenY);
|
||||||
|
|
||||||
if (this.isPan()) {
|
KineticPanning.record(delta, evt.timeStamp);
|
||||||
KineticPanning.record(delta);
|
this.scrollCallback(delta.scale(-1));
|
||||||
this.scrollCallback(delta.scale(-1));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -232,24 +238,11 @@ const ContentPanning = {
|
||||||
this.scrollCallback = null;
|
this.scrollCallback = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
isPan: function cp_isPan() {
|
|
||||||
let dpi = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils)
|
|
||||||
.displayDPI;
|
|
||||||
|
|
||||||
let threshold = Services.prefs.getIntPref('ui.dragThresholdX') / 240 * dpi;
|
|
||||||
|
|
||||||
let deltaX = this.position.origin.x - this.position.current.x;
|
|
||||||
let deltaY = this.position.origin.y - this.position.current.y;
|
|
||||||
return (Math.abs(deltaX) > threshold || Math.abs(deltaY) > threshold);
|
|
||||||
},
|
|
||||||
|
|
||||||
getPannable: function cp_getPannable(node) {
|
getPannable: function cp_getPannable(node) {
|
||||||
if (!(node instanceof Ci.nsIDOMHTMLElement) || node.tagName == 'HTML')
|
if (!(node instanceof Ci.nsIDOMHTMLElement) || node.tagName == 'HTML')
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
let content = node.ownerDocument.defaultView;
|
let content = node.ownerDocument.defaultView;
|
||||||
|
|
||||||
while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) {
|
while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) {
|
||||||
let style = content.getComputedStyle(node, null);
|
let style = content.getComputedStyle(node, null);
|
||||||
|
|
||||||
|
@ -299,7 +292,7 @@ const kMinVelocity = 0.4;
|
||||||
const kMaxVelocity = 6;
|
const kMaxVelocity = 6;
|
||||||
|
|
||||||
// Constants that affect the "friction" of the scroll pane.
|
// Constants that affect the "friction" of the scroll pane.
|
||||||
const kExponentialC = 1400;
|
const kExponentialC = 1000;
|
||||||
const kPolynomialC = 100 / 1000000;
|
const kPolynomialC = 100 / 1000000;
|
||||||
|
|
||||||
// How often do we change the position of the scroll pane?
|
// How often do we change the position of the scroll pane?
|
||||||
|
@ -307,17 +300,25 @@ const kPolynomialC = 100 / 1000000;
|
||||||
// Too little and panning will be choppy. In milliseconds.
|
// Too little and panning will be choppy. In milliseconds.
|
||||||
const kUpdateInterval = 16;
|
const kUpdateInterval = 16;
|
||||||
|
|
||||||
|
// The numbers of momentums to use for calculating the velocity of the pan.
|
||||||
|
// Those are taken from the end of the action
|
||||||
|
const kSamples = 5;
|
||||||
|
|
||||||
const KineticPanning = {
|
const KineticPanning = {
|
||||||
_position: new Point(0, 0),
|
_position: new Point(0, 0),
|
||||||
_velocity: new Point(0, 0),
|
_velocity: new Point(0, 0),
|
||||||
_acceleration: new Point(0, 0),
|
_acceleration: new Point(0, 0),
|
||||||
|
|
||||||
|
get active() {
|
||||||
|
return this.target !== null;
|
||||||
|
},
|
||||||
|
|
||||||
_target: null,
|
_target: null,
|
||||||
start: function kp_start(target) {
|
start: function kp_start(target) {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
|
||||||
// Calculate the initial velocity of the movement based on user input
|
// Calculate the initial velocity of the movement based on user input
|
||||||
let momentums = this.momentums;
|
let momentums = this.momentums.slice(-kSamples);
|
||||||
|
|
||||||
let distance = new Point(0, 0);
|
let distance = new Point(0, 0);
|
||||||
momentums.forEach(function(momentum) {
|
momentums.forEach(function(momentum) {
|
||||||
|
@ -338,6 +339,7 @@ const KineticPanning = {
|
||||||
let velocity = this._velocity;
|
let velocity = this._velocity;
|
||||||
velocity.set(Math.abs(velocityX) < kMinVelocity ? 0 : velocityX,
|
velocity.set(Math.abs(velocityX) < kMinVelocity ? 0 : velocityX,
|
||||||
Math.abs(velocityY) < kMinVelocity ? 0 : velocityY);
|
Math.abs(velocityY) < kMinVelocity ? 0 : velocityY);
|
||||||
|
this.momentums = [];
|
||||||
|
|
||||||
// Set acceleration vector to opposite signs of velocity
|
// Set acceleration vector to opposite signs of velocity
|
||||||
function sign(x) {
|
function sign(x) {
|
||||||
|
@ -358,20 +360,32 @@ const KineticPanning = {
|
||||||
if (!this.target)
|
if (!this.target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.momentums.splice(0);
|
this.momentums = [];
|
||||||
|
|
||||||
this.target.onKineticEnd();
|
this.target.onKineticEnd();
|
||||||
this.target = null;
|
this.target = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
momentums: [],
|
momentums: [],
|
||||||
record: function kp_record(delta) {
|
record: function kp_record(delta, timestamp) {
|
||||||
// If the panning direction has changed, stop the current activity.
|
this.momentums.push({ 'time': timestamp, 'dx' : delta.x, 'dy' : delta.y });
|
||||||
if (this.target && ((delta.x * this._velocity.x < 0) ||
|
},
|
||||||
(delta.y * this._velocity.y < 0)))
|
|
||||||
this.stop();
|
|
||||||
|
|
||||||
this.momentums.push({ 'time': Date.now(), 'dx' : delta.x, 'dy' : delta.y });
|
isPan: function cp_isPan() {
|
||||||
|
let dpi = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDOMWindowUtils)
|
||||||
|
.displayDPI;
|
||||||
|
|
||||||
|
let threshold = Services.prefs.getIntPref('ui.dragThresholdX') / 240 * dpi;
|
||||||
|
|
||||||
|
let deltaX = 0;
|
||||||
|
let deltaY = 0;
|
||||||
|
let start = this.momentums[0].time;
|
||||||
|
return this.momentums.slice(1).some(function(momentum) {
|
||||||
|
deltaX += momentum.dx;
|
||||||
|
deltaY += momentum.dy;
|
||||||
|
return (Math.abs(deltaX) > threshold) || (Math.abs(deltaY) > threshold);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_startAnimation: function kp_startAnimation() {
|
_startAnimation: function kp_startAnimation() {
|
||||||
|
|
|
@ -282,6 +282,7 @@ pref("browser.urlbar.doubleClickSelectsAll", true);
|
||||||
pref("browser.urlbar.doubleClickSelectsAll", false);
|
pref("browser.urlbar.doubleClickSelectsAll", false);
|
||||||
#endif
|
#endif
|
||||||
pref("browser.urlbar.autoFill", false);
|
pref("browser.urlbar.autoFill", false);
|
||||||
|
pref("browser.urlbar.autoFill.typed", true);
|
||||||
// 0: Match anywhere (e.g., middle of words)
|
// 0: Match anywhere (e.g., middle of words)
|
||||||
// 1: Match on word boundaries and then try matching anywhere
|
// 1: Match on word boundaries and then try matching anywhere
|
||||||
// 2: Match only on word boundaries (e.g., after / or .)
|
// 2: Match only on word boundaries (e.g., after / or .)
|
||||||
|
|
|
@ -9053,7 +9053,14 @@ XPCOMUtils.defineLazyGetter(Scratchpad, "ScratchpadManager", function() {
|
||||||
|
|
||||||
var StyleEditor = {
|
var StyleEditor = {
|
||||||
prefEnabledName: "devtools.styleeditor.enabled",
|
prefEnabledName: "devtools.styleeditor.enabled",
|
||||||
openChrome: function SE_openChrome()
|
/**
|
||||||
|
* Opens the style editor. If the UI is already open, it will be focused.
|
||||||
|
*
|
||||||
|
* @param {CSSStyleSheet} [aSelectedStyleSheet] default Stylesheet.
|
||||||
|
* @param {Number} [aLine] Line to which the caret should be moved (one-indexed).
|
||||||
|
* @param {Number} [aCol] Column to which the caret should be moved (one-indexed).
|
||||||
|
*/
|
||||||
|
openChrome: function SE_openChrome(aSelectedStyleSheet, aLine, aCol)
|
||||||
{
|
{
|
||||||
const CHROME_URL = "chrome://browser/content/styleeditor.xul";
|
const CHROME_URL = "chrome://browser/content/styleeditor.xul";
|
||||||
const CHROME_WINDOW_TYPE = "Tools:StyleEditor";
|
const CHROME_WINDOW_TYPE = "Tools:StyleEditor";
|
||||||
|
@ -9067,14 +9074,23 @@ var StyleEditor = {
|
||||||
while (enumerator.hasMoreElements()) {
|
while (enumerator.hasMoreElements()) {
|
||||||
var win = enumerator.getNext();
|
var win = enumerator.getNext();
|
||||||
if (win.styleEditorChrome.contentWindowID == contentWindowID) {
|
if (win.styleEditorChrome.contentWindowID == contentWindowID) {
|
||||||
|
if (aSelectedStyleSheet) {
|
||||||
|
win.styleEditorChrome.selectStyleSheet(aSelectedStyleSheet, aLine, aCol);
|
||||||
|
}
|
||||||
win.focus();
|
win.focus();
|
||||||
return win;
|
return win;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let args = {
|
||||||
|
contentWindow: contentWindow,
|
||||||
|
selectedStyleSheet: aSelectedStyleSheet,
|
||||||
|
line: aLine,
|
||||||
|
col: aCol
|
||||||
|
};
|
||||||
|
args.wrappedJSObject = args;
|
||||||
let chromeWindow = Services.ww.openWindow(null, CHROME_URL, "_blank",
|
let chromeWindow = Services.ww.openWindow(null, CHROME_URL, "_blank",
|
||||||
CHROME_WINDOW_FLAGS,
|
CHROME_WINDOW_FLAGS, args);
|
||||||
contentWindow);
|
|
||||||
chromeWindow.focus();
|
chromeWindow.focus();
|
||||||
return chromeWindow;
|
return chromeWindow;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@
|
||||||
lightweightthemes="true"
|
lightweightthemes="true"
|
||||||
lightweightthemesfooter="browser-bottombox"
|
lightweightthemesfooter="browser-bottombox"
|
||||||
windowtype="navigator:browser"
|
windowtype="navigator:browser"
|
||||||
|
macanimationtype="document"
|
||||||
screenX="4" screenY="4"
|
screenX="4" screenY="4"
|
||||||
browsingmode="normal"
|
browsingmode="normal"
|
||||||
persist="screenX screenY width height sizemode">
|
persist="screenX screenY width height sizemode">
|
||||||
|
|
|
@ -536,7 +536,8 @@
|
||||||
if (!this.mBlank) {
|
if (!this.mBlank) {
|
||||||
if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
|
if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
|
||||||
this.mTab.setAttribute("busy", "true");
|
this.mTab.setAttribute("busy", "true");
|
||||||
this.mTabBrowser.setTabTitleLoading(this.mTab);
|
if (!(this.mBrowser.docShell.loadType & Ci.nsIDocShell.LOAD_CMD_RELOAD))
|
||||||
|
this.mTabBrowser.setTabTitleLoading(this.mTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mTab.selected)
|
if (this.mTab.selected)
|
||||||
|
@ -1265,6 +1266,12 @@
|
||||||
else {
|
else {
|
||||||
t._animStartTime = Date.now();
|
t._animStartTime = Date.now();
|
||||||
t.setAttribute("fadein", "true");
|
t.setAttribute("fadein", "true");
|
||||||
|
|
||||||
|
// This call to adjustTabstrip is redundant but needed so that
|
||||||
|
// when opening a second tab, the first tab's close buttons
|
||||||
|
// appears immediately rather than when the transition ends.
|
||||||
|
if (tabContainer.childNodes.length == 2)
|
||||||
|
tabContainer.adjustTabstrip();
|
||||||
}
|
}
|
||||||
}, 0, this.tabContainer);
|
}, 0, this.tabContainer);
|
||||||
}
|
}
|
||||||
|
@ -1364,7 +1371,8 @@
|
||||||
|
|
||||||
// pretend the user typed this so it'll be available till
|
// pretend the user typed this so it'll be available till
|
||||||
// the document successfully loads
|
// the document successfully loads
|
||||||
b.userTypedValue = aURI;
|
if (!isBlankPageURL(aURI))
|
||||||
|
b.userTypedValue = aURI;
|
||||||
|
|
||||||
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
||||||
if (aAllowThirdPartyFixup)
|
if (aAllowThirdPartyFixup)
|
||||||
|
@ -1556,15 +1564,26 @@
|
||||||
<parameter name="aCloseWindowFastpath"/>
|
<parameter name="aCloseWindowFastpath"/>
|
||||||
<body>
|
<body>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
if (aTab.closing || this._windowIsClosing)
|
if (aTab.closing ||
|
||||||
|
aTab._pendingPermitUnload ||
|
||||||
|
this._windowIsClosing)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var browser = this.getBrowserForTab(aTab);
|
var browser = this.getBrowserForTab(aTab);
|
||||||
|
|
||||||
if (!aTabWillBeMoved) {
|
if (!aTabWillBeMoved) {
|
||||||
let ds = browser.docShell;
|
let ds = browser.docShell;
|
||||||
if (ds && ds.contentViewer && !ds.contentViewer.permitUnload())
|
if (ds && ds.contentViewer) {
|
||||||
return false;
|
// We need to block while calling permitUnload() because it
|
||||||
|
// processes the event queue and may lead to another removeTab()
|
||||||
|
// call before permitUnload() even returned.
|
||||||
|
aTab._pendingPermitUnload = true;
|
||||||
|
let permitUnload = ds.contentViewer.permitUnload();
|
||||||
|
delete aTab._pendingPermitUnload;
|
||||||
|
|
||||||
|
if (!permitUnload)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var closeWindow = false;
|
var closeWindow = false;
|
||||||
|
@ -3983,24 +4002,18 @@
|
||||||
|
|
||||||
<implementation implements="nsIDOMEventListener">
|
<implementation implements="nsIDOMEventListener">
|
||||||
<constructor><![CDATA[
|
<constructor><![CDATA[
|
||||||
window.addEventListener("findbaropen", this, false);
|
|
||||||
window.addEventListener("resize", this, false);
|
window.addEventListener("resize", this, false);
|
||||||
]]></constructor>
|
]]></constructor>
|
||||||
|
|
||||||
<destructor><![CDATA[
|
<destructor><![CDATA[
|
||||||
window.removeEventListener("findbaropen", this, false);
|
|
||||||
window.removeEventListener("resize", this, false);
|
window.removeEventListener("resize", this, false);
|
||||||
MousePosTracker.removeListener(this);
|
MousePosTracker.removeListener(this);
|
||||||
]]></destructor>
|
]]></destructor>
|
||||||
|
|
||||||
<property name="label">
|
<property name="label">
|
||||||
<setter><![CDATA[
|
<setter><![CDATA[
|
||||||
if (!this.label) {
|
if (!this.label)
|
||||||
if (window.gFindBarInitialized && !window.gFindBar.hidden)
|
this.removeAttribute("mirror");
|
||||||
this.setAttribute("mirror", "true");
|
|
||||||
else
|
|
||||||
this.removeAttribute("mirror");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.style.minWidth = this.getAttribute("type") == "status" &&
|
this.style.minWidth = this.getAttribute("type") == "status" &&
|
||||||
this.getAttribute("previoustype") == "status"
|
this.getAttribute("previoustype") == "status"
|
||||||
|
@ -4048,10 +4061,6 @@
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case "findbaropen":
|
|
||||||
this.setAttribute("mirror", "true");
|
|
||||||
this._calcMouseTargetRect();
|
|
||||||
break;
|
|
||||||
case "resize":
|
case "resize":
|
||||||
this._calcMouseTargetRect();
|
this._calcMouseTargetRect();
|
||||||
break;
|
break;
|
||||||
|
@ -4061,10 +4070,10 @@
|
||||||
|
|
||||||
<method name="_calcMouseTargetRect">
|
<method name="_calcMouseTargetRect">
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
let alignRight = (window.gFindBarInitialized && !window.gFindBar.hidden);
|
let alignRight = false;
|
||||||
|
|
||||||
if (getComputedStyle(document.documentElement).direction == "rtl")
|
if (getComputedStyle(document.documentElement).direction == "rtl")
|
||||||
alighRight = !alignRight;
|
alignRight = !alignRight;
|
||||||
|
|
||||||
let rect = this.getBoundingClientRect();
|
let rect = this.getBoundingClientRect();
|
||||||
this._mouseTargetRect = {
|
this._mouseTargetRect = {
|
||||||
|
|
|
@ -15,24 +15,26 @@ function reallyHandleRequest(request, response) {
|
||||||
|
|
||||||
// Allow the caller to drive how authentication is processed via the query.
|
// Allow the caller to drive how authentication is processed via the query.
|
||||||
// Eg, http://localhost:8888/authenticate.sjs?user=foo&realm=bar
|
// Eg, http://localhost:8888/authenticate.sjs?user=foo&realm=bar
|
||||||
var query = request.queryString;
|
// The extra ? allows the user/pass/realm checks to succeed if the name is
|
||||||
|
// at the beginning of the query string.
|
||||||
|
var query = "?" + request.queryString;
|
||||||
|
|
||||||
var expected_user = "", expected_pass = "", realm = "mochitest";
|
var expected_user = "", expected_pass = "", realm = "mochitest";
|
||||||
var proxy_expected_user = "", proxy_expected_pass = "", proxy_realm = "mochi-proxy";
|
var proxy_expected_user = "", proxy_expected_pass = "", proxy_realm = "mochi-proxy";
|
||||||
var huge = false, plugin = false;
|
var huge = false, plugin = false, anonymous = false;
|
||||||
var authHeaderCount = 1;
|
var authHeaderCount = 1;
|
||||||
// user=xxx
|
// user=xxx
|
||||||
match = /user=([^&]*)/.exec(query);
|
match = /[^_]user=([^&]*)/.exec(query);
|
||||||
if (match)
|
if (match)
|
||||||
expected_user = match[1];
|
expected_user = match[1];
|
||||||
|
|
||||||
// pass=xxx
|
// pass=xxx
|
||||||
match = /pass=([^&]*)/.exec(query);
|
match = /[^_]pass=([^&]*)/.exec(query);
|
||||||
if (match)
|
if (match)
|
||||||
expected_pass = match[1];
|
expected_pass = match[1];
|
||||||
|
|
||||||
// realm=xxx
|
// realm=xxx
|
||||||
match = /realm=([^&]*)/.exec(query);
|
match = /[^_]realm=([^&]*)/.exec(query);
|
||||||
if (match)
|
if (match)
|
||||||
realm = match[1];
|
realm = match[1];
|
||||||
|
|
||||||
|
@ -66,6 +68,10 @@ function reallyHandleRequest(request, response) {
|
||||||
if (match)
|
if (match)
|
||||||
authHeaderCount = match[1]+0;
|
authHeaderCount = match[1]+0;
|
||||||
|
|
||||||
|
// anonymous=1
|
||||||
|
match = /anonymous=1/.exec(query);
|
||||||
|
if (match)
|
||||||
|
anonymous = true;
|
||||||
|
|
||||||
// Look for an authentication header, if any, in the request.
|
// Look for an authentication header, if any, in the request.
|
||||||
//
|
//
|
||||||
|
@ -74,8 +80,9 @@ function reallyHandleRequest(request, response) {
|
||||||
// This test only supports Basic auth. The value sent by the client is
|
// This test only supports Basic auth. The value sent by the client is
|
||||||
// "username:password", obscured with base64 encoding.
|
// "username:password", obscured with base64 encoding.
|
||||||
|
|
||||||
var actual_user = "", actual_pass = "", authHeader;
|
var actual_user = "", actual_pass = "", authHeader, authPresent = false;
|
||||||
if (request.hasHeader("Authorization")) {
|
if (request.hasHeader("Authorization")) {
|
||||||
|
authPresent = true;
|
||||||
authHeader = request.getHeader("Authorization");
|
authHeader = request.getHeader("Authorization");
|
||||||
match = /Basic (.+)/.exec(authHeader);
|
match = /Basic (.+)/.exec(authHeader);
|
||||||
if (match.length != 2)
|
if (match.length != 2)
|
||||||
|
@ -115,16 +122,24 @@ function reallyHandleRequest(request, response) {
|
||||||
requestProxyAuth = false;
|
requestProxyAuth = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestProxyAuth) {
|
if (anonymous) {
|
||||||
response.setStatusLine("1.0", 407, "Proxy authentication required");
|
if (authPresent) {
|
||||||
for (i = 0; i < authHeaderCount; ++i)
|
response.setStatusLine("1.0", 400, "Unexpected authorization header found");
|
||||||
response.setHeader("Proxy-Authenticate", "basic realm=\"" + proxy_realm + "\"", true);
|
} else {
|
||||||
} else if (requestAuth) {
|
response.setStatusLine("1.0", 200, "Authorization header not found");
|
||||||
response.setStatusLine("1.0", 401, "Authentication required");
|
}
|
||||||
for (i = 0; i < authHeaderCount; ++i)
|
|
||||||
response.setHeader("WWW-Authenticate", "basic realm=\"" + realm + "\"", true);
|
|
||||||
} else {
|
} else {
|
||||||
response.setStatusLine("1.0", 200, "OK");
|
if (requestProxyAuth) {
|
||||||
|
response.setStatusLine("1.0", 407, "Proxy authentication required");
|
||||||
|
for (i = 0; i < authHeaderCount; ++i)
|
||||||
|
response.setHeader("Proxy-Authenticate", "basic realm=\"" + proxy_realm + "\"", true);
|
||||||
|
} else if (requestAuth) {
|
||||||
|
response.setStatusLine("1.0", 401, "Authentication required");
|
||||||
|
for (i = 0; i < authHeaderCount; ++i)
|
||||||
|
response.setHeader("WWW-Authenticate", "basic realm=\"" + realm + "\"", true);
|
||||||
|
} else {
|
||||||
|
response.setStatusLine("1.0", 200, "OK");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response.setHeader("Content-Type", "application/xhtml+xml", false);
|
response.setHeader("Content-Type", "application/xhtml+xml", false);
|
||||||
|
|
|
@ -28,14 +28,18 @@ function test() {
|
||||||
executeSoon(function () {
|
executeSoon(function () {
|
||||||
let consoleListener = {
|
let consoleListener = {
|
||||||
observe: function (m) {
|
observe: function (m) {
|
||||||
|
info("m: " + m + "\n");
|
||||||
|
info("m.message: " + m.message + "\n");
|
||||||
if (m.message.indexOf("NS_ERROR_DOM_BAD_URI") > -1) {
|
if (m.message.indexOf("NS_ERROR_DOM_BAD_URI") > -1) {
|
||||||
Services.console.unregisterListener(consoleListener);
|
|
||||||
ok(true, "drop was blocked");
|
ok(true, "drop was blocked");
|
||||||
executeSoon(finish);
|
executeSoon(finish);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Services.console.registerListener(consoleListener);
|
Services.console.registerListener(consoleListener);
|
||||||
|
registerCleanupFunction(function () {
|
||||||
|
Services.console.unregisterListener(consoleListener);
|
||||||
|
});
|
||||||
|
|
||||||
// The drop handler throws an exception when dragging URIs that inherit
|
// The drop handler throws an exception when dragging URIs that inherit
|
||||||
// principal, e.g. javascript:
|
// principal, e.g. javascript:
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
MOZ_APP_DISPLAYNAME=Firefox
|
MOZ_APP_DISPLAYNAME=Firefox
|
||||||
MOZ_UA_BUILDID=20100101
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ const Cr = Components.results;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
Cu.import("resource:///modules/TelemetryStopwatch.jsm");
|
||||||
|
|
||||||
const STATE_RUNNING_STR = "running";
|
const STATE_RUNNING_STR = "running";
|
||||||
const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 megabytes
|
const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 megabytes
|
||||||
|
@ -127,23 +128,30 @@ SessionStartup.prototype = {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// parse the session state into a JS object
|
// parse the session state into a JS object
|
||||||
|
// remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
|
||||||
|
if (iniString.charAt(0) == '(')
|
||||||
|
iniString = iniString.slice(1, -1);
|
||||||
|
let corruptFile = false;
|
||||||
try {
|
try {
|
||||||
// remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
|
this._initialState = JSON.parse(iniString);
|
||||||
if (iniString.charAt(0) == '(')
|
}
|
||||||
iniString = iniString.slice(1, -1);
|
catch (ex) {
|
||||||
|
debug("The session file contained un-parse-able JSON: " + ex);
|
||||||
|
// Try to eval.
|
||||||
|
// evalInSandbox will throw if iniString is not parse-able.
|
||||||
try {
|
try {
|
||||||
this._initialState = JSON.parse(iniString);
|
|
||||||
}
|
|
||||||
catch (exJSON) {
|
|
||||||
var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
|
var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
|
||||||
this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
|
this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
|
||||||
|
} catch(ex) {
|
||||||
|
debug("The session file contained un-eval-able JSON: " + ex);
|
||||||
|
corruptFile = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a normal restore then throw away any previous session
|
|
||||||
if (!doResumeSessionOnce)
|
|
||||||
delete this._initialState.lastSessionState;
|
|
||||||
}
|
}
|
||||||
catch (ex) { debug("The session file is invalid: " + ex); }
|
Services.telemetry.getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE").add(corruptFile);
|
||||||
|
|
||||||
|
// If this is a normal restore then throw away any previous session
|
||||||
|
if (!doResumeSessionOnce)
|
||||||
|
delete this._initialState.lastSessionState;
|
||||||
|
|
||||||
let resumeFromCrash = prefBranch.getBoolPref("sessionstore.resume_from_crash");
|
let resumeFromCrash = prefBranch.getBoolPref("sessionstore.resume_from_crash");
|
||||||
let lastSessionCrashed =
|
let lastSessionCrashed =
|
||||||
|
@ -154,8 +162,7 @@ SessionStartup.prototype = {
|
||||||
// Report shutdown success via telemetry. Shortcoming here are
|
// Report shutdown success via telemetry. Shortcoming here are
|
||||||
// being-killed-by-OS-shutdown-logic, shutdown freezing after
|
// being-killed-by-OS-shutdown-logic, shutdown freezing after
|
||||||
// session restore was written, etc.
|
// session restore was written, etc.
|
||||||
let Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
|
Services.telemetry.getHistogramById("SHUTDOWN_OK").add(!lastSessionCrashed);
|
||||||
Telemetry.getHistogramById("SHUTDOWN_OK").add(!lastSessionCrashed);
|
|
||||||
|
|
||||||
// set the startup type
|
// set the startup type
|
||||||
if (lastSessionCrashed && resumeFromCrash)
|
if (lastSessionCrashed && resumeFromCrash)
|
||||||
|
@ -296,9 +303,11 @@ SessionStartup.prototype = {
|
||||||
* @returns a session state string
|
* @returns a session state string
|
||||||
*/
|
*/
|
||||||
_readStateFile: function sss_readStateFile(aFile) {
|
_readStateFile: function sss_readStateFile(aFile) {
|
||||||
|
TelemetryStopwatch.start("FX_SESSION_RESTORE_READ_FILE_MS");
|
||||||
var stateString = Cc["@mozilla.org/supports-string;1"].
|
var stateString = Cc["@mozilla.org/supports-string;1"].
|
||||||
createInstance(Ci.nsISupportsString);
|
createInstance(Ci.nsISupportsString);
|
||||||
stateString.data = this._readFile(aFile) || "";
|
stateString.data = this._readFile(aFile) || "";
|
||||||
|
TelemetryStopwatch.finish("FX_SESSION_RESTORE_READ_FILE_MS");
|
||||||
|
|
||||||
Services.obs.notifyObservers(stateString, "sessionstore-state-read", "");
|
Services.obs.notifyObservers(stateString, "sessionstore-state-read", "");
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/debug.js");
|
Cu.import("resource://gre/modules/debug.js");
|
||||||
|
|
||||||
Cu.import("resource:///modules/TelemetryTimestamps.jsm");
|
Cu.import("resource:///modules/TelemetryTimestamps.jsm");
|
||||||
|
Cu.import("resource:///modules/TelemetryStopwatch.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
||||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||||
|
@ -3653,6 +3654,8 @@ SessionStoreService.prototype = {
|
||||||
// if we crash.
|
// if we crash.
|
||||||
let pinnedOnly = this._loadState == STATE_RUNNING && !this._resume_from_crash;
|
let pinnedOnly = this._loadState == STATE_RUNNING && !this._resume_from_crash;
|
||||||
|
|
||||||
|
TelemetryStopwatch.start("FX_SESSION_RESTORE_COLLECT_DATA_MS");
|
||||||
|
|
||||||
var oState = this._getCurrentState(aUpdateAll, pinnedOnly);
|
var oState = this._getCurrentState(aUpdateAll, pinnedOnly);
|
||||||
if (!oState)
|
if (!oState)
|
||||||
return;
|
return;
|
||||||
|
@ -3691,6 +3694,8 @@ SessionStoreService.prototype = {
|
||||||
if (this._lastSessionState)
|
if (this._lastSessionState)
|
||||||
oState.lastSessionState = this._lastSessionState;
|
oState.lastSessionState = this._lastSessionState;
|
||||||
|
|
||||||
|
TelemetryStopwatch.finish("FX_SESSION_RESTORE_COLLECT_DATA_MS");
|
||||||
|
|
||||||
this._saveStateObject(oState);
|
this._saveStateObject(oState);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3698,9 +3703,11 @@ SessionStoreService.prototype = {
|
||||||
* write a state object to disk
|
* write a state object to disk
|
||||||
*/
|
*/
|
||||||
_saveStateObject: function sss_saveStateObject(aStateObj) {
|
_saveStateObject: function sss_saveStateObject(aStateObj) {
|
||||||
|
TelemetryStopwatch.start("FX_SESSION_RESTORE_SERIALIZE_DATA_MS");
|
||||||
var stateString = Cc["@mozilla.org/supports-string;1"].
|
var stateString = Cc["@mozilla.org/supports-string;1"].
|
||||||
createInstance(Ci.nsISupportsString);
|
createInstance(Ci.nsISupportsString);
|
||||||
stateString.data = this._toJSONString(aStateObj);
|
stateString.data = this._toJSONString(aStateObj);
|
||||||
|
TelemetryStopwatch.finish("FX_SESSION_RESTORE_SERIALIZE_DATA_MS");
|
||||||
|
|
||||||
Services.obs.notifyObservers(stateString, "sessionstore-state-write", "");
|
Services.obs.notifyObservers(stateString, "sessionstore-state-write", "");
|
||||||
|
|
||||||
|
@ -3809,7 +3816,7 @@ SessionStoreService.prototype = {
|
||||||
argString.data = "";
|
argString.data = "";
|
||||||
|
|
||||||
// Build feature string
|
// Build feature string
|
||||||
let features = "chrome,dialog=no,all";
|
let features = "chrome,dialog=no,macsuppressanimation,all";
|
||||||
let winState = aState.windows[0];
|
let winState = aState.windows[0];
|
||||||
WINDOW_ATTRIBUTES.forEach(function(aFeature) {
|
WINDOW_ATTRIBUTES.forEach(function(aFeature) {
|
||||||
// Use !isNaN as an easy way to ignore sizemode and check for numbers
|
// Use !isNaN as an easy way to ignore sizemode and check for numbers
|
||||||
|
@ -4427,6 +4434,7 @@ SessionStoreService.prototype = {
|
||||||
* String data
|
* String data
|
||||||
*/
|
*/
|
||||||
_writeFile: function sss_writeFile(aFile, aData) {
|
_writeFile: function sss_writeFile(aFile, aData) {
|
||||||
|
TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_MS");
|
||||||
// Initialize the file output stream.
|
// Initialize the file output stream.
|
||||||
var ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"].
|
var ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"].
|
||||||
createInstance(Ci.nsIFileOutputStream);
|
createInstance(Ci.nsIFileOutputStream);
|
||||||
|
@ -4442,6 +4450,7 @@ SessionStoreService.prototype = {
|
||||||
var self = this;
|
var self = this;
|
||||||
NetUtil.asyncCopy(istream, ostream, function(rc) {
|
NetUtil.asyncCopy(istream, ostream, function(rc) {
|
||||||
if (Components.isSuccessCode(rc)) {
|
if (Components.isSuccessCode(rc)) {
|
||||||
|
TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_MS");
|
||||||
Services.obs.notifyObservers(null,
|
Services.obs.notifyObservers(null,
|
||||||
"sessionstore-state-write-complete",
|
"sessionstore-state-write-complete",
|
||||||
"");
|
"");
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
. $topsrcdir/build/macosx/universal/mozconfig
|
||||||
|
|
||||||
|
# Universal builds override the default of browser (bug 575283 comment 29)
|
||||||
|
ac_add_options --enable-application=browser
|
||||||
|
|
||||||
|
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||||
|
ac_add_options --enable-update-packaging
|
||||||
|
ac_add_options --enable-codesighs
|
||||||
|
ac_add_options --disable-install-strip
|
||||||
|
|
||||||
|
# Nightlies only since this has a cost in performance
|
||||||
|
ac_add_options --enable-js-diagnostics
|
||||||
|
|
||||||
|
# Needed to enable breakpad in application.ini
|
||||||
|
export MOZILLA_OFFICIAL=1
|
||||||
|
|
||||||
|
export MOZ_TELEMETRY_REPORTING=1
|
||||||
|
mk_add_options MOZ_MAKE_FLAGS="-j12"
|
||||||
|
|
||||||
|
ac_add_options --with-macbundlename-prefix=Firefox
|
||||||
|
|
||||||
|
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||||
|
ac_add_options --enable-warnings-as-errors
|
||||||
|
ac_add_options --with-ccache
|
|
@ -0,0 +1,20 @@
|
||||||
|
. $topsrcdir/build/macosx/universal/mozconfig
|
||||||
|
|
||||||
|
# Universal builds override the default of browser (bug 575283 comment 29)
|
||||||
|
ac_add_options --enable-application=browser
|
||||||
|
|
||||||
|
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||||
|
ac_add_options --enable-update-packaging
|
||||||
|
ac_add_options --enable-official-branding
|
||||||
|
|
||||||
|
# Needed to enable breakpad in application.ini
|
||||||
|
export MOZILLA_OFFICIAL=1
|
||||||
|
|
||||||
|
export MOZ_TELEMETRY_REPORTING=1
|
||||||
|
|
||||||
|
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||||
|
ac_add_options --enable-warnings-as-errors
|
||||||
|
|
||||||
|
# Enable parallel compiling
|
||||||
|
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
||||||
|
ac_add_options --with-ccache
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Just like nightlies, but without tests, not on an update channel, and with
|
||||||
|
# shark and dtrace enabled
|
||||||
|
. $topsrcdir/build/macosx/universal/mozconfig
|
||||||
|
|
||||||
|
# Universal builds override the default of browser (bug 575283 comment 29)
|
||||||
|
ac_add_options --enable-application=browser
|
||||||
|
|
||||||
|
ac_add_options --disable-tests
|
||||||
|
ac_add_options --disable-install-strip
|
||||||
|
|
||||||
|
# Needed to enable breakpad in application.ini
|
||||||
|
export MOZILLA_OFFICIAL=1
|
||||||
|
|
||||||
|
# Enable parallel compiling
|
||||||
|
mk_add_options MOZ_MAKE_FLAGS="-j12"
|
||||||
|
|
||||||
|
# shark specific options
|
||||||
|
ac_add_options --enable-shark
|
||||||
|
ac_add_options --enable-dtrace
|
||||||
|
|
||||||
|
# Need this to prevent name conflicts with the normal nightly build packages
|
||||||
|
export MOZ_PKG_SPECIAL="shark"
|
||||||
|
|
||||||
|
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||||
|
ac_add_options --enable-warnings-as-errors
|
||||||
|
ac_add_options --with-ccache
|
|
@ -0,0 +1,12 @@
|
||||||
|
. $topsrcdir/build/macosx/mozconfig.leopard
|
||||||
|
ac_add_options --enable-debug
|
||||||
|
ac_add_options --enable-trace-malloc
|
||||||
|
|
||||||
|
# Enable parallel compiling
|
||||||
|
mk_add_options MOZ_MAKE_FLAGS="-j12"
|
||||||
|
|
||||||
|
# Needed to enable breakpad in application.ini
|
||||||
|
export MOZILLA_OFFICIAL=1
|
||||||
|
|
||||||
|
ac_add_options --with-macbundlename-prefix=Firefox
|
||||||
|
ac_add_options --with-ccache
|
|
@ -0,0 +1,17 @@
|
||||||
|
. $topsrcdir/build/macosx/common
|
||||||
|
|
||||||
|
ac_add_options --enable-debug
|
||||||
|
ac_add_options --enable-trace-malloc
|
||||||
|
ac_add_options --enable-accessibility
|
||||||
|
|
||||||
|
# Enable parallel compiling
|
||||||
|
mk_add_options MOZ_MAKE_FLAGS="-j12"
|
||||||
|
|
||||||
|
# Needed to enable breakpad in application.ini
|
||||||
|
export MOZILLA_OFFICIAL=1
|
||||||
|
|
||||||
|
ac_add_options --with-macbundlename-prefix=Firefox
|
||||||
|
|
||||||
|
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||||
|
ac_add_options --enable-warnings-as-errors
|
||||||
|
ac_add_options --with-ccache
|
|
@ -0,0 +1,5 @@
|
||||||
|
ac_add_options --with-l10n-base=../../l10n-central
|
||||||
|
ac_add_options --enable-official-branding
|
||||||
|
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||||
|
ac_add_options --enable-update-packaging
|
||||||
|
ac_add_options --with-ccache
|
|
@ -72,6 +72,7 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_dbg_pause-resume.js \
|
browser_dbg_pause-resume.js \
|
||||||
browser_dbg_update-editor-mode.js \
|
browser_dbg_update-editor-mode.js \
|
||||||
browser_dbg_select-line.js \
|
browser_dbg_select-line.js \
|
||||||
|
browser_dbg_clean-exit.js \
|
||||||
head.js \
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Test that closing a tab with the debugger in a paused state exits cleanly.
|
||||||
|
|
||||||
|
var gPane = null;
|
||||||
|
var gTab = null;
|
||||||
|
var gDebuggee = null;
|
||||||
|
var gDebugger = null;
|
||||||
|
|
||||||
|
const DEBUGGER_TAB_URL = "http://example.com/browser/browser/devtools/" +
|
||||||
|
"debugger/test/" +
|
||||||
|
"browser_dbg_debuggerstatement.html";
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
debug_tab_pane(DEBUGGER_TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||||
|
gTab = aTab;
|
||||||
|
gDebuggee = aDebuggee;
|
||||||
|
gPane = aPane;
|
||||||
|
gDebugger = gPane.debuggerWindow;
|
||||||
|
|
||||||
|
testCleanExit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testCleanExit() {
|
||||||
|
gPane.activeThread.addOneTimeListener("framesadded", function() {
|
||||||
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
is(gDebugger.StackFrames.activeThread.paused, true,
|
||||||
|
"Should be paused after the debugger statement.");
|
||||||
|
|
||||||
|
gPane._client.addOneTimeListener("tabDetached", function () {
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
removeTab(gTab);
|
||||||
|
}}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
|
||||||
|
}
|
|
@ -43,37 +43,41 @@ function testSelectLine() {
|
||||||
ok(gDebugger.editor.getText().search(/debugger/) != -1,
|
ok(gDebugger.editor.getText().search(/debugger/) != -1,
|
||||||
"The correct script was loaded initially.");
|
"The correct script was loaded initially.");
|
||||||
|
|
||||||
// getCaretPosition is 0-based.
|
// Yield control back to the event loop so that the debugger has a
|
||||||
is(gDebugger.editor.getCaretPosition().line, 5,
|
// chance to highlight the proper line.
|
||||||
"The correct line is selected.");
|
executeSoon(function(){
|
||||||
|
// getCaretPosition is 0-based.
|
||||||
|
is(gDebugger.editor.getCaretPosition().line, 5,
|
||||||
|
"The correct line is selected.");
|
||||||
|
|
||||||
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
|
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
|
||||||
function onChange() {
|
function onChange() {
|
||||||
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
|
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
|
||||||
onChange);
|
onChange);
|
||||||
ok(gDebugger.editor.getText().search(/debugger/) == -1,
|
ok(gDebugger.editor.getText().search(/debugger/) == -1,
|
||||||
"The second script is no longer displayed.");
|
"The second script is no longer displayed.");
|
||||||
|
|
||||||
ok(gDebugger.editor.getText().search(/firstCall/) != -1,
|
ok(gDebugger.editor.getText().search(/firstCall/) != -1,
|
||||||
"The first script is displayed.");
|
"The first script is displayed.");
|
||||||
|
|
||||||
// Yield control back to the event loop so that the debugger has a
|
// Yield control back to the event loop so that the debugger has a
|
||||||
// chance to highlight the proper line.
|
// chance to highlight the proper line.
|
||||||
executeSoon(function(){
|
executeSoon(function(){
|
||||||
// getCaretPosition is 0-based.
|
// getCaretPosition is 0-based.
|
||||||
is(gDebugger.editor.getCaretPosition().line, 4,
|
is(gDebugger.editor.getCaretPosition().line, 4,
|
||||||
"The correct line is selected.");
|
"The correct line is selected.");
|
||||||
|
|
||||||
gDebugger.StackFrames.activeThread.resume(function() {
|
gDebugger.StackFrames.activeThread.resume(function() {
|
||||||
removeTab(gTab);
|
removeTab(gTab);
|
||||||
finish();
|
finish();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// Click the oldest stack frame.
|
// Click the oldest stack frame.
|
||||||
let element = gDebugger.document.getElementById("stackframe-3");
|
let element = gDebugger.document.getElementById("stackframe-3");
|
||||||
EventUtils.synthesizeMouseAtCenter(element, {}, gDebugger);
|
EventUtils.synthesizeMouseAtCenter(element, {}, gDebugger);
|
||||||
|
});
|
||||||
}}, 0);
|
}}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -763,6 +763,9 @@ InspectorUI.prototype = {
|
||||||
this.boundRuleViewChanged = this.ruleViewChanged.bind(this);
|
this.boundRuleViewChanged = this.ruleViewChanged.bind(this);
|
||||||
this.ruleView.element.addEventListener("CssRuleViewChanged",
|
this.ruleView.element.addEventListener("CssRuleViewChanged",
|
||||||
this.boundRuleViewChanged);
|
this.boundRuleViewChanged);
|
||||||
|
this.cssRuleViewBoundCSSLinkClicked = this.ruleViewCSSLinkClicked.bind(this);
|
||||||
|
this.ruleView.element.addEventListener("CssRuleViewCSSLinkClicked",
|
||||||
|
this.cssRuleViewBoundCSSLinkClicked);
|
||||||
|
|
||||||
doc.documentElement.appendChild(this.ruleView.element);
|
doc.documentElement.appendChild(this.ruleView.element);
|
||||||
this.ruleView.highlight(this.selection);
|
this.ruleView.highlight(this.selection);
|
||||||
|
@ -800,6 +803,30 @@ InspectorUI.prototype = {
|
||||||
this.nodeChanged(this.ruleViewObject);
|
this.nodeChanged(this.ruleViewObject);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a css link is clicked this method is called in order to either:
|
||||||
|
* 1. Open the link in view source (for element style attributes)
|
||||||
|
* 2. Open the link in the style editor
|
||||||
|
*
|
||||||
|
* @param aEvent The event containing the style rule to act on
|
||||||
|
*/
|
||||||
|
ruleViewCSSLinkClicked: function(aEvent)
|
||||||
|
{
|
||||||
|
if (!this.chromeWin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rule = aEvent.detail.rule;
|
||||||
|
let styleSheet = rule.sheet;
|
||||||
|
|
||||||
|
if (styleSheet) {
|
||||||
|
this.chromeWin.StyleEditor.openChrome(styleSheet, rule.ruleLine);
|
||||||
|
} else {
|
||||||
|
let href = rule.elementStyle.element.ownerDocument.location.href;
|
||||||
|
this.chromeWin.openUILinkIn("view-source:" + href, "window");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the rule view.
|
* Destroy the rule view.
|
||||||
*/
|
*/
|
||||||
|
@ -811,6 +838,8 @@ InspectorUI.prototype = {
|
||||||
if (this.ruleView) {
|
if (this.ruleView) {
|
||||||
this.ruleView.element.removeEventListener("CssRuleViewChanged",
|
this.ruleView.element.removeEventListener("CssRuleViewChanged",
|
||||||
this.boundRuleViewChanged);
|
this.boundRuleViewChanged);
|
||||||
|
this.ruleView.element.removeEventListener("CssRuleViewCSSLinkClicked",
|
||||||
|
this.cssRuleViewBoundCSSLinkClicked);
|
||||||
delete boundRuleViewChanged;
|
delete boundRuleViewChanged;
|
||||||
this.ruleView.clear();
|
this.ruleView.clear();
|
||||||
delete this.ruleView;
|
delete this.ruleView;
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
title="&window.title;"
|
title="&window.title;"
|
||||||
windowtype="devtools:scratchpad"
|
windowtype="devtools:scratchpad"
|
||||||
|
macanimationtype="document"
|
||||||
screenX="4" screenY="4"
|
screenX="4" screenY="4"
|
||||||
width="640" height="480"
|
width="640" height="480"
|
||||||
persist="screenX screenY width height sizemode">
|
persist="screenX screenY width height sizemode">
|
||||||
|
|
|
@ -78,6 +78,9 @@ const ORION_EVENTS = {
|
||||||
Selection: "Selection",
|
Selection: "Selection",
|
||||||
Focus: "Focus",
|
Focus: "Focus",
|
||||||
Blur: "Blur",
|
Blur: "Blur",
|
||||||
|
MouseOver: "MouseOver",
|
||||||
|
MouseOut: "MouseOut",
|
||||||
|
MouseMove: "MouseMove",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -161,6 +161,30 @@ SourceEditor.EVENTS = {
|
||||||
* The blur event is fired when the editor goes out of focus.
|
* The blur event is fired when the editor goes out of focus.
|
||||||
*/
|
*/
|
||||||
BLUR: "Blur",
|
BLUR: "Blur",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MouseMove event is sent when the user moves the mouse over a line
|
||||||
|
* annotation. The event object properties:
|
||||||
|
* - event - the DOM mousemove event object.
|
||||||
|
* - x and y - the mouse coordinates relative to the document being edited.
|
||||||
|
*/
|
||||||
|
MOUSE_MOVE: "MouseMove",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MouseOver event is sent when the mouse pointer enters a line
|
||||||
|
* annotation. The event object properties:
|
||||||
|
* - event - the DOM mouseover event object.
|
||||||
|
* - x and y - the mouse coordinates relative to the document being edited.
|
||||||
|
*/
|
||||||
|
MOUSE_OVER: "MouseOver",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This MouseOut event is sent when the mouse pointer exits a line
|
||||||
|
* annotation. The event object properties:
|
||||||
|
* - event - the DOM mouseout event object.
|
||||||
|
* - x and y - the mouse coordinates relative to the document being edited.
|
||||||
|
*/
|
||||||
|
MOUSE_OUT: "MouseOut",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -55,6 +55,7 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_bug687160_line_api.js \
|
browser_bug687160_line_api.js \
|
||||||
browser_bug650345_find.js \
|
browser_bug650345_find.js \
|
||||||
browser_bug703692_focus_blur.js \
|
browser_bug703692_focus_blur.js \
|
||||||
|
browser_bug725388_mouse_events.js \
|
||||||
head.js \
|
head.js \
|
||||||
|
|
||||||
libs:: $(_BROWSER_TEST_FILES)
|
libs:: $(_BROWSER_TEST_FILES)
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let tempScope = {};
|
||||||
|
Cu.import("resource:///modules/source-editor.jsm", tempScope);
|
||||||
|
let SourceEditor = tempScope.SourceEditor;
|
||||||
|
|
||||||
|
let testWin;
|
||||||
|
let editor;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
|
||||||
|
"<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
|
||||||
|
" title='Test for bug 725388' width='600' height='500'><hbox flex='1'/></window>";
|
||||||
|
const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
|
||||||
|
|
||||||
|
testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
|
||||||
|
testWin.addEventListener("load", function onWindowLoad() {
|
||||||
|
testWin.removeEventListener("load", onWindowLoad, false);
|
||||||
|
waitForFocus(initEditor, testWin);
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initEditor()
|
||||||
|
{
|
||||||
|
let hbox = testWin.document.querySelector("hbox");
|
||||||
|
|
||||||
|
editor = new SourceEditor();
|
||||||
|
editor.init(hbox, {}, editorLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
function editorLoaded()
|
||||||
|
{
|
||||||
|
let text = "BrowserBug - 725388";
|
||||||
|
editor.setText(text);
|
||||||
|
|
||||||
|
let target = editor.editorElement;
|
||||||
|
let targetWin = target.ownerDocument.defaultView;
|
||||||
|
|
||||||
|
let mMoveHandler = function(aEvent) {
|
||||||
|
editor.removeEventListener(SourceEditor.EVENTS.MOUSE_MOVE, mMoveHandler);
|
||||||
|
|
||||||
|
is(aEvent.event.type, "mousemove", "MouseMove event fired.");
|
||||||
|
|
||||||
|
editor.addEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
|
||||||
|
waitForFocus(function() {
|
||||||
|
EventUtils.synthesizeMouse(target, 10, 10, {type: "mouseover"},
|
||||||
|
targetWin);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let mOverHandler = function(aEvent) {
|
||||||
|
editor.removeEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
|
||||||
|
|
||||||
|
is(aEvent.event.type, "mouseover", "MouseOver event fired.");
|
||||||
|
|
||||||
|
editor.addEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
|
||||||
|
waitForFocus(function() {
|
||||||
|
EventUtils.synthesizeMouse(target, -10, -10, {type: "mouseout"},
|
||||||
|
targetWin);
|
||||||
|
}, targetWin);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mOutHandler = function(aEvent) {
|
||||||
|
editor.removeEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
|
||||||
|
|
||||||
|
is(aEvent.event.type, "mouseout", "MouseOut event fired.");
|
||||||
|
executeSoon(testEnd);
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.addEventListener(SourceEditor.EVENTS.MOUSE_MOVE, mMoveHandler);
|
||||||
|
|
||||||
|
editor.focus();
|
||||||
|
waitForFocus(function() {
|
||||||
|
EventUtils.synthesizeMouse(target, 1, 1, {type: "mousemove"},
|
||||||
|
targetWin);
|
||||||
|
}, targetWin);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testEnd()
|
||||||
|
{
|
||||||
|
if (editor) {
|
||||||
|
editor.destroy();
|
||||||
|
}
|
||||||
|
if (testWin) {
|
||||||
|
testWin.close();
|
||||||
|
}
|
||||||
|
testWin = editor = null;
|
||||||
|
|
||||||
|
waitForFocus(finish, window);
|
||||||
|
}
|
|
@ -146,7 +146,7 @@ StyleEditor.prototype = {
|
||||||
*/
|
*/
|
||||||
get styleSheet()
|
get styleSheet()
|
||||||
{
|
{
|
||||||
assert(this._styleSheet, "StyleSheet must be loaded first.")
|
assert(this._styleSheet, "StyleSheet must be loaded first.");
|
||||||
return this._styleSheet;
|
return this._styleSheet;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -921,9 +921,11 @@ StyleEditor.prototype = {
|
||||||
aArgs.unshift(this);
|
aArgs.unshift(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy the list of listeners to allow adding/removing listeners in handlers
|
||||||
|
let listeners = this._actionListeners.concat();
|
||||||
// trigger all listeners that have this action handler
|
// trigger all listeners that have this action handler
|
||||||
for (let i = 0; i < this._actionListeners.length; ++i) {
|
for (let i = 0; i < listeners.length; ++i) {
|
||||||
let listener = this._actionListeners[i];
|
let listener = listeners[i];
|
||||||
let actionHandler = listener["on" + aName];
|
let actionHandler = listener["on" + aName];
|
||||||
if (actionHandler) {
|
if (actionHandler) {
|
||||||
actionHandler.apply(listener, aArgs);
|
actionHandler.apply(listener, aArgs);
|
||||||
|
|
|
@ -270,9 +270,11 @@ StyleEditorChrome.prototype = {
|
||||||
aArgs.unshift(this);
|
aArgs.unshift(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// trigger all listeners that have this named handler
|
// copy the list of listeners to allow adding/removing listeners in handlers
|
||||||
for (let i = 0; i < this._listeners.length; ++i) {
|
let listeners = this._listeners.concat();
|
||||||
let listener = this._listeners[i];
|
// trigger all listeners that have this named handler.
|
||||||
|
for (let i = 0; i < listeners.length; i++) {
|
||||||
|
let listener = listeners[i];
|
||||||
let handler = listener["on" + aName];
|
let handler = listener["on" + aName];
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.apply(listener, aArgs);
|
handler.apply(listener, aArgs);
|
||||||
|
@ -329,10 +331,10 @@ StyleEditorChrome.prototype = {
|
||||||
{
|
{
|
||||||
this._resetChrome();
|
this._resetChrome();
|
||||||
|
|
||||||
this._document.title = _("chromeWindowTitle",
|
|
||||||
this.contentDocument.title || this.contentDocument.location.href);
|
|
||||||
|
|
||||||
let document = this.contentDocument;
|
let document = this.contentDocument;
|
||||||
|
this._document.title = _("chromeWindowTitle",
|
||||||
|
document.title || document.location.href);
|
||||||
|
|
||||||
for (let i = 0; i < document.styleSheets.length; ++i) {
|
for (let i = 0; i < document.styleSheets.length; ++i) {
|
||||||
let styleSheet = document.styleSheets[i];
|
let styleSheet = document.styleSheets[i];
|
||||||
|
|
||||||
|
@ -352,6 +354,79 @@ StyleEditorChrome.prototype = {
|
||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* selects a stylesheet and optionally moves the cursor to a selected line
|
||||||
|
*
|
||||||
|
* @param {CSSStyleSheet} [aSheet]
|
||||||
|
* Stylesheet that should be selected. If a stylesheet is not passed
|
||||||
|
* and the editor is not initialized we focus the first stylesheet. If
|
||||||
|
* a stylesheet is not passed and the editor is initialized we ignore
|
||||||
|
* the call.
|
||||||
|
* @param {Number} [aLine]
|
||||||
|
* Line to which the caret should be moved (one-indexed).
|
||||||
|
* @param {Number} [aCol]
|
||||||
|
* Column to which the caret should be moved (one-indexed).
|
||||||
|
*/
|
||||||
|
selectStyleSheet: function SEC_selectSheet(aSheet, aLine, aCol)
|
||||||
|
{
|
||||||
|
let select = function DEC_select(aEditor) {
|
||||||
|
let summary = aSheet ? this.getSummaryElementForEditor(aEditor)
|
||||||
|
: this._view.getSummaryElementByOrdinal(0);
|
||||||
|
let setCaret = false;
|
||||||
|
|
||||||
|
if (aLine || aCol) {
|
||||||
|
aLine = aLine || 1;
|
||||||
|
aCol = aCol || 1;
|
||||||
|
setCaret = true;
|
||||||
|
}
|
||||||
|
if (!aEditor.sourceEditor) {
|
||||||
|
// If a line or column was specified we move the caret appropriately.
|
||||||
|
if (setCaret) {
|
||||||
|
aEditor.addActionListener({
|
||||||
|
onAttach: function SEC_selectSheet_onAttach()
|
||||||
|
{
|
||||||
|
aEditor.removeActionListener(this);
|
||||||
|
aEditor.sourceEditor.setCaretPosition(aLine - 1, aCol - 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this._view.activeSummary = summary;
|
||||||
|
} else {
|
||||||
|
this._view.activeSummary = summary;
|
||||||
|
|
||||||
|
// If a line or column was specified we move the caret appropriately.
|
||||||
|
if (setCaret) {
|
||||||
|
aEditor.sourceEditor.setCaretPosition(aLine - 1, aCol - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
if (!this.editors.length) {
|
||||||
|
// We are in the main initialization phase so we wait for the editor
|
||||||
|
// containing the target stylesheet to be added and select the target
|
||||||
|
// stylesheet, optionally moving the cursor to a selected line.
|
||||||
|
this.addChromeListener({
|
||||||
|
onEditorAdded: function SEC_selectSheet_onEditorAdded(aChrome, aEditor) {
|
||||||
|
if ((!aSheet && aEditor.styleSheetIndex == 0) ||
|
||||||
|
aEditor.styleSheet == aSheet) {
|
||||||
|
aChrome.removeChromeListener(this);
|
||||||
|
select(aEditor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (aSheet) {
|
||||||
|
// We are already initialized and a stylesheet has been specified. Here
|
||||||
|
// we iterate through the editors and select the one containing the target
|
||||||
|
// stylesheet, optionally moving the cursor to a selected line.
|
||||||
|
for each (let editor in this.editors) {
|
||||||
|
if (editor.styleSheet == aSheet) {
|
||||||
|
select(editor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable all UI, effectively making editors read-only.
|
* Disable all UI, effectively making editors read-only.
|
||||||
* This is automatically called when no content window is attached.
|
* This is automatically called when no content window is attached.
|
||||||
|
@ -455,9 +530,8 @@ StyleEditorChrome.prototype = {
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
// autofocus the first or new stylesheet
|
// autofocus new stylesheets
|
||||||
if (editor.styleSheetIndex == 0 ||
|
if (editor.hasFlag(StyleEditorFlags.NEW)) {
|
||||||
editor.hasFlag(StyleEditorFlags.NEW)) {
|
|
||||||
this._view.activeSummary = aSummary;
|
this._view.activeSummary = aSummary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,8 +132,10 @@
|
||||||
<xul:script type="application/javascript"><![CDATA[
|
<xul:script type="application/javascript"><![CDATA[
|
||||||
Components.utils.import("resource:///modules/devtools/StyleEditorChrome.jsm");
|
Components.utils.import("resource:///modules/devtools/StyleEditorChrome.jsm");
|
||||||
let chromeRoot = document.getElementById("style-editor-chrome");
|
let chromeRoot = document.getElementById("style-editor-chrome");
|
||||||
let contentWindow = window.arguments[0];
|
let args = window.arguments[0].wrappedJSObject;
|
||||||
|
let contentWindow = args.contentWindow;
|
||||||
let chrome = new StyleEditorChrome(chromeRoot, contentWindow);
|
let chrome = new StyleEditorChrome(chromeRoot, contentWindow);
|
||||||
|
chrome.selectStyleSheet(args.selectedStyleSheet, args.line, args.col);
|
||||||
window.styleEditorChrome = chrome;
|
window.styleEditorChrome = chrome;
|
||||||
]]></xul:script>
|
]]></xul:script>
|
||||||
</xul:window>
|
</xul:window>
|
||||||
|
|
|
@ -51,6 +51,7 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_styleeditor_init.js \
|
browser_styleeditor_init.js \
|
||||||
browser_styleeditor_loading.js \
|
browser_styleeditor_loading.js \
|
||||||
browser_styleeditor_new.js \
|
browser_styleeditor_new.js \
|
||||||
|
browser_styleeditor_passedinsheet.js \
|
||||||
browser_styleeditor_pretty.js \
|
browser_styleeditor_pretty.js \
|
||||||
browser_styleeditor_readonly.js \
|
browser_styleeditor_readonly.js \
|
||||||
browser_styleeditor_reopen.js \
|
browser_styleeditor_reopen.js \
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
const TESTCASE_URI = TEST_BASE + "simple.html";
|
||||||
|
const LINE = 6;
|
||||||
|
const COL = 2;
|
||||||
|
|
||||||
|
let editor = null;
|
||||||
|
let sheet = null;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
waitForExplicitFinish();
|
||||||
|
gBrowser.selectedBrowser.addEventListener("load", function () {
|
||||||
|
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||||
|
run();
|
||||||
|
}, true);
|
||||||
|
content.location = TESTCASE_URI;
|
||||||
|
}
|
||||||
|
|
||||||
|
function run()
|
||||||
|
{
|
||||||
|
sheet = content.document.styleSheets[1];
|
||||||
|
launchStyleEditorChrome(function attachListeners(aChrome) {
|
||||||
|
aChrome.addChromeListener({
|
||||||
|
onEditorAdded: checkSourceEditor
|
||||||
|
});
|
||||||
|
}, sheet, LINE, COL);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSourceEditor(aChrome, aEditor)
|
||||||
|
{
|
||||||
|
if (!aEditor.sourceEditor) {
|
||||||
|
aEditor.addActionListener({
|
||||||
|
onAttach: function (aEditor) {
|
||||||
|
aEditor.removeActionListener(this);
|
||||||
|
validate(aEditor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
validate(aEditor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate(aEditor)
|
||||||
|
{
|
||||||
|
info("validating style editor");
|
||||||
|
let sourceEditor = aEditor.sourceEditor;
|
||||||
|
let caretPosition = sourceEditor.getCaretPosition();
|
||||||
|
is(caretPosition.line, LINE - 1, "caret row is correct"); // index based
|
||||||
|
is(caretPosition.col, COL - 1, "caret column is correct");
|
||||||
|
is(aEditor.styleSheet, sheet, "loaded stylesheet matches document stylesheet");
|
||||||
|
finishUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishUp()
|
||||||
|
{
|
||||||
|
editor = sheet = null;
|
||||||
|
finish();
|
||||||
|
}
|
|
@ -19,9 +19,9 @@ function cleanup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchStyleEditorChrome(aCallback)
|
function launchStyleEditorChrome(aCallback, aSheet, aLine, aCol)
|
||||||
{
|
{
|
||||||
gChromeWindow = StyleEditor.openChrome();
|
gChromeWindow = StyleEditor.openChrome(aSheet, aLine, aCol);
|
||||||
if (gChromeWindow.document.readyState != "complete") {
|
if (gChromeWindow.document.readyState != "complete") {
|
||||||
gChromeWindow.addEventListener("load", function onChromeLoad() {
|
gChromeWindow.addEventListener("load", function onChromeLoad() {
|
||||||
gChromeWindow.removeEventListener("load", onChromeLoad, true);
|
gChromeWindow.removeEventListener("load", onChromeLoad, true);
|
||||||
|
@ -34,12 +34,12 @@ function launchStyleEditorChrome(aCallback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTabAndLaunchStyleEditorChromeWhenLoaded(aCallback)
|
function addTabAndLaunchStyleEditorChromeWhenLoaded(aCallback, aSheet, aLine, aCol)
|
||||||
{
|
{
|
||||||
gBrowser.selectedTab = gBrowser.addTab();
|
gBrowser.selectedTab = gBrowser.addTab();
|
||||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||||
launchStyleEditorChrome(aCallback);
|
launchStyleEditorChrome(aCallback, aSheet, aLine, aCol);
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -273,6 +273,7 @@ CssHtmlTree.prototype = {
|
||||||
this._matchedProperties = null;
|
this._matchedProperties = null;
|
||||||
|
|
||||||
if (this.htmlComplete) {
|
if (this.htmlComplete) {
|
||||||
|
this.refreshSourceFilter();
|
||||||
this.refreshPanel();
|
this.refreshPanel();
|
||||||
} else {
|
} else {
|
||||||
if (this._refreshProcess) {
|
if (this._refreshProcess) {
|
||||||
|
@ -281,6 +282,9 @@ CssHtmlTree.prototype = {
|
||||||
|
|
||||||
CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
|
CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
|
||||||
|
|
||||||
|
// Refresh source filter ... this must be done after templateRoot has been
|
||||||
|
// processed.
|
||||||
|
this.refreshSourceFilter();
|
||||||
this.numVisibleProperties = 0;
|
this.numVisibleProperties = 0;
|
||||||
let fragment = this.doc.createDocumentFragment();
|
let fragment = this.doc.createDocumentFragment();
|
||||||
this._refreshProcess = new UpdateProcess(this.win, CssHtmlTree.propertyNames, {
|
this._refreshProcess = new UpdateProcess(this.win, CssHtmlTree.propertyNames, {
|
||||||
|
@ -362,21 +366,28 @@ CssHtmlTree.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The change event handler for the onlyUserStyles checkbox. When
|
* The change event handler for the onlyUserStyles checkbox.
|
||||||
* onlyUserStyles.checked is true we do not display properties that have no
|
|
||||||
* matched selectors, and we do not display UA styles. If .checked is false we
|
|
||||||
* do display even properties with no matched selectors, and we include the UA
|
|
||||||
* styles.
|
|
||||||
*
|
*
|
||||||
* @param {Event} aEvent the DOM Event object.
|
* @param {Event} aEvent the DOM Event object.
|
||||||
*/
|
*/
|
||||||
onlyUserStylesChanged: function CssHtmltree_onlyUserStylesChanged(aEvent)
|
onlyUserStylesChanged: function CssHtmltree_onlyUserStylesChanged(aEvent)
|
||||||
|
{
|
||||||
|
this.refreshSourceFilter();
|
||||||
|
this.refreshPanel();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When onlyUserStyles.checked is true we only display properties that have
|
||||||
|
* matched selectors and have been included by the document or one of the
|
||||||
|
* document's stylesheets. If .checked is false we display all properties
|
||||||
|
* including those that come from UA stylesheets.
|
||||||
|
*/
|
||||||
|
refreshSourceFilter: function CssHtmlTree_setSourceFilter()
|
||||||
{
|
{
|
||||||
this._matchedProperties = null;
|
this._matchedProperties = null;
|
||||||
this.cssLogic.sourceFilter = this.showOnlyUserStyles ?
|
this.cssLogic.sourceFilter = this.showOnlyUserStyles ?
|
||||||
CssLogic.FILTER.ALL :
|
CssLogic.FILTER.ALL :
|
||||||
CssLogic.FILTER.UA;
|
CssLogic.FILTER.UA;
|
||||||
this.refreshPanel();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -974,4 +985,24 @@ SelectorView.prototype = {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a css link is clicked this method is called in order to either:
|
||||||
|
* 1. Open the link in view source (for element style attributes).
|
||||||
|
* 2. Open the link in the style editor.
|
||||||
|
*
|
||||||
|
* @param aEvent The click event
|
||||||
|
*/
|
||||||
|
openStyleEditor: function(aEvent)
|
||||||
|
{
|
||||||
|
if (this.selectorInfo.selector._cssRule._cssSheet) {
|
||||||
|
let styleSheet = this.selectorInfo.selector._cssRule._cssSheet.domSheet;
|
||||||
|
let line = this.selectorInfo.ruleLine;
|
||||||
|
|
||||||
|
this.tree.win.StyleEditor.openChrome(styleSheet, line);
|
||||||
|
} else {
|
||||||
|
let href = this.selectorInfo.sourceElement.ownerDocument.location.href;
|
||||||
|
this.tree.win.openUILinkIn("view-source:" + href, "window");
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -232,7 +232,7 @@ CssLogic.prototype = {
|
||||||
// Update the CssSheet objects.
|
// Update the CssSheet objects.
|
||||||
this.forEachSheet(function(aSheet) {
|
this.forEachSheet(function(aSheet) {
|
||||||
aSheet._sheetAllowed = -1;
|
aSheet._sheetAllowed = -1;
|
||||||
if (!aSheet.systemSheet && aSheet.sheetAllowed) {
|
if (aSheet.contentSheet && aSheet.sheetAllowed) {
|
||||||
ruleCount += aSheet.ruleCount;
|
ruleCount += aSheet.ruleCount;
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
@ -345,7 +345,7 @@ CssLogic.prototype = {
|
||||||
|
|
||||||
let sheets = [];
|
let sheets = [];
|
||||||
this.forEachSheet(function (aSheet) {
|
this.forEachSheet(function (aSheet) {
|
||||||
if (!aSheet.systemSheet) {
|
if (aSheet.contentSheet) {
|
||||||
sheets.push(aSheet);
|
sheets.push(aSheet);
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
@ -395,7 +395,7 @@ CssLogic.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
sheet = new CssSheet(this, aDomSheet, aIndex);
|
sheet = new CssSheet(this, aDomSheet, aIndex);
|
||||||
if (sheet.sheetAllowed && !sheet.systemSheet) {
|
if (sheet.sheetAllowed && sheet.contentSheet) {
|
||||||
this._ruleCount += sheet.ruleCount;
|
this._ruleCount += sheet.ruleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,7 +569,7 @@ CssLogic.prototype = {
|
||||||
|
|
||||||
this.forEachSheet(function (aSheet) {
|
this.forEachSheet(function (aSheet) {
|
||||||
// We do not show unmatched selectors from system stylesheets
|
// We do not show unmatched selectors from system stylesheets
|
||||||
if (aSheet.systemSheet || aSheet.disabled || !aSheet.mediaMatches) {
|
if (!aSheet.contentSheet || aSheet.disabled || !aSheet.mediaMatches) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +664,7 @@ CssLogic.prototype = {
|
||||||
sheet._passId = this._passId;
|
sheet._passId = this._passId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter !== CssLogic.FILTER.UA && sheet.systemSheet) {
|
if (filter === CssLogic.FILTER.ALL && !sheet.contentSheet) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,7 +710,7 @@ CssLogic.prototype = {
|
||||||
let result = {};
|
let result = {};
|
||||||
|
|
||||||
this.forSomeSheets(function (aSheet) {
|
this.forSomeSheets(function (aSheet) {
|
||||||
if (aSheet.systemSheet || aSheet.disabled || !aSheet.mediaMatches) {
|
if (!aSheet.contentSheet || aSheet.disabled || !aSheet.mediaMatches) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,29 +865,23 @@ XPCOMUtils.defineLazyGetter(CssLogic, "_strings", function() Services.strings
|
||||||
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
|
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the given property sheet a system (user agent) stylesheet?
|
* Is the given property sheet a content stylesheet?
|
||||||
*
|
*
|
||||||
* @param {CSSStyleSheet} aSheet a stylesheet
|
* @param {CSSStyleSheet} aSheet a stylesheet
|
||||||
* @return {boolean} true if the given stylesheet is a system stylesheet or
|
* @return {boolean} true if the given stylesheet is a content stylesheet,
|
||||||
* false otherwise.
|
* false otherwise.
|
||||||
*/
|
*/
|
||||||
CssLogic.isSystemStyleSheet = function CssLogic_isSystemStyleSheet(aSheet)
|
CssLogic.isContentStylesheet = function CssLogic_isContentStylesheet(aSheet)
|
||||||
{
|
{
|
||||||
if (!aSheet) {
|
// All sheets with owner nodes have been included by content.
|
||||||
|
if (aSheet.ownerNode) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = aSheet.href;
|
// If the sheet has a CSSImportRule we need to check the parent stylesheet.
|
||||||
|
if (aSheet.ownerRule instanceof Ci.nsIDOMCSSImportRule) {
|
||||||
if (!url) return false;
|
return CssLogic.isContentStylesheet(aSheet.parentStyleSheet);
|
||||||
if (url.length === 0) return true;
|
}
|
||||||
|
|
||||||
// Check for http[s]
|
|
||||||
if (url[0] === 'h') return false;
|
|
||||||
if (url.substr(0, 9) === "resource:") return true;
|
|
||||||
if (url.substr(0, 7) === "chrome:") return true;
|
|
||||||
if (url === "XPCSafeJSObjectWrapper.cpp") return true;
|
|
||||||
if (url.substr(0, 6) === "about:") return true;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -942,7 +936,7 @@ function CssSheet(aCssLogic, aDomSheet, aIndex)
|
||||||
{
|
{
|
||||||
this._cssLogic = aCssLogic;
|
this._cssLogic = aCssLogic;
|
||||||
this.domSheet = aDomSheet;
|
this.domSheet = aDomSheet;
|
||||||
this.index = this.systemSheet ? -100 * aIndex : aIndex;
|
this.index = this.contentSheet ? aIndex : -100 * aIndex;
|
||||||
|
|
||||||
// Cache of the sheets href. Cached by the getter.
|
// Cache of the sheets href. Cached by the getter.
|
||||||
this._href = null;
|
this._href = null;
|
||||||
|
@ -960,21 +954,21 @@ function CssSheet(aCssLogic, aDomSheet, aIndex)
|
||||||
|
|
||||||
CssSheet.prototype = {
|
CssSheet.prototype = {
|
||||||
_passId: null,
|
_passId: null,
|
||||||
_systemSheet: null,
|
_contentSheet: null,
|
||||||
_mediaMatches: null,
|
_mediaMatches: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells if the stylesheet is provided by the browser or not.
|
* Tells if the stylesheet is provided by the browser or not.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if this is a browser-provided stylesheet, or false
|
* @return {boolean} false if this is a browser-provided stylesheet, or true
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
get systemSheet()
|
get contentSheet()
|
||||||
{
|
{
|
||||||
if (this._systemSheet === null) {
|
if (this._contentSheet === null) {
|
||||||
this._systemSheet = CssLogic.isSystemStyleSheet(this.domSheet);
|
this._contentSheet = CssLogic.isContentStylesheet(this.domSheet);
|
||||||
}
|
}
|
||||||
return this._systemSheet;
|
return this._contentSheet;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1048,7 +1042,7 @@ CssSheet.prototype = {
|
||||||
this._sheetAllowed = true;
|
this._sheetAllowed = true;
|
||||||
|
|
||||||
let filter = this._cssLogic.sourceFilter;
|
let filter = this._cssLogic.sourceFilter;
|
||||||
if (filter === CssLogic.FILTER.ALL && this.systemSheet) {
|
if (filter === CssLogic.FILTER.ALL && !this.contentSheet) {
|
||||||
this._sheetAllowed = false;
|
this._sheetAllowed = false;
|
||||||
}
|
}
|
||||||
if (filter !== CssLogic.FILTER.ALL && filter !== CssLogic.FILTER.UA) {
|
if (filter !== CssLogic.FILTER.ALL && filter !== CssLogic.FILTER.UA) {
|
||||||
|
@ -1202,13 +1196,13 @@ function CssRule(aCssSheet, aDomRule, aElement)
|
||||||
this.line = this._cssSheet._cssLogic.domUtils.getRuleLine(this._domRule);
|
this.line = this._cssSheet._cssLogic.domUtils.getRuleLine(this._domRule);
|
||||||
this.source = this._cssSheet.shortSource + ":" + this.line;
|
this.source = this._cssSheet.shortSource + ":" + this.line;
|
||||||
this.href = this._cssSheet.href;
|
this.href = this._cssSheet.href;
|
||||||
this.systemRule = this._cssSheet.systemSheet;
|
this.contentRule = this._cssSheet.contentSheet;
|
||||||
} else if (aElement) {
|
} else if (aElement) {
|
||||||
this._selectors = [ new CssSelector(this, "@element.style") ];
|
this._selectors = [ new CssSelector(this, "@element.style") ];
|
||||||
this.line = -1;
|
this.line = -1;
|
||||||
this.source = CssLogic.l10n("rule.sourceElement");
|
this.source = CssLogic.l10n("rule.sourceElement");
|
||||||
this.href = "#";
|
this.href = "#";
|
||||||
this.systemRule = false;
|
this.contentRule = true;
|
||||||
this.sourceElement = aElement;
|
this.sourceElement = aElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1396,12 +1390,12 @@ CssSelector.prototype = {
|
||||||
/**
|
/**
|
||||||
* Check if the selector comes from a browser-provided stylesheet.
|
* Check if the selector comes from a browser-provided stylesheet.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if the selector comes from a browser-provided
|
* @return {boolean} true if the selector comes from a content-provided
|
||||||
* stylesheet, or false otherwise.
|
* stylesheet, or false otherwise.
|
||||||
*/
|
*/
|
||||||
get systemRule()
|
get contentRule()
|
||||||
{
|
{
|
||||||
return this._cssRule.systemRule;
|
return this._cssRule.contentRule;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1794,12 +1788,12 @@ function CssSelectorInfo(aSelector, aProperty, aValue, aStatus)
|
||||||
4 important
|
4 important
|
||||||
5 inline important
|
5 inline important
|
||||||
*/
|
*/
|
||||||
let scorePrefix = this.systemRule ? 0 : 2;
|
let scorePrefix = this.contentRule ? 2 : 0;
|
||||||
if (this.elementStyle) {
|
if (this.elementStyle) {
|
||||||
scorePrefix++;
|
scorePrefix++;
|
||||||
}
|
}
|
||||||
if (this.important) {
|
if (this.important) {
|
||||||
scorePrefix += this.systemRule ? 1 : 2;
|
scorePrefix += this.contentRule ? 2 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.specificityScore = "" + scorePrefix + this.specificity.ids +
|
this.specificityScore = "" + scorePrefix + this.specificity.ids +
|
||||||
|
@ -1902,9 +1896,9 @@ CssSelectorInfo.prototype = {
|
||||||
* @return {boolean} true if the selector comes from a browser-provided
|
* @return {boolean} true if the selector comes from a browser-provided
|
||||||
* stylesheet, or false otherwise.
|
* stylesheet, or false otherwise.
|
||||||
*/
|
*/
|
||||||
get systemRule()
|
get contentRule()
|
||||||
{
|
{
|
||||||
return this.selector.systemRule;
|
return this.selector.contentRule;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1916,8 +1910,8 @@ CssSelectorInfo.prototype = {
|
||||||
*/
|
*/
|
||||||
compareTo: function CssSelectorInfo_compareTo(aThat)
|
compareTo: function CssSelectorInfo_compareTo(aThat)
|
||||||
{
|
{
|
||||||
if (this.systemRule && !aThat.systemRule) return 1;
|
if (!this.contentRule && aThat.contentRule) return 1;
|
||||||
if (!this.systemRule && aThat.systemRule) return -1;
|
if (this.contentRule && !aThat.contentRule) return -1;
|
||||||
|
|
||||||
if (this.elementStyle && !aThat.elementStyle) {
|
if (this.elementStyle && !aThat.elementStyle) {
|
||||||
if (!this.important && aThat.important) return 1;
|
if (!this.important && aThat.important) return 1;
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
"use strict"
|
"use strict";
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
|
@ -181,8 +181,8 @@ ElementStyle.prototype = {
|
||||||
let domRule = domRules.GetElementAt(i);
|
let domRule = domRules.GetElementAt(i);
|
||||||
|
|
||||||
// XXX: Optionally provide access to system sheets.
|
// XXX: Optionally provide access to system sheets.
|
||||||
let systemSheet = CssLogic.isSystemStyleSheet(domRule.parentStyleSheet);
|
let contentSheet = CssLogic.isContentStylesheet(domRule.parentStyleSheet);
|
||||||
if (systemSheet) {
|
if (!contentSheet) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ ElementStyle.prototype = {
|
||||||
aProp.overridden = overridden;
|
aProp.overridden = overridden;
|
||||||
return dirty;
|
return dirty;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single style rule or declaration.
|
* A single style rule or declaration.
|
||||||
|
@ -358,11 +358,9 @@ Rule.prototype = {
|
||||||
if (this._title) {
|
if (this._title) {
|
||||||
return this._title;
|
return this._title;
|
||||||
}
|
}
|
||||||
let sheet = this.domRule ? this.domRule.parentStyleSheet : null;
|
this._title = CssLogic.shortSource(this.sheet);
|
||||||
this._title = CssLogic.shortSource(sheet);
|
|
||||||
if (this.domRule) {
|
if (this.domRule) {
|
||||||
let line = this.elementStyle.domUtils.getRuleLine(this.domRule);
|
this._title += ":" + this.ruleLine;
|
||||||
this._title += ":" + line;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.inherited) {
|
if (this.inherited) {
|
||||||
|
@ -378,6 +376,26 @@ Rule.prototype = {
|
||||||
return this._title;
|
return this._title;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rule's stylesheet.
|
||||||
|
*/
|
||||||
|
get sheet()
|
||||||
|
{
|
||||||
|
return this.domRule ? this.domRule.parentStyleSheet : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rule's line within a stylesheet
|
||||||
|
*/
|
||||||
|
get ruleLine()
|
||||||
|
{
|
||||||
|
if (!this.sheet) {
|
||||||
|
// No stylesheet, no ruleLine
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this.elementStyle.domUtils.getRuleLine(this.domRule);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new TextProperty to include in the rule.
|
* Create a new TextProperty to include in the rule.
|
||||||
*
|
*
|
||||||
|
@ -530,7 +548,7 @@ Rule.prototype = {
|
||||||
this.textProps.push(textProp);
|
this.textProps.push(textProp);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single property in a rule's cssText.
|
* A single property in a rule's cssText.
|
||||||
|
@ -618,7 +636,7 @@ TextProperty.prototype = {
|
||||||
{
|
{
|
||||||
this.rule.removeProperty(this);
|
this.rule.removeProperty(this);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -643,7 +661,7 @@ TextProperty.prototype = {
|
||||||
* apply to a given element. After construction, the 'element'
|
* apply to a given element. After construction, the 'element'
|
||||||
* property will be available with the user interface.
|
* property will be available with the user interface.
|
||||||
*
|
*
|
||||||
* @param Document aDocument
|
* @param Document aDoc
|
||||||
* The document that will contain the rule view.
|
* The document that will contain the rule view.
|
||||||
* @param object aStore
|
* @param object aStore
|
||||||
* The CSS rule view can use this object to store metadata
|
* The CSS rule view can use this object to store metadata
|
||||||
|
@ -655,7 +673,6 @@ function CssRuleView(aDoc, aStore)
|
||||||
{
|
{
|
||||||
this.doc = aDoc;
|
this.doc = aDoc;
|
||||||
this.store = aStore;
|
this.store = aStore;
|
||||||
|
|
||||||
this.element = this.doc.createElementNS(XUL_NS, "vbox");
|
this.element = this.doc.createElementNS(XUL_NS, "vbox");
|
||||||
this.element.setAttribute("tabindex", "0");
|
this.element.setAttribute("tabindex", "0");
|
||||||
this.element.classList.add("ruleview");
|
this.element.classList.add("ruleview");
|
||||||
|
@ -768,6 +785,14 @@ RuleEditor.prototype = {
|
||||||
class: "ruleview-rule-source",
|
class: "ruleview-rule-source",
|
||||||
textContent: this.rule.title
|
textContent: this.rule.title
|
||||||
});
|
});
|
||||||
|
source.addEventListener("click", function() {
|
||||||
|
let rule = this.rule;
|
||||||
|
let evt = this.doc.createEvent("CustomEvent");
|
||||||
|
evt.initCustomEvent("CssRuleViewCSSLinkClicked", true, false, {
|
||||||
|
rule: rule,
|
||||||
|
});
|
||||||
|
this.element.dispatchEvent(evt);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
let code = createChild(this.element, "div", {
|
let code = createChild(this.element, "div", {
|
||||||
class: "ruleview-code"
|
class: "ruleview-code"
|
||||||
|
@ -1094,8 +1119,6 @@ TextPropertyEditor.prototype = {
|
||||||
_parseValue: function TextPropertyEditor_parseValue(aValue)
|
_parseValue: function TextPropertyEditor_parseValue(aValue)
|
||||||
{
|
{
|
||||||
let pieces = aValue.split("!", 2);
|
let pieces = aValue.split("!", 2);
|
||||||
let value = pieces[0];
|
|
||||||
let priority = pieces.length > 1 ? pieces[1] : "";
|
|
||||||
return {
|
return {
|
||||||
value: pieces[0].trim(),
|
value: pieces[0].trim(),
|
||||||
priority: (pieces.length > 1 ? pieces[1].trim() : "")
|
priority: (pieces.length > 1 ? pieces[1].trim() : "")
|
||||||
|
|
|
@ -114,7 +114,7 @@ To visually debug the templates without running firefox, alter the display:none
|
||||||
${selector.humanReadableText(__element)}
|
${selector.humanReadableText(__element)}
|
||||||
</td>
|
</td>
|
||||||
<td class="rule-link">
|
<td class="rule-link">
|
||||||
<a target="_blank" href="view-source:${selector.selectorInfo.href}" class="link"
|
<a target="_blank" onclick="${selector.openStyleEditor}" class="link"
|
||||||
title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
|
title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -59,11 +59,19 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_ruleview_manipulation.js \
|
browser_ruleview_manipulation.js \
|
||||||
browser_ruleview_override.js \
|
browser_ruleview_override.js \
|
||||||
browser_ruleview_ui.js \
|
browser_ruleview_ui.js \
|
||||||
|
browser_bug705707_is_content_stylesheet.js \
|
||||||
head.js \
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
_BROWSER_TEST_PAGES = \
|
_BROWSER_TEST_PAGES = \
|
||||||
browser_bug683672.html \
|
browser_bug683672.html \
|
||||||
|
browser_bug705707_is_content_stylesheet.html \
|
||||||
|
browser_bug705707_is_content_stylesheet_imported.css \
|
||||||
|
browser_bug705707_is_content_stylesheet_imported2.css \
|
||||||
|
browser_bug705707_is_content_stylesheet_linked.css \
|
||||||
|
browser_bug705707_is_content_stylesheet_script.css \
|
||||||
|
browser_bug705707_is_content_stylesheet.xul \
|
||||||
|
browser_bug705707_is_content_stylesheet_xul.css \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libs:: $(_BROWSER_TEST_FILES)
|
libs:: $(_BROWSER_TEST_FILES)
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>test</title>
|
||||||
|
|
||||||
|
<link href="./browser_bug705707_is_content_stylesheet_linked.css" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Load script.css
|
||||||
|
function loadCSS() {
|
||||||
|
var link = document.createElement('link');
|
||||||
|
link.rel = 'stylesheet';
|
||||||
|
link.type = 'text/css';
|
||||||
|
link.href = "./browser_bug705707_is_content_stylesheet_script.css";
|
||||||
|
document.getElementsByTagName('head')[0].appendChild(link);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body onload="loadCSS();">
|
||||||
|
<table id="target">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<h3>Simple test</h3>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,100 @@
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
// Tests that the correct stylesheets origins are identified in HTML & XUL
|
||||||
|
// stylesheets
|
||||||
|
|
||||||
|
let doc;
|
||||||
|
|
||||||
|
const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/" +
|
||||||
|
"test/browser_bug705707_is_content_stylesheet.html";
|
||||||
|
const TEST_URI2 = "http://example.com/browser/browser/devtools/styleinspector/" +
|
||||||
|
"test/browser_bug705707_is_content_stylesheet.xul";
|
||||||
|
const XUL_URI = Cc["@mozilla.org/network/io-service;1"]
|
||||||
|
.getService(Ci.nsIIOService)
|
||||||
|
.newURI(TEST_URI2, null, null);
|
||||||
|
|
||||||
|
let tempScope = {};
|
||||||
|
Cu.import("resource:///modules/devtools/CssLogic.jsm", tempScope);
|
||||||
|
let CssLogic = tempScope.CssLogic;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
waitForExplicitFinish();
|
||||||
|
addTab(TEST_URI);
|
||||||
|
browser.addEventListener("load", htmlLoaded, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function htmlLoaded()
|
||||||
|
{
|
||||||
|
browser.removeEventListener("load", htmlLoaded, true);
|
||||||
|
doc = content.document;
|
||||||
|
testFromHTML()
|
||||||
|
}
|
||||||
|
|
||||||
|
function testFromHTML()
|
||||||
|
{
|
||||||
|
let target = doc.querySelector("#target");
|
||||||
|
|
||||||
|
executeSoon(function() {
|
||||||
|
checkSheets(target);
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
openXUL();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function openXUL()
|
||||||
|
{
|
||||||
|
Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
|
||||||
|
.add(XUL_URI, 'allowXULXBL', Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||||
|
addTab(TEST_URI2);
|
||||||
|
browser.addEventListener("load", xulLoaded, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function xulLoaded()
|
||||||
|
{
|
||||||
|
browser.removeEventListener("load", xulLoaded, true);
|
||||||
|
doc = content.document;
|
||||||
|
testFromXUL()
|
||||||
|
}
|
||||||
|
|
||||||
|
function testFromXUL()
|
||||||
|
{
|
||||||
|
let target = doc.querySelector("#target");
|
||||||
|
|
||||||
|
executeSoon(function() {
|
||||||
|
checkSheets(target);
|
||||||
|
finishUp();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSheets(aTarget)
|
||||||
|
{
|
||||||
|
let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
|
||||||
|
.getService(Ci.inIDOMUtils);
|
||||||
|
let domRules = domUtils.getCSSStyleRules(aTarget);
|
||||||
|
|
||||||
|
for (let i = 0, n = domRules.Count(); i < n; i++) {
|
||||||
|
let domRule = domRules.GetElementAt(i);
|
||||||
|
let sheet = domRule.parentStyleSheet;
|
||||||
|
let isContentSheet = CssLogic.isContentStylesheet(sheet);
|
||||||
|
|
||||||
|
if (!sheet.href ||
|
||||||
|
/browser_bug705707_is_content_stylesheet_/.test(sheet.href)) {
|
||||||
|
ok(isContentSheet, sheet.href + " identified as content stylesheet");
|
||||||
|
} else {
|
||||||
|
ok(!isContentSheet, sheet.href + " identified as non-content stylesheet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishUp()
|
||||||
|
{
|
||||||
|
info("finishing up");
|
||||||
|
Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
|
||||||
|
.add(XUL_URI, 'allowXULXBL', Ci.nsIPermissionManager.DENY_ACTION);
|
||||||
|
doc = null;
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
finish();
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet href="chrome://global/skin/xul.css" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="./browser_bug705707_is_content_stylesheet_xul.css"
|
||||||
|
type="text/css"?>
|
||||||
|
<!DOCTYPE window>
|
||||||
|
<window id="testwindow" xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
<label id="target" value="Simple XUL document" />
|
||||||
|
</window>
|
|
@ -0,0 +1,5 @@
|
||||||
|
@import url("./browser_bug705707_is_content_stylesheet_imported2.css");
|
||||||
|
|
||||||
|
#target {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
#target {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
@import url("./browser_bug705707_is_content_stylesheet_imported.css");
|
||||||
|
|
||||||
|
table {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
#target {
|
||||||
|
font-size: 200px;
|
||||||
|
}
|
|
@ -126,6 +126,40 @@ gcli.addCommand({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 'edit' command
|
||||||
|
*/
|
||||||
|
gcli.addCommand({
|
||||||
|
name: "edit",
|
||||||
|
description: gcli.lookup("editDesc"),
|
||||||
|
manual: gcli.lookup("editManual"),
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: 'resource',
|
||||||
|
type: {
|
||||||
|
name: 'resource',
|
||||||
|
include: 'text/css'
|
||||||
|
},
|
||||||
|
description: gcli.lookup("editResourceDesc")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "line",
|
||||||
|
defaultValue: 1,
|
||||||
|
type: {
|
||||||
|
name: "number",
|
||||||
|
min: 1,
|
||||||
|
step: 10
|
||||||
|
},
|
||||||
|
description: gcli.lookup("editLineToJumpToDesc")
|
||||||
|
}
|
||||||
|
],
|
||||||
|
exec: function(args, context) {
|
||||||
|
let hud = HUDService.getHudReferenceById(context.environment.hudId);
|
||||||
|
let StyleEditor = hud.gcliterm.document.defaultView.StyleEditor;
|
||||||
|
StyleEditor.openChrome(args.resource.element, args.line);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let breakpoints = [];
|
let breakpoints = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -129,3 +129,23 @@ breakdelRemoved=Breakpoint removed
|
||||||
# 'console close' command. This string is designed to be shown in a menu
|
# 'console close' command. This string is designed to be shown in a menu
|
||||||
# alongside the command name, which is why it should be as short as possible.
|
# alongside the command name, which is why it should be as short as possible.
|
||||||
consolecloseDesc=Close the console
|
consolecloseDesc=Close the console
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (editDesc) A very short description of the 'edit'
|
||||||
|
# command. See editManual for a fuller description of what it does. This
|
||||||
|
# string is designed to be shown in a menu alongside the command name, which
|
||||||
|
# is why it should be as short as possible.
|
||||||
|
editDesc=Tweak a page resource
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (editManual) A fuller description of the 'edit' command,
|
||||||
|
# displayed when the user asks for help on what it does.
|
||||||
|
editManual=Edit one of the resources that is part of this page (or maybe any generic web resource?)
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (editResourceDesc) A very short string to describe the
|
||||||
|
# 'resource' parameter to the 'edit' command, which is displayed in a dialog
|
||||||
|
# when the user is using this command.
|
||||||
|
editResourceDesc=URL to edit
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (editLineToJumpToDesc) A very short string to describe the
|
||||||
|
# 'line' parameter to the 'edit' command, which is displayed in a dialog
|
||||||
|
# when the user is using this command.
|
||||||
|
editLineToJumpToDesc=Line to jump to
|
||||||
|
|
|
@ -88,6 +88,12 @@ browser/themes/Makefile
|
||||||
$MOZ_BRANDING_DIRECTORY/Makefile
|
$MOZ_BRANDING_DIRECTORY/Makefile
|
||||||
$MOZ_BRANDING_DIRECTORY/content/Makefile
|
$MOZ_BRANDING_DIRECTORY/content/Makefile
|
||||||
$MOZ_BRANDING_DIRECTORY/locales/Makefile
|
$MOZ_BRANDING_DIRECTORY/locales/Makefile
|
||||||
|
toolkit/locales/Makefile
|
||||||
|
extensions/spellcheck/locales/Makefile
|
||||||
|
intl/locales/Makefile
|
||||||
|
netwerk/locales/Makefile
|
||||||
|
dom/locales/Makefile
|
||||||
|
security/manager/locales/Makefile
|
||||||
"
|
"
|
||||||
|
|
||||||
if [ "$MOZ_SAFE_BROWSING" ]; then
|
if [ "$MOZ_SAFE_BROWSING" ]; then
|
||||||
|
|
|
@ -68,6 +68,9 @@
|
||||||
.helplink:visited {
|
.helplink:visited {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
.link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.helplink {
|
.helplink {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -135,6 +138,7 @@
|
||||||
.rule-link {
|
.rule-link {
|
||||||
text-align: end;
|
text-align: end;
|
||||||
-moz-padding-start: 10px;
|
-moz-padding-start: 10px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
||||||
|
@ -200,7 +204,13 @@
|
||||||
|
|
||||||
.ruleview-rule-source {
|
.ruleview-rule-source {
|
||||||
background-color: -moz-dialog;
|
background-color: -moz-dialog;
|
||||||
|
color: #0091ff;
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruleview-rule-source:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ruleview-code {
|
.ruleview-code {
|
||||||
|
|
|
@ -68,6 +68,9 @@
|
||||||
.helplink:visited {
|
.helplink:visited {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
.link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.helplink {
|
.helplink {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -137,6 +140,7 @@
|
||||||
.rule-link {
|
.rule-link {
|
||||||
text-align: end;
|
text-align: end;
|
||||||
-moz-padding-start: 10px;
|
-moz-padding-start: 10px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
||||||
|
@ -202,7 +206,13 @@
|
||||||
|
|
||||||
.ruleview-rule-source {
|
.ruleview-rule-source {
|
||||||
background-color: -moz-dialog;
|
background-color: -moz-dialog;
|
||||||
|
color: #0091ff;
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruleview-rule-source:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ruleview-code {
|
.ruleview-code {
|
||||||
|
|
|
@ -67,6 +67,9 @@
|
||||||
.helplink:visited {
|
.helplink:visited {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
.link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.helplink {
|
.helplink {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -135,6 +138,7 @@
|
||||||
.rule-link {
|
.rule-link {
|
||||||
text-align: end;
|
text-align: end;
|
||||||
-moz-padding-start: 10px;
|
-moz-padding-start: 10px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
||||||
|
@ -200,7 +204,13 @@
|
||||||
|
|
||||||
.ruleview-rule-source {
|
.ruleview-rule-source {
|
||||||
background-color: -moz-dialog;
|
background-color: -moz-dialog;
|
||||||
|
color: #0091ff;
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruleview-rule-source:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ruleview-code {
|
.ruleview-code {
|
||||||
|
|
|
@ -84,7 +84,7 @@ DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DAPP_BUILDID=$(APP_BUILDID)
|
||||||
DEFINES += -DMOZ_APP_VERSION="$(MOZ_APP_VERSION)"
|
DEFINES += -DMOZ_APP_VERSION="$(MOZ_APP_VERSION)"
|
||||||
APP_INI_DEPS += $(DEPTH)/config/autoconf.mk
|
APP_INI_DEPS += $(DEPTH)/config/autoconf.mk
|
||||||
|
|
||||||
MOZ_SOURCE_STAMP ?= $(firstword $(shell hg -R $(topsrcdir)/$(MOZ_BUILD_APP)/.. parent --template="{node|short}\n" 2>/dev/null))
|
MOZ_SOURCE_STAMP := $(firstword $(shell cd $(topsrcdir)/$(MOZ_BUILD_APP)/.. && hg parent --template="{node|short}\n" 2>/dev/null))
|
||||||
ifdef MOZ_SOURCE_STAMP
|
ifdef MOZ_SOURCE_STAMP
|
||||||
DEFINES += -DMOZ_SOURCE_STAMP="$(MOZ_SOURCE_STAMP)"
|
DEFINES += -DMOZ_SOURCE_STAMP="$(MOZ_SOURCE_STAMP)"
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
dnl Add compiler specific options
|
||||||
|
|
||||||
|
AC_DEFUN([MOZ_COMPILER_OPTS],
|
||||||
|
[
|
||||||
|
if test "$CLANG_CXX"; then
|
||||||
|
## We disable return-type-c-linkage because jsval is defined as a C++ type but is
|
||||||
|
## returned by C functions. This is possible because we use knowledge about the ABI
|
||||||
|
## to typedef it to a C type with the same layout when the headers are included
|
||||||
|
## from C.
|
||||||
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-return-type-c-linkage"
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
|
@ -41,43 +41,55 @@ package @ANDROID_PACKAGE_NAME@;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface Actions {
|
public interface Actions {
|
||||||
public enum SpecialKey {
|
|
||||||
DOWN, UP, LEFT, RIGHT, ENTER, MENU, BACK
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface EventExpecter {
|
/** Special keys supported by sendSpecialKey() */
|
||||||
/** Blocks until the event has been received. Subsequent calls will return immediately. */
|
public enum SpecialKey {
|
||||||
public void blockForEvent();
|
DOWN, UP, LEFT, RIGHT, ENTER, MENU, BACK
|
||||||
/** Polls to see if the event has been received. Once this returns true, subsequent calls will also return true. */
|
}
|
||||||
public boolean eventReceived();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface RepeatedEventExpecter extends EventExpecter {
|
public interface EventExpecter {
|
||||||
/** Blocks until at least one event has been received, and no events have been received in the last <code>millis</code> milliseconds. */
|
/** Blocks until the event has been received. Subsequent calls will return immediately. */
|
||||||
public void blockUntilClear(long millis);
|
public void blockForEvent();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Polls to see if the event has been received. Once this returns true, subsequent calls will also return true. */
|
||||||
* Listens for a gecko event to be sent from the Gecko instance.
|
public boolean eventReceived();
|
||||||
* The returned object can be used to test if the event has been
|
}
|
||||||
* received. Note that only one event is listened for.
|
|
||||||
*
|
|
||||||
* @param geckoEvent The geckoEvent JSONObject's type
|
|
||||||
*/
|
|
||||||
EventExpecter expectGeckoEvent(String geckoEvent);
|
|
||||||
|
|
||||||
/**
|
public interface RepeatedEventExpecter extends EventExpecter {
|
||||||
* Listens for a paint event. Note that calling expectPaint() will
|
/** Blocks until at least one event has been received, and no events have been received in the last <code>millis</code> milliseconds. */
|
||||||
* invalidate the event expecters returned from any previous calls
|
public void blockUntilClear(long millis);
|
||||||
* to expectPaint(); calling any methods on those invalidated objects
|
}
|
||||||
* will result in undefined behaviour.
|
|
||||||
*/
|
|
||||||
RepeatedEventExpecter expectPaint();
|
|
||||||
|
|
||||||
// Send the string kewsToSend to the application
|
/**
|
||||||
void sendKeys(String keysToSend);
|
* Listens for a gecko event to be sent from the Gecko instance.
|
||||||
//Send any of the above keys to the element
|
* The returned object can be used to test if the event has been
|
||||||
void sendSpecialKey(SpecialKey button);
|
* received. Note that only one event is listened for.
|
||||||
|
*
|
||||||
|
* @param geckoEvent The geckoEvent JSONObject's type
|
||||||
|
*/
|
||||||
|
EventExpecter expectGeckoEvent(String geckoEvent);
|
||||||
|
|
||||||
void drag(int startingX, int endingX, int startingY, int endingY);
|
/**
|
||||||
|
* Listens for a paint event. Note that calling expectPaint() will
|
||||||
|
* invalidate the event expecters returned from any previous calls
|
||||||
|
* to expectPaint(); calling any methods on those invalidated objects
|
||||||
|
* will result in undefined behaviour.
|
||||||
|
*/
|
||||||
|
RepeatedEventExpecter expectPaint();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a string to the application
|
||||||
|
*
|
||||||
|
* @param keysToSend The string to send
|
||||||
|
*/
|
||||||
|
void sendKeys(String keysToSend);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a special keycode to the element
|
||||||
|
*
|
||||||
|
* @param key The special key to send
|
||||||
|
*/
|
||||||
|
void sendSpecialKey(SpecialKey key);
|
||||||
|
|
||||||
|
void drag(int startingX, int endingX, int startingY, int endingY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,19 +40,19 @@
|
||||||
package @ANDROID_PACKAGE_NAME@;
|
package @ANDROID_PACKAGE_NAME@;
|
||||||
|
|
||||||
public interface Assert {
|
public interface Assert {
|
||||||
void dumpLog(String message);
|
void dumpLog(String message);
|
||||||
void setLogFile(String filename);
|
void setLogFile(String filename);
|
||||||
void setTestName(String testName);
|
void setTestName(String testName);
|
||||||
|
|
||||||
void finalize();
|
void finalize();
|
||||||
void ok(boolean condition, String name, String diag);
|
void ok(boolean condition, String name, String diag);
|
||||||
void is(Object a, Object b, String name);
|
void is(Object a, Object b, String name);
|
||||||
void isnot(Object a, Object b, String name);
|
void isnot(Object a, Object b, String name);
|
||||||
void todo(boolean condition, String name, String diag);
|
void todo(boolean condition, String name, String diag);
|
||||||
void todo_is(Object a, Object b, String name);
|
void todo_is(Object a, Object b, String name);
|
||||||
void todo_isnot(Object a, Object b, String name);
|
void todo_isnot(Object a, Object b, String name);
|
||||||
void info(String name, String message);
|
void info(String name, String message);
|
||||||
|
|
||||||
// robocop-specific asserts
|
// robocop-specific asserts
|
||||||
void ispixel(int actual, int r, int g, int b, String name);
|
void ispixel(int actual, int r, int g, int b, String name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,39 +43,39 @@ import java.util.List;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
|
||||||
public interface Driver {
|
public interface Driver {
|
||||||
/**
|
/**
|
||||||
* Find the first Element using the given method.
|
* Find the first Element using the given method.
|
||||||
*
|
*
|
||||||
* @param activity The activity the element belongs to
|
* @param activity The activity the element belongs to
|
||||||
* @param name The name of the element
|
* @param name The name of the element
|
||||||
* @return The first matching element on the current context
|
* @return The first matching element on the current context
|
||||||
* @throws RoboCopException If no matching elements are found
|
* @throws RoboCopException If no matching elements are found
|
||||||
*/
|
*/
|
||||||
Element findElement(Activity activity, String name);
|
Element findElement(Activity activity, String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up scroll handling so that data is received from the extension.
|
* Sets up scroll handling so that data is received from the extension.
|
||||||
*/
|
*/
|
||||||
void setupScrollHandling();
|
void setupScrollHandling();
|
||||||
|
|
||||||
int getPageHeight();
|
int getPageHeight();
|
||||||
int getScrollHeight();
|
int getScrollHeight();
|
||||||
int getHeight();
|
int getHeight();
|
||||||
int getGeckoTop();
|
int getGeckoTop();
|
||||||
int getGeckoLeft();
|
int getGeckoLeft();
|
||||||
int getGeckoWidth();
|
int getGeckoWidth();
|
||||||
int getGeckoHeight();
|
int getGeckoHeight();
|
||||||
|
|
||||||
void startFrameRecording();
|
void startFrameRecording();
|
||||||
int stopFrameRecording();
|
int stopFrameRecording();
|
||||||
|
|
||||||
void startCheckerboardRecording();
|
void startCheckerboardRecording();
|
||||||
float stopCheckerboardRecording();
|
float stopCheckerboardRecording();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a copy of the painted content region.
|
* Get a copy of the painted content region.
|
||||||
* @return A 2-D array of pixels (indexed by y, then x). The pixels
|
* @return A 2-D array of pixels (indexed by y, then x). The pixels
|
||||||
* are in ARGB-8888 format.
|
* are in ARGB-8888 format.
|
||||||
*/
|
*/
|
||||||
int[][] getPaintedSurface();
|
int[][] getPaintedSurface();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,13 +39,21 @@
|
||||||
|
|
||||||
package @ANDROID_PACKAGE_NAME@;
|
package @ANDROID_PACKAGE_NAME@;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Element provides access to a specific UI view (android.view.View).
|
||||||
|
* See also Driver.findElement().
|
||||||
|
*/
|
||||||
public interface Element {
|
public interface Element {
|
||||||
//Click on the element
|
|
||||||
void click();
|
/** Click on the element */
|
||||||
//Returns true if the element is currently displayed
|
void click();
|
||||||
boolean isDisplayed();
|
|
||||||
//Returns the text currently displayed on the element.
|
/** Returns true if the element is currently displayed */
|
||||||
String getText();
|
boolean isDisplayed();
|
||||||
//Returns view ID.
|
|
||||||
Integer getId();
|
/** Returns the text currently displayed on the element */
|
||||||
|
String getText();
|
||||||
|
|
||||||
|
/** Returns the view ID */
|
||||||
|
Integer getId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,202 +38,194 @@
|
||||||
package @ANDROID_PACKAGE_NAME@;
|
package @ANDROID_PACKAGE_NAME@;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import android.os.SystemClock;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public class FennecMochitestAssert implements Assert {
|
public class FennecMochitestAssert implements Assert {
|
||||||
// Objects for reflexive access of fennec classes.
|
private LinkedList<testInfo> mTestList = new LinkedList<testInfo>();
|
||||||
|
|
||||||
private LinkedList<testInfo> testList = new LinkedList<testInfo>();
|
// Internal state variables to make logging match up with existing mochitests
|
||||||
|
private int mLineNumber = 0;
|
||||||
|
private int mPassed = 0;
|
||||||
|
private int mFailed = 0;
|
||||||
|
private int mTodo = 0;
|
||||||
|
|
||||||
|
// Used to write the first line of the test file
|
||||||
|
private boolean mLogStarted = false;
|
||||||
|
|
||||||
// Internal state variables to make logging match up with existing mochitests
|
// Used to write the test-start/test-end log lines
|
||||||
private int lineNumber = 0;
|
private String mLogTestName = "";
|
||||||
private int passed = 0;
|
|
||||||
private int failed = 0;
|
|
||||||
private int todo = 0;
|
|
||||||
|
|
||||||
// Used to write the first line of the test file
|
|
||||||
private boolean logStarted = false;
|
|
||||||
|
|
||||||
// Used to write the test-start/test-end log lines
|
// Measure the time it takes to run test case
|
||||||
private String logTestName = "";
|
private long mStartTime = 0;
|
||||||
|
|
||||||
// Measure the time it takes to run test case
|
public FennecMochitestAssert() {
|
||||||
private long startTime = 0;
|
|
||||||
|
|
||||||
public FennecMochitestAssert() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write information to a logfile and logcat
|
|
||||||
public void dumpLog(String message)
|
|
||||||
{
|
|
||||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the filename used for dumpLog.
|
|
||||||
public void setLogFile(String filename)
|
|
||||||
{
|
|
||||||
FennecNativeDriver.setLogFile(filename);
|
|
||||||
|
|
||||||
String message;
|
|
||||||
if (!logStarted) {
|
|
||||||
dumpLog(Integer.toString(lineNumber++) + " INFO SimpleTest START");
|
|
||||||
logStarted = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logTestName != "") {
|
/** Write information to a logfile and logcat */
|
||||||
long diff = (new Date().getTime()) - startTime;
|
public void dumpLog(String message) {
|
||||||
message = Integer.toString(lineNumber++) + " INFO TEST-END | " + logTestName;
|
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
|
||||||
message += " | finished in " + diff + "ms";
|
|
||||||
dumpLog(message);
|
|
||||||
logTestName = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTestName(String testName)
|
|
||||||
{
|
|
||||||
String[] nameParts = testName.split("\\.");
|
|
||||||
logTestName = nameParts[nameParts.length - 1];
|
|
||||||
startTime = new Date().getTime();
|
|
||||||
|
|
||||||
dumpLog(Integer.toString(lineNumber++) + " INFO TEST-START | " + logTestName);
|
|
||||||
}
|
|
||||||
|
|
||||||
class testInfo {
|
|
||||||
public boolean result;
|
|
||||||
public String name;
|
|
||||||
public String diag;
|
|
||||||
public boolean todo;
|
|
||||||
public testInfo(boolean r, String n, String d, boolean t) {
|
|
||||||
result = r;
|
|
||||||
name = n;
|
|
||||||
diag = d;
|
|
||||||
todo = t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/** Set the filename used for dumpLog. */
|
||||||
|
public void setLogFile(String filename) {
|
||||||
|
FennecNativeDriver.setLogFile(filename);
|
||||||
|
|
||||||
private void _logMochitestResult(testInfo test, String passString, String failString)
|
String message;
|
||||||
{
|
if (!mLogStarted) {
|
||||||
boolean isError = true;
|
dumpLog(Integer.toString(mLineNumber++) + " INFO SimpleTest START");
|
||||||
String resultString = failString;
|
mLogStarted = true;
|
||||||
if (test.result || test.todo) {
|
}
|
||||||
isError = false;
|
|
||||||
}
|
|
||||||
if (test.result)
|
|
||||||
{
|
|
||||||
resultString = passString;
|
|
||||||
}
|
|
||||||
String diag = test.name;
|
|
||||||
if (test.diag != null) diag += " - " + test.diag;
|
|
||||||
|
|
||||||
String message = Integer.toString(lineNumber++) + " INFO " + resultString + " | " + logTestName + " | " + diag;
|
if (mLogTestName != "") {
|
||||||
dumpLog(message);
|
long diff = SystemClock.uptimeMillis() - mStartTime;
|
||||||
|
message = Integer.toString(mLineNumber++) + " INFO TEST-END | " + mLogTestName;
|
||||||
if (test.todo) {
|
message += " | finished in " + diff + "ms";
|
||||||
todo++;
|
dumpLog(message);
|
||||||
} else if (isError) {
|
mLogTestName = "";
|
||||||
failed++;
|
}
|
||||||
} else {
|
|
||||||
passed++;
|
|
||||||
}
|
|
||||||
if (isError) {
|
|
||||||
junit.framework.Assert.fail(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finalize()
|
|
||||||
{
|
|
||||||
// It appears that we call finalize during cleanup, this might be an invalid assertion.
|
|
||||||
String message;
|
|
||||||
|
|
||||||
if (logTestName != "") {
|
|
||||||
long diff = (new Date().getTime()) - startTime;
|
|
||||||
message = Integer.toString(lineNumber++) + " INFO TEST-END | " + logTestName;
|
|
||||||
message += " | finished in " + diff + "ms";
|
|
||||||
dumpLog(message);
|
|
||||||
logTestName = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message = Integer.toString(lineNumber++) + " INFO TEST-START | Shutdown";
|
public void setTestName(String testName) {
|
||||||
dumpLog(message);
|
String[] nameParts = testName.split("\\.");
|
||||||
message = Integer.toString(lineNumber++) + " INFO Passed: " + Integer.toString(passed);
|
mLogTestName = nameParts[nameParts.length - 1];
|
||||||
dumpLog(message);
|
mStartTime = SystemClock.uptimeMillis();
|
||||||
message = Integer.toString(lineNumber++) + " INFO Failed: " + Integer.toString(failed);
|
|
||||||
dumpLog(message);
|
|
||||||
message = Integer.toString(lineNumber++) + " INFO Todo: " + Integer.toString(todo);
|
|
||||||
dumpLog(message);
|
|
||||||
message = Integer.toString(lineNumber++) + " INFO SimpleTest FINISHED";
|
|
||||||
dumpLog(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ok(boolean condition, String name, String diag) {
|
dumpLog(Integer.toString(mLineNumber++) + " INFO TEST-START | " + mLogTestName);
|
||||||
testInfo test = new testInfo(condition, name, diag, false);
|
|
||||||
_logMochitestResult(test, "TEST-PASS", "TEST-UNEXPECTED-FAIL");
|
|
||||||
testList.add(test);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void is(Object a, Object b, String name) {
|
|
||||||
boolean pass = a.equals(b);
|
|
||||||
String diag = "got " + a.toString() + ", expected " + b.toString();
|
|
||||||
if(pass) {
|
|
||||||
diag = a.toString() + " should equal " + b.toString();
|
|
||||||
}
|
}
|
||||||
ok(pass, name, diag);
|
|
||||||
}
|
class testInfo {
|
||||||
|
public boolean mResult;
|
||||||
public void isnot(Object a, Object b, String name) {
|
public String mName;
|
||||||
boolean pass = !a.equals(b);
|
public String mDiag;
|
||||||
String diag = "didn't expect " + a.toString() + ", but got it";
|
public boolean mTodo;
|
||||||
if(pass) {
|
public testInfo(boolean r, String n, String d, boolean t) {
|
||||||
diag = a.toString() + " should not equal " + b.toString();
|
mResult = r;
|
||||||
|
mName = n;
|
||||||
|
mDiag = d;
|
||||||
|
mTodo = t;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ok(pass, name, diag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ispixel(int actual, int r, int g, int b, String name) {
|
private void _logMochitestResult(testInfo test, String passString, String failString) {
|
||||||
// When we read GL pixels the GPU has already processed them and they
|
boolean isError = true;
|
||||||
// are usually off by a little bit. For example a CSS-color pixel of color #64FFF5
|
String resultString = failString;
|
||||||
// was turned into #63FFF7 when it came out of glReadPixels. So in order to compare
|
if (test.mResult || test.mTodo) {
|
||||||
// against the expected value, we use a little fuzz factor. For the alpha we just
|
isError = false;
|
||||||
// make sure it is always 0xFF.
|
}
|
||||||
int aAlpha = ((actual >> 24) & 0xFF);
|
if (test.mResult)
|
||||||
int aR = ((actual >> 16) & 0xFF);
|
{
|
||||||
int aG = ((actual >> 8) & 0xFF);
|
resultString = passString;
|
||||||
int aB = (actual & 0xFF);
|
}
|
||||||
boolean pass = (aAlpha == 0xFF) /* alpha */
|
String diag = test.mName;
|
||||||
&& (Math.abs(aR - r) < 8) /* red */
|
if (test.mDiag != null) diag += " - " + test.mDiag;
|
||||||
&& (Math.abs(aG - g) < 8) /* green */
|
|
||||||
&& (Math.abs(aB - b) < 8); /* blue */
|
|
||||||
ok(pass, name, "Color rgba(" + aR + "," + aG + "," + aB + "," + aAlpha + ")" + (pass ? " " : " not") + " close enough to expected rgb(" + r + "," + g + "," + b + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void todo(boolean condition, String name, String diag) {
|
String message = Integer.toString(mLineNumber++) + " INFO " + resultString + " | " + mLogTestName + " | " + diag;
|
||||||
testInfo test = new testInfo(condition, name, diag, true);
|
dumpLog(message);
|
||||||
_logMochitestResult(test, "TEST-UNEXPECTED-PASS", "TEST-KNOWN-FAIL");
|
|
||||||
testList.add(test);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void todo_is(Object a, Object b, String name) {
|
if (test.mTodo) {
|
||||||
boolean pass = a.equals(b);
|
mTodo++;
|
||||||
String diag = "got " + a.toString() + ", expected " + b.toString();
|
} else if (isError) {
|
||||||
if(pass) {
|
mFailed++;
|
||||||
diag = a.toString() + " should equal " + b.toString();
|
} else {
|
||||||
|
mPassed++;
|
||||||
|
}
|
||||||
|
if (isError) {
|
||||||
|
junit.framework.Assert.fail(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
todo(pass, name, diag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void todo_isnot(Object a, Object b, String name) {
|
|
||||||
boolean pass = !a.equals(b);
|
|
||||||
String diag = "didn't expect " + a.toString() + ", but got it";
|
|
||||||
if(pass) {
|
|
||||||
diag = a.toString() + " should not equal " + b.toString();
|
|
||||||
}
|
|
||||||
todo(pass, name, diag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void info(String name, String message) {
|
public void finalize() {
|
||||||
testInfo test = new testInfo(true, name, message, false);
|
// It appears that we call finalize during cleanup, this might be an invalid assertion.
|
||||||
_logMochitestResult(test, "TEST-INFO", "INFO FAILED?");
|
String message;
|
||||||
}
|
|
||||||
|
if (mLogTestName != "") {
|
||||||
|
long diff = SystemClock.uptimeMillis() - mStartTime;
|
||||||
|
message = Integer.toString(mLineNumber++) + " INFO TEST-END | " + mLogTestName;
|
||||||
|
message += " | finished in " + diff + "ms";
|
||||||
|
dumpLog(message);
|
||||||
|
mLogTestName = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
message = Integer.toString(mLineNumber++) + " INFO TEST-START | Shutdown";
|
||||||
|
dumpLog(message);
|
||||||
|
message = Integer.toString(mLineNumber++) + " INFO Passed: " + Integer.toString(mPassed);
|
||||||
|
dumpLog(message);
|
||||||
|
message = Integer.toString(mLineNumber++) + " INFO Failed: " + Integer.toString(mFailed);
|
||||||
|
dumpLog(message);
|
||||||
|
message = Integer.toString(mLineNumber++) + " INFO Todo: " + Integer.toString(mTodo);
|
||||||
|
dumpLog(message);
|
||||||
|
message = Integer.toString(mLineNumber++) + " INFO SimpleTest FINISHED";
|
||||||
|
dumpLog(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ok(boolean condition, String name, String diag) {
|
||||||
|
testInfo test = new testInfo(condition, name, diag, false);
|
||||||
|
_logMochitestResult(test, "TEST-PASS", "TEST-UNEXPECTED-FAIL");
|
||||||
|
mTestList.add(test);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void is(Object a, Object b, String name) {
|
||||||
|
boolean pass = a.equals(b);
|
||||||
|
String diag = "got " + a.toString() + ", expected " + b.toString();
|
||||||
|
if (pass) {
|
||||||
|
diag = a.toString() + " should equal " + b.toString();
|
||||||
|
}
|
||||||
|
ok(pass, name, diag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void isnot(Object a, Object b, String name) {
|
||||||
|
boolean pass = !a.equals(b);
|
||||||
|
String diag = "didn't expect " + a.toString() + ", but got it";
|
||||||
|
if (pass) {
|
||||||
|
diag = a.toString() + " should not equal " + b.toString();
|
||||||
|
}
|
||||||
|
ok(pass, name, diag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ispixel(int actual, int r, int g, int b, String name) {
|
||||||
|
// When we read GL pixels the GPU has already processed them and they
|
||||||
|
// are usually off by a little bit. For example a CSS-color pixel of color #64FFF5
|
||||||
|
// was turned into #63FFF7 when it came out of glReadPixels. So in order to compare
|
||||||
|
// against the expected value, we use a little fuzz factor. For the alpha we just
|
||||||
|
// make sure it is always 0xFF.
|
||||||
|
int aAlpha = ((actual >> 24) & 0xFF);
|
||||||
|
int aR = ((actual >> 16) & 0xFF);
|
||||||
|
int aG = ((actual >> 8) & 0xFF);
|
||||||
|
int aB = (actual & 0xFF);
|
||||||
|
boolean pass = (aAlpha == 0xFF) /* alpha */
|
||||||
|
&& (Math.abs(aR - r) < 8) /* red */
|
||||||
|
&& (Math.abs(aG - g) < 8) /* green */
|
||||||
|
&& (Math.abs(aB - b) < 8); /* blue */
|
||||||
|
ok(pass, name, "Color rgba(" + aR + "," + aG + "," + aB + "," + aAlpha + ")" + (pass ? " " : " not") + " close enough to expected rgb(" + r + "," + g + "," + b + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void todo(boolean condition, String name, String diag) {
|
||||||
|
testInfo test = new testInfo(condition, name, diag, true);
|
||||||
|
_logMochitestResult(test, "TEST-UNEXPECTED-PASS", "TEST-KNOWN-FAIL");
|
||||||
|
mTestList.add(test);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void todo_is(Object a, Object b, String name) {
|
||||||
|
boolean pass = a.equals(b);
|
||||||
|
String diag = "got " + a.toString() + ", expected " + b.toString();
|
||||||
|
if (pass) {
|
||||||
|
diag = a.toString() + " should equal " + b.toString();
|
||||||
|
}
|
||||||
|
todo(pass, name, diag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void todo_isnot(Object a, Object b, String name) {
|
||||||
|
boolean pass = !a.equals(b);
|
||||||
|
String diag = "didn't expect " + a.toString() + ", but got it";
|
||||||
|
if (pass) {
|
||||||
|
diag = a.toString() + " should not equal " + b.toString();
|
||||||
|
}
|
||||||
|
todo(pass, name, diag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void info(String name, String message) {
|
||||||
|
testInfo test = new testInfo(true, name, message, false);
|
||||||
|
_logMochitestResult(test, "TEST-INFO", "INFO FAILED?");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,295 +59,294 @@ import org.json.*;
|
||||||
import com.jayway.android.robotium.solo.Solo;
|
import com.jayway.android.robotium.solo.Solo;
|
||||||
|
|
||||||
public class FennecNativeActions implements Actions {
|
public class FennecNativeActions implements Actions {
|
||||||
private Solo solo;
|
private Solo mSolo;
|
||||||
private Instrumentation instr;
|
private Instrumentation mInstr;
|
||||||
private Activity geckoApp;
|
private Activity mGeckoApp;
|
||||||
|
|
||||||
// Objects for reflexive access of fennec classes.
|
// Objects for reflexive access of fennec classes.
|
||||||
private ClassLoader classLoader;
|
private ClassLoader mClassLoader;
|
||||||
private Class gel;
|
private Class mGel;
|
||||||
private Class ge;
|
private Class mGe;
|
||||||
private Class gas;
|
private Class mGas;
|
||||||
private Class drawListener;
|
private Class mDrawListener;
|
||||||
private Method registerGEL;
|
private Method mRegisterGEL;
|
||||||
private Method unregisterGEL;
|
private Method mUnregisterGEL;
|
||||||
private Method sendGE;
|
private Method mSendGE;
|
||||||
private Method getLayerClient;
|
private Method mGetLayerClient;
|
||||||
private Method setDrawListener;
|
private Method mSetDrawListener;
|
||||||
|
|
||||||
public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation){
|
public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation) {
|
||||||
this.solo = robocop;
|
mSolo = robocop;
|
||||||
this.instr = instrumentation;
|
mInstr = instrumentation;
|
||||||
this.geckoApp = activity;
|
mGeckoApp = activity;
|
||||||
// Set up reflexive access of java classes and methods.
|
// Set up reflexive access of java classes and methods.
|
||||||
try {
|
|
||||||
classLoader = activity.getClassLoader();
|
|
||||||
gel = classLoader.loadClass("org.mozilla.gecko.GeckoEventListener");
|
|
||||||
ge = classLoader.loadClass("org.mozilla.gecko.GeckoEvent");
|
|
||||||
gas = classLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
|
|
||||||
Class [] parameters = new Class[2];
|
|
||||||
parameters[0] = String.class;
|
|
||||||
parameters[1] = gel;
|
|
||||||
registerGEL = gas.getMethod("registerGeckoEventListener", parameters);
|
|
||||||
unregisterGEL = gas.getMethod("unregisterGeckoEventListener", parameters);
|
|
||||||
parameters = new Class[1];
|
|
||||||
parameters[0] = ge;
|
|
||||||
sendGE = gas.getMethod("sendEventToGecko", parameters);
|
|
||||||
|
|
||||||
getLayerClient = activity.getClass().getMethod("getSoftwareLayerClient");
|
|
||||||
Class gslc = classLoader.loadClass("org.mozilla.gecko.gfx.GeckoSoftwareLayerClient");
|
|
||||||
drawListener = classLoader.loadClass("org.mozilla.gecko.gfx.GeckoSoftwareLayerClient$DrawListener");
|
|
||||||
setDrawListener = gslc.getDeclaredMethod("setDrawListener", drawListener);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class wakeInvocationHandler implements InvocationHandler {
|
|
||||||
private final GeckoEventExpecter mEventExpecter;
|
|
||||||
|
|
||||||
public wakeInvocationHandler(GeckoEventExpecter expecter) {
|
|
||||||
mEventExpecter = expecter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
|
||||||
String methodName = method.getName();
|
|
||||||
//Depending on the method, return a completely different type.
|
|
||||||
if(methodName.equals("toString")) {
|
|
||||||
return "wakeInvocationHandler";
|
|
||||||
}
|
|
||||||
if(methodName.equals("equals")) {
|
|
||||||
return this == args[0];
|
|
||||||
}
|
|
||||||
if(methodName.equals("clone")) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
if(methodName.equals("hashCode")) {
|
|
||||||
return 314;
|
|
||||||
}
|
|
||||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG,
|
|
||||||
"Waking up on "+methodName);
|
|
||||||
mEventExpecter.notifyOfEvent();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class GeckoEventExpecter implements EventExpecter {
|
|
||||||
private final String mGeckoEvent;
|
|
||||||
private final Object[] mRegistrationParams;
|
|
||||||
private boolean mEventReceived;
|
|
||||||
|
|
||||||
GeckoEventExpecter(String geckoEvent, Object[] registrationParams) {
|
|
||||||
mGeckoEvent = geckoEvent;
|
|
||||||
mRegistrationParams = registrationParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void blockForEvent() {
|
|
||||||
while (! mEventReceived) {
|
|
||||||
try {
|
try {
|
||||||
this.wait();
|
mClassLoader = activity.getClassLoader();
|
||||||
} catch (InterruptedException ie) {
|
mGel = mClassLoader.loadClass("org.mozilla.gecko.GeckoEventListener");
|
||||||
ie.printStackTrace();
|
mGe = mClassLoader.loadClass("org.mozilla.gecko.GeckoEvent");
|
||||||
break;
|
mGas = mClassLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
|
||||||
|
Class [] parameters = new Class[2];
|
||||||
|
parameters[0] = String.class;
|
||||||
|
parameters[1] = mGel;
|
||||||
|
mRegisterGEL = mGas.getMethod("registerGeckoEventListener", parameters);
|
||||||
|
mUnregisterGEL = mGas.getMethod("unregisterGeckoEventListener", parameters);
|
||||||
|
parameters = new Class[1];
|
||||||
|
parameters[0] = mGe;
|
||||||
|
mSendGE = mGas.getMethod("sendEventToGecko", parameters);
|
||||||
|
|
||||||
|
mGetLayerClient = activity.getClass().getMethod("getSoftwareLayerClient");
|
||||||
|
Class gslc = mClassLoader.loadClass("org.mozilla.gecko.gfx.GeckoSoftwareLayerClient");
|
||||||
|
mDrawListener = mClassLoader.loadClass("org.mozilla.gecko.gfx.GeckoSoftwareLayerClient$DrawListener");
|
||||||
|
mSetDrawListener = gslc.getDeclaredMethod("setDrawListener", mDrawListener);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class wakeInvocationHandler implements InvocationHandler {
|
||||||
|
private final GeckoEventExpecter mEventExpecter;
|
||||||
|
|
||||||
|
public wakeInvocationHandler(GeckoEventExpecter expecter) {
|
||||||
|
mEventExpecter = expecter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||||
|
String methodName = method.getName();
|
||||||
|
//Depending on the method, return a completely different type.
|
||||||
|
if(methodName.equals("toString")) {
|
||||||
|
return "wakeInvocationHandler";
|
||||||
|
}
|
||||||
|
if(methodName.equals("equals")) {
|
||||||
|
return this == args[0];
|
||||||
|
}
|
||||||
|
if(methodName.equals("clone")) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
if(methodName.equals("hashCode")) {
|
||||||
|
return 314;
|
||||||
|
}
|
||||||
|
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG,
|
||||||
|
"Waking up on "+methodName);
|
||||||
|
mEventExpecter.notifyOfEvent();
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG,
|
|
||||||
"unblocked on expecter for " + mGeckoEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean eventReceived() {
|
class GeckoEventExpecter implements EventExpecter {
|
||||||
return mEventReceived;
|
private final String mGeckoEvent;
|
||||||
}
|
private final Object[] mRegistrationParams;
|
||||||
|
private boolean mEventReceived;
|
||||||
|
|
||||||
void notifyOfEvent() {
|
GeckoEventExpecter(String geckoEvent, Object[] registrationParams) {
|
||||||
try {
|
mGeckoEvent = geckoEvent;
|
||||||
unregisterGEL.invoke(null, mRegistrationParams);
|
mRegistrationParams = registrationParams;
|
||||||
} catch (IllegalAccessException e) {
|
}
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG,
|
|
||||||
"received event " + mGeckoEvent);
|
|
||||||
synchronized (this) {
|
|
||||||
mEventReceived = true;
|
|
||||||
this.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public EventExpecter expectGeckoEvent(String geckoEvent) {
|
|
||||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG,
|
|
||||||
"waiting for "+geckoEvent);
|
|
||||||
try {
|
|
||||||
Class [] interfaces = new Class[1];
|
|
||||||
interfaces[0] = gel;
|
|
||||||
Object[] finalParams = new Object[2];
|
|
||||||
finalParams[0] = geckoEvent;
|
|
||||||
|
|
||||||
GeckoEventExpecter expecter = new GeckoEventExpecter(geckoEvent, finalParams);
|
|
||||||
wakeInvocationHandler wIH = new wakeInvocationHandler(expecter);
|
|
||||||
Object proxy = Proxy.newProxyInstance(classLoader, interfaces, wIH);
|
|
||||||
finalParams[1] = proxy;
|
|
||||||
registerGEL.invoke(null, finalParams);
|
|
||||||
|
|
||||||
return expecter;
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DrawListenerProxy implements InvocationHandler {
|
public synchronized void blockForEvent() {
|
||||||
private final PaintExpecter mPaintExpecter;
|
while (! mEventReceived) {
|
||||||
|
try {
|
||||||
|
this.wait();
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
ie.printStackTrace();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG,
|
||||||
|
"unblocked on expecter for " + mGeckoEvent);
|
||||||
|
}
|
||||||
|
|
||||||
DrawListenerProxy(PaintExpecter paintExpecter) {
|
public synchronized boolean eventReceived() {
|
||||||
mPaintExpecter = paintExpecter;
|
return mEventReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyOfEvent() {
|
||||||
|
try {
|
||||||
|
mUnregisterGEL.invoke(null, mRegistrationParams);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG,
|
||||||
|
"received event " + mGeckoEvent);
|
||||||
|
synchronized (this) {
|
||||||
|
mEventReceived = true;
|
||||||
|
this.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
public EventExpecter expectGeckoEvent(String geckoEvent) {
|
||||||
String methodName = method.getName();
|
|
||||||
if ("drawFinished".equals(methodName)) {
|
|
||||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG,
|
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG,
|
||||||
"Received drawFinished notification");
|
"waiting for "+geckoEvent);
|
||||||
mPaintExpecter.notifyOfEvent();
|
|
||||||
} else if ("toString".equals(methodName)) {
|
|
||||||
return "DrawListenerProxy";
|
|
||||||
} else if ("equals".equals(methodName)) {
|
|
||||||
return false;
|
|
||||||
} else if ("hashCode".equals(methodName)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PaintExpecter implements RepeatedEventExpecter {
|
|
||||||
private Object mLayerClient;
|
|
||||||
private boolean mPaintDone;
|
|
||||||
|
|
||||||
PaintExpecter() throws IllegalAccessException, InvocationTargetException {
|
|
||||||
mLayerClient = getLayerClient.invoke(geckoApp);
|
|
||||||
setDrawListener.invoke(mLayerClient, Proxy.newProxyInstance(classLoader, new Class[] { drawListener }, new DrawListenerProxy(this)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void notifyOfEvent() {
|
|
||||||
synchronized (this) {
|
|
||||||
mPaintDone = true;
|
|
||||||
this.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void blockForEvent() {
|
|
||||||
while (! mPaintDone) {
|
|
||||||
try {
|
try {
|
||||||
this.wait();
|
Class [] interfaces = new Class[1];
|
||||||
} catch (InterruptedException ie) {
|
interfaces[0] = mGel;
|
||||||
ie.printStackTrace();
|
Object[] finalParams = new Object[2];
|
||||||
break;
|
finalParams[0] = geckoEvent;
|
||||||
|
|
||||||
|
GeckoEventExpecter expecter = new GeckoEventExpecter(geckoEvent, finalParams);
|
||||||
|
wakeInvocationHandler wIH = new wakeInvocationHandler(expecter);
|
||||||
|
Object proxy = Proxy.newProxyInstance(mClassLoader, interfaces, wIH);
|
||||||
|
finalParams[1] = proxy;
|
||||||
|
mRegisterGEL.invoke(null, finalParams);
|
||||||
|
|
||||||
|
return expecter;
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
return null;
|
||||||
try {
|
|
||||||
setDrawListener.invoke(mLayerClient, (Object)null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean eventReceived() {
|
class DrawListenerProxy implements InvocationHandler {
|
||||||
return mPaintDone;
|
private final PaintExpecter mPaintExpecter;
|
||||||
|
|
||||||
|
DrawListenerProxy(PaintExpecter paintExpecter) {
|
||||||
|
mPaintExpecter = paintExpecter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||||
|
String methodName = method.getName();
|
||||||
|
if ("drawFinished".equals(methodName)) {
|
||||||
|
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG,
|
||||||
|
"Received drawFinished notification");
|
||||||
|
mPaintExpecter.notifyOfEvent();
|
||||||
|
} else if ("toString".equals(methodName)) {
|
||||||
|
return "DrawListenerProxy";
|
||||||
|
} else if ("equals".equals(methodName)) {
|
||||||
|
return false;
|
||||||
|
} else if ("hashCode".equals(methodName)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void blockUntilClear(long millis) {
|
class PaintExpecter implements RepeatedEventExpecter {
|
||||||
if (millis <= 0) {
|
private Object mLayerClient;
|
||||||
throw new IllegalArgumentException("millis must be > 0");
|
private boolean mPaintDone;
|
||||||
}
|
|
||||||
// wait for at least one event
|
PaintExpecter() throws IllegalAccessException, InvocationTargetException {
|
||||||
while (! mPaintDone) {
|
mLayerClient = mGetLayerClient.invoke(mGeckoApp);
|
||||||
|
mSetDrawListener.invoke(mLayerClient, Proxy.newProxyInstance(mClassLoader, new Class[] { mDrawListener }, new DrawListenerProxy(this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyOfEvent() {
|
||||||
|
synchronized (this) {
|
||||||
|
mPaintDone = true;
|
||||||
|
this.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void blockForEvent() {
|
||||||
|
while (!mPaintDone) {
|
||||||
|
try {
|
||||||
|
this.wait();
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
ie.printStackTrace();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mSetDrawListener.invoke(mLayerClient, (Object)null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean eventReceived() {
|
||||||
|
return mPaintDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void blockUntilClear(long millis) {
|
||||||
|
if (millis <= 0) {
|
||||||
|
throw new IllegalArgumentException("millis must be > 0");
|
||||||
|
}
|
||||||
|
// wait for at least one event
|
||||||
|
while (!mPaintDone) {
|
||||||
|
try {
|
||||||
|
this.wait();
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
ie.printStackTrace();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// now wait for a period of millis where we don't get an event
|
||||||
|
long startTime = SystemClock.uptimeMillis();
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
this.wait(millis);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
ie.printStackTrace();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
long endTime = SystemClock.uptimeMillis();
|
||||||
|
if (endTime - startTime >= millis) {
|
||||||
|
// success
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// we got a notify() before we could wait long enough, so we need to start over
|
||||||
|
startTime = endTime;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mSetDrawListener.invoke(mLayerClient, (Object)null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepeatedEventExpecter expectPaint() {
|
||||||
try {
|
try {
|
||||||
this.wait();
|
return new PaintExpecter();
|
||||||
} catch (InterruptedException ie) {
|
} catch (Exception e) {
|
||||||
ie.printStackTrace();
|
e.printStackTrace();
|
||||||
break;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// now wait for a period of millis where we don't get an event
|
|
||||||
long startTime = SystemClock.uptimeMillis();
|
public void sendSpecialKey(SpecialKey button) {
|
||||||
while (true) {
|
switch(button) {
|
||||||
try {
|
case DOWN:
|
||||||
this.wait(millis);
|
mInstr.sendCharacterSync(KeyEvent.KEYCODE_DPAD_DOWN);
|
||||||
} catch (InterruptedException ie) {
|
break;
|
||||||
ie.printStackTrace();
|
case UP:
|
||||||
break;
|
mInstr.sendCharacterSync(KeyEvent.KEYCODE_DPAD_UP);
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
mInstr.sendCharacterSync(KeyEvent.KEYCODE_DPAD_LEFT);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
mInstr.sendCharacterSync(KeyEvent.KEYCODE_DPAD_RIGHT);
|
||||||
|
break;
|
||||||
|
case ENTER:
|
||||||
|
mInstr.sendCharacterSync(KeyEvent.KEYCODE_ENTER);
|
||||||
|
break;
|
||||||
|
case MENU:
|
||||||
|
mInstr.sendCharacterSync(KeyEvent.KEYCODE_MENU);
|
||||||
|
break;
|
||||||
|
case BACK:
|
||||||
|
mInstr.sendCharacterSync(KeyEvent.KEYCODE_BACK);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
long endTime = SystemClock.uptimeMillis();
|
|
||||||
if (endTime - startTime >= millis) {
|
|
||||||
// success
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// we got a notify() before we could wait long enough, so we need to start over
|
|
||||||
startTime = endTime;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
setDrawListener.invoke(mLayerClient, (Object)null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public RepeatedEventExpecter expectPaint() {
|
@Override
|
||||||
try {
|
public void sendKeys(String input) {
|
||||||
return new PaintExpecter();
|
mInstr.sendStringSync(input);
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void sendSpecialKey(SpecialKey button) {
|
public void drag(int startingX, int endingX, int startingY, int endingY) {
|
||||||
switch( button) {
|
mSolo.drag(startingX, endingX, startingY, endingY, 10);
|
||||||
case DOWN:
|
|
||||||
instr.sendCharacterSync(KeyEvent.KEYCODE_DPAD_DOWN);
|
|
||||||
break;
|
|
||||||
case UP:
|
|
||||||
instr.sendCharacterSync(KeyEvent.KEYCODE_DPAD_UP);
|
|
||||||
break;
|
|
||||||
case LEFT:
|
|
||||||
instr.sendCharacterSync(KeyEvent.KEYCODE_DPAD_LEFT);
|
|
||||||
break;
|
|
||||||
case RIGHT:
|
|
||||||
instr.sendCharacterSync(KeyEvent.KEYCODE_DPAD_RIGHT);
|
|
||||||
break;
|
|
||||||
case ENTER:
|
|
||||||
instr.sendCharacterSync(KeyEvent.KEYCODE_ENTER);
|
|
||||||
break;
|
|
||||||
case MENU:
|
|
||||||
instr.sendCharacterSync(KeyEvent.KEYCODE_MENU);
|
|
||||||
break;
|
|
||||||
case BACK:
|
|
||||||
instr.sendCharacterSync(KeyEvent.KEYCODE_BACK);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendKeys(String input) {
|
|
||||||
instr.sendStringSync(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void drag(int startingX, int endingX, int startingY, int endingY) {
|
|
||||||
solo.drag(startingX, endingX, startingY, endingY, 10);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,8 +46,6 @@ import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -68,396 +66,405 @@ import org.json.*;
|
||||||
import com.jayway.android.robotium.solo.Solo;
|
import com.jayway.android.robotium.solo.Solo;
|
||||||
|
|
||||||
public class FennecNativeDriver implements Driver {
|
public class FennecNativeDriver implements Driver {
|
||||||
// Map of IDs to element names.
|
// Map of IDs to element names.
|
||||||
private HashMap locators = null;
|
private HashMap mLocators = null;
|
||||||
private Activity activity;
|
private Activity mActivity;
|
||||||
private Solo solo;
|
private Solo mSolo;
|
||||||
|
|
||||||
private static String mLogFile = null;
|
private static String mLogFile = null;
|
||||||
private static LogLevel mLogLevel = LogLevel.LOG_LEVEL_INFO;
|
private static LogLevel mLogLevel = LogLevel.LOG_LEVEL_INFO;
|
||||||
|
|
||||||
// Objects for reflexive access of fennec classes.
|
// Objects for reflexive access of fennec classes.
|
||||||
private ClassLoader classLoader;
|
private ClassLoader mClassLoader;
|
||||||
private Class gel;
|
private Class mGel;
|
||||||
private Class ge;
|
private Class mGe;
|
||||||
private Class gas;
|
private Class mGas;
|
||||||
private Method registerGEL;
|
private Method mRegisterGEL;
|
||||||
private Method unregisterGEL;
|
private Method mUnregisterGEL;
|
||||||
private Method sendGE;
|
private Method mSendGE;
|
||||||
private Method _startFrameRecording;
|
private Method _startFrameRecording;
|
||||||
private Method _stopFrameRecording;
|
private Method _stopFrameRecording;
|
||||||
private Method _startCheckerboardRecording;
|
private Method _startCheckerboardRecording;
|
||||||
private Method _stopCheckerboardRecording;
|
private Method _stopCheckerboardRecording;
|
||||||
private Method _getPixels;
|
private Method _getPixels;
|
||||||
|
|
||||||
public enum LogLevel {
|
public enum LogLevel {
|
||||||
LOG_LEVEL_DEBUG(1),
|
LOG_LEVEL_DEBUG(1),
|
||||||
LOG_LEVEL_INFO(2),
|
LOG_LEVEL_INFO(2),
|
||||||
LOG_LEVEL_WARN(3),
|
LOG_LEVEL_WARN(3),
|
||||||
LOG_LEVEL_ERROR(4);
|
LOG_LEVEL_ERROR(4);
|
||||||
|
|
||||||
private int mValue;
|
private int mValue;
|
||||||
LogLevel(int value) {
|
LogLevel(int value) {
|
||||||
mValue = value;
|
mValue = value;
|
||||||
}
|
|
||||||
public boolean isEnabled(LogLevel configuredLevel) {
|
|
||||||
return mValue >= configuredLevel.getValue();
|
|
||||||
}
|
|
||||||
private int getValue() {
|
|
||||||
return mValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FennecNativeDriver(Activity activity, Solo robocop){
|
|
||||||
this.activity = activity;
|
|
||||||
this.solo = robocop;
|
|
||||||
|
|
||||||
// Set up table of fennec_ids.
|
|
||||||
locators = convertTextToTable(getFile("/mnt/sdcard/fennec_ids.txt"));
|
|
||||||
|
|
||||||
// Set up reflexive access of java classes and methods.
|
|
||||||
try {
|
|
||||||
classLoader = activity.getClassLoader();
|
|
||||||
gel = classLoader.loadClass("org.mozilla.gecko.GeckoEventListener");
|
|
||||||
ge = classLoader.loadClass("org.mozilla.gecko.GeckoEvent");
|
|
||||||
gas = classLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
|
|
||||||
Class [] parameters = new Class[2];
|
|
||||||
parameters[0] = String.class;
|
|
||||||
parameters[1] = gel;
|
|
||||||
registerGEL = gas.getMethod("registerGeckoEventListener", parameters);
|
|
||||||
unregisterGEL = gas.getMethod("unregisterGeckoEventListener", parameters);
|
|
||||||
parameters = new Class[1];
|
|
||||||
parameters[0] = ge;
|
|
||||||
sendGE = gas.getMethod("sendEventToGecko", parameters);
|
|
||||||
|
|
||||||
Class gfx = classLoader.loadClass("org.mozilla.gecko.gfx.PanningPerfAPI");
|
|
||||||
_startFrameRecording = gfx.getDeclaredMethod("startFrameTimeRecording");
|
|
||||||
_stopFrameRecording = gfx.getDeclaredMethod("stopFrameTimeRecording");
|
|
||||||
_startCheckerboardRecording = gfx.getDeclaredMethod("startCheckerboardRecording");
|
|
||||||
_stopCheckerboardRecording = gfx.getDeclaredMethod("stopCheckerboardRecording");
|
|
||||||
|
|
||||||
Class layerView = classLoader.loadClass("org.mozilla.gecko.gfx.LayerView");
|
|
||||||
_getPixels = layerView.getDeclaredMethod("getPixels");
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Information on the location of the Gecko Frame.
|
|
||||||
private boolean geckoInfo = false;
|
|
||||||
private int geckoTop = 100;
|
|
||||||
private int geckoLeft = 0;
|
|
||||||
private int geckoHeight= 700;
|
|
||||||
private int geckoWidth = 1024;
|
|
||||||
|
|
||||||
private void getGeckoInfo() {
|
|
||||||
View geckoLayout = activity.findViewById(Integer.decode((String)locators.get("gecko_layout")));
|
|
||||||
if (geckoLayout != null) {
|
|
||||||
int[] pos = new int[2];
|
|
||||||
geckoLayout.getLocationOnScreen(pos);
|
|
||||||
geckoTop = pos[1];
|
|
||||||
geckoLeft = pos[0];
|
|
||||||
geckoWidth = geckoLayout.getWidth();
|
|
||||||
geckoHeight = geckoLayout.getHeight();
|
|
||||||
geckoInfo = true;
|
|
||||||
} else {
|
|
||||||
throw new RoboCopException("Unable to find view gecko_layout");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getGeckoTop() {
|
|
||||||
if(!geckoInfo) {
|
|
||||||
getGeckoInfo();
|
|
||||||
}
|
|
||||||
return geckoTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getGeckoLeft() {
|
|
||||||
if(!geckoInfo) {
|
|
||||||
getGeckoInfo();
|
|
||||||
}
|
|
||||||
return geckoLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getGeckoHeight() {
|
|
||||||
if(!geckoInfo) {
|
|
||||||
getGeckoInfo();
|
|
||||||
}
|
|
||||||
return geckoHeight;
|
|
||||||
}
|
|
||||||
public int getGeckoWidth() {
|
|
||||||
if(!geckoInfo) {
|
|
||||||
getGeckoInfo();
|
|
||||||
}
|
|
||||||
return geckoWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Element findElement(Activity activity, String name) {
|
|
||||||
if (name == null)
|
|
||||||
throw new IllegalArgumentException("Can not findElements when passed a null");
|
|
||||||
if (locators.containsKey(name)){
|
|
||||||
return new FennecNativeElement(Integer.decode((String)locators.get(name)), activity, solo);
|
|
||||||
}
|
|
||||||
throw new RoboCopException("Element does not exist in the list");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startFrameRecording() {
|
|
||||||
try {
|
|
||||||
Object [] params = null;
|
|
||||||
_startFrameRecording.invoke(null, params);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int stopFrameRecording() {
|
|
||||||
Class [] parameters = new Class[1];
|
|
||||||
parameters[0] = null;
|
|
||||||
List frames;
|
|
||||||
|
|
||||||
try {
|
|
||||||
Object [] params = null;
|
|
||||||
frames = (List)_stopFrameRecording.invoke(null, params);
|
|
||||||
Object [] framearray = frames.toArray();
|
|
||||||
Long last = new Long(0);
|
|
||||||
Long threshold = new Long(17);
|
|
||||||
int numDelays = 0;
|
|
||||||
for (int i=0; i < framearray.length; i++) {
|
|
||||||
Long val = (Long)framearray[i];
|
|
||||||
if ((val - last) > threshold) {
|
|
||||||
numDelays++;
|
|
||||||
}
|
}
|
||||||
last = val;
|
public boolean isEnabled(LogLevel configuredLevel) {
|
||||||
}
|
return mValue >= configuredLevel.getValue();
|
||||||
return numDelays;
|
}
|
||||||
} catch (IllegalAccessException e) {
|
private int getValue() {
|
||||||
e.printStackTrace();
|
return mValue;
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startCheckerboardRecording() {
|
|
||||||
try {
|
|
||||||
Object [] params = null;
|
|
||||||
_startCheckerboardRecording.invoke(null, params);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public float stopCheckerboardRecording() {
|
|
||||||
Class [] parameters = new Class[1];
|
|
||||||
parameters[0] = null;
|
|
||||||
List checkerboard;
|
|
||||||
|
|
||||||
try {
|
|
||||||
Object [] params = null;
|
|
||||||
checkerboard = (List)_stopCheckerboardRecording.invoke(null, params);
|
|
||||||
Object [] amountarray = checkerboard.toArray();
|
|
||||||
double completeness = 0;
|
|
||||||
for (Object obj : amountarray) {
|
|
||||||
float val = (Float)obj;
|
|
||||||
completeness += (1.0 - (double)val) / (double)amountarray.length;
|
|
||||||
}
|
|
||||||
return (float)completeness;
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GLSurfaceView getSurfaceView() {
|
|
||||||
for (View v : solo.getCurrentViews()) {
|
|
||||||
if (v instanceof GLSurfaceView) {
|
|
||||||
return (GLSurfaceView)v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int[][] getPaintedSurface() {
|
|
||||||
GLSurfaceView view = getSurfaceView();
|
|
||||||
if (view == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
IntBuffer pixelBuffer;
|
|
||||||
try {
|
|
||||||
pixelBuffer = (IntBuffer)_getPixels.invoke(view);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we need to (1) flip the image, because GL likes to do things up-side-down,
|
|
||||||
// and (2) rearrange the bits from AGBR-8888 to ARGB-8888.
|
|
||||||
int w = view.getWidth();
|
|
||||||
int h = view.getHeight();
|
|
||||||
pixelBuffer.position(0);
|
|
||||||
int[][] pixels = new int[h][w];
|
|
||||||
for (int y = h - 1; y >= 0; y--) {
|
|
||||||
for (int x = 0; x < w; x++) {
|
|
||||||
int agbr = pixelBuffer.get();
|
|
||||||
pixels[y][x] = (agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pixels;
|
|
||||||
}
|
|
||||||
|
|
||||||
class scrollHandler implements InvocationHandler {
|
|
||||||
public scrollHandler(){};
|
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
|
||||||
try{
|
|
||||||
//Disect the JSON object into the appropriate variables
|
|
||||||
JSONObject jo = ((JSONObject)args[1]);
|
|
||||||
scrollHeight = jo.getInt("y");
|
|
||||||
height = jo.getInt("cheight");
|
|
||||||
//We don't want a height of 0. That means it's a bad response.
|
|
||||||
if( height > 0) {
|
|
||||||
pageHeight = jo.getInt("height");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch( Throwable e) {
|
|
||||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_WARN,
|
|
||||||
"WARNING: ScrollReceived, but read wrong!");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public int getScrollHeight() {
|
|
||||||
return scrollHeight;
|
|
||||||
}
|
|
||||||
public int getPageHeight() {
|
|
||||||
return pageHeight;
|
|
||||||
}
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int height=0;
|
|
||||||
public int scrollHeight=0;
|
|
||||||
public int pageHeight=10;
|
|
||||||
public void setupScrollHandling() {
|
|
||||||
//Setup scrollHandler to catch "robocop:scroll" events.
|
|
||||||
try {
|
|
||||||
Class [] interfaces = new Class[1];
|
|
||||||
interfaces[0] = gel;
|
|
||||||
Object[] finalParams = new Object[2];
|
|
||||||
finalParams[0] = "robocop:scroll";
|
|
||||||
finalParams[1] = Proxy.newProxyInstance(classLoader, interfaces, new scrollHandler());
|
|
||||||
registerGEL.invoke(null, finalParams);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public FennecNativeDriver(Activity activity, Solo robocop) {
|
||||||
|
mActivity = activity;
|
||||||
|
mSolo = robocop;
|
||||||
|
|
||||||
//Takes a filename, loads the file,
|
// Set up table of fennec_ids.
|
||||||
// and returns a string version of the entire file.
|
mLocators = convertTextToTable(getFile("/mnt/sdcard/fennec_ids.txt"));
|
||||||
public static String getFile(String filename)
|
|
||||||
{
|
|
||||||
StringBuilder text = new StringBuilder();
|
|
||||||
|
|
||||||
BufferedReader br = null;
|
// Set up reflexive access of java classes and methods.
|
||||||
try {
|
|
||||||
br = new BufferedReader(new FileReader(filename));
|
|
||||||
String line;
|
|
||||||
|
|
||||||
while ((line = br.readLine()) != null) {
|
|
||||||
text.append(line);
|
|
||||||
text.append('\n');
|
|
||||||
}
|
|
||||||
} catch(IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return text.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes a string of "key=value" pairs split by \n and creates a hash table.
|
|
||||||
public static HashMap convertTextToTable(String data)
|
|
||||||
{
|
|
||||||
HashMap retVal = new HashMap();
|
|
||||||
|
|
||||||
String[] lines = data.split("\n");
|
|
||||||
for (int i = 0; i < lines.length; i++) {
|
|
||||||
String[] parts = lines[i].split("=");
|
|
||||||
retVal.put(parts[0].trim(), parts[1].trim());
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the filename used for logging. If the file already exists, delete it
|
|
||||||
// as a safe-guard against accidentally appending to an old log file.
|
|
||||||
public static void setLogFile(String filename) {
|
|
||||||
mLogFile = filename;
|
|
||||||
File file = new File(mLogFile);
|
|
||||||
if (file.exists()) {
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setLogLevel(LogLevel level) {
|
|
||||||
mLogLevel = level;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void log(LogLevel level, String message) {
|
|
||||||
if (mLogFile == null) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level.isEnabled(mLogLevel)) {
|
|
||||||
File file = new File(mLogFile);
|
|
||||||
BufferedWriter bw = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
bw = new BufferedWriter(new FileWriter(mLogFile, true));
|
|
||||||
bw.write(message);
|
|
||||||
bw.newLine();
|
|
||||||
} catch(IOException e) {
|
|
||||||
Log.e("Robocop", "exception with file writer on: " + mLogFile);
|
|
||||||
} finally {
|
|
||||||
try {
|
try {
|
||||||
if (bw != null) {
|
mClassLoader = activity.getClassLoader();
|
||||||
bw.flush();
|
mGel = mClassLoader.loadClass("org.mozilla.gecko.GeckoEventListener");
|
||||||
bw.close();
|
mGe = mClassLoader.loadClass("org.mozilla.gecko.GeckoEvent");
|
||||||
}
|
mGas = mClassLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
|
||||||
} catch (IOException ex) {
|
Class [] parameters = new Class[2];
|
||||||
ex.printStackTrace();
|
parameters[0] = String.class;
|
||||||
}
|
parameters[1] = mGel;
|
||||||
}
|
mRegisterGEL = mGas.getMethod("registerGeckoEventListener", parameters);
|
||||||
|
mUnregisterGEL = mGas.getMethod("unregisterGeckoEventListener", parameters);
|
||||||
|
parameters = new Class[1];
|
||||||
|
parameters[0] = mGe;
|
||||||
|
mSendGE = mGas.getMethod("sendEventToGecko", parameters);
|
||||||
|
|
||||||
|
Class gfx = mClassLoader.loadClass("org.mozilla.gecko.gfx.PanningPerfAPI");
|
||||||
|
_startFrameRecording = gfx.getDeclaredMethod("startFrameTimeRecording");
|
||||||
|
_stopFrameRecording = gfx.getDeclaredMethod("stopFrameTimeRecording");
|
||||||
|
_startCheckerboardRecording = gfx.getDeclaredMethod("startCheckerboardRecording");
|
||||||
|
_stopCheckerboardRecording = gfx.getDeclaredMethod("stopCheckerboardRecording");
|
||||||
|
|
||||||
|
Class layerView = mClassLoader.loadClass("org.mozilla.gecko.gfx.LayerView");
|
||||||
|
_getPixels = layerView.getDeclaredMethod("getPixels");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level == LogLevel.LOG_LEVEL_INFO) {
|
//Information on the location of the Gecko Frame.
|
||||||
Log.i("Robocop", message);
|
private boolean mGeckoInfo = false;
|
||||||
} else if (level == LogLevel.LOG_LEVEL_DEBUG) {
|
private int mGeckoTop = 100;
|
||||||
Log.d("Robocop", message);
|
private int mGeckoLeft = 0;
|
||||||
} else if (level == LogLevel.LOG_LEVEL_WARN) {
|
private int mGeckoHeight= 700;
|
||||||
Log.w("Robocop", message);
|
private int mGeckoWidth = 1024;
|
||||||
} else if (level == LogLevel.LOG_LEVEL_ERROR) {
|
|
||||||
Log.e("Robocop", message);
|
private void getGeckoInfo() {
|
||||||
|
View geckoLayout = mActivity.findViewById(Integer.decode((String)mLocators.get("gecko_layout")));
|
||||||
|
if (geckoLayout != null) {
|
||||||
|
int[] pos = new int[2];
|
||||||
|
geckoLayout.getLocationOnScreen(pos);
|
||||||
|
mGeckoTop = pos[1];
|
||||||
|
mGeckoLeft = pos[0];
|
||||||
|
mGeckoWidth = geckoLayout.getWidth();
|
||||||
|
mGeckoHeight = geckoLayout.getHeight();
|
||||||
|
mGeckoInfo = true;
|
||||||
|
} else {
|
||||||
|
throw new RoboCopException("Unable to find view gecko_layout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGeckoTop() {
|
||||||
|
if (!mGeckoInfo) {
|
||||||
|
getGeckoInfo();
|
||||||
|
}
|
||||||
|
return mGeckoTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGeckoLeft() {
|
||||||
|
if (!mGeckoInfo) {
|
||||||
|
getGeckoInfo();
|
||||||
|
}
|
||||||
|
return mGeckoLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGeckoHeight() {
|
||||||
|
if (!mGeckoInfo) {
|
||||||
|
getGeckoInfo();
|
||||||
|
}
|
||||||
|
return mGeckoHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGeckoWidth() {
|
||||||
|
if (!mGeckoInfo) {
|
||||||
|
getGeckoInfo();
|
||||||
|
}
|
||||||
|
return mGeckoWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Element findElement(Activity activity, String name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new IllegalArgumentException("Can not findElements when passed a null");
|
||||||
|
}
|
||||||
|
if (mLocators.containsKey(name)) {
|
||||||
|
return new FennecNativeElement(Integer.decode((String)mLocators.get(name)), activity, mSolo);
|
||||||
|
}
|
||||||
|
throw new RoboCopException("Element does not exist in the list");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startFrameRecording() {
|
||||||
|
try {
|
||||||
|
Object [] params = null;
|
||||||
|
_startFrameRecording.invoke(null, params);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int stopFrameRecording() {
|
||||||
|
Class [] parameters = new Class[1];
|
||||||
|
parameters[0] = null;
|
||||||
|
List frames;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object [] params = null;
|
||||||
|
frames = (List)_stopFrameRecording.invoke(null, params);
|
||||||
|
Object [] framearray = frames.toArray();
|
||||||
|
Long last = new Long(0);
|
||||||
|
Long threshold = new Long(17);
|
||||||
|
int numDelays = 0;
|
||||||
|
for (int i=0; i < framearray.length; i++) {
|
||||||
|
Long val = (Long)framearray[i];
|
||||||
|
if ((val - last) > threshold) {
|
||||||
|
numDelays++;
|
||||||
|
}
|
||||||
|
last = val;
|
||||||
|
}
|
||||||
|
return numDelays;
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startCheckerboardRecording() {
|
||||||
|
try {
|
||||||
|
Object [] params = null;
|
||||||
|
_startCheckerboardRecording.invoke(null, params);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float stopCheckerboardRecording() {
|
||||||
|
Class [] parameters = new Class[1];
|
||||||
|
parameters[0] = null;
|
||||||
|
List checkerboard;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object [] params = null;
|
||||||
|
checkerboard = (List)_stopCheckerboardRecording.invoke(null, params);
|
||||||
|
Object [] amountarray = checkerboard.toArray();
|
||||||
|
double completeness = 0;
|
||||||
|
for (Object obj : amountarray) {
|
||||||
|
float val = (Float)obj;
|
||||||
|
completeness += (1.0 - (double)val) / (double)amountarray.length;
|
||||||
|
}
|
||||||
|
return (float)completeness;
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GLSurfaceView getSurfaceView() {
|
||||||
|
for (View v : mSolo.getCurrentViews()) {
|
||||||
|
if (v instanceof GLSurfaceView) {
|
||||||
|
return (GLSurfaceView)v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[][] getPaintedSurface() {
|
||||||
|
GLSurfaceView view = getSurfaceView();
|
||||||
|
if (view == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
IntBuffer pixelBuffer;
|
||||||
|
try {
|
||||||
|
pixelBuffer = (IntBuffer)_getPixels.invoke(view);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we need to (1) flip the image, because GL likes to do things up-side-down,
|
||||||
|
// and (2) rearrange the bits from AGBR-8888 to ARGB-8888.
|
||||||
|
int w = view.getWidth();
|
||||||
|
int h = view.getHeight();
|
||||||
|
pixelBuffer.position(0);
|
||||||
|
int[][] pixels = new int[h][w];
|
||||||
|
for (int y = h - 1; y >= 0; y--) {
|
||||||
|
for (int x = 0; x < w; x++) {
|
||||||
|
int agbr = pixelBuffer.get();
|
||||||
|
pixels[y][x] = (agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int mHeight=0;
|
||||||
|
public int mScrollHeight=0;
|
||||||
|
public int mPageHeight=10;
|
||||||
|
|
||||||
|
class scrollHandler implements InvocationHandler {
|
||||||
|
public scrollHandler(){};
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||||
|
try {
|
||||||
|
// Disect the JSON object into the appropriate variables
|
||||||
|
JSONObject jo = ((JSONObject)args[1]);
|
||||||
|
mScrollHeight = jo.getInt("y");
|
||||||
|
mHeight = jo.getInt("cheight");
|
||||||
|
// We don't want a height of 0. That means it's a bad response.
|
||||||
|
if (mHeight > 0) {
|
||||||
|
mPageHeight = jo.getInt("height");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch( Throwable e) {
|
||||||
|
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_WARN,
|
||||||
|
"WARNING: ScrollReceived, but read wrong!");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getScrollHeight() {
|
||||||
|
return mScrollHeight;
|
||||||
|
}
|
||||||
|
public int getPageHeight() {
|
||||||
|
return mPageHeight;
|
||||||
|
}
|
||||||
|
public int getHeight() {
|
||||||
|
return mHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupScrollHandling() {
|
||||||
|
//Setup scrollHandler to catch "robocop:scroll" events.
|
||||||
|
try {
|
||||||
|
Class [] interfaces = new Class[1];
|
||||||
|
interfaces[0] = mGel;
|
||||||
|
Object[] finalParams = new Object[2];
|
||||||
|
finalParams[0] = "robocop:scroll";
|
||||||
|
finalParams[1] = Proxy.newProxyInstance(mClassLoader, interfaces, new scrollHandler());
|
||||||
|
mRegisterGEL.invoke(null, finalParams);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a filename, loads the file, and returns a string version of the entire file.
|
||||||
|
*/
|
||||||
|
public static String getFile(String filename)
|
||||||
|
{
|
||||||
|
StringBuilder text = new StringBuilder();
|
||||||
|
|
||||||
|
BufferedReader br = null;
|
||||||
|
try {
|
||||||
|
br = new BufferedReader(new FileReader(filename));
|
||||||
|
String line;
|
||||||
|
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
text.append(line);
|
||||||
|
text.append('\n');
|
||||||
|
}
|
||||||
|
} catch(IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
br.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a string of "key=value" pairs split by \n and creates a hash table.
|
||||||
|
*/
|
||||||
|
public static HashMap convertTextToTable(String data)
|
||||||
|
{
|
||||||
|
HashMap retVal = new HashMap();
|
||||||
|
|
||||||
|
String[] lines = data.split("\n");
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
String[] parts = lines[i].split("=");
|
||||||
|
retVal.put(parts[0].trim(), parts[1].trim());
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the filename used for logging. If the file already exists, delete it
|
||||||
|
* as a safe-guard against accidentally appending to an old log file.
|
||||||
|
*/
|
||||||
|
public static void setLogFile(String filename) {
|
||||||
|
mLogFile = filename;
|
||||||
|
File file = new File(mLogFile);
|
||||||
|
if (file.exists()) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setLogLevel(LogLevel level) {
|
||||||
|
mLogLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void log(LogLevel level, String message) {
|
||||||
|
if (mLogFile == null) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level.isEnabled(mLogLevel)) {
|
||||||
|
File file = new File(mLogFile);
|
||||||
|
BufferedWriter bw = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
bw = new BufferedWriter(new FileWriter(mLogFile, true));
|
||||||
|
bw.write(message);
|
||||||
|
bw.newLine();
|
||||||
|
} catch(IOException e) {
|
||||||
|
Log.e("Robocop", "exception with file writer on: " + mLogFile);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (bw != null) {
|
||||||
|
bw.flush();
|
||||||
|
bw.close();
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level == LogLevel.LOG_LEVEL_INFO) {
|
||||||
|
Log.i("Robocop", message);
|
||||||
|
} else if (level == LogLevel.LOG_LEVEL_DEBUG) {
|
||||||
|
Log.d("Robocop", message);
|
||||||
|
} else if (level == LogLevel.LOG_LEVEL_WARN) {
|
||||||
|
Log.w("Robocop", message);
|
||||||
|
} else if (level == LogLevel.LOG_LEVEL_ERROR) {
|
||||||
|
Log.e("Robocop", message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,6 @@ package @ANDROID_PACKAGE_NAME@;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
@ -55,110 +54,110 @@ import com.jayway.android.robotium.solo.Solo;
|
||||||
import java.util.concurrent.SynchronousQueue;
|
import java.util.concurrent.SynchronousQueue;
|
||||||
|
|
||||||
public class FennecNativeElement implements Element {
|
public class FennecNativeElement implements Element {
|
||||||
private final Activity mActivity;
|
private final Activity mActivity;
|
||||||
private Integer id;
|
private Integer mId;
|
||||||
private Solo robocop;
|
private Solo mSolo;
|
||||||
|
|
||||||
public FennecNativeElement(Integer id, Activity activity, Solo solo){
|
public FennecNativeElement(Integer id, Activity activity, Solo solo) {
|
||||||
this.id = id;
|
mId = id;
|
||||||
mActivity = activity;
|
mActivity = activity;
|
||||||
robocop = solo;
|
mSolo = solo;
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void click() {
|
|
||||||
final SynchronousQueue syncQueue = new SynchronousQueue();
|
|
||||||
mActivity.runOnUiThread(
|
|
||||||
new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
View view = (View)mActivity.findViewById(id);
|
|
||||||
if(view != null) {
|
|
||||||
if (!view.performClick()) {
|
|
||||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_WARN,
|
|
||||||
"Robocop called click on an element with no listener");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new RoboCopException("click: unable to find view "+id);
|
|
||||||
}
|
|
||||||
syncQueue.offer(new Object());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
syncQueue.take();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private Object text;
|
public Integer getId() {
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getText() {
|
public void click() {
|
||||||
final SynchronousQueue syncQueue = new SynchronousQueue();
|
final SynchronousQueue syncQueue = new SynchronousQueue();
|
||||||
mActivity.runOnUiThread(
|
mActivity.runOnUiThread(
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
View v = mActivity.findViewById(id);
|
View view = (View)mActivity.findViewById(mId);
|
||||||
if(v instanceof EditText) {
|
if(view != null) {
|
||||||
EditText et = (EditText)v;
|
if (!view.performClick()) {
|
||||||
text = et.getEditableText();
|
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_WARN,
|
||||||
}else if(v instanceof TextSwitcher) {
|
"Robocop called click on an element with no listener");
|
||||||
TextSwitcher ts = (TextSwitcher)v;
|
}
|
||||||
ts.getNextView();
|
} else {
|
||||||
text = ((TextView)ts.getCurrentView()).getText();
|
throw new RoboCopException("click: unable to find view "+mId);
|
||||||
}else if(v instanceof ViewGroup) {
|
}
|
||||||
ViewGroup vg = (ViewGroup)v;
|
syncQueue.offer(new Object());
|
||||||
for(int i = 0; i < vg.getChildCount(); i++) {
|
|
||||||
if(vg.getChildAt(i) instanceof TextView) {
|
|
||||||
text = ((TextView)vg.getChildAt(i)).getText();
|
|
||||||
}
|
}
|
||||||
} //end of for
|
});
|
||||||
} else if(v instanceof TextView) {
|
try {
|
||||||
text = ((TextView)v).getText();
|
syncQueue.take();
|
||||||
} else if(v == null) {
|
} catch (InterruptedException e) {
|
||||||
throw new RoboCopException("getText: unable to find view "+id);
|
e.printStackTrace();
|
||||||
} else {
|
}
|
||||||
throw new RoboCopException("getText: unhandled type for view "+id);
|
|
||||||
}
|
|
||||||
syncQueue.offer(new Object());
|
|
||||||
} // end of run() method definition
|
|
||||||
} // end of anonymous Runnable object instantiation
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
//Wait for the UiThread code to finish running
|
|
||||||
syncQueue.take();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
if(text == null) {
|
|
||||||
throw new RoboCopException("getText: Text is null for view "+id);
|
|
||||||
}
|
|
||||||
return text.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean displayed;
|
private Object mText;
|
||||||
|
|
||||||
public boolean isDisplayed() {
|
public String getText() {
|
||||||
final SynchronousQueue syncQueue = new SynchronousQueue();
|
final SynchronousQueue syncQueue = new SynchronousQueue();
|
||||||
displayed = false;
|
mActivity.runOnUiThread(
|
||||||
mActivity.runOnUiThread(
|
new Runnable() {
|
||||||
new Runnable() {
|
public void run() {
|
||||||
public void run() {
|
View v = mActivity.findViewById(mId);
|
||||||
View view = (View)mActivity.findViewById(id);
|
if (v instanceof EditText) {
|
||||||
if(view != null) {
|
EditText et = (EditText)v;
|
||||||
displayed = true;
|
mText = et.getEditableText();
|
||||||
}
|
} else if (v instanceof TextSwitcher) {
|
||||||
syncQueue.offer(new Object());
|
TextSwitcher ts = (TextSwitcher)v;
|
||||||
}
|
ts.getNextView();
|
||||||
});
|
mText = ((TextView)ts.getCurrentView()).getText();
|
||||||
try {
|
} else if (v instanceof ViewGroup) {
|
||||||
syncQueue.take();
|
ViewGroup vg = (ViewGroup)v;
|
||||||
} catch (InterruptedException e) {
|
for (int i = 0; i < vg.getChildCount(); i++) {
|
||||||
e.printStackTrace();
|
if (vg.getChildAt(i) instanceof TextView) {
|
||||||
|
mText = ((TextView)vg.getChildAt(i)).getText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (v instanceof TextView) {
|
||||||
|
mText = ((TextView)v).getText();
|
||||||
|
} else if (v == null) {
|
||||||
|
throw new RoboCopException("getText: unable to find view "+mId);
|
||||||
|
} else {
|
||||||
|
throw new RoboCopException("getText: unhandled type for view "+mId);
|
||||||
|
}
|
||||||
|
syncQueue.offer(new Object());
|
||||||
|
} // end of run() method definition
|
||||||
|
} // end of anonymous Runnable object instantiation
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
// Wait for the UiThread code to finish running
|
||||||
|
syncQueue.take();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (mText == null) {
|
||||||
|
throw new RoboCopException("getText: Text is null for view "+mId);
|
||||||
|
}
|
||||||
|
return mText.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean mDisplayed;
|
||||||
|
|
||||||
|
public boolean isDisplayed() {
|
||||||
|
final SynchronousQueue syncQueue = new SynchronousQueue();
|
||||||
|
mDisplayed = false;
|
||||||
|
mActivity.runOnUiThread(
|
||||||
|
new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
View view = (View)mActivity.findViewById(mId);
|
||||||
|
if (view != null) {
|
||||||
|
mDisplayed = true;
|
||||||
|
}
|
||||||
|
syncQueue.offer(new Object());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
syncQueue.take();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return mDisplayed;
|
||||||
}
|
}
|
||||||
return displayed;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,52 +39,40 @@ package @ANDROID_PACKAGE_NAME@;
|
||||||
|
|
||||||
|
|
||||||
public class FennecTalosAssert implements Assert {
|
public class FennecTalosAssert implements Assert {
|
||||||
|
|
||||||
public FennecTalosAssert() {
|
public FennecTalosAssert() { }
|
||||||
}
|
|
||||||
|
|
||||||
// Write information to a logfile and logcat
|
/**
|
||||||
public void dumpLog(String message)
|
* Write information to a logfile and logcat
|
||||||
{
|
*/
|
||||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
|
public void dumpLog(String message) {
|
||||||
}
|
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
|
||||||
|
}
|
||||||
|
|
||||||
// Set the filename used for dumpLog.
|
/**
|
||||||
public void setLogFile(String filename)
|
* Set the filename used for dumpLog.
|
||||||
{
|
*/
|
||||||
FennecNativeDriver.setLogFile(filename);
|
public void setLogFile(String filename) {
|
||||||
}
|
FennecNativeDriver.setLogFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
public void setTestName(String testName)
|
public void setTestName(String testName) { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public void finalize() { }
|
||||||
|
|
||||||
public void finalize()
|
public void ok(boolean condition, String name, String diag) { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ok(boolean condition, String name, String diag) {
|
public void is(Object a, Object b, String name) { }
|
||||||
}
|
|
||||||
|
public void isnot(Object a, Object b, String name) { }
|
||||||
|
|
||||||
public void is(Object a, Object b, String name) {
|
public void ispixel(int actual, int r, int g, int b, String name) { }
|
||||||
}
|
|
||||||
|
|
||||||
public void isnot(Object a, Object b, String name) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ispixel(int actual, int r, int g, int b, String name) {
|
public void todo(boolean condition, String name, String diag) { }
|
||||||
}
|
|
||||||
|
|
||||||
public void todo(boolean condition, String name, String diag) {
|
public void todo_is(Object a, Object b, String name) { }
|
||||||
}
|
|
||||||
|
public void todo_isnot(Object a, Object b, String name) { }
|
||||||
|
|
||||||
public void todo_is(Object a, Object b, String name) {
|
public void info(String name, String message) { }
|
||||||
}
|
|
||||||
|
|
||||||
public void todo_isnot(Object a, Object b, String name) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void info(String name, String message) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,20 +40,20 @@
|
||||||
package @ANDROID_PACKAGE_NAME@;
|
package @ANDROID_PACKAGE_NAME@;
|
||||||
|
|
||||||
public class RoboCopException extends RuntimeException {
|
public class RoboCopException extends RuntimeException {
|
||||||
|
|
||||||
public RoboCopException(){
|
public RoboCopException() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RoboCopException(String message){
|
public RoboCopException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RoboCopException(Throwable cause){
|
public RoboCopException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RoboCopException(String message, Throwable cause){
|
public RoboCopException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,18 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
# The directories end up in the debug info, so the easy way of getting
|
||||||
|
# a reproducible build is to run it in a know absolute directory.
|
||||||
|
# We use a directory in /builds/slave because the mozilla infrastructure
|
||||||
|
# cleans it up automatically.
|
||||||
|
base_dir = "/builds/slave/moz-toolschain"
|
||||||
|
|
||||||
|
source_dir = base_dir + "/src"
|
||||||
|
build_dir = base_dir + "/build"
|
||||||
|
aux_inst_dir = build_dir + '/aux_inst'
|
||||||
|
old_make = aux_inst_dir + '/bin/make'
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
|
||||||
import urllib
|
import urllib
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
@ -33,17 +46,21 @@ def patch(patch, plevel, srcdir):
|
||||||
check_run(['patch', '-d', srcdir, '-p%s' % plevel, '-i', patch, '--fuzz=0',
|
check_run(['patch', '-d', srcdir, '-p%s' % plevel, '-i', patch, '--fuzz=0',
|
||||||
'-s'])
|
'-s'])
|
||||||
|
|
||||||
def build_package(package_source_dir, package_build_dir, configure_args):
|
def build_package(package_source_dir, package_build_dir, configure_args,
|
||||||
|
make = old_make):
|
||||||
os.mkdir(package_build_dir)
|
os.mkdir(package_build_dir)
|
||||||
run_in(package_build_dir,
|
run_in(package_build_dir,
|
||||||
["%s/configure" % package_source_dir] + configure_args)
|
["%s/configure" % package_source_dir] + configure_args)
|
||||||
run_in(package_build_dir, ["make", "-j8"])
|
run_in(package_build_dir, [make, "-j8"])
|
||||||
run_in(package_build_dir, ["make", "install"])
|
run_in(package_build_dir, [make, "install"])
|
||||||
|
|
||||||
def build_tar(base_dir, tar_inst_dir):
|
def build_aux_tools(base_dir):
|
||||||
|
make_build_dir = base_dir + '/make_build'
|
||||||
|
build_package(make_source_dir, make_build_dir,
|
||||||
|
["--prefix=%s" % aux_inst_dir], "make")
|
||||||
tar_build_dir = base_dir + '/tar_build'
|
tar_build_dir = base_dir + '/tar_build'
|
||||||
build_package(tar_source_dir, tar_build_dir,
|
build_package(tar_source_dir, tar_build_dir,
|
||||||
["--prefix=%s" % tar_inst_dir])
|
["--prefix=%s" % aux_inst_dir])
|
||||||
|
|
||||||
def with_env(env, f):
|
def with_env(env, f):
|
||||||
old_env = os.environ.copy()
|
old_env = os.environ.copy()
|
||||||
|
@ -133,21 +150,13 @@ def build_tar_package(tar, name, base, directory):
|
||||||
|
|
||||||
##############################################
|
##############################################
|
||||||
|
|
||||||
# The directories end up in the debug info, so the easy way of getting
|
|
||||||
# a reproducible build is to run it in a know absolute directory.
|
|
||||||
# We use a directory in /builds/slave because the mozilla infrastructure
|
|
||||||
# cleans it up automatically.
|
|
||||||
base_dir = "/builds/slave/moz-toolschain"
|
|
||||||
|
|
||||||
source_dir = base_dir + "/src"
|
|
||||||
build_dir = base_dir + "/build"
|
|
||||||
|
|
||||||
def build_source_dir(prefix, version):
|
def build_source_dir(prefix, version):
|
||||||
return source_dir + '/' + prefix + version
|
return source_dir + '/' + prefix + version
|
||||||
|
|
||||||
binutils_version = "2.21.1"
|
binutils_version = "2.21.1"
|
||||||
glibc_version = "2.12.2" #FIXME: should probably use 2.5.1
|
glibc_version = "2.5.1"
|
||||||
tar_version = "1.26"
|
tar_version = "1.26"
|
||||||
|
make_version = "3.81"
|
||||||
gcc_version = "4.5.2"
|
gcc_version = "4.5.2"
|
||||||
mpfr_version = "2.4.2"
|
mpfr_version = "2.4.2"
|
||||||
gmp_version = "5.0.1"
|
gmp_version = "5.0.1"
|
||||||
|
@ -159,6 +168,8 @@ glibc_source_uri = "http://ftp.gnu.org/gnu/glibc/glibc-%s.tar.bz2" % \
|
||||||
glibc_version
|
glibc_version
|
||||||
tar_source_uri = "http://ftp.gnu.org/gnu/tar/tar-%s.tar.bz2" % \
|
tar_source_uri = "http://ftp.gnu.org/gnu/tar/tar-%s.tar.bz2" % \
|
||||||
tar_version
|
tar_version
|
||||||
|
make_source_uri = "http://ftp.gnu.org/gnu/make/make-%s.tar.bz2" % \
|
||||||
|
make_version
|
||||||
gcc_source_uri = "http://ftp.gnu.org/gnu/gcc/gcc-%s/gcc-%s.tar.bz2" % \
|
gcc_source_uri = "http://ftp.gnu.org/gnu/gcc/gcc-%s/gcc-%s.tar.bz2" % \
|
||||||
(gcc_version, gcc_version)
|
(gcc_version, gcc_version)
|
||||||
mpfr_source_uri = "http://www.mpfr.org/mpfr-%s/mpfr-%s.tar.bz2" % \
|
mpfr_source_uri = "http://www.mpfr.org/mpfr-%s/mpfr-%s.tar.bz2" % \
|
||||||
|
@ -170,6 +181,7 @@ mpc_source_uri = "http://www.multiprecision.org/mpc/download/mpc-%s.tar.gz" % \
|
||||||
binutils_source_tar = download_uri(binutils_source_uri)
|
binutils_source_tar = download_uri(binutils_source_uri)
|
||||||
glibc_source_tar = download_uri(glibc_source_uri)
|
glibc_source_tar = download_uri(glibc_source_uri)
|
||||||
tar_source_tar = download_uri(tar_source_uri)
|
tar_source_tar = download_uri(tar_source_uri)
|
||||||
|
make_source_tar = download_uri(make_source_uri)
|
||||||
mpc_source_tar = download_uri(mpc_source_uri)
|
mpc_source_tar = download_uri(mpc_source_uri)
|
||||||
mpfr_source_tar = download_uri(mpfr_source_uri)
|
mpfr_source_tar = download_uri(mpfr_source_uri)
|
||||||
gmp_source_tar = download_uri(gmp_source_uri)
|
gmp_source_tar = download_uri(gmp_source_uri)
|
||||||
|
@ -178,6 +190,7 @@ gcc_source_tar = download_uri(gcc_source_uri)
|
||||||
binutils_source_dir = build_source_dir('binutils-', binutils_version)
|
binutils_source_dir = build_source_dir('binutils-', binutils_version)
|
||||||
glibc_source_dir = build_source_dir('glibc-', glibc_version)
|
glibc_source_dir = build_source_dir('glibc-', glibc_version)
|
||||||
tar_source_dir = build_source_dir('tar-', tar_version)
|
tar_source_dir = build_source_dir('tar-', tar_version)
|
||||||
|
make_source_dir = build_source_dir('make-', make_version)
|
||||||
mpc_source_dir = build_source_dir('mpc-', mpc_version)
|
mpc_source_dir = build_source_dir('mpc-', mpc_version)
|
||||||
mpfr_source_dir = build_source_dir('mpfr-', mpfr_version)
|
mpfr_source_dir = build_source_dir('mpfr-', mpfr_version)
|
||||||
gmp_source_dir = build_source_dir('gmp-', gmp_version)
|
gmp_source_dir = build_source_dir('gmp-', gmp_version)
|
||||||
|
@ -191,6 +204,7 @@ if not os.path.exists(source_dir):
|
||||||
patch('glibc-deterministic.patch', 1, glibc_source_dir)
|
patch('glibc-deterministic.patch', 1, glibc_source_dir)
|
||||||
run_in(glibc_source_dir, ["autoconf"])
|
run_in(glibc_source_dir, ["autoconf"])
|
||||||
extract(tar_source_tar, source_dir)
|
extract(tar_source_tar, source_dir)
|
||||||
|
extract(make_source_tar, source_dir)
|
||||||
extract(mpc_source_tar, source_dir)
|
extract(mpc_source_tar, source_dir)
|
||||||
extract(mpfr_source_tar, source_dir)
|
extract(mpfr_source_tar, source_dir)
|
||||||
extract(gmp_source_tar, source_dir)
|
extract(gmp_source_tar, source_dir)
|
||||||
|
@ -203,19 +217,18 @@ if os.path.exists(build_dir):
|
||||||
shutil.rmtree(build_dir)
|
shutil.rmtree(build_dir)
|
||||||
os.makedirs(build_dir)
|
os.makedirs(build_dir)
|
||||||
|
|
||||||
tar_inst_dir = build_dir + '/tar_inst'
|
build_aux_tools(build_dir)
|
||||||
build_tar(build_dir, tar_inst_dir)
|
|
||||||
|
|
||||||
stage1_dir = build_dir + '/stage1'
|
stage1_dir = build_dir + '/stage1'
|
||||||
build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True)
|
build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True)
|
||||||
|
|
||||||
stage1_tool_inst_dir = stage1_dir + '/inst'
|
stage1_tool_inst_dir = stage1_dir + '/inst'
|
||||||
stage2_dir = build_dir + '/stage2'
|
stage2_dir = build_dir + '/stage2'
|
||||||
build_one_stage({"CC" : stage1_tool_inst_dir + "/bin/gcc",
|
build_one_stage({"CC" : stage1_tool_inst_dir + "/bin/gcc -fgnu89-inline",
|
||||||
"CXX" : stage1_tool_inst_dir + "/bin/g++",
|
"CXX" : stage1_tool_inst_dir + "/bin/g++",
|
||||||
"AR" : stage1_tool_inst_dir + "/bin/ar",
|
"AR" : stage1_tool_inst_dir + "/bin/ar",
|
||||||
"RANLIB" : "true" },
|
"RANLIB" : "true" },
|
||||||
stage2_dir, False)
|
stage2_dir, False)
|
||||||
|
|
||||||
build_tar_package(tar_inst_dir + "/bin/tar",
|
build_tar_package(aux_inst_dir + "/bin/tar",
|
||||||
"toolchain.tar", stage2_dir, "inst")
|
"toolchain.tar", stage2_dir, "inst")
|
||||||
|
|
|
@ -1,7 +1,22 @@
|
||||||
diff -ru a/configure.in b/configure.in
|
diff -ru a/configure.in b/configure.in
|
||||||
--- a/configure.in 2011-01-17 23:34:07.000000000 -0500
|
--- a/configure.in 2011-01-17 23:34:07.000000000 -0500
|
||||||
+++ b/configure.in 2012-01-25 20:40:27.919485606 -0500
|
+++ b/configure.in 2012-01-25 20:40:27.919485606 -0500
|
||||||
@@ -2230,6 +2230,7 @@
|
@@ -841,14 +841,6 @@
|
||||||
|
LIBC_PROG_BINUTILS
|
||||||
|
AC_SUBST(MIG)dnl Needed by sysdeps/mach/configure.in
|
||||||
|
|
||||||
|
-# Accept binutils 2.13 or newer.
|
||||||
|
-AC_CHECK_PROG_VER(AS, $AS, --version,
|
||||||
|
- [GNU assembler.* \([0-9]*\.[0-9.]*\)],
|
||||||
|
- [2.1[3-9]*], AS=: critic_missing="$critic_missing as")
|
||||||
|
-AC_CHECK_PROG_VER(LD, $LD, --version,
|
||||||
|
- [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)],
|
||||||
|
- [2.1[3-9]*], LD=: critic_missing="$critic_missing ld")
|
||||||
|
-
|
||||||
|
# We need the physical current working directory. We cannot use the
|
||||||
|
# "pwd -P" shell builtin since that's not portable. Instead we try to
|
||||||
|
# find a pwd binary. Note that assigning to the PWD environment
|
||||||
|
@@ -2175,6 +2167,7 @@
|
||||||
fi
|
fi
|
||||||
AC_SUBST(old_glibc_headers)
|
AC_SUBST(old_glibc_headers)
|
||||||
|
|
||||||
|
@ -12,7 +27,7 @@ diff -ru a/configure.in b/configure.in
|
||||||
diff -ru a/csu/Makefile b/csu/Makefile
|
diff -ru a/csu/Makefile b/csu/Makefile
|
||||||
--- a/csu/Makefile 2011-01-17 23:34:07.000000000 -0500
|
--- a/csu/Makefile 2011-01-17 23:34:07.000000000 -0500
|
||||||
+++ b/csu/Makefile 2012-01-23 13:58:28.957792633 -0500
|
+++ b/csu/Makefile 2012-01-23 13:58:28.957792633 -0500
|
||||||
@@ -234,8 +234,7 @@
|
@@ -223,8 +223,7 @@
|
||||||
if [ -z "$$os" ]; then \
|
if [ -z "$$os" ]; then \
|
||||||
os=Linux; \
|
os=Linux; \
|
||||||
fi; \
|
fi; \
|
||||||
|
@ -22,10 +37,58 @@ diff -ru a/csu/Makefile b/csu/Makefile
|
||||||
*) ;; \
|
*) ;; \
|
||||||
esac; \
|
esac; \
|
||||||
files="$(all-Banner-files)"; \
|
files="$(all-Banner-files)"; \
|
||||||
|
diff -ru a/elf/Makefile b/elf/Makefile
|
||||||
|
--- a/elf/Makefile 2008-10-31 16:35:11.000000000 -0400
|
||||||
|
+++ b/elf/Makefile 2012-02-16 12:20:00.038593752 -0500
|
||||||
|
@@ -295,18 +295,11 @@
|
||||||
|
z-now-yes = -Wl,-z,now
|
||||||
|
|
||||||
|
$(objpfx)ld.so: $(objpfx)librtld.os $(ld-map)
|
||||||
|
- @rm -f $@.lds
|
||||||
|
- $(LINK.o) -nostdlib -nostartfiles -shared $(z-now-$(bind-now)) \
|
||||||
|
- $(LDFLAGS-rtld) -Wl,-z,defs -Wl,--verbose 2>&1 | \
|
||||||
|
- LC_ALL=C \
|
||||||
|
- sed -e '/^=========/,/^=========/!d;/^=========/d' \
|
||||||
|
- -e 's/\. = 0 + SIZEOF_HEADERS;/& _begin = . - SIZEOF_HEADERS;/' \
|
||||||
|
- > $@.lds
|
||||||
|
$(LINK.o) -nostdlib -nostartfiles -shared -o $@ \
|
||||||
|
$(LDFLAGS-rtld) -Wl,-z,defs $(z-now-$(bind-now)) \
|
||||||
|
$(filter-out $(map-file),$^) $(load-map-file) \
|
||||||
|
- -Wl,-soname=$(rtld-installed-name) -T $@.lds
|
||||||
|
- rm -f $@.lds
|
||||||
|
+ -Wl,-soname=$(rtld-installed-name) \
|
||||||
|
+ -Wl,-defsym=_begin=0
|
||||||
|
|
||||||
|
# interp.c exists just to get this string into the libraries.
|
||||||
|
CFLAGS-interp.c = -D'RUNTIME_LINKER="$(slibdir)/$(rtld-installed-name)"' \
|
||||||
|
diff -ru a/localedata/Makefile b/localedata/Makefile
|
||||||
|
--- a/localedata/Makefile 2006-04-26 01:14:03.000000000 -0400
|
||||||
|
+++ b/localedata/Makefile 2012-02-17 10:31:24.592345047 -0500
|
||||||
|
@@ -113,7 +113,7 @@
|
||||||
|
$(make-target-directory)
|
||||||
|
rm -f $(@:.gz=) $@
|
||||||
|
$(INSTALL_DATA) $< $(@:.gz=)
|
||||||
|
- gzip -9 $(@:.gz=)
|
||||||
|
+ gzip -9n $(@:.gz=)
|
||||||
|
|
||||||
|
# Install the locale source files in the appropriate directory.
|
||||||
|
$(inst_i18ndir)/locales/%: locales/% $(+force); $(do-install)
|
||||||
|
diff -ru a/Makeconfig b/Makeconfig
|
||||||
|
--- a/Makeconfig 2006-07-10 17:42:27.000000000 -0400
|
||||||
|
+++ b/Makeconfig 2012-02-17 08:28:31.859584817 -0500
|
||||||
|
@@ -674,7 +674,7 @@
|
||||||
|
$(foreach lib,$(libof-$(basename $(@F))) \
|
||||||
|
$(libof-$(<F)) $(libof-$(@F)),$(CPPFLAGS-$(lib))) \
|
||||||
|
$(CPPFLAGS-$(<F)) $(CPPFLAGS-$(@F)) $(CPPFLAGS-$(basename $(@F)))
|
||||||
|
-override CFLAGS = -std=gnu99 \
|
||||||
|
+override CFLAGS = -std=gnu99 -fgnu89-inline \
|
||||||
|
$(filter-out %frame-pointer,$(+cflags)) $(+gccwarn-c) \
|
||||||
|
$(sysdep-CFLAGS) $(CFLAGS-$(suffix $@)) $(CFLAGS-$(<F)) \
|
||||||
|
$(CFLAGS-$(@F))
|
||||||
diff -ru a/Makerules b/Makerules
|
diff -ru a/Makerules b/Makerules
|
||||||
--- a/Makerules 2011-01-17 23:34:07.000000000 -0500
|
--- a/Makerules 2011-01-17 23:34:07.000000000 -0500
|
||||||
+++ b/Makerules 2012-01-30 08:47:56.565068903 -0500
|
+++ b/Makerules 2012-01-30 08:47:56.565068903 -0500
|
||||||
@@ -992,9 +992,9 @@
|
@@ -977,9 +977,9 @@
|
||||||
echo ' Use the shared library, but some functions are only in';\
|
echo ' Use the shared library, but some functions are only in';\
|
||||||
echo ' the static library, so try that secondarily. */';\
|
echo ' the static library, so try that secondarily. */';\
|
||||||
cat $<; \
|
cat $<; \
|
||||||
|
|
|
@ -57,7 +57,6 @@ MOZ_PROFILE_MIGRATOR = @MOZ_PROFILE_MIGRATOR@
|
||||||
MOZ_EXTENSION_MANAGER = @MOZ_EXTENSION_MANAGER@
|
MOZ_EXTENSION_MANAGER = @MOZ_EXTENSION_MANAGER@
|
||||||
MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@
|
MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@
|
||||||
MOZ_APP_VERSION = @MOZ_APP_VERSION@
|
MOZ_APP_VERSION = @MOZ_APP_VERSION@
|
||||||
MOZ_UA_BUILDID = @MOZ_UA_BUILDID@
|
|
||||||
MOZ_MACBUNDLE_NAME = @MOZ_MACBUNDLE_NAME@
|
MOZ_MACBUNDLE_NAME = @MOZ_MACBUNDLE_NAME@
|
||||||
MOZ_APP_STATIC_INI = @MOZ_APP_STATIC_INI@
|
MOZ_APP_STATIC_INI = @MOZ_APP_STATIC_INI@
|
||||||
|
|
||||||
|
@ -181,6 +180,7 @@ LIBJPEG_TURBO_AS = @LIBJPEG_TURBO_AS@
|
||||||
LIBJPEG_TURBO_ASFLAGS = @LIBJPEG_TURBO_ASFLAGS@
|
LIBJPEG_TURBO_ASFLAGS = @LIBJPEG_TURBO_ASFLAGS@
|
||||||
LIBJPEG_TURBO_X86_ASM = @LIBJPEG_TURBO_X86_ASM@
|
LIBJPEG_TURBO_X86_ASM = @LIBJPEG_TURBO_X86_ASM@
|
||||||
LIBJPEG_TURBO_X64_ASM = @LIBJPEG_TURBO_X64_ASM@
|
LIBJPEG_TURBO_X64_ASM = @LIBJPEG_TURBO_X64_ASM@
|
||||||
|
LIBJPEG_TURBO_ARM_ASM = @LIBJPEG_TURBO_ARM_ASM@
|
||||||
NS_PRINTING = @NS_PRINTING@
|
NS_PRINTING = @NS_PRINTING@
|
||||||
MOZ_PDF_PRINTING = @MOZ_PDF_PRINTING@
|
MOZ_PDF_PRINTING = @MOZ_PDF_PRINTING@
|
||||||
MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
|
MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#
|
#
|
||||||
# ***** END LICENSE BLOCK *****
|
# ***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
import sys, os, subprocess, struct
|
import sys, os, subprocess, struct, re
|
||||||
|
|
||||||
local_file_header = [
|
local_file_header = [
|
||||||
("signature", "uint32"),
|
("signature", "uint32"),
|
||||||
|
@ -329,10 +329,12 @@ if len(sys.argv) != 5:
|
||||||
print "Usage: --optimize|--deoptimize %s JAR_LOG_DIR IN_JAR_DIR OUT_JAR_DIR" % sys.argv[0]
|
print "Usage: --optimize|--deoptimize %s JAR_LOG_DIR IN_JAR_DIR OUT_JAR_DIR" % sys.argv[0]
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
jar_regex = re.compile("\\.jar?$")
|
||||||
|
|
||||||
def optimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR):
|
def optimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR):
|
||||||
ls = os.listdir(IN_JAR_DIR)
|
ls = os.listdir(IN_JAR_DIR)
|
||||||
for jarfile in ls:
|
for jarfile in ls:
|
||||||
if not jarfile.endswith(".jar"):
|
if not re.search(jar_regex, jarfile):
|
||||||
continue
|
continue
|
||||||
injarfile = os.path.join(IN_JAR_DIR, jarfile)
|
injarfile = os.path.join(IN_JAR_DIR, jarfile)
|
||||||
outjarfile = os.path.join(OUT_JAR_DIR, jarfile)
|
outjarfile = os.path.join(OUT_JAR_DIR, jarfile)
|
||||||
|
@ -347,7 +349,7 @@ def deoptimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR):
|
||||||
|
|
||||||
ls = os.listdir(IN_JAR_DIR)
|
ls = os.listdir(IN_JAR_DIR)
|
||||||
for jarfile in ls:
|
for jarfile in ls:
|
||||||
if not jarfile.endswith(".jar"):
|
if not re.search(jar_regex, jarfile):
|
||||||
continue
|
continue
|
||||||
injarfile = os.path.join(IN_JAR_DIR, jarfile)
|
injarfile = os.path.join(IN_JAR_DIR, jarfile)
|
||||||
outjarfile = os.path.join(OUT_JAR_DIR, jarfile)
|
outjarfile = os.path.join(OUT_JAR_DIR, jarfile)
|
||||||
|
|
95
configure.in
95
configure.in
|
@ -225,7 +225,14 @@ if test -n "$L10NBASEDIR"; then
|
||||||
if test "$L10NBASEDIR" = "yes" -o "$L10NBASEDIR" = "no"; then
|
if test "$L10NBASEDIR" = "yes" -o "$L10NBASEDIR" = "no"; then
|
||||||
AC_MSG_ERROR([--with-l10n-base must specify a path])
|
AC_MSG_ERROR([--with-l10n-base must specify a path])
|
||||||
elif test -d "$L10NBASEDIR"; then
|
elif test -d "$L10NBASEDIR"; then
|
||||||
L10NBASEDIR=`cd "$L10NBASEDIR" && pwd`
|
case "$host_os" in
|
||||||
|
mingw*)
|
||||||
|
L10NBASEDIR=`cd "$L10NBASEDIR" && pwd -W`
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
L10NBASEDIR=`cd "$L10NBASEDIR" && pwd`
|
||||||
|
;;
|
||||||
|
esac
|
||||||
else
|
else
|
||||||
AC_MSG_ERROR([Invalid value --with-l10n-base, $L10NBASEDIR doesn't exist])
|
AC_MSG_ERROR([Invalid value --with-l10n-base, $L10NBASEDIR doesn't exist])
|
||||||
fi
|
fi
|
||||||
|
@ -3336,6 +3343,7 @@ AC_SUBST(WRAP_SYSTEM_INCLUDES)
|
||||||
AC_SUBST(VISIBILITY_FLAGS)
|
AC_SUBST(VISIBILITY_FLAGS)
|
||||||
|
|
||||||
MOZ_GCC_PR49911
|
MOZ_GCC_PR49911
|
||||||
|
MOZ_COMPILER_OPTS
|
||||||
|
|
||||||
dnl Check for __force_align_arg_pointer__ for SSE2 on gcc
|
dnl Check for __force_align_arg_pointer__ for SSE2 on gcc
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
|
@ -4084,6 +4092,56 @@ if test "$ac_cv_thread_keyword" = yes -a "$MOZ_LINKER" != 1; then
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dnl Using the custom linker on ARMv6 requires 16k alignment of ELF segments.
|
||||||
|
if test -n "$MOZ_LINKER"; then
|
||||||
|
if test "$CPU_ARCH" = arm; then
|
||||||
|
dnl Determine the target ARM architecture (5 for ARMv5, v5T, v5E, etc.; 6 for ARMv6, v6K, etc.)
|
||||||
|
ARM_ARCH=`${CC-cc} ${CFLAGS} -dM -E - < /dev/null | sed -n 's/.*__ARM_ARCH_\([[0-9]]*\).*/\1/p'`
|
||||||
|
dnl When building for < ARMv7, we need to ensure 16k alignment of ELF segments
|
||||||
|
if test -n "$ARM_ARCH" && test "$ARM_ARCH" -lt 7; then
|
||||||
|
LDFLAGS="$LDFLAGS -Wl,-z,max-page-size=0x4000"
|
||||||
|
_SUBDIR_LDFLAGS="$_SUBDIR_LDFLAGS -Wl,-z,max-page-size=0x4000"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl The custom linker doesn't support text relocations, but NDK >= r6b
|
||||||
|
dnl creates some (http://code.google.com/p/android/issues/detail?id=23203)
|
||||||
|
dnl We however want to avoid these text relocations, and this can be done
|
||||||
|
dnl by making gcc not link crtbegin and crtend. In the broken NDKs, crtend
|
||||||
|
dnl doesn't contain anything at all, beside placeholders for some sections,
|
||||||
|
dnl and crtbegin only contains a finalizer function that calls
|
||||||
|
dnl __cxa_finalize. The custom linker actually takes care of calling
|
||||||
|
dnl __cxa_finalize when the library doesn't call it itself, which makes it
|
||||||
|
dnl safe not to link crtbegin. Besides, previous versions of the NDK didn't
|
||||||
|
dnl link crtbegin and crtend at all.
|
||||||
|
if test -n "$MOZ_LINKER" -a -z "$MOZ_OLD_LINKER" -a "$OS_TARGET" = "Android"; then
|
||||||
|
AC_CACHE_CHECK([whether the CRT objects have text relocations],
|
||||||
|
ac_cv_crt_has_text_relocations,
|
||||||
|
[echo 'int foo() { return 0; }' > conftest.cpp
|
||||||
|
if AC_TRY_COMMAND(${CXX-g++} -o conftest${DLL_SUFFIX} $CXXFLAGS $DSO_LDOPTS $LDFLAGS conftest.cpp $LIBS 1>&5) &&
|
||||||
|
test -s conftest${DLL_SUFFIX}; then
|
||||||
|
if readelf -d conftest${DLL_SUFFIX} | grep TEXTREL > /dev/null; then
|
||||||
|
ac_cv_crt_has_text_relocations=yes
|
||||||
|
else
|
||||||
|
ac_cv_crt_has_text_relocations=no
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
AC_ERROR([couldn't compile a simple C file])
|
||||||
|
fi
|
||||||
|
rm -rf conftest*])
|
||||||
|
if test "$ac_cv_crt_has_text_relocations" = yes; then
|
||||||
|
dnl While we want libraries to skip the CRT files, we don't want
|
||||||
|
dnl executables to be treated the same way. We thus set the flag
|
||||||
|
dnl in DSO_LDOPTS and not LDFLAGS. However, to pass it to nspr,
|
||||||
|
dnl we need to use LDFLAGS because nspr doesn't inherit DSO_LDOPTS.
|
||||||
|
dnl Using LDFLAGS in nspr is safe, since we only really build
|
||||||
|
dnl libraries there.
|
||||||
|
DSO_LDOPTS="$DSO_LDOPTS -nostartfiles"
|
||||||
|
NSPR_LDFLAGS=-nostartfiles
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
dnl Check for the existence of various allocation headers/functions
|
dnl Check for the existence of various allocation headers/functions
|
||||||
|
|
||||||
MALLOC_H=
|
MALLOC_H=
|
||||||
|
@ -4605,6 +4663,7 @@ LIBJPEG_TURBO_AS=
|
||||||
LIBJPEG_TURBO_ASFLAGS=
|
LIBJPEG_TURBO_ASFLAGS=
|
||||||
LIBJPEG_TURBO_X86_ASM=
|
LIBJPEG_TURBO_X86_ASM=
|
||||||
LIBJPEG_TURBO_X64_ASM=
|
LIBJPEG_TURBO_X64_ASM=
|
||||||
|
LIBJPEG_TURBO_ARM_ASM=
|
||||||
MOZ_PANGO=1
|
MOZ_PANGO=1
|
||||||
MOZ_PERMISSIONS=1
|
MOZ_PERMISSIONS=1
|
||||||
MOZ_PLACES=1
|
MOZ_PLACES=1
|
||||||
|
@ -6163,38 +6222,51 @@ if test -n "$MOZ_LIBJPEG_TURBO"; then
|
||||||
LIBJPEG_TURBO_ASFLAGS="-f win64 -rnasm -pnasm -D__x86_64__ -DPIC -DWIN64 -DMSVC"
|
LIBJPEG_TURBO_ASFLAGS="-f win64 -rnasm -pnasm -D__x86_64__ -DPIC -DWIN64 -DMSVC"
|
||||||
LIBJPEG_TURBO_X64_ASM=1
|
LIBJPEG_TURBO_X64_ASM=1
|
||||||
;;
|
;;
|
||||||
|
*:arm*)
|
||||||
|
LIBJPEG_TURBO_ASFLAGS="-march=armv7-a -mfpu=neon"
|
||||||
|
LIBJPEG_TURBO_ARM_ASM=1
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl If we're on a system which supports libjpeg-turbo's asm routines and
|
dnl If we're on an x86 or x64 system which supports libjpeg-turbo's asm routines
|
||||||
dnl --disable-libjpeg-turbo wasn't passed, check for yasm, and error out if it
|
dnl and --disable-libjpeg-turbo wasn't passed, check for Yasm, and error out if
|
||||||
dnl doesn't exist or we have too old of a version.
|
dnl it doesn't exist or we have too old of a version.
|
||||||
if test -n "$LIBJPEG_TURBO_X86_ASM" -o -n "$LIBJPEG_TURBO_X64_ASM" ; then
|
if test -n "$LIBJPEG_TURBO_X86_ASM" -o -n "$LIBJPEG_TURBO_X64_ASM" ; then
|
||||||
AC_MSG_CHECKING([for YASM assembler])
|
AC_MSG_CHECKING([for Yasm assembler])
|
||||||
AC_CHECK_PROGS(LIBJPEG_TURBO_AS, yasm, "")
|
AC_CHECK_PROGS(LIBJPEG_TURBO_AS, yasm, "")
|
||||||
|
|
||||||
if test -z "$LIBJPEG_TURBO_AS" ; then
|
if test -z "$LIBJPEG_TURBO_AS" ; then
|
||||||
AC_MSG_ERROR([yasm is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you do not appear to have yasm installed. Either install it or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.])
|
AC_MSG_ERROR([Yasm is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you do not appear to have Yasm installed. Either install it or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Check that we have the right yasm version. We require 1.0.1 or newer
|
dnl Check that we have the right yasm version. We require 1.0.1 or newer
|
||||||
dnl on Linux and 1.1 or newer everywhere else.
|
dnl on Linux and 1.1 or newer everywhere else.
|
||||||
if test "$OS_ARCH" = "Linux" ; then
|
if test "$OS_ARCH" = "Linux" ; then
|
||||||
if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -eq "0" -a "$_YASM_RELEASE" -lt "1" \) ; then
|
if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -eq "0" -a "$_YASM_RELEASE" -lt "1" \) ; then
|
||||||
AC_MSG_ERROR([yasm 1.0.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.$_YASM_RELEASE. Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.])
|
AC_MSG_ERROR([Yasm 1.0.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.$_YASM_RELEASE. Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.])
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -lt "1" \) ; then
|
if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -lt "1" \) ; then
|
||||||
AC_MSG_ERROR([yasm 1.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION. Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.])
|
AC_MSG_ERROR([Yasm 1.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION. Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.])
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dnl If we're on an ARM system which supports libjpeg-turbo's asm routines and
|
||||||
|
dnl --disable-libjpeg-turbo wasn't passed, use the C compiler as the assembler.
|
||||||
|
if test -n "$LIBJPEG_TURBO_ARM_ASM" ; then
|
||||||
|
echo "Using $AS as the assembler for ARM code."
|
||||||
|
LIBJPEG_TURBO_AS=$AS
|
||||||
|
fi
|
||||||
|
|
||||||
if test -n "$LIBJPEG_TURBO_X86_ASM"; then
|
if test -n "$LIBJPEG_TURBO_X86_ASM"; then
|
||||||
AC_DEFINE(LIBJPEG_TURBO_X86_ASM)
|
AC_DEFINE(LIBJPEG_TURBO_X86_ASM)
|
||||||
elif test -n "$LIBJPEG_TURBO_X64_ASM"; then
|
elif test -n "$LIBJPEG_TURBO_X64_ASM"; then
|
||||||
AC_DEFINE(LIBJPEG_TURBO_X64_ASM)
|
AC_DEFINE(LIBJPEG_TURBO_X64_ASM)
|
||||||
|
elif test -n "$LIBJPEG_TURBO_ARM_ASM"; then
|
||||||
|
AC_DEFINE(LIBJPEG_TURBO_ARM_ASM)
|
||||||
elif test -n "$MOZ_LIBJPEG_TURBO"; then
|
elif test -n "$MOZ_LIBJPEG_TURBO"; then
|
||||||
dnl Warn if we're not building the optimized routines, even though the user
|
dnl Warn if we're not building the optimized routines, even though the user
|
||||||
dnl didn't specify --disable-libjpeg-turbo.
|
dnl didn't specify --disable-libjpeg-turbo.
|
||||||
|
@ -8565,8 +8637,6 @@ AC_SUBST(MOZ_APP_VERSION)
|
||||||
AC_DEFINE_UNQUOTED(MOZ_UA_FIREFOX_VERSION, "$FIREFOX_VERSION")
|
AC_DEFINE_UNQUOTED(MOZ_UA_FIREFOX_VERSION, "$FIREFOX_VERSION")
|
||||||
AC_DEFINE_UNQUOTED(FIREFOX_VERSION,$FIREFOX_VERSION)
|
AC_DEFINE_UNQUOTED(FIREFOX_VERSION,$FIREFOX_VERSION)
|
||||||
AC_SUBST(FIREFOX_VERSION)
|
AC_SUBST(FIREFOX_VERSION)
|
||||||
AC_DEFINE_UNQUOTED(MOZ_UA_BUILDID, "$MOZ_UA_BUILDID")
|
|
||||||
AC_SUBST(MOZ_UA_BUILDID)
|
|
||||||
|
|
||||||
# We can't use the static application.ini data when building against
|
# We can't use the static application.ini data when building against
|
||||||
# a libxul SDK.
|
# a libxul SDK.
|
||||||
|
@ -8736,6 +8806,7 @@ AC_SUBST(LIBJPEG_TURBO_AS)
|
||||||
AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
|
AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
|
||||||
AC_SUBST(LIBJPEG_TURBO_X86_ASM)
|
AC_SUBST(LIBJPEG_TURBO_X86_ASM)
|
||||||
AC_SUBST(LIBJPEG_TURBO_X64_ASM)
|
AC_SUBST(LIBJPEG_TURBO_X64_ASM)
|
||||||
|
AC_SUBST(LIBJPEG_TURBO_ARM_ASM)
|
||||||
|
|
||||||
AC_MSG_CHECKING([for posix_fallocate])
|
AC_MSG_CHECKING([for posix_fallocate])
|
||||||
AC_TRY_LINK([#define _XOPEN_SOURCE 600
|
AC_TRY_LINK([#define _XOPEN_SOURCE 600
|
||||||
|
@ -9070,7 +9141,11 @@ if test -z "$MOZ_NATIVE_NSPR"; then
|
||||||
_SAVE_CPPFLAGS="$CPPFLAGS"
|
_SAVE_CPPFLAGS="$CPPFLAGS"
|
||||||
export CPPFLAGS="-include $_topsrcdir/mozglue/linker/dladdr.h $CPPFLAGS"
|
export CPPFLAGS="-include $_topsrcdir/mozglue/linker/dladdr.h $CPPFLAGS"
|
||||||
fi
|
fi
|
||||||
|
_SAVE_LDFLAGS="$LDFLAGS"
|
||||||
|
export LDFLAGS="$LDFLAGS $NSPR_LDFLAGS"
|
||||||
AC_OUTPUT_SUBDIRS(nsprpub)
|
AC_OUTPUT_SUBDIRS(nsprpub)
|
||||||
|
unset LDFLAGS
|
||||||
|
LDFLAGS="$_SAVE_LDFLAGS"
|
||||||
if test -n "$MOZ_LINKER" -a -z "$MOZ_OLD_LINKER" -a "$ac_cv_func_dladdr" = no; then
|
if test -n "$MOZ_LINKER" -a -z "$MOZ_OLD_LINKER" -a "$ac_cv_func_dladdr" = no; then
|
||||||
unset CPPFLAGS
|
unset CPPFLAGS
|
||||||
CPPFLAGS="$_SAVE_CFLAGS"
|
CPPFLAGS="$_SAVE_CFLAGS"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
onmessage = function(event) {
|
onmessage = function(event) {
|
||||||
var blob = event.data;
|
var blob = event.data;
|
||||||
|
|
||||||
blob.mozSlice(1, 5);
|
blob.slice(1, 5);
|
||||||
|
|
||||||
postMessage("done");
|
postMessage("done");
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,9 +71,9 @@ interface nsIDOMBlob : nsISupports
|
||||||
// blob: protocol handler
|
// blob: protocol handler
|
||||||
[noscript] DOMString getInternalUrl(in nsIPrincipal principal);
|
[noscript] DOMString getInternalUrl(in nsIPrincipal principal);
|
||||||
|
|
||||||
[optional_argc] nsIDOMBlob mozSlice([optional] in long long start,
|
[optional_argc] nsIDOMBlob slice([optional] in long long start,
|
||||||
[optional] in long long end,
|
[optional] in long long end,
|
||||||
[optional] in DOMString contentType);
|
[optional] in DOMString contentType);
|
||||||
|
|
||||||
// Get internal id of stored file. Returns -1 if it is not a stored file.
|
// Get internal id of stored file. Returns -1 if it is not a stored file.
|
||||||
// Intended only for testing. It can be called on any thread.
|
// Intended only for testing. It can be called on any thread.
|
||||||
|
|
|
@ -136,6 +136,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64 SizeOf() const;
|
PRInt64 SizeOf() const;
|
||||||
|
bool HasMappedAttrs() const
|
||||||
|
{
|
||||||
|
return MappedAttrCount();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsAttrAndChildArray(const nsAttrAndChildArray& aOther) MOZ_DELETE;
|
nsAttrAndChildArray(const nsAttrAndChildArray& aOther) MOZ_DELETE;
|
||||||
|
|
|
@ -54,6 +54,8 @@
|
||||||
|
|
||||||
namespace css = mozilla::css;
|
namespace css = mozilla::css;
|
||||||
|
|
||||||
|
using mozilla::SVGAttrValueWrapper;
|
||||||
|
|
||||||
#define MISC_STR_PTR(_cont) \
|
#define MISC_STR_PTR(_cont) \
|
||||||
reinterpret_cast<void*>((_cont)->mStringBits & NS_ATTRVALUE_POINTERVALUE_MASK)
|
reinterpret_cast<void*>((_cont)->mStringBits & NS_ATTRVALUE_POINTERVALUE_MASK)
|
||||||
|
|
||||||
|
@ -76,6 +78,12 @@ nsAttrValue::nsAttrValue(const nsAString& aValue)
|
||||||
SetTo(aValue);
|
SetTo(aValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAttrValue::nsAttrValue(nsIAtom* aValue)
|
||||||
|
: mBits(0)
|
||||||
|
{
|
||||||
|
SetTo(aValue);
|
||||||
|
}
|
||||||
|
|
||||||
nsAttrValue::nsAttrValue(css::StyleRule* aValue, const nsAString* aSerialized)
|
nsAttrValue::nsAttrValue(css::StyleRule* aValue, const nsAString* aSerialized)
|
||||||
: mBits(0)
|
: mBits(0)
|
||||||
{
|
{
|
||||||
|
@ -260,7 +268,13 @@ nsAttrValue::SetTo(const nsAttrValue& aOther)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
NS_NOTREACHED("unknown type stored in MiscContainer");
|
if (IsSVGType(otherCont->mType)) {
|
||||||
|
// All SVG types are just pointers to classes and will therefore have
|
||||||
|
// the same size so it doesn't really matter which one we assign
|
||||||
|
cont->mSVGAngle = otherCont->mSVGAngle;
|
||||||
|
} else {
|
||||||
|
NS_NOTREACHED("unknown type stored in MiscContainer");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,6 +304,16 @@ nsAttrValue::SetTo(const nsAString& aValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(nsIAtom* aValue)
|
||||||
|
{
|
||||||
|
ResetIfSet();
|
||||||
|
if (aValue) {
|
||||||
|
NS_ADDREF(aValue);
|
||||||
|
SetPtrValueAndType(aValue, eAtomBase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsAttrValue::SetTo(PRInt16 aInt)
|
nsAttrValue::SetTo(PRInt16 aInt)
|
||||||
{
|
{
|
||||||
|
@ -297,6 +321,24 @@ nsAttrValue::SetTo(PRInt16 aInt)
|
||||||
SetIntValueAndType(aInt, eInteger, nsnull);
|
SetIntValueAndType(aInt, eInteger, nsnull);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(PRInt32 aInt, const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
ResetIfSet();
|
||||||
|
SetIntValueAndType(aInt, eInteger, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(double aValue, const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
if (EnsureEmptyMiscContainer()) {
|
||||||
|
MiscContainer* cont = GetMiscContainer();
|
||||||
|
cont->mDoubleValue = aValue;
|
||||||
|
cont->mType = eDoubleValue;
|
||||||
|
SetMiscAtomOrString(aSerialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsAttrValue::SetTo(css::StyleRule* aValue, const nsAString* aSerialized)
|
nsAttrValue::SetTo(css::StyleRule* aValue, const nsAString* aSerialized)
|
||||||
{
|
{
|
||||||
|
@ -331,6 +373,115 @@ nsAttrValue::SetToSerialized(const nsAttrValue& aOther)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const nsSVGAngle& aValue, const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
SetSVGType(eSVGAngle, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const nsSVGIntegerPair& aValue, const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
SetSVGType(eSVGIntegerPair, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const nsSVGLength2& aValue, const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
SetSVGType(eSVGLength, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const mozilla::SVGLengthList& aValue,
|
||||||
|
const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
// While an empty string will parse as a length list, there's no need to store
|
||||||
|
// it (and SetMiscAtomOrString will assert if we try)
|
||||||
|
if (aSerialized && aSerialized->IsEmpty()) {
|
||||||
|
aSerialized = nsnull;
|
||||||
|
}
|
||||||
|
SetSVGType(eSVGLengthList, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const mozilla::SVGNumberList& aValue,
|
||||||
|
const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
// While an empty string will parse as a number list, there's no need to store
|
||||||
|
// it (and SetMiscAtomOrString will assert if we try)
|
||||||
|
if (aSerialized && aSerialized->IsEmpty()) {
|
||||||
|
aSerialized = nsnull;
|
||||||
|
}
|
||||||
|
SetSVGType(eSVGNumberList, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const nsSVGNumberPair& aValue, const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
SetSVGType(eSVGNumberPair, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const mozilla::SVGPathData& aValue,
|
||||||
|
const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
// While an empty string will parse as path data, there's no need to store it
|
||||||
|
// (and SetMiscAtomOrString will assert if we try)
|
||||||
|
if (aSerialized && aSerialized->IsEmpty()) {
|
||||||
|
aSerialized = nsnull;
|
||||||
|
}
|
||||||
|
SetSVGType(eSVGPathData, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const mozilla::SVGPointList& aValue,
|
||||||
|
const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
// While an empty string will parse as a point list, there's no need to store
|
||||||
|
// it (and SetMiscAtomOrString will assert if we try)
|
||||||
|
if (aSerialized && aSerialized->IsEmpty()) {
|
||||||
|
aSerialized = nsnull;
|
||||||
|
}
|
||||||
|
SetSVGType(eSVGPointList, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const mozilla::SVGAnimatedPreserveAspectRatio& aValue,
|
||||||
|
const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
SetSVGType(eSVGPreserveAspectRatio, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const mozilla::SVGStringList& aValue,
|
||||||
|
const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
// While an empty string will parse as a string list, there's no need to store
|
||||||
|
// it (and SetMiscAtomOrString will assert if we try)
|
||||||
|
if (aSerialized && aSerialized->IsEmpty()) {
|
||||||
|
aSerialized = nsnull;
|
||||||
|
}
|
||||||
|
SetSVGType(eSVGStringList, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const mozilla::SVGTransformList& aValue,
|
||||||
|
const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
// While an empty string will parse as a transform list, there's no need to
|
||||||
|
// store it (and SetMiscAtomOrString will assert if we try)
|
||||||
|
if (aSerialized && aSerialized->IsEmpty()) {
|
||||||
|
aSerialized = nsnull;
|
||||||
|
}
|
||||||
|
SetSVGType(eSVGTransformList, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const nsSVGViewBox& aValue, const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
SetSVGType(eSVGViewBox, &aValue, aSerialized);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsAttrValue::SwapValueWith(nsAttrValue& aOther)
|
nsAttrValue::SwapValueWith(nsAttrValue& aOther)
|
||||||
{
|
{
|
||||||
|
@ -428,6 +579,73 @@ nsAttrValue::ToString(nsAString& aResult) const
|
||||||
aResult.AppendFloat(GetDoubleValue());
|
aResult.AppendFloat(GetDoubleValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case eSVGAngle:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGAngle, aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGIntegerPair:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGIntegerPair,
|
||||||
|
aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGLength:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGLength, aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGLengthList:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGLengthList,
|
||||||
|
aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGNumberList:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGNumberList,
|
||||||
|
aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGNumberPair:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGNumberPair,
|
||||||
|
aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGPathData:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGPathData, aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGPointList:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGPointList, aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGPreserveAspectRatio:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGPreserveAspectRatio,
|
||||||
|
aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGStringList:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGStringList,
|
||||||
|
aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGTransformList:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGTransformList,
|
||||||
|
aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eSVGViewBox:
|
||||||
|
{
|
||||||
|
SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGViewBox, aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
aResult.Truncate();
|
aResult.Truncate();
|
||||||
|
@ -614,6 +832,10 @@ nsAttrValue::HashValue() const
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
if (IsSVGType(cont->mType)) {
|
||||||
|
// All SVG types are just pointers to classes so we can treat them alike
|
||||||
|
return NS_PTR_TO_INT32(cont->mSVGAngle);
|
||||||
|
}
|
||||||
NS_NOTREACHED("unknown type stored in MiscContainer");
|
NS_NOTREACHED("unknown type stored in MiscContainer");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -706,6 +928,16 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
if (IsSVGType(thisCont->mType)) {
|
||||||
|
// Currently this method is never called for nsAttrValue objects that
|
||||||
|
// point to SVG data types.
|
||||||
|
// If that changes then we probably want to add methods to the
|
||||||
|
// corresponding SVG types to compare their base values.
|
||||||
|
// As a shortcut, however, we can begin by comparing the pointers.
|
||||||
|
NS_ABORT_IF_FALSE(false, "Comparing nsAttrValues that point to SVG "
|
||||||
|
"data");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
NS_NOTREACHED("unknown type stored in MiscContainer");
|
NS_NOTREACHED("unknown type stored in MiscContainer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1351,6 +1583,22 @@ nsAttrValue::ResetMiscAtomOrString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetSVGType(ValueType aType, const void* aValue,
|
||||||
|
const nsAString* aSerialized) {
|
||||||
|
NS_ABORT_IF_FALSE(IsSVGType(aType), "Not an SVG type");
|
||||||
|
if (EnsureEmptyMiscContainer()) {
|
||||||
|
MiscContainer* cont = GetMiscContainer();
|
||||||
|
// All SVG types are just pointers to classes so just setting any of them
|
||||||
|
// will do. We'll lose type-safety but the signature of the calling
|
||||||
|
// function should ensure we don't get anything unexpected, and once we
|
||||||
|
// stick aValue in a union we lose type information anyway.
|
||||||
|
cont->mSVGAngle = static_cast<const nsSVGAngle*>(aValue);
|
||||||
|
cont->mType = aType;
|
||||||
|
SetMiscAtomOrString(aSerialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsAttrValue::EnsureEmptyMiscContainer()
|
nsAttrValue::EnsureEmptyMiscContainer()
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "nsCaseTreatment.h"
|
#include "nsCaseTreatment.h"
|
||||||
#include "nsMargin.h"
|
#include "nsMargin.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
#include "SVGAttrValueWrapper.h"
|
||||||
|
|
||||||
typedef PRUptrdiff PtrBits;
|
typedef PRUptrdiff PtrBits;
|
||||||
class nsAString;
|
class nsAString;
|
||||||
|
@ -102,6 +103,7 @@ public:
|
||||||
nsAttrValue();
|
nsAttrValue();
|
||||||
nsAttrValue(const nsAttrValue& aOther);
|
nsAttrValue(const nsAttrValue& aOther);
|
||||||
explicit nsAttrValue(const nsAString& aValue);
|
explicit nsAttrValue(const nsAString& aValue);
|
||||||
|
explicit nsAttrValue(nsIAtom* aValue);
|
||||||
nsAttrValue(mozilla::css::StyleRule* aValue, const nsAString* aSerialized);
|
nsAttrValue(mozilla::css::StyleRule* aValue, const nsAString* aSerialized);
|
||||||
explicit nsAttrValue(const nsIntMargin& aValue);
|
explicit nsAttrValue(const nsIntMargin& aValue);
|
||||||
~nsAttrValue();
|
~nsAttrValue();
|
||||||
|
@ -123,9 +125,23 @@ public:
|
||||||
// Values below here won't matter, they'll be always stored in the 'misc'
|
// Values below here won't matter, they'll be always stored in the 'misc'
|
||||||
// struct.
|
// struct.
|
||||||
eCSSStyleRule = 0x10
|
eCSSStyleRule = 0x10
|
||||||
,eAtomArray = 0x11
|
,eAtomArray = 0x11
|
||||||
,eDoubleValue = 0x12
|
,eDoubleValue = 0x12
|
||||||
,eIntMarginValue = 0x13
|
,eIntMarginValue = 0x13
|
||||||
|
,eSVGTypesBegin = 0x14
|
||||||
|
,eSVGAngle = eSVGTypesBegin
|
||||||
|
,eSVGIntegerPair = 0x15
|
||||||
|
,eSVGLength = 0x16
|
||||||
|
,eSVGLengthList = 0x17
|
||||||
|
,eSVGNumberList = 0x18
|
||||||
|
,eSVGNumberPair = 0x19
|
||||||
|
,eSVGPathData = 0x20
|
||||||
|
,eSVGPointList = 0x21
|
||||||
|
,eSVGPreserveAspectRatio = 0x22
|
||||||
|
,eSVGStringList = 0x23
|
||||||
|
,eSVGTransformList = 0x24
|
||||||
|
,eSVGViewBox = 0x25
|
||||||
|
,eSVGTypesEnd = 0x34
|
||||||
};
|
};
|
||||||
|
|
||||||
ValueType Type() const;
|
ValueType Type() const;
|
||||||
|
@ -134,9 +150,29 @@ public:
|
||||||
|
|
||||||
void SetTo(const nsAttrValue& aOther);
|
void SetTo(const nsAttrValue& aOther);
|
||||||
void SetTo(const nsAString& aValue);
|
void SetTo(const nsAString& aValue);
|
||||||
|
void SetTo(nsIAtom* aValue);
|
||||||
void SetTo(PRInt16 aInt);
|
void SetTo(PRInt16 aInt);
|
||||||
|
void SetTo(PRInt32 aInt, const nsAString* aSerialized);
|
||||||
|
void SetTo(double aValue, const nsAString* aSerialized);
|
||||||
void SetTo(mozilla::css::StyleRule* aValue, const nsAString* aSerialized);
|
void SetTo(mozilla::css::StyleRule* aValue, const nsAString* aSerialized);
|
||||||
void SetTo(const nsIntMargin& aValue);
|
void SetTo(const nsIntMargin& aValue);
|
||||||
|
void SetTo(const nsSVGAngle& aValue, const nsAString* aSerialized);
|
||||||
|
void SetTo(const nsSVGIntegerPair& aValue, const nsAString* aSerialized);
|
||||||
|
void SetTo(const nsSVGLength2& aValue, const nsAString* aSerialized);
|
||||||
|
void SetTo(const mozilla::SVGLengthList& aValue,
|
||||||
|
const nsAString* aSerialized);
|
||||||
|
void SetTo(const mozilla::SVGNumberList& aValue,
|
||||||
|
const nsAString* aSerialized);
|
||||||
|
void SetTo(const nsSVGNumberPair& aValue, const nsAString* aSerialized);
|
||||||
|
void SetTo(const mozilla::SVGPathData& aValue, const nsAString* aSerialized);
|
||||||
|
void SetTo(const mozilla::SVGPointList& aValue, const nsAString* aSerialized);
|
||||||
|
void SetTo(const mozilla::SVGAnimatedPreserveAspectRatio& aValue,
|
||||||
|
const nsAString* aSerialized);
|
||||||
|
void SetTo(const mozilla::SVGStringList& aValue,
|
||||||
|
const nsAString* aSerialized);
|
||||||
|
void SetTo(const mozilla::SVGTransformList& aValue,
|
||||||
|
const nsAString* aSerialized);
|
||||||
|
void SetTo(const nsSVGViewBox& aValue, const nsAString* aSerialized);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets this object with the string or atom representation of aValue.
|
* Sets this object with the string or atom representation of aValue.
|
||||||
|
@ -368,10 +404,23 @@ private:
|
||||||
AtomArray* mAtomArray;
|
AtomArray* mAtomArray;
|
||||||
double mDoubleValue;
|
double mDoubleValue;
|
||||||
nsIntMargin* mIntMargin;
|
nsIntMargin* mIntMargin;
|
||||||
|
const nsSVGAngle* mSVGAngle;
|
||||||
|
const nsSVGIntegerPair* mSVGIntegerPair;
|
||||||
|
const nsSVGLength2* mSVGLength;
|
||||||
|
const mozilla::SVGLengthList* mSVGLengthList;
|
||||||
|
const mozilla::SVGNumberList* mSVGNumberList;
|
||||||
|
const nsSVGNumberPair* mSVGNumberPair;
|
||||||
|
const mozilla::SVGPathData* mSVGPathData;
|
||||||
|
const mozilla::SVGPointList* mSVGPointList;
|
||||||
|
const mozilla::SVGAnimatedPreserveAspectRatio* mSVGPreserveAspectRatio;
|
||||||
|
const mozilla::SVGStringList* mSVGStringList;
|
||||||
|
const mozilla::SVGTransformList* mSVGTransformList;
|
||||||
|
const nsSVGViewBox* mSVGViewBox;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline ValueBaseType BaseType() const;
|
inline ValueBaseType BaseType() const;
|
||||||
|
inline bool IsSVGType(ValueType aType) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the index of an EnumTable in the sEnumTableArray.
|
* Get the index of an EnumTable in the sEnumTableArray.
|
||||||
|
@ -388,6 +437,8 @@ private:
|
||||||
void SetColorValue(nscolor aColor, const nsAString& aString);
|
void SetColorValue(nscolor aColor, const nsAString& aString);
|
||||||
void SetMiscAtomOrString(const nsAString* aValue);
|
void SetMiscAtomOrString(const nsAString* aValue);
|
||||||
void ResetMiscAtomOrString();
|
void ResetMiscAtomOrString();
|
||||||
|
void SetSVGType(ValueType aType, const void* aValue,
|
||||||
|
const nsAString* aSerialized);
|
||||||
inline void ResetIfSet();
|
inline void ResetIfSet();
|
||||||
|
|
||||||
inline void* GetPtr() const;
|
inline void* GetPtr() const;
|
||||||
|
@ -502,6 +553,12 @@ nsAttrValue::BaseType() const
|
||||||
return static_cast<ValueBaseType>(mBits & NS_ATTRVALUE_BASETYPE_MASK);
|
return static_cast<ValueBaseType>(mBits & NS_ATTRVALUE_BASETYPE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
nsAttrValue::IsSVGType(ValueType aType) const
|
||||||
|
{
|
||||||
|
return aType >= eSVGTypesBegin && aType <= eSVGTypesEnd;
|
||||||
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
nsAttrValue::SetPtrValueAndType(void* aValue, ValueBaseType aType)
|
nsAttrValue::SetPtrValueAndType(void* aValue, ValueBaseType aType)
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "nsCopySupport.h"
|
#include "nsCopySupport.h"
|
||||||
#include "nsIDOMUIEvent.h"
|
#include "nsIDOMUIEvent.h"
|
||||||
#include "nsISelection.h"
|
#include "nsISelection.h"
|
||||||
|
#include "nsISelectionController.h"
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
#include "nsIDOMNodeList.h"
|
#include "nsIDOMNodeList.h"
|
||||||
#include "nsIDOMEvent.h"
|
#include "nsIDOMEvent.h"
|
||||||
|
@ -70,6 +71,7 @@
|
||||||
#include "nsIDocShell.h"
|
#include "nsIDocShell.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsIImageLoadingContent.h"
|
#include "nsIImageLoadingContent.h"
|
||||||
|
#include "nsITextControlElement.h"
|
||||||
#include "nsUnicharUtils.h"
|
#include "nsUnicharUtils.h"
|
||||||
#include "nsIURL.h"
|
#include "nsIURL.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
|
@ -84,37 +86,6 @@
|
||||||
#include "imgIRequest.h"
|
#include "imgIRequest.h"
|
||||||
#include "nsDOMDataTransfer.h"
|
#include "nsDOMDataTransfer.h"
|
||||||
|
|
||||||
// private clipboard data flavors for html copy, used by editor when pasting
|
|
||||||
#define kHTMLContext "text/_moz_htmlcontext"
|
|
||||||
#define kHTMLInfo "text/_moz_htmlinfo"
|
|
||||||
|
|
||||||
// if aNode is null, use the selection from the window
|
|
||||||
static nsresult
|
|
||||||
GetTransferableForNodeOrSelection(nsIDOMWindow* aWindow,
|
|
||||||
nsIContent* aNode,
|
|
||||||
nsITransferable** aTransferable)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aWindow);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
|
||||||
aWindow->GetDocument(getter_AddRefs(domDoc));
|
|
||||||
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
|
|
||||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
if (aNode) {
|
|
||||||
rv = nsCopySupport::GetTransferableForNode(aNode, doc, aTransferable);
|
|
||||||
} else {
|
|
||||||
nsCOMPtr<nsISelection> selection;
|
|
||||||
aWindow->GetSelection(getter_AddRefs(selection));
|
|
||||||
rv = nsCopySupport::GetTransferableForSelection(selection, doc,
|
|
||||||
aTransferable);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
class NS_STACK_CLASS DragDataProducer
|
class NS_STACK_CLASS DragDataProducer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -124,7 +95,7 @@ public:
|
||||||
bool aIsAltKeyPressed);
|
bool aIsAltKeyPressed);
|
||||||
nsresult Produce(nsDOMDataTransfer* aDataTransfer,
|
nsresult Produce(nsDOMDataTransfer* aDataTransfer,
|
||||||
bool* aCanDrag,
|
bool* aCanDrag,
|
||||||
bool* aDragSelection,
|
nsISelection** aSelection,
|
||||||
nsIContent** aDragNode);
|
nsIContent** aDragNode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -172,7 +143,7 @@ nsContentAreaDragDrop::GetDragData(nsIDOMWindow* aWindow,
|
||||||
bool aIsAltKeyPressed,
|
bool aIsAltKeyPressed,
|
||||||
nsDOMDataTransfer* aDataTransfer,
|
nsDOMDataTransfer* aDataTransfer,
|
||||||
bool* aCanDrag,
|
bool* aCanDrag,
|
||||||
bool* aDragSelection,
|
nsISelection** aSelection,
|
||||||
nsIContent** aDragNode)
|
nsIContent** aDragNode)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(aSelectionTargetNode, NS_ERROR_INVALID_ARG);
|
NS_ENSURE_TRUE(aSelectionTargetNode, NS_ERROR_INVALID_ARG);
|
||||||
|
@ -181,7 +152,7 @@ nsContentAreaDragDrop::GetDragData(nsIDOMWindow* aWindow,
|
||||||
|
|
||||||
DragDataProducer
|
DragDataProducer
|
||||||
provider(aWindow, aTarget, aSelectionTargetNode, aIsAltKeyPressed);
|
provider(aWindow, aTarget, aSelectionTargetNode, aIsAltKeyPressed);
|
||||||
return provider.Produce(aDataTransfer, aCanDrag, aDragSelection, aDragNode);
|
return provider.Produce(aDataTransfer, aCanDrag, aSelection, aDragNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -412,10 +383,10 @@ DragDataProducer::GetNodeString(nsIContent* inNode,
|
||||||
nsresult
|
nsresult
|
||||||
DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
||||||
bool* aCanDrag,
|
bool* aCanDrag,
|
||||||
bool* aDragSelection,
|
nsISelection** aSelection,
|
||||||
nsIContent** aDragNode)
|
nsIContent** aDragNode)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(aCanDrag && aDragSelection && aDataTransfer && aDragNode,
|
NS_PRECONDITION(aCanDrag && aSelection && aDataTransfer && aDragNode,
|
||||||
"null pointer passed to Produce");
|
"null pointer passed to Produce");
|
||||||
NS_ASSERTION(mWindow, "window not set");
|
NS_ASSERTION(mWindow, "window not set");
|
||||||
NS_ASSERTION(mSelectionTargetNode, "selection target node should have been set");
|
NS_ASSERTION(mSelectionTargetNode, "selection target node should have been set");
|
||||||
|
@ -424,33 +395,72 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsIContent* dragNode = nsnull;
|
nsIContent* dragNode = nsnull;
|
||||||
|
*aSelection = nsnull;
|
||||||
|
|
||||||
// find the selection to see what we could be dragging and if
|
// Find the selection to see what we could be dragging and if what we're
|
||||||
// what we're dragging is in what is selected.
|
// dragging is in what is selected. If this is an editable textbox, use
|
||||||
|
// the textbox's selection, otherwise use the window's selection.
|
||||||
nsCOMPtr<nsISelection> selection;
|
nsCOMPtr<nsISelection> selection;
|
||||||
mWindow->GetSelection(getter_AddRefs(selection));
|
nsIContent* editingElement = mSelectionTargetNode->IsEditable() ?
|
||||||
if (!selection) {
|
mSelectionTargetNode->GetEditingHost() : nsnull;
|
||||||
return NS_OK;
|
nsCOMPtr<nsITextControlElement> textControl(do_QueryInterface(editingElement));
|
||||||
}
|
if (textControl) {
|
||||||
|
nsISelectionController* selcon = textControl->GetSelectionController();
|
||||||
// check if the node is inside a form control. If so, dragging will be
|
if (selcon) {
|
||||||
// handled in editor code (nsPlaintextDataTransfer::DoDrag). Don't set
|
selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
|
||||||
// aCanDrag to false however, as we still want to allow the drag.
|
if (!selection)
|
||||||
nsCOMPtr<nsIContent> findFormNode = mSelectionTargetNode;
|
return NS_OK;
|
||||||
nsIContent* findFormParent = findFormNode->GetParent();
|
}
|
||||||
while (findFormParent) {
|
}
|
||||||
nsCOMPtr<nsIFormControl> form(do_QueryInterface(findFormParent));
|
else {
|
||||||
if (form && !form->AllowDraggableChildren()) {
|
mWindow->GetSelection(getter_AddRefs(selection));
|
||||||
return NS_OK;
|
if (!selection)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
// Check if the node is inside a form control. Don't set aCanDrag to false
|
||||||
|
//however, as we still want to allow the drag.
|
||||||
|
nsCOMPtr<nsIContent> findFormNode = mSelectionTargetNode;
|
||||||
|
nsIContent* findFormParent = findFormNode->GetParent();
|
||||||
|
while (findFormParent) {
|
||||||
|
nsCOMPtr<nsIFormControl> form(do_QueryInterface(findFormParent));
|
||||||
|
if (form && !form->AllowDraggableChildren()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
findFormParent = findFormParent->GetParent();
|
||||||
}
|
}
|
||||||
findFormParent = findFormParent->GetParent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if set, serialize the content under this node
|
// if set, serialize the content under this node
|
||||||
nsCOMPtr<nsIContent> nodeToSerialize;
|
nsCOMPtr<nsIContent> nodeToSerialize;
|
||||||
*aDragSelection = false;
|
|
||||||
|
|
||||||
{
|
bool isChromeShell = false;
|
||||||
|
nsCOMPtr<nsIWebNavigation> webnav = do_GetInterface(mWindow);
|
||||||
|
nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(webnav);
|
||||||
|
if (dsti) {
|
||||||
|
PRInt32 type = -1;
|
||||||
|
if (NS_SUCCEEDED(dsti->GetItemType(&type)) &&
|
||||||
|
type == nsIDocShellTreeItem::typeChrome) {
|
||||||
|
isChromeShell = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In chrome shells, only allow dragging inside editable areas.
|
||||||
|
if (isChromeShell && !editingElement)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
if (isChromeShell && textControl) {
|
||||||
|
// Only use the selection if it isn't collapsed.
|
||||||
|
bool isCollapsed = false;
|
||||||
|
selection->GetIsCollapsed(&isCollapsed);
|
||||||
|
if (!isCollapsed)
|
||||||
|
selection.swap(*aSelection);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// In content shells, a number of checks are made below to determine
|
||||||
|
// whether an image or a link is being dragged. If so, add additional
|
||||||
|
// data to the data transfer. This is also done for chrome shells, but
|
||||||
|
// only when in a non-textbox editor.
|
||||||
|
|
||||||
bool haveSelectedContent = false;
|
bool haveSelectedContent = false;
|
||||||
|
|
||||||
// possible parent link node
|
// possible parent link node
|
||||||
|
@ -490,7 +500,7 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
*aDragSelection = true;
|
selection.swap(*aSelection);
|
||||||
} else if (selectedImageOrLinkNode) {
|
} else if (selectedImageOrLinkNode) {
|
||||||
// an image is selected
|
// an image is selected
|
||||||
image = do_QueryInterface(selectedImageOrLinkNode);
|
image = do_QueryInterface(selectedImageOrLinkNode);
|
||||||
|
@ -660,20 +670,28 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeToSerialize || *aDragSelection) {
|
if (nodeToSerialize || *aSelection) {
|
||||||
// if we have selected text, use it in preference to the node
|
|
||||||
if (*aDragSelection) {
|
|
||||||
nodeToSerialize = nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
mHtmlString.Truncate();
|
mHtmlString.Truncate();
|
||||||
mContextString.Truncate();
|
mContextString.Truncate();
|
||||||
mInfoString.Truncate();
|
mInfoString.Truncate();
|
||||||
mTitleString.Truncate();
|
mTitleString.Truncate();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||||
|
mWindow->GetDocument(getter_AddRefs(domDoc));
|
||||||
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
||||||
|
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
// if we have selected text, use it in preference to the node
|
||||||
nsCOMPtr<nsITransferable> transferable;
|
nsCOMPtr<nsITransferable> transferable;
|
||||||
rv = ::GetTransferableForNodeOrSelection(mWindow, nodeToSerialize,
|
if (*aSelection) {
|
||||||
getter_AddRefs(transferable));
|
rv = nsCopySupport::GetTransferableForSelection(*aSelection, doc,
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
getter_AddRefs(transferable));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rv = nsCopySupport::GetTransferableForNode(nodeToSerialize, doc,
|
||||||
|
getter_AddRefs(transferable));
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsISupportsString> data;
|
nsCOMPtr<nsISupportsString> data;
|
||||||
PRUint32 dataSize;
|
PRUint32 dataSize;
|
||||||
rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(data), &dataSize);
|
rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(data), &dataSize);
|
||||||
|
@ -747,15 +765,17 @@ DragDataProducer::AddStringsToDataTransfer(nsIContent* aDragNode,
|
||||||
AddString(aDataTransfer, NS_LITERAL_STRING("text/uri-list"), mUrlString, principal);
|
AddString(aDataTransfer, NS_LITERAL_STRING("text/uri-list"), mUrlString, principal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a special flavor, even if we don't have html context data
|
// add a special flavor for the html context data
|
||||||
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), mContextString, principal);
|
if (!mContextString.IsEmpty())
|
||||||
|
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), mContextString, principal);
|
||||||
|
|
||||||
// add a special flavor if we have html info data
|
// add a special flavor if we have html info data
|
||||||
if (!mInfoString.IsEmpty())
|
if (!mInfoString.IsEmpty())
|
||||||
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), mInfoString, principal);
|
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), mInfoString, principal);
|
||||||
|
|
||||||
// add the full html
|
// add the full html
|
||||||
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLMime), mHtmlString, principal);
|
if (!mHtmlString.IsEmpty())
|
||||||
|
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLMime), mHtmlString, principal);
|
||||||
|
|
||||||
// add the plain text. we use the url for text/plain data if an anchor is
|
// add the plain text. we use the url for text/plain data if an anchor is
|
||||||
// being dragged, rather than the title text of the link or the alt text for
|
// being dragged, rather than the title text of the link or the alt text for
|
||||||
|
|
|
@ -78,8 +78,8 @@ public:
|
||||||
* aDataTransfer - the dataTransfer for the drag event.
|
* aDataTransfer - the dataTransfer for the drag event.
|
||||||
* aCanDrag - [out] set to true if the drag may proceed, false to stop the
|
* aCanDrag - [out] set to true if the drag may proceed, false to stop the
|
||||||
* drag entirely
|
* drag entirely
|
||||||
* aDragSelection - [out] set to true to indicate that a selection is being
|
* aSelection - [out] set to the selection being dragged, or null if no
|
||||||
* dragged, rather than a specific node
|
* selection is being dragged.
|
||||||
* aDragNode - [out] the link, image or area being dragged, or null if the
|
* aDragNode - [out] the link, image or area being dragged, or null if the
|
||||||
* drag occurred on another element.
|
* drag occurred on another element.
|
||||||
*/
|
*/
|
||||||
|
@ -89,7 +89,7 @@ public:
|
||||||
bool aIsAltKeyPressed,
|
bool aIsAltKeyPressed,
|
||||||
nsDOMDataTransfer* aDataTransfer,
|
nsDOMDataTransfer* aDataTransfer,
|
||||||
bool* aCanDrag,
|
bool* aCanDrag,
|
||||||
bool* aDragSelection,
|
nsISelection** aSelection,
|
||||||
nsIContent** aDragNode);
|
nsIContent** aDragNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -91,10 +91,6 @@ static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
||||||
static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
|
static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
|
||||||
static NS_DEFINE_CID(kHTMLConverterCID, NS_HTMLFORMATCONVERTER_CID);
|
static NS_DEFINE_CID(kHTMLConverterCID, NS_HTMLFORMATCONVERTER_CID);
|
||||||
|
|
||||||
// private clipboard data flavors for html copy, used by editor when pasting
|
|
||||||
#define kHTMLContext "text/_moz_htmlcontext"
|
|
||||||
#define kHTMLInfo "text/_moz_htmlinfo"
|
|
||||||
|
|
||||||
// copy string data onto the transferable
|
// copy string data onto the transferable
|
||||||
static nsresult AppendString(nsITransferable *aTransferable,
|
static nsresult AppendString(nsITransferable *aTransferable,
|
||||||
const nsAString& aString,
|
const nsAString& aString,
|
||||||
|
|
|
@ -122,9 +122,9 @@ nsDOMMultipartFile::CreateSlice(PRUint64 aStart, PRUint64 aLength,
|
||||||
PRUint64 upperBound = NS_MIN<PRUint64>(l - skipStart, length);
|
PRUint64 upperBound = NS_MIN<PRUint64>(l - skipStart, length);
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMBlob> firstBlob;
|
nsCOMPtr<nsIDOMBlob> firstBlob;
|
||||||
rv = blob->MozSlice(skipStart, skipStart + upperBound,
|
rv = blob->Slice(skipStart, skipStart + upperBound,
|
||||||
aContentType, 3,
|
aContentType, 3,
|
||||||
getter_AddRefs(firstBlob));
|
getter_AddRefs(firstBlob));
|
||||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||||
|
|
||||||
// Avoid wrapping a single blob inside an nsDOMMultipartFile
|
// Avoid wrapping a single blob inside an nsDOMMultipartFile
|
||||||
|
@ -150,8 +150,8 @@ nsDOMMultipartFile::CreateSlice(PRUint64 aStart, PRUint64 aLength,
|
||||||
|
|
||||||
if (length < l) {
|
if (length < l) {
|
||||||
nsCOMPtr<nsIDOMBlob> lastBlob;
|
nsCOMPtr<nsIDOMBlob> lastBlob;
|
||||||
rv = blob->MozSlice(0, length, aContentType, 3,
|
rv = blob->Slice(0, length, aContentType, 3,
|
||||||
getter_AddRefs(lastBlob));
|
getter_AddRefs(lastBlob));
|
||||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||||
|
|
||||||
blobs.AppendElement(lastBlob);
|
blobs.AppendElement(lastBlob);
|
||||||
|
|
|
@ -238,9 +238,9 @@ ParseSize(PRInt64 aSize, PRInt64& aStart, PRInt64& aEnd)
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMFileBase::MozSlice(PRInt64 aStart, PRInt64 aEnd,
|
nsDOMFileBase::Slice(PRInt64 aStart, PRInt64 aEnd,
|
||||||
const nsAString& aContentType, PRUint8 optional_argc,
|
const nsAString& aContentType, PRUint8 optional_argc,
|
||||||
nsIDOMBlob **aBlob)
|
nsIDOMBlob **aBlob)
|
||||||
{
|
{
|
||||||
*aBlob = nsnull;
|
*aBlob = nsnull;
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ nsEventSource::nsEventSource() :
|
||||||
mErrorLoadOnRedirect(false),
|
mErrorLoadOnRedirect(false),
|
||||||
mGoingToDispatchAllMessages(false),
|
mGoingToDispatchAllMessages(false),
|
||||||
mWithCredentials(false),
|
mWithCredentials(false),
|
||||||
|
mWaitingForOnStopRequest(false),
|
||||||
mLastConvertionResult(NS_OK),
|
mLastConvertionResult(NS_OK),
|
||||||
mReadyState(nsIEventSource::CONNECTING),
|
mReadyState(nsIEventSource::CONNECTING),
|
||||||
mScriptLine(0),
|
mScriptLine(0),
|
||||||
|
@ -108,13 +109,19 @@ nsEventSource::~nsEventSource()
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventSource)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventSource)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsEventSource)
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsEventSource)
|
||||||
if (tmp->IsBlack()) {
|
bool isBlack = tmp->IsBlack();
|
||||||
|
if (isBlack || tmp->mWaitingForOnStopRequest) {
|
||||||
if (tmp->mListenerManager) {
|
if (tmp->mListenerManager) {
|
||||||
tmp->mListenerManager->UnmarkGrayJSListeners();
|
tmp->mListenerManager->UnmarkGrayJSListeners();
|
||||||
NS_UNMARK_LISTENER_WRAPPER(Open)
|
NS_UNMARK_LISTENER_WRAPPER(Open)
|
||||||
NS_UNMARK_LISTENER_WRAPPER(Message)
|
NS_UNMARK_LISTENER_WRAPPER(Message)
|
||||||
NS_UNMARK_LISTENER_WRAPPER(Error)
|
NS_UNMARK_LISTENER_WRAPPER(Error)
|
||||||
}
|
}
|
||||||
|
if (!isBlack) {
|
||||||
|
xpc_UnmarkGrayObject(tmp->PreservingWrapper() ?
|
||||||
|
tmp->GetWrapperPreserveColor() :
|
||||||
|
tmp->GetExpandoObjectPreserveColor());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
|
||||||
|
@ -599,6 +606,8 @@ nsEventSource::OnStopRequest(nsIRequest *aRequest,
|
||||||
nsISupports *aContext,
|
nsISupports *aContext,
|
||||||
nsresult aStatusCode)
|
nsresult aStatusCode)
|
||||||
{
|
{
|
||||||
|
mWaitingForOnStopRequest = false;
|
||||||
|
|
||||||
if (mReadyState == nsIEventSource::CLOSED) {
|
if (mReadyState == nsIEventSource::CLOSED) {
|
||||||
return NS_ERROR_ABORT;
|
return NS_ERROR_ABORT;
|
||||||
}
|
}
|
||||||
|
@ -949,7 +958,11 @@ nsEventSource::InitChannelAndRequestEventSource()
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Start reading from the channel
|
// Start reading from the channel
|
||||||
return mHttpChannel->AsyncOpen(listener, nsnull);
|
rv = mHttpChannel->AsyncOpen(listener, nsnull);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
mWaitingForOnStopRequest = true;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -216,6 +216,7 @@ protected:
|
||||||
bool mErrorLoadOnRedirect;
|
bool mErrorLoadOnRedirect;
|
||||||
bool mGoingToDispatchAllMessages;
|
bool mGoingToDispatchAllMessages;
|
||||||
bool mWithCredentials;
|
bool mWithCredentials;
|
||||||
|
bool mWaitingForOnStopRequest;
|
||||||
|
|
||||||
// used while reading the input streams
|
// used while reading the input streams
|
||||||
nsCOMPtr<nsIUnicodeDecoder> mUnicodeDecoder;
|
nsCOMPtr<nsIUnicodeDecoder> mUnicodeDecoder;
|
||||||
|
|
|
@ -1700,9 +1700,29 @@ nsINode::SetExplicitBaseURI(nsIURI* aURI)
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
static JSObject*
|
||||||
|
GetJSObjectChild(nsWrapperCache* aCache)
|
||||||
|
{
|
||||||
|
if (aCache->PreservingWrapper()) {
|
||||||
|
return aCache->GetWrapperPreserveColor();
|
||||||
|
}
|
||||||
|
return aCache->GetExpandoObjectPreserveColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
NeedsScriptTraverse(nsWrapperCache* aCache)
|
||||||
|
{
|
||||||
|
JSObject* o = GetJSObjectChild(aCache);
|
||||||
|
return o && xpc_IsGrayGCThing(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsChildContentList)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsChildContentList)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsChildContentList)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsChildContentList)
|
||||||
|
|
||||||
|
// If nsChildContentList is changed so that any additional fields are
|
||||||
|
// traversed by the cycle collector, then CAN_SKIP must be updated.
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsChildContentList)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsChildContentList)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsChildContentList)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsChildContentList)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||||
|
@ -1714,6 +1734,20 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsChildContentList)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
|
// nsChildContentList only ever has a single child, its wrapper, so if
|
||||||
|
// the wrapper is black, the list can't be part of a garbage cycle.
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsChildContentList)
|
||||||
|
return !NeedsScriptTraverse(tmp);
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsChildContentList)
|
||||||
|
return !NeedsScriptTraverse(tmp);
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
|
||||||
|
|
||||||
|
// CanSkipThis returns false to avoid problems with incomplete unlinking.
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsChildContentList)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
|
||||||
|
|
||||||
NS_INTERFACE_TABLE_HEAD(nsChildContentList)
|
NS_INTERFACE_TABLE_HEAD(nsChildContentList)
|
||||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||||
NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsChildContentList)
|
NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsChildContentList)
|
||||||
|
@ -4405,22 +4439,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGenericElement)
|
||||||
nsINode::Trace(tmp, aCallback, aClosure);
|
nsINode::Trace(tmp, aCallback, aClosure);
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
static JSObject*
|
|
||||||
GetJSObjectChild(nsINode* aNode)
|
|
||||||
{
|
|
||||||
if (aNode->PreservingWrapper()) {
|
|
||||||
return aNode->GetWrapperPreserveColor();
|
|
||||||
}
|
|
||||||
return aNode->GetExpandoObjectPreserveColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
NeedsScriptTraverse(nsINode* aNode)
|
|
||||||
{
|
|
||||||
JSObject* o = GetJSObjectChild(aNode);
|
|
||||||
return o && xpc_IsGrayGCThing(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsGenericElement::MarkUserData(void* aObject, nsIAtom* aKey, void* aChild,
|
nsGenericElement::MarkUserData(void* aObject, nsIAtom* aKey, void* aChild,
|
||||||
void* aData)
|
void* aData)
|
||||||
|
|
|
@ -102,7 +102,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsChildContentList)
|
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsChildContentList)
|
||||||
|
|
||||||
// nsWrapperCache
|
// nsWrapperCache
|
||||||
virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
|
virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
|
||||||
|
|
|
@ -439,7 +439,8 @@ nsWebSocket::~nsWebSocket()
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsWebSocket)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsWebSocket)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsWebSocket)
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsWebSocket)
|
||||||
if (tmp->IsBlack()) {
|
bool isBlack = tmp->IsBlack();
|
||||||
|
if (isBlack|| tmp->mKeepingAlive) {
|
||||||
if (tmp->mListenerManager) {
|
if (tmp->mListenerManager) {
|
||||||
tmp->mListenerManager->UnmarkGrayJSListeners();
|
tmp->mListenerManager->UnmarkGrayJSListeners();
|
||||||
NS_UNMARK_LISTENER_WRAPPER(Open)
|
NS_UNMARK_LISTENER_WRAPPER(Open)
|
||||||
|
@ -447,6 +448,11 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsWebSocket)
|
||||||
NS_UNMARK_LISTENER_WRAPPER(Message)
|
NS_UNMARK_LISTENER_WRAPPER(Message)
|
||||||
NS_UNMARK_LISTENER_WRAPPER(Close)
|
NS_UNMARK_LISTENER_WRAPPER(Close)
|
||||||
}
|
}
|
||||||
|
if (!isBlack) {
|
||||||
|
xpc_UnmarkGrayObject(tmp->PreservingWrapper() ?
|
||||||
|
tmp->GetWrapperPreserveColor() :
|
||||||
|
tmp->GetExpandoObjectPreserveColor());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
|
||||||
|
|
|
@ -445,8 +445,8 @@ nsXMLHttpRequest::nsXMLHttpRequest()
|
||||||
mProgressSinceLastProgressEvent(false),
|
mProgressSinceLastProgressEvent(false),
|
||||||
mUploadProgress(0), mUploadProgressMax(0),
|
mUploadProgress(0), mUploadProgressMax(0),
|
||||||
mRequestSentTime(0), mTimeoutMilliseconds(0),
|
mRequestSentTime(0), mTimeoutMilliseconds(0),
|
||||||
mErrorLoad(false), mProgressTimerIsActive(false),
|
mErrorLoad(false), mWaitingForOnStopRequest(false),
|
||||||
mProgressEventWasDelayed(false),
|
mProgressTimerIsActive(false), mProgressEventWasDelayed(false),
|
||||||
mIsHtml(false),
|
mIsHtml(false),
|
||||||
mWarnAboutMultipartHtml(false),
|
mWarnAboutMultipartHtml(false),
|
||||||
mWarnAboutSyncHtml(false),
|
mWarnAboutSyncHtml(false),
|
||||||
|
@ -602,7 +602,8 @@ nsXMLHttpRequest::SetRequestObserver(nsIRequestObserver* aObserver)
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsXMLHttpRequest)
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsXMLHttpRequest)
|
||||||
if (tmp->IsBlack()) {
|
bool isBlack = tmp->IsBlack();
|
||||||
|
if (isBlack || tmp->mWaitingForOnStopRequest) {
|
||||||
if (tmp->mListenerManager) {
|
if (tmp->mListenerManager) {
|
||||||
tmp->mListenerManager->UnmarkGrayJSListeners();
|
tmp->mListenerManager->UnmarkGrayJSListeners();
|
||||||
NS_UNMARK_LISTENER_WRAPPER(Load)
|
NS_UNMARK_LISTENER_WRAPPER(Load)
|
||||||
|
@ -614,6 +615,11 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsXMLHttpRequest)
|
||||||
NS_UNMARK_LISTENER_WRAPPER(UploadProgress)
|
NS_UNMARK_LISTENER_WRAPPER(UploadProgress)
|
||||||
NS_UNMARK_LISTENER_WRAPPER(Readystatechange)
|
NS_UNMARK_LISTENER_WRAPPER(Readystatechange)
|
||||||
}
|
}
|
||||||
|
if (!isBlack) {
|
||||||
|
xpc_UnmarkGrayObject(tmp->PreservingWrapper() ?
|
||||||
|
tmp->GetWrapperPreserveColor() :
|
||||||
|
tmp->GetExpandoObjectPreserveColor());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
|
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
|
||||||
|
@ -2140,6 +2146,8 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mWaitingForOnStopRequest = false;
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
// If we're loading a multipart stream of XML documents, we'll get
|
// If we're loading a multipart stream of XML documents, we'll get
|
||||||
|
@ -2774,6 +2782,9 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Either AsyncOpen was called, or CORS will open the channel later.
|
||||||
|
mWaitingForOnStopRequest = true;
|
||||||
|
|
||||||
// If we're synchronous, spin an event loop here and wait
|
// If we're synchronous, spin an event loop here and wait
|
||||||
if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
|
if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
|
||||||
mState |= XML_HTTP_REQUEST_SYNCLOOPING;
|
mState |= XML_HTTP_REQUEST_SYNCLOOPING;
|
||||||
|
|
|
@ -365,7 +365,7 @@ protected:
|
||||||
void HandleTimeoutCallback();
|
void HandleTimeoutCallback();
|
||||||
|
|
||||||
bool mErrorLoad;
|
bool mErrorLoad;
|
||||||
|
bool mWaitingForOnStopRequest;
|
||||||
bool mProgressTimerIsActive;
|
bool mProgressTimerIsActive;
|
||||||
bool mProgressEventWasDelayed;
|
bool mProgressEventWasDelayed;
|
||||||
bool mIsHtml;
|
bool mIsHtml;
|
||||||
|
|
|
@ -201,24 +201,24 @@ function testSlice(file, size, type, contents, fileType) {
|
||||||
ok(file instanceof File, fileType + " file is a File");
|
ok(file instanceof File, fileType + " file is a File");
|
||||||
ok(file instanceof Blob, fileType + " file is also a Blob");
|
ok(file instanceof Blob, fileType + " file is also a Blob");
|
||||||
|
|
||||||
var slice = file.mozSlice(0, size);
|
var slice = file.slice(0, size);
|
||||||
ok(slice instanceof Blob, fileType + " fullsize slice is a Blob");
|
ok(slice instanceof Blob, fileType + " fullsize slice is a Blob");
|
||||||
ok(!(slice instanceof File), fileType + " fullsize slice is not a File");
|
ok(!(slice instanceof File), fileType + " fullsize slice is not a File");
|
||||||
|
|
||||||
slice = file.mozSlice(0, 1234);
|
slice = file.slice(0, 1234);
|
||||||
ok(slice instanceof Blob, fileType + " sized slice is a Blob");
|
ok(slice instanceof Blob, fileType + " sized slice is a Blob");
|
||||||
ok(!(slice instanceof File), fileType + " sized slice is not a File");
|
ok(!(slice instanceof File), fileType + " sized slice is not a File");
|
||||||
|
|
||||||
slice = file.mozSlice(0, size, "foo/bar");
|
slice = file.slice(0, size, "foo/bar");
|
||||||
is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type");
|
is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type");
|
||||||
|
|
||||||
slice = file.mozSlice(0, 5432, "foo/bar");
|
slice = file.slice(0, 5432, "foo/bar");
|
||||||
is(slice.type, "foo/bar", fileType + " sized slice foo/bar type");
|
is(slice.type, "foo/bar", fileType + " sized slice foo/bar type");
|
||||||
|
|
||||||
is(slice.mozSlice(0, 10).type, "", fileType + " slice-slice type");
|
is(slice.slice(0, 10).type, "", fileType + " slice-slice type");
|
||||||
is(slice.mozSlice(0, 10).size, 10, fileType + " slice-slice size");
|
is(slice.slice(0, 10).size, 10, fileType + " slice-slice size");
|
||||||
is(slice.mozSlice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type");
|
is(slice.slice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type");
|
||||||
is(slice.mozSlice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size");
|
is(slice.slice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size");
|
||||||
|
|
||||||
// Start, end, expected size
|
// Start, end, expected size
|
||||||
var indexes = [[0, size, size],
|
var indexes = [[0, size, size],
|
||||||
|
@ -247,17 +247,17 @@ function testSlice(file, size, type, contents, fileType) {
|
||||||
var sliceContents;
|
var sliceContents;
|
||||||
var testName;
|
var testName;
|
||||||
if (indexes[i][0] == undefined) {
|
if (indexes[i][0] == undefined) {
|
||||||
slice = file.mozSlice();
|
slice = file.slice();
|
||||||
sliceContents = contents.slice();
|
sliceContents = contents.slice();
|
||||||
testName = fileType + " slice()";
|
testName = fileType + " slice()";
|
||||||
}
|
}
|
||||||
else if (indexes[i][1] == undefined) {
|
else if (indexes[i][1] == undefined) {
|
||||||
slice = file.mozSlice(indexes[i][0]);
|
slice = file.slice(indexes[i][0]);
|
||||||
sliceContents = contents.slice(indexes[i][0]);
|
sliceContents = contents.slice(indexes[i][0]);
|
||||||
testName = fileType + " slice(" + indexes[i][0] + ")";
|
testName = fileType + " slice(" + indexes[i][0] + ")";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
slice = file.mozSlice(indexes[i][0], indexes[i][1]);
|
slice = file.slice(indexes[i][0], indexes[i][1]);
|
||||||
sliceContents = contents.slice(indexes[i][0], indexes[i][1]);
|
sliceContents = contents.slice(indexes[i][0], indexes[i][1]);
|
||||||
testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")";
|
testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")";
|
||||||
}
|
}
|
||||||
|
@ -268,11 +268,11 @@ function testSlice(file, size, type, contents, fileType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slice of slice
|
// Slice of slice
|
||||||
var slice = file.mozSlice(0, 40000);
|
var slice = file.slice(0, 40000);
|
||||||
testFile(slice.mozSlice(5000, 42000), contents.slice(5000, 40000), "file slice slice");
|
testFile(slice.slice(5000, 42000), contents.slice(5000, 40000), "file slice slice");
|
||||||
|
|
||||||
// ...of slice of slice
|
// ...of slice of slice
|
||||||
slice = slice.mozSlice(5000, 42000).mozSlice(400, 700);
|
slice = slice.slice(5000, 42000).slice(400, 700);
|
||||||
SpecialPowers.gc();
|
SpecialPowers.gc();
|
||||||
testFile(slice, contents.slice(5400, 5700), "file slice slice slice");
|
testFile(slice, contents.slice(5400, 5700), "file slice slice slice");
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ function doTest(data) {
|
||||||
ok(blob instanceof Blob, "Test " + testCounter + " blob is a Blob");
|
ok(blob instanceof Blob, "Test " + testCounter + " blob is a Blob");
|
||||||
ok(!(blob instanceof File), "Test " + testCounter + " blob is not a File");
|
ok(!(blob instanceof File), "Test " + testCounter + " blob is not a File");
|
||||||
|
|
||||||
let slice = blob.mozSlice(test.start, test.start + test.length);
|
let slice = blob.slice(test.start, test.start + test.length);
|
||||||
ok(slice, "Test " + testCounter + " got slice");
|
ok(slice, "Test " + testCounter + " got slice");
|
||||||
ok(slice instanceof Blob, "Test " + testCounter + " slice is a Blob");
|
ok(slice instanceof Blob, "Test " + testCounter + " slice is a Blob");
|
||||||
ok(!(slice instanceof File), "Test " + testCounter + " slice is not a File");
|
ok(!(slice instanceof File), "Test " + testCounter + " slice is not a File");
|
||||||
|
|
|
@ -49,7 +49,7 @@ function attr_modified(ev) {
|
||||||
e_prev = e_new;
|
e_prev = e_new;
|
||||||
if (!recursive) {
|
if (!recursive) {
|
||||||
recursive = true;
|
recursive = true;
|
||||||
e_new = "width: 0pt;";
|
e_new = "width: 0px;";
|
||||||
testDiv.style.width = "0";
|
testDiv.style.width = "0";
|
||||||
} else {
|
} else {
|
||||||
recursive = false;
|
recursive = false;
|
||||||
|
|
|
@ -104,7 +104,7 @@ function imageLoadHandler(event) {
|
||||||
var imgfile = createFileWithData(testBinaryData + fileData + testBinaryData);
|
var imgfile = createFileWithData(testBinaryData + fileData + testBinaryData);
|
||||||
is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)");
|
is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)");
|
||||||
var img = new Image;
|
var img = new Image;
|
||||||
img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size));
|
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
|
||||||
img.onload = imageLoadHandler;
|
img.onload = imageLoadHandler;
|
||||||
expectedTestCount++;
|
expectedTestCount++;
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ expectedTestCount++;
|
||||||
var imgfile = createFileWithData(fileData + testBinaryData);
|
var imgfile = createFileWithData(fileData + testBinaryData);
|
||||||
is(imgfile.size, size + testBinaryData.length, "correct file size (start)");
|
is(imgfile.size, size + testBinaryData.length, "correct file size (start)");
|
||||||
var img = new Image;
|
var img = new Image;
|
||||||
img.src = URL.createObjectURL(imgfile.mozSlice(0, size));
|
img.src = URL.createObjectURL(imgfile.slice(0, size));
|
||||||
img.onload = imageLoadHandler;
|
img.onload = imageLoadHandler;
|
||||||
expectedTestCount++;
|
expectedTestCount++;
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ expectedTestCount++;
|
||||||
var imgfile = createFileWithData(testBinaryData + fileData);
|
var imgfile = createFileWithData(testBinaryData + fileData);
|
||||||
is(imgfile.size, size + testBinaryData.length, "correct file size (end)");
|
is(imgfile.size, size + testBinaryData.length, "correct file size (end)");
|
||||||
var img = new Image;
|
var img = new Image;
|
||||||
img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size));
|
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
|
||||||
img.onload = imageLoadHandler;
|
img.onload = imageLoadHandler;
|
||||||
expectedTestCount++;
|
expectedTestCount++;
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ expectedTestCount++;
|
||||||
var imgfile = createFileWithData(testBinaryData + fileData);
|
var imgfile = createFileWithData(testBinaryData + fileData);
|
||||||
is(imgfile.size, size + testBinaryData.length, "correct file size (past end)");
|
is(imgfile.size, size + testBinaryData.length, "correct file size (past end)");
|
||||||
var img = new Image;
|
var img = new Image;
|
||||||
img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size + 1000));
|
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size + 1000));
|
||||||
img.onload = imageLoadHandler;
|
img.onload = imageLoadHandler;
|
||||||
expectedTestCount++;
|
expectedTestCount++;
|
||||||
|
|
||||||
|
|
|
@ -1024,7 +1024,7 @@ struct WebGLVertexAttribData {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebGLBuffer
|
class WebGLBuffer MOZ_FINAL
|
||||||
: public nsIWebGLBuffer
|
: public nsIWebGLBuffer
|
||||||
, public WebGLRefCountedObject<WebGLBuffer>
|
, public WebGLRefCountedObject<WebGLBuffer>
|
||||||
, public WebGLContextBoundObject
|
, public WebGLContextBoundObject
|
||||||
|
@ -1158,7 +1158,7 @@ protected:
|
||||||
void* mData; // in the case of an Element Array Buffer, we keep a copy.
|
void* mData; // in the case of an Element Array Buffer, we keep a copy.
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebGLTexture
|
class WebGLTexture MOZ_FINAL
|
||||||
: public nsIWebGLTexture
|
: public nsIWebGLTexture
|
||||||
, public WebGLRefCountedObject<WebGLTexture>
|
, public WebGLRefCountedObject<WebGLTexture>
|
||||||
, public WebGLContextBoundObject
|
, public WebGLContextBoundObject
|
||||||
|
@ -1608,7 +1608,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebGLShader
|
class WebGLShader MOZ_FINAL
|
||||||
: public nsIWebGLShader
|
: public nsIWebGLShader
|
||||||
, public WebGLRefCountedObject<WebGLShader>
|
, public WebGLRefCountedObject<WebGLShader>
|
||||||
, public WebGLContextBoundObject
|
, public WebGLContextBoundObject
|
||||||
|
@ -1673,7 +1673,7 @@ protected:
|
||||||
WebGLMonotonicHandle mMonotonicHandle;
|
WebGLMonotonicHandle mMonotonicHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebGLProgram
|
class WebGLProgram MOZ_FINAL
|
||||||
: public nsIWebGLProgram
|
: public nsIWebGLProgram
|
||||||
, public WebGLRefCountedObject<WebGLProgram>
|
, public WebGLRefCountedObject<WebGLProgram>
|
||||||
, public WebGLContextBoundObject
|
, public WebGLContextBoundObject
|
||||||
|
@ -1795,7 +1795,7 @@ protected:
|
||||||
WebGLMonotonicHandle mMonotonicHandle;
|
WebGLMonotonicHandle mMonotonicHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebGLRenderbuffer
|
class WebGLRenderbuffer MOZ_FINAL
|
||||||
: public nsIWebGLRenderbuffer
|
: public nsIWebGLRenderbuffer
|
||||||
, public WebGLRefCountedObject<WebGLRenderbuffer>
|
, public WebGLRefCountedObject<WebGLRenderbuffer>
|
||||||
, public WebGLRectangleObject
|
, public WebGLRectangleObject
|
||||||
|
@ -2001,7 +2001,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebGLFramebuffer
|
class WebGLFramebuffer MOZ_FINAL
|
||||||
: public nsIWebGLFramebuffer
|
: public nsIWebGLFramebuffer
|
||||||
, public WebGLRefCountedObject<WebGLFramebuffer>
|
, public WebGLRefCountedObject<WebGLFramebuffer>
|
||||||
, public WebGLContextBoundObject
|
, public WebGLContextBoundObject
|
||||||
|
@ -2296,7 +2296,7 @@ public:
|
||||||
WebGLMonotonicHandle mMonotonicHandle;
|
WebGLMonotonicHandle mMonotonicHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebGLUniformLocation
|
class WebGLUniformLocation MOZ_FINAL
|
||||||
: public nsIWebGLUniformLocation
|
: public nsIWebGLUniformLocation
|
||||||
, public WebGLContextBoundObject
|
, public WebGLContextBoundObject
|
||||||
, public WebGLRefCountedObject<WebGLUniformLocation>
|
, public WebGLRefCountedObject<WebGLUniformLocation>
|
||||||
|
@ -2337,7 +2337,7 @@ protected:
|
||||||
friend class WebGLProgram;
|
friend class WebGLProgram;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebGLActiveInfo
|
class WebGLActiveInfo MOZ_FINAL
|
||||||
: public nsIWebGLActiveInfo
|
: public nsIWebGLActiveInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -2356,7 +2356,7 @@ protected:
|
||||||
nsString mName;
|
nsString mName;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebGLShaderPrecisionFormat
|
class WebGLShaderPrecisionFormat MOZ_FINAL
|
||||||
: public nsIWebGLShaderPrecisionFormat
|
: public nsIWebGLShaderPrecisionFormat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -2388,6 +2388,7 @@ public:
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSIWEBGLEXTENSION
|
NS_DECL_NSIWEBGLEXTENSION
|
||||||
|
virtual ~WebGLExtension() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const WebGLRectangleObject *WebGLContext::FramebufferRectangleObject() const {
|
inline const WebGLRectangleObject *WebGLContext::FramebufferRectangleObject() const {
|
||||||
|
|
|
@ -4377,7 +4377,7 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
||||||
// ESSL backend
|
// ESSL backend
|
||||||
compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
|
compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
|
||||||
SH_WEBGL_SPEC,
|
SH_WEBGL_SPEC,
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef ANDROID
|
||||||
SH_GLSL_OUTPUT,
|
SH_GLSL_OUTPUT,
|
||||||
#else
|
#else
|
||||||
gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT,
|
gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT,
|
||||||
|
|
|
@ -180,7 +180,7 @@ CopyContext(gfxContext* dest, gfxContext* src)
|
||||||
**/
|
**/
|
||||||
#define NS_CANVASGRADIENT_PRIVATE_IID \
|
#define NS_CANVASGRADIENT_PRIVATE_IID \
|
||||||
{ 0x491d39d8, 0x4058, 0x42bd, { 0xac, 0x76, 0x70, 0xd5, 0x62, 0x7f, 0x02, 0x10 } }
|
{ 0x491d39d8, 0x4058, 0x42bd, { 0xac, 0x76, 0x70, 0xd5, 0x62, 0x7f, 0x02, 0x10 } }
|
||||||
class nsCanvasGradient : public nsIDOMCanvasGradient
|
class nsCanvasGradient MOZ_FINAL : public nsIDOMCanvasGradient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENT_PRIVATE_IID)
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENT_PRIVATE_IID)
|
||||||
|
@ -238,7 +238,7 @@ NS_INTERFACE_MAP_END
|
||||||
**/
|
**/
|
||||||
#define NS_CANVASPATTERN_PRIVATE_IID \
|
#define NS_CANVASPATTERN_PRIVATE_IID \
|
||||||
{ 0xb85c6c8a, 0x0624, 0x4530, { 0xb8, 0xee, 0xff, 0xdf, 0x42, 0xe8, 0x21, 0x6d } }
|
{ 0xb85c6c8a, 0x0624, 0x4530, { 0xb8, 0xee, 0xff, 0xdf, 0x42, 0xe8, 0x21, 0x6d } }
|
||||||
class nsCanvasPattern : public nsIDOMCanvasPattern
|
class nsCanvasPattern MOZ_FINAL : public nsIDOMCanvasPattern
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASPATTERN_PRIVATE_IID)
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASPATTERN_PRIVATE_IID)
|
||||||
|
|
|
@ -7,3 +7,5 @@ conformance/more/conformance/quickCheckAPI-S_V.html
|
||||||
conformance/glsl/misc/attrib-location-length-limits.html
|
conformance/glsl/misc/attrib-location-length-limits.html
|
||||||
conformance/glsl/misc/uniform-location-length-limits.html
|
conformance/glsl/misc/uniform-location-length-limits.html
|
||||||
conformance/programs/program-test.html
|
conformance/programs/program-test.html
|
||||||
|
conformance/textures/texture-mips.html
|
||||||
|
conformance/textures/texture-npot.html
|
||||||
|
|
|
@ -180,8 +180,7 @@ nsDOMEvent::InitPresContextData(nsPresContext* aPresContext)
|
||||||
// Get the explicit original target (if it's anonymous make it null)
|
// Get the explicit original target (if it's anonymous make it null)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIContent> content = GetTargetFromFrame();
|
nsCOMPtr<nsIContent> content = GetTargetFromFrame();
|
||||||
mTmpRealOriginalTarget = do_QueryInterface(content);
|
mExplicitOriginalTarget = do_QueryInterface(content);
|
||||||
mExplicitOriginalTarget = mTmpRealOriginalTarget;
|
|
||||||
if (content && content->IsInAnonymousSubtree()) {
|
if (content && content->IsInAnonymousSubtree()) {
|
||||||
mExplicitOriginalTarget = nsnull;
|
mExplicitOriginalTarget = nsnull;
|
||||||
}
|
}
|
||||||
|
@ -237,10 +236,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPresContext);
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPresContext);
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTmpRealOriginalTarget)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mExplicitOriginalTarget);
|
||||||
// Always set mExplicitOriginalTarget to null, when
|
|
||||||
// mTmpRealOriginalTarget doesn't point to any object!
|
|
||||||
tmp->mExplicitOriginalTarget = nsnull;
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent)
|
||||||
|
@ -275,7 +271,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mPresContext.get(), nsPresContext)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mPresContext.get(), nsPresContext)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTmpRealOriginalTarget)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mExplicitOriginalTarget)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
// nsIDOMEventInterface
|
// nsIDOMEventInterface
|
||||||
|
@ -355,18 +351,6 @@ nsDOMEvent::GetExplicitOriginalTarget(nsIDOMEventTarget** aRealEventTarget)
|
||||||
return GetTarget(aRealEventTarget);
|
return GetTarget(aRealEventTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsDOMEvent::GetTmpRealOriginalTarget(nsIDOMEventTarget** aRealEventTarget)
|
|
||||||
{
|
|
||||||
if (mTmpRealOriginalTarget) {
|
|
||||||
*aRealEventTarget = mTmpRealOriginalTarget;
|
|
||||||
NS_ADDREF(*aRealEventTarget);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetOriginalTarget(aRealEventTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMEvent::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget)
|
nsDOMEvent::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget)
|
||||||
{
|
{
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче