This commit is contained in:
Ms2ger 2011-12-16 21:04:41 +01:00
Родитель 9cf3cc807d 72ede3876a
Коммит 6b8d5d04ab
78 изменённых файлов: 1794 добавлений и 414 удалений

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

@ -401,8 +401,9 @@ WindowHelper.prototype = {
let key = aDelta < 0 ? "UP" : "DOWN";
let abs = Math.abs(aDelta);
let treechildren = this.getTree().treeBoxObject.treeBody;
treechildren.focus();
for (let i = 0; i < abs; i++) {
EventUtils.sendKey(key, treechildren);
EventUtils.sendKey(key);
}
},

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

@ -41,7 +41,7 @@ function testReturnCommit()
start: function() {
is(span.inplaceEditor.input.value, "explicit initial", "Explicit initial value should be used.");
span.inplaceEditor.input.value = "Test Value";
EventUtils.sendKey("return", span.inplaceEditor.input);
EventUtils.sendKey("return");
},
done: expectDone("Test Value", true, testBlurCommit)
});
@ -74,7 +74,7 @@ function testAdvanceCharCommit()
start: function() {
let input = span.inplaceEditor.input;
for each (let ch in "Test:") {
EventUtils.sendChar(ch, input);
EventUtils.sendChar(ch);
}
},
done: expectDone("Test", true, testEscapeCancel)
@ -91,7 +91,7 @@ function testEscapeCancel()
initial: "initial text",
start: function() {
span.inplaceEditor.input.value = "Test Value";
EventUtils.sendKey("escape", span.inplaceEditor.input);
EventUtils.sendKey("escape");
},
done: expectDone("initial text", false, finishTest)
});

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

@ -120,7 +120,7 @@ function testCreateNew()
aEditor.input.blur();
});
EventUtils.sendKey("return", input);
EventUtils.sendKey("return", ruleDialog);
});
EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1,
@ -148,11 +148,11 @@ function testEditProperty()
});
for each (let ch in "red;") {
EventUtils.sendChar(ch, input);
EventUtils.sendChar(ch, ruleDialog);
}
});
for each (let ch in "border-color:") {
EventUtils.sendChar(ch, input);
EventUtils.sendChar(ch, ruleDialog);
}
});

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

@ -0,0 +1,9 @@
Robocop is a Mozilla project which uses Robotium to test Firefox on Android devices.
Robotium is an open source tool licensed under the Apache 2.0 license and the original
source can be found here:
http://code.google.com/p/robotium/
We are including robotium-solo-3.0.jar as a binary and are not modifying it in anyway
from the original download found at:
http://code.google.com/p/robotium/

Двоичные данные
build/mobile/robocop/robotium-solo-3.0.jar Normal file

Двоичный файл не отображается.

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

@ -171,6 +171,9 @@ endif # MOZ_BUILD_PROJECTS
CONFIGURES := $(TOPSRCDIR)/configure
CONFIGURES += $(TOPSRCDIR)/js/src/configure
# Make targets that are going to be passed to the real build system
OBJDIR_TARGETS = install export libs clean realclean distclean alldep maybe_clobber_profiledbuild upload sdk installer package package-compare stage-package source-package l10n-check
#######################################################################
# Rules
@ -259,7 +262,7 @@ endif
# loop through them.
ifeq (,$(MOZ_CURRENT_PROJECT)$(if $(MOZ_BUILD_PROJECTS),,1))
configure depend realbuild install export libs clean realclean distclean alldep preflight postflight maybe_clobber_profiledbuild upload sdk::
configure depend realbuild preflight postflight $(OBJDIR_TARGETS)::
set -e; \
for app in $(MOZ_BUILD_PROJECTS); do \
$(MAKE) -f $(TOPSRCDIR)/client.mk $@ MOZ_CURRENT_PROJECT=$$app; \
@ -370,7 +373,7 @@ realbuild:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
# Other targets
# Pass these target onto the real build system
install export libs clean realclean distclean alldep maybe_clobber_profiledbuild upload sdk:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
$(OBJDIR_TARGETS):: $(OBJDIR)/Makefile $(OBJDIR)/config.status
$(MOZ_MAKE) $@
####################################
@ -429,4 +432,4 @@ echo-variable-%:
# in parallel.
.NOTPARALLEL:
.PHONY: checkout real_checkout depend realbuild build profiledbuild maybe_clobber_profiledbuild export libs alldep install clean realclean distclean cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything configure preflight_all preflight postflight postflight_all upload sdk
.PHONY: checkout real_checkout depend realbuild build profiledbuild cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything configure preflight_all preflight postflight postflight_all $(OBJDIR_TARGETS)

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

@ -5705,6 +5705,7 @@ if test -n "$MOZ_WEBM"; then
[return 0;],
[AC_MSG_RESULT([yes])
MOZ_NATIVE_LIBVPX=1
AC_DEFINE(MOZ_NATIVE_LIBVPX)
MOZ_LIBVPX_INCLUDES="-I${LIBVPX_DIR}/include"
MOZ_LIBVPX_LIBS="-L${LIBVPX_DIR}/lib -lvpx"],
[AC_MSG_RESULT([no])

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

@ -62,7 +62,8 @@ var hrefs = {
function submitForm(idNum) {
$("test"+idNum).setAttribute("onload", "frameLoaded(this)");
sendKey("return", "test" + idNum + "image");
$("test" + idNum + "image").focus();
sendKey("return");
}
function submitFormMouse(idNum) {

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

@ -76,7 +76,7 @@ is(i.value, "test3", "Setting textarea defaultValue after hide/show should work"
i = $("target2");
i.focus(); // Otherwise editor gets confused when we send the key events
is(i.value, "", "Textarea value should be empty string in second control");
sendString("2test2", "target2");
sendString("2test2");
is(i.value, "2test2", 'We just typed the string "2test2"');
i.defaultValue = "2test3";
is(i.value, "2test2", "Setting textarea defaultValue after typing should not work");

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

@ -121,7 +121,7 @@ function checkInputEmail()
synthesizeKey("a", {});
checkInvalidApplies(element);
sendString("@b.c", element);
sendString("@b.c");
checkValidApplies(element);
synthesizeKey("VK_BACK_SPACE", {});
@ -151,7 +151,7 @@ function checkInputURL()
synthesizeKey("h", {});
checkInvalidApplies(element);
sendString("ttp://mozilla.org", element);
sendString("ttp://mozilla.org");
checkValidApplies(element);
for (var i=0; i<13; ++i) {

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

@ -66,14 +66,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782
// WARNING: If the following test fails, give the setTimeout() in the onload()
// a bit longer; the doc hasn't had enough time to setup its editor.
is(gTest.window.document.body.innerHTML, gTest.expectedBodyBeforeEdit, "Is doc setup yet");
sendChar('E', gTest.window.document.body);
sendChar('D', gTest.window.document.body);
sendChar('I', gTest.window.document.body);
sendChar('T', gTest.window.document.body);
sendChar('E', gTest.window.document.body);
sendChar('D', gTest.window.document.body);
sendChar(' ', gTest.window.document.body);
sendString('EDITED ', gTest.window);
is(gTest.window.document.body.innerHTML, gTest.expectedBodyAfterEdit, "Editing failed.");
gTest.window.location = 'data:text/html;charset=utf-8,SomeOtherDocument';
@ -103,12 +96,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782
// Check that we can still edit the page.
gTest.window.document.body.focus();
sendChar('T', gTest.window.document.body);
sendChar('W', gTest.window.document.body);
sendChar('I', gTest.window.document.body);
sendChar('C', gTest.window.document.body);
sendChar('E', gTest.window.document.body);
sendChar(' ', gTest.window.document.body);
sendString('TWICE ', gTest.window);
is(gTest.window.document.body.innerHTML, gTest.expectedBodyAfterSecondEdit, "Can we still edit?");
gTest.window.close();

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

@ -36,12 +36,8 @@ function onReload() {
function doTest() {
var bodyElement = window.frames[0].frameElement.contentDocument.body;
sendChar('S', bodyElement);
sendChar('t', bodyElement);
sendChar('i', bodyElement);
sendChar('l', bodyElement);
sendChar('l', bodyElement);
sendChar(' ', bodyElement);
bodyElement.focus();
sendString('Still ', window.frames[0].frameElement.contentWindow);
is(bodyElement.innerHTML, "Still contentEditable", "Check we're contentEditable after reload");

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

@ -62,15 +62,25 @@ var step1 =function() {
// Navigate down and up.
is(testWindow.document.body.scrollTop, 0,
"Page1: Ensure we scrollpane is at the top before we start scrolling.");
testWindow.addEventListener("scroll", function () {
testWindow.removeEventListener("scroll", arguments.callee, true);
isnot(testWindow.document.body.scrollTop, 0,
"Page1: Ensure we can scroll down.");
SimpleTest.executeSoon(step1_2);
}, true);
sendKey('DOWN', testWindow);
sendKey('UP', testWindow);
setTimeout(function() {
is(testWindow.document.body.scrollTop, 0,
"Page1: Ensure we can scroll down and up, back to the top.");
// Nav to blue box page. This should fire step2.
testWindow.location = gTallBlueBoxURI;
}, 0);
function step1_2() {
testWindow.addEventListener("scroll", function () {
testWindow.removeEventListener("scroll", arguments.callee, true);
is(testWindow.document.body.scrollTop, 0,
"Page1: Ensure we can scroll up, back to the top.");
// Nav to blue box page. This should fire step2.
testWindow.location = gTallBlueBoxURI;
}, true);
sendKey('UP', testWindow);
}
}
@ -80,16 +90,22 @@ var step2 =function() {
// Scroll around a bit.
is(testWindow.document.body.scrollTop, 0,
"Page2: Ensure we scrollpane is at the top before we start scrolling.");
var count = 0;
testWindow.addEventListener("scroll", function () {
if (++count < 4) {
SimpleTest.executeSoon(function () { sendKey('DOWN', testWindow); });
} else {
testWindow.removeEventListener("scroll", arguments.callee, true);
isnot(testWindow.document.body.scrollTop, 0,
"Page2: Ensure we could scroll.");
// Navigate backwards. This should fire step3.
testWindow.history.back();
}
}, true);
sendKey('DOWN', testWindow);
sendKey('DOWN', testWindow);
sendKey('DOWN', testWindow);
setTimeout(function() {
isnot(testWindow.document.body.scrollTop, 0,
"Page2: Ensure we could scrol.");
// Navigate backwards. This should fire step3.
testWindow.history.back();
}, 0);
}
var step3 =function() {
@ -99,14 +115,16 @@ var step3 =function() {
// Check we can still scroll with the keys.
is(testWindow.document.body.scrollTop, 0,
"Page1Again: Ensure scroll pane at top before we scroll.");
sendKey('DOWN', testWindow);
setTimeout(function() {
testWindow.addEventListener("scroll", function () {
testWindow.removeEventListener("scroll", arguments.callee, true);
isnot(testWindow.document.body.scrollTop, 0,
"Page2Again: Ensure we can still scroll.");
testWindow.close();
window.SimpleTest.finish();
}, 0);
}, true);
sendKey('DOWN', testWindow);
}
SimpleTest.waitForExplicitFinish();

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

@ -15,9 +15,7 @@ function runTest() {
e.contentDocument.designMode='on';
e.style.display='block';
e.focus();
sendChar('a', e.contentDocument);
sendChar('b', e.contentDocument);
sendChar('c', e.contentDocument);
sendString('abc');
var expected = "<head></head><body>abc</body>";
var result = e.contentDocument.documentElement.innerHTML;
is(result, expected, "iframe with designmode on had incorrect content");

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

@ -58,12 +58,7 @@ function addWords(aLimit) {
return;
}
getEdit().focus();
sendChar('a', editDoc());
sendChar('a', editDoc());
sendChar(' ', editDoc());
sendChar('O', editDoc());
sendChar('K', editDoc());
sendChar(' ', editDoc());
sendString('aa OK ');
gMisspeltWords.push("aa");
setTimeout(function() { addWords(aLimit-1); }, 0);
}

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

@ -27,7 +27,7 @@ function runTest() {
function test_begin_bs(e) {
const msg = "BACKSPACE at beginning of contenteditable inline element";
var before = e.parentNode.childNodes[0].nodeValue;
sendKey("back_space", e);
sendKey("back_space");
is(e.parentNode.childNodes[0].nodeValue, before, msg + " with id=" + e.id);
is(e.innerHTML, "X", msg + " with id=" + e.id);
}
@ -35,7 +35,7 @@ function runTest() {
function test_begin_space(e) {
const msg = "SPACE at beginning of contenteditable inline element";
var before = e.parentNode.childNodes[0].nodeValue;
sendChar(" ", e);
sendChar(" ");
is(e.parentNode.childNodes[0].nodeValue, before, msg + " with id=" + e.id);
is(e.innerHTML, "&nbsp;X", msg + " with id=" + e.id);
}
@ -43,8 +43,8 @@ function runTest() {
function test_end_delete(e) {
const msg = "DEL at end of contenteditable inline element";
var before = e.parentNode.childNodes[2].nodeValue;
sendKey("right", e);
sendKey("delete", e);
sendKey("right");
sendKey("delete");
is(e.parentNode.childNodes[2].nodeValue, before, msg + " with id=" + e.id);
is(e.innerHTML, "X", msg + " with id=" + e.id);
}
@ -52,8 +52,8 @@ function runTest() {
function test_end_space(e) {
const msg = "SPACE at end of contenteditable inline element";
var before = e.parentNode.childNodes[2].nodeValue;
sendKey("right", e);
sendChar(" ", e);
sendKey("right");
sendChar(" ");
is(e.parentNode.childNodes[2].nodeValue, before, msg + " with id=" + e.id);
is(e.innerHTML, "X" + (e.tagName=="SPAN" ? "&nbsp;" : " <br>"), msg + " with id=" + e.id);
}

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

@ -27,9 +27,9 @@ function runTest() {
function test_end_bs(e) {
const msg = "Deleting all text in contenteditable inline element";
var before = e.parentNode.childNodes[0].nodeValue;
sendKey("right", e);
sendKey("back_space", e);
sendKey("back_space", e);
sendKey("right");
sendKey("back_space");
sendKey("back_space");
is(e.parentNode.childNodes[0].nodeValue, before, msg + " with id=" + e.id);
is(e.innerHTML, "", msg + " with id=" + e.id);
}
@ -43,8 +43,8 @@ function runTest() {
var doc = e.contentDocument;
doc.body.setAttribute("contenteditable", "true");
doc.body.focus();
sendKey("right", doc.body);
sendKey("back_space", doc.body);
sendKey("right");
sendKey("back_space");
is(doc.body.innerHTML, "<br>", msg + " with id=" + e.id);
}

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

@ -31,7 +31,7 @@ function runTest() {
range.setEnd(li1.nextSibling,0);
selection.addRange(range);
sendKey('delete', li1);
sendKey('delete');
is(doc.body.innerHTML,'<ul><li>two</li><ul><li>a</li></ul></ul>','delete 1st LI');
var li2 = setupIframe(i1,'<ul><li id="li2">two</li><ul><li>a</li></ul></ul>','li2')
@ -43,7 +43,7 @@ function runTest() {
range.setEnd(li2.nextSibling.firstChild,0);
selection.addRange(range);
sendKey('delete', li2);
sendKey('delete');
is(doc.body.innerHTML,'<ul><ul><li>a</li></ul></ul>','delete 2nd LI');
SimpleTest.finish();

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

@ -57,12 +57,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=607584
{
var editor = this.mEditor.getEditor(this.mEditor.contentWindow);
if (editor) {
this.mEditor.focus();
editor instanceof Components.interfaces.nsIHTMLEditor;
editor.returnInParagraphCreatesNewParagraph = true;
editor.insertHTML("<p id='foo'>this is a paragraph carrying id 'foo'</p>");
var p = editor.document.getElementById('foo')
editor.beginningOfDocument();
sendKey("return", p);
sendKey("return");
var firstP = p.parentNode.firstElementChild;
var lastP = p.parentNode.lastElementChild;
var isOk = firstP.nodeName.toLowerCase() == "p" &&

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

@ -26,10 +26,10 @@ SimpleTest.waitForFocus(function() {
element.focus();
element.selectionStart = 4;
element.selectionEnd = 4;
synthesizeKey("VK_BACKSPACE", {});
synthesizeKey("VK_BACKSPACE", {});
synthesizeKey("VK_BACKSPACE", {});
synthesizeKey("VK_BACKSPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
ok(element.value, "", "4 backspaces should delete all of the characters in the " + element.localName);
}

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

@ -1171,6 +1171,10 @@ LayerManagerOGL::CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit,
msg.AppendInt(result, 16);
msg.Append(", mFBOTextureTarget 0x");
msg.AppendInt(mFBOTextureTarget, 16);
msg.Append(", aRect.width ");
msg.AppendInt(aRect.width);
msg.Append(", aRect.height ");
msg.AppendInt(aRect.height);
NS_RUNTIMEABORT(msg.get());
}

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

@ -3494,15 +3494,16 @@ EndVerifyBarriers(JSContext *cx)
JS_ASSERT(trc->number == rt->gcNumber);
for (CompartmentsIter c(rt); !c.done(); c.next()) {
c->gcIncrementalTracer = NULL;
c->needsBarrier_ = false;
}
if (rt->gcIncrementalTracer->hasDelayedChildren())
rt->gcIncrementalTracer->markDelayedChildren();
rt->gcVerifyData = NULL;
rt->gcIncrementalTracer = NULL;
for (CompartmentsIter c(rt); !c.done(); c.next()) {
c->gcIncrementalTracer = NULL;
c->needsBarrier_ = false;
}
JS_TRACER_INIT(trc, cx, CheckAutorooter);

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

@ -17,10 +17,10 @@ y
var area = document.getElementById('t');
area.focus();
sendKey('RIGHT', window); // now after "A"
sendKey('RIGHT', window); //
sendKey('RIGHT', window); //
sendKey('RIGHT', window); // now at the last line
sendKey('RIGHT'); // now after "A"
sendKey('RIGHT'); //
sendKey('RIGHT'); //
sendKey('RIGHT'); // now at the last line
</script>
</body>

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

@ -17,9 +17,9 @@ y
var area = document.getElementById('t');
area.focus();
sendKey('DOWN', window); // now after "A"
sendKey('DOWN', window); //
sendKey('DOWN', window); // now at the last line
sendKey('DOWN'); // now after "A"
sendKey('DOWN'); //
sendKey('DOWN'); // now at the last line
</script>
</body>
</html>

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

@ -17,10 +17,10 @@ y
var area = document.getElementById('t');
area.focus();
sendKey('DOWN', window); // now after "A"
sendKey('DOWN', window); //
sendKey('DOWN', window); //
sendKey('DOWN', window); // now at the last line
sendKey('DOWN'); // now after "A"
sendKey('DOWN'); //
sendKey('DOWN'); //
sendKey('DOWN'); // now at the last line
</script>
</body>
</html>

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

@ -7,7 +7,7 @@
var area = document.getElementById('t');
area.focus();
sendKey('ENTER', "t"); // press Enter once
sendKey('ENTER'); // press Enter once
</script>
</body>
</html>

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

@ -7,9 +7,9 @@
var area = document.getElementById('t');
area.focus();
sendKey('ENTER', "t"); // press Enter twice
sendKey('ENTER', "t");
sendKey('BACK_SPACE', "t"); // press Backspace once
sendKey('ENTER'); // press Enter twice
sendKey('ENTER');
sendKey('BACK_SPACE'); // press Backspace once
</script>
</body>
</html>

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

@ -15,8 +15,8 @@
range.setEnd(p.firstChild, 0);
sel.addRange(range);
sendKey('UP', div); // move UP
sendChar('A', div); // insert "A"
sendKey('UP'); // move UP
sendChar('A'); // insert "A"
</script>
</body>
</html>

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

@ -19,12 +19,12 @@ x
sel.addRange(range);
p.parentNode.focus();
sendKey('DOWN', window); // now after "1"
sendKey('DOWN', window); // now make sure we get to the end
sendKey('DOWN', window); // now make sure we get to the end
sendKey('DOWN', window); // now make sure we get to the end
sendKey('DOWN', window); // now make sure we get to the end
sendKey('DOWN', window); // now make sure we get to the end
sendKey('DOWN'); // now after "1"
sendKey('DOWN'); // now make sure we get to the end
sendKey('DOWN'); // now make sure we get to the end
sendKey('DOWN'); // now make sure we get to the end
sendKey('DOWN'); // now make sure we get to the end
sendKey('DOWN'); // now make sure we get to the end
</script>
</body>
</html>

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

@ -19,12 +19,12 @@ x
sel.addRange(range);
p.parentNode.focus();
sendKey('DOWN', window); // now after "1"
sendKey('DOWN', window); // now below the P element
sendKey('UP', window); // now before the "1"
sendKey('UP', window); // now before the "A"
sendKey('UP', window); // now before the "A"
sendKey('UP', window); // now before the "A"
sendKey('DOWN'); // now after "1"
sendKey('DOWN'); // now below the P element
sendKey('UP'); // now before the "1"
sendKey('UP'); // now before the "A"
sendKey('UP'); // now before the "A"
sendKey('UP'); // now before the "A"
</script>
</body>
</html>

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

@ -15,7 +15,7 @@
sel.addRange(range);
x.focus();
sendKey('RIGHT', window); // Try to move the caret one position to the right
sendKey('RIGHT'); // Try to move the caret one position to the right
</script>
</body>
</html>

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

@ -17,7 +17,7 @@
sel.addRange(range);
x.focus();
sendKey('RIGHT', window); // Try to move the caret one position to the right
sendKey('RIGHT'); // Try to move the caret one position to the right
</script>
</body>
</html>

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

@ -15,7 +15,7 @@ noteditable<span id="x" contenteditable="true">navigable|unnavigable</span><br /
sel.addRange(range);
x.focus();
sendKey('RIGHT', window); // Try to move the caret one position to the right
sendKey('RIGHT'); // Try to move the caret one position to the right
</script>
</body>
</html>

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

@ -15,7 +15,7 @@
sel.addRange(range);
x.focus();
sendKey('RIGHT', window); // Try to move the caret one position to the right
sendKey('RIGHT'); // Try to move the caret one position to the right
</script>
</body>
</html>

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

@ -8,7 +8,7 @@
var t = document.querySelector("textarea");
t.focus();
t.selectionStart = t.selectionEnd = t.value.length;
sendKey('ENTER', "target");
sendKey('ENTER');
document.body.appendChild(document.createTextNode(t.selectionStart + " - " + t.selectionEnd));
</script>
</body>

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

@ -8,7 +8,7 @@
var t = document.querySelector("textarea");
t.focus();
t.selectionStart = t.selectionEnd = t.value.length;
sendKey('ENTER', "target");
sendKey('ENTER');
document.body.appendChild(document.createTextNode(t.selectionStart + " - " + t.selectionEnd));
</script>
</body>

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

@ -8,7 +8,7 @@
var t = document.querySelector("textarea");
t.focus();
t.selectionStart = t.selectionEnd = t.value.length;
sendKey('ENTER', "target");
sendKey('ENTER');
document.body.appendChild(document.createTextNode(t.selectionStart + " - " + t.selectionEnd));
</script>
</body>

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

@ -12,8 +12,8 @@
function test() {
document.querySelector("div").focus();
// type a character, then press backspace to delete it
sendKey("X", "div1");
sendKey("BACK_SPACE", "div1");
sendChar("X");
sendKey("BACK_SPACE");
document.documentElement.removeAttribute("class");
}
</script>

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

@ -12,8 +12,8 @@
function test() {
document.querySelector("div").focus();
// type a character, then press backspace to delete it
sendKey("X", "div1");
sendKey("BACK_SPACE", "div1");
sendChar("X");
sendKey("BACK_SPACE");
document.documentElement.removeAttribute("class");
}
</script>

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

@ -12,8 +12,8 @@
function test() {
document.querySelector("div").focus();
// type a character, then press backspace to delete it
sendKey("X", "div1");
sendKey("BACK_SPACE", "div1");
sendChar("X");
sendKey("BACK_SPACE");
document.documentElement.removeAttribute("class");
}
</script>

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

@ -14,6 +14,7 @@
window.addEventListener("message",
function(evt) {
doIs(evt.data, "start", "Unexpected message");
$("target").focus();
sendString("Test");
var t = $("target");
doIs(t.value, "Test", "Typing should work");

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

@ -83,7 +83,7 @@ is($("target").value, "abc", "Typing should be limited by maxlength");
$("target").value = "";
sendString("ad");
sendKey("left");
sendString("bc")
sendString("bc");
is($("target").value, "abd", "Typing should be limited by maxlength again");
</script>

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

@ -78,10 +78,10 @@ function pageUpDownTest(id,index) {
var elm = document.getElementById(id);
elm.focus();
elm.selectedIndex = 0;
sendKey("page_down", elm);
sendKey("page_down", elm);
sendKey("page_up", elm);
sendKey("page_down", elm);
sendKey("page_down");
sendKey("page_down");
sendKey("page_up");
sendKey("page_down");
is(elm.selectedIndex, index, "pageUpDownTest: selectedIndex for " + id + " is " + index);
}
@ -89,10 +89,10 @@ function upDownTest(id,index) {
var elm = document.getElementById(id);
elm.focus();
elm.selectedIndex = 0;
sendKey("down", elm);
sendKey("down", elm);
sendKey("up", elm);
sendKey("down", elm);
sendKey("down");
sendKey("down");
sendKey("up");
sendKey("down");
is(elm.selectedIndex, index, "upDownTest: selectedIndex for " + id + " is " + index);
}

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

@ -48,11 +48,11 @@ var elm = document.getElementById(id);
elm.focus();
var x = document.body.offsetHeight;
$(id).addEventListener("input", inputListener, false);
sendChar('1',elm);
sendChar('1');
is(inputHappened, true, "How come no input?");
sendChar('3',elm);
sendKey('LEFT',elm)
sendChar('2',elm);
sendChar('3');
sendKey('LEFT')
sendChar('2');
elm.blur();
x = document.body.offsetHeight;
is(elm.value, '123', id + " edit");
@ -61,14 +61,14 @@ test_edit_cmds(id)
id = 'bug446663_b'
elm = document.getElementById(id);
elm.focus();
sendChar('1',elm);
sendChar('1');
elm.style.display = 'none'
var x = document.body.offsetHeight;
elm.style.display = 'inline'
x = document.body.offsetHeight;
sendChar('3',elm);
sendKey('LEFT',elm)
sendChar('2',elm);
sendChar('3');
sendKey('LEFT')
sendChar('2');
elm.blur();
x = document.body.offsetHeight;
is(elm.value, '123', id + " edit");

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

@ -59,13 +59,14 @@ function runTests(callback, type) {
// Make sure that the control accepts input events without explicit initialization
is(c.value, "", "Control is empty initially");
sendChar("a", c);
c.focus();
sendChar("a");
is(c.value, "a", "Control accepts input without explicit initialization");
// Make sure that the control retains its caret position
c.focus();
c.blur();
c.focus();
sendChar("b", c);
sendChar("b");
is(c.value, "ab", "Control retains caret position after being re-focused");
var d = document.createElement("input");
@ -76,8 +77,9 @@ function runTests(callback, type) {
// Make sure dynamically injected inputs work as expected
is(d.value, "", "Dynamic control's initial value should be empty");
d.value = "new";
d.focus();
is(d.value, "new", "Dynamic control's value can be set before initialization");
sendChar("x", d);
sendChar("x");
is(d.value, "xnew", "Dynamic control accepts keyboard input without explicit initialization");
$("display").removeChild(d);
is(d.value, "xnew", "Dynamic control retains value after being removed from the document");

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

@ -41,11 +41,11 @@ function pageUpDownTest(id,index) {
var elm = document.getElementById(id);
elm.focus();
elm.selectedIndex = 0;
sendKey("page_down", elm);
sendKey("page_down", elm);
sendKey("page_down", elm);
sendKey("page_up", elm);
sendKey("page_down", elm);
sendKey("page_down");
sendKey("page_down");
sendKey("page_down");
sendKey("page_up");
sendKey("page_down");
is(elm.selectedIndex, index, "pageUpDownTest: selectedIndex for " + id + " is " + index);
}
@ -53,11 +53,11 @@ function upDownTest(id,index) {
var elm = document.getElementById(id);
elm.focus();
elm.selectedIndex = 0;
sendKey("down", elm);
sendKey("down", elm);
sendKey("down", elm);
sendKey("up", elm);
sendKey("down", elm);
sendKey("down");
sendKey("down");
sendKey("down");
sendKey("up");
sendKey("down");
is(elm.selectedIndex, index, "upDownTest: selectedIndex for " + id + " is " + index);
}

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

@ -34,7 +34,7 @@ function runTests() {
// record scrolltop
scrollTopBefore = doc.body.scrollTop;
// send up arrow key event
sendKey("UP", doc.body);
sendKey("UP");
setTimeout("finish();", 0);
}

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

@ -93,7 +93,10 @@ SHARED_LIBRARY_LIBS += \
EXTRA_DSO_LDOPTS = $(MOZALLOC_LIB) $(NSPR_LIBS)
ifeq (WINNT,$(OS_TARGET))
DEFFILE = $(srcdir)/symbols.def
DEFFILE = symbols.def
symbols.def: symbols.def.in
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(ACDEFINES) $< > $@
endif
include $(topsrcdir)/config/rules.mk

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

@ -1,5 +1,6 @@
LIBRARY gkmedias.dll
EXPORTS
#ifdef MOZ_WEBM
nestegg_destroy
nestegg_duration
nestegg_free_packet
@ -18,6 +19,16 @@ nestegg_track_seek
nestegg_track_type
nestegg_track_video_params
nestegg_tstamp_scale
#ifndef MOZ_NATIVE_LIBVPX
vpx_codec_dec_init_ver
vpx_codec_decode
vpx_codec_destroy
vpx_codec_get_frame
vpx_codec_peek_stream_info
vpx_codec_vp8_dx
#endif
#endif
#ifdef MOZ_VORBIS
ogg_page_bos
ogg_page_granulepos
ogg_page_serialno
@ -33,29 +44,6 @@ ogg_sync_init
ogg_sync_pageseek
ogg_sync_reset
ogg_sync_wrote
sa_stream_create_pcm
sa_stream_destroy
sa_stream_drain
sa_stream_get_min_write
sa_stream_get_position
sa_stream_get_write_size
sa_stream_open
sa_stream_pause
sa_stream_resume
sa_stream_write
th_comment_clear
th_comment_init
th_decode_alloc
th_decode_free
th_decode_headerin
th_decode_packetin
th_decode_ycbcr_out
th_granule_frame
th_info_clear
th_info_init
th_packet_isheader
th_packet_iskeyframe
th_setup_free
vorbis_block_clear
vorbis_block_init
vorbis_comment_clear
@ -71,12 +59,34 @@ vorbis_synthesis_init
vorbis_synthesis_pcmout
vorbis_synthesis_read
vorbis_synthesis_restart
vpx_codec_dec_init_ver
vpx_codec_decode
vpx_codec_destroy
vpx_codec_get_frame
vpx_codec_peek_stream_info
vpx_codec_vp8_dx
#endif
#ifdef MOZ_SYDNEYAUDIO
sa_stream_create_pcm
sa_stream_destroy
sa_stream_drain
sa_stream_get_min_write
sa_stream_get_position
sa_stream_get_write_size
sa_stream_open
sa_stream_pause
sa_stream_resume
sa_stream_write
#endif
#ifdef MOZ_OGG
th_comment_clear
th_comment_init
th_decode_alloc
th_decode_free
th_decode_headerin
th_decode_packetin
th_decode_ycbcr_out
th_granule_frame
th_info_clear
th_info_init
th_packet_isheader
th_packet_iskeyframe
th_setup_free
#endif
ShInitialize
ShFinalize
ShGetObjectCode

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

@ -744,6 +744,24 @@ abstract public class GeckoApp
});
}
void handleLoadError(final int tabId, final String uri, final String title) {
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null)
return;
// When a load error occurs, the URLBar can get corrupt so we reset it
mMainHandler.post(new Runnable() {
public void run() {
if (Tabs.getInstance().isSelectedTab(tab)) {
mBrowserToolbar.setTitle(tab.getDisplayTitle());
mBrowserToolbar.setFavicon(tab.getFavicon());
mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
mBrowserToolbar.setProgressVisibility(tab.isLoading());
}
}
});
}
public File getProfileDir() {
// XXX: TO-DO read profiles.ini to get the default profile
return getProfileDir("default");
@ -880,6 +898,11 @@ abstract public class GeckoApp
handleDocumentStop(tabId);
}
}
} else if (event.equals("Content:LoadError")) {
final int tabId = message.getInt("tabID");
final String uri = message.getString("uri");
final String title = message.getString("title");
handleLoadError(tabId, uri, title);
} else if (event.equals("onCameraCapture")) {
//GeckoApp.mAppContext.doCameraCapture(message.getString("path"));
doCameraCapture();
@ -1423,6 +1446,7 @@ abstract public class GeckoApp
GeckoAppShell.registerGeckoEventListener("Content:LocationChange", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Content:SecurityChange", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Content:StateChange", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Content:LoadError", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("onCameraCapture", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Tab:Added", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Tab:Closed", GeckoApp.mAppContext);
@ -1653,6 +1677,7 @@ abstract public class GeckoApp
GeckoAppShell.unregisterGeckoEventListener("Content:LocationChange", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Content:SecurityChange", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Content:StateChange", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Content:LoadError", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("onCameraCapture", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Tab:Added", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Tab:Closed", GeckoApp.mAppContext);
@ -1979,10 +2004,8 @@ abstract public class GeckoApp
String url = data.getStringExtra(AwesomeBar.URL_KEY);
AwesomeBar.Type type = AwesomeBar.Type.valueOf(data.getStringExtra(AwesomeBar.TYPE_KEY));
String searchEngine = data.getStringExtra(AwesomeBar.SEARCH_KEY);
if (url != null && url.length() > 0) {
mBrowserToolbar.setProgressVisibility(true);
if (url != null && url.length() > 0)
loadRequest(url, type, searchEngine);
}
}
break;
case CAMERA_CAPTURE_REQUEST:

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

@ -1229,17 +1229,32 @@ public class GeckoAppShell
return accessibilityManager.isEnabled();
}
public static void addPluginView(View view,
double x, double y,
double w, double h)
{
public static void addPluginView(final View view,
final double x, final double y,
final double w, final double h) {
Log.i(LOGTAG, "addPluginView:" + view + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h ) ;
GeckoApp.mAppContext.addPluginView(view, x, y, w, h);
getMainHandler().post(new Runnable() {
public void run() {
try {
GeckoApp.mAppContext.addPluginView(view, x, y, w, h);
} catch (Exception e) {
Log.e(LOGTAG, "Failed to add plugin view: ", e);
}
}
});
}
public static void removePluginView(View view) {
Log.i(LOGTAG, "remove view:" + view);
GeckoApp.mAppContext.removePluginView(view);
public static void removePluginView(final View view) {
Log.i(LOGTAG, "removePluginView:" + view);
getMainHandler().post(new Runnable() {
public void run() {
try {
GeckoApp.mAppContext.removePluginView(view);
} catch (Exception e) {
Log.e(LOGTAG, "Failed to remove plugin view: ", e);
}
}
});
}
public static Class<?> loadPluginClass(String className, String libName) {

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

@ -0,0 +1,108 @@
#filter substitution
package @ANDROID_PACKAGE_NAME@.tests;
import com.jayway.android.robotium.solo.Solo;
import @ANDROID_PACKAGE_NAME@.*;
import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
import android.test.PerformanceTestCase;
import android.util.Log;
import android.widget.Button;
import android.content.Intent;
import java.util.HashMap;
@SuppressWarnings("unused")
public class testAwesomebar extends ActivityInstrumentationTestCase2 {
@SuppressWarnings("unchecked")
public testAwesomebar(Class activityClass) {
super(activityClass);
// TODO Auto-generated constructor stub
}
private static final String TARGET_PACKAGE_ID = "org.mozilla.gecko";
private static final String LAUNCH_ACTIVITY_FULL_CLASSNAME="@ANDROID_PACKAGE_NAME@.App";
private Solo solo;
private Activity activity;
private Driver driver;
private Actions actions;
private static Class<?> launcherActivityClass;
static{
try{
launcherActivityClass = Class.forName(LAUNCH_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e){
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public testAwesomebar() throws ClassNotFoundException {
super(TARGET_PACKAGE_ID, launcherActivityClass);
}
@Override
protected void setUp() throws Exception
{
// Load config file from sdcard (setup by python script)
String configFile = FennecNativeDriver.getFile("/mnt/sdcard/robotium.config");
HashMap config = FennecNativeDriver.convertTextToTable(configFile);
// Create the intent to be used with all the important arguments.
Intent i = new Intent(Intent.ACTION_MAIN);
String argsList = "-no-remote -profile " + (String)config.get("profile");
i.putExtra("args", argsList);
//Start the activity
setActivityIntent(i);
activity = getActivity();
//Set up Robotium.solo and Driver objects
solo = new Solo(getInstrumentation(), getActivity());
driver = new FennecNativeDriver(activity, solo);
actions = new FennecNativeActions(activity, solo, getInstrumentation());
driver.setLogFile((String)config.get("logfile"));
}
public void testAwesomebar() {
// TODO: find a better way to not hardcode this url
String url = "http://mochi.test:8888/tests/robocop/robocop.html";
Element awesomebar = driver.findElement("awesome_bar");
awesomebar.click();
Element urlbar = driver.findElement("awesomebar_text");
actions.sendKeys(url);
driver.is(url, urlbar.getText(), "Awesomebar URL Typed Properly");
//could also use: urlbar.clickSpecialKey(Element.SpecialKey.ENTER)
actions.sendKeys("\n");
//wait for screen to load
actions.waitForGeckoEvent("DOMContentLoaded");
driver.setupScrollHandling();
//Calculate where we should be dragging.
int midX = driver.getGeckoLeft() + driver.getGeckoWidth()/2;
int midY = driver.getGeckoTop() + driver.getGeckoHeight()/2;
int endY = driver.getGeckoTop() + driver.getGeckoHeight()/10;
for(int i = 0; i < 10; i++) {
actions.drag(midX,midX,midY,endY);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//Click the awesomebar again
awesomebar.click();
driver.is(url, urlbar.getText(), "Aweosmebar URL stayed the same");
}
@Override
public void tearDown() throws Exception {
try {
solo.finalize();
}catch (Throwable e){
e.printStackTrace();
}
getActivity().finish();
super.tearDown();
}
}

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

@ -0,0 +1,109 @@
#filter substitution
package @ANDROID_PACKAGE_NAME@.tests;
import com.jayway.android.robotium.solo.Solo;
import @ANDROID_PACKAGE_NAME@.*;
import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
import android.test.PerformanceTestCase;
import android.util.Log;
import android.widget.Button;
import android.content.Intent;
import java.util.HashMap;
@SuppressWarnings("unused")
public class testBookmark extends ActivityInstrumentationTestCase2 {
@SuppressWarnings("unchecked")
public testBookmark(Class activityClass) {
super(activityClass);
// TODO Auto-generated constructor stub
}
private static final String TARGET_PACKAGE_ID = "org.mozilla.gecko";
private static final String LAUNCH_ACTIVITY_FULL_CLASSNAME="@ANDROID_PACKAGE_NAME@.App";
private Solo solo;
private Activity activity;
private Driver driver;
private Actions actions;
private static Class<?> launcherActivityClass;
static{
try{
launcherActivityClass = Class.forName(LAUNCH_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e){
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public testBookmark() throws ClassNotFoundException {
super(TARGET_PACKAGE_ID, launcherActivityClass);
}
@Override
protected void setUp() throws Exception
{
//Load config file
String configFile = FennecNativeDriver.getFile("/mnt/sdcard/robotium.config");
HashMap config = FennecNativeDriver.convertTextToTable(configFile);
//Create the intent to be used with all the important arguments
Intent i = new Intent(Intent.ACTION_MAIN);
String argsList = "-no-remote -profile " + (String)config.get("profile");
i.putExtra("args", argsList);
//Start the activity
setActivityIntent(i);
activity = getActivity();
//Set up Robotium.solo and Driver objects
solo = new Solo(getInstrumentation(), getActivity());
driver = new FennecNativeDriver(activity, solo);
actions = new FennecNativeActions(activity, solo, getInstrumentation());
driver.setLogFile((String)config.get("logfile"));
}
public void testBookmark(){
// TODO: find a better way to not hardcode this url
String url = "http://mochi.test:8888/tests/robocop/robocop.html";
Element awesomebar = driver.findElement("awesome_bar");
awesomebar.click();
Element urlbar = driver.findElement("awesomebar_text");
actions.sendKeys(url);
driver.is(url, urlbar.getText(), "Awesomebar url typed properly");
//Click the top item in the list.
actions.sendSpecialKey(Actions.SpecialKey.DOWN);
actions.sendSpecialKey(Actions.SpecialKey.ENTER);
actions.waitForGeckoEvent("DOMContentLoaded");
awesomebar.click();
driver.is(url, urlbar.getText(),"Awesomebar URL still on");
//Click the Top item in the history list.
actions.sendSpecialKey(Actions.SpecialKey.RIGHT);
actions.sendSpecialKey(Actions.SpecialKey.RIGHT);
actions.sendSpecialKey(Actions.SpecialKey.DOWN);
actions.sendSpecialKey(Actions.SpecialKey.DOWN);
actions.sendSpecialKey(Actions.SpecialKey.ENTER);
actions.waitForGeckoEvent("DOMContentLoaded");
awesomebar.click();
//Unfortunately, the item isn't constant so can't be tested.
//driver.is(url, urlbar.getText(),"Shouldn't this be the last url in the history?");
}
@Override
public void tearDown() throws Exception {
try {
solo.finalize();
}catch (Throwable e){
e.printStackTrace();
}
getActivity().finish();
super.tearDown();
}
}

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

@ -0,0 +1,96 @@
#filter substitution
package @ANDROID_PACKAGE_NAME@.tests;
import com.jayway.android.robotium.solo.Solo;
import @ANDROID_PACKAGE_NAME@.*;
import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
import android.test.PerformanceTestCase;
import android.util.Log;
import android.widget.Button;
import android.content.Intent;
import java.util.HashMap;
@SuppressWarnings("unused")
public class testLoad extends ActivityInstrumentationTestCase2 {
@SuppressWarnings("unchecked")
public testLoad(Class activityClass) {
super(activityClass);
// TODO Auto-generated constructor stub
}
private static final String TARGET_PACKAGE_ID = "org.mozilla.gecko";
private static final String LAUNCH_ACTIVITY_FULL_CLASSNAME="@ANDROID_PACKAGE_NAME@.App";
private Solo solo;
private Activity activity;
private Driver driver;
private Actions actions;
private static Class<?> launcherActivityClass;
static{
try{
launcherActivityClass = Class.forName(LAUNCH_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e){
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public testLoad() throws ClassNotFoundException {
super(TARGET_PACKAGE_ID, launcherActivityClass);
}
@Override
protected void setUp() throws Exception
{
//Load config file
String configFile = FennecNativeDriver.getFile("/mnt/sdcard/robotium.config");
HashMap config = FennecNativeDriver.convertTextToTable(configFile);
//Create the intent to be used with all the important arguments
Intent i = new Intent(Intent.ACTION_MAIN);
String argsList = "-no-remote -profile " + (String)config.get("profile");
i.putExtra("args", argsList);
//Start the activity
setActivityIntent(i);
activity = getActivity();
//Set up Robotium.solo and Driver objects
solo = new Solo(getInstrumentation(), getActivity());
driver = new FennecNativeDriver(activity, solo);
actions = new FennecNativeActions(activity, solo, getInstrumentation());
driver.setLogFile((String)config.get("logfile"));
}
public void testLoad(){
// TODO: find a better way to not hardcode this url
String url = "http://mochi.test:8888/tests/robocop/robocop.html";
Element awesomebar = driver.findElement("awesome_bar");
awesomebar.click();
Element urlbar = driver.findElement("awesomebar_text");
actions.sendKeys(url);
driver.is(url, urlbar.getText(),"Awesomebar URL Correct");
//Select top item in the list.
actions.sendSpecialKey(Actions.SpecialKey.DOWN);
actions.sendKeys("\n");
actions.waitForGeckoEvent("DOMContentLoaded");
awesomebar.click();
driver.is(url, urlbar.getText(), "Awesomebar URL is still correct");
}
@Override
public void tearDown() throws Exception {
try {
solo.finalize();
}catch (Throwable e){
e.printStackTrace();
}
getActivity().finish();
super.tearDown();
}
}

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

@ -0,0 +1,111 @@
#filter substitution
package @ANDROID_PACKAGE_NAME@.tests;
import com.jayway.android.robotium.solo.Solo;
import @ANDROID_PACKAGE_NAME@.*;
import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
import android.test.PerformanceTestCase;
import android.util.Log;
import android.widget.Button;
import android.content.Intent;
import java.util.HashMap;
@SuppressWarnings("unused")
public class testNewTab extends ActivityInstrumentationTestCase2 {
@SuppressWarnings("unchecked")
public testNewTab(Class activityClass) {
super(activityClass);
// TODO Auto-generated constructor stub
}
private static final String TARGET_PACKAGE_ID = "org.mozilla.gecko";
private static final String LAUNCH_ACTIVITY_FULL_CLASSNAME="@ANDROID_PACKAGE_NAME@.App";
private Solo solo;
private Activity activity;
private Actions actions;
private Driver driver;
private static Class<?> launcherActivityClass;
static{
try{
launcherActivityClass = Class.forName(LAUNCH_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e){
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public testNewTab() throws ClassNotFoundException {
super(TARGET_PACKAGE_ID, launcherActivityClass);
}
@Override
protected void setUp() throws Exception
{
// Load config file from sdcard (setup by python script)
String configFile = FennecNativeDriver.getFile("/mnt/sdcard/robotium.config");
HashMap config = FennecNativeDriver.convertTextToTable(configFile);
// Create the intent to be used with all the important arguments.
Intent i = new Intent(Intent.ACTION_MAIN);
String argsList = "-no-remote -profile " + (String)config.get("profile");
i.putExtra("args", argsList);
//Start the activity
setActivityIntent(i);
activity = getActivity();
//Set up Robotium.solo and Driver objects
solo = new Solo(getInstrumentation(), getActivity());
driver = new FennecNativeDriver(activity, solo);
actions = new FennecNativeActions(activity, solo, getInstrumentation());
driver.setLogFile((String)config.get("logfile"));
}
public void testNewTab(){
// TODO: find a better way to not hardcode this url
String url = "http://mochi.test:8888/tests/robocop/robocop.html";
Element tabs = driver.findElement("tabs");
//Add one tab
tabs.click();
Element urlbar = driver.findElement("awesomebar_text");
actions.sendKeys(url);
driver.is(url, urlbar.getText(),"Awesomebar url is fine");
actions.sendSpecialKey(Actions.SpecialKey.ENTER);
actions.waitForGeckoEvent("DOMContentLoaded");
try{Thread.sleep(5000);}catch(Throwable e){};
//See tab count
Element tabCount = driver.findElement("tabs_count");
driver.is("2", tabCount.getText(),"Number of tabs has increased");
//Click tab list
tabs.click();
Element addTab = driver.findElement("add_tab");
//Add another tab
addTab.click();
actions.sendKeys(url);
driver.is(url, urlbar.getText(),"URL is still fine");
actions.sendSpecialKey(Actions.SpecialKey.ENTER);
actions.waitForGeckoEvent("DOMContentLoaded");
//Check tab count another time.
driver.is("3", tabCount.getText(),"Number of tabs has increased");
}
@Override
public void tearDown() throws Exception {
try {
solo.finalize();
}catch (Throwable e){
e.printStackTrace();
}
getActivity().finish();
super.tearDown();
}
}

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

@ -0,0 +1,120 @@
#filter substitution
package @ANDROID_PACKAGE_NAME@.tests;
import com.jayway.android.robotium.solo.Solo;
import @ANDROID_PACKAGE_NAME@.*;
import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
import android.test.PerformanceTestCase;
import android.util.Log;
import android.widget.Button;
import android.content.Intent;
import java.util.HashMap;
import java.util.List;
@SuppressWarnings("unused")
public class testPan extends ActivityInstrumentationTestCase2 {
@SuppressWarnings("unchecked")
public testPan(Class activityClass) {
super(activityClass);
// TODO Auto-generated constructor stub
}
private static final String TARGET_PACKAGE_ID = "org.mozilla.gecko";
private static final String LAUNCH_ACTIVITY_FULL_CLASSNAME="@ANDROID_PACKAGE_NAME@.App";
private Solo solo;
private Activity activity;
private Driver driver;
private Actions actions;
private static Class<?> launcherActivityClass;
static{
try{
launcherActivityClass = Class.forName(LAUNCH_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e){
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public testPan() throws ClassNotFoundException {
super(TARGET_PACKAGE_ID, launcherActivityClass);
}
@Override
protected void setUp() throws Exception
{
// Load config file from sdcard (setup by python script)
String configFile = FennecNativeDriver.getFile("/mnt/sdcard/robotium.config");
HashMap config = FennecNativeDriver.convertTextToTable(configFile);
// Create the intent to be used with all the important arguments.
Intent i = new Intent(Intent.ACTION_MAIN);
String argsList = "-no-remote -profile " + (String)config.get("profile");
i.putExtra("args", argsList);
//Start the activity
setActivityIntent(i);
activity = getActivity();
//Set up Robotium.solo and Driver objects
solo = new Solo(getInstrumentation(), getActivity());
driver = new FennecNativeDriver(activity, solo);
actions = new FennecNativeActions(activity, solo, getInstrumentation());
driver.setLogFile((String)config.get("logfile"));
}
public void testPan() {
// TODO: find a better way to not hardcode this url
String url = "http://mochi.test:8888/tests/robocop/robocop.html";
Element awesomebar = driver.findElement("awesome_bar");
awesomebar.click();
Element urlbar = driver.findElement("awesomebar_text");
actions.sendKeys(url);
driver.is(url, urlbar.getText(),"Asserting Awesomebar typing works");
actions.sendSpecialKey(Actions.SpecialKey.ENTER);
actions.waitForGeckoEvent("DOMContentLoaded");
driver.setupScrollHandling();
// Setup scrolling coordinates.
int midX = driver.getGeckoLeft() + driver.getGeckoWidth()/2;
int midY = driver.getGeckoTop() + driver.getGeckoHeight()/2;
int endY = driver.getGeckoTop() + driver.getGeckoHeight()/10;
driver.startFrameRecording();
int i = 0;
// Scroll a thousand times or until the end of the page.
do {
actions.drag(midX, midX, midY, endY);
try {
Thread.sleep(200);
}
catch (InterruptedException e) {
e.printStackTrace();
}
i++;
} while( i < 1000 && driver.getScrollHeight() + 2*driver.getHeight() < driver.getPageHeight() );
driver.ok(i < 1000, "Less than 1000", "Should take less than 1000 drags to get to bottom of the page.");
int frames = driver.stopFrameRecording();
driver.dumpLog("__start_report" + Integer.toString(frames) + "__end_report");
Long msecs = System.currentTimeMillis();
driver.dumpLog("__startTimestamp" + msecs.toString() + "__endTimestamp");
}
@Override
public void tearDown() throws Exception {
try {
solo.finalize();
}catch (Throwable e){
e.printStackTrace();
}
getActivity().finish();
super.tearDown();
}
}

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

@ -332,20 +332,37 @@ var BrowserApp = {
return null;
},
loadURI: function loadURI(aURI, aParams) {
let browser = this.selectedBrowser;
if (!browser)
loadURI: function loadURI(aURI, aBrowser, aParams) {
aBrowser = aBrowser || this.selectedBrowser;
if (!aBrowser)
return;
let flags = aParams.flags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
let flags = "flags" in aParams ? aParams.flags : Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
let postData = ("postData" in aParams && aParams.postData) ? aParams.postData.value : null;
let referrerURI = "referrerURI" in aParams ? aParams.referrerURI : null;
let charset = "charset" in aParams ? aParams.charset : null;
browser.loadURIWithFlags(aURI, flags, referrerURI, charset, postData);
try {
aBrowser.loadURIWithFlags(aURI, flags, referrerURI, charset, postData);
} catch(e) {
let tab = this.getTabForBrowser(aBrowser);
if (tab) {
let message = {
gecko: {
type: "Content:LoadError",
tabID: tab.id,
uri: aBrowser.currentURI.spec,
title: aBrowser.contentTitle
}
};
sendMessageToJava(message);
dump("Handled load error: " + e)
}
}
},
addTab: function addTab(aURI, aParams) {
aParams = aParams || { selected: true };
aParams = aParams || { selected: true, flags: Ci.nsIWebNavigation.LOAD_FLAGS_NONE };
let newTab = new Tab(aURI, aParams);
this._tabs.push(newTab);
if ("selected" in aParams && aParams.selected)
@ -604,10 +621,19 @@ var BrowserApp = {
browser.reload();
} else if (aTopic == "Session:Stop") {
browser.stop();
} else if (aTopic == "Tab:Add") {
let newTab = this.addTab(this.getSearchOrFixupURI(aData));
} else if (aTopic == "Tab:Load") {
browser.loadURI(this.getSearchOrFixupURI(aData));
} else if (aTopic == "Tab:Add" || aTopic == "Tab:Load") {
// Pass LOAD_FLAGS_DISALLOW_INHERIT_OWNER to prevent any loads from
// inheriting the currently loaded document's principal.
let params = {
selected: true,
flags: Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER
};
let url = this.getSearchOrFixupURI(aData);
if (aTopic == "Tab:Add")
this.addTab(url, params);
else
this.loadURI(url, browser, params);
} else if (aTopic == "Tab:Select") {
this.selectTab(this.getTabForId(parseInt(aData)));
} else if (aTopic == "Tab:Close") {
@ -963,7 +989,7 @@ nsBrowserAccess.prototype = {
// Why does returning the browser.contentWindow not work here?
Services.io.offline = false;
browser.loadURI(aURI.spec, null, null);
BrowserApp.loadURI(aURI.spec, browser);
return null;
},
@ -1043,14 +1069,35 @@ Tab.prototype = {
Ci.nsIWebProgress.NOTIFY_SECURITY;
this.browser.addProgressListener(this, flags);
this.browser.sessionHistory.addSHistoryListener(this);
this.browser.addEventListener("DOMContentLoaded", this, true);
this.browser.addEventListener("DOMLinkAdded", this, true);
this.browser.addEventListener("DOMTitleChanged", this, true);
this.browser.addEventListener("scroll", this, true);
this.browser.addEventListener("PluginClickToPlay", this, true);
this.browser.addEventListener("pagehide", this, true);
Services.obs.addObserver(this, "http-on-modify-request", false);
this.browser.loadURI(aURL);
let flags = "flags" in aParams ? aParams.flags : Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
let postData = ("postData" in aParams && aParams.postData) ? aParams.postData.value : null;
let referrerURI = "referrerURI" in aParams ? aParams.referrerURI : null;
let charset = "charset" in aParams ? aParams.charset : null;
try {
this.browser.loadURIWithFlags(aURL, flags, referrerURI, charset, postData);
} catch(e) {
let message = {
gecko: {
type: "Content:LoadError",
tabID: this.id,
uri: this.browser.currentURI.spec,
title: this.browser.contentTitle
}
};
sendMessageToJava(message);
dump("Handled load error: " + e)
}
},
setAgentMode: function(aMode) {

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

@ -98,7 +98,7 @@ function testReturnToOwner() {
tab1 = Browser.addTab("about:blank", true);
tab2 = Browser.addTab("about:blank", true, tab1);
is(Browser.selectedTab, tab2, "tab2 is selected");
EventUtils.sendKey("ESCAPE", window);
EventUtils.sendKey("ESCAPE");
is(Browser.selectedTab, tab1, "tab1 is selected");
closeTabs();
testContextMenu();

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

@ -47,7 +47,7 @@ function closeSelect() {
let selectui = document.getElementById("select-container");
is(selectui.hidden, false, "Select UI should be open");
EventUtils.sendKey("ESCAPE", window);
EventUtils.sendKey("ESCAPE");
waitFor(tapOnMultiSelect, function() { return document.getElementById("select-container").hidden == true; });
}
@ -70,7 +70,7 @@ function onUIReady() {
is(selectui.hidden, false, "Select UI should be open");
is(SelectHelperUI._selectedIndexes, 7, "Select UI should have the 8th option selected:" + SelectHelperUI._selectedIndexes);
EventUtils.sendKey("ESCAPE", window);
EventUtils.sendKey("ESCAPE");
// Close our tab when finished
Browser.closeTab(new_tab);

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

@ -98,7 +98,7 @@ function testReturnToOwner() {
tab1 = Browser.addTab("about:blank", true);
tab2 = Browser.addTab("about:blank", true, tab1);
is(Browser.selectedTab, tab2, "tab2 is selected");
EventUtils.sendKey("ESCAPE", window);
EventUtils.sendKey("ESCAPE");
is(Browser.selectedTab, tab1, "tab1 is selected");
closeTabs();
testContextMenu();

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

@ -47,7 +47,7 @@ function closeSelect() {
let selectui = document.getElementById("select-container");
is(selectui.hidden, false, "Select UI should be open");
EventUtils.sendKey("ESCAPE", window);
EventUtils.sendKey("ESCAPE");
waitFor(tapOnMultiSelect, function() { return document.getElementById("select-container").hidden == true; });
}
@ -70,7 +70,7 @@ function onUIReady() {
is(selectui.hidden, false, "Select UI should be open");
is(SelectHelperUI._selectedIndexes, 7, "Select UI should have the 8th option selected:" + SelectHelperUI._selectedIndexes);
EventUtils.sendKey("ESCAPE", window);
EventUtils.sendKey("ESCAPE");
// Close our tab when finished
Browser.closeTab(new_tab);

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

@ -73,105 +73,39 @@ function sendMouseEvent(aEvent, aTarget, aWindow) {
}
/**
* Send the char aChar to the node with id aTarget. If aTarget is not
* provided, use "target". This method handles casing of chars (sends the
* right charcode, and sends a shift key for uppercase chars). No other
* modifiers are handled at this point.
* Send the char aChar to the focused element. This method handles casing of
* chars (sends the right charcode, and sends a shift key for uppercase chars).
* No other modifiers are handled at this point.
*
* For now this method only works for English letters (lower and upper case)
* and the digits 0-9.
*
* Returns true if the keypress event was accepted (no calls to preventDefault
* or anything like that), false otherwise.
*/
function sendChar(aChar, aTarget) {
function sendChar(aChar, aWindow) {
// DOM event charcodes match ASCII (JS charcodes) for a-zA-Z0-9.
var hasShift = (aChar == aChar.toUpperCase());
var charCode = aChar.charCodeAt(0);
var keyCode = charCode;
if (!hasShift) {
// For lowercase letters, the keyCode is actually 32 less than the charCode
keyCode -= 0x20;
}
return __doEventDispatch(aTarget, charCode, keyCode, hasShift);
synthesizeKey(aChar, { shiftKey: hasShift }, aWindow);
}
/**
* Send the string aStr to the node with id aTarget. If aTarget is not
* provided, use "target".
* Send the string aStr to the focused element.
*
* For now this method only works for English letters (lower and upper case)
* and the digits 0-9.
*/
function sendString(aStr, aTarget) {
function sendString(aStr, aWindow) {
for (var i = 0; i < aStr.length; ++i) {
sendChar(aStr.charAt(i), aTarget);
sendChar(aStr.charAt(i), aWindow);
}
}
/**
* Send the non-character key aKey to the node with id aTarget. If aTarget is
* not provided, use "target". The name of the key should be a lowercase
* version of the part that comes after "DOM_VK_" in the KeyEvent constant
* name for this key. No modifiers are handled at this point.
*
* Returns true if the keypress event was accepted (no calls to preventDefault
* or anything like that), false otherwise.
* Send the non-character key aKey to the focused node. The name of the key
* should be a lowercase version of the part that comes after "DOM_VK_" in the
* KeyEvent constant name for this key. No modifiers are handled at this point.
*/
function sendKey(aKey, aTarget) {
keyName = "DOM_VK_" + aKey.toUpperCase();
if (!KeyEvent[keyName]) {
throw "Unknown key: " + keyName;
}
return __doEventDispatch(aTarget, 0, KeyEvent[keyName], false);
}
/**
* Actually perform event dispatch given a charCode, keyCode, and boolean for
* whether "shift" was pressed. Send the event to the node with id aTarget. If
* aTarget is not provided, use "target".
*
* Returns true if the keypress event was accepted (no calls to preventDefault
* or anything like that), false otherwise.
*/
function __doEventDispatch(aTarget, aCharCode, aKeyCode, aHasShift) {
if (aTarget === undefined) {
aTarget = "target";
}
var event = document.createEvent("KeyEvents");
event.initKeyEvent("keydown", true, true, document.defaultView,
false, false, aHasShift, false,
aKeyCode, 0);
var accepted = SpecialPowers.dispatchEvent(window, aTarget, event);
// Preventing the default keydown action also prevents the default
// keypress action.
event = document.createEvent("KeyEvents");
if (aCharCode) {
event.initKeyEvent("keypress", true, true, document.defaultView,
false, false, aHasShift, false,
0, aCharCode);
} else {
event.initKeyEvent("keypress", true, true, document.defaultView,
false, false, aHasShift, false,
aKeyCode, 0);
}
if (!accepted) {
event.preventDefault();
}
accepted = SpecialPowers.dispatchEvent(window, aTarget, event);
// Always send keyup
var event = document.createEvent("KeyEvents");
event.initKeyEvent("keyup", true, true, document.defaultView,
false, false, aHasShift, false,
aKeyCode, 0);
SpecialPowers.dispatchEvent(window, aTarget, event);
return accepted;
function sendKey(aKey, aWindow) {
keyName = "VK_" + aKey.toUpperCase();
synthesizeKey(keyName, { shiftKey: false }, aWindow);
}
/**
@ -393,9 +327,12 @@ function synthesizeKey(aKey, aEvent, aWindow)
var utils = _getDOMWindowUtils(aWindow);
if (utils) {
var keyCode = 0, charCode = 0;
if (aKey.indexOf("VK_") == 0)
if (aKey.indexOf("VK_") == 0) {
keyCode = KeyEvent["DOM_" + aKey];
else {
if (!keyCode) {
throw "Unknown key: " + aKey;
}
} else {
charCode = aKey.charCodeAt(0);
keyCode = _computeKeyCodeFromChar(aKey.charAt(0));
}
@ -410,6 +347,7 @@ function synthesizeKey(aKey, aEvent, aWindow)
} else {
var keyDownDefaultHappened =
utils.sendKeyEvent("keydown", keyCode, 0, modifiers);
// XXX Shouldn't dispatch keypress event if the key is a modifier key.
utils.sendKeyEvent("keypress", charCode ? 0 : keyCode, charCode,
modifiers, !keyDownDefaultHappened);
utils.sendKeyEvent("keyup", keyCode, 0, modifiers);

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

@ -44,13 +44,13 @@ is(press2, true, "synthesizeKey should dispatch keyPress with default prevented"
var press3 = false;
$("testKeyEvent3").focus();
sendChar("x", "testKeyEvent3")
sendChar("x")
is($("testKeyEvent3").value, "x", "sendChar should work");
is(press3, true, "sendChar should dispatch keyPress");
var press4 = false;
$("testKeyEvent4").focus();
sendChar("x", "testKeyEvent4")
sendChar("x")
is($("testKeyEvent4").value, "", "sendChar should respect keydown preventDefault");
is(press4, true, "sendChar should dispatch keyPress with default prevented");

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

@ -46,17 +46,19 @@ function starttest() {
check = false;
$("testKeyEvent").addEventListener("keypress", function() { check = true; }, false);
$("testKeyEvent").focus();
sendChar("x", "testKeyEvent");
sendChar("x");
is($("testKeyEvent").value, "x", "sendChar should work");
is(check, true, "sendChar should dispatch keyPress");
$("testKeyEvent").value = "";
sendString("string", "testStrEvent");
$("testStrEvent").focus();
sendString("string");
is($("testStrEvent").value, "string", "sendString should work");
$("testStrEvent").value = "";
check = false;
sendKey("DOWN", "testKeyEvent");
$("testKeyEvent").focus();
sendKey("DOWN");
is(check, true, "sendKey should dispatch keyPress");
/* test synthesizeMouse* */

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

@ -643,7 +643,7 @@ function runTest(testNum) {
// the username.
uname.focus();
doKey("right");
sendChar("X", uname);
sendChar("X");
// Trigger the 'blur' event on uname
pword.focus();
checkACForm("sXingleuser5", "singlepass5");
@ -722,14 +722,15 @@ function runTest(testNum) {
pwmgr.removeLogin(login7);
testNum = 699;
gNextTestWillOpenPopup = false;
gNextTestWillOpenPopup = true;
break;
case 700:
// Turn our attention to form9 to test the dropdown - bug 497541
uname = $_(9, "uname");
pword = $_(9, "pword");
sendString("form9userAB", uname);
uname.focus();
sendString("form9userAB");
gNextTestWillOpenPopup = true;
break;
@ -737,7 +738,7 @@ function runTest(testNum) {
checkACForm("form9userAB", "");
uname.focus();
doKey("left");
sendChar("A", uname);
sendChar("A");
gNextTestWillOpenPopup = false;
break;
@ -753,7 +754,8 @@ function runTest(testNum) {
case 703:
pwmgr.addLogin(login8C);
sendChar("z", uname);
uname.focus();
sendChar("z");
gNextTestWillOpenPopup = false;
break;

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

@ -477,19 +477,22 @@ function runTest(testNum) {
input = $_(5, "field3");
restoreForm();
testNum = 199;
sendChar("a", input);
input.focus();
sendChar("a");
break;
/* Test filtering as characters are typed. */
case 200:
checkMenuEntries(["a", "aa", "aaz", "aa\xe6", "az"]);
sendChar("a", input);
input.focus();
sendChar("a");
break;
case 201:
checkMenuEntries(["aa", "aaz", "aa\xe6"]);
sendChar("\xc6", input);
input.focus();
sendChar("\xc6");
break;
case 202:
@ -504,27 +507,31 @@ function runTest(testNum) {
case 204:
checkMenuEntries(["a", "aa", "aaz", "aa\xe6", "az"]);
sendChar("z", input);
input.focus();
sendChar("z");
break;
case 205:
ok(getMenuEntries().length > 0, "checking typing in middle of text");
input.focus();
doKey("left");
sendChar("a", input);
sendChar("a");
break;
case 206:
checkMenuEntries(["aaz"]);
fh.addEntry("field3", "aazq");
input.focus();
doKey("right");
sendChar("q", input);
sendChar("q");
break;
case 207:
// check that results were cached
checkMenuEntries([]);
fh.addEntry("field3", "aazqq");
sendChar("q", input);
input.focus();
sendChar("q");
break;
case 208:
@ -536,7 +543,8 @@ function runTest(testNum) {
input = $_(6, "field4");
restoreForm();
testNum = 249;
sendChar("a", input);
input.focus();
sendChar("a");
break;
/* Test substring matches and word boundary bonuses */
@ -544,7 +552,8 @@ function runTest(testNum) {
case 250:
// alphabetical results for first character
checkMenuEntries(["aa a\xe6", "aba\xe6", "a\xe6"]);
sendChar("\xc6", input);
input.focus();
sendChar("\xc6");
break;
case 251:
@ -553,31 +562,36 @@ function runTest(testNum) {
checkMenuEntries(["a\xe6", "aa a\xe6", "aba\xe6"]);
restoreForm();
sendChar("b", input);
input.focus();
sendChar("b");
break;
case 252:
checkMenuEntries(["bc d\xe6"]);
sendChar(" ", input);
input.focus();
sendChar(" ");
break;
case 253:
// check that trailing space has no effect after single char.
checkMenuEntries(["bc d\xe6"]);
sendChar("\xc6", input);
input.focus();
sendChar("\xc6");
break;
case 254:
// check multi-word substring matches
checkMenuEntries(["bc d\xe6", "aba\xe6"]);
input.focus();
doKey("left");
sendChar("d", input);
sendChar("d");
break;
case 255:
// check inserting in multi-word searches
checkMenuEntries(["bc d\xe6"]);
sendChar("z", input);
input.focus();
sendChar("z");
break;
case 256:
@ -630,7 +644,8 @@ function runTest(testNum) {
input.maxLength = 4;
// now again with a character typed
sendChar("1", input);
input.focus();
sendChar("1");
doKey("escape");
doKey("down");
break;

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

@ -111,6 +111,17 @@ struct TelemetryHistogram {
PRUint32 histogramType;
};
// Perform the checks at the beginning of HistogramGet at compile time, so
// that if people add incorrect histogram definitions, they get compiler
// errors.
#define HISTOGRAM(id, min, max, bucket_count, histogram_type, b) \
PR_STATIC_ASSERT(nsITelemetry::HISTOGRAM_ ## histogram_type == nsITelemetry::HISTOGRAM_BOOLEAN || \
(min < max && bucket_count > 2 && min >= 1));
#include "TelemetryHistograms.h"
#undef HISTOGRAM
const TelemetryHistogram gHistograms[] = {
#define HISTOGRAM(id, min, max, bucket_count, histogram_type, b) \
{ NULL, NS_STRINGIFY(id), min, max, bucket_count, nsITelemetry::HISTOGRAM_ ## histogram_type },

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

@ -70,7 +70,7 @@ HISTOGRAM(CYCLE_COLLECTOR_COLLECTED, 1, 100000, 50, EXPONENTIAL, "Number of obje
/**
* GC telemetry
*/
HISTOGRAM(GC_REASON, 0, 20, 20, LINEAR, "Reason (enum value) for initiating a GC")
HISTOGRAM(GC_REASON, 1, 20, 20, LINEAR, "Reason (enum value) for initiating a GC")
HISTOGRAM_BOOLEAN(GC_IS_COMPARTMENTAL, "Is it a compartmental GC?")
HISTOGRAM_BOOLEAN(GC_IS_SHAPE_REGEN, "Is it a shape regenerating GC?")
HISTOGRAM(GC_MS, 1, 10000, 50, EXPONENTIAL, "Time spent running JS GC (ms)")
@ -273,7 +273,7 @@ HISTOGRAM(PLACES_AUTOCOMPLETE_1ST_RESULT_TIME_MS, 50, 500, 10, EXPONENTIAL, "PLA
/**
* Updater telemetry.
*/
HISTOGRAM(UPDATE_STATUS, 0, 16004, 18, LINEAR, "Updater: the status of the latest update performed")
HISTOGRAM(UPDATE_STATUS, 1, 16004, 18, LINEAR, "Updater: the status of the latest update performed")
/**
* Thunderbird-specific telemetry.

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

@ -44,19 +44,20 @@ SimpleTest.waitForExplicitFinish();
function testListbox(id)
{
var listbox = document.getElementById(id);
listbox.focus();
is(listbox.getRowCount(), 7, id + ": Returned the wrong number of rows");
is(listbox.getItemAtIndex(2).id, id + "_item3", id + ": Should still return hidden items");
listbox.selectedIndex = 0;
is(listbox.selectedItem.id, id + "_item1", id + ": First item was not selected");
sendKey("DOWN", id);
sendKey("DOWN");
is(listbox.selectedItem.id, id + "_item2", id + ": Down didn't move to second item");
sendKey("DOWN", id);
sendKey("DOWN");
is(listbox.selectedItem.id, id + "_item4", id + ": Down didn't skip hidden item");
sendKey("DOWN", id);
sendKey("DOWN");
is(listbox.selectedItem.id, id + "_item6", id + ": Down didn't skip collapsed item");
sendKey("UP", id);
sendKey("UP");
is(listbox.selectedItem.id, id + "_item4", id + ": Up didn't skip collapsed item");
sendKey("UP", id);
sendKey("UP");
is(listbox.selectedItem.id, id + "_item2", id + ": Up didn't skip hidden item");
listbox.selectAll();
is(listbox.selectedItems.length, 7, id + ": Should have still selected all items");
@ -65,7 +66,7 @@ function testListbox(id)
listbox.selectedIndex = 2;
ok(listbox.selectedItem == listbox.getItemAtIndex(2), id + ": Should have selected the hidden item");
listbox.selectedIndex = 0;
sendKey("END", id);
sendKey("END");
is(listbox.selectedItem.id, id + "_item6", id + ": Should have moved to the last unhidden item");
sendMouseEvent({type: 'click'}, id + "_item1");
ok(listbox.selectedItem == listbox.getItemAtIndex(0), id + ": Should have selected the first item");
@ -73,9 +74,9 @@ function testListbox(id)
sendMouseEvent({type: 'click', shiftKey: true}, id + "_item6");
is(listbox.selectedItems.length, 4, id + ": Should have selected all visible items");
listbox.selectedIndex = 0;
sendKey("PAGE_DOWN", id);
sendKey("PAGE_DOWN");
is(listbox.selectedItem.id, id + "_item6", id + ": Page down should go to the last visible item");
sendKey("PAGE_UP", id);
sendKey("PAGE_UP");
is(listbox.selectedItem.id, id + "_item1", id + ": Page up should go to the first visible item");
}

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

@ -71,23 +71,24 @@ function testRichlistbox()
{
var id = "richlistbox";
var listbox = document.getElementById(id);
listbox.focus();
listbox.selectedIndex = 0;
sendKey("PAGE_DOWN", id);
sendKey("PAGE_DOWN");
is(listbox.selectedItem.id, id + "_item7", id + ": Page down should go to the item one visible page away");
is(listbox.getIndexOfFirstVisibleRow(), 6, id + ": Page down should have scrolled down a visible page");
sendKey("PAGE_DOWN", id);
sendKey("PAGE_DOWN");
is(listbox.selectedItem.id, id + "_item11", id + ": Second page down should go to the item two visible pages away");
is(listbox.getIndexOfFirstVisibleRow(), 9, id + ": Second page down should not scroll beyond the end");
sendKey("PAGE_DOWN", id);
sendKey("PAGE_DOWN");
is(listbox.selectedItem.id, id + "_item14", id + ": Third page down should go to the last visible item");
is(listbox.getIndexOfFirstVisibleRow(), 9, id + ": Third page down should not have scrolled at all");
sendKey("PAGE_UP", id);
sendKey("PAGE_UP");
is(listbox.selectedItem.id, id + "_item10", id + ": Page up should go to the item one visible page away");
is(listbox.getIndexOfFirstVisibleRow(), 5, id + ": Page up should scroll up a visible page");
sendKey("PAGE_UP", id);
sendKey("PAGE_UP");
is(listbox.selectedItem.id, id + "_item6", id + ": Second page up should go to the item two visible pages away");
is(listbox.getIndexOfFirstVisibleRow(), 0, id + ": Second page up should not scroll beyond the start");
sendKey("PAGE_UP", id);
sendKey("PAGE_UP");
is(listbox.selectedItem.id, id + "_item1", id + ": Third page up should return to the first visible item");
is(listbox.getIndexOfFirstVisibleRow(), 0, id + ": Third page up should not have scrolled at all");
}
@ -105,24 +106,25 @@ function testListbox()
var rowHeight = listbox.firstChild.getBoundingClientRect().height;
listbox.focus();
listbox.selectedIndex = 0;
sendKey("PAGE_DOWN", id);
sendKey("PAGE_DOWN");
is(listbox.selectedItem.id, id + "_item8", id + ": Page down should go to the item one visible page away");
is(listbox.getIndexOfFirstVisibleRow(), 7, id + ": Page down should have scrolled down a visible page");
sendKey("PAGE_DOWN", id);
sendKey("PAGE_DOWN");
is(listbox.selectedItem.id, id + "_item13", id + ": Second page down should go to the item two visible pages away");
is(listbox.getIndexOfFirstVisibleRow(), 9, id + ": Second page down should not scroll beyond the end");
sendKey("PAGE_DOWN", id);
sendKey("PAGE_DOWN");
is(listbox.selectedItem.id, id + "_item14", id + ": Third page down should go to the last visible item");
is(listbox.getIndexOfFirstVisibleRow(), 9, id + ": Third page down should not have scrolled at all");
sendKey("PAGE_UP", id);
sendKey("PAGE_UP");
is(listbox.selectedItem.id, id + "_item9", id + ": Page up should go to the item one visible page away");
// the listScrollbox seems to go haywire when scrolling up with hidden listitems
todo_is(listbox.getIndexOfFirstVisibleRow(), 3, id + ": Page up should scroll up a visible page");
sendKey("PAGE_UP", id);
sendKey("PAGE_UP");
is(listbox.selectedItem.id, id + "_item2", id + ": Second page up should go to the item two visible pages away");
is(listbox.getIndexOfFirstVisibleRow(), 0, id + ": Second page up should not scroll beyond the start");
sendKey("PAGE_UP", id);
sendKey("PAGE_UP");
is(listbox.selectedItem.id, id + "_item1", id + ": Third page up should return to the first visible item");
is(listbox.getIndexOfFirstVisibleRow(), 0, id + ": Third page up should not have scrolled at all");

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

@ -46,24 +46,25 @@ function test_richlistbox()
// richlistboxes respond differently when a user initiates a selection
richListBox.dir = "reverse";
var count = richListBox.itemCount;
richListBox.focus();
richListBox.selectedIndex = count - 1;
sendKey("DOWN", richListBox);
sendKey("DOWN");
is(richListBox.currentIndex, count - 2, "Selection should move to the next item");
sendKey("UP", richListBox);
sendKey("UP");
is(richListBox.currentIndex, count - 1, "Selection should move to the previous item");
sendKey("END", richListBox);
sendKey("END");
is(richListBox.currentIndex, 0, "Selection should move to the last item");
sendKey("HOME", richListBox);
sendKey("HOME");
is(richListBox.currentIndex, count - 1, "Selection should move to the first item");
var currentIndex = richListBox.currentIndex;
var index = getScrollIndexAmount(-1);
sendKey("PAGE_DOWN", richListBox);
sendKey("PAGE_DOWN");
is(richListBox.currentIndex, index, "Selection should move to one page down");
ok(richListBox.currentIndex < currentIndex, "Selection should move downwards");
sendKey("END", richListBox);
sendKey("END");
currentIndex = richListBox.currentIndex;
index = getScrollIndexAmount(1);
sendKey("PAGE_UP", richListBox);
sendKey("PAGE_UP");
is(richListBox.currentIndex, index, "Selection should move to one page up");
ok(richListBox.currentIndex > currentIndex, "Selection should move upwards");
richListBox.selectedItem = richListBox.lastChild;
@ -87,29 +88,29 @@ function test_richlistbox()
aEvent.preventDefault();
}, true);
richListBox.selectedIndex = 1;
sendKey("HOME", richListBox);
sendKey("HOME");
is(richListBox.selectedIndex, 1, "A stopped event should return indexing to normal");
// direction = "normal"
richListBox.dir = "normal";
richListBox.selectedIndex = 0;
sendKey("DOWN", richListBox);
sendKey("DOWN");
is(richListBox.currentIndex, 1, "Selection should move to the next item");
sendKey("UP", richListBox);
sendKey("UP");
is(richListBox.currentIndex, 0, "Selection should move to the previous item");
sendKey("END", richListBox);
sendKey("END");
is(richListBox.currentIndex, count - 1, "Selection should move to the last item");
sendKey("HOME", richListBox);
sendKey("HOME");
is(richListBox.currentIndex, 0, "Selection should move to the first item");
var currentIndex = richListBox.currentIndex;
var index = richListBox.scrollOnePage(1);
sendKey("PAGE_DOWN", richListBox);
sendKey("PAGE_DOWN");
is(richListBox.currentIndex, index, "Selection should move to one page down");
ok(richListBox.currentIndex > currentIndex, "Selection should move downwards");
sendKey("END", richListBox);
sendKey("END");
currentIndex = richListBox.currentIndex;
index = richListBox.scrollOnePage(-1) + richListBox.currentIndex;
sendKey("PAGE_UP", richListBox);
sendKey("PAGE_UP");
is(richListBox.currentIndex, index, "Selection should move to one page up");
ok(richListBox.currentIndex < currentIndex, "Selection should move upwards");
richListBox.selectedItem = richListBox.firstChild;

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

@ -111,7 +111,9 @@
if (!toolbox)
throw("toolboxid attribute points to a toolbox which doesn't exist");
toolbox.externalToolbars.push(this);
if (toolbox.externalToolbars.indexOf(this) == -1)
toolbox.externalToolbars.push(this);
return this._toolbox = toolbox;
}

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

@ -0,0 +1,149 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "AndroidDirectTexture.h"
typedef gfxASurface::gfxImageFormat gfxImageFormat;
namespace mozilla {
AndroidDirectTexture::AndroidDirectTexture(PRUint32 width, PRUint32 height, PRUint32 usage,
gfxImageFormat format) :
mLock("AndroidDirectTexture.mLock")
, mNeedFlip(false)
, mWidth(width)
, mHeight(height)
, mFormat(format)
, mPendingReallocBuffer(NULL)
{
mFrontBuffer = new AndroidGraphicBuffer(width, height, usage, format);
mBackBuffer = new AndroidGraphicBuffer(width, height, usage, format);
}
AndroidDirectTexture::~AndroidDirectTexture()
{
if (mFrontBuffer) {
delete mFrontBuffer;
mFrontBuffer = NULL;
}
if (mBackBuffer) {
delete mBackBuffer;
mBackBuffer = NULL;
}
}
void
AndroidDirectTexture::ReallocPendingBuffer()
{
// We may have reallocated while the current back buffer was being
// used as the front buffer. If we have such a reallocation pending
// and the current back buffer is the target buffer, do it now.
//
// It is assumed that mLock is already acquired
if (mPendingReallocBuffer == mBackBuffer) {
mBackBuffer->Reallocate(mWidth, mHeight, mFormat);
mPendingReallocBuffer = NULL;
}
}
bool
AndroidDirectTexture::Lock(PRUint32 aUsage, unsigned char **bits)
{
mLock.Lock();
ReallocPendingBuffer();
return mBackBuffer->Lock(aUsage, bits);
}
bool
AndroidDirectTexture::Lock(PRUint32 aUsage, const nsIntRect& aRect, unsigned char **bits)
{
mLock.Lock();
ReallocPendingBuffer();
return mBackBuffer->Lock(aUsage, aRect, bits);
}
bool
AndroidDirectTexture::Unlock(bool aFlip)
{
if (aFlip) {
mNeedFlip = true;
}
bool result = mBackBuffer->Unlock();
mLock.Unlock();
return result;
}
bool
AndroidDirectTexture::Reallocate(PRUint32 aWidth, PRUint32 aHeight) {
return Reallocate(aWidth, aHeight, mFormat);
}
bool
AndroidDirectTexture::Reallocate(PRUint32 aWidth, PRUint32 aHeight, gfxASurface::gfxImageFormat aFormat)
{
MutexAutoLock lock(mLock);
// We only reallocate the current back buffer. The front buffer is likely
// in use, so we'll reallocate it on the first Lock() after it is rotated
// to the back.
bool result = mBackBuffer->Reallocate(aWidth, aHeight, aFormat);
if (result) {
mPendingReallocBuffer = mFrontBuffer;
}
return result;
}
bool
AndroidDirectTexture::Bind()
{
MutexAutoLock lock(mLock);
if (mNeedFlip) {
AndroidGraphicBuffer* tmp = mBackBuffer;
mBackBuffer = mFrontBuffer;
mFrontBuffer = tmp;
mNeedFlip = false;
}
return mFrontBuffer->Bind();
}
} /* mozilla */

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

@ -0,0 +1,90 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef AndroidDirectTexture_h_
#define AndroidDirectTexture_h_
#include "gfxASurface.h"
#include "nsRect.h"
#include "mozilla/Mutex.h"
#include "AndroidGraphicBuffer.h"
namespace mozilla {
/**
* This is a thread safe wrapper around AndroidGraphicBuffer that handles
* double buffering. Each call to Bind() flips the buffer when necessary.
*
* You need to be careful when destroying an instance of this class. If either
* buffer is locked by the application of the driver/hardware, bad things will
* happen. Be sure that the OpenGL texture is no longer on the screen.
*/
class AndroidDirectTexture
{
public:
AndroidDirectTexture(PRUint32 width, PRUint32 height, PRUint32 usage, gfxASurface::gfxImageFormat format);
virtual ~AndroidDirectTexture();
bool Lock(PRUint32 usage, unsigned char **bits);
bool Lock(PRUint32 usage, const nsIntRect& rect, unsigned char **bits);
bool Unlock(bool aFlip = true);
bool Reallocate(PRUint32 aWidth, PRUint32 aHeight);
bool Reallocate(PRUint32 aWidth, PRUint32 aHeight, gfxASurface::gfxImageFormat aFormat);
PRUint32 Width() { return mWidth; }
PRUint32 Height() { return mHeight; }
bool Bind();
private:
mozilla::Mutex mLock;
bool mNeedFlip;
PRUint32 mWidth;
PRUint32 mHeight;
gfxASurface::gfxImageFormat mFormat;
AndroidGraphicBuffer* mFrontBuffer;
AndroidGraphicBuffer* mBackBuffer;
AndroidGraphicBuffer* mPendingReallocBuffer;
void ReallocPendingBuffer();
};
} /* mozilla */
#endif /* AndroidDirectTexture_h_ */

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

@ -0,0 +1,433 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <dlfcn.h>
#include <android/log.h>
#include <GLES2/gl2.h>
#include "AndroidGraphicBuffer.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AndroidGraphicBuffer" , ## args)
#define EGL_NATIVE_BUFFER_ANDROID 0x3140
#define EGL_IMAGE_PRESERVED_KHR 0x30D2
typedef void* EGLContext;
typedef void* EGLImageKHR;
typedef void* EGLClientBuffer;
typedef void* EGLDisplay;
typedef PRUint32 EGLenum;
typedef PRInt32 EGLint;
typedef PRUint32 EGLBoolean;
typedef gfxASurface::gfxImageFormat gfxImageFormat;
#define EGL_TRUE 1
#define EGL_FALSE 0
#define EGL_NONE 0x3038
#define EGL_NO_CONTEXT (EGLContext)0
#define EGL_DEFAULT_DISPLAY (void*)0
#define ANDROID_LIBUI_PATH "/system/lib/libui.so"
#define ANDROID_GLES_PATH "/system/lib/libGLESv2.so"
#define ANDROID_EGL_PATH "/system/lib/libEGL.so"
// Really I have no idea, but this should be big enough
#define GRAPHIC_BUFFER_SIZE 1024
enum {
/* buffer is never read in software */
GRALLOC_USAGE_SW_READ_NEVER = 0x00000000,
/* buffer is rarely read in software */
GRALLOC_USAGE_SW_READ_RARELY = 0x00000002,
/* buffer is often read in software */
GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003,
/* mask for the software read values */
GRALLOC_USAGE_SW_READ_MASK = 0x0000000F,
/* buffer is never written in software */
GRALLOC_USAGE_SW_WRITE_NEVER = 0x00000000,
/* buffer is never written in software */
GRALLOC_USAGE_SW_WRITE_RARELY = 0x00000020,
/* buffer is never written in software */
GRALLOC_USAGE_SW_WRITE_OFTEN = 0x00000030,
/* mask for the software write values */
GRALLOC_USAGE_SW_WRITE_MASK = 0x000000F0,
/* buffer will be used as an OpenGL ES texture */
GRALLOC_USAGE_HW_TEXTURE = 0x00000100,
/* buffer will be used as an OpenGL ES render target */
GRALLOC_USAGE_HW_RENDER = 0x00000200,
/* buffer will be used by the 2D hardware blitter */
GRALLOC_USAGE_HW_2D = 0x00000400,
/* buffer will be used with the framebuffer device */
GRALLOC_USAGE_HW_FB = 0x00001000,
/* mask for the software usage bit-mask */
GRALLOC_USAGE_HW_MASK = 0x00001F00,
};
enum {
HAL_PIXEL_FORMAT_RGBA_8888 = 1,
HAL_PIXEL_FORMAT_RGBX_8888 = 2,
HAL_PIXEL_FORMAT_RGB_888 = 3,
HAL_PIXEL_FORMAT_RGB_565 = 4,
HAL_PIXEL_FORMAT_BGRA_8888 = 5,
HAL_PIXEL_FORMAT_RGBA_5551 = 6,
HAL_PIXEL_FORMAT_RGBA_4444 = 7,
};
typedef struct AndroidRect {
int32_t left;
int32_t top;
int32_t right;
int32_t bottom;
} AndroidRect;
static bool gTryRealloc = true;
static class GLFunctions
{
public:
GLFunctions() : mInitialized(false)
{
}
typedef EGLDisplay (* pfnGetDisplay)(void *display_id);
pfnGetDisplay fGetDisplay;
typedef EGLint (* pfnEGLGetError)(void);
pfnEGLGetError fEGLGetError;
typedef EGLImageKHR (* pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
pfnCreateImageKHR fCreateImageKHR;
typedef EGLBoolean (* pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image);
pfnDestroyImageKHR fDestroyImageKHR;
typedef void (* pfnImageTargetTexture2DOES)(GLenum target, EGLImageKHR image);
pfnImageTargetTexture2DOES fImageTargetTexture2DOES;
typedef void (* pfnBindTexture)(GLenum target, GLuint texture);
pfnBindTexture fBindTexture;
typedef GLenum (* pfnGLGetError)();
pfnGLGetError fGLGetError;
typedef void (*pfnGraphicBufferCtor)(void*, PRUint32 w, PRUint32 h, PRUint32 format, PRUint32 usage);
pfnGraphicBufferCtor fGraphicBufferCtor;
typedef void (*pfnGraphicBufferDtor)(void*);
pfnGraphicBufferDtor fGraphicBufferDtor;
typedef int (*pfnGraphicBufferLock)(void*, PRUint32 usage, unsigned char **addr);
pfnGraphicBufferLock fGraphicBufferLock;
typedef int (*pfnGraphicBufferLockRect)(void*, PRUint32 usage, const AndroidRect&, unsigned char **addr);
pfnGraphicBufferLockRect fGraphicBufferLockRect;
typedef int (*pfnGraphicBufferUnlock)(void*);
pfnGraphicBufferUnlock fGraphicBufferUnlock;
typedef void* (*pfnGraphicBufferGetNativeBuffer)(void*);
pfnGraphicBufferGetNativeBuffer fGraphicBufferGetNativeBuffer;
typedef int (*pfnGraphicBufferReallocate)(void*, PRUint32 w, PRUint32 h, PRUint32 format);
pfnGraphicBufferReallocate fGraphicBufferReallocate;
bool EnsureInitialized()
{
if (mInitialized) {
return true;
}
void *handle = dlopen(ANDROID_EGL_PATH, RTLD_LAZY);
if (!handle) {
LOG("Couldn't load EGL library");
return false;
}
fGetDisplay = (pfnGetDisplay)dlsym(handle, "eglGetDisplay");
fEGLGetError = (pfnEGLGetError)dlsym(handle, "eglGetError");
fCreateImageKHR = (pfnCreateImageKHR)dlsym(handle, "eglCreateImageKHR");
fDestroyImageKHR = (pfnDestroyImageKHR)dlsym(handle, "eglDestroyImageKHR");
if (!fGetDisplay || !fEGLGetError || !fCreateImageKHR || !fDestroyImageKHR) {
LOG("Failed to find some EGL functions");
return false;
}
handle = dlopen(ANDROID_GLES_PATH, RTLD_LAZY);
if (!handle) {
LOG("Couldn't load GL library");
return false;
}
fImageTargetTexture2DOES = (pfnImageTargetTexture2DOES)dlsym(handle, "glEGLImageTargetTexture2DOES");
fBindTexture = (pfnBindTexture)dlsym(handle, "glBindTexture");
fGLGetError = (pfnGLGetError)dlsym(handle, "glGetError");
if (!fImageTargetTexture2DOES || !fBindTexture || !fGLGetError) {
LOG("Failed to find some GL functions");
return false;
}
handle = dlopen(ANDROID_LIBUI_PATH, RTLD_LAZY);
if (!handle) {
LOG("Couldn't load libui.so");
return false;
}
fGraphicBufferCtor = (pfnGraphicBufferCtor)dlsym(handle, "_ZN7android13GraphicBufferC1Ejjij");
fGraphicBufferDtor = (pfnGraphicBufferDtor)dlsym(handle, "_ZN7android13GraphicBufferD1Ev");
fGraphicBufferLock = (pfnGraphicBufferLock)dlsym(handle, "_ZN7android13GraphicBuffer4lockEjPPv");
fGraphicBufferLockRect = (pfnGraphicBufferLockRect)dlsym(handle, "_ZN7android13GraphicBuffer4lockEjRKNS_4RectEPPv");
fGraphicBufferUnlock = (pfnGraphicBufferUnlock)dlsym(handle, "_ZN7android13GraphicBuffer6unlockEv");
fGraphicBufferGetNativeBuffer = (pfnGraphicBufferGetNativeBuffer)dlsym(handle, "_ZNK7android13GraphicBuffer15getNativeBufferEv");
fGraphicBufferReallocate = (pfnGraphicBufferReallocate)dlsym(handle, "_ZN7android13GraphicBuffer10reallocateEjjij");
if (!fGraphicBufferCtor || !fGraphicBufferDtor || !fGraphicBufferLock ||
!fGraphicBufferUnlock || !fGraphicBufferGetNativeBuffer) {
LOG("Failed to lookup some GraphicBuffer functions");
return false;
}
mInitialized = true;
return true;
}
private:
bool mInitialized;
} sGLFunctions;
namespace mozilla {
static bool ensureNoGLError(const char* name)
{
bool result = true;
GLuint error;
while ((error = glGetError()) != GL_NO_ERROR) {
LOG("GL error [%s]: %40x\n", name, error);
result = false;
}
return result;
}
AndroidGraphicBuffer::AndroidGraphicBuffer(PRUint32 width, PRUint32 height, PRUint32 usage,
gfxImageFormat format) :
mWidth(width)
, mHeight(height)
, mUsage(usage)
, mFormat(format)
, mHandle(0)
, mEGLImage(0)
{
}
AndroidGraphicBuffer::~AndroidGraphicBuffer()
{
DestroyBuffer();
}
void
AndroidGraphicBuffer::DestroyBuffer()
{
if (mHandle) {
if (sGLFunctions.EnsureInitialized()) {
sGLFunctions.fGraphicBufferDtor(mHandle);
}
free(mHandle);
mHandle = NULL;
}
if (mEGLImage) {
if (sGLFunctions.EnsureInitialized()) {
sGLFunctions.fDestroyImageKHR(sGLFunctions.fGetDisplay(EGL_DEFAULT_DISPLAY), mEGLImage);
mEGLImage = NULL;
}
}
}
bool
AndroidGraphicBuffer::EnsureBufferCreated(PRUint32 aWidth, PRUint32 aHeight, PRUint32 aUsage, gfxImageFormat aFormat)
{
if (!mHandle) {
mHandle = malloc(GRAPHIC_BUFFER_SIZE);
sGLFunctions.fGraphicBufferCtor(mHandle, mWidth, mHeight, GetAndroidFormat(aFormat), GetAndroidUsage(aUsage));
}
return true;
}
bool
AndroidGraphicBuffer::EnsureInitialized()
{
if (!sGLFunctions.EnsureInitialized()) {
return false;
}
EnsureBufferCreated(mWidth, mHeight, mUsage, mFormat);
return true;
}
bool
AndroidGraphicBuffer::Lock(PRUint32 aUsage, unsigned char **bits)
{
if (!EnsureInitialized())
return true;
return sGLFunctions.fGraphicBufferLock(mHandle, GetAndroidUsage(aUsage), bits) == 0;
}
bool
AndroidGraphicBuffer::Lock(PRUint32 aUsage, const nsIntRect& aRect, unsigned char **bits)
{
if (!EnsureInitialized())
return false;
AndroidRect rect;
rect.left = aRect.x;
rect.top = aRect.y;
rect.right = aRect.x + aRect.width;
rect.bottom = aRect.y + aRect.height;
return sGLFunctions.fGraphicBufferLockRect(mHandle, GetAndroidUsage(aUsage), rect, bits) == 0;
}
bool
AndroidGraphicBuffer::Unlock()
{
if (!EnsureInitialized())
return false;
return sGLFunctions.fGraphicBufferUnlock(mHandle) == 0;
}
bool
AndroidGraphicBuffer::Reallocate(PRUint32 aWidth, PRUint32 aHeight, gfxImageFormat aFormat)
{
if (!EnsureInitialized())
return false;
// Sometimes GraphicBuffer::reallocate just doesn't work. In those cases we'll just allocate a brand
// new buffer. If reallocate fails once, never try it again.
if (!gTryRealloc || sGLFunctions.fGraphicBufferReallocate(mHandle, aWidth, aHeight, GetAndroidFormat(aFormat)) != 0) {
DestroyBuffer();
EnsureBufferCreated(aWidth, aHeight, mUsage, aFormat);
gTryRealloc = false;
}
mWidth = aWidth;
mHeight = aHeight;
mFormat = aFormat;
return true;
}
PRUint32
AndroidGraphicBuffer::GetAndroidUsage(PRUint32 aUsage)
{
PRUint32 flags = 0;
if (aUsage & UsageSoftwareRead) {
flags |= GRALLOC_USAGE_SW_READ_OFTEN;
}
if (aUsage & UsageSoftwareWrite) {
flags |= GRALLOC_USAGE_SW_WRITE_OFTEN;
}
if (aUsage & UsageTexture) {
flags |= GRALLOC_USAGE_HW_TEXTURE;
}
if (aUsage & UsageTarget) {
flags |= GRALLOC_USAGE_HW_RENDER;
}
if (aUsage & Usage2D) {
flags |= GRALLOC_USAGE_HW_2D;
}
return flags;
}
PRUint32
AndroidGraphicBuffer::GetAndroidFormat(gfxImageFormat aFormat)
{
switch (aFormat) {
case gfxImageFormat::ImageFormatRGB24:
return HAL_PIXEL_FORMAT_RGBX_8888;
case gfxImageFormat::ImageFormatRGB16_565:
return HAL_PIXEL_FORMAT_RGB_565;
default:
return 0;
}
}
bool
AndroidGraphicBuffer::EnsureEGLImage()
{
if (mEGLImage)
return true;
if (!EnsureInitialized())
return false;
EGLint eglImgAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE };
void* nativeBuffer = sGLFunctions.fGraphicBufferGetNativeBuffer(mHandle);
mEGLImage = sGLFunctions.fCreateImageKHR(sGLFunctions.fGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)nativeBuffer, eglImgAttrs);
return mEGLImage != NULL;
}
bool
AndroidGraphicBuffer::Bind()
{
if (!EnsureInitialized())
return false;
if (!EnsureEGLImage()) {
LOG("No valid EGLImage!");
return false;
}
sGLFunctions.fImageTargetTexture2DOES(GL_TEXTURE_2D, mEGLImage);
return ensureNoGLError("glEGLImageTargetTexture2DOES");
}
} /* mozilla */

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

@ -0,0 +1,99 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef AndroidGraphicBuffer_h_
#define AndroidGraphicBuffer_h_
#include "gfxASurface.h"
#include "nsRect.h"
namespace mozilla {
/**
* This class allows access to Android's direct texturing mechanism. Locking
* the buffer gives you a pointer you can read/write to directly. It is fully
* threadsafe, but you probably really want to use the AndroidDirectTexture
* class which will handle double buffering.
*
* In order to use the buffer in OpenGL, just call Bind() and it will attach
* to whatever texture is bound to GL_TEXTURE_2D.
*/
class AndroidGraphicBuffer
{
public:
enum {
UsageSoftwareRead = 1,
UsageSoftwareWrite = 1 << 1,
UsageTexture = 1 << 2,
UsageTarget = 1 << 3,
Usage2D = 1 << 4
};
AndroidGraphicBuffer(PRUint32 width, PRUint32 height, PRUint32 usage, gfxASurface::gfxImageFormat format);
virtual ~AndroidGraphicBuffer();
bool Lock(PRUint32 usage, unsigned char **bits);
bool Lock(PRUint32 usage, const nsIntRect& rect, unsigned char **bits);
bool Unlock();
bool Reallocate(PRUint32 aWidth, PRUint32 aHeight, gfxASurface::gfxImageFormat aFormat);
PRUint32 Width() { return mWidth; }
PRUint32 Height() { return mHeight; }
bool Bind();
private:
PRUint32 mWidth;
PRUint32 mHeight;
PRUint32 mUsage;
gfxASurface::gfxImageFormat mFormat;
bool EnsureInitialized();
bool EnsureEGLImage();
void DestroyBuffer();
bool EnsureBufferCreated(PRUint32 aWidth, PRUint32 aHeight, PRUint32 aUsage, gfxASurface::gfxImageFormat aFormat);
PRUint32 GetAndroidUsage(PRUint32 aUsage);
PRUint32 GetAndroidFormat(gfxASurface::gfxImageFormat aFormat);
void *mHandle;
void *mEGLImage;
};
} /* mozilla */
#endif /* AndroidGraphicBuffer_h_ */

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

@ -813,9 +813,6 @@ nsFilePicker::ShowXPFilePicker(const nsString& aInitialDir)
return true;
}
// Clear previous file selection list
mFiles.Clear();
// Set user-selected location of file or directory. From msdn's "Open and
// Save As Dialog Boxes" section:
// If you specify OFN_EXPLORER, the directory and file name strings are NULL
@ -1040,7 +1037,9 @@ nsFilePicker::ShowW(PRInt16 *aReturnVal)
initialDir = mLastUsedUnicodeDirectory;
}
// Clear previous file selections
mUnicodeFile.Truncate();
mFiles.Clear();
bool result = false;
if (mMode == modeGetFolder) {

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

@ -43,6 +43,7 @@
#include "mozilla/Util.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsMemory.h"
#include "nsLocalFile.h"
@ -142,52 +143,36 @@ public:
nsresult Resolve(const WCHAR* in, WCHAR* out);
private:
Mutex mLock;
IPersistFile* mPersistFile;
// Win 95 and 98 don't have IShellLinkW
IShellLinkW* mShellLink;
Mutex mLock;
nsRefPtr<IPersistFile> mPersistFile;
nsRefPtr<IShellLinkW> mShellLink;
};
ShortcutResolver::ShortcutResolver() : mLock("ShortcutResolver.mLock")
ShortcutResolver::ShortcutResolver() :
mLock("ShortcutResolver.mLock")
{
mPersistFile = nsnull;
mShellLink = nsnull;
CoInitialize(NULL);
}
ShortcutResolver::~ShortcutResolver()
{
// Release the pointer to the IPersistFile interface.
if (mPersistFile)
mPersistFile->Release();
// Release the pointer to the IShellLink interface.
if (mShellLink)
mShellLink->Release();
CoUninitialize();
}
nsresult
ShortcutResolver::Init()
{
CoInitialize(NULL); // FIX: we should probably move somewhere higher up during startup
HRESULT hres;
hres = CoCreateInstance(CLSID_ShellLink,
NULL,
CLSCTX_INPROC_SERVER,
IID_IShellLinkW,
(void**)&(mShellLink));
if (SUCCEEDED(hres))
{
// Get a pointer to the IPersistFile interface.
hres = mShellLink->QueryInterface(IID_IPersistFile,
(void**)&mPersistFile);
}
if (mPersistFile == nsnull || mShellLink == nsnull)
// Get a pointer to the IPersistFile interface.
if (FAILED(CoCreateInstance(CLSID_ShellLink,
NULL,
CLSCTX_INPROC_SERVER,
IID_IShellLinkW,
getter_AddRefs(mShellLink))) ||
FAILED(mShellLink->QueryInterface(IID_IPersistFile,
getter_AddRefs(mPersistFile)))) {
mShellLink = nsnull;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
@ -195,24 +180,14 @@ ShortcutResolver::Init()
nsresult
ShortcutResolver::Resolve(const WCHAR* in, WCHAR* out)
{
if (!mShellLink)
return NS_ERROR_FAILURE;
MutexAutoLock lock(mLock);
// see if we can Load the path.
HRESULT hres = mPersistFile->Load(in, STGM_READ);
if (FAILED(hres))
return NS_ERROR_FAILURE;
// Resolve the link.
hres = mShellLink->Resolve(nsnull, SLR_NO_UI);
if (FAILED(hres))
return NS_ERROR_FAILURE;
// Get the path to the link target.
hres = mShellLink->GetPath(out, MAX_PATH, NULL, SLGP_UNCPRIORITY);
if (FAILED(hres))
if (FAILED(mPersistFile->Load(in, STGM_READ)) ||
FAILED(mShellLink->Resolve(nsnull, SLR_NO_UI)) ||
FAILED(mShellLink->GetPath(out, MAX_PATH, NULL, SLGP_UNCPRIORITY)))
return NS_ERROR_FAILURE;
return NS_OK;
}