зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to m-i.
This commit is contained in:
Коммит
6b8d5d04ab
|
@ -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/
|
Двоичный файл не отображается.
|
@ -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, " 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" ? " " : " <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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче